Scrapy 和 scrapy-redis的區別
Scrapy 是一個通用的爬蟲框架,但是不支援分散式,Scrapy-redis是為了更方便地實現Scrapy分散式爬取,而提供了一些以redis為基礎的元件(僅有元件)。
pip install scrapy-redis
Scrapy-redis提供了下面四種元件(components):(四種元件意味著這四個模組都要做相應的修改)
Scheduler
Duplication Filter
Item Pipeline
Base Spider
scrapy-redis架構
scrapy-redis在scrapy的架構上增加了redis,基於redis的特性拓展瞭如下元件:Scheduler
:
Scrapy改造了python本來的collection.deque(雙向佇列)形成了自己的Scrapy queue(
Scrapy中跟“待爬佇列”直接相關的就是排程器Scheduler
,它負責對新的request進行入列操作(加入Scrapy queue),取出下一個要爬取的request(從Scrapy queue中取出)等操作。它把待爬佇列按照優先順序建立了一個字典結構,比如:
{
優先順序0 : 佇列0
優先順序1 : 佇列1
優先順序2 : 佇列2
}
然後根據request中的優先順序,來決定該入哪個佇列,出列時則按優先順序較小的優先出列。為了管理這個比較高階的佇列字典,Scheduler需要提供一系列的方法。但是原來的Scheduler已經無法使用,所以使用Scrapy-redis的scheduler元件。
Duplication Filter
Scrapy中用集合實現這個request去重功能,Scrapy中把已經發送的request指紋放入到一個集合中,把下一個request的指紋拿到集合中比對,如果該指紋存在於集合中,說明這個request傳送過了,如果沒有則繼續操作。這個核心的判重功能是這樣實現的:
def request_seen(self, request):
# self.request_figerprints就是一個指紋集合
fp = self.request_fingerprint(request)
# 這就是判重的核心操作
if fp in self.fingerprints:
return True
self.fingerprints.add(fp)
if self.file:
self.file.write(fp + os.linesep)
在scrapy-redis中去重是由Duplication Filter
元件來實現的,它通過redis的set 不重複的特性,巧妙的實現了Duplication Filter去重。scrapy-redis排程器從引擎接受request,將request的指紋存⼊redis的set檢查是否重複,並將不重複的request push寫⼊redis的 request queue。
引擎請求request(Spider發出的)時,排程器從redis的request queue佇列⾥里根據優先順序pop 出⼀個request 返回給引擎,引擎將此request發給spider處理。
Item Pipeline
:
引擎將(Spider返回的)爬取到的Item給Item Pipeline,scrapy-redis 的Item Pipeline將爬取到的 Item 存⼊redis的 items queue。
修改過Item Pipeline
可以很方便的根據 key 從 items queue 提取item,從⽽實現items processes
叢集。
Base Spider
不在使用scrapy原有的Spider類,重寫的RedisSpider
繼承了Spider和RedisMixin這兩個類,RedisMixin是用來從redis讀取url的類。
當我們生成一個Spider繼承RedisSpider時,呼叫setup_redis函式,這個函式會去連線redis資料庫,然後會設定signals(訊號):
一個是當spider空閒時候的signal,會呼叫spider_idle函式,這個函式呼叫
schedule_next_request
函式,保證spider是一直活著的狀態,並且丟擲DontCloseSpider異常。一個是當抓到一個item時的signal,會呼叫item_scraped函式,這個函式會呼叫
schedule_next_request
函式,獲取下一個request。