scrapy-redis 分布式爬蟲(chóng)框架

scrapy-redis(0.6)依賴的環(huán)境

Scrapy >= 1.0.0 #終于過(guò)了1版本劫窒,這個(gè)太重要了,總算坑小了點(diǎn)燃乍,感謝那些為了解決各種scrapy與scrapy-redis不兼容做出了貢獻(xiàn)的開(kāi)發(fā)者和博主悟泵。redis-py >= 2.10.0redis server >= 2.8.0

0.6版本的主要更新內(nèi)容是更新代碼以支持Scrapy 1.0香到; 增加了-a domain=... option for example spiders.

雖然scrapy能做的事情很多图柏,但是要做到大規(guī)模的分布式應(yīng)用則捉襟見(jiàn)肘序六。有能人改變了scrapy的隊(duì)列調(diào)度,將起始的網(wǎng)址從start_urls里分離出來(lái)蚤吹,改為從redis讀取例诀,多個(gè)客戶端可以同時(shí)讀取同一個(gè)redis,從而實(shí)現(xiàn)了分布式的爬蟲(chóng)裁着。

scrapy-redis架構(gòu):



scrapy-Redis組件詳解:


四種組件:

Scheduler繁涂,Duplication Filter,Item Pipeline二驰,Base Spider

1扔罪、Scheduler: scrapy改造了python本來(lái)的collection.deque(雙向隊(duì)列)形成了自己的Scrapy

queue,但是Scrapy多個(gè)spider不能共享待爬取隊(duì)列Scrapy

queue桶雀,即Scrapy本身不支持爬蟲(chóng)分布式矿酵,scrapy-redis 的解決是把這個(gè)Scrapy

queue換成redis數(shù)據(jù)庫(kù)(也是指redis隊(duì)列),從同一個(gè)redis-server存放要爬取的request矗积,便能讓多個(gè)spider去同一個(gè)數(shù)據(jù)庫(kù)里讀取全肮。Scrapy中跟“待爬隊(duì)列”直接相關(guān)的就是調(diào)度器Scheduler,它負(fù)責(zé)對(duì)新的request進(jìn)行入列操作(加入Scrapy

queue)漠魏,取出下一個(gè)要爬取的request(從Scrapy

queue中取出)等操作倔矾。它把待爬隊(duì)列按照優(yōu)先級(jí)建立了一個(gè)字典結(jié)構(gòu),然后根據(jù)request中的優(yōu)先級(jí)柱锹,來(lái)決定該入哪個(gè)隊(duì)列哪自,出列時(shí)則按優(yōu)先級(jí)較小的優(yōu)先出列。為了管理這個(gè)比較高級(jí)的隊(duì)列字典禁熏,Scheduler需要提供一系列的方法壤巷。但是原來(lái)的Scheduler已經(jīng)無(wú)法使用,所以使用Scrapy-redis的scheduler組件瞧毙。

2胧华、Duplication Filter

Scrapy中用集合實(shí)現(xiàn)這個(gè)request去重功能,Scrapy中把已經(jīng)發(fā)送的request指紋放入到一個(gè)集合中宙彪,把下一個(gè)request的指紋拿到集合中比對(duì)矩动,如果該指紋存在于集合中,說(shuō)明這個(gè)request發(fā)送過(guò)了释漆,如果沒(méi)有則繼續(xù)操作悲没。這個(gè)核心的判重功能是這樣實(shí)現(xiàn)的:

在scrapy-redis中去重是由Duplication Filter組件來(lái)實(shí)現(xiàn)的,它通過(guò)redis的set不重復(fù)的特性男图,巧妙的實(shí)現(xiàn)了DuplicationFilter去重示姿。scrapy-redis調(diào)度器從引擎接受request甜橱,將request的指紋存入redis的set檢查是否重復(fù),并將不重復(fù)的request push寫(xiě)入redis的 request queue栈戳。

引擎請(qǐng)求request(Spider發(fā)出的)時(shí)岂傲,調(diào)度器從redis的request queue隊(duì)列里根據(jù)優(yōu)先級(jí)pop 出?個(gè)request 返回給引擎,引擎將此request發(fā)給spider處理子檀。

3镊掖、Item Pipeline:

