這篇博客咱們聊聊 scrapy 中的 Downloader Middleware ,即下載中間件相關知識,
Downloader Middlerware
首先看一下中間件在 scrapy 資料流中的位置,下圖黑色箭頭即下載中間件,

結合上圖就能看出來, Requests 和 Response 都會通過 Downloader Middlerware,所以在后續代碼撰寫的時候需要注意該點,
中間件的開啟非常簡單,只需要在 settings.py 檔案中去除下述代碼的注釋即可,
DOWNLOADER_MIDDLEWARES = {
'mid_test.middlewares.MidTestDownloaderMiddleware': 543,
}
其實 settings.py 檔案僅僅是一個 scrapy 專案基礎配置,除此之外,在 scrapy 框架中還存在一個 default_settings.py 檔案,里面的 DOWNLOADER_MIDDLEWARES_BASE 包含更多下載中間件,而且它們是 scrapy 專案啟動之后默認加載的,具體如下圖所示,
我們在設定 DOWNLOADER_MIDDLEWARES 的時候,需要注意優先級的問題,其原因是在后續撰寫自定義下載中間件時,存在 1 個 process_request() 方法和 1 個 process_response() 方法,它們會按照優先級對中間件進行排序,并按照順序進行中間的呼叫,
還有一點要注意的是,如果你想要屏蔽掉 DOWNLOADER_MIDDLEWARES_BASE 中設定的中間件,需要在 DOWNLOADER_MIDDLEWARES 中給其賦值為 None 才可以,例如下述代碼將屏蔽 RobotsTxtMiddleware 中間件,
DOWNLOADER_MIDDLEWARES = {
'myproject.middlewares.CustomDownloaderMiddleware': 543,
'scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware': None,
}
自定義下載中間件的相關知識
本次案例撰寫使用的網站是 http://httpbin.org ,該站點可以直接回傳請求頭相關引數,測驗起來非常方便,
正式撰寫代碼前在 settings.py 檔案中增加添加一個新的欄位,便于輸出列印日志(屏蔽了一些除錯日志的輸出),
LOG_LEVEL = 'WARNING'
撰寫自己的下載中間件
默認請求代碼如下所示,回傳資料在代碼下方,
import scrapy
class HbinSpider(scrapy.Spider):
name = 'hbin'
allowed_domains = ['httpbin.org']
start_urls = ['http://httpbin.org/get']
def parse(self, response):
print(response.text)
請求目標站點之后,得到的回傳資料如下所示:

接下來啟用中間件,然后將請求相關引數進行修改,主要操作的檔案是 middlewares.py,并且要實作其中的 process_request(),process_response(),process_exception(),spider_opened() 方法(可以僅實作一部分),
process_request(request, spider)
通過下載中間件的每個請求,都會呼叫該方法,
本方法回傳值必須是 None,Response 物件,Request 物件或者 IgnoreRequest 錯誤,
- 回傳
None:沒啥影響,其它的請求繼續處理完畢; - 回傳
Response:直接去呼叫process_response()方法去; - 回傳
Request:將新的 Request 加入調度佇列; - 回傳
IgnoreRequest:process_exception()方法被執行,
下面撰寫一個 UserAgentMiddlerware 中間件,替換默認中間件的同時實作自己的代理設定,
在 middlewares.py 檔案中添加如下代碼
class UserAgentMiddleware(object):
def process_request(self, request, spider):
request.headers.setdefault('User-Agent',
'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36')
return None
在 settings.py 檔案中添加如下代碼
DOWNLOADER_MIDDLEWARES = {
'mid_test.middlewares.UserAgentMiddleware': 543, # 配置自己的中間件,可以修改名稱為 MyUserAgentMiddleware
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware':None # 覆寫配置
}
如果沒有覆寫原配置,會發現我們撰寫的中間件優先級不如 UserAgentMiddleware 高,即下圖加載順序,

process_response(request, response, spider)
該方法可下載中間件在回傳回應資料時,進行一些資料處理,它默認回傳的是 response 物件,也可以回傳 request 物件,邏輯與 process_request() 方法基本一致,
class MyUserAgentMiddleware(object):
def process_request(self, request, spider):
request.headers.setdefault('User-Agent',
'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36')
return None
def process_response(self, request, response, spider):
print(response) # 單純輸出一下 response
return response
process_exception(request, exception, spider)
用于處理例外,默認回傳 None,也可以回傳 Response 物件和 Request 物件,
一般場景都是回傳 Request 物件,當出現例外時,可以重新發起請求,
內置的下載中間件
通過 scrapy 命令列可以查看所有的內置中間件,
> scrapy settings --get DOWNLOADER_MIDDLEWARES_BASE
按照優先級依次為大家介紹一下,
RobotsTxtMiddleware
查看該中間件原始碼了解到,當 settings.py 檔案中的 ROBOTSTXT_OBEY 被設定為 True 時,尊重 robots.txt 協議,
HttpAuthMiddleware
HTTP 認證,核心邏輯如下所示:
def spider_opened(self, spider):
usr = getattr(spider, 'http_user', '')
pwd = getattr(spider, 'http_pass', '')
if usr or pwd:
self.auth = basic_auth_header(usr, pwd)
def process_request(self, request, spider):
auth = getattr(self, 'auth', None)
if auth and b'Authorization' not in request.headers:
request.headers[b'Authorization'] = auth
DownloadTimeoutMiddleware
設定請求的超時時間,需要配置 settings.py 檔案中的 DOWNLOAD_TIMEOUT 值,然后手動給 meta 中 download_timeout 引數賦值,
def process_request(self, request, spider):
if self._timeout:
request.meta.setdefault('download_timeout', self._timeout)
DefaultHeadersMiddleware
設定 DEFAULT_REQUEST_HEADERS 指定的默認請求頭,
UserAgentMiddleware
請求的用戶代理設定,
RetryMiddleware
請求重試次數,
MetaRefreshMiddleware 與 RedirectMiddleware
以上 2 個中間件都繼承自 BaseRedirectMiddleware,都與重定向有關系,
HttpCompressionMiddleware
提供了對壓縮(gzip, deflate)資料的支持,
CookiesMiddleware
Cookie 相關能力的支持,
HttpProxyMiddleware
代理相關設定,
DownloaderStats
下載中間件的統計資訊,
HttpCacheMiddleware
為所有 HTTP 請求和回應提供低級快取,
本篇博客內容屬于 scrapy 知識鋪墊,并且部分知識點在后續博客中會反復用到,請掌握,
寫在后面
今天是持續寫作的第 253 / 365 天,
期待 關注,點贊、評論、收藏,
更多精彩
《爬蟲 100 例,專欄銷售中,買完就能學會系列專欄》

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/344251.html
標籤:python
