如何使用Scrapy 中間鍵,相信很多沒有經(jīng)驗(yàn)的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。
創(chuàng)新互聯(lián)一直通過網(wǎng)站建設(shè)和網(wǎng)站營銷幫助企業(yè)獲得更多客戶資源。 以"深度挖掘,量身打造,注重實(shí)效"的一站式服務(wù),以網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站設(shè)計(jì)、移動(dòng)互聯(lián)產(chǎn)品、成都全網(wǎng)營銷推廣服務(wù)為核心業(yè)務(wù)。10年網(wǎng)站制作的經(jīng)驗(yàn),使用新網(wǎng)站建設(shè)技術(shù),全新開發(fā)出的標(biāo)準(zhǔn)網(wǎng)站,不但價(jià)格便宜而且實(shí)用、靈活,特別適合中小公司網(wǎng)站制作。網(wǎng)站管理系統(tǒng)簡單易用,維護(hù)方便,您可以完全操作網(wǎng)站資料,是中小公司快速網(wǎng)站建設(shè)的選擇。
中間件的運(yùn)用比較廣泛,如果直接從定義的角度去理解中間件會(huì)有點(diǎn)亂,我以分布式系統(tǒng)為例子進(jìn)行說明。在上篇文章,我講到目前后臺(tái)服務(wù)架構(gòu)基本都是往分布式發(fā)展。其實(shí)分布式系統(tǒng)也算是一個(gè)中間件。
那什么是分布式系統(tǒng)?分布式系統(tǒng)是由一組通過網(wǎng)絡(luò)進(jìn)行通信、為了完成共同的任務(wù)而協(xié)調(diào)工作的計(jì)算機(jī)節(jié)點(diǎn)組成的系統(tǒng)。我們從下圖中可得知,分布式系統(tǒng)是介于操作系統(tǒng)和用戶應(yīng)用之間的軟件。
那么不妨我們進(jìn)一步拓展下思維去理解中間件。可知,中間件(middleware)是基礎(chǔ)軟件的一大類,屬于可復(fù)用軟件的范疇。顧名思義,中間件處于操作系統(tǒng)軟件與用戶的應(yīng)用軟件的中間。
我們先通過一張圖了解下 Scrapy 架構(gòu)。
我們可以看到 Scrapy 框架是有兩個(gè)中間件。
一個(gè)是 Downloader 中間件,它是 Engine 和 Downloader 的樞紐。主要負(fù)責(zé)處理 Downloader 傳遞給 Engine 的 responses;
另一個(gè)是 Spider 中間件,它Spider 中間件是 Engine 和 Spider 的連接橋梁;它主要是處理 Spider 的輸入(responses) 以及輸出 item 和 requests 給 Engine;
在 Scrapy 框架中,Downloader 中間件和 Spider 中間件都是支持自定義擴(kuò)展。在實(shí)際應(yīng)用中,我們經(jīng)常需要對 Downloader 中間件進(jìn)行制定化。例如實(shí)現(xiàn)一個(gè) User-Agent 中間件給每個(gè) HTTP 請求的頭部增加隨機(jī)篩選的 User-Agent 屬性;或者實(shí)現(xiàn)一個(gè)代理中間件給每個(gè) HTTP 請求設(shè)置隨機(jī)選擇的代理地址。
接下來,讓我們學(xué)習(xí)如何實(shí)現(xiàn) Scrapy 的 Downloader 中間件。
1) 定義中間件
在 Scrapy 項(xiàng)目中,找到 middlewares.py 文件,在文件中創(chuàng)建自己的中間件類。例如,我創(chuàng)建一個(gè)代理中間件:
class ProxyMiddleware(object):
每個(gè)中間件一共有三個(gè)方法,分別是:
process_request(request,spider)
當(dāng)每個(gè) request 通過下載中間件時(shí),該方法被調(diào)用。該方法必須返回以下三種中的任意一種:None,返回一個(gè) Response 對象,返回一個(gè) Request 對象或 raise IgnoreRequest。每種返回值的作用是不同的。
None: Scrapy 將會(huì)繼續(xù)處理該 request,執(zhí)行其他的中間件的相應(yīng)方法,直到合適的下載器處理函數(shù)( download handler )被調(diào)用,該 request 被執(zhí)行(其 response被下載)。如果有多個(gè)中間件,其他的中間件可以通過返回 Null,然后指定對應(yīng)的中間件去處理 request
Request 對象:Scrapy 則停止調(diào)用 process_request 方法并重新調(diào)度返回的 request。簡單來說是拒絕該 Request 的 HTTP 請求。
Response 對象:直接返回結(jié)果。
raise IgnoreRequest 異常:拋出異常,然后會(huì)被中間件的 process_exception() 方法會(huì)被調(diào)用。
process_response(request, response, spider)
process_response 的返回值也是有三種:Response 對象,Request對象,或者 raise 一個(gè) IgnoreRequest 異常。
如果返回的結(jié)果是 Response, 該 response 會(huì)被在鏈中的其他中間件的 process_response() 方法處理。
如果的結(jié)果是 Request 對象,則中間件鏈停止,request 會(huì)被重新調(diào)度下載。
raise IgnoreRequest 異常: 拋出異常,然后會(huì)被中間件的 process_exception() 方法會(huì)被調(diào)用。。
process_exception(request, exception, spider)
當(dāng)下載處理器(download handler)或 process_request() (下載中間件)拋出異常(包括 IgnoreRequest 異常)時(shí),Scrapy 調(diào)用 process_exception()。
process_exception() 的返回結(jié)果同樣也是有三個(gè): None、Response 對象、Request 對象。
如果其返回 None ,Scrapy 將會(huì)繼續(xù)處理該異常,接著調(diào)用已安裝的其他中間件的 process_exception() 方法,直到所有中間件都被調(diào)用完畢。
如果其返回一個(gè) Response 對象,則其他中間件鏈的 process_response() 方法被調(diào)用,之后 Scrap y將不會(huì)調(diào)用其他中間件的 process_exception() 方法。
如果其返回一個(gè) Request 對象, 則返回的request將會(huì)被重新調(diào)用下載。這將停止中間件的 process_exception() 方法執(zhí)行,就如返回一個(gè) response 的那樣。如果 HTTP 請求失敗,我們可以在這里對 HTTP 請求進(jìn)行重試。例如我們頻繁爬取訪問一個(gè)網(wǎng)站導(dǎo)致被封 IP,就可以在這里設(shè)置增加代理繼續(xù)訪問。
我們可以不用實(shí)現(xiàn)全部方法,只需要根據(jù)需求實(shí)現(xiàn)對應(yīng)的方法即可。例如,我想給每個(gè) HTTP 請求都添加代理地址, 我實(shí)現(xiàn) process_request() 即可。
class ProxyMiddleware(object):
# overwrite process request
def process_request(self, request, spider):
# 從數(shù)據(jù)庫中隨機(jī)讀取一個(gè)代理地址
proxy_address = proxy_pool.random_select_proxy()
logging.debug("===== ProxyMiddleware get a random_proxy:【 {} 】 =====".format(proxy_address))
request.meta['proxy'] = proxy_address
return None
2) 在 setting.py 啟用中間件
我們已經(jīng)實(shí)現(xiàn)了中間件,最后一步需要啟用該中間件。我們將定義的中間件添加到 settings.py 文件。如果你是重載系統(tǒng)中間件,還需要將系統(tǒng)的中間件的值設(shè)置為 None。我前面定義的代理中間件,是需要對 HTTP 請求做操作。所以重載了 HttpProxyMiddleware 中間件。
# 中間件填寫規(guī)則
# yourproject.myMiddlewares(文件名).middleware類
# 設(shè)置代理
'scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware': None,
'scrapydemo.middlewares.ProxyMiddleware': 100
看完上述內(nèi)容,你們掌握如何使用Scrapy 中間鍵的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!