1. 程式人生 > >爬蟲2.5-scrapy框架-下載中介軟體

爬蟲2.5-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,
}