1. 程式人生 > >爬蟲2.5-scrapy框架-下載中間件

爬蟲2.5-scrapy框架-下載中間件

choice 不同 驗證碼 ini python 自己 必須 spi RoCE

目錄

  • scrapy框架-下載中間件

scrapy框架-下載中間件

middlewares.py中有兩個類,一個是xxSpiderMiddleware類 一個是xxDownloaderMiddleware類,xx代表項目名,本次筆記主要記錄DownloaderMiddleware類的一些知識點

1. process_request(self, request, spider):

這個方法會在請求之前執行,所以可以添加代理pi和隨機請求頭等

1.1 參數:

? reuqest:發送的請求

? spider:發送請求的spider對象,即request是哪個爬蟲對象發過來的。

1.2 返回值:

1)如果返回的是None:scrapy將把request對象交給下一個中間件

2)如果返回的是response對象,則不會調用任何的process_request方法,而是將response對象直接返回給已激活的process_response()方法

3)返回request對象,不會調用下一個中間件,而是根據返回的request對象返回數據

4)拋出異常,調用process_exception方法。

2. process_response(self, request, response, spider):

2.1 參數:

1)request:之前發送的request請求對象

2)response:返回的數據對象

3)spider:爬蟲對象

2.2 返回值:

1)返回response對象,會將這個新的response對象傳給其他中間件,最終傳給爬蟲

2)返回request對象,下載器鏈被切斷,返回的request會重新被下載器調度

3)拋出異常,調用request中的errback方法,沒有就拋出異常

3. 設置請求頭

專業請求頭網站 http://www.useragentstring.com/pages/useragentstring.php?type=Browser

定義xxDownloaderMiddleware類,在寫process_request()方法

class xxDownloaderMiddleware(object):
    USER_AGENTS = [
        ‘xxxx‘,
        ‘xxxxx‘,
        ‘xxxx‘,
        ‘xxxxxx‘ # 請求頭
        ]

def process_request(self, request, spider):
    user_agent = random.choice(self.USER_AGENTS)
    request.headers[‘user-agent‘] = user_agent

然後在settings.py中打開中間件設置

DOWNLOADER_MIDDLEWARES = {
    ‘projectname.middlewares.xxDownloaderMiddleware‘: 543
}

4. ip代理池

代理服務商:

快遞代理、芝麻代理、太陽代理、訊代理、螞蟻代理

當然是花錢買,免費的不好用

新建一個類

class XXXDownloaderMiddleware(object):
    PROXIES = [‘IP1‘,‘IP2‘,‘IP3‘]
    def process_request(self, request, spider):
        proxy = random.choice(self.PROXIES)
        request.meta(‘proxy‘) = proxy

修改settings.py

DOWNLOADER_MIDDLEWARES = {
    ‘project.middlewares.XXXDownloaderMiddleware‘:542 # 多個中間件的優先級自己設定,1為最高級
}

5. 一個略完善的代理思路

開啟兩個下載中間件,一個請求頭代理,一個ip代理,添加到settings中間

ip代理中間件需要兩個函數,

1 process_request(self, request, spider)

2 process_response(self, request, response, spider)

函數1 獲取代理ip、端口、過期時間可以調用代理網站給的api獲取

函數2 當ip被封,返回的是值是不一樣的,所以可以return request對象 重新分配代理ip、端口

偽代碼:

def process_request(self, request, spider):
    if ‘proxy‘ not in request.meta or 代理即將過期 or 代理被封:
        更新代理
        更新代理被封標誌
    request.meta[‘proxy‘] = 代理ip

def process_response(self, request, response, spider):
    if response.status != 200 or 驗證碼頁面url特殊標誌 in response.url:
        代理被封標誌
        更新代理
        return request
    return response

因為scrapy框架下各個請求是異步的,所以更新代理的函數需要進行一定的更改,因為每次將一個ip使用到被封才使用下一個ip,所以每個異步請求都應該使用同一個ip,過期或被封之後才更換

def 更新代理:
    加鎖:
    if 代理沒有設置好 or 代理即將過期
        請求代理ip
    

6. selenium+chromedriver中間件

這個中間件相當於使用chromedriver訪問頁面,並將各類ajax數據傳回給爬蟲進行解析,而scrapy框架負責調度url和數據解析存儲。

當頁面中ajax數據較多且復雜時,采用這種方式更方便。

~ meddlewares.py
from selenium import webdriver
from scrapy.http.response.html import HtmlResponse
class SeleniumDownloaderMiddleware(object):
    def __init__(self):
        self.driver = webdriver.Chrome(executable_path=r‘D:\chromedriver\chromedriver.exe‘)  # 創建driver

    def process_request(self, request, spider):
        self.driver.get(request.url)  # 打開不同的頁面
        source = self.driver.page_source
        response = HtmlResponse(self.driver.current_url, body=source, request=request, encoding=‘utf-8‘)  # 傳入的參數是按原本response對象需要的參數
        return response  # 必須返回response對象給爬蟲

最後在settings.py中開啟這個中間件

DOWNLOADER_MIDDLEWARES = {
   ‘boss.middlewares.SeleniumDownloaderMiddleware‘: 543,
}

爬蟲2.5-scrapy框架-下載中間件