1. 程式人生 > >小白學 Python 爬蟲(36):爬蟲框架 Scrapy 入門基礎(四) Downloader Middleware

小白學 Python 爬蟲(36):爬蟲框架 Scrapy 入門基礎(四) Downloader Middleware

人生苦短,我用 Python

前文傳送門:

小白學 Python 爬蟲(1):開篇

小白學 Python 爬蟲(2):前置準備(一)基本類庫的安裝

小白學 Python 爬蟲(3):前置準備(二)Linux基礎入門

小白學 Python 爬蟲(4):前置準備(三)Docker基礎入門

小白學 Python 爬蟲(5):前置準備(四)資料庫基礎

小白學 Python 爬蟲(6):前置準備(五)爬蟲框架的安裝

小白學 Python 爬蟲(7):HTTP 基礎

小白學 Python 爬蟲(8):網頁基礎

小白學 Python 爬蟲(9):爬蟲基礎

小白學 Python 爬蟲(10):Session 和 Cookies

小白學 Python 爬蟲(11):urllib 基礎使用(一)

小白學 Python 爬蟲(12):urllib 基礎使用(二)

小白學 Python 爬蟲(13):urllib 基礎使用(三)

小白學 Python 爬蟲(14):urllib 基礎使用(四)

小白學 Python 爬蟲(15):urllib 基礎使用(五)

小白學 Python 爬蟲(16):urllib 實戰之爬取妹子圖

小白學 Python 爬蟲(17):Requests 基礎使用

小白學 Python 爬蟲(18):Requests 進階操作

小白學 Python 爬蟲(19):Xpath 基操

小白學 Python 爬蟲(20):Xpath 進階

小白學 Python 爬蟲(21):解析庫 Beautiful Soup(上)

小白學 Python 爬蟲(22):解析庫 Beautiful Soup(下)

小白學 Python 爬蟲(23):解析庫 pyquery 入門

小白學 Python 爬蟲(24):2019 豆瓣電影排行

小白學 Python 爬蟲(25):爬取股票資訊

小白學 Python 爬蟲(26):為啥買不起上海二手房你都買不起

小白學 Python 爬蟲(27):自動化測試框架 Selenium 從入門到放棄(上)

小白學 Python 爬蟲(28):自動化測試框架 Selenium 從入門到放棄(下)

小白學 Python 爬蟲(29):Selenium 獲取某大型電商網站商品資訊

小白學 Python 爬蟲(30):代理基礎

小白學 Python 爬蟲(31):自己構建一個簡單的代理池

小白學 Python 爬蟲(32):非同步請求庫 AIOHTTP 基礎入門

小白學 Python 爬蟲(33):爬蟲框架 Scrapy 入門基礎(一)

小白學 Python 爬蟲(34):爬蟲框架 Scrapy 入門基礎(二)

小白學 Python 爬蟲(35):爬蟲框架 Scrapy 入門基礎(三) Selector 選擇器

引言

Downloader Middleware 直譯過來是下載器中介軟體,本文後續就叫它下載中介軟體了。

下載器中介軟體主要用於 Scrapy 的 Request 和 Response 處理。

Downloader Middleware 的功能非常的強大,可以修改 UA 頭、處理重定向、設定代理、設定超時時間、失敗重試、設定 Cookies 等功能。

內建下載器中介軟體

Scrapy 已經為我們提供相當多的內建的下載器中介軟體,用於各種功能,列表如下:

{
    'scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware': 100,
    'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware': 300,
    'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware': 350,
    'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware': 400,
    'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': 500,
    'scrapy.downloadermiddlewares.retry.RetryMiddleware': 550,
    'scrapy.downloadermiddlewares.ajaxcrawl.AjaxCrawlMiddleware': 560,
    'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware': 580,
    'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 590,
    'scrapy.downloadermiddlewares.redirect.RedirectMiddleware': 600,
    'scrapy.downloadermiddlewares.cookies.CookiesMiddleware': 700,
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 750,
    'scrapy.downloadermiddlewares.stats.DownloaderStats': 850,
    'scrapy.downloadermiddlewares.httpcache.HttpCacheMiddleware': 900,
}

這些列表定義在 DOWNLOADER_MIDDLEWARES_BASE 變數中。

這些列表的資料結構是一個字典格式,後面的值代表了優先順序,數字越小代表了越靠近 Scrapy 引擎,數字越大越靠近下載器,數字小的會被優先呼叫。

自定義下載器中介軟體

如果要在專案自定義一個下載器中介軟體,需要我們自己設定 DOWNLOADER_MIDDLEWARES 這個變數,這個變數位於 settings.py ,預設是註釋狀態,當我們需要的時候直接開啟這個註釋就可以了,這裡不僅可以自定義我們所需要的下載器中介軟體,還可以禁用 DOWNLOADER_MIDDLEWARES_BASE 中定義的下載器中介軟體。

每個下載器中介軟體都是一個Python類,該類定義了以下定義的一個或多個方法。

核心方法共有 4 個,如下:

  • process_request(request, spider)
  • process_response(request, response, spider)
  • process_exception(request, exception, spider)
  • from_crawler(cls, crawler)

而我們至少只需要實現其中的一個方法就可以定義一個下載器中介軟體。

process_request(request, spider)

引數:

  • request(Request物件)–正在處理的請求
  • spider(Spider物件)–此請求所針對的蜘蛛

對於通過下載中介軟體的每個請求,都會呼叫此方法。

process_request() 應該是:return None,返回一個 Response 物件,返回一個Request 物件或引發 IgnoreRequest 異常。

如果返回 None ,則 Scrapy 將繼續處理此請求,執行所有其他中介軟體,直到最終將適當的下載程式處理程式稱為執行的請求(並下載了其響應)。

