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

下載器中間件(Downloader Middleware)

下載器中間件是介于 Scrapy 的 request/response 處理的鉤子框架。 是用于全局修改 Scrapy request 和 response 的一個輕量、底層的系統(tǒng)。

激活下載器中間件

要激活下載器中間件組件,將其加入到 DOWNLOADER_MIDDLEWARES 設置中。該設置是一個字典(dict),鍵為中間件類的路徑,值為其中間件的順序(order)。

這里是一個例子:

DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.CustomDownloaderMiddleware': 543,
}

DOWNLOADER_MIDDLEWARES 設置會與 Scrapy 定義的 DOWNLOADER_MIDDLEWARES_BASE 設置合并(但不是覆蓋),而后根據順序(order)進行排序,最后得到啟用中間件的有序列表: 第一個中間件是最靠近引擎的,最后一個中間件是最靠近下載器的。

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

如果您想禁止內置的(在 DOWNLOADER_MIDDLEWARES_BASE 中設置并默認啟用的)中間件,您必須在項目的 DOWNLOADER_MIDDLEWARES 設置中定義該中間件,并將其值賦為 None。例如,如果您想要關閉 user-agent 中間件:

DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.CustomDownloaderMiddleware': 543,
    'scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware': None,
}

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

編寫您自己的下載器中間件

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

class scrapy.contrib.downloadermiddleware.DownloaderMiddleware

process_request(request, spider)

當每個 request 通過下載中間件時,該方法被調用。

process_request() 必須返回其中之一: 返回 None 、返回一個 Response 對象、返回一個 Request 對象或 raise IgnoreRequest。

如果其返回 None,Scrapy 將繼續(xù)處理該 request,執(zhí)行其他的中間件的相應方法,直到合適的下載器處理函數(download handler)被調用,該 request 被執(zhí)行(其 response 被下載)。

如果其返回 Response 對象,Scrapy 將不會調用 任何 其他的 process_request()或 process_exception()方法,或相應地下載函數; 其將返回該 response。已安裝的中間件的 process_response()方法則會在每個 response 返回時被調用。

如果其返回 Request 對象,Scrapy 則停止調用 process_request 方法并重新調度返回的 request。當新返回的 request 被執(zhí)行后, 相應地中間件鏈將會根據下載的 response 被調用。

如果其 raise 一個 IgnoreRequest 異常,則安裝的下載中間件的 process_exception() 方法會被調用。如果沒有任何一個方法處理該異常, 則 request 的 errback(Request.errback)方法會被調用。如果沒有代碼處理拋出的異常, 則該異常被忽略且不記錄(不同于其他異常那樣)。

參數:

  • request (Request 對象) – 處理的 request
  • spider (Spider 對象) – 該 request 對應的 spider

process_response(request, response, spider)

process_request() 必須返回以下之一: 返回一個 Response 對象、返回一個 Request 對象或 raise 一個 IgnoreRequest 異常。

如果其返回一個 Response (可以與傳入的 response 相同,也可以是全新的對象) 該 response 會被在鏈中的其他中間件的 process_response()方法處理。

如果其返回一個 Request 對象,則中間件鏈停止,返回的 request 會被重新調度下載。處理類似于 process_request()返回 request 所做的那樣。

如果其拋出一個 IgnoreRequest 異常,則調用 request 的 errback(Request.errback)。如果沒有代碼處理拋出的異常,則該異常被忽略且不記錄(不同于其他異常那樣)。

參數:

  • request (Request 對象) – response 所對應的 request
  • response (Response 對象) – 被處理的 response
  • spider (Spider 對象) – response 所對應的 spider

process_exception(request, exception, spider)

當下載處理器(download handler)或 process_request()(下載中間件)拋出異常(包括 IgnoreRequest 異常)時,Scrapy 調用 process_exception() 。

process_exception()應該返回以下之一: 返回 None、一個 Response 對象、或者一個 Request 對象。

如果其返回 None,Scrapy 將會繼續(xù)處理該異常,接著調用已安裝的其他中間件的 process_exception()方法,直到所有中間件都被調用完畢,則調用默認的異常處理。

如果其返回一個 Response 對象,則已安裝的中間件鏈的 process_response()方法被調用。Scrapy 將不會調用任何其他中間件的 process_exception() 方法。

