最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Scrapy?之中間件(Middleware)的具體使用

 更新時間:2022年06月12日 10:41:32   作者:zombres  
本文主要介紹了Scrapy?之中間件(Middleware)的具體使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

Scrapy 結(jié)構(gòu)概述:

一、下載器中間件(Downloader Middleware)

如上圖標(biāo)號4、5處所示,下載器中間件用于處理scrapy的request和response的鉤子框架,如在request中設(shè)置代理ip,header等,檢測response的HTTP響應(yīng)碼等。

scrapy已經(jīng)自帶來一堆下載器中間件。

{
    '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,
}

上面就是默認(rèn)啟用的下載器中間件,其各個中間件的作用參考一下官方文檔:Scrapy download-middleware

自定義下載器中間件

有時我們需要編寫自己的一些下載器中間件,如使用代理池,隨機(jī)更換user-agent等,要使用自定義的下載器中間件,就需要在setting文件中激活我們自己的實(shí)現(xiàn)類,如下:

DOWNLOADERMIDDLEWARES = {
    'myproject.middlewares.Custom_A_DownloaderMiddleware': 543,
    'myproject.middlewares.Custom_B_DownloaderMiddleware': 643,
    'myproject.middlewares.Custom_B_DownloaderMiddleware': None,
}

設(shè)置值是個DICT,key是我們自定義的類路徑,后面數(shù)字是執(zhí)行順序,數(shù)字越小,越靠近引擎,數(shù)字越大越靠近下載器,所以數(shù)字越小的,processrequest()優(yōu)先處理;數(shù)字越大的,process_response()優(yōu)先處理;若需要關(guān)閉某個中間件直接設(shè)為None即可。
(PS. 如果兩個下載器的沒有強(qiáng)制的前后關(guān)系,數(shù)字大小沒什么影響)

實(shí)現(xiàn)下載器我們需要重寫以下幾個方法:

  • 對于請求的中間件實(shí)現(xiàn) process_request(request, spider);
  • 對于處理回復(fù)中間件實(shí)現(xiàn)process_response(request, response, spider);
  • 以及異常處理實(shí)現(xiàn) process_exception(request, exception, spider)

process_request(request, spider)

process_request:可以選擇返回None、Response、Request、raise IgnoreRequest其中之一。

  • 如果返回None,scrapy將繼續(xù)處理該request,執(zhí)行其他的中間件的響應(yīng)方法。直到合適的下載器處理函數(shù)(downloader handler)被調(diào)用,該request被執(zhí)行,其response被下載。
  • 如果其返回Response對象,Scrapy將不會調(diào)用任何其他的process_request()或process_exception()方法,或相應(yīng)地下載函數(shù); 其將返回該response。已安裝的中間件的process_response()方法則會在每個response返回時被調(diào)用
  • 如果其返回Request對象,Scrapy則停止調(diào)用process_request方法并重新調(diào)度返回的request。當(dāng)新返回的request被執(zhí)行后,相應(yīng)地中間件鏈將會根據(jù)下載的response被調(diào)用。
  • 如果其raise IgnoreRequest,則安裝的下載中間件的process_exception()方法會被調(diào)用。如果沒有任何一個方法處理該異常, 則request的errback(Request.errback)方法會被調(diào)用。如果沒有代碼處理拋出的異常, 則該異常被忽略且不記錄(不同于其他異常那樣)。

通常返回None較常見,它會繼續(xù)執(zhí)行爬蟲下去

process_response(request, response, spider)

當(dāng)下載器完成HTTP請求,傳遞響應(yīng)給引擎的時候調(diào)用,它會返回 Response 、Request 、IgnoreRequest三種對象的一種

  • 若返回Response對象,它會被下個中間件中的process_response()處理
  • 若返回Request對象,中間鏈停止,然后返回的Request會被重新調(diào)度下載
  • 拋出IgnoreRequest,回調(diào)函數(shù) Request.errback將會被調(diào)用處理,若沒處理,將會忽略

process_exception(request, exception, spider)

當(dāng)下載處理器(download handler)或process_request()拋出異常(包括 IgnoreRequest 異常)時, Scrapy調(diào)用 process_exception() ,通常返回None,它會一直處理異常

from_crawler(cls, crawler)

這個類方法通常是訪問settings和signals的入口函數(shù)

例如下面2個例子是更換user-agent和代理ip的下載中間件

# setting中設(shè)置
USER_AGENT_LIST = [ \
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1", \
    "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11", \
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", \
    "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6", \
    "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1", \
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5", \
    "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5", \
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \
    "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \
    "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", \
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", \
    "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \
    "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \
    "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3", \
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24", \
    "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24", \
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36", \
    "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0"
]

