使用scrapy_redis进行kuku漫画全站爬取

2018-07-21  本文已影响160人  小温侯

思路

虽然scrapy支持多线程,但是单机scrapy也是有性能瓶颈的。使用scrapy-redis可以将scrapy改造成分布式的爬虫架构。

改造的原理是什么?

对于原版的scrapy,scrapy-redis修改了四个部分:调度器(Scheduler)、去重(Dupefilter)、管道(Pipeline)、抓取器(Spider)。其核心是使用了redis代替了原本的queue,因为redis可以作为一个消息队列,这样多个爬虫实例就可以通过共享消息队列来实现分布式了。

要实现分布式主要要解决的问题无非就是几个:

这里Scheduler就是用来分发任务的;如果配置了去重,Dupefilter会负责维护一个集合,包含抓取过的url,避免重复抓取;Pipeline可以是自己写的,也可以使用RedisPipeline将结果存储在redis中;最后Spider中需要实现具体爬虫功能的部分,也是写代码的地方。

如果一切顺利,你可以看到Redis中会出现三个序列:

scrapy_redis_db11.jpg

Redis中的key都是按照spidername:word的形式来命名的,其中Dupefiler用来去重,需要合适的配置项。Requests包含了所有爬取的序列,是所有各个爬虫节点的任务来源;同时所有在爬取过程中yield出的新request都会被放入这个序列。最后如果你在配置项中使用了RedisPipeline,Spider返回的结果会被存储在Items中。

除了这三个序列,有时候会有一个名为start_urls序列。如果你的爬虫只写了处理一个URL时的代码,但是没有其实URL,也就是说爬虫不知道从哪个url开始入手(有了第一个URL之后就会像蛛网一样衍生出更多的URL)。这时候你会需要用到redis-cli(redis的客户端程序)来手动向redis中添加一条url:

redis-cli -h redis_addr -p redis_port -n redis_db# lpush spidername:start_urls CustomURL

这个项目里我把start_urls直接写在代码里了。

怎么部署这个分布式爬虫?

scrapy本身支持并发和异步IO,通过修改其配置项CONCURRENT_REQUESTS来实现,默认为16。因为GIL的存在,如果配置合理,此时的爬虫会占满你一个CPU核心;通过手动执行N个爬虫实例(scrapy crawl comicCrawler),N一般是你的CPU核心数,你可以充分发挥出一台机器的性能。同样,在其他机器上,你可以执行相同的操作,所有的爬虫实例都共享一个redis数据库。通过这种多进程+多线程的模式,理论上可以最大限度地发挥机器的能力。

具体怎么做?

这里只包含了从scrapy转scrapy-redis需要修改的地方。

修改Setting.py

在官网上提供了一个scrapy-redis的完整配置文件,可以按需修改,一般来说,有几个是必须的,你需要在原本的Setting.py的基础上,增加:

SCHEDULER = "scrapy_redis.scheduler.Scheduler"
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
SCHEDULER_PERSIST = True
REDIS_HOST = '34.229.250.31'
REDIS_PORT = 6379
REDIS_PARAMS = {
    'db': 11
}
LOG_LEVEL = 'DEBUG'

几个比较重要参数是:

除了新增的几个配置项,如果你选择将最终的结果存入redis,你需要向ITEM_PIPELINES中添加scrapy_redis.pipelines.RedisPipeline管道。

ITEM_PIPELINES = {
    'comicspider.pipelines.ComicspiderPipeline': 300,
    'scrapy_redis.pipelines.RedisPipeline': 400
}

修改spider文件

所有涉及到的spider文件都需要修改,scarpy的spider类一般继承于scrapy.Spider,这里要调整为scrapy_redis.spiders。然后,没了。

这里没了是我这个例子中,不需要修改其他代码了。但是每个人可能写的spider的结构不一样,因此调整起来可能还有一点出入。

比如说:

代码和效果

代码我放在GitHub上了,我的笔记本是八核的,然后再加一个云主机,我一共起了9个实例,每个实例的并发数是16。最后跑出来,大概一个小时可以抓到27W结果。

上一篇 下一篇

猜你喜欢

热点阅读