鍍金池/ 教程/ Python/ Spider 中間件(Middleware)
Benchmarking
命令行工具(Command line tools)
下載器中間件(Downloader Middleware)
信號(Signals)
Telnet 終端(Telnet Console)
初窺 Scrapy
數(shù)據(jù)收集(Stats Collection)
Scrapyd
通用爬蟲(Broad Crawls)
Item Loaders
試驗階段特性
Scrapy 入門教程
自動限速(AutoThrottle)擴(kuò)展
Settings
Scrapy 終端(Scrapy shell)
下載項目圖片
DjangoItem
調(diào)試(Debugging)Spiders
選擇器(Selectors)
Feed exports
Spiders Contracts
借助 Firefox 來爬取
Logging
Spiders
Ubuntu 軟件包
實踐經(jīng)驗(Common Practices)
安裝指南
Item Exporters
擴(kuò)展(Extensions)
Items
Spider 中間件(Middleware)
異常(Exceptions)
例子
發(fā)送 email
架構(gòu)概覽
常見問題(FAQ)
Jobs:暫停,恢復(fù)爬蟲
核心 API
使用 Firebug 進(jìn)行爬取
Item Pipeline
Link Extractors
Web Service
調(diào)試內(nèi)存溢出

Spider 中間件(Middleware)

Spider 中間件(Middleware) 下載器中間件是介入到 Scrapy 的 spider 處理機制的鉤子框架,您可以添加代碼來處理發(fā)送給 Spiders 的 response 及 spider 產(chǎn)生的 item 和 request。

激活 spider 中間件

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

樣例:

SPIDER_MIDDLEWARES = {
    'myproject.middlewares.CustomSpiderMiddleware': 543,
}

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

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

如果您想禁止內(nèi)置的(在 SPIDER_MIDDLEWARES_BASE 中設(shè)置并默認(rèn)啟用的)中間件,您必須在項目的 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)中間件文檔。

編寫您自己的 spider 中間件

編寫 spider 中間件十分簡單。每個中間件組件是一個定義了以下一個或多個方法的 Python 類:

class scrapy.contrib.spidermiddleware.SpiderMiddleware

process_spider_input(response, spider)

當(dāng) response 通過 spider 中間件時,該方法被調(diào)用,處理該 response。

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

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