PROXIES = [
    '1.85.220.195:8118',
    '60.255.186.169:8888',
    '118.187.58.34:53281',
    '116.224.191.141:8118',
    '120.27.5.62:9090',
    '119.132.250.156:53281',
    '139.129.166.68:3128'
]

代理ip中間件

import random

class Proxy_Middleware():

    def __init__(self, crawler):
        self.proxy_list = crawler.settings.PROXY_LIST
        self.ua_list = crawler.settings.USER_AGENT_LIST

	@classmethod
	def from_crawler(cls, crawler):
	    return cls(crawler)

    def process_request(self, request, spider):
        try:
			ua = random.choice(self.ua_list)
        	request.headers.setdefault('User-Agent', ua)
        	
            proxy_ip_port = random.choice(self.proxy_list)
            request.meta['proxy'] = 'http://' + proxy_ip_port
        except request.exceptions.RequestException:
            spider.logger.error('some error happended!')

重試中間件

有時使用代理會被遠(yuǎn)程拒絕或超時等錯誤,這時我們需要換代理ip重試,重寫scrapy.downloadermiddlewares.retry.RetryMiddleware

from scrapy.downloadermiddlewares.retry import RetryMiddleware
from scrapy.utils.response import response_status_message

class My_RetryMiddleware(RetryMiddleware):
	def __init__(self, crawler):
        self.proxy_list = crawler.settings.PROXY_LIST
        self.ua_list = crawler.settings.USER_AGENT_LIST

	@classmethod
	def from_crawler(cls, crawler):
	    return cls(crawler)

    def process_response(self, request, response, spider):
        if request.meta.get('dont_retry', False):
            return response

        if response.status in self.retry_http_codes:
            reason = response_status_message(response.status)
            try:
                ua = random.choice(self.ua_list)
	        	request.headers.setdefault('User-Agent', ua)
	        	
	            proxy_ip_port = random.choice(self.proxy_list)
	            request.meta['proxy'] = 'http://' + proxy_ip_port
            except request.exceptions.RequestException:
                spider.logger.error('獲取訊代理ip失??!')

            return self._retry(request, reason, spider) or response
        return response
# scrapy中對接selenium

from scrapy.http import HtmlResponse
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from gp.configs import *


class ChromeDownloaderMiddleware(object):

    def __init__(self):
        options = webdriver.ChromeOptions()
        options.add_argument('--headless')  # 設(shè)置無界面
        if CHROME_PATH:
            options.binary_location = CHROME_PATH
        if CHROME_DRIVER_PATH:  # 初始化Chrome驅(qū)動
            self.driver = webdriver.Chrome(chrome_options=options, executable_path=CHROME_DRIVER_PATH)  
        else:
            self.driver = webdriver.Chrome(chrome_options=options)  # 初始化Chrome驅(qū)動

    def __del__(self):
        self.driver.close()

    def process_request(self, request, spider):
        try:
            print('Chrome driver begin...')
            self.driver.get(request.url)  # 獲取網(wǎng)頁鏈接內(nèi)容
            return HtmlResponse(url=request.url, body=self.driver.page_source, request=request, encoding='utf-8',
                                status=200)  # 返回HTML數(shù)據(jù)
        except TimeoutException:
            return HtmlResponse(url=request.url, request=request, encoding='utf-8', status=500)
        finally:
            print('Chrome driver end...')

二、Spider中間件(Spider Middleware)

如文章第一張圖所示,spider中間件用于處理response及spider生成的item和Request

啟動自定義spider中間件必須先開啟settings中的設(shè)置

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

同理,數(shù)字越小越靠近引擎,process_spider_input()優(yōu)先處理,數(shù)字越大越靠近spider,process_spider_output()優(yōu)先處理,關(guān)閉用None

編寫自定義spider中間件

process_spider_input(response, spider)

當(dāng)response通過spider中間件時,這個方法被調(diào)用,返回None

process_spider_output(response, result, spider)

當(dāng)spider處理response后返回result時,這個方法被調(diào)用,必須返回Request或Item對象的可迭代對象,一般返回result

process_spider_exception(response, exception, spider)

當(dāng)spider中間件拋出異常時,這個方法被調(diào)用,返回None或可迭代對象的Request、dict、Item

補(bǔ)充一張圖:

參考文檔:

https://docs.scrapy.org/en/latest/topics/spider-middleware.html

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