引擎將(Spider返回的)爬取到的Item給Item Pipeline,scrapy-redis 的Item Pipeline將爬取到的

Item 存入redis的 items queue命锄。修改過(guò)Item Pipeline可以很方便的根據(jù) key 從 items queue

提取item堰乔,從而實(shí)現(xiàn) items processes集群。

4脐恩、Base Spider

不在使用scrapy原有的Spider類镐侯,重寫(xiě)的RedisSpider繼承了Spider和RedisMixin這兩個(gè)類,RedisMixin是用來(lái)從redis讀取url的類驶冒。

當(dāng)我們生成一個(gè)Spider繼承RedisSpider時(shí)苟翻,調(diào)用setup_redis函數(shù),這個(gè)函數(shù)會(huì)去連接redis數(shù)據(jù)庫(kù)骗污,然后會(huì)設(shè)置signals(信號(hào)):一個(gè)是當(dāng)spider空閑時(shí)候的signal崇猫,會(huì)調(diào)用spider_idle函數(shù),這個(gè)函數(shù)調(diào)用schedule_next_request函數(shù)需忿,保證spider是一直活著的狀態(tài)诅炉,并且拋出DontCloseSpider異常。一個(gè)是當(dāng)抓到一個(gè)item時(shí)的signal屋厘,會(huì)調(diào)用item_scraped函數(shù)涕烧,這個(gè)函數(shù)會(huì)調(diào)用schedule_next_request函數(shù),獲取下一個(gè)request汗洒。

5议纯、 總結(jié)

總結(jié)一下scrapy-redis的總體思路:這套組件通過(guò)重寫(xiě)scheduler和spider類,實(shí)現(xiàn)了調(diào)度溢谤、spider啟動(dòng)和redis的交互瞻凤;

實(shí)現(xiàn)新的dupefilter和queue類,達(dá)到了判重和調(diào)度容器和redis的交互世杀,因?yàn)槊總€(gè)主機(jī)上的爬蟲(chóng)進(jìn)程都訪問(wèn)同一個(gè)redis數(shù)據(jù)庫(kù)阀参,所以調(diào)度和判重都統(tǒng)一進(jìn)行統(tǒng)一管理,達(dá)到了分布式爬蟲(chóng)的目的瞻坝;當(dāng)spider被初始化時(shí)蛛壳,同時(shí)會(huì)初始化一個(gè)對(duì)應(yīng)的scheduler對(duì)象,這個(gè)調(diào)度器對(duì)象通過(guò)讀取settings,配置好自己的調(diào)度容器queue和判重工具dupefilter炕吸;

每當(dāng)一個(gè)spider產(chǎn)出一個(gè)request的時(shí)候,scrapy引擎會(huì)把這個(gè)reuqest遞交給這個(gè)spider對(duì)應(yīng)的scheduler對(duì)象進(jìn)行調(diào)度勉痴,scheduler對(duì)象通過(guò)訪問(wèn)redis對(duì)request進(jìn)行判重赫模,如果不重復(fù)就把他添加進(jìn)redis中的調(diào)度器隊(duì)列里。當(dāng)調(diào)度條件滿足時(shí)蒸矛,scheduler對(duì)象就從redis的調(diào)度器隊(duì)列中取出一個(gè)request發(fā)送給spider瀑罗,讓他爬取雏掠;

當(dāng)spider爬取的所有暫時(shí)可用url之后斩祭,scheduler發(fā)現(xiàn)這個(gè)spider對(duì)應(yīng)的redis的調(diào)度器隊(duì)列空了,于是觸發(fā)信號(hào)spider_idle乡话,spider收到這個(gè)信號(hào)之后摧玫,直接連接redis讀取strart_url池,拿去新的一批url入口绑青,然后再次重復(fù)上邊的工作诬像。


scrapy-Redis分布式策略:


Slaver端從Master端拿任務(wù)(Request/url/ID)進(jìn)行數(shù)據(jù)抓取,在抓取數(shù)據(jù)的同時(shí)也生成新任務(wù)闸婴,并將任務(wù)拋給Master坏挠。Master端只有一個(gè)Redis數(shù)據(jù)庫(kù),負(fù)責(zé)對(duì)Slaver提交的任務(wù)進(jìn)行去重邪乍、加入待爬隊(duì)列降狠。

