1. 程式人生 > >設定代理 IP | Requests & Scrapy

設定代理 IP | Requests & Scrapy

對於採取了比較強的反爬措施網站來說,要想順利爬取網站資料,設定隨機 User-Agent 和代理 IP 是非常有效的兩個方法。本文介紹如何在 Requests 和 Scrapy 中設定代理 IP。

本文的目標測試網頁選擇下面這個 URL,請求該網頁可以返回當前的 IP 地址:

http://icanhazip.com

下面,我們就先來說說 Requests 中如何設定代理 IP。

Requests

不使用代理

首先,先來看一下不使用代理 IP 的情況:

import requests
url = 'http://icanhazip.com'
try:
    response = requests.get(url) #不使用代理
    print(response.status_code)
    if response.status_code == 200:
        print(response.text)
except requests.ConnectionError as e:
    print(e.args)

執行上面的程式,會返回我們電腦本機的 IP,可以通過百度查詢 IP 地址對比一下。

200
124.238.223.xxx # 後三位隱去了

[Finished in 0.8s]

在這裡插入圖片描述

使用代理
然後,我們測試一下使用代理後的情況。

常見的代理包括 HTTP 代理和 SOCKS5 代理,前者可以找一些免費代理 IP 進行測試,由於我電腦上使用的是 Shadowsocks,所以就介紹一下 SOCKS5 代理的設定。

首先,電腦上要安裝有 Shadowsocks

啟動該軟體後預設會在 1080 埠下建立 SOCKS5 代理服務,代理為:127.0.0.1:1080,然後我們在 Requests 中使用該代理,方法很簡單隻需要新增一項 proxies 引數即可:

proxies = [
     {'http':'socks5://127.0.0.1:1080'},
     {'https':'socks5://127.0.0.1:1080'}
 ]
 proxies = random.choice(proxies)
 print(proxies)
 url = 'http://icanhazip.com'
 try:
     response = requests.get(url,proxies=proxies) #使用代理
    print(response.status_code)
    if response.status_code == 200:
        print(response.text)
 except requests.ConnectionError as e:
     print(e.args)

這裡,proxies 引數是字典型別,鍵名http表示協議型別,鍵值 socks5://127.0.0.1:1080表示代理。
proxies 添加了 http 和 https 兩個代理,這樣寫是因為有些網頁採用 http 協議,有的則是採用 https 協議,為了在這兩類網頁上都能順利使用代理,所以一般都同時寫上,當然,如果確定了某網頁的請求型別,可以只寫一種,比如這裡我們請求的 url 使用的是 http 協議,那麼使用 http 代理就可以,random 函式用來隨機選擇一個代理,我們來看一下結果:

{'http': 'socks5://127.0.0.1:1080'}
200
45.78.42.xxx #xxx表示隱去了部分資訊

可以看到,這裡隨機選擇了 http 協議的代理後,返回的 IP 就是我真實的 IP 代理地址,成功代理後就可以爬一些牆外的網頁了。

延伸一下,假如隨機選擇的是 https 代理,那麼返回的 IP 結果還一樣麼?我們嘗試重複執行一下上面的程式:

{'https': 'socks5://127.0.0.1:1080'}
200
124.238.223.xxx

可以看到這次使用了 https 代理,返回的 IP 卻是本機的真實 IP,也就是說代理沒有起作用。

進一步地,我們將 url 改為 https 協議:https://icanhazip.com,然後再嘗試分別用 http 和 https 代理請求,檢視一下結果:

#http 請求
{'http': 'socks5://127.0.0.1:1080'}
200
124.238.223.xxx

#https 請求
{'https': 'socks5://127.0.0.1:1080'}
200
45.78.42.xxx

可以看到,兩種請求的結果和之前的剛好相反了,由於 url 採用了 https 協議,則起作用的是 https 代理,而 http 代理則不起作用了,所以顯示的是本機 IP。

因此,可以得到這樣的一個結論:

HTTP 代理,只代理 HTTP 網站,對於 HTTPS 的網站不起作用,也就是說,用的是本機 IP。

HTTPS 代理則同理。

使用付費代理

上面,我們只使用了一個代理,而在爬蟲中往往需要使用多個代理,那有如何構造呢,這裡主要兩種方法,一種是使用免費的多個 IP,一種是使用付費的 IP 代理,免費的 IP 往往效果不好,那麼可以搭建 IP 代理池,但對新手來說搞一個 IP 代理池成本太高,如果只是個人平時玩玩爬蟲,完全可以考慮付費 IP,幾塊錢買個幾小時動態 IP,多數情況下都足夠爬一個網站了。

這裡推薦一個付費代理「阿布雲代理」,最近使用了一下,效果非常不錯,5 塊錢買了 5個小時,爬完了一個網站,所以沒有必要為了省 5 塊錢,而費勁地去搞 IP 代理池。
在這裡插入圖片描述
首次使用的話,可以選擇購買一個小時的動態版試用下,點選生成隧道代理資訊作為憑證加入到程式碼中。
在這裡插入圖片描述
在這裡插入圖片描述
將資訊複製到官方提供的 Requests 程式碼中,執行來檢視一下代理 IP 的效果:

import requests
 # 待測試目標網頁
 targetUrl = "http://icanhazip.com"
 def get_proxies():
     # 代理伺服器
     proxyHost = "http-dyn.abuyun.com"
     proxyPort = "9020"
 
     # 代理隧道驗證資訊
     proxyUser = "HS77K12Q77V4G9MD"
     proxyPass = "4131FFDFCE27F104"

     proxyMeta = "http://%(user)s:%(pass)[email protected]%(host)s:%(port)s" % {
       "host" : proxyHost,
       "port" : proxyPort,
       "user" : proxyUser,
       "pass" : proxyPass,
     }
     proxies = {
         "http"  : proxyMeta,
         "https" : proxyMeta,
     }
 
     for i in range(1,6):
         resp = requests.get(targetUrl, proxies=proxies)
         # print(resp.status_code)
         print('第%s次請求的IP為:%s'%(i,resp.text))

 get_proxies()

