java抓取网页内容(基于QtWebkit内核来开发的动态页面渲染处理服务器(图))
优采云 发布时间: 2022-01-22 04:01java抓取网页内容(基于QtWebkit内核来开发的动态页面渲染处理服务器(图))
前言
曾几何时,动态页面的信息提取(ajax、内部js二次渲染等)一直是爬虫开发者的痛点。总之,真的没有合适的工具。尤其在Java中,像htmlunit这样的工具可以算是解析动态页面的神器,但是还不够完善,无法达到浏览器级别的解析效果,遇到稍微复杂一点的页面就不行了。在经历了种种痛苦和仇恨之后,笔者决定干脆开发一款专门为爬取、监控、测试这类场景设计的动态页面渲染处理服务器。要想达到浏览器级别的效果,就必须基于浏览器内核进行开发。好在我们有开源的webkit,好在我们有QtWebkit,对开发者更加友好。
SeimiAgent 是基于 QtWebkit 开发的可以在服务器端后台运行的 webkit 服务。它可以通过 SeimiAgent 提供的 http 接口向 SeimiAgent 发送加载请求(要加载的 URL 和该页面接受的渲染时间或使用什么代理等),通过它加载和渲染你要处理的动态页面SeimiAgent,然后将渲染好的页面直接返回给调用者进行后续处理,所以运行的SeimiAgent服务是语言无关的,任何语言或框架都可以通过SeimiAgent提供的标准http接口获取服务。SeimiAgent 的加载和渲染环境都是常见的浏览器级别的,所以不用担心他处理动态页面的能力。目前 SeimiAgent 只支持返回渲染后的 HTML 文档。将来,
使用演示
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
启动
public class Boot {
public static void main(String[] args){
Seimi s = new Seimi;
s.start("seimiagent");
}
}
SeimiCrawler 上线后,可以看到想要的搜易贷交易总量。
完整的Demo地址