如果其返回一個 Request 對象, 則返回的 request 將會被重新調用下載。這將停止中間件的 process_exception()方法執(zhí)行,就如返回一個 response 的那樣。

參數:

  • request (是 Request 對象) – 產生異常的 request
  • exception (Exception 對象) – 拋出的異常
  • spider (Spider 對象) – request 對應的 spider

內置下載中間件參考手冊

本頁面介紹了 Scrapy 自帶的所有下載中間件。關于如何使用及編寫您自己的中間件,請參考 downloader middleware usage guide。

關于默認啟用的中間件列表(及其順序)請參考 DOWNLOADER_MIDDLEWARES_BASE 設置。

CookiesMiddleware

class scrapy.contrib.downloadermiddleware.cookies.CookiesMiddleware

該中間件使得爬取需要 cookie(例如使用 session)的網站成為了可能。其追蹤了 web server 發(fā)送的 cookie,并在之后的 request 中發(fā)送回去,就如瀏覽器所做的那樣。

以下設置可以用來配置 cookie 中間件:

  • COOKIES_ENABLED
  • COOKIES_DEBUG

單 spider 多 cookie session

Scrapy 通過使用 cookiejar Request meta key 來支持單 spider 追蹤多 cookie session。 默認情況下其使用一個 cookie jar(session),不過您可以傳遞一個標示符來使用多個。

例如:

for i, url in enumerate(urls):
    yield scrapy.Request("http://www.example.com", meta={'cookiejar': i},
        callback=self.parse_page)

需要注意的是 cookiejar meta key 不是”黏性的(sticky)”。您需要在之后的 request 請求中接著傳遞。例如:

def parse_page(self, response):
    # do some processing
    return scrapy.Request("http://www.example.com/otherpage",
        meta={'cookiejar': response.meta['cookiejar']},
        callback=self.parse_other_page)

COOKIES_ENABLED

默認: True

是否啟用 cookies middleware。如果關閉,cookies 將不會發(fā)送給 web server。

COOKIES_DEBUG

默認: False

如果啟用,Scrapy 將記錄所有在 request(Cookie 請求頭)發(fā)送的 cookies 及 response 接收到的 cookies(Set-Cookie 接收頭)。

下邊是啟用 COOKIES_DEBUG 的記錄的樣例:

2011-04-06 14:35:10-0300 [diningcity] INFO: Spider opened
2011-04-06 14:35:10-0300 [diningcity] DEBUG: Sending cookies to: <GET http://www.diningcity.com/netherlands/index.html>
        Cookie: clientlanguage_nl=en_EN
2011-04-06 14:35:14-0300 [diningcity] DEBUG: Received cookies from: <200 http://www.diningcity.com/netherlands/index.html>
        Set-Cookie: JSESSIONID=B~FA4DC0C496C8762AE4F1A620EAB34F38; Path=/
        Set-Cookie: ip_isocode=US
        Set-Cookie: clientlanguage_nl=en_EN; Expires=Thu, 07-Apr-2011 21:21:34 GMT; Path=/
2011-04-06 14:49:50-0300 [diningcity] DEBUG: Crawled (200) <GET http://www.diningcity.com/netherlands/index.html> (referer: None)
[...]

DefaultHeadersMiddleware

class scrapy.contrib.downloadermiddleware.defaultheaders.DefaultHeadersMiddleware

該中間件設置 DEFAULT_REQUEST_HEADERS 指定的默認 request header。

DownloadTimeoutMiddleware

class scrapy.contrib.downloadermiddleware.downloadtimeout.DownloadTimeoutMiddleware

該中間件設置 DOWNLOAD_TIMEOUT 或 spider 的 download_timeout 屬性指定的 request 下載超時時間。

注解

您也可以使用 download_timeout Request.meta key 來對每個請求設置下載超時時間。這種方式在 DownloadTimeoutMiddleware 被關閉時仍然有效。

HttpAuthMiddleware

class scrapy.contrib.downloadermiddleware.httpauth.HttpAuthMiddleware

該中間件完成某些使用 Basic access authentication (或者叫 HTTP 認證)的 spider 生成的請求的認證過程。

在 spider 中啟用 HTTP 認證,請設置 spider 的 http_userhttp_pass 屬性。

