# Selenium下载器
在抓取js渲染的网页时,风铃虫默认的内置Jsoup下载器可能会无力从心了,此时可以使用风铃虫内置的Selenium下载器了。
与Jsoup下载器相比,Selenium下载器具有以下特性:
- 支持设置超时时间
- 支持完成前端渲染
- 支持设置cookie
- 支持动态设置等待渲染时间
在另一方面,Selenium下载器也存在以下问题:
- 不支持自定义设置浏览器标识
- 不支持自定义请求头参数
# 简单使用
使用Selenium下载器的步骤如下:
# 安装火狐浏览器
先在运行风铃虫的服务器上安装好 火狐浏览器
# 下载geckodriver文件
安装好火狐浏览器后,需要下载对应版本的geckodriver文件文件
geckodriver官网下载地址为:
https://github.com/mozilla/geckodriver/releases (opens new window)
注意:下载的geckodriver的版本一定要与先前安装的火狐的版本保持一致
如果官网的geckodriver文件下载比较慢,可以从百度网盘下载,下载地址为
链接:https://pan.baidu.com/s/19zVhrD74IB4Ndwy73eRPag 提取码:ipql
如果都无法下载,可以加入交流群,从群文件中获取
# 复制geckodriver文件
完成geckodriver文件的下载后,将geckodriver文件复制到运行风铃虫的服务器的某个可读性的路径下。
# 应用Selenium下载器
使用Selenium下载器的关键代码如下:
Crawler crawler = ...
crawler .setDownloader(new SeleniumDownloader("C:\\Users\\yishui\\Desktop\\geckodriver\\win32.exe",3000L))
创建SeleniumDownloader
时有两个初始化参数,他们的作用如下:
- 第一个参数:第三步中放置的geckodriver文件的位置
- 第二个参数:等待js渲染的时间,单位为毫秒
之所以会有第二个参数,这是因为对于js渲染的网站,需要等待一段时间来进行js渲染,这个渲染时间需要使用者根据当前服务器的性能进行调节,如果时间设置过短会造成网页未渲染完成,无法提取到目标数据。
# 高级使用
除了简单使用之外,风铃虫还提供了SeleniumDownloader
下载器的高级用法,当系统内置的SeleniumDownloader
不能满足用户的使用需求时,用户可以实现自定义的SeleniumDownloader
来实现自定义功能。
示例代码如下:
/**
* 基于Firefox的下载器 <br/>
* 使用selenium-java实现
*
* @author yishui
* @date 2019年12月24日
* @version 1.0.0
*/
@Slf4j
public class SeleniumDownloader extends BaseDownloader {
/**
* 是否已经执行过
*/
private boolean hasDone = false;
/**
* 等待一段时间,以便在下载需要前端渲染的网站时让浏览器有时间完成前端渲染,单位为毫秒
*/
private long waitRender;
/**
* 构造函数<br/>
* 必须传入浏览器驱动文件geckodriver所在地址的路径<br/>
* geckodriver文件的下载路径为 https://github.com/mozilla/geckodriver/releases<br/>
* 请根据运行环境的信息配置好此参数
*
* @param driverPath 浏览器驱动文件geckodriver的地址
* @param waitRender 等待一段时间,以便在下载需要前端渲染的网站时让浏览器有时间完成前端渲染,单位为毫秒,如果此值不大于0表示不开启此功能
* @throws ServiceException 创建浏览器对象时出现的问题
*
*/
public SeleniumDownloader(String driverPath, long waitRender) throws ServiceException {
super(driverPath);
this.waitRender = waitRender;
}
@Override
public Page down(WebDriver driver, String url) throws ServiceException {
Page page = new Page(url);
try {
driver.get(url);
// 等待一段时间
this.waitRender();
// 设置真实的请求地址
page.setRedirectUrl(driver.getCurrentUrl());
page.setCode(HttpStatus.SC_OK);
page.setRawTxt(driver.getPageSource());
} catch (Exception e) {
log.info("An error occurred while downloading the page {}, the problem is {}", url, e.getMessage());
page.setCode(HttpStatus.SC_INTERNAL_SERVER_ERROR);
page.setRawTxt(e.getMessage());
}
return page;
}
/**
* 休眠一段时间,以便完成渲染
*
*
*/
private void waitRender() {
if (this.waitRender > 0) {
try {
Thread.sleep(this.waitRender);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
protected void preHandle(final SiteRule siteRule, final WebDriver driver) {
if (!hasDone) {
if (siteRule.getConnectTimeout() > 0) {
// 识别对象时的超时时间。过了这个时间如果对象还没找到的话就会抛出NoSuchElement异常。单位毫秒。
driver.manage().timeouts().implicitlyWait(siteRule.getConnectTimeout(), TimeUnit.MILLISECONDS);
}
siteRule.getCookiValues().forEach((k, v) -> {
driver.manage().addCookie(new Cookie(k, v));
});
hasDone = true;
}
}
}