scrapy架構(gòu)詳解

Scrapy架構(gòu)概覽

要探究清楚Spider Middleware,首先得對Scrapy框架的整體架構(gòu)有個(gè)大致的認(rèn)識,如下圖所示:


image.png

1,組件(Components)

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ì),以便之后引擎請求他們時(shí)提供給引擎。

下載器(Downloader)

下載器負(fù)責(zé)獲取頁面數(shù)據(jù)并提供給引擎,而后提供給spider。

Spiders

Spider是Scrapy用戶編寫用于分析response并提取item(即獲取到的item)或額外跟進(jìn)的URL的類。 每個(gè)spider負(fù)責(zé)處理一個(gè)特定(或一些)網(wǎng)站,我們前面幾篇文章中,通過Scrapy框架實(shí)現(xiàn)的爬蟲例子都是在Spiders這個(gè)組件中實(shí)現(xiàn)。 更多內(nèi)容請看 Spiders 。

管道(Item Pipeline)

Item Pipeline負(fù)責(zé)處理被spider提取出來的item。典型的處理有清理、 驗(yàn)證及持久化(例如存取到數(shù)據(jù)庫中)。 更多內(nèi)容查看 Item Pipeline 。

下載器中間件(Downloader Middlewares)

下載器中間件是在引擎及下載器之間的特定鉤子(specific hook),處理Downloader傳遞給引擎的response,以及引擎?zhèn)鬟f給Downloader的request,(介于reuqest和response之間) 其提供了一個(gè)簡便的機(jī)制,通過插入自定義代碼來擴(kuò)展Scrapy功能。更多內(nèi)容請看 Downloader Middleware 。

Spider中間件(Spider Middlewares)

Spider中間件是在引擎及Spider之間的特定鉤子(specific hook),處理spider的輸入(response)和輸出(items及requests)。 其提供了一個(gè)簡便的機(jī)制,通過插入自定義代碼來擴(kuò)展Scrapy功能。更多內(nèi)容請看 Spider Middleware 。

2,數(shù)據(jù)流(Data flow)

Scrapy中的數(shù)據(jù)流由執(zhí)行引擎控制,其過程如下:

1,引擎從Spiders中獲取到最初的要爬取的請求(Requests)。
2,引擎安排請求(Requests)到調(diào)度器中,并向調(diào)度器請求下一個(gè)要爬取的請求(Requests)。
3,調(diào)度器返回下一個(gè)要爬取的請求(Requests)給引擎。
4,引擎將上步中得到的請求(Requests)通過下載器中間件(Downloader Middlewares)發(fā)送給下載器(Downloader ),這個(gè)過程中下載器中間件(Downloader Middlewares)中的process_request()函數(shù)會(huì)被調(diào)用到。
5,一旦頁面下載完畢,下載器生成一個(gè)該頁面的Response,并將其通過下載中間件(Downloader Middlewares)發(fā)送給引擎,這個(gè)過程中下載器中間件(Downloader Middlewares)中的process_response()函數(shù)會(huì)被調(diào)用到。
6,引擎從下載器中得到上步中的Response并通過Spider中間件(Spider Middlewares)發(fā)送給Spider處理,這個(gè)過程中Spider中間件(Spider Middlewares)中的process_spider_input()函數(shù)會(huì)被調(diào)用到。
7,Spider處理Response并通過Spider中間件(Spider Middlewares)返回爬取到的Item及(跟進(jìn)的)新的Request給引擎,這個(gè)過程中Spider中間件(Spider Middlewares)的process_spider_output()函數(shù)會(huì)被調(diào)用到。
8,引擎將上步中Spider處理的其爬取到的Item給Item 管道(Pipeline),將Spider處理的Request發(fā)送給調(diào)度器,并向調(diào)度器請求可能存在的下一個(gè)要爬取的請求(Requests)。
9,(從第二步)重復(fù)直到調(diào)度器中沒有更多的請求(Requests)。

二,Spider中間件(Spider Middlewares)

Spider中間件是介入到Scrapy中的spider處理機(jī)制的鉤子框架,可以插入自定義功能來處理發(fā)送給 Spiders 的response,以及spider產(chǎn)生的item和request。

1,激活Spider中間件(Spider Middlewares)
要啟用Spider中間件(Spider Middlewares),可以將其加入到 SPIDER_MIDDLEWARES 設(shè)置中。 該設(shè)置是一個(gè)字典,鍵為中間件的路徑,值為中間件的順序(order)。

樣例:

SPIDER_MIDDLEWARES = {
'myproject.middlewares.CustomSpiderMiddleware': 543,
}
SPIDER_MIDDLEWARES 設(shè)置會(huì)與Scrapy定義的 SPIDER_MIDDLEWARES_BASE 設(shè)置合并(但不是覆蓋), 而后根據(jù)順序(order)進(jìn)行排序,最后得到啟用中間件的有序列表: 第一個(gè)中間件是最靠近引擎的,最后一個(gè)中間件是最靠近spider的。