可以看到每次請求都會使用不同的 IP,是不是很簡單?比搞 IP 代理池省事多了。
在這裡插入圖片描述
以上,介紹了 Requests 中設定代理 IP 的方法,下面我們接著介紹在 Scrapy 中如何設定。

Scrapy

middlewares.py 中設定

這種方法需要先在 middlewares.py 中設定代理 IP 中介軟體:

import random
 class ProxyMiddleware(object):
     def __init__(self, ip):
         self.ip = ip
 
     @classmethod
     def from_crawler(cls, crawler):
         return cls(ip=crawler.settings.get('PROXIES'))
 
     def process_request(self, request, spider):
        ip = random.choice(self.ip)
         request.meta['proxy'] = ip
         logging.debug('Using Proxy:%s'%ip)

接著,需要在 settings.py 新增幾個在西刺上找的代理 IP,格式如下:

PROXIES = [
    'https://127.0.0.1:8112', 
    'https://119.101.112.176:9999',
    'https://119.101.115.53:9999',
    'https://119.101.117.226:9999']

然後,我們仍然以 http://icanhazip.com 為目標網頁,執行 Scrapy 專案重複請求 5 次,檢視一下每次返回的 IP 情況:

def start_requests(self):
        items = []
        for i in range(1,6):
            item = yield scrapy.Request(self.cate_url,callback=self.get_category)
            items.append(item)
        return items

    def get_category(self, response):
        print(response.text)

在這裡插入圖片描述
可以看到部分 IP 成功請求得到了相應,部分 IP 則無效請求失敗,因為這幾個 IP 是免費的 IP,所有失效很正常。

使用付費代理

接下來我們使用阿布雲付費代理,繼續嘗試一下,在 middlewares.py 中新增下面的程式碼:

""" 阿布雲ip代理配置,包括賬號密碼 """
 # 阿布雲scrapy 寫法
 import base64
 proxyServer = "http://http-dyn.abuyun.com:9020"
 proxyUser = "HS77K12Q77V4G9MD"  # 購買後點擊生成獲得
 proxyPass = "4131FFDFCE27F104"    # 購買後點擊生成獲得
 
 # for Python3
 proxyAuth = "Basic " + base64.urlsafe_b64encode(bytes((proxyUser + ":" + proxyPass), "ascii")).decode("utf8")

 class AbuyunProxyMiddleware(object):
      """ 阿布雲ip代理配置 """
      def process_request(self, request, spider):
         request.meta["proxy"] = proxyServer
         request.headers["Proxy-Authorization"] = proxyAuth
         logging.debug('Using Proxy:%s'%proxyServer)

由於,在阿布雲購買的是最基礎的代理,即每秒 5 個請求,因為 Scrapy 預設的併發數是 16 個,所以需要對 Scrapy 請求數量進行一下限制,可以設定每個請求的延遲時間為 0.2s ,這樣一秒就剛好請求 5 個,最後啟用上面的代理中介軟體類即可:

""" 啟用限速設定 """
 AUTOTHROTTLE_ENABLED = True
 DOWNLOAD_DELAY = 0.2  # 每次請求間隔時間
 
 DOWNLOADER_MIDDLEWARES = {
  #'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None, #啟用隨機UA
  #'scrapy_fake_useragent.middleware.RandomUserAgentMiddleware': 100,  #啟用隨機UA
  'wandoujia.middlewares.AbuyunProxyMiddleware': 200, # 啟用阿布雲代理
  #value值越小優先順序越高
 }

然後同樣地請求 5 次,檢視每次請求返回的 IP :
在這裡插入圖片描述

可以看到,每個 IP 都順利請求成功了,所以說付費地效果還是好。

使用 scrapy-proxies 庫代理

除了上述兩種方法,我們還可以使用 GitHub 上的一個 IP 代理庫:scrapy-proxies,庫的使用方法很簡單, 三個步驟就可以開啟代理 IP。

首先,執行下面命令安裝好這個庫:

pip install scrapy_proxies

然後,在 Scrapy 專案中的 settings.py 檔案中,新增下面一段程式碼:

RETRY_TIMES = 3 # 自定義請求失敗重試次數
 #重試的包含的錯誤請求程式碼
 RETRY_HTTP_CODES = [500, 503, 504, 400, 403, 404, 408]
 DOWNLOADER_MIDDLEWARES = {
     'scrapy.downloadermiddlewares.retry.RetryMiddleware': 90,
     'scrapy_proxies.RandomProxy': 100,
     'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 110,
 }
 PROXY_LIST = r'/proxies.txt'  # proxy 代理檔案存放位置,此處為程式所在磁碟根目錄下
 PROXY_MODE = 0 # 每次請求都使用不同的代理

最後,需要提供多個代理 IP,我們在西刺上隨便找幾個 IP,然後存放在 PROXY_LIST 指定的 txt 檔案中即可,格式如下:

https://119.101.112.176:9999
https://119.101.115.53:9999
https://119.101.117.53:999

然後重複之前的操作,檢視代理 IP 的設定效果。

我在使用該庫的過程中,發現有一些問題,不知道是配置不對還是怎麼回事,效果不是太好,所以推薦使用前兩種方法。

好,以上就是在 Requests 和 Scrapy 中使用代理 IP 的方法總結,如果爬蟲專案不大、追求穩定且不差錢的話,建議直接上付費代理。

原文