如果其跑出一個異常(exception),Scrapy 將不會調(diào)用任何其他中間件的 process_spider_input()方法,并調(diào)用 request 的 errback。 errback 的輸出將會以另一個方向被重新輸入到中間件鏈中,使用 process_spider_output()方法來處理,當(dāng)其拋出異常時則帶調(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 時,該方法被調(diào)用。

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

參數(shù):

  • response (Response 對象) – 生成該輸出的 response
  • result (包含 RequestItem 對象的可迭代對象(iterable)) – spider 返回的 result
  • spider (Spider 對象) – 其結(jié)果被處理的 spider
process_spider_exception(response, exception, spider)

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

process_spider_exception()必須要么返回 None, 要么返回一個包含 ResponseItem 對象的可迭代對象(iterable)。

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

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

參數(shù):

  • response (Response 對象) – 異常被拋出時被處理的 response
  • exception (Exception 對象) – 被跑出的異常
  • spider (Spider 對象) – 拋出該異常的 spider
process_start_requests(start_requests, spider)

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

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

注解

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

參數(shù):

  • start_requests (包含 Request 的可迭代對象) – start requests
  • spider (Spider 對象) – start requests 所屬的 spider

內(nèi)置 spider 中間件參考手冊

本頁面介紹了 Scrapy 自帶的所有 spider 中間件。關(guān)于如何使用及編寫您自己的中間件,請參考 spider middleware usage guide

關(guān)于默認(rèn)啟用的中間件列表(及其順序)請參考 SPIDER_MIDDLEWARES_BASE 設(shè)置。

DepthMiddleware

class scrapy.contrib.spidermiddleware.depth.DepthMiddleware

DepthMiddleware 是一個用于追蹤每個 Request 在被爬取的網(wǎng)站的深度的中間件。 其可以用來限制爬取深度的最大深度或類似的事情。

DepthMiddleware 可以通過下列設(shè)置進(jìn)行配置(更多內(nèi)容請參考設(shè)置文檔):

  • DEPTH_LIMIT - 爬取所允許的最大深度,如果為 0,則沒有限制。
  • DEPTH_STATS - 是否收集爬取狀態(tài)。
  • DEPTH_PRIORITY - 是否根據(jù)其深度對 requet 安排優(yōu)先級

HttpErrorMiddleware

class scrapy.contrib.spidermiddleware.httperror.HttpErrorMiddleware

過濾出所有失敗(錯誤)的 HTTP response,因此 spider 不需要處理這些 request。 處理這些 request 意味著消耗更多資源,并且使得 spider 邏輯更為復(fù)雜。

根據(jù) HTTP 標(biāo)準(zhǔn),返回值為 200-300 之間的值為成功的 resonse。

如果您想處理在這個范圍之外的 response,您可以通過 spider 的 handle_httpstatus_list 屬性或 HTTPERROR_ALLOWED_CODES 設(shè)置來指定 spider 能處理的 response 返回值。

例如,如果您想要處理返回值為 404 的 response 您可以這么做:

class MySpider(CrawlSpider):
    handle_httpstatus_list = [404]

Request.meta 中的 handle_httpstatus_list 鍵也可以用來指定每個 request 所允許的 response code。

不過請記住,除非您知道您在做什么,否則處理非 200 返回一般來說是個糟糕的決定。

更多內(nèi)容請參考:HTTP Status Code 定義

HttpErrorMiddleware settings

HTTPERROR_ALLOWED_CODES

默認(rèn):[]

忽略該列表中所有非 200 狀態(tài)碼的 response。

HTTPERROR_ALLOW_ALL

默認(rèn):False

忽略所有 response,不管其狀態(tài)值。

OffsiteMiddleware

class scrapy.contrib.spidermiddleware.offsite.OffsiteMiddleware

過濾出所有 URL 不由該 spider 負(fù)責(zé)的 Request。

該中間件過濾出所有主機名不在 spider 屬性 allowed_domains 的 request。

當(dāng) spide 返回一個主機名不屬于該 spider 的 request 時, 該中間件將會做一個類似于下面的記錄:

DEBUG: Filtered offsite request to 'www.othersite.com': <GET http://www.othersite.com/some/page.html>

為了避免記錄太多無用信息,其將對每個新發(fā)現(xiàn)的網(wǎng)站記錄一次。因此,例如,如果過濾出另一個 www.othersite.com 請求,將不會有新的記錄 但如果過濾出 someothersite.com 請求,仍然會有記錄信息(僅針對第一次)。

如果 spider 沒有定義 allowed_domains 屬性,或該屬性為空,則 offsite 中間件將會允許所有 request。

如果 request 設(shè)置了 dont_filter 屬性,即使該 request 的網(wǎng)站不在允許列表里,則 offsite 中間件將會允許該 request。

RefererMiddleware

class scrapy.contrib.spidermiddleware.referer.RefererMiddleware

根據(jù)生成 Request 的 Response 的 URL 來設(shè)置 Request Referer 字段。

RefererMiddleware settings

REFERER_ENABLED

默認(rèn):True

是否啟用 referer 中間件。

UrlLengthMiddleware

class scrapy.contrib.spidermiddleware.urllength.UrlLengthMiddleware

過濾出 URL 長度比 URLLENGTH_LIMIT 的 request。

UrlLengthMiddleware 可以通過下列設(shè)置進(jìn)行配置(更多內(nèi)容請參考設(shè)置文檔):

  • URLLENGTH_LIMIT - 允許爬取 URL 最長的長度。