樣例:

from scrapy.contrib.spiders import CrawlSpider

class SomeIntranetSiteSpider(CrawlSpider):

    http_user = 'someuser'
    http_pass = 'somepass'
    name = 'intranet.example.com'

    # .. rest of the spider code omitted ...

HttpCacheMiddleware

class scrapy.contrib.downloadermiddleware.httpcache.HttpCacheMiddleware

該中間件為所有 HTTP request 及 response 提供了底層(low-level)緩存支持。其由 cache 存儲后端及 cache 策略組成。

Scrapy 提供了兩種 HTTP 緩存存儲后端:

  • Filesystem storage backend (默認值)
  • DBM storage backend

您可以使用 HTTPCACHE_STORAGE 設定來修改 HTTP 緩存存儲后端。您也可以實現您自己的存儲后端。

Scrapy 提供了兩種了緩存策略:

  • RFC2616 策略
  • Dummy 策略(默認值)

您可以使用 HTTPCACHE_POLICY 設定來修改 HTTP 緩存存儲后端。您也可以實現您自己的存儲策略。

Dummy 策略(默認值)

該策略不考慮任何 HTTP Cache-Control 指令。每個 request 及其對應的 response 都被緩存。 當相同的 request 發(fā)生時,其不發(fā)送任何數據,直接返回 response。

Dummpy 策略對于測試 spider 十分有用。其能使 spider 運行更快(不需要每次等待下載完成), 同時在沒有網絡連接時也能測試。其目的是為了能夠回放 spider 的運行過程,使之與之前的運行過程一模一樣。

使用這個策略請設置:

  • HTTPCACHE_POLICYscrapy.contrib.httpcache.DummyPolicy

RFC2616 策略

該策略提供了符合 RFC2616 的 HTTP 緩存,例如符合 HTTP Cache-Control,針對生產環(huán)境并且應用在持續(xù)性運行環(huán)境所設置。該策略能避免下載未修改的數據(來節(jié)省帶寬,提高爬取速度)。

實現了:

  • 當 no-store cache-control 指令設置時不存儲 response/request。
  • 當 no-cache cache-control 指定設置時不從 cache 中提取 response,即使 response 為最新。
  • 根據 max-age cache-control 指令中計算保存時間(freshness lifetime)。
  • 根據 Expires 指令來計算保存時間(freshness lifetime)。
  • 根據 response 包頭的 Last-Modified 指令來計算保存時間(freshness lifetime)。(Firefox 使用的啟發(fā)式算法)。
  • 根據 response 包頭的 Age 計算當前年齡(current age)。
  • 根據 Date 計算當前年齡(current age)。
  • 根據 response 包頭的 Last-Modified 驗證老舊的 response。
  • 根據 response 包頭的 ETag 驗證老舊的 response。
  • 為接收到的 response 設置缺失的 Date 字段。

目前仍然缺失:

使用這個策略,設置:

  • HTTPCACHE_POLICYscrapy.contrib.httpcache.RFC2616Policy

Filesystem storage backend (默認值)

文件系統(tǒng)存儲后端可以用于 HTTP 緩存中間件。

使用該存儲端,設置:

  • HTTPCACHE_STORAGEscrapy.contrib.httpcache.FilesystemCacheStorage

每個 request/response 組存儲在不同的目錄中,包含下列文件:

  • request_body - the plain request body
  • request_headers - the request headers (原始 HTTP 格式)
  • response_body - the plain response body
  • response_headers - the request headers (原始 HTTP 格式)
  • meta - 以 Python repr()格式(grep-friendly 格式)存儲的該緩存資源的一些元數據。
  • pickled_meta - 與 meta 相同的元數據,不過使用 pickle 來獲得更高效的反序列化性能。

目錄的名稱與 request 的指紋(參考 scrapy.utils.request.fingerprint)有關,而二級目錄是為了避免在同一文件夾下有太多文件 (這在很多文件系統(tǒng)中是十分低效的)。目錄的例子:

/path/to/cache/dir/example.com/72/72811f648e718090f041317756c03adb0ada46c7

DBM storage backend

同時也有 DBM 存儲后端可以用于 HTTP 緩存中間件。

