小爬虫Gecco 01


网络爬虫的定义与Gecco快速开始

什么是爬虫?

WiKi中的定义:网络爬虫(英语:web crawler),也叫网络蜘蛛(spider),是一种用来自动浏览万维网的网络机器人。其目的一般为编纂网络索引网络搜索引擎等站点通过爬虫软件更新自身的网站内容或其对其他网站的索引。网络爬虫可以将自己所访问的页面保存下来,以便搜索引擎事后生成索引供用户搜索。

通俗来讲,爬虫就是一个探测机器,它的基本操作就是模拟人的行为去各个网站溜达,点点按钮,查查数据,或者把看到的信息背回来。就像一只虫子在一幢楼里不知疲倦地爬来爬去。

由此我们可以知道,爬虫的应用领域有:搜索引擎、比价网站、舆情系统、知识信息储备。

网络爬虫工作原理是什么?

网络爬虫一般分为如下两个阶段:第一阶段,URL库初始化然后开始爬取;第二阶段,爬虫读取没有访问过的URL,来确定它的工作范围。对于所要抓取的URL,具体步骤如下:

  1. 获取URL链接;
  2. 解析内容,获取URL相关数据;
  3. 存储有价值的数据;
  4. 对新抓取的RL进行规范化;
  5. 过滤掉不相关的URL;
  6. 将要抓取的URL更新到URL库中;
  7. 重复步骤2,直到终止条件为止。

爬虫实现策略包括哪些?

  • 指定初始URL下载的选择策略
  • 检测页面是否更新的重新访问策略
  • 定义如何避免网站过度访问的约定性策略
  • 如何部署分布式网络爬虫的并行策略

网络爬虫主要爬取策略有:深度优先策略宽度优先策略等等。

一个典型的网络爬虫系统组成包括哪些?

网络爬虫本质是对网络资源的抓取、分析、过滤、存储。一个典型的网络爬虫系统组成主要有控制器,解析器,资源库三部分组成。

控制器负责给多线程中的各个爬虫线程分配工作任务。

解析器的主要工作是下载网页,进行页面的处理。

资源库是用来存放下载到的网页资源,一般都采用大型的数据库存储,如Oracle数据库,并对其建立索引。

知己知彼:常用的反爬虫手段

常见的反爬虫手段包括:统计IP访问限制、单个session访问量以及单个User-agent的访问,基于网站流量统计和日志分析反爬虫,通过Headers反爬虫,添加验证码限制等。

介绍:什么是Gecco?

Gecco 是一款基于 java 语言开发的轻量化的易用的网络爬虫。Gecco 整合了 jsoup、httpclient、fastjson、spring、htmlunit、redission 等优秀框架,让您只需要配置一些 jquery 风格的选择器就能很快的写出一个爬虫。

Gecco主要特征

  1. 使用 jquery 风格的选择器抽取元素
  2. 支持爬取规则的动态配置和加载
  3. 支持页面中的异步 ajax 请求
  4. 支持页面中的 javascript 变量抽取
  5. 利用 Redis 实现分布式抓取
  6. 支持结合 Spring 开发业务逻辑
  7. 支持 htmlunit 扩展
  8. 支持插件扩展机制
  9. 支持下载时 UserAgent 随机选取
  10. 支持下载代理服务器随机选取

框架概述

img

GeccoEngine

GeccoEngine 是爬虫引擎,每个爬虫引擎最好是一个独立进程,在分布式爬虫场景下,建议每台爬虫服务器(物理机或者虚机)运行一个 GeccoEngine。爬虫引擎包括 Scheduler、Downloader、Spider、SpiderBeanFactory、PipelineFactory 5 个主要模块。

Scheduler(下载地址管理)

通常爬虫需要一个有效管理下载地址的角色,Scheduler 负责下载地址的管理。gecco 对初始地址的管理使用 StartScheduler,StartScheduler 内部采用一个阻塞的 FIFO 的队列。初始地址通常会派生出很多其他待抓取的地址,派生出来的其他地址采用 SpiderScheduler 进行管理,SpiderScheduler 内部采用线程安全的非阻塞 FIFO 队列。这种设计使的 gecco 对初始地址采用了深度遍历的策略,即一个线程抓取完一个初始地址后才会去抓取另外一个初始地址;对初始地址派生出来的地址,采用广度优先策略。

Downloader(下载器)

Downloader 负责从 Scheduler 中获取需要下载的请求,gecco 默认采用 httpclient4.x 作为下载引擎。通过实现 Downloader 接口可以自定义自己的下载引擎。你也可以对每个请求定义 BeforeDownload 和 AfterDownload,实现不同的请求下载的个性需求。

