网络爬虫——Selenium的使用

1、Selenium简介

Selenium 最初是由 Shinya Kasatani 基于火狐(Firefox)浏览器开发的工具,其主 要用于网站的自动化测试。读者可以在火狐浏览器中安装 Selenium IDE 插件,并使用 该插件录制在浏览器中的执行动作(如表单提交、单击和鼠标的移动等)。在本章中, 我们将重点介绍 Selenium WebDriver 的使用。Selenium WebDriver 主要应用于程序 (Java、Python 和 C#等)与浏览器的交互,其可以用来实现数据的采集。

Selenium 不自带浏览器,需要与第三方浏览器结合使用,如本章与 Selenium 结合 使用的浏览器为谷歌浏览器相比 Jsoup 和 HttpClient 等工具, Selenium 有其特有优势,如自动加载页面(执行 JavaScript 脚本)、模拟真实的浏览器 操作(可用于模拟登录)等。

2、Java Selenium环境搭建

2.1、依赖

首先,创建一个 Java Maven 工程,并在该工程下添加两个文件夹 drivers 和 libs。
在这里插入图片描述

其次,在 Java 中使用 Selenium,需要下载相关 jar 包,下载 selenium-server-standalone-3.141.59.jar。下载完成后,将该 jar 包放到工程的 libs 目 录下,并将该 jar 包引入项目。

另外一种配置相关 jar 包的方式是下载 selenium-java-3.141.59 压缩包,并进行解压,之后将解压后 文件夹中的所有 jar 包放到 libs 目录下,并将这些 jar 包引入项目。

再者,也可以直接 使用 Maven 工程中的 pom.xml 文件配置所需的 jar 包。

<dependency> 	
	<groupId>org.seleniumhq.selenium</groupId> 
	<artifactId>selenium-java</artifactId> 
	<version>3.141.59</version>
</dependency>

2.2、安装浏览器

没有安装Chrome浏览器,则需先安装(建议官方地址下载)

官方下载地址为:https://www.google.cn/chrome/
在这里插入图片描述

2.3、下载驱动 chromedriver

在相关 jar 包配置完成之后,需要下载 Selenium WebDriver 连接谷歌浏览器的工具chromedriver,下载之后放到drivers目录下。

下载地址:http://chromedriver.storage.googleapis.com/index.html

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、浏览器的操控

搭建好 Java Selenium 环境后,便可以利用 Java 程序操控浏览器,获取网页 的响应内容。下面以某搜索网站为例,主要任务是使用 Selenium WebDriver 和 googledriver 启动浏览器,打开某搜索网站首页,并在搜索框中自动输入“Java 网 络爬虫”,执行搜索,最后针对响应页面使用 Xpath 语法解析得到搜索结果的标题 和 URL。

这段代码中使用 setProperty(String key, String value) 配置 googledriver,然后实例化 ChromeDriver(声明使用的是谷歌浏览器),接着使用谷歌浏览器打开页面执行一系列操作。值得注意的是在执行搜索的过程中,需要利用 implicitlyWait()方法休息一定的时间,以供网页完全加载数据。最后,使用 Xpath 语法 进行元素定位,解析相应的字段。

示例

public class Test {
    public static void main(String[] args) {
        //chromedriver配置
        System.setProperty("webdriver.chrome.driver", "drivers/chromedriver");
        //声明使用的是谷歌浏览器
        ChromeDriver driver = new ChromeDriver();
        //打开baidu
        driver.get("http://www.baidu.com");
        //元素定位,输入内容
        driver.findElementById("kw").sendKeys("Java网络爬虫");
        //元素定位,执行单机命令
        driver.findElementById("su").click();
        //给出一定的响应时间
        driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
        driver.getPageSource();
        //使用Xpath解析数据 //*[@id="1"]/div/div[1]/h3/a
        List<WebElement> titleList = driver.findElements(By.xpath("//*[@class='result c-container xpath-log new-pmd']/div/div/h3/a"));
        //输出标题
        for (WebElement e : titleList) {
            System.out.println("标题为:" + e.getText() + "\t" + "url为:" + e.getAttribute("href"));
        }
        driver.quit();
    }
}

执行程序,会发现相关操作都会在浏览器中自动执行。另外,在控制台也会 输出解析的标题和 URL,输出如下:
在这里插入图片描述

4、元素定位

在使用 Selenium 时,往往需要先通过定位器找到相应的元素,然后再进行其他操 作。例如,在上面程序中,先使用 findElementById(“kw”)定位到搜索框,随后再利用 sendKeys(CharSequence… keysToSend)方法输入搜索内容。

定位器是一种抽象查询语言, 功能是定位元素。Selenium WebDriver 提供了多种定位策略,如 id 定位、name 定位、 class 定位、tag name 定位、link text 定位、Xpath 定位和 CSS 定位等。下面将分别介 绍这些定位策略。

4.1、id定位

在 Java 中,有以下四种方式实现 id 定位策略

//第一种方式返回WebElement
driver.findElementById(<element id>)
//第二种方式返回List<WebElement>
driver.findElementsById(<element id>)
//第三种方式返回WebElement
driver.findElement(By.id(<element id>)) 
//第四种方式返回List<WebElement>
driver.findElements(By.id(<element id>))

4.2、name定位

当元素中包含 name 属性时,可以使用 name 进行定位。在 Java 中,有以下四种方式实现 name 定位策略

//第一种方式返回WebElement
driver.findElementByName(<element name>)
//第二种方式返回List<WebElement>
driver.findElementsByName(<element name>)
//第三种方式返回WebElement
driver.findElement(By.Name(<element name>)) 
//第四种方式返回List<WebElement>
driver.findElements(By.Name(<element name>))

4.3、class定位

当元素中包含 class 属性时,可以使用 class 进行定位。在 Java 中,有以下四种方式实现 class 定位 策略

//第一种方式返回WebElement
driver.findElementByClassName(<element classname>)
//第二种方式返回List<WebElement>
driver.findElementsByClassName(<element classname>)
//第三种方式返回WebElement
driver.findElement(By.ClassName(<element classname>)) 
//第四种方式返回List<WebElement>
driver.findElements(By.ClassName(<element classname>))

4.4、tag name定位

Selenium WebDriver 也提供了 tag name(标签名称)定位的方法,使用标签名称 可以很方便地定位一些元素,如定位所有表格中的、定位所有链接等。程序 展示了实现 tag name 定位策略的四种方式。

//第一种方式返回WebElement
driver.findElementByTagName(<tagName>)
//第二种方式返回List<WebElement>
driver.findElementsByTagName(<tagName>)
//第三种方式返回WebElement
driver.findElement(By.TagName(<tagName>)) 
//第四种方式返回List<WebElement>
driver.findElements(By.TagName(<element tagName>))

4.5、link text定位

link text 定位,是通过链接文本定位链接的。在 Java 中,有以下四种方式实现 link text 定位策略

//第一种方式返回WebElement
driver.findElementByLinkText(<linkText>)
//第二种方式返回List<WebElement>
driver.findElementsByLinkText(<linkText>)
//第三种方式返回WebElement
driver.findElement(By.LinkText(<linkText>)) 
//第四种方式返回List<WebElement>
driver.findElements(By.LinkText(<linkText>))

4.6、Xpath定位

Selenium WebDriver 支持使用 Xpath 表达式定位元素,Xpath 使用路径表达式来定位 HTML 或 XML 文档中的节点 或节点集合,在 Java 中,同 样可以使用四种方式实现 Xpath 定位策略

//第一种方式返回WebElement
driver.findElementByXPath(<Xpath query expression>)
//第二种方式返回List<WebElement>
driver.findElementsByXPath(<Xpath query expression>)
//第三种方式返回WebElement
driver.findElement(By.xpath(<Xpath query expression>)) 
//第四种方式返回List<WebElement>
driver.findElements(By.xpath(<Xpath query expression>))

4.7、CSS选择器

Selenium WebDriver 在定位元素时,也可以使用 CSS 选择器,其实现方式有四种

//第一种方式返回WebElement
driver.findElementByCssSelector(<css selector>)
//第二种方式返回List<WebElement>
driver.findElementsByCssSelector(<css selector>)
//第三种方式返回WebElement
driver.findElement(By.cssSelector(<css selector>)) 
//第四种方式返回List<WebElement>
driver.findElements(By.cssSelector(<css selector>))

5、模拟登录

Selenium 可以精准地定位浏览器中的元素(如输入框)、模拟真实的浏览器操作 (如输入文本、单击等)。针对一些复杂且需要登录才能获取数据的网站,可以利用 Selenium 的特性,模拟登录该网站,获取登录的 Cookie。之后,使用 Jsoup 或者 Httpclient 采集该网站中的数据。以下,将以某网站的模拟登录为例,介绍 Selenium 的使用情况。

首先定位登录按钮:id=“s-top-loginbtn”
在这里插入图片描述

然后在弹出的模态框中定位输入框和登录按钮:
在这里插入图片描述

在这里插入图片描述

利用 Selenium,输入用户名和密码,并单击“登录”按钮执行登录操作。需要注意的是在模拟单击登录按钮后, 需要使用 sleep(long millis)方法休息一段时间,使登录信息加载完整。

public class LoginRenren {
    public static void main(String[] args) throws InterruptedException, IOException {
        //chromedriver配置
        System.setProperty("webdriver.chrome.driver", "drivers/chromedriver");
        //声明使用的是谷歌浏览器
        ChromeDriver driver = new ChromeDriver();
        //打开baidu
        driver.get("http://www.baidu.com");
        //元素定位,单机登录按钮
        WebElement topButton = driver.findElementById("s-top-loginbtn");
        topButton.click();
        //等待模态框弹出
        Thread.sleep(2 * 1000);
        //在弹出的登录框中定位元素
        WebElement nameInput = driver.findElementById("TANGRAM__PSP_11__userName");
        nameInput.clear();
        nameInput.sendKeys("15043577079");
        WebElement passInput = driver.findElementById("TANGRAM__PSP_11__password");
        passInput.clear();
        passInput.sendKeys("459594186zcl");
        driver.findElementById("TANGRAM__PSP_11__submit").click();
        //等待页面充分加载
        Thread.sleep(5 * 1000);

        //注意,如果baidu弹出了验证框,那无法绕过,后续操作失败。
        //获取Cookie
        Set<Cookie> cookies = driver.manage().getCookies();
        String cookieStr = "";
        for (Cookie cookie : cookies) {
            cookieStr += cookie.getName() + "=" + cookie.getValue() + ";";
        }
        System.out.println(cookieStr);

        //基于Jsoup,使用cookies请求个人信息页面
        Connection.Response response = Jsoup.connect("https://www.baidu.com/my/index")
                .header("Host", "www.baidu.com")
                .header("Connection", "keep-alive")
                .header("Accept", "text/html,application/xhtml+xml, application/xml;q=0.9,image/webp,*;q=0.8")
                .header("Origin", "http://www.baidu.com")
                .header("Referer", "http://www.baidu.com")
                .header("Content-Type", "application/x-www-form-urlencoded")
                .cookie("Cookie", cookieStr)
                .execute();
        //解析数据
        Document doc = response.parse();
        Elements elements = doc.select("#user-center > div.main-wrapper_3KoRh > div.siderbar-wrapper_Nk4dE > div > div > a");
        for (Element e : elements) {
            System.out.println(e.select("p:nth-child(2)").text());
        }

        //关闭浏览器
        driver.quit();
    }
}

6、动态加载JavaScript数据(操作滚动条)

在使用 Jsoup 和 Httpclient 直接请求 URL 时,有时会发现响应得到的 HTML 中包 含的信息不全,未展示出的信息必须通过执行页面中的 JavaScript 代码才能展示。相 比于 Jsoup 和 Httpclient,Selenium 可以利用 JavascriptExecutor 接口执行任意 JavaScript 代码。

下面将以百度图片中的搜索图片数据为例,讲解如何使用 Selenium 动态加载 JavaScript 数据。

public class FinancialRolling {
    public static void main(String[] args) throws InterruptedException {
        //chromedriver配置
        System.setProperty("webdriver.chrome.driver", "drivers/chromedriver");
        //声明使用的是谷歌浏览器
        ChromeDriver driver = new ChromeDriver();
        //打开baidu
        driver.get("http://image.baidu.com");
        WebElement kw = driver.findElementById("kw");
        kw.clear();
        kw.sendKeys("美女");
        WebElement button = driver.findElement(By.cssSelector("#homeSearchForm > span.s_btn_wr > input"));
        button.click();
        //等待页面加载
        Thread.sleep(5 * 1000);
        //执行JS操作
        JavascriptExecutor js = (JavascriptExecutor)driver;
        try {
            js.executeScript("scrollTo(0, 5000)");
            System.out.println("1");
            Thread.sleep(5000); //调整休眠时间可以获取更多的内容
            js.executeScript("scrollTo(5000, 10000)");
            System.out.println("2");
            Thread.sleep(5000);
            js.executeScript("scrollTo(10000, 30000)"); // 继续下拉
            System.out.println("3");
            Thread.sleep(5000);
            js.executeScript("scrollTo(10000, 50000)"); //继续下拉
            System.out.println("4");
        } catch (Exception e) {
            System.out.println("Error at loading the page...");
            driver.quit();
        }

        //解析数据
        String html = driver.getPageSource();
        Document doc = Jsoup.parse(html);
        Elements elements = doc.select("#imgid > div:nth-child(1) > ul > li");
        for (Element e : elements) {
            System.out.println(e.attr("data-thumburl"));
        }

        //关闭浏览器
        driver.quit();
    }
}
1
2
3
4
https://t7.baidu.com/it/u=3676218341,3686214618&fm=193&f=GIF
https://img0.baidu.com/it/u=1825304346,2860164199&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=666
https://img2.baidu.com/it/u=3323311628,2330835932&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=666
https://img2.baidu.com/it/u=3354585195,1512541150&fm=253&fmt=auto&app=138&f=JPEG?w=890&h=500
https://img0.baidu.com/it/u=3794430030,3426009381&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=750
https://img0.baidu.com/it/u=2911164322,2998857390&fm=253&fmt=auto&app=138&f=JPEG?w=346&h=500
https://img1.baidu.com/it/u=2339589192,1294229754&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=647
https://img1.baidu.com/it/u=1622759797,988413400&fm=253&fmt=auto&app=138&f=JPEG?w=343&h=500
https://img1.baidu.com/it/u=3392591833,1640391553&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=714
https://img1.baidu.com/it/u=2972437056,3031136317&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=666
https://img1.baidu.com/it/u=2775377376,69094478&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=666
https://img1.baidu.com/it/u=2278717026,2923133725&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=665
https://img0.baidu.com/it/u=1397203767,4231030802&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=665
https://img0.baidu.com/it/u=3298051423,2256566422&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=683
https://img1.baidu.com/it/u=3649894598,1420228163&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=750
https://img2.baidu.com/it/u=1348122341,4168765603&fm=253&fmt=auto&app=138&f=JPEG?w=888&h=500
https://img1.baidu.com/it/u=4139258405,3795750908&fm=253&fmt=auto&app=120&f=JPEG?w=1140&h=760
https://img0.baidu.com/it/u=3481356926,3210196434&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=889
https://img2.baidu.com/it/u=2055715645,3308680961&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=750
https://img1.baidu.com/it/u=2236572226,1780107877&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=721
https://img2.baidu.com/it/u=3941944942,3848012963&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=665
https://img0.baidu.com/it/u=2849159227,3411294549&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=698
https://img1.baidu.com/it/u=2119626721,2606712208&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=666
https://img1.baidu.com/it/u=1983760057,2461413428&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500
https://img0.baidu.com/it/u=3673910398,1309627678&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=736
https://img0.baidu.com/it/u=4234484084,1391640149&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800
https://img1.baidu.com/it/u=3809752281,1928271428&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=1082
https://img0.baidu.com/it/u=4126260600,3694641195&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500
https://img0.baidu.com/it/u=518980756,774483131&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=713
https://img0.baidu.com/it/u=499045485,1119545308&fm=253&fmt=auto&app=120&f=JPEG?w=800&h=1379
https://img1.baidu.com/it/u=316030150,2128050393&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=732
https://img1.baidu.com/it/u=3885230234,3434479436&fm=253&fmt=auto&app=138&f=JPEG?w=333&h=500

7、隐藏浏览器

由以上内容可知使用 Selenium 采集网页数据时,需要不断地调用浏览器。实际 上,通过对 Selenium 的设置,可以达到隐藏浏览器的效果。

public class FinancialRolling {
    public static void main(String[] args) throws InterruptedException {
        //设置隐藏浏览器
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--headless");
        //chromedriver配置
        System.setProperty("webdriver.chrome.driver", "drivers/chromedriver");
        //声明使用的是谷歌浏览器
        ChromeDriver driver = new ChromeDriver(options);
        //打开baidu
        driver.get("http://image.baidu.com");
        WebElement kw = driver.findElementById("kw");
        kw.clear();
        kw.sendKeys("美女");
        WebElement button = driver.findElement(By.cssSelector("#homeSearchForm > span.s_btn_wr > input"));
        button.click();
        //等待页面加载
        Thread.sleep(5 * 1000);
        //执行JS操作
        JavascriptExecutor js = (JavascriptExecutor)driver;
        try {
            js.executeScript("scrollTo(0, 5000)");
            System.out.println("1");
            Thread.sleep(5000); //调整休眠时间可以获取更多的内容
            js.executeScript("scrollTo(5000, 10000)");
            System.out.println("2");
            Thread.sleep(5000);
            js.executeScript("scrollTo(10000, 30000)"); // 继续下拉
            System.out.println("3");
            Thread.sleep(5000);
            js.executeScript("scrollTo(10000, 50000)"); //继续下拉
            System.out.println("4");
        } catch (Exception e) {
            System.out.println("Error at loading the page...");
            driver.quit();
        }

        //解析数据
        String html = driver.getPageSource();
        Document doc = Jsoup.parse(html);
        Elements elements = doc.select("#imgid > div:nth-child(1) > ul > li");
        for (Element e : elements) {
            System.out.println(e.attr("data-thumburl"));
        }

        //关闭浏览器
        driver.quit();
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值