到此這篇關(guān)于Scrapy 之中間件(Middleware)的文章就介紹到這了,更多相關(guān)Scrapy 之中間件(Middleware)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python3利用pathlib替代os.path的方法實(shí)例

    python3利用pathlib替代os.path的方法實(shí)例

    os.path 模塊始終是適合Python運(yùn)行的操作系統(tǒng)的路徑模塊,因此可用于本地路徑,下面這篇文章主要給大家介紹了關(guān)于python3利用pathlib替代os.path的相關(guān)資料,需要的朋友可以參考下
    2022-04-04
  • Python實(shí)現(xiàn)計算函數(shù)或程序執(zhí)行時間

    Python實(shí)現(xiàn)計算函數(shù)或程序執(zhí)行時間

    在Python程序的開發(fā)過程中,一些程序需要獲取函數(shù)或程序的開始時間、結(jié)束時間和時間間隔等內(nèi)容用來分析和處理內(nèi)容。本文就來聊聊具體實(shí)現(xiàn)方法
    2023-02-02
  • Python filter過濾器原理及實(shí)例應(yīng)用

    Python filter過濾器原理及實(shí)例應(yīng)用

    這篇文章主要介紹了Python filter過濾器原理及實(shí)例應(yīng)用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-08-08
  • 使用python提取html文件中的特定數(shù)據(jù)的實(shí)現(xiàn)代碼

    使用python提取html文件中的特定數(shù)據(jù)的實(shí)現(xiàn)代碼

    python提供了SGMLParser類用于html文件的解析。用戶只需從SGMLParser類繼承子類,并在子類中對html文件做具體處理
    2013-03-03
  • Python實(shí)現(xiàn)將照片變成卡通圖片的方法【基于opencv】

    Python實(shí)現(xiàn)將照片變成卡通圖片的方法【基于opencv】

    這篇文章主要介紹了Python實(shí)現(xiàn)將照片變成卡通圖片的方法,涉及Python基于opencv庫進(jìn)行圖片處理的相關(guān)操作技巧,需要的朋友可以參考下
    2018-01-01
  • python實(shí)現(xiàn)書法碑帖圖片分割

    python實(shí)現(xiàn)書法碑帖圖片分割

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)書法碑帖圖片分割,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • Pycharm Available Package無法顯示/安裝包的問題Error Loading Package List解決

    Pycharm Available Package無法顯示/安裝包的問題Error Loading Package Li

    這篇文章主要介紹了Pycharm Available Package無法顯示/安裝包的問題Error Loading Package List解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Scrapy抓取京東商品、豆瓣電影及代碼分享

    Scrapy抓取京東商品、豆瓣電影及代碼分享

    Scrapy,Python開發(fā)的一個快速、高層次的屏幕抓取和web抓取框架,用于抓取web站點(diǎn)并從頁面中提取結(jié)構(gòu)化的數(shù)據(jù)。Scrapy用途廣泛,可以用于數(shù)據(jù)挖掘、監(jiān)測和自動化測試。
    2017-11-11
  • Python中你應(yīng)該知道的一些內(nèi)置函數(shù)

    Python中你應(yīng)該知道的一些內(nèi)置函數(shù)

    python提供了內(nèi)聯(lián)模塊buidin,該模塊定義了一些軟件開發(fā)中常用的函數(shù),這些函數(shù)實(shí)現(xiàn)了數(shù)據(jù)類型的轉(zhuǎn)換,數(shù)據(jù)的計算,序列的處理等功能。下面這篇文章主要給大家介紹了Python中一些大家應(yīng)該知道的內(nèi)置函數(shù),文中總結(jié)的非常詳細(xì),需要的朋友們下面來一起看看吧。
    2017-03-03
  • python 實(shí)現(xiàn)彈球游戲的示例代碼

    python 實(shí)現(xiàn)彈球游戲的示例代碼

    這篇文章主要介紹了python 實(shí)現(xiàn)彈球小游戲,幫助大家更好的理解和學(xué)習(xí)python,感興趣的朋友可以了解下
    2020-11-11

最新評論

包头市| 邵阳市| 青岛市| 临海市| 忻州市| 连南| 克什克腾旗| 三原县| 通州区| 河北区| 阿拉善右旗| 长海县| 阳城县| 景宁| 玛曲县| 湘潭县| 方正县| 晴隆县| 安远县| 阿尔山市| 富宁县| 沙洋县| 沽源县| 信阳市| 中江县| 景泰县| 武宁县| 彰化市| 北宁市| 吕梁市| 新巴尔虎右旗| 游戏| 樟树市| 汉源县| 眉山市| 雷波县| 加查县| 奉节县| 兴业县| 鹤庆县| 当阳市|