Gecco 是一款用 java 语言开发的轻量化的易用的网络爬虫。Gecco 整合了 jsoup、httpclient、fastjson、spring、htmlunit、redission 等优秀框架,让您只需要配置一些 jquery 风格的选择器就能很快的写出一个爬虫。Gecco 框架有优秀的可扩展性,框架基于开闭原则进行设计,对修改关闭、对扩展开放。同时 Gecco 基于十分开放的 MIT 开源协议,无论你是使用者还是希望共同完善 Gecco 的开发者,欢迎 pull request。如果你喜欢这款爬虫框架请star 或者 fork!
- 简单易用,使用 jquery 风格的选择器抽取元素
- 支持爬取规则的动态配置和加载
- 支持页面中的异步 ajax 请求
- 支持页面中的 javascript 变量抽取
- 利用 Redis 实现分布式抓取,参考gecco-redis
- 支持结合 Spring 开发业务逻辑,参考gecco-spring
- 支持 htmlunit 扩展,参考gecco-htmlunit
- 支持插件扩展机制
- 支持下载时 UserAgent 随机选取
- 支持下载代理服务器随机选取
GeccoEngine 是爬虫引擎,每个爬虫引擎最好是一个独立进程,在分布式爬虫场景下,建议每台爬虫服务器(物理机或者虚机)运行一个 GeccoEngine。爬虫引擎包括 Scheduler、Downloader、Spider、SpiderBeanFactory、PipelineFactory5 个主要模块。
通常爬虫需要一个有效管理下载地址的角色,Scheduler 负责下载地址的管理。gecco 对初始地址的管理使用 StartScheduler,StartScheduler 内部采用一个阻塞的 FIFO 的队列。初始地址通常会派生出很多其他待抓取的地址,派生出来的其他地址采用 SpiderScheduler 进行管理,SpiderScheduler 内部采用线程安全的非阻塞 FIFO 队列。这种设计使的 gecco 对初始地址采用了深度遍历的策略,即一个线程抓取完一个初始地址后才会去抓取另外一个初始地址;对初始地址派生出来的地址,采用广度优先策略。
Downloader 负责从 Scheduler 中获取需要下载的请求,gecco 默认采用 httpclient4.x 作为下载引擎。通过实现 Downloader 接口可以自定义自己的下载引擎。你也可以对每个请求定义 BeforeDownload 和 AfterDownload,实现不同的请求下载的个性需求。
Gecco 将下载下来的内容渲染为 SpiderBean,所有爬虫渲染的 JavaBean 都统一继承 SpiderBean,SpiderBean 又分为 HtmlBean 和 JsonBean 分别对应 html 页面的渲染和 json 数据的渲染。SpiderBeanFactroy 会根据请求的 url 地址,匹配相应的 SpiderBean,同时生成该 SpiderBean 的上下文 SpiderBeanContext。上下文 SpiderBeanContext 会告知这个 SpiderBean 采用什么渲染器,采用那个下载器,渲染完成后采用哪些 pipeline 处理等相关上下文信息。
pipeline 是 SpiderBean 渲染完成的后续业务处理单元,PipelineFactory 是 pipeline 的工厂类,负责 pipeline 实例化。通过扩展 PipelineFactory 就可以实现和 Spring 等业务处理框架的整合。
Gecco 框架最核心的类应该是 Spider 线程,一个爬虫引擎可以同时运行多个 Spider 线程。Spider 描绘了这个框架运行的基本骨架,先从 Scheduler 获取请求,再通过 SpiderBeanFactory 匹配 SpiderBeanClass,再通过 SpiderBeanClass 找到 SpiderBean 的上下文,下载网页并对 SpiderBean 做渲染,将渲染后的 SpiderBean 交个 pipeline 处理。
<dependency>
<groupId>com.geccocrawler</groupId>
<artifactId>gecco</artifactId>
<version>x.x.x</version>
</dependency>
httpclient,jsoup,fastjson,reflections,cglib,rhino,log4j,jmxutils,commons-lang3
@Gecco(matchUrl="https://github.com/{user}/{project}", pipelines="consolePipeline")
public class MyGithub implements HtmlBean {
private static final long serialVersionUID = -7127412585200687225L;
@RequestParameter("user")
private String user;//url中的{user}值
@RequestParameter("project")
private String project;//url中的{project}值
@Text
@HtmlField(cssPath=".pagehead-actions li:nth-child(2) .social-count")
private String star;//抽取页面中的star
@Text
@HtmlField(cssPath=".pagehead-actions li:nth-child(3) .social-count")
private String fork;//抽取页面中的fork
@Html
@HtmlField(cssPath=".entry-content")
private String readme;//抽取页面中的readme
public String getReadme() {
return readme;
}
public void setReadme(String readme) {
this.readme = readme;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getProject() {
return project;
}
public void setProject(String project) {
this.project = project;
}
public String getStar() {
return star;
}
public void setStar(String star) {
this.star = star;
}
public String getFork() {
return fork;
}
public void setFork(String fork) {
this.fork = fork;
}
public static void main(String[] args) {
GeccoEngine.create()
//工程的包路径
.classpath("com.geccocrawler.gecco.demo")
//开始抓取的页面地址
.start("https://github.com/xtuhcy/gecco")
//开启几个爬虫线程
.thread(1)
//单个爬虫每次抓取完一个请求后的间隔时间
.interval(2000)
//循环抓取
.loop(true)
//使用pc端userAgent
.mobile(false)
//非阻塞方式运行
.start();
}
}
DynamicGecco 的目的是在不定义 SpiderBean 的情况下实现爬取规则的运行时配置。其实现原理是采用字节码编程,动态生成 SpiderBean,而且通过自定义的 GeccoClassLoader 实现了抓取规则的热部署。下面是一个简单 Demo,更复杂的 Demo 可以参考 com.geccocrawler.gecco.demo.dynamic 下的例子。
下面的代码实现了爬取规则的运行时配置:
DynamicGecco.html()
.gecco("https://github.com/{user}/{project}", "consolePipeline")
.requestField("request").request().build()
.stringField("user").requestParameter("user").build()
.stringField("project").requestParameter().build()
.stringField("star").csspath(".pagehead-actions li:nth-child(2) .social-count").text(false).build()
.stringField("fork").csspath(".pagehead-actions li:nth-child(3) .social-count").text().build()
.stringField("contributors").csspath("ul.numbers-summary > li:nth-child(4) > a").href().build()
.register();
//开始抓取
GeccoEngine.create()
.classpath("com.geccocrawler.gecco.demo")
.start("https://github.com/xtuhcy/gecco")
.run();
可以看到,DynamicGecco 的方式相比传统的注解方式代码量大大减少,而且很酷的一点是 DynamicGecco 支持运行时定义和修改规则。
教您使用 java 爬虫 gecco 抓取 JD 全部商品信息(一)
教您使用 java 爬虫 gecco 抓取 JD 全部商品信息(二)
教您使用 java 爬虫 gecco 抓取 JD 全部商品信息(三)
一个完整的例子,分页处理,结合 spring,mysql 入库
- 博客:http://my.oschina.net/u/2336761/blog
- 邮箱:[email protected]
- QQ 群:531949844
Gecco 的发展离不开大家支持,扫一扫请作者喝杯咖啡~
请遵守开源协议MIT