默認情況下,其采用 anydbm 模塊,不過您也可以通過 HTTPCACHE_DBM_MODULE 設置進行修改。

使用該存儲端,設置:

HTTPCACHE_STORAGE 為 scrapy.contrib.httpcache.DbmCacheStorage

LevelDB storage backend

A LevelDB storage backend is also available for the HTTP cache middleware.

This backend is not recommended for development because only one process can access LevelDB databases at the same time, so you can’t run a crawl and open the scrapy shell in parallel for the same spider.

In order to use this storage backend:

  • set HTTPCACHE_STORAGE to scrapy.contrib.httpcache.LeveldbCacheStorage
  • install LevelDB python bindings like pip install leveldb

HTTPCache 中間件設置

HttpCacheMiddleware 可以通過以下設置進行配置:

HTTPCACHE_ENABLED

新版功能。

默認: False

HTTP 緩存是否開啟。

在 0.11 版更改: 在 0.11 版本前,是使用 HTTPCACHE_DIR 來開啟緩存。

HTTPCACHE_EXPIRATION_SECS

默認: 0

緩存的 request 的超時時間,單位秒。

超過這個時間的緩存 request 將會被重新下載。如果為 0,則緩存的 request 將永遠不會超時。

在 0.11 版更改: 在 0.11 版本前,0 的意義是緩存的 request 永遠超時。

HTTPCACHE_DIR

默認: 'httpcache'

存儲(底層的)HTTP 緩存的目錄。如果為空,則 HTTP 緩存將會被關閉。 如果為相對目錄,則相對于項目數據目錄(project data dir)。更多內容請參考默認的 Scrapy 項目結構

HTTPCACHE_IGNORE_HTTP_CODES

新版功能。

默認: []

不緩存設置中的 HTTP 返回值(code)的 request。

HTTPCACHE_IGNORE_MISSING

默認: False

如果啟用,在緩存中沒找到的 request 將會被忽略,不下載。

HTTPCACHE_IGNORE_SCHEMES

新版功能。

默認: ['file']

不緩存這些 URI 標準(scheme)的 response。

HTTPCACHE_STORAGE

默認: 'scrapy.contrib.httpcache.FilesystemCacheStorage'

實現緩存存儲后端的類。

HTTPCACHE_DBM_MODULE

新版功能。

默認: 'anydbm'

DBM 存儲后端的數據庫模塊。 該設定針對 DBM 后端。

HTTPCACHE_POLICY

新版功能。

默認: 'scrapy.contrib.httpcache.DummyPolicy'

實現緩存策略的類。

HttpCompressionMiddleware

class scrapy.contrib.downloadermiddleware.httpcompression.HttpCompressionMiddleware

該中間件提供了對壓縮(gzip, deflate)數據的支持。

HttpCompressionMiddleware Settings

COMPRESSION_ENABLED

默認:True

Compression Middleware(壓縮中間件)是否開啟。

ChunkedTransferMiddleware

class scrapy.contrib.downloadermiddleware.chunked.ChunkedTransferMiddleware

該中間件添加了對 chunked transfer encoding 的支持。

HttpProxyMiddleware

新版功能。

class scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware

該中間件提供了對 request 設置 HTTP 代理的支持。您可以通過在 Request 對象中設置 proxy 元數據來開啟代理。

類似于 Python 標準庫模塊 urlliburllib2,其使用了下列環(huán)境變量:

  • http_proxy
  • https_proxy
  • no_proxy

RedirectMiddleware

class scrapy.contrib.downloadermiddleware.redirect.RedirectMiddleware

該中間件根據 response 的狀態(tài)處理重定向的 request。

通過該中間件的(被重定向的)request 的 url 可以通過 Request.metaredirect_urls 鍵找到。

RedirectMiddleware 可以通過下列設置進行配置(更多內容請參考設置文檔):

  • REDIRECT_ENABLED
  • REDIRECT_MAX_TIMES

如果 Request.metadont_redirect 設置為 True,則該 request 將會被此中間件忽略。

RedirectMiddleware settings

REDIRECT_ENABLED

新版功能。

默認: True

是否啟用 Redirect 中間件。

REDIRECT_MAX_TIMES

默認:20

單個 request 被重定向的最大次數。

MetaRefreshMiddleware

