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 scrapyfrom scrapy import Requestimport jsonclass XiciSpider(scrapy.Spider):name = "xici_proxy"allowed_domains = ["http://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)://http://httpbin.org/ip url = %s://http://httpbin.org/ip % schemeproxy = %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)://http://httpbin.org/ip验证其是否可用,用check_acailable方法作为页面的解析函数要是能够执行到check_available方法,那么也就意味着response中对应的请求所使用的代理都是可用的,在check_available方法中,通过响应json字符串中的origin字段可以判断代理是否是匿名的(隐藏IP),返回匿名代理。http代理一键切换h.wandouip.com