優(yōu)點(diǎn):scrapy-redis默認(rèn)使用的就是這種策略,我們實(shí)現(xiàn)起來(lái)很簡(jiǎn)單庇楞,因?yàn)槿蝿?wù)調(diào)度等工作scrapy-redis都已經(jīng)幫我們做好了榜配,我們只需要繼承RedisSpider、指定redis_key就行了姐刁。

缺點(diǎn):scrapy-redis調(diào)度的任務(wù)是Request對(duì)象芥牌,里面信息量比較大(不僅包含url,還有callback函數(shù)聂使、headers等信息)壁拉,導(dǎo)致的結(jié)果就是會(huì)降低爬蟲(chóng)速度、而且會(huì)占用Redis大量的存儲(chǔ)空間柏靶。當(dāng)然我們可以重寫(xiě)方法實(shí)現(xiàn)調(diào)度url弃理。

創(chuàng)建項(xiàng)目


這個(gè)爬蟲(chóng)繼承了RedisSpider,它能夠支持分布式的抓取屎蜓,采用的是basic spider痘昌,需要寫(xiě)parse函數(shù)。其次就是不再有start_urls了,取而代之的是redis_key辆苔,scrapy-redis將key從Redis里pop出來(lái)算灸,成為請(qǐng)求的url地址。

修改settings.py

修改設(shè)置settings.py

①Scheduler驻啤,首先是Scheduler的替換菲驴,這個(gè)東西是Scrapy中的調(diào)度員。在settings.py中添加以下代碼:

SCHEDULER="scrapy_redis.scheduler.Scheduler"

②去重

DUPEFILTER_CLASS="scrapy_redis.dupefilter.RFPDupeFilter"

③不清理Redis隊(duì)列

SCHEDULER_PERSIST=True

如果這一項(xiàng)為True骑冗,那么在Redis中的URL不會(huì)被Scrapy_redis清理掉赊瞬,這樣的好處是:爬蟲(chóng)停止了再重新啟動(dòng),它會(huì)從上次暫停的地方開(kāi)始繼續(xù)爬取贼涩。但是它的弊端也很明顯巧涧,如果有多個(gè)爬蟲(chóng)都要從這里讀取URL,需要另外寫(xiě)一段代碼來(lái)防止重復(fù)爬取遥倦。

如果設(shè)置成了False谤绳,那么Scrapy_redis每一次讀取了URL以后,就會(huì)把這個(gè)URL給刪除袒哥。這樣的好處是:多個(gè)服務(wù)器的爬蟲(chóng)不會(huì)拿到同一個(gè)URL闷供,也就不會(huì)重復(fù)爬取。但弊端是:爬蟲(chóng)暫停以后再重新啟動(dòng)统诺,它會(huì)重新開(kāi)始爬歪脏。

④設(shè)置redis地址

啟用本地redis:? REDIS_URL = 'redis://127.0.0.1:6379'

啟用遠(yuǎn)程redis:? REDIS_URL = 'redis://39.106.155.194:6379'

其他設(shè)置(可選)

爬蟲(chóng)請(qǐng)求的調(diào)度算法

爬蟲(chóng)的請(qǐng)求調(diào)度算法,有三種情況可供選擇:

①隊(duì)列

SCHEDULER_QUEUE_CLASS='scrapy_redis.queue.SpiderQueue'

如果不配置調(diào)度算法粮呢,默認(rèn)就會(huì)使用這種方式婿失。它實(shí)現(xiàn)了一個(gè)先入先出的隊(duì)列,先放進(jìn)Redis的請(qǐng)求會(huì)優(yōu)先爬取啄寡。

②棧

SCHEDULER_QUEUE_CLASS='scrapy_redis.queue.SpiderStack'

這種方式豪硅,后放入到Redis的請(qǐng)求會(huì)優(yōu)先爬取。

③優(yōu)先級(jí)隊(duì)列

SCHEDULER_QUEUE_CLASS='scrapy_redis.queue.SpiderPriorityQueue'

這種方式挺物,會(huì)根據(jù)一個(gè)優(yōu)先級(jí)算法來(lái)計(jì)算哪些請(qǐng)求先爬取懒浮,哪些請(qǐng)求后爬取。這個(gè)優(yōu)先級(jí)算法比較復(fù)雜识藤,會(huì)綜合考慮請(qǐng)求的深度等各個(gè)因素砚著。