class scrapy.contrib.downloadermiddleware.redirect.MetaRefreshMiddleware

該中間件根據 meta-refresh html 標簽處理 request 重定向。

MetaRefreshMiddleware 可以通過以下設定進行配置 (更多內容請參考設置文檔)。

  • METAREFRESH_ENABLED
  • METAREFRESH_MAXDELAY

該中間件遵循 RedirectMiddleware 描述的 REDIRECT_MAX_TIMES 設定,dont_redirect及 redirect_urls meta key。

MetaRefreshMiddleware settings

METAREFRESH_ENABLED

新版功能。

默認: True

Meta Refresh 中間件是否啟用。

REDIRECT_MAX_METAREFRESH_DELAY

默認: 100

跟進重定向的最大 meta-refresh 延遲(單位:秒)。

RetryMiddleware

class scrapy.contrib.downloadermiddleware.retry.RetryMiddleware

該中間件將重試可能由于臨時的問題,例如連接超時或者 HTTP 500 錯誤導致失敗的頁面。

爬取進程會收集失敗的頁面并在最后,spider 爬取完所有正常(不失敗)的頁面后重新調度。 一旦沒有更多需要重試的失敗頁面,該中間件將會發(fā)送一個信號(retry_complete), 其他插件可以監(jiān)聽該信號。

RetryMiddleware 可以通過下列設定進行配置 (更多內容請參考設置文檔):

  • RETRY_ENABLED
  • RETRY_TIMES
  • RETRY_HTTP_CODES

關于 HTTP 錯誤的考慮:

如果根據 HTTP 協(xié)議,您可能想要在設定 RETRY_HTTP_CODES 中移除 400 錯誤。該錯誤被默認包括是由于這個代碼經常被用來指示服務器過載(overload)了。而在這種情況下,我們想進行重試。

如果 Request.metadont_retry 設為 True,該 request 將會被本中間件忽略。

RetryMiddleware Settings

RETRY_ENABLED

新版功能。

默認: True

Retry Middleware 是否啟用。

RETRY_TIMES

默認:2

包括第一次下載,最多的重試次數

RETRY_HTTP_CODES

默認: [500, 502, 503, 504, 400, 408]

重試的 response 返回值(code)。其他錯誤(DNS 查找問題、連接失敗及其他)則一定會進行重試。

RobotsTxtMiddleware

class scrapy.contrib.downloadermiddleware.robotstxt.RobotsTxtMiddleware

該中間件過濾所有 robots.txt eclusion standard 中禁止的 request。

確認該中間件及 ROBOTSTXT_OBEY 設置被啟用以確保 Scrapy 尊重 robots.txt。

警告

記住,如果您在一個網站中使用了多個并發(fā)請求,Scrapy 仍然可能下載一些被禁止的頁面。這是由于這些頁面是在 robots.txt 被下載前被請求的。這是當前 robots.txt 中間件已知的限制,并將在未來進行修復。

DownloaderStats

class scrapy.contrib.downloadermiddleware.stats.DownloaderStats

保存所有通過的 request、response 及 exception 的中間件。

您必須啟用 DOWNLOADER_STATS 來啟用該中間件。

UserAgentMiddleware

class scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware

用于覆蓋 spider 的默認 user agent 的中間件。

要使得 spider 能覆蓋默認的 user agent,其 user_agent 屬性必須被設置。

AjaxCrawlMiddleware

class scrapy.contrib.downloadermiddleware.ajaxcrawl.AjaxCrawlMiddleware

根據 meta-fragment html 標簽查找 ‘AJAX 可爬取’ 頁面的中間件。查看 https://developers.google.com/webmasters/ajax-crawling/docs/getting-started 來獲得更多內容。

注解

即使沒有啟用該中間件,Scrapy 仍能查找類似于 'http://example.com/!#foo=bar' 這樣的’AJAX 可爬取’頁面。AjaxCrawlMiddleware 是針對不具有 '!#' 的 URL,通常發(fā)生在’index’或者’main’頁面中。

AjaxCrawlMiddleware 設置

AJAXCRAWL_ENABLED

新版功能。

默認:False

AjaxCrawlMiddleware 是否啟用。您可能需要針對通用爬蟲啟用該中間件。

上一篇:Settings下一篇:選擇器(Selectors)