分布式爬虫
爬虫,即模拟网络请求,获得目标页面数据的一种方式。
简单的爬虫,比如单线程爬虫,一个爬虫处理所有内容:拿到任务,发起请求,处理反爬,解析内容,入库。但效率低下,为了加快速度,可以使用多线程,多进程爬虫,相当于多个爬虫,每个爬虫除了任务可能不同,其他的过程从请求到入库全部一样。速度可以较大幅度的获得提升,但速度提升是有限的。并且这种单个线程或进程进行的一条龙式的运行,本身并不是最合理的方法。
网络IO和读写IO的效率是不同的,并且网络IO还处于一种不稳定状态,因此应该将爬虫的任务进行合理的分解,分解的各个部分间,因该具有低耦合性,互相间的影响较小,比如网络IO阻塞时,并不会影响系统读写IO,两个模块可以独立运行。
初步分解:
- 任务队列
- 任务队列之所以单独作为一个模块,是因为大规模抓取时,一个任务需要很多组成项,任务的url,代理ip,目标网站的ip(cdn)等,这些内容需要进行合理的组合。
- 尽可能提高代理ip的使用效率,尽可能的合理使用目标网站ip(cdn),尽可能降低对目标服务器的压力。以本方较小的时间代价,目标网站较小的服务器压力,完成任务。
- 任务队列由多种选择,可以使用celery,可以使用RabbitMQ,也可使用redis进行构建
- 下载器
- 从任务队列中拿到任务,处理反爬,进行下载,将结果存入解析器中,如果反爬措施消耗较大,应考虑将反爬单独作为一个模块进行处理
- 下载器结构简单,可支持快速水平扩容,增加服务器,部署程序,即可加大抓取量
- 下载方式:对速度不高可使用多线程多进程爬虫,对速度要求较高的可使用多进程+异步爬虫
- 解析器
- 负责解析网页,获得目标数据
- 也可以集成在下载器中,可使用xpath或re
- 缓存数据库
- 下载量较大时,比如每小时抓取百万级的页面,那么需要入库的数据可能已经时千万级别,如此大量的数据直接入库,会造成mysql奔溃,需要进行中转缓存
- 可以考虑使用redis,基于内存,速度快,有持久化(RDB和AOF),可作为中间缓存,也不会存在大量丢失数据
- 数据入库
- 数据量较小时,可不用单独设置一台服务器,也不需要进行过多设置。
- 当数据量较大,达到每小时千万以上,考虑单独使用一台服务器作为数据库,并将较大内存分配给mysql,保证具有足够的缓冲空间,避免内存不足
以上是初步分解,每个模块都可能可以再继续细分,降低耦合,增加效率,比如任务队列,要保证代理ip和cdn的合理使用,简单的使用random是远远不够的,必须进行合理的分配。