手写分布式爬虫框架

分布式爬虫框架 Demo

记录用Java开发一个简单的分布式爬虫框架,从最开始的十几行代码到开发一个支持集群、分布式的爬虫框架。

代码地址:单机版本 分布式版本

起因

在训练智能问答机器人的模型时,缺少模型数据,决定使用爬虫进行。
当前每天的生活如下:

  • 写一个爬虫抓数据
  • 训练模型
  • 查看训练结果

弊端

  • 单线程爬虫太慢了,没法充分利用计算资源,亟需性能提升。
  • 目标网站经常变更,势必经常添加、修改爬取网站。需要一个框架(其实已有很多很好地框架,这里仅为了学习)。
  • 手动触发爬虫和训练太蠢了,希望自动触发,夜里完成

由于“懒”,第一步第二步占用了90%的时间,决定将其自动化。

目标

  • 每天凌晨2点定时增量抓取数据并保存
  • 每天凌晨3点训练模型
  • 每天白天到实验室增加爬虫数据源,看结果,调整模型

用最简单的代码实现一个爬虫

用十几行代码爬取全站新闻 代码地址


建立爬虫模型(接口)

用面向对象的思想将爬取数据抽象为

  • 任务(主要包含目标网站 url)
  • 爬虫(执行任务(发起HTTP请求),返回目标 url 的数据)
  • 结果处理(将爬虫返回的数据处理,主要包含解析、保存)

模型完善
上面的基本模型有了,但是还不够完善,补充一些东西。

  • 为了充分利用计算资源,爬虫和结果都使用多线程执行,线程还要复用,这里为他们分为两个不同的线程池(IO和计算)。
  • 为了消除任务创建和爬虫的耦合,在任务和爬虫间增加一个队列(因为在处理页面结果时,可能再发出新的爬虫HTTP请求,或者说创建爬虫任务)。

初步方案如图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6NSFv1Wb-1591437963199)(https://gitee.com/ChinaLym/learn-spider/raw/single-1.0/spider.png)]

模型解读

  • 由爬虫启动器(SpiderStarter)创建爬虫任务(SpiderTask)加入到任务队列(SpiderTaskQueue)
  • 爬虫管理器(SpiderManager)间歇性的从爬虫任务队列中尝试获取全部任务,并分配给爬虫(Spider)使用新线程去爬取
  • 爬虫(Spider)向任务(SpiderTask)中描述的url发起Http请求并反回结果,交给结果处理器接头人(ResultHanderManager)然后等等爬虫管理器(SpiderManager)再次分配任务。
  • 爬虫结果处理器接头人(ResultHanderManager)收到结果后开启处理线程,交给对应的结果处理器(Handler)去处理
  • 爬虫结果处理器(Handler)来处理返回的数据(匹配想要的内容,保存到希望的文件),若希望爬取深一层的url,也可以在处理过程中创建新的爬虫任务,扔进爬虫队列(SpiderTaskQueue)

触发

  • 项目启动时
  • 每天凌晨2点

调用启动器(SpiderStarter)的start方法即可。

代码实现
单机版本

使用

想新增加一个网站的爬取处理时,只需要新增一个爬虫类型:

  • 新建 xxxSpiderTask 类来保存 url 和任务类型
  • 新建 xxxHandler 类来处理新的爬取来的数据

集群,异构

实验室里有多台电脑,想充分利用这些电脑,就得让自己的爬虫支持集群,由于爬虫本身并不关心是否支持集群,那就从刚才搭好的框架做,框架实现,所有爬虫便全都支持。

需要改动的点

由于我们已经使用面向对象的思想建立好了模型,因此想支持集群只需要多个实例共享 Task 的状态即可。故只需要将 SpiderTaskQueue 切换为消息中间件,并实现Task的序列化即可。

其中消息中间件开源的有如 RabbitMq、KafKa 等,序列化直接用 Json 就好了。

代码参见 Gitee

分布式

集群后其实一个实例既能爬取,又能处理,但爬虫和处理消耗的资源不对等,因此决定将它拆开,分开运行,同时实验室有专门的同学也可以用python写爬虫,也有会Java的同学专门做数据处理,充分发挥各个语言的优势。

.#### 需要改动的点

为了解决这个问题很简单,我们只需要将爬虫执行器和处理器分开即可,只需要添加一个爬虫结果队列,爬虫执行完后,将结果放置在队列中,爬虫结果处理器从这个队列里取就好了。

代码参见 爬虫执行器代码 爬虫处理器代码

这样可以更加合理的利用计算机资源。

  • 当爬虫任务大量增加时,便可以只部署爬虫执行实例,快速爬取。
  • 当爬虫结果多但任务少时,可以减少爬虫执行器的实例,增加结果处理实例加速解析。

后语

本框架仅为思想启发,如何将一个问题更好地解决,未关注性能问题,实现中有很多可以优化的点~。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章