# Selenium下载器

在抓取js渲染的网页时,风铃虫默认的内置Jsoup下载器可能会无力从心了,此时可以使用风铃虫内置的Selenium下载器了。

与Jsoup下载器相比,Selenium下载器具有以下特性:

  • 支持设置超时时间
  • 支持完成前端渲染
  • 支持设置cookie
  • 支持动态设置等待渲染时间

在另一方面,Selenium下载器也存在以下问题:

  1. 不支持自定义设置浏览器标识
  2. 不支持自定义请求头参数

# 简单使用

使用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;
		}

	}

}
Last Updated: 1/7/2020, 10:34:40 PM