最近试了下如何通过模拟浏览器请求的方式获取网页源代码。
Selenium
Selenium
是一个用于Web应用程序测试的工具,通过调用浏览器模拟用户请求,最终获取页面源代码。好处在于可以使用浏览器 headless
模式,在无桌面环境的 linux
系统下运行。
以 Chrome
为例,安装 Chrome
后,我们需要根据浏览器版本获取到对应的浏览器驱动。
CentOS下使用
CentOS
下通过 yum
命令安装 Chrome
:
1 | yum install google-chrome-stable_current_x86_64.rpm |
该命令安装的 chrome
是最新版本,历史版本可以查看:http://orion.lcg.ufrj.br/RPMS/myrpms/google/
使用命令 google-chrome --version
查看当前安装的版本:
1 | # google-chrome --version |
在官网上查找该版本对应的驱动:http://chromedriver.storage.googleapis.com/index.html ,下载并解压。
获取网页源代码
1 | import org.openqa.selenium.chrome.ChromeDriver; |
运行效果:
优化访问
通过设置浏览器选项禁用图片和 js:
1 | // 设置页面加载策略 |
运行效果:
Headless
在无桌面系统的服务器上,需要启用 headless
模式:
1 | options.addArguments("--headless"); |
需要注意的是,在 headless
模式下,由于安全保护机制,很多的设置无法生效。
Webview
javaFx
中已经拥有 webview
组件,因此可以通过 webview
模拟浏览器请求,等待页面加载完成后获取网页的源代码。
一个简单的示例如下:
1 | import javafx.application.Application; |
运行效果:
获取网页源代码
通过监听网页加载状态判断页面是否已经加载完成,加载完成后执行 javascript
脚本获取源代码:
1 | // 添加加载状态监听器 |
设置UA
1 | webView.getEngine().setUserAgent("UA"); |
优化访问
对于有些网页而言,静态资源加载(如图片等)是比较耗时的,而如果我们只想获取网页的源代码,那么类似 图片
,css
,js
等静态资源并不是必须的,在这种情况下,可以过滤掉部分的远程请求,加快页面的响应时间。
因为 Webview
并没有提供这样的入口,因此我们可以通过设置全局的 URLStreamHandlerFactory
实现过滤远程请求:
1 | private static void initConnection() { |
运行效果:
自动抓取
在程序启动后,新启线程调用 webView.getEngine().load(url)
方法,并最终提交到 javaFx
线程中执行。
1 | Platform.runLater(() -> webView.getEngine().load(url)); |
需要注意的是,需要等待上一个页面加载完成后才能继续请求下一个页面。