關(guān)于如何分配中間件的順序請查看 SPIDER_MIDDLEWARES_BASE 設(shè)置,而后根據(jù)您想要放置中間件的位置選擇一個(gè)值。 由于每個(gè)中間件執(zhí)行不同的動(dòng)作,您的中間件可能會(huì)依賴于之前(或者之后)執(zhí)行的中間件,因此順序是很重要的。

如果您想禁止內(nèi)置的(在 SPIDER_MIDDLEWARES_BASE 中設(shè)置并默認(rèn)啟用的)中間件, 您必須在項(xiàng)目的 SPIDER_MIDDLEWARES設(shè)置中定義該中間件,并將其值賦為 None 。 例如,如果您想要關(guān)閉off-site中間件:

SPIDER_MIDDLEWARES = {
'myproject.middlewares.CustomSpiderMiddleware': 543,
'scrapy.contrib.spidermiddleware.offsite.OffsiteMiddleware': None,
}

最后,請注意,有些中間件需要通過特定的設(shè)置來啟用。更多內(nèi)容請查看相關(guān)中間件文檔。

2,編寫自己的spider中間件
編寫spider中間件十分簡單。每個(gè)中間件組件是一個(gè)定義了以下一個(gè)或多個(gè)方法的Python類:
class scrapy.contrib.spidermiddleware.SpiderMiddleware
process_spider_input(response, spider)
當(dāng)response通過spider中間件時(shí),該方法被調(diào)用,處理該response。

process_spider_input() 應(yīng)該返回 None 或者拋出一個(gè)異常(exception)。

如果其返回 None ,Scrapy將會(huì)繼續(xù)處理該response,調(diào)用所有其他的中間件直到spider處理該response。

如果其拋出一個(gè)異常(exception),Scrapy將不會(huì)調(diào)用任何其他中間件的 process_spider_input() 方法,并調(diào)用request的errback。 errback的輸出將會(huì)以另一個(gè)方向被重新輸入到中間件鏈中,使用 process_spider_output() 方法來處理,當(dāng)其拋出異常時(shí)則帶調(diào)用process_spider_exception() 。

參數(shù):
response (Response 對象) – 被處理的response
spider (Spider 對象) – 該response對應(yīng)的spider

process_spider_output(response, result, spider)
當(dāng)Spider處理response返回result時(shí),該方法被調(diào)用。

process_spider_output() 必須返回包含 Request 或 Item 對象的可迭代對象(iterable)。

參數(shù):
response (Response 對象) – 生成該輸出的response
result (包含 Request 或 Item 對象的可迭代對象(iterable)) – spider返回的result
spider (Spider 對象) – 其結(jié)果被處理的spider

process_spider_exception(response, exception, spider)
當(dāng)spider或(其他spider中間件的) process_spider_input() 拋出異常時(shí), 該方法被調(diào)用。

process_spider_exception() 必須要么返回 None , 要么返回一個(gè)包含 Response 或 Item 對象的可迭代對象(iterable)。

如果其返回 None ,Scrapy將繼續(xù)處理該異常,調(diào)用中間件鏈中的其他中間件的 process_spider_exception() 方法,直到所有中間件都被調(diào)用,該異常到達(dá)引擎(異常將被記錄并被忽略)。

如果其返回一個(gè)可迭代對象,則中間件鏈的 process_spider_output() 方法被調(diào)用, 其他的 process_spider_exception() 將不會(huì)被調(diào)用。

參數(shù):
response (Response 對象) – 異常被拋出時(shí)被處理的response
exception (Exception 對象) – 被跑出的異常
spider (Spider 對象) – 拋出該異常的spider

process_start_requests(start_requests, spider)
0.15 新版功能.

該方法以spider 啟動(dòng)的request為參數(shù)被調(diào)用,執(zhí)行的過程類似于 process_spider_output() ,只不過其沒有相關(guān)聯(lián)的response并且必須返回request(不是item)。

其接受一個(gè)可迭代的對象(start_requests 參數(shù))且必須返回另一個(gè)包含 Request 對象的可迭代對象。

注解
當(dāng)在您的spider中間件實(shí)現(xiàn)該方法時(shí), 您必須返回一個(gè)可迭代對象(類似于參數(shù)start_requests)且不要遍歷所有的 start_requests。 該迭代器會(huì)很大(甚至是無限),進(jìn)而導(dǎo)致內(nèi)存溢出。 Scrapy引擎在其具有能力處理start request時(shí)將會(huì)拉起request, 因此start request迭代器會(huì)變得無限,而由其他參數(shù)來停止spider( 例如時(shí)間限制或者item/page記數(shù))。

參數(shù):
start_requests (包含 Request 的可迭代對象) – start requests
spider (Spider 對象) – start requests所屬的spider

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容