使用HTTP代理

HTTP代理服務器可以比作客戶端與Web服務器網站之間的一個信息中轉站,客戶端發送的HTTP請求和Web服務器返回的HTTP響應通過代理服務器轉發給對方,

 

爬蟲程序在爬取某些網站的時候也需要使用代理,例如

  • 由於網絡環境因素,直接爬取的速度太慢了,使用代理提高爬取的速度
  • 某些網站讀用戶的訪問速度進行限制,爬取過快會被封禁IP,使用代理防止被封禁
  • 由於地方法律或者政治的原因,某些網站是無法直接進行訪問的,使用代理可以繞過訪問的限制

在scrapy中專門提供了HttpProxyMiddleware來給scrapy爬蟲設置代理

  

HttpProxyMiddleware默認就是開啓的,它會在系統環境變量中搜索當前系統代理,作爲scrapy爬蟲使用的代理

源碼解析:

  __init__方法:

    在HttpProxyMiddleware的構造器中,使用python標準庫urllib中的getproxies函數在系統環境變量中搜索系統代理的相關配置(變量名格式爲[格式]_proxy的變量),調用self._get_proxy方法解析代理配置信息,並將其返回結果保存到self.proxies字典中,如果沒有找到任何代理配置的話,就拋出NotConfigured異常,HttpProxyMiddleware就會被放棄使用

  _get_proxy方法:

    解析代理配置信息,返回身份驗證信息以及代理服務器url

  process_request方法

    處理每一個待發送的請求,爲沒有設置過代理的請求(meta屬性不包含proxy字段的請求)調用self.set_proxy方法設置代理

  _set_proxy方法

    爲一個請求設置代理,以請求的協議(HTTP或者HTTPS)作爲鍵,從代理服務器信息字典self.proxies中選擇代理,賦給request.meta的proxy字段。對於身份需要驗證的代理服務器,添加HTTP頭部Proxy-Authorization,他的值是在_get_proxy方法中計算得到的。

 

總結:

  在scrapy中爲一個請求設置代理就是將代理服務器的url寫到request.meta['proxy']中

 

使用多個代理:

  利用HttpProxyMiddleware爲爬蟲設置代理的時候,對於一種協議(HTTPShuozheHTTP)的所有請求只能使用一個代理,如果想使用多個代理,可以在構造每一個Request對象的時候,通過meta參數的proxy字段手動進行設置

import scrapy
from scrapy import Request
import json
class XiciSpider(scrapy.Spider):
name = "xici_proxy"
allowed_domains = ["www.xicidaili.com"]
def start_requests(self): #爬取http://www.xicidaili.com/nn/前3 頁 foriin range(1, 4):
yield Request('http://www.xicidaili.com/nn/%s' % i)
def parse(self, response):
for sel in response.xpath('//table[@id="ip_list"]/tr[pos
# 提取代理的IP、port、scheme(http or https)
ip = sel.css('td:nth-child(2)::text').extract_first()
port = sel.css('td:nth-child(3)::text').extract_first()
scheme = sel.css('td:nth-child(6)::text').extract_first() # 使用爬取到的代理再次發送請求到http(s)://httpbin.org/ip url = '%s://httpbin.org/ip' % scheme proxy = '%s://%s:%s' % (scheme, ip, port) meta = { 'proxy': proxy,
'dont_retry': True,
'download_timeout': 10, # 以下兩個字段是傳遞給check_available 方法的信息,方便 '_proxy_scheme': scheme, '_proxy_ip': ip, } yield Request(url, callback=self.check_available, meta=meta, dont_filter=True) def check_available(self, response): proxy_ip = response.meta['_proxy_ip'] # 判斷代理是否具有隱藏IP 功能 if proxy_ip == json.loads(response.text)['origin']: yield { 'proxy_scheme': response.meta['_proxy_scheme'], 'proxy': response.meta['proxy'], }

 

  • 在start_requests中請求網站下的前三頁,用parse方法作爲頁面解析的函數
  • 在parse方法中提取一個頁面中的所有的代理服務器信息,由於這些代理未必都是可用的,所以使用採集到的代理髮送請求http(s)://httpbin.org/ip驗證其是否可用,用check_acailable方法作爲頁面的解析函數
  • 要是能夠執行到check_available方法,那麼也就意味着response中對應的請求所使用的代理都是可用的,在check_available方法中,通過響應json字符串中的origin字段可以判斷代理是否是匿名的(隱藏IP),返回匿名代理。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章