pip3 install scrapy-redis
Scrapy-redis提供了四種組件(components):
(四種組件意味著這四個模塊都要做相應(yīng)的修改)
- Scheduler
Scrapy中跟“待爬隊列”直接相關(guān)的就是調(diào)度器Scheduler,它負(fù)責(zé)對新的request進(jìn)行入列操作(加入Scrapy queue)疗我,取出下一個要爬取的request(從Scrapy queue中取出)等操作高每。它把待爬隊列按照優(yōu)先級建立了一個字典結(jié)構(gòu)。
- Duplication Filter
Scrapy中用集合實現(xiàn)這個request去重功能坞琴,Scrapy中把已經(jīng)發(fā)送的request指紋放入到一個集合中,把下一個request的指紋拿到集合中比對逗抑,如果該指紋存在于集合中剧辐,說明這個request發(fā)送過了,如果沒有則繼續(xù)操作邮府。
在scrapy-redis中去重是由Duplication Filter組件來實現(xiàn)的荧关,它通過redis的set 不重復(fù)的特性,巧妙的實現(xiàn)了Duplication Filter去重褂傀。scrapy-redis調(diào)度器從引擎接受request忍啤,將request的指紋存?redis的set檢查是否重復(fù),并將不重復(fù)的request push寫?redis的 request queue仙辟。
引擎請求request(Spider發(fā)出的)時同波,調(diào)度器從redis的request queue隊列?里根據(jù)優(yōu)先級pop 出?個request 返回給引擎,引擎將此request發(fā)給spider處理欺嗤。
- Item Pipeline
引擎將(Spider返回的)爬取到的Item給Item Pipeline参萄,scrapy-redis 的Item Pipeline將爬取到的 Item 存?redis的 items queue。
修改過Item Pipeline可以很方便的根據(jù) key 從 items queue 提取item煎饼,從?實現(xiàn) items processes集群讹挎。
- Base Spider
不在使用scrapy原有的Spider類校赤,重寫的RedisSpider繼承了Spider和RedisMixin這兩個類,RedisMixin是用來從redis讀取url的類筒溃。
當(dāng)我們生成一個Spider繼承RedisSpider時马篮,調(diào)用setup_redis函數(shù),這個函數(shù)會去連接redis數(shù)據(jù)庫怜奖,然后會設(shè)置signals(信號):
一個是當(dāng)spider空閑時候的signal浑测,會調(diào)用spider_idle函數(shù),這個函數(shù)調(diào)用schedule_next_request函數(shù)歪玲,保證spider是一直活著的狀態(tài)迁央,并且拋出DontCloseSpider異常。
一個是當(dāng)抓到一個item時的signal滥崩,會調(diào)用item_scraped函數(shù)岖圈,這個函數(shù)會調(diào)用schedule_next_request函數(shù),獲取下一個request钙皮。
Scrapy_redis式工作流程
修改設(shè)置文件
(1)設(shè)置去重組件,使用的是scrapy_redis的去重組件,而不再使用scrapy框架自己的去重組件了
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
(2)設(shè)置調(diào)度器,使用的是scrapy_redis重寫的調(diào)度器,而不再使用scrapy框架自帶的調(diào)度器了
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
(3)可以實現(xiàn)斷點爬确淇啤(請求的記錄不會丟失,會存儲在redis數(shù)據(jù)庫中,不會清除redis的任務(wù)隊列)
SCHEDULER_PERSIST = True
(4)設(shè)置任務(wù)隊列的模式(三選一)
SpiderPriorityQueue是scrapy_redis默認(rèn)使用的隊列模式
(有自己的優(yōu)先級)
SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"
使用了隊列的形式,任務(wù)先進(jìn)先出
SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderQueue"
采用了棧的形式,任務(wù)先進(jìn)后出
SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderStack"
(5)實現(xiàn)這個管道,可以將爬蟲端獲取的item數(shù)據(jù),統(tǒng)一保存在redis數(shù)據(jù)庫中
'scrapy_redis.pipelines.RedisPipeline': 400,
(6)指定要存儲的redis數(shù)據(jù)庫的主機ip
REDIS_HOST = '127.0.0.1'
指定redis數(shù)據(jù)庫主機的端口
REDIS_PORT = 6379
"xcfCrawlSpider:requests":存儲的是請求的request對象
"xcfCrawlSpider:items":存儲的爬蟲端獲取的items數(shù)據(jù)
"xcfCrawlSpider:dupefilter":存儲的指紋(為了實現(xiàn)去重)
127.0.0.1:6379> type xcfCrawlSpider:requests
zset
127.0.0.1:6379> type xcfCrawlSpider:items
list
127.0.0.1:6379> type xcfCrawlSpider:dupefilter
set
第一種情況:只設(shè)置settings.py文件,并沒有實現(xiàn)分布式,知識使用了sctapy_redis的數(shù)據(jù)存儲和去重功能
-
第二種情況:實現(xiàn)通用爬蟲的分布式爬蟲
from scrapy_redis.spiders import RedisCrawlSpider #繼承制:RedisCrawlSpider class MyCrawler(RedisCrawlSpider): """Spider that reads urls from redis queue (myspider:start_urls).""" name = 'mycrawler_redis' allowed_domains = ['dmoz.org'] #缺少了start_url,多了redis_key:根據(jù)redis_key從redis #數(shù)據(jù)庫中獲取任務(wù) redis_key = 'mycrawler:start_urls'
啟動爬蟲:scrapy crawl 爬蟲名稱
現(xiàn)象:爬蟲處于等待狀態(tài)
需要設(shè)置起始任務(wù):
lpush mycrawler:start_urls 目標(biāo)url
-
第三中情況:實現(xiàn)scrpy.spider爬蟲的分布式爬蟲
from scrapy_redis.spiders import RedisSpider #繼承制:RedisSpider class MyCrawler(RedisSpider): """Spider that reads urls from redis queue (myspider:start_urls).""" name = 'mycrawler_redis' allowed_domains = ['dmoz.org'] #缺少了start_url,多了redis_key:根據(jù)redis_key從redis #數(shù)據(jù)庫中獲取任務(wù) redis_key = 'mycrawler:start_urls'
啟動爬蟲:scrapy crawl 爬蟲名稱
現(xiàn)象:爬蟲處于等待狀態(tài)
需要設(shè)置起始任務(wù):
lpush mycrawler:start_urls 目標(biāo)url
僅為個人學(xué)習(xí)小結(jié),若有錯處短条,歡迎指正~