scrapy的组建scrapy Engine ,scheduler,downloader,spider,item pipeline ,在编写爬虫程序一般用到的组件是 spider,item,pipeline,middleware
scrapy-redis 改写了scrapy的spider,pipeline,shedulers组件,由于scrapy原本的sheduler是在内存中,不支持分布式。
scrapy-redis改写了 spider中下载得到的request和item的传递路径,由传给原本的sheduler变更为 传给 共用的redis,在redis中存储并去重得到的request,最终得到的items也存储在redis中,sheduler由scrapy-redis内部实现。
这些改写,使得在编写分布式爬虫程序时,spider.py中由原来的继承scrapy.spiders.Spider变为继承scrapy_redis.spiders.RedisSpider,其他的无变化
item.py中无变化,Pipeline.py中也无变换,middlerwares.py中也无变化
主要设置在settings.py中
#scrapy-redis定义的Scheduler
SCHEDULER = 'scrapy_redis.scheduler.Scheduler'
#利用redis去重:
DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter'
#序列化方案
SCHEDULER_SERIALIZER = 'scrapy_redis.picklecompat'
#当scrapy中断时,是否保存记录,以便下次开启时能接着爬取
SCHEDULER_PERSIST = True
#是否在开启爬虫时清空上次留下的记录(去重,待爬url)
#SCHEDULER_FLUSH_ON_START=False
#队列名
REDIS_ITEMS_KEY='%(spider)s:items'
#键值对中键值命名规则
REDIS_START_URLS_KEY='%(name)s:start_urls'
#去重key值
#SCHEDULER_DUPEFILTER_KEY='%(spider)s:dupefilter'
#设置set格式(不允许重复的元素)
REDIS_START_URLS_AS_SET=False
#redis用于连接的参数redis.StrictRedis()
REDIS_PARAMS={
'host' : '120.79.135.4',
'port' : 6379,
'db' : 0,
'password' : 'redis$yeah',
'encoding':'utf-8',
}
scrapy-redis中主管redis连接的内容在 connection.py中,dupefilter.py用于去重,queue.py和scheduler.py实现了调度
上面的设置都是由于更换的scheduler到redis中所以需要添加的redis配置,下面的pipeline的设置需要注意的是scrapy_redis.pipelines.RedisPipeline是最后处理item的管道,所以如果要将item做其他的加工存储,写的pipeline的优先度排在它之前就可
#item存储管道
ITEM_PIPELINES={
'scrapy_redis.pipelines.RedisPipeline':300,
'myspider.pipelines.Tongch58Pipelines.PgPipeline':290,}
对scrapy项目进行了上述改动后,就可以将项目clone到不同的server上,进入项目所在的目录,执行 scrapy crawl spidername 就开启了各服务器上的spider,这时向共用的redis中执行 lpush myspider:start_urls https://myfisrt_crawl_url.com 各服务器上的spider之一就会爬去首页之一,将爬到的url存储到redis的 myspider:requests列表中存储,各sipder又从myspider:requests中获取url来爬取。
原scrapy中对requests的去重是在scheduler,所以,scrapy-redis重写的scheduler,利用了redis的set的特性实现了去重,在运行的过程中,在redis中看到这几个键值:
myspider:dupefilter 用于存储去重后的request
myspider:items 用于存储最终的items
myspider:requests 用于存储待爬去的request
scheduler在每个主机上都会实例化一个,并且和spider一一对应,所以分布式运行时会有一个spider的多个实例和一个scheduler的多个实例存在于不同的主机上,但是,因为scheduler都是用相同的调度机制,而这些容器都连接同一个redis服务器,又都使用spider名加queue来作为key读写数据,所以不同主机上的不同爬虫实例公用一个request池,实现了分布式爬虫之间的统一调度。
github上对scrapy-redis的介绍 https://github.com/rmax/scrapy-redis