前言
《Java 中使用 selenium 和 chrome 浏览器下载动态网页》 一文中,演示了如何在 window 环境下通过 selenium 和 chrome 来下载动态网页。但是我们的爬虫一般是运行在 linux 服务器上的。服务器上一般是没有 GUI 环境的。无法打开 chrome 窗口界面。以前的时候,爬虫系统是用一种无界面的浏览器 PhantomJS 来实现。但是现在因为 FireFox 、chrome 这些浏览器开始支持无头模式后, PhantomJS 已经停止更新了,所以现在推荐使用 FireFox 和 chrome 的无头模式来替代 PhantomJS 了。所谓的无头模式就是无界面运行模式,正好适合在 linux 服务器这种没有 GUI 环境的情况下使用。
在 linux 环境下使用 selenium 驱动 chrome 需要安装 chrome 浏览器和 chrome webdriver。下面在 centos 7 环境下展示应该如何做。
安装 google chrome
首先从地址 https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm 下载离线安装包。然后执行下面的命令安装 chrome 需要的依赖包
yum install libX11 libXcursor libXdamage libXext libXcomposite libXi libXrandr gtk3 libappindicator-gtk3 xdg-utils libXScrnSaver liberation-fonts
然后执行命令安装 chrome
rpm -ivh google-chrome-stable_current_x86_64.rpm
完成后执行下面的命令查看版本
[root@localhost ~]# google-chrome --version
Google Chrome 70.0.3538.110
可以看出当前版本为 70 版本
安装 chrome webdriver
和文章 《Java 中使用 selenium 和 chrome 浏览器下载动态网页》 中一样,找到支持 70 版本 chrome 的下载地址,下载 linux 平台版本的文件 chromedriver_linux64.zip 即可
无头模式 selenium chrome 调用程序样例
还是以 《Java 中使用 selenium 和 chrome 浏览器下载动态网页》 中的程序为基础,将他改造为无头模式
WebDriver webDriver = null;
try {
String url = "https://www.jianshu.com/p/675ea919230e";
ChromeOptions chromeOptions=new ChromeOptions();
//设置 chrome 的无头模式
chromeOptions.setHeadless(Boolean.TRUE);
//启动一个 chrome 实例
webDriver = new ChromeDriver(chromeOptions);
//访问网址
webDriver.get(url);
Document document = Jsoup.parse(webDriver.getPageSource());
Element titleElement = document.selectFirst("div.article h1.title");
Element authorElement = document.selectFirst("div.article div.author span.name");
Element timeElement = document.selectFirst("div.article span.publish-time");
Element wordCountElement = document.selectFirst("div.article span.wordage");
Element viewCountElement = document.selectFirst("div.article span.views-count");
Element commentCountElement = document.selectFirst("div.article span.comments-count");
Element likeCountElement = document.selectFirst("div.article span.likes-count");
Element contentElement = document.selectFirst("div.article div.show-content");
if (titleElement != null) {
System.out.println("标题:" + titleElement.text());
}
if (authorElement != null) {
System.out.println("作者:" + authorElement.text());
}
if (timeElement != null) {
System.out.println("发布时间:" + timeElement.text());
}
if (wordCountElement != null) {
System.out.println(wordCountElement.text());
}
if (viewCountElement != null) {
System.out.println(viewCountElement.text());
}
if (commentCountElement != null) {
System.out.println(commentCountElement.text());
}
if (likeCountElement != null) {
System.out.println(likeCountElement.text());
}
if (contentElement != null && contentElement.text() != null) {
System.out.println("正文长度:" + contentElement.text().length());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (webDriver != null) {
//退出 chrome
webDriver.quit();
}
}
和前文中的代码相比,就是下面的地方不一样
ChromeOptions chromeOptions=new ChromeOptions();
//设置 chrome 的无头模式
chromeOptions.setHeadless(Boolean.TRUE);
//启动一个 chrome 实例
webDriver = new ChromeDriver(chromeOptions);
这个参数决定了是否用无头模式来启动
将程序打包并且上传到 linux 服务器上,执行命令
java -jar -Dwebdriver.chrome.driver=/data/deploy/chromedriver spider_demo-0.0.1-SNAPSHOT.jar
控制台会打印出下面的内容
标题:是什么支撑了淘宝双十一,没错就是它java编程语言。
作者:Java帮帮
发布时间:2018.08.29 14:49
字数 561
阅读 632
评论 0
喜欢 4
正文长度:655
说明在 linux 用 java 通过 selenium 调用 chrome 访问这个网页成功了。如果没有设置上面的无头模式参数,那么执行的时候将会出现下面的提示
org.openqa.selenium.WebDriverException: unknown error: Chrome failed to start: exited abnormally
(unknown error: DevToolsActivePort file doesn't exist)
(The process started from chrome location /usr/bin/google-chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.)
(Driver info: chromedriver=2.44.609551 (5d576e9a44fe4c5b6a07e568f1ebc753f1214634),platform=Linux 3.10.0-514.26.2.el7.x86_64 x86_64) (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 399 milliseconds
Build info: version: 'unknown', revision: 'unknown', time: 'unknown'
System info: host: 'iz2ze9kvzy03hms75m3jzlz', ip: '172.17.251.3', os.name: 'Linux', os.arch: 'amd64', os.version: '3.10.0-514.26.2.el7.x86_64', java.version: '1.8.0_171'
Driver info: driver.version: ChromeDriver
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:214)
at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:166)
at org.openqa.selenium.remote.JsonWireProtocolResponse.lambda$new$0(JsonWireProtocolResponse.java:53)
at org.openqa.selenium.remote.JsonWireProtocolResponse.lambda$getResponseFunction$2(JsonWireProtocolResponse.java:91)
at org.openqa.selenium.remote.ProtocolHandshake.lambda$createSession$0(ProtocolHandshake.java:122)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.Spliterators$ArraySpliterator.tryAdvance(Spliterators.java:958)
at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126)
at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:498)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:464)
at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:125)
at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:73)
at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:136)
at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:548)
at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:212)
at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:130)
at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:181)
at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:168)
at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:123)
at com.yanggaochao.spider.SpiderDemoApplication.run(SpiderDemoApplication.java:34)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:813)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:797)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:324)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
at com.yanggaochao.spider.SpiderDemoApplication.main(SpiderDemoApplication.java:21)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
这样,我们就可以在我们的爬虫系统里面采用浏览器的方式下载网页,实现所见即所得的下载效果。再也不用担心动态渲染的网页内容无法下载了。