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),返回匿名代理。

最新文章

  1. C# 反射创建对象,包括创建引用外部程序集类的实例
  2. BFPRT(线性查找算法)
  3. PostgreSQL中,如何查表属于哪个数据库
  4. html跳转到同一个页面的不同位置
  5. iOS-Core Text 入门
  6. Algorithm --> 字符串中最长不重合子串长度
  7. [leetcode]25. Reverse Nodes in k-Group每k个节点反转一下
  8. 小程序模板中data传值有无...
  9. JVM调优原理
  10. 更改Outlook 2013中Exchange数据文件存放路径
  11. Maven项目继承与聚合
  12. hdu3974 Assign the task【线段树】
  13. java 判断字符串IP合法性以及获取IP的数值形式
  14. typescript-dva脚手架
  15. SNMP TRAP报文解析
  16. jenkins配置01--用户添加及权限配置
  17. 关于GCD的几个结论
  18. python使用virtualenv
  19. javascript转换日期字符串为Date对象
  20. Javaee项目经验须知

热门文章

  1. JS对象 字符串分割 split() 方法将字符串分割为字符串数组,并返回此数组。 语法: stringObject.split(separator,limit)
  2. 修改jupyter保存文件目录
  3. Python基础知识之5——函数基础
  4. 解决Keep-Alive 和 Close 不能使用此属性设置
  5. Python学习笔记(四)——文件永久存储
  6. JSF(JavaServer Faces)简介
  7. 使用串口绘制实时曲线 —— SerialChart
  8. Spark 读写数据、抽象转换 拾遗
  9. [kuangbin带你飞]专题一 简单搜索 - D - Fliptile
  10. 数据类中引用virtual