Scrapy Redis
Posted dalton
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scrapy Redis相关的知识,希望对你有一定的参考价值。
安装
使用pip安装:
$ pip install scrapy_redis |
在使用Scrapy_redis之前,先来讲一讲它的原理。
在Redis中,有一个数据结果叫做“列表”。这个列表和 Python 的列表很相似,可以添加数据进去,也可以从里面读取数据或者删除元素。
在下图的例子中,创建一个名字叫做 spider 的列表,从列表的尾部添加了三个元素:“hotstone”, "shilei" 和 "slzcc",然后再从列表的头部一个一个元素的读取并删除。
127.0.0.1:6379> lrange spider 0 -1 (empty list or set ) 127.0.0.1:6379> rpush spider ‘hotstone‘ (integer) 1 127.0.0.1:6379> rpush spider ‘shilei‘ (integer) 2 127.0.0.1:6379> rpush spider ‘slzcc‘ (integer) 3 127.0.0.1:6379> lrange spider 0 -1 1) "hotstone" 2) "shilei" 3) "slzcc" 127.0.0.1:6379> lpop spider "hotstone" 127.0.0.1:6379> lpop spider "shilei" 127.0.0.1:6379> lpop spider "slzcc" |
在 Scrapy_redis 中,也是使用了这个原理,Scrapy 通过:
yield scrapy.Request(URL, callback = xxxx) |
这一个语句将URL放到Redis的队列中,然后在生成器中的代码被执行的时候再去Redis中取这个URL。如果多个服务器的爬虫都从Redis中读取URL的话,这就是分布式爬虫。
Scrapy_redis 的使用
由于Scrapy_redis已经为封装了大部分的流程,所以使用它不会有任何难度。
修改爬虫
爬虫是继承自scrapy.Spider这个父类。这是Scrapy里面最基本的一个爬虫类,只能实现基本的爬虫功能。现在需要把它替换掉,从而实现更高级的功能。
请对比一下下面这段使用了Scrapy_redis的代码与前面read color网站爬虫的代码头部有什么不同:
from scrapy_redis.spiders import RedisSpider class ReadColorSpider(RedisSpider): name = "zhihuspider" redis_key = ‘zhihuspider:start_urls‘ |
可以看出,这里爬虫的父类已经改成了RedisSpider,同时多了一个:
redis_key = ‘zhihuspider:start_urls‘ |
这里的redis_key实际上就是一个变量名,之后爬虫爬到的所有URL都会保存到Redis中这个名为“zhihuspider:start_urls”的列表下面,爬虫同时也会从这个列表中读取后续页面的URL。这个变量名可以任意修改。
除了这两点以外,在爬虫部分的其他代码都不需要做修改。
实际上,这样就已经建立了一个分布式爬虫,只不过现在只有一台电脑。
修改设置
现在已经把三轮车换成了挖掘机,但是Scrapy还在按照指挥三轮车的方式指挥挖掘机,所以挖掘机还不能正常工作。因此修改爬虫文件还不行,Scrapy还不能认识这个新的爬虫。现在修改settings.py。
(1)Scheduler
首先是Scheduler的替换,这个东西是Scrapy中的调度员。在settings.py中添加以下代码:
# Enables scheduling storing requests queue in redis. SCHEDULER = "scrapy_redis.scheduler.Scheduler" |
(2)去重
# Ensure all spiders share same duplicates filter through redis. DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" |
设置好上面两项以后,爬虫已经可以正常开始工作了。不过还可以多设置一些东西使爬虫更好用。
(3)不清理Redis队列
# Don‘t cleanup redis queues, allows to pause/resume crawls. SCHEDULER_PERSIST = True |
如果这一项为True,那么在Redis中的URL不会被Scrapy_redis清理掉,这样的好处是:爬虫停止了再重新启动,它会从上次暂停的地方开始继续爬取。但是它的弊端也很明显,如果有多个爬虫都要从这里读取URL,需要另外写一段代码来防止重复爬取。
如果设置成了False,那么Scrapy_redis每一次读取了URL以后,就会把这个URL给删除。这样的好处是:多个服务器的爬虫不会拿到同一个URL,也就不会重复爬取。但弊端是:爬虫暂停以后再重新启动,它会重新开始爬。
爬虫请求的调度算法
爬虫的请求调度算法,有三种情况可供选择:
- 队列
SCHEDULER_QUEUE_CLASS = ‘scrapy_redis.queue.SpiderQueue‘ |
如果不配置调度算法,默认就会使用这种方式。它实现了一个先入先出的队列,先放进Redis的请求会优先爬取。
- 栈
SCHEDULER_QUEUE_CLASS = ‘scrapy_redis.queue.SpiderStack‘ |
这种方式,后放入到Redis的请求会优先爬取。
- 优先级队列
SCHEDULER_QUEUE_CLASS = ‘scrapy_redis.queue.SpiderPriorityQueue‘ |
这种方式,会根据一个优先级算法来计算哪些请求先爬取,哪些请求后爬取。这个优先级算法比较复杂,会综合考虑请求的深度等各个因素。
【拓展阅读】
Redis信息,如果不配置的话,Scrapy_redis会默认Redis就运行在现在这台电脑上,IP和端口也都是默认的127.0.0.1和6379。如果Redis不在本地的话,就需要将它们写出来:
REDIS_HOST = ‘127.0.0.1‘ #修改为Redis的实际IP地址 REDIS_PORT = 6379 #修改为Redis的实际端口 |
代码展示:
修复 BUG
如果出现了 scrapy_redis 字符串报错的信息请修改,路径有可能不一样,这里使用 Macbook brew 安装后的路径:
/usr/local/Cellar/python3/3 .6.0 /Frameworks/Python .framework /Versions/3 .6 /lib/python3 .6 /site-packages/scrapy_redis/spiders .py |
中添加,如图
data = data.decode() |
配置文件讲解
#启用Redis调度存储请求队列SCHEDULER = "scrapy_redis.scheduler.Scheduler" #确保所有的爬虫通过Redis去重 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" #默认请求序列化使用的是pickle 但是我们可以更改为其他类似的。PS:这玩意儿2.X的可以用。3.X的不能用 #SCHEDULER_SERIALIZER = "scrapy_redis.picklecompat" #不清除Redis队列、这样可以暂停/恢复 爬取 #SCHEDULER_PERSIST = True #使用优先级调度请求队列 (默认使用) #SCHEDULER_QUEUE_CLASS = ‘scrapy_redis.queue.PriorityQueue‘ #可选用的其它队列 #SCHEDULER_QUEUE_CLASS = ‘scrapy_redis.queue.FifoQueue‘ #SCHEDULER_QUEUE_CLASS = ‘scrapy_redis.queue.LifoQueue‘ #最大空闲时间防止分布式爬虫因为等待而关闭 #SCHEDULER_IDLE_BEFORE_CLOSE = 10 #将清除的项目在redis进行处理 ITEM_PIPELINES =
‘scrapy_redis.pipelines.RedisPipeline‘ : 300
#序列化项目管道作为redis Key存储 #REDIS_ITEMS_KEY = ‘%(spider)s:items‘ #默认使用ScrapyJSONEncoder进行项目序列化 #You can use any importable path to a callable object. #REDIS_ITEMS_SERIALIZER = ‘json.dumps‘ #指定连接到redis时使用的端口和地址(可选) #REDIS_HOST = ‘localhost‘ #REDIS_PORT = 6379 #指定用于连接redis的URL(可选) #如果设置此项,则此项优先级高于设置的REDIS_HOST 和 REDIS_PORT #REDIS_URL = ‘redis://user:pass@hostname:9001‘ #自定义的redis参数(连接超时之类的) #REDIS_PARAMS = #自定义redis客户端类 #REDIS_PARAMS[‘redis_cls‘] = ‘myproject.RedisClient‘ #如果为True,则使用redis的‘spop‘进行操作。 #如果需要避免起始网址列表出现重复,这个选项非常有用。开启此选项urls必须通过sadd添加,否则会出现类型错误。 #REDIS_START_URLS_AS_SET = False #RedisSpider和RedisCrawlSpider默认 start_usls 键 #REDIS_START_URLS_KEY = ‘%(name)s:start_urls‘ #设置redis使用utf-8之外的编码 #REDIS_ENCODING = ‘latin1‘ |
官方地址介绍:http://scrapy-redis.readthedocs.io/en/stable/readme.html
以上是关于Scrapy Redis的主要内容,如果未能解决你的问题,请参考以下文章
scrapy基础知识之 Scrapy 和 scrapy-redis的区别:
Python爬虫 scrapy -- scrapy 日志信息和日志等级scrapy shell的使用scrapy post请求