SpiderBeanFactory(爬虫工厂类:生成爬虫SpiderBean)

Gecco 将下载下来的内容渲染为 SpiderBean,所有爬虫渲染的 JavaBean 都统一继承 SpiderBean,SpiderBean 又分为 HtmlBean 和 JsonBean 分别对应 html 页面的渲染和 json 数据的渲染。SpiderBeanFactroy 会根据请求的 url 地址,匹配相应的 SpiderBean,同时生成该 SpiderBean 的上下文 SpiderBeanContext。上下文 SpiderBeanContext 会告知这个 SpiderBean 采用什么渲染器,采用那个下载器,渲染完成后采用哪些 pipeline 处理等相关上下文信息。

PipelineFactory(管道工厂类)

pipeline 是 SpiderBean 渲染完成的后续业务处理单元,PipelineFactory 是 pipeline 的工厂类,负责 pipeline 实例化。通过扩展 PipelineFactory 就可以实现和 Spring 等业务处理框架的整合。

Spider

Gecco 框架最核心的类应该是 Spider 线程,一个爬虫引擎可以同时运行多个 Spider 线程。Spider 描绘了这个框架运行的基本骨架,先从 Scheduler 获取请求,再通过 SpiderBeanFactory 匹配 SpiderBeanClass,再通过 SpiderBeanClass 找到 SpiderBean 的上下文,下载网页并对 SpiderBean 做渲染,将渲染后的 SpiderBean 交给 pipeline 处理。

GeccoEngine基本配置项

  • loop(true):表示是否循环抓取,默认为false
  • thread(2):表示开启的爬虫线程数量,默认是1,需要注意的是线程数量要小于或者等于start请求的数量
  • interval(2000):表示某个线程在抓取完成一个请求后的间隔时间,单位是毫秒,系统会在左右1秒时间内随机。如果为2000,系统会在1000~3000之间随机选取。
  • mobile(false):表示使用移动端还是pc端的UserAgent。默认为false使用pc端的UserAgent。
  • debug(true):是否开启debug模式,如果开启debug模式,会在控制台输出jsoup元素抽取的日志。
  • pipelineFactory(PipelineFactory):自定义Pipeline工厂类
  • scheduler(Scheduler):自定义请求队列管理器

非阻塞启动和阻塞启动

  • start():非阻塞启动,GeccoEngine会单独启动线程运行,推荐以该方式运行。线程模型如下:

Main Thread–>GeccoEngine Thread–>Spider Thread

  • run():阻塞启动,GeccoEngine在主线程中启动运行,非循环模式GeccoEngine需要等待其他爬虫线程运行完毕后才会退出。线程模型r如下:

Main Thread–>Spider Thread

Maven导入jar包

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

项目quick-start

快速入门源码:

@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();
    }
}

代码说明

  • 接口HtmlBean说明该爬虫是一个解析html页面的爬虫(gecco还支持json格式的解析)
  • 注解@Gecco告知该爬虫匹配的url格式(matchUrl)和内容抽取后的bean处理类(pipelines处理类采用管道过滤器模式,可以定义多个处理类)。
  • 注解@RequestParameter可以注入url中的请求参数,如@RequestParameter(“user”)表示匹配url中的{user}
  • 注解@HtmlField表示抽取html中的元素,cssPath采用类似jquery的css selector选取元素
  • 注解@Text表示获取@HtmlField抽取出来的元素的text内容
  • 注解@Html表示获取@HtmlField抽取出来的元素的html内容(如果不指定默认为@Html)
  • GeccoEngine表示爬虫引擎,通过create()初始化,通过start()/run()运行。可以配置一些启动参数如:扫描**@Gecco注解**的包名classpath;开始抓取的url地址star;抓取线程数thread;抓取完一个页面后的间隔时间interval(ms)等

@Gecco自定义注解

@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Gecco {

   /**
    * 摒弃正则表达式的匹配方式,采用更容易理解的{value}方式
    * 如:https://github.com/{user}/{project}
    * 
    * @return url匹配规则
    */
   String[] matchUrl() default "*";
   
   /**
    * url下载器,默认为httpClientDownloader
    * 
    * @return 下载器
    */
   String downloader() default "";
   
   /**
    * 下载超时时间
    * 
    * @return 下载超时时间
    */
   int timeout() default 3000;
   
   /**
    * bean渲染完成后,后续的管道过滤器
    * 
    * @return 管道过滤器
    */
   String[] pipelines() default "";
}

伏笔:在启动quickstart之后,打印出了以下错误信息:

image-20220628175501708

具体问题解决看下篇~

本篇结束


文章作者: 银色回廊
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 银色回廊 !
评论
  目录