关于Requests代理,你应该知道的
说到代理,写过爬虫的小伙伴一定都不陌生。但是你的代理真的生效了么?
代理主要分为以下几类:
如果是爬虫的话,最常见的选择是高匿代理。
Requests 设置代理非常方便,只需传递一个 proxies 参数即可。如官方示例:
import requestsproxies = {'http': 'http://10.10.1.10:3128','https': 'http://10.10.1.10:1080',
}requests.get('http://example.org', proxies=proxies)
留意一个地方,proxies 字典中有两个 key :https 和 http,为什么要写两个 key,如果只有一个可以么?
试试就知道了
准备验证函数
这个函数会使用代理去访问两个 IP 验证网站,一个是 https,一个是 http。
import requests
from bs4 import BeautifulSoupdef validate(proxies):https_url = 'https://ip.cn'http_url = 'http://ip111.cn/'headers = {'User-Agent': 'curl/7.29.0'}https_r = requests.get(https_url, headers=headers, proxies=proxies, timeout=10)http_r = requests.get(http_url, headers=headers, proxies=proxies, timeout=10)soup = BeautifulSoup(http_r.content, 'html.parser')result = soup.find(class_='card-body').get_text().strip().split('''\n''')[0]print(f"当前使用代理:{proxies.values()}")print(f"访问https网站使用代理:{https_r.json()}")print(f"访问http网站使用代理:{result}")
测试
Case 1
proxies = {'http': '222.189.244.56:48304','https': '222.189.244.56:48304' } validate(proxies)
输出
当前使用代理:dict_values(['222.189.244.56:48304', '222.189.244.56:48304']) 访问https网站使用代理:{'ip': '222.189.244.56', 'country': '江苏省扬州市', 'city': '电信'} 访问http网站使用代理:222.189.244.56 China / Nanjing
结果: 访问两个网站均使用了代理
Case 2
proxies = {'http': '222.189.244.56:48304' } validate(proxies)
输出
当前使用代理:dict_values(['222.189.244.56:48304']) 访问https网站使用代理:{'ip': '118.24.234.46', 'country': '重庆市', 'city': '腾讯'} 访问http网站使用代理:222.189.244.56 China / Nanjing
结果: 只有http请求使用了代理
Case 3
proxies = {'https': '222.189.244.56:48304' } validate(proxies)
输出
当前使用代理:dict_values(['222.189.244.56:48304']) 访问https网站使用代理:{'ip': '222.189.244.56', 'country': '江苏省扬州市', 'city': '电信'} 访问http网站使用代理:118.24.234.46 China / Nanning
结果: 只有https请求使用了代理
其他测试
通过 wireshark 抓包发现,当协议不匹配时,根本不会向代理服务器发起请求。
通过 postman 测试,结果与 Requests 一致,协议不同的情况下,不会走代理。
猜测可能是一种约定或者规则,类似 PAC ?(如果你知道答案,请告诉我)
寻找答案
从源码入手试试?在requests.ultis
中找到了这个函数:
def select_proxy(url, proxies):"""Select a proxy for the url, if applicable.:param url: The url being for the request:param proxies: A dictionary of schemes or schemes and hosts to proxy URLs"""proxies = proxies or {}urlparts = urlparse(url)if urlparts.hostname is None:return proxies.get(urlparts.scheme, proxies.get('all'))proxy_keys = [urlparts.scheme + '://' + urlparts.hostname,urlparts.scheme,'all://' + urlparts.hostname,'all',]proxy = Nonefor proxy_key in proxy_keys:if proxy_key in proxies:proxy = proxies[proxy_key]breakreturn proxy
答案揭晓了,Requests 会根据目标 url 的协议按照一定顺序来为它选择代理。 就拿上面的 Case 2 来说:
proxies = {'http': '222.189.244.56:48304'
}
请求http://ip111.cn/
时,按照以下顺序在 proxies 字典中为这个链接选用代理:
- 协议+域名 :
http://222.189.244.56
- 协议:
http
- all + 域名:
all://222.189.244.56
- all:
all
在第 2 步匹配到222.189.244.56:48304
,然后就使用这个代理去访问目标地址。
而在请求https://ip.cn
时,按照上面顺序匹配不到任何内容,就使用本地的 ip 去访问目标地址了。
这样也就能说明上面 3 个例子了。
扩展
官方示例中的代理包含协议,而我们测试的例子中没有但同样能够成功访问。这又是为什么呢?
# 官方的
proxies = {'http': 'http://10.10.1.10:3128','https': 'http://10.10.1.10:1080',
}
# 我们的
proxies = {'http': '222.189.244.56:48304','https': '222.189.244.56:48304'
}
答案同样可以在源码里找到,请看下面这两个函数:
requests.apdpters
def get_connection(self, url, proxies=None):"""Returns a urllib3 connection for the given URL. This should not becalled from user code, and is only exposed for use when subclassing the:class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.:param url: The URL to connect to.:param proxies: (optional) A Requests-style dictionary of proxies used on this request.:rtype: urllib3.ConnectionPool"""proxy = select_proxy(url, proxies)if proxy:proxy = prepend_scheme_if_needed(proxy, 'http')proxy_url = parse_url(proxy)if not proxy_url.host:raise InvalidProxyURL("Please check proxy URL. It is malformed"" and could be missing the host.")proxy_manager = self.proxy_manager_for(proxy)conn = proxy_manager.connection_from_url(url)else:# Only scheme should be lower caseparsed = urlparse(url)url = parsed.geturl()conn = self.poolmanager.connection_from_url(url)return conn
看这一行代码:proxy = prepend_scheme_if_needed(proxy, 'http')
,找到这个函数的定义:
def prepend_scheme_if_needed(url, new_scheme):"""Given a URL that may or may not have a scheme, prepend the given scheme.Does not replace a present scheme with the one provided as an argument.:rtype: str"""scheme, netloc, path, params, query, fragment = urlparse(url, new_scheme)# urlparse is a finicky beast, and sometimes decides that there isn't a# netloc present. Assume that it's being over-cautious, and switch netloc# and path if urlparse decided there was no netloc.if not netloc:netloc, path = path, netlocreturn urlunparse((scheme, netloc, path, params, query, fragment))
从注释中可以找到答案:
如果代理提供了协议,不做改变;如果代理没有协议的话,就为代理加上http
协议。
结论
- Requests 会按照目标url的协议来为它配置代理。基于此你可以为不同的协议甚至不同域名设置不同的代理,如果想为所有请求使用同一个代理,那直接使用 all 作为 key 来设置即可。
- 代理地址如果没有指明协议,则默认使用 http 请求。
参考链接
- HTTP 代理原理及实现(一)
- HTTP 代理原理及实现(二)
- 什么是透明、匿名、高匿代理?详解!
- HTTP代理和HTTPS代理的区别
关于Requests代理,你应该知道的相关推荐
- SQL Server 2005:你应该知道的13件事情
距离微软的SQL Server 2005正式版的推出,已经将近一年的时间.随着最近两份研究报告的出炉,SQL Server 2005又引起了业界的关注和评论--微软凭借SQL Server 2005取 ...
- C#开发人员应该知道的13件事情
C#开发人员应该知道的13件事情 本文讲述了C#开发人员应该了解到的13件事情,希望对C#开发人员有所帮助. 1. 开发过程 开发过程是错误和缺陷开始的地方.使用工具可以帮助你在发布之后,解决掉一些问 ...
- 网络服务器最基本的是文件,你可能想知道的15个网络常用基础知识
原标题:你可能想知道的15个网络常用基础知识 网络是一个复杂的系统,涉及知识很多.现在腾正小超人给大家分享15个常用的网络基础知识: 1) 如何查看本机所开端口 用netstat -a -n命令查看! ...
- C# Development 13 Things Every C# Developer Should Know--C#开发人员应该知道的13件事情
原文链接:https://dzone.com/refcardz/csharp 本文讲述了C#开发人员应该了解到的13件事情,希望对C#开发人员有所帮助. 1. 开发过程 开发过程是错误和缺陷开始的地方 ...
- 程序员应该知道的10大编程格言
作者 | BarryWang 来源 | https://www.cnblogs.com/barrywxx/p/4399007.html 每个程序员都该知道的10大编程格言(Kevin Pang): 编 ...
- 2019-11-29-git-需要知道的1000个问题
title author date CreateTime categories git 需要知道的1000个问题 lindexi 2019-11-29 8:36:7 +0800 2018-2-13 1 ...
- iOS 开发者一定要知道的 14 个知识点
本文讲的是iOS 开发者一定要知道的 14 个知识点, 作为一个 iOS 开发者(现在对 Swift 中毒颇深 ).我从零开始创建应用.维护应用,并且在很多团队待过.在我的职业生涯中,一句话一直响彻耳 ...
- 每个团队都应知道的API安全威胁
原文发表于kubernetes中文社区,为作者原创翻译 ,原文地址 更多kubernetes文章,请多关注kubernetes中文社区 目录 每个团队都应知道的API安全威胁 分页和资源限制不安全 如 ...
- 你应该知道的25个非常有用的CSS技巧
在我们的前端CSS编码当中,经常要设置特殊的字体效果,边框圆角等等,还要考虑兼容性的问题, CSS网页布局,说难,其实很简单.说它容易,往往有很多问题困扰着新手,在中介绍了非常多的技巧,这些小技巧与知 ...
- 关于机器学习,你应该知道的3个热门专业术语
https://www.toutiao.com/a6683842829510246923/ 2019-04-25 22:43:48 关于机器学习,你应该知道的3个热门专业术语 原创: 吴郦军.罗人千 ...
最新文章
- OSPF中第一类外部路由和第二类外部路由的区别
- 【Java Web前端开发】web概念概述和HTML基础部分
- [bzoj2242][SDOI2011]计算器
- 考公专业科目计算机,2017国考中国证监会专业科目考试大纲(计算机类)
- php把语音转成帧,[转载]用TCP/IP实现自己简单的应用程序协议:成帧器部分
- 对github的初步认识以及对软件技术基础课程的期待
- Eclipse去除js(JavaScript)验证错误
- Thymeleaf 模板 js和css引入的方式
- 离线安装CDH5集群及相关软件
- UEFI模式下安装ubuntu以及重装ubuntu教程
- jpg图片太大怎么压缩?jpg图片怎么压缩大小?
- Atitit q2016 qa doc list on home ntpc.docx
- 微软Windows商店会变得更像Steam ,Xbox可自由安装PC游戏
- java RSA生成公钥对象和私钥对象
- canvas实现蜘蛛网动态背景特效
- 用uniapp搞了个小说阅读器
- ThinkPHP的车辆租赁管理系统
- 使用Hprose制作一个简单的分布式应用程序
- [转]深度分析中国移动、中国联通、中国电信的3G胜算
- 【eos系列】eos系统合约介绍 — 发币合约eosio.token
热门文章
- 嵌入式单片机基础篇(三十六)之STM32F1SPI标准接口程序以及模拟SPI标准接口程序讲解
- sklearn与其他算法集合使用步骤
- 2021年美容师(初级)找解析及美容师(初级)模拟考试题
- java atan atan2_Java Math atan2() 使用方法及示例
- 使用FastStone Capture进行长截图(滚动截图)
- 购买二手计算机信息询问英语作文,英语作文:学生是否应该买二手书
- Sleep()函数的理解、使用、意义
- java的jvm和事务并发的关系_Java程序员岗面试总结
- 人声合成效果器 – iZotope VocalSynth 2 v2.1.0 WiN-MAC
- 2019勒索病毒攻击盘点,企业该如何做好防范?