htmlunit抓取动态网页(基于浏览器内核来开发的动态页面渲染处理服务器(组图))
优采云 发布时间: 2021-11-23 03:23htmlunit抓取动态网页(基于浏览器内核来开发的动态页面渲染处理服务器(组图))
前言
曾几何时,从动态页面中提取信息(ajax、内部js二次渲染等)一直是爬虫开发者的心病。总之,真的没有合适的工具。尤其是在Java中,像htmlunit这样的工具可以算是解析动态页面的神器了,但是还不够完善,无法达到浏览器级别的解析效果,遇到稍微复杂一点的页面就不行了。在经历了各种痛苦和仇恨之后,作者决定开发一个动态页面渲染处理服务器,专门用于抓取、监控和测试此类场景。要实现浏览器级别的效果,必须基于浏览器内核进行开发。幸运的是,我们有开源的webkit,更幸运的是,我们有QtWebkit,这对开发人员更友好。于是 SeimiAgent 诞生了。
SeimiAgent 简介
SeimiAgent 是基于 QtWebkit 开发的可以在服务器端后台运行的 webkit 服务。它可以通过SeimiAgent提供的http接口向SeimiAgent发送加载请求(要加载的URL和该页面接受的渲染时间或使用什么代理等参数),通过SeimiAgent加载并渲染动态页面要处理,然后直接将渲染好的页面返回给调用者进行后续处理,所以运行的SeimiAgent服务是语言无关的,任何语言或框架都可以通过SeimiAgent提供标准的http接口来获取服务。SeimiAgent 的加载和渲染环境都是通用浏览器级别的,所以不用担心他处理动态页面的能力。目前,SeimiAgent 只支持返回渲染的 HTML 文档。未来将增加图片快照和PDF支持,以方便更多样化的使用需求。
使用演示
SeimiCrawler 简介
SeimiCrawler 是一个敏捷、独立部署、支持分布式Java 爬虫框架。希望最大限度地降低新手开发高可用低性能爬虫系统的门槛,提高爬虫系统的开发效率。在 SeimiCrawler 的世界里,大部分人只需要关心编写爬行的业务逻辑,剩下的 Seimi 会为你做。在设计方面,SeimiCrawler 的灵感来自于 Python 的爬虫框架 Scrapy。同时结合Java语言的特点和Spring的特点,希望在国内使用更高效的XPath来更方便、更通用的解析HTML,所以SeimiCrawler默认的HTML解析处理器是JsoupXpath(独立扩展项目) ,不收录在 jsoup 中),
集成和部署 SeimiAgent
下载和解压就不显示了,上面的动态图片里也有演示,下载地址可以在SeimiAgent主页上找到。进入SeimiAgent的bin目录,执行:
./SeimiAgent -p 8000
这就是启动SeimiAgent服务,*敏*感*词*8000端口。接下来其实可以用任何语言通过http请求发送加载页面的请求,然后得到渲染结果。当然,我们这里介绍的是SeimiCrawler是如何集成和使用SeimiAgent的。
SeimiCrawler 配置
SeimiCrawler 在 v0.3.0 版本中内置了对 SeimiAgent 的支持。开发者只需要配置SeimiAgent的地址和端口,然后在生成具体的Request时选择是否提交给SeimiAgent,并指定如何提交。我们直接在评论中解释最后一个完整的例子:
package cn.wanghaomiao.crawlers;
import cn.wanghaomiao.seimi.annotation.Crawler;
import cn.wanghaomiao.seimi.def.BaseSeimiCrawler;
import cn.wanghaomiao.seimi.struct.Request;
import cn.wanghaomiao.seimi.struct.Response;
import cn.wanghaomiao.xpath.model.JXDocument;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
/**
* 这个例子演示如何使用SeimiAgent进行复杂动态页面信息抓取
* @author 汪浩淼 et.tw@163.com
* @since 2016/4/14.
*/
@Crawler(name = "seimiagent")
public class SeimiAgentDemo extends BaseSeimiCrawler{
/**
* 在resource/config/seimi.properties中配置方便更换,当然也可以自行根据情况使用自己的统一配置中心等服务。这里配置SeimiAgent服务所在地址。
*/
@Value("${seimiAgentHost}")
private String seimiAgentHost;
//SeimiAgent*敏*感*词*的端口好,如上文中的8000
@Value("${seimiAgentPort}")
private int seimiAgentPort;
@Override
public String[] startUrls() {
return new String[]{"https://www.baidu.com"};
}
@Override
public String seiAgentHost() {
return this.seimiAgentHost;
}
@Override
public int seimiAgentPort() {
return this.seimiAgentPort;
}
@Override
public void start(Response response) {
Request seimiAgentReq = Request.build("https://www.souyidai.com","getTotalTransactions")
.useSeimiAgent()
// 告诉SeimiAgent针对这个请求是否使用cookie,如果没有设置使用当前Crawler关于cookie使用条件作为默认值。
//.setSeimiAgentUseCookie(true)
// 设置全部load完成后给SeimiAgent多少时间用于执行js并渲染页面,单位为毫秒
.setSeimiAgentRenderTime(5000);
push(seimiAgentReq);
}
/**
* 获取搜易贷首页总成交额
* @param response
*/
public void getTotalTransactions(Response response){
JXDocument doc = response.document();
try {
String trans = StringUtils.join(doc.sel("//div[@class='homepage-amount']/div[@class='number font-arial']/div/span/text()"),"");
logger.info("Final Res:{}",trans);
} catch (Exception e) {
e.printStackTrace();
}
}
}
配置文件seimi.properties
seimiAgentHost=127.0.0.1
seimiAgentPort=8000
启动
public class Boot {
public static void main(String[] args){
Seimi s = new Seimi();
s.start("seimiagent");
}
}
SeimiCrawler 启动后,您可以看到您想要的搜一贷交易总额。
完整演示地址
演示