Java分布式爬虫框架:Gecco 入门

/ 技术 / 无站内评论 / 616浏览

什么是Gecco ?

Gecco 是一款用java语言开发的轻量化的易用的网络爬虫,整合了jsoup、httpclient、fastjson、spring、htmlunit、redission等优秀框架。


为什么使用Gecco?


我是在码云上面搜了java爬虫框架,结果如下

前三个都有试过,但是远远没有Gecco的API简洁,上手简单。最重要的一点是:它跟我学过的Python的爬虫框架Scrapy用法很相似。

看图,不多说。

接下来我们上手吧

开源地址

https://gitee.com/xtuhcy/gecco


官网文档

http://www.geccocrawler.com/



依赖

目前最新版本1.3.0

<dependency>
<groupId>com.geccocrawler</groupId>
<artifactId>gecco</artifactId>
<version>1.3.0</version>
</dependency>

为了使我们代码更简洁,我们还要引入LomBok

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>


gecco的内容抽取都是直接映射到java bean的属性中,利用注解可以方便的注入页面中的各种信息包括html页面内容、Ajax请求、javascript变量、request信息等

http://www.geccocrawler.com/sysc-5/

常用注解

@HtmlField
html属性定义,表示该属性是通过html查找解析,在html的渲染器下使用
  • cssPath:jquery风格的元素选择器,使用jsoup实现。jsoup在分析html方面提供了极大的便利。计划实现xpath风格的元素选择器。
@Href
表示该字段是一个链接类型的元素,jsoup会默认获取元素的href属性值。属性必须是String类型。
  • value:默认获取href属性值,可以多选,按顺序查找
  • click:表示是否点击打开,继续让爬虫抓取
@Image
表示该字段是一个图片类型的元素,jsoup会默认获取元素的src属性值。属性必须是String类型。
  • value:默认获取src属性值,可以多选,按顺序查找
  • download:表示是否需要将图片下载到本地
@Attr
获取html元素的attribute。属性支持java基本类型的自动转换。
  • value:表示属性名称
@Text
获取元素的text或者owntext。属性支持java基本类型的自动转换。
  • own:是否获取owntext,默认为是
@Html
默认类型,可以不写,获取html元素的整个节点内容。属性必须是String类型。


快速开始

package me.liao.gecco.liaowo;

import com.geccocrawler.gecco.GeccoEngine;
import com.geccocrawler.gecco.annotation.*;
import com.geccocrawler.gecco.spider.HtmlBean;
import lombok.Data;

//Lombok注解 省去get/set方法
@Data
// matchUrl 是要抓取的地址 这里的{id}是个占位符 pipelines后面讲
@Gecco(matchUrl = "https://sanii.cn/article/{id}", pipelines = "liaowome")
public class liaowo implements HtmlBean {
private static final long serialVersionUID = -7127412585200687225L;

@RequestParameter("id")
private String id;

@Text
@HtmlField(cssPath = "body > article > div.post-header > h1 > a")
private String title;

@Text
@HtmlField(cssPath = "body > article > div.post-header > div")
private String view;

@Html
@HtmlField(cssPath = "#post-content")
private String content;

public static void main(String[] args) {
GeccoEngine.create()
//工程的包路径
.classpath("me.liao.gecco.liaowo")
//开始抓取的页面地址
.start("https://sanii.cn/article/249")
//开启几个爬虫线程
.thread(1)
//单个爬虫每次抓取完一个请求后的间隔时间
.interval(2000)
//循环抓取
.loop(true)
//使用pcuserAgent
.mobile(false)
//非阻塞方式运行
.start();
}
}


HtmlField字段的提取规则我们怎么写呢?

我们可以借助chrome浏览器解决

拿上面的代码举例(唉,我又拿自己的站点举例了 受伤)

我们要爬取title、view、content的数据。


如上图,会得到页面的DOM节点(如3),此时右键Copy>Copy selector 即可得到>  body > article > div.post-header > h1 > a 类似这样的内容,直接填入HtmlField即可。

重复如下可以得到


我们可以直接在main方法中启动测试一下

public static void main(String[] args) {
GeccoEngine.create()
//工程的包路径
.classpath("me.liao.gecco.liaowo")
//开始抓取的页面地址
.start("https://sanii.cn/article/249")
//开启几个爬虫线程
.thread(1)
//单个爬虫每次抓取完一个请求后的间隔时间
.interval(2000)
//循环抓取
.loop(true)
//使用pcuserAgent
.mobile(false)
//非阻塞方式运行
.start();
}

Gecco如何运行

Gecco的初始化和启动通过GeccoEngine完成,GeccoEngine主要负责初始化配置、开始请求的配置和启动爬虫运行,最基本的启动方法:

GeccoEngine.create()
    .classpath("com.geccocrawler.gecco.demo")
    .start("https://github.com/xtuhcy/gecco")
    .start();

classpath是必填项,指定扫描@Gecco的包路径。start是初始请求地址。start()表示采用非阻塞方式运行爬虫。

GeccoEngine基本配置项

非阻塞启动和阻塞启动

Main Thread-->GeccoEngine Thread-->Spider Thread

Main Thread-->Spider Thread

输出结果

我们怎么得到爬取的数据bean呢?

这个问题我在官网的文档中找了很久,并没有找到相关的文章。最后是在翻一些Demo的时候找到的

@PipelineName("liaowome")
public class ConsolePipeline implements Pipeline<SpiderBean> {

@Override
public void process(SpiderBean bean) {
System.out.println("爬虫结果: " + JSON.toJSONString(bean));
}
}

创建一个类,格式如上。在Process中就可以得到我们的数据

这里有一个坑:

PipelineName的名字最好不要是consolePipeline,我从demo上照搬了这个名字,导致在获取的时候死活得不到数据。

改成我们定义的PipelineName。

把爬到的数据保存到文本中

@PipelineName("liaowome")
public class ConsolePipeline implements Pipeline<SpiderBean> {

@Override
public void process(SpiderBean bean) {
System.out.println("爬虫结果: " + JSON.toJSONString(bean));
try {
File to = new File("E:\\liaowome.txt");
Files.append(JSON.toJSONString(bean) + System.getProperty("line.separator"), to, Charsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
}
}
}

System.getProperty("line.separator") 得到当前操作系统的换行符;

上面使用了Guava包(Gecco自带了Guava依赖)的Files类,一行代码解决。

代码下载

点我下载

召唤蕾姆
琼ICP备18000156号

鄂公网安备 42011502000211号