Scrapy的架構(gòu)太重要了,單用一篇文章再總結(jié)整合下。前兩張圖來(lái)自《Learning Scrapy》,第三張圖來(lái)自Scrapy 1.0中文官方文檔(該中文文檔只到1.0版),第四張圖來(lái)自Scrapy 1.4英文官方文檔(最新版),是我翻譯的。
一、Scrapy的Twisted引擎模型
這里重要的概念是單線程、NIO、延遲項(xiàng)和延遲鏈。
二、Scrapy的性能模型
Scrapy包括以下部分:
- 調(diào)度器:大量的Request在這里排隊(duì),直到下載器處理它們。其中大部分是URL,因此體積不大,也就是說(shuō)即便有大量請(qǐng)求存在,也可以被下載器及時(shí)處理。
- 阻塞器:這是抓取器由后向前進(jìn)行反饋的一個(gè)安全閥,如果進(jìn)程中的響應(yīng)大于5MB,阻塞器就會(huì)暫停更多的請(qǐng)求進(jìn)入下載器。這可能會(huì)造成性能的波動(dòng)。
- 下載器:這是對(duì)Scrapy的性能最重要的組件。它用復(fù)雜的機(jī)制限制了并發(fā)數(shù)。它的延遲(管道長(zhǎng)度)等于遠(yuǎn)程服務(wù)器的響應(yīng)時(shí)間,加上網(wǎng)絡(luò)/操作系統(tǒng)、Python/Twisted的延遲。我們可以調(diào)節(jié)并發(fā)請(qǐng)求數(shù),但是對(duì)其它延遲無(wú)能為力。下載器的能力受限于CONCURRENT_REQUESTS*設(shè)置。
- 爬蟲:這是抓取器將Response變?yōu)镮tem和其它Request的組件。只要我們遵循規(guī)則來(lái)寫爬蟲,通常它不是瓶頸。
- Item Pipelines:這是抓取器的第二部分。我們的爬蟲對(duì)每個(gè)Request可能產(chǎn)生幾百個(gè)Items,只有CONCURRENT_ITEMS會(huì)被并行處理。這一點(diǎn)很重要,因?yàn)?,如果你用pipelines連接數(shù)據(jù)庫(kù),你可能無(wú)意地向數(shù)據(jù)庫(kù)導(dǎo)入數(shù)據(jù),pipelines的默認(rèn)值(100)就會(huì)看起來(lái)很少。
爬蟲和pipelines的代碼是異步的,會(huì)包含必要的延遲,但二者不會(huì)是瓶頸。爬蟲和pipelines很少會(huì)做繁重的處理工作。如果是的話,服務(wù)器的CPU則是瓶頸。
三、Scrapy架構(gòu)
原文鏈接:http://scrapy-chs.readthedocs.io/zh_CN/latest/topics/architecture.html
接下來(lái)的圖表展現(xiàn)了Scrapy的架構(gòu),包括組件及在系統(tǒng)中發(fā)生的數(shù)據(jù)流的概覽(綠色箭頭所示)。 下面對(duì)每個(gè)組件都做了簡(jiǎn)單介紹,并給出了詳細(xì)內(nèi)容的鏈接。數(shù)據(jù)流如下所描述。
組件
Scrapy Engine
引擎負(fù)責(zé)控制數(shù)據(jù)流在系統(tǒng)中所有組件中流動(dòng),并在相應(yīng)動(dòng)作發(fā)生時(shí)觸發(fā)事件。 詳細(xì)內(nèi)容查看下面的數(shù)據(jù)流(Data Flow)部分。
調(diào)度器(Scheduler)
調(diào)度器從引擎接受request并將他們?nèi)腙?duì),以便之后引擎請(qǐng)求他們時(shí)提供給引擎。
下載器(Downloader)
下載器負(fù)責(zé)獲取頁(yè)面數(shù)據(jù)并提供給引擎,而后提供給spider。
Spiders
Spider是Scrapy用戶編寫用于分析response并提取item(即獲取到的item)或額外跟進(jìn)的URL的類。 每個(gè)spider負(fù)責(zé)處理一個(gè)特定(或一些)網(wǎng)站。 更多內(nèi)容請(qǐng)看 Spiders 。
Item Pipeline
Item Pipeline負(fù)責(zé)處理被spider提取出來(lái)的item。典型的處理有清理、 驗(yàn)證及持久化(例如存取到數(shù)據(jù)庫(kù)中)。 更多內(nèi)容查看 Item Pipeline 。
下載器中間件(Downloader middlewares)
下載器中間件是在引擎及下載器之間的特定鉤子(specific hook),處理Downloader傳遞給引擎的response。 其提供了一個(gè)簡(jiǎn)便的機(jī)制,通過(guò)插入自定義代碼來(lái)擴(kuò)展Scrapy功能。更多內(nèi)容請(qǐng)看 下載器中間(Downloader Middleware) 。
Spider中間件(Spider middlewares)
Spider中間件是在引擎及Spider之間的特定鉤子(specific hook),處理spider的輸入(response)和輸出(items及requests)。 其提供了一個(gè)簡(jiǎn)便的機(jī)制,通過(guò)插入自定義代碼來(lái)擴(kuò)展Scrapy功能。更多內(nèi)容請(qǐng)看 Spider中間件(Middleware) 。
數(shù)據(jù)流(Data flow)
Scrapy中的數(shù)據(jù)流由執(zhí)行引擎控制,其過(guò)程如下:
- 引擎打開一個(gè)網(wǎng)站(open a domain),找到處理該網(wǎng)站的Spider并向該spider請(qǐng)求第一個(gè)要爬取的URL(s)。
- 引擎從Spider中獲取到第一個(gè)要爬取的URL并在調(diào)度器(Scheduler)以Request調(diào)度。
- 引擎向調(diào)度器請(qǐng)求下一個(gè)要爬取的URL。
- 調(diào)度器返回下一個(gè)要爬取的URL給引擎,引擎將URL通過(guò)下載中間件(請(qǐng)求(request)方向)轉(zhuǎn)發(fā)給下載器(Downloader)。
- 一旦頁(yè)面下載完畢,下載器生成一個(gè)該頁(yè)面的Response,并將其通過(guò)下載中間件(返回(response)方向)發(fā)送給引擎。
- 引擎從下載器中接收到Response并通過(guò)Spider中間件(輸入方向)發(fā)送給Spider處理。
- Spider處理Response并返回爬取到的Item及(跟進(jìn)的)新的Request給引擎。
- 引擎將(Spider返回的)爬取到的Item給Item Pipeline,將(Spider返回的)Request給調(diào)度器。
- (從第二步)重復(fù)直到調(diào)度器中沒有更多地request,引擎關(guān)閉該網(wǎng)站。
事件驅(qū)動(dòng)網(wǎng)絡(luò)(Event-driven networking)
Scrapy基于事件驅(qū)動(dòng)網(wǎng)絡(luò)框架 Twisted 編寫。因此,Scrapy基于并發(fā)性考慮由非阻塞(即異步)的實(shí)現(xiàn)。
關(guān)于異步編程及Twisted更多的內(nèi)容請(qǐng)查看下列鏈接:
四、Scrapy架構(gòu)
原文鏈接:https://docs.scrapy.org/en/latest/topics/architecture.html
下圖展示了Scrapy的架構(gòu)、它的組件及數(shù)據(jù)流(紅色箭頭)。分別對(duì)組件和數(shù)據(jù)流進(jìn)行了說(shuō)明。
數(shù)據(jù)流
數(shù)據(jù)流是受執(zhí)行引擎控制的,流程如下:
- 引擎從爬蟲得到初始請(qǐng)求;
- 引擎在調(diào)度器中調(diào)度請(qǐng)求,并請(qǐng)求下一個(gè)要爬取的請(qǐng)求;
- 調(diào)度器返回引擎下一個(gè)要爬取的請(qǐng)求;
- 通過(guò)下載中間件,引擎將請(qǐng)求發(fā)送到下載器;
- 頁(yè)面下載完畢之后,下載器生成一個(gè)該頁(yè)面的響應(yīng),并通過(guò)下載中間件發(fā)送給引擎;
- 引擎收到來(lái)自下載器的響應(yīng),并通過(guò)爬蟲中間件,將它發(fā)送到爬蟲進(jìn)行處理;
- 爬蟲處理響應(yīng),而后返回抓取到的items和新的請(qǐng)求到引擎,返回還要要通過(guò)爬蟲中間件;
- 引擎將處理好的items發(fā)送到Item Pipelines,然后發(fā)送已處理的請(qǐng)求到調(diào)度器,并詢問(wèn)下個(gè)可能的請(qǐng)求;
- 這個(gè)過(guò)程重復(fù)進(jìn)行(從1開始),直到調(diào)度器沒有更多的請(qǐng)求。
組件
Scrapy引擎
引擎負(fù)責(zé)控制數(shù)據(jù)流在系統(tǒng)中所有組件中流動(dòng),并在相應(yīng)動(dòng)作發(fā)生時(shí)觸發(fā)事件。
調(diào)度器
調(diào)度器從引擎接受請(qǐng)求并將其排隊(duì),以便之后引擎請(qǐng)求它們時(shí)提供給引擎。
下載器
下載器負(fù)責(zé)獲取頁(yè)面,并提供給引擎,引擎再將其提供給爬蟲。
爬蟲
Spider是Scrapy用戶編寫的用于解析請(qǐng)求并提取item或額外跟進(jìn)的請(qǐng)求的類。
Item Pipeline
Item Pipeline負(fù)責(zé)處理爬蟲提取出來(lái)的item。典型的任務(wù)有清理、 驗(yàn)證及持久化(例如存取到數(shù)據(jù)庫(kù)中)。
下載器中間件
下載器中間件是在引擎及下載器之間的特定鉤子(specific hook),當(dāng)請(qǐng)求從引擎到下載器時(shí)處理請(qǐng)求,響應(yīng)從下載器到引擎時(shí)處理響應(yīng)。
如果要做以下的工作,就可以使用下載器中間件:
- 請(qǐng)求發(fā)送給下載器之前,處理這個(gè)請(qǐng)求(即,在Scrapy發(fā)送請(qǐng)求到網(wǎng)站之前);
- 傳遞響應(yīng)到爬蟲之前,修改收到的響應(yīng);
- 發(fā)送一個(gè)新的請(qǐng)求到爬蟲,而不是傳遞收到的響應(yīng)到爬蟲;
- 沒有獲取網(wǎng)頁(yè),直接傳遞響應(yīng)給爬蟲;
- 默默丟棄一些請(qǐng)求。
爬蟲中間件
爬蟲中間件是在引擎及爬蟲之間的特定鉤子(specific hook),處理爬蟲的輸入(響應(yīng))和輸出(items和請(qǐng)求)。
爬蟲中間件的可以用來(lái):
- 對(duì)爬蟲調(diào)回的輸出做后處理 —— 修改、添加、移除請(qǐng)求或items;
- 后處理初始請(qǐng)求(start_requests);
- 處理爬蟲異常;
- 調(diào)用errback,而不是基于響應(yīng)內(nèi)容調(diào)回一些請(qǐng)求。
事件驅(qū)動(dòng)網(wǎng)絡(luò)
Scrapy是基于事件驅(qū)動(dòng)網(wǎng)絡(luò)框架 Twisted 編寫的。因此,Scrapy基于并發(fā)考慮由非阻塞(異步)代碼實(shí)現(xiàn)。
關(guān)于異步編程及Twisted更多的內(nèi)容請(qǐng)查看下列鏈接: