十、Gecco爬虫框架的线程和队列模型

简述

爬虫在抓取一个页面后一般有两个任务,一个是解析页面内容,一个是将需要继续抓取的url放入队列继续抓取。因此,当爬取的网页很多的情况下,待抓取url的管理也是爬虫框架需要解决的问题。本文主要说的是gecco爬虫框架的队列和线程模型。

线程和队列模型

线程和队列模型

  • gecco的队列模型是两级队列模型。分为初始请求队列和派生请求队列。初始请求队列在循环模式下是一个阻塞式的FIFO队列,在非循环模式下是一个非阻塞式的FIFO队列。派生队列是一个非阻塞的剔重的FIFO队列;
  • 线程首先去初始请求队列按照FIFO原则获取一个请求,如果线程数量大于初始请求队列的数量,多余的线程就会待定新的初始请求入队,因此建议线程数量不要大于初始请求队列的数量;
  • 对于循环模式loop(true),线程在抓取完成后,会将初始请求重新放入队列;
  • 多线程只对初始请求队列有效,每个线程会有自己的派生请求队列,因此派生请求队列是在单线程下运行的,爬虫将派生请求放入队列继续抓取,直到没有派生请求;
  • 线程在抓取完成派生请求后,会继续向初始请求队列获取初始请求

为什么要用这种模型

  • Gecco的线程模型很像浏览器,每一个线程对应一个浏览器的Tab。每个浏览器的Tab一次只能看一个页面,因此就有了初始请求队列多线程,派生请求队列单线程的模型。
  • 使用这种队列和线程模型开发人员很好理解,结构简单易懂,效率也能保证。想用多线程提高效率就想办法放入初始请求队列。

如何动态的获取初始请求队列

如果想通过多线程提高爬虫的效率就需要想办法将请求放入初始请求队列。我们可以先通过一个爬虫引擎将待抓取的请求保存起来。另外一个爬虫引擎以第一个爬虫引擎获取的请求作为初始请求开启多线程运行。简单说就是初始请求也是可以抓取出来的,并不一定非要写死。下面是jd采用多线程抓取的一段代码,全部代码已经上传github。

    //先获取分类列表,放入AllSortPipeline.sortRequests
    HttpGetRequest start = new HttpGetRequest("http://www.jd.com/allSort.aspx");
    start.setCharset("GBK");
    GeccoEngine.create()
    .classpath("com.geccocrawler.gecco.demo.jd")
    .start(start)
    .run();


    //分类列表下的商品列表采用5线程抓取
    GeccoEngine.create()
    .classpath("com.geccocrawler.gecco.demo.jd")
    //从上面的GeccoEngine获取初始请求
    .start(AllSortPipeline.sortRequests)
    .thread(5)
    .interval(2000)
    .start();

gecco

继续阅读此作者的更多文章