“百行代码”实现简单的Python分布式爬虫

2020-06-19 00:00:00 数据 分布式 爬虫 机器 抓取
本篇文章属于进阶知识,可能会用到以前出现在专栏文章中的知识,如果你是次关注本专栏,建议你先阅读下其他文章:查询--爬虫(计算机网络)

现在搞爬虫的人,可能被问的多的问题就是“你会不会分布式爬虫?”。给人的感觉就是你不会分布式爬虫,都不好意思说自己是搞爬虫的。但其实分布式爬虫的原理比较简单,大多数的业务用不到分布式模式。

所谓的分布式爬虫,就是多台机器合作进行爬虫工作,提高工作效率。

分布式爬虫需要考虑的问题有:

(1)如何从一个统一的接口获取待抓取的URL?

(2)如何保证多台机器之间的排重操作?即保证不会出现多台机器同时抓取同一个URL。

(3)当多台机器中的一台或者几台挂掉,如何保证任务继续,且数据不会丢失?

这里首先利用Redis数据库解决前两个问题。

Redis数据库是一种key-value数据库,它本身包含了一些比较好的特性,比较适合解决分布式爬虫的问题。关于Redis的一些基本概念、操作等,建议读者自行百度。我们这里使用到Redis中自带的“消息队列”,来解决分布式爬虫问题。具体实现步骤如下:

  1. 在Redis中初始化两条key-value数据,对应的key分别为spider.wait和spider.all。
  2. spider.wait的value是一个list队列,存放我们待抓取的URL。该数据类型方便我们实现消息队列。我们使用lpush操作添加URL数据,同时使用brpop监听并获取取URL数据。
  3. spider.all的value是一个set集合,存放我们所有待抓取和已抓取的URL。该数据类型方便我们实现排重操作。我们使用sadd操作添加数据。

在我的代码中,我是在原来爬虫框架的基础上,添加了分布式爬虫模式(一个文件),该文件的代码行数大概在100行左右,所以文章标题为“百行代码”。但实际上,在每台客户端机器上,我都使用了多线程爬虫框架。即:

(1)每台机器从Redis获取待抓取的URL,执行“抓取--解析--保存”的过程

(2)每台机器本身使用多线程爬虫模式,即有多个线程同时从Redis获取URL并抓取

(3)每台机器解析数据得到的新的URL,会传回Redis数据库,同时保证数据一致性

(4)每台机器单独启动自己的爬虫,之后单独关闭爬虫任务,没有自动功能

具体可查看代码:distributed_threads.py

这里的代码还不够完善,主要还要如下的问题:

  • 抓取的数据如何统一汇总。解决方法:可以统一保存到某个数据库
  • 如何解决第3个问题,即当某台机器挂掉,如何保证数据不丢失
  • 如何自动启动、关闭分布式爬虫

有兴趣解决问题的,可以fork代码之后,自行修改,并提交pull-requests。

=============================================================

作者主页:笑虎(Python爱好者,关注爬虫、数据分析、数据挖掘、数据可视化等)

作者专栏主页:撸代码,学知识 - 知乎专栏

作者GitHub主页:撸代码,学知识 - GitHub

欢迎大家拍砖、提意见。相互交流,共同进步!

==============================================================

相关文章