呼~(yú)~配置完這些,爬蟲(chóng)就可以正常工作了痴昧,slave從master取url采集數(shù)據(jù)稽穆,當(dāng)master redis中"shixisheng:start_urls"和"slave_1:requests"都為空時(shí),爬蟲(chóng)會(huì)暫停等待赶撰,直到redis中有新的url舌镶。若再無(wú)新url添加進(jìn)來(lái)柱彻,就可以在此刻結(jié)束程序。


運(yùn)行爬蟲(chóng)

scrapy runspider myspider.py

向redis中裝入url們

redis-cli lpush myspider:start_urls http://xiaowangzhi.com

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末餐胀,一起剝皮案震驚了整個(gè)濱河市哟楷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌否灾,老刑警劉巖吓蘑,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異坟冲,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)溃蔫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門健提,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人伟叛,你說(shuō)我怎么就攤上這事私痹。” “怎么了统刮?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵紊遵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我侥蒙,道長(zhǎng)暗膜,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任鞭衩,我火速辦了婚禮学搜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘论衍。我一直安慰自己瑞佩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布坯台。 她就那樣靜靜地躺著炬丸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蜒蕾。 梳的紋絲不亂的頭發(fā)上稠炬,一...
    開(kāi)封第一講書(shū)人閱讀 50,050評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音咪啡,去河邊找鬼酸纲。 笑死,一個(gè)胖子當(dāng)著我的面吹牛瑟匆,可吹牛的內(nèi)容都是我干的闽坡。 我是一名探鬼主播栽惶,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼疾嗅!你這毒婦竟也來(lái)了外厂?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤代承,失蹤者是張志新(化名)和其女友劉穎汁蝶,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體论悴,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡掖棉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了膀估。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片幔亥。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖察纯,靈堂內(nèi)的尸體忽然破棺而出帕棉,到底是詐尸還是另有隱情,我是刑警寧澤饼记,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布香伴,位于F島的核電站,受9級(jí)特大地震影響具则,放射性物質(zhì)發(fā)生泄漏即纲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一博肋、第九天 我趴在偏房一處隱蔽的房頂上張望崇裁。 院中可真熱鬧,春花似錦束昵、人聲如沸拔稳。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)巴比。三九已至,卻和暖如春礁遵,著一層夾襖步出監(jiān)牢的瞬間轻绞,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工佣耐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留政勃,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓兼砖,卻偏偏與公主長(zhǎng)得像奸远,于是被迫代替她去往敵國(guó)和親既棺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • 引言 在上篇使用Scrapy爬取知乎用戶信息我們編寫(xiě)了一個(gè)單機(jī)的爬蟲(chóng)懒叛,這篇記錄了使用Scrapy-Redis將其重...
    朱曉飛閱讀 6,688評(píng)論 1 24
  • 前言 scrapy是python界出名的一個(gè)爬蟲(chóng)框架丸冕。Scrapy是一個(gè)為了爬取網(wǎng)站數(shù)據(jù),提取結(jié)構(gòu)性數(shù)據(jù)而編寫(xiě)的應(yīng)...
    以后的以后_hzh閱讀 2,259評(píng)論 0 14
  • 背景 部門(東方IC薛窥、圖蟲(chóng))業(yè)務(wù)驅(qū)動(dòng)胖烛,需要搜集大量圖片資源,做數(shù)據(jù)分析诅迷,以及正版圖片維權(quán)佩番。前期主要用node做爬蟲(chóng)...
  • 為甚要學(xué)習(xí)scrapy_redis?罢杉? Scrapy_redis在scrapy的基礎(chǔ)上實(shí)現(xiàn)了更多趟畏,更強(qiáng)大的功能,具...
    Pickupthesmokes閱讀 1,052評(píng)論 0 1
  • 昨天蒙塵的法國(guó)梧桐屑那,今天一如既往地深綠對(duì)于這件事實(shí),我只能保持緘默一個(gè)人被現(xiàn)實(shí)涂成墨色她對(duì)生存的理解不比一株草來(lái)的...
    南方小余閱讀 446評(píng)論 0 4