iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 24
0
AI & Data

Scrapy爬蟲與資料處理30天筆記系列 第 24

[Day 24] Scrapy 隨機代理實現

嗨,第24天,接續昨天的主題,我們來要實做隨機代理,將昨天爬到的代理在spider內使用,隨機代理的話每次對網頁的請求就會被不同的代理分攤,就不容易被封鎖了。

Scrapy中,有一個Downloader Middleware: HttpProxyMiddleware,是用來給爬蟲設定代理的。
原始程式碼:scrapy/httpproxy.py GitHub

  • _get_proxy方法為解析代理資訊,傳回身份驗證的資訊creds以及代理伺服器url。
  • process_request方法用來處理每個發送的請求,判斷式if 'proxy' in request.meta也就是meta中不包含proxy欄位(沒設定代理)的請求則呼叫self._set_proxy()
  • _set_proxy為請求設定代理,以HTTPHTTPS為key,從self.proxies中選擇代理指定給request.metaproxy欄位。

現在我們基於HttpProxyMiddleware來實現隨機代理的Middleware,開啟middlewares.py

from scrapy import signals
from scrapy.downloadermiddlewares.httpproxy import HttpProxyMiddleware
from collections import defaultdict
import json
import random
  • 建立一個RandomProxyMiddleware類別且它繼承HttpProxyMiddleware
class RandomProxyMiddleware(HttpProxyMiddleware):
  ...
  • 定義參數,編碼以及讀取代理檔案的資訊,最後把內容加到proxies內:
   def __init__(self, auth_encoding="latin-1", proxy_list_file=None):
        if not proxy_list_file:
            raise NotConfigured
        self.auth_encoding = auth_encoding
        self.proxies = defaultdict(list)

        with open(proxy_list_file) as f:
            proxy_list = json.load(f)
            for proxy in proxy_list:
                scheme = proxy["scheme"]
                url = proxy["proxy"]
                self.proxies[scheme].append(self._get_proxy(url, scheme))
  • from_crawler用來讀取settings.py檔案的參數HTTPPROXY_AUTH_ENCODING, PROXY_LIST_FILE
    @classmethod
    def from_crawler(cls, crawler):
        auth_encoding = crawler.settings.get("HTTPPROXY_AUTH_ENCODING", "latin-1")
        proxy_list_file = crawler.settings.get("PROXY_LIST_FILE")
        return cls(auth_encoding, proxy_list_file)
  • 覆寫一個_set_proxy方法,根據請求的協定從proxies中選出一個proxyrequest.meta["proxy"]
    def _set_proxy(self, request, scheme):
        creds, proxy = random.choice(self.proxies[scheme])
        request.meta["proxy"] = proxy
        if creds:
            request.headers["Proxy-Authorization"] = b"Basic" + creds
  • 設定settings.py中的DOWNLOADER_MIDDLEWARES,啟用RandomProxyMiddleware
DOWNLOADER_MIDDLEWARES = {
   'get_proxy.middlewares.RandomProxyMiddleware':745
}
  • 設定PROXY_LIST_FILE, HTTPPROXY_AUTH_ENCODING

這樣就完成了,接下來要來實際測試是否可行了,建立一隻簡單的spider,請求網址為之前測試的網址:

import scrapy
class ProxyExampleSpider(scrapy.Spider):
    name = "test"
    # start_urls = ['https://httpbin.org/ip']
    def start_requests(self):
        for i in range(10):
            yield scrapy.Request('https://httpbin.org/ip', dont_filter=True)

    def parse(self, response):
        print(response.text)
  • 執行後可以看到如下圖,請求的ip都不同,就表示成功了:

Imgur

好的,接續昨天的主題,今天實作了隨機代理,
其實到目前為止其實已經理解了大部分爬蟲會用到的功能。
最後幾天會再看看有什麼需要說明的吧。

總之今天先這樣了,明天見!


上一篇
[Day 23] Scrapy 爬免費代理(Proxy)
下一篇
[Day 25] OCR 圖片識別
系列文
Scrapy爬蟲與資料處理30天筆記30

1 則留言

0
rockywang
iT邦新手 5 級 ‧ 2020-05-04 11:44:17

請問 HttpProxyMiddleware 在如果該代理伺服器是不 work 的時候,會自動排除掉下次不再使用嗎?

每次 scrapy crawl XXX 的時候 , 並不會參考上次run spider的所有結果 , 且代理伺服器 是在 middleware中去寫判斷拿取ip並代理

如果 要自動排除掉下次不再使用 , 可以改寫以下方法 , 並寫在pipeline裡

    def drop_href(self, item, spider):
        if 'nike' in str(item['Brand']):
            file_name = spider.settings.get('NIKE_PRODCUTS_JSON_FILE_PATH')
        elif 'athleta' in str(item['Brand']):
            file_name = spider.settings.get('ATHLETA_PRODUCTS_LINK_PATH')
        else:
            pass
        f = open(file_name, 'r',encoding="utf-8")
        a = f.readlines()  
        f = open(file_name,'w',encoding="utf-8") 
        for i in a:                               
            f.write(i.replace(str(item['Url']),''))

我要留言

立即登入留言