如果它返回一個 Response 物件, Scrapy 不會打擾呼叫任何其他 process_request() 或 process_exception() 方法,或相應的下載功能; 它將返回該響應。 process_response() 總是在每個響應上呼叫已安裝中介軟體的方法。

如果返回一個 Request 物件, Scrapy 將停止呼叫 process_request 方法並重新計劃返回的請求。一旦執行了新返回的請求,就會在下載的響應上呼叫適當的中介軟體鏈。

如果引發 IgnoreRequest 異常,則所有的下載器中介軟體的方法 process_exception() 會依次執行,如果沒有一個方法處理該異常,那麼 Request 的 errback() 方法就會回撥,如果該異常還沒處理,那麼就會忽略。

process_response(request, response, spider)

引數:

  • request (是一個 Request 物件)–發起響應的請求
  • response (response 物件)–正在處理的響應
  • spider (spider 物件)–此響應預期用於的蜘蛛

process_response() 應該:返回響應物件,返回請求物件或引發 IgnoreRequest 異常。

如果它返回一個 Response (它可以是相同的給定響應,也可以是全新的響應),那麼該響應將繼續使用鏈中下一個中介軟體的 process_response() 進行處理。

如果它返回一個 Request 物件,則中介軟體鏈將暫停,並將返回的請求重新安排為將來下載。 這與從 process_request() 返回請求的行為相同。

如果引發 IgnoreRequest 異常,則呼叫請求的 errback 函式(Request.errback)。 如果沒有程式碼處理引發的異常,則將其忽略並且不記錄(與其他異常不同)。

process_exception(request, exception, spider)

引數:

  • request (是一個Request物件)–生成異常的請求
  • exception (Exception物件)–引發的異常
  • spider (spider物件)–此請求所針對的蜘蛛

當下載處理程式或 process_request() (從下載程式中介軟體中)引發異常(包括 IgnoreRequest 異常)時, Scrapy 會呼叫 process_exception() 。

process_exception() 應該返回:無,響應物件或請求物件。

如果返回 None ,則 Scrapy 將繼續處理此異常,執行已安裝中介軟體的任何其他 process_exception() 方法,直到沒有中介軟體為止,並且預設異常處理開始。

如果返回 Response 物件,則會啟動已安裝中介軟體的 process_response() 方法鏈,並且 Scrapy 不會費心呼叫中介軟體的任何其他 process_exception() 方法。

如果它返回一個 Request 物件,則將返回的請求重新安排為將來下載。 這將停止執行中介軟體的 process_exception() 方法,就像返回響應一樣。

from_crawler(cls, crawler)

引數:

  • crawler(搜尋器物件)–使用此中介軟體的搜尋器

如果存在,則呼叫該類方法以從 Crawler 建立中介軟體例項。 它必須返回中介軟體的新例項。 搜尋器物件提供對所有 Scrapy 核心元件(如設定和訊號)的訪問; 它是中介軟體訪問它們並將其功能連線到 Scrapy 中的一種方式。

示例

首先,我們還是在前面的 Scrapy 的專案上新建一個 Spider ,具體程式碼如下:

# -*- coding: utf-8 -*-
import scrapy

class HttpbinSpider(scrapy.Spider):
    name = 'httpbin'
    allowed_domains = ['httpbin.org']
    start_urls = ['https://httpbin.org/get']

    def parse(self, response):
        self.logger.debug(response.text)

使用如下命令執行一下:

scrapy crawl httpbin

結果部分擷取如下:

{
  "args": {},
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Encoding": "gzip,deflate,br",
    "Accept-Language": "en",
    "Host": "httpbin.org",
    "User-Agent": "Scrapy/1.8.0 (+https://scrapy.org)"
  },
  "origin": "183.195.68.215, 183.195.68.215",
  "url": "https://httpbin.org/get"
}

可以看到,這裡的 UA 頭是 Scrapy/1.8.0 (+https://scrapy.org) ,這個其實是由 Scrapy 內建的 UserAgentMiddleware 設定的。

這裡我們通過修改一下 UA 頭,當然修改 UA 頭可以通過 settings 中的 USER_AGENT 進行設定,這裡我們要演示下載器中介軟體嘛,所以就使用下載器中介軟體設定一下。

首先我們在 middlewares.py 中新增一個 UaDownLoaderMiddleware ,示例程式碼如下:

class UaDownLoaderMiddleware(object):
    
    def process_request(self, request, spider):

        request.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'

新增完成後,還需要在配置檔案 settings 中開啟這個下載器中介軟體,找到 DOWNLOADER_MIDDLEWARES ,將註釋去掉,修改為:

DOWNLOADER_MIDDLEWARES = {
   'first_scrapy.middlewares.UaDownLoaderMiddleware': 543,
}

到這裡,我們的修改就完成了,可以重新執行這隻爬蟲:

scrapy crawl httpbin

結果部分擷取如下:

{
  "args": {},
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Encoding": "gzip,deflate,br",
    "Accept-Language": "en",
    "Host": "httpbin.org",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"
  },
  "origin": "183.195.68.215, 183.195.68.215",
  "url": "https://httpbin.org/get"
}

可以看到,這裡響應的 UA 已經變成了我們剛才設定的 UA 頭,證明我們的修改是成功的。

本篇就先到這裡了,希望各位同學可以自己動手試一下。

示例程式碼

本系列的所有程式碼小編都會放在程式碼管理倉庫 Github 和 Gitee 上,方便大家取用。

示例程式碼-Github

示例程式碼-Gitee

參考

https://docs.scrapy.org/en/latest/topics/settings.html#std:setting-DOWNLOADER_MIDDLEWARES_BASE

https://docs.scrapy.org/en/latest/topics/downloader-middleware.h