python requests session刷新_Python Requests Session set-cookie不生效的坑
我们知道 Python Requests库 中的 Session 模块有连接池和会话管理的功能,比如请求一个登录接口后,会自动处理 response 中的 set-cookie,下次再请求时会自动把 cookie 带上。但最近出现了一个诡异的事情,cookie 没有自动带上,导致请求 403。
一开始怀疑是登录接口错误了,没有 set-cookie,但抓包发现 response header 中有 set-cookie,打印请求的 response.cookies 也有需要的 cookie。又怀疑是 set-cookie 的格式不对或者其它问题,但用浏览器实际跑了下流程,发现系统一切正常,那基本就是 requests 库的问题了。
没办法,只能 debug 了,单步调试了几轮,基本了解了 requests 的处理方式,首先把请求参数转变为 Request 对象,然后对使用 prepare_request 对 Request 进行预处理,其中有一步 merge_cookies 的操作(还有各种其它处理),把传入的 cookies 和 self.cookies merge 到 RequestsCookieJar 对象上去,这一步也没啥问题,merged_cookies 变量也是对的。后续将预处理过的请求,通过内置的 http adapter 发送出去。http adapter 底层是通过 urllib3.poolmanager 获取到 urllib3.connectionpool 连接(这里是连接池的核心部分),再通过 conn.urlopen 实际发送请求。虽然跟踪了解到了整个请求逻辑,但最终发出的请求还是没有带上需要的 cookie。
问题定位一度陷入僵局,只能再回顾上面的流程,cookie 肯定就是在 merged_cookies 和 conn.urlopen 之间没的,再仔细观察发现,conn.urlopen 请求参数里面压根没有 cookie 字段。
1
2
3
4
5
6
7
8
9
10
11
12
13 # :param request: The :class:`PreparedRequest ` being sent.
resp=conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout
)
查阅资料发现,urllib3 的作者说,连接池只处理底层连接,cookie 跟踪等事情应该上层来做。大胆猜测,那 cookie 应该是放在 header 里了,往前捣看看 request.headers 是怎么变动的(此时里面的 Cookie 字段确实不正确)。
再走查代码发现 prepare_request 里面是调用了 PreparedRequest.prepare,其中有一步 prepare_cookies,主要是调用了 cookielib.CookieJar.add_cookie_header 最终将 cookie 放到了 self.headers['Cookie']。但里面有个 request.has_header("Cookie") 的判断,header 中没有 Cookie 字段才会放,不知道为什么这么考虑(最新版 3.8 还是这样),估计是 merge cookie 比较麻烦,但问题确实就出在这里,这次请求之前,Requests Session 已经直接通过 headers['Cookie'] 设置了 cookie。复现代码(修改自官方示例):
1
2
3
4
5
6
7
8
9
10 importrequests
s=requests.Session()
s.headers.update({
'Cookie':'k=v'
})
s.get('https://httpbin.org/cookies/set/sessioncookie/123456789')
r=s.get('https://httpbin.org/cookies')
print(r.text)
# {"cookies":{"k":"v"}}
虽然找到了问题的原因,但又不好解决,总不能不让直接操作 headers['Cookie'] 吧,先不说无法限制使用者,而且之前的代码已经这样做了,改动量非常之大。不过好在,现在自己用的框架是在 Requests Session 上封装了一层,操作 header 都是调用的统一的 update_headers 方法:
1
2
3
4
5
6 defupdate_headers(self,headers):
"""
更新当前会话的header
:param headers: header字典
"""
self.headers.update(headers)
对 headers['Cookie'] 的操作拦截一下,变成对 cookies 的操作:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 defupdate_headers(self,headers):
"""
更新当前会话的header
:param headers: header字典
"""
forheader_key,header_valueinheaders.items:
ifheader_key=='Cookie'orheader_key=='cookie':
c=Cookie.SimpleCookie()
c.load(header_value)
cookies={}
forkey,morselinc.items():
cookies[key]=morsel.value
requests.utils.add_dict_to_cookiejar(self.cookies,cookies)
delheaders[header_key]
self.headers.update(headers)
这样即不用改之前的调用方代码,也防止了后人掉坑。
参考资料
python requests session刷新_Python Requests Session set-cookie不生效的坑相关推荐
- python session模块_Python requests模块session代码实例
http协议本身是无状态的,为了让请求之间保持状态,有了session和cookie机制.requests也提供了相应的方法去操纵它们. requests中的session对象能够让我们跨http请求 ...
- python requests 代理超时_python requests 超时与重试
一 源起: requests模块作为python爬虫方向的基础模块实际上在日常实际工作中也会涉及到,比如用requests向对方接口url发送POST请求进行推送数据,使用GET请求拉取数据. 但是这 ...
- python requests是什么_python requests库学习
Requests python的request库官方介绍就是让HTTP服务人类,所以从这点我们就可以知道request库是为了让我们更加方便的进行http相关的各种操作 我们学习request有什么用 ...
- 工信部python证书多少钱_python requests SSL证书问题
错误信息如下: requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'tls_process_ser ...
- python绘制蚊香形_Python requests发送post请求的一些疑点
前言 在Python爬虫中,使用requests发送请求,访问指定网站,是常见的做法.一般是发送GET请求或者POST请求,对于GET请求没有什么好说的,而发送POST请求,有很多朋友不是很清楚,主要 ...
- python requests cookies请求_python+requests实现接口测试 - cookies的使用
在很多时候,发送请求后,服务端会对发送请求方进行身份识别,如果请求中缺少识别信息或存在错误的识别信息, 会造成识别失败. 如一些需要用户登录以后才能访问的页面. import requests mya ...
- python自动点赞软件_python requests 简单实现易班登录,自动点赞,评论,发表
小编能力有限,本文纯属瞎编,如有雷同,你去打辅导员涩 一.前戏 有个操蛋,操蛋,操蛋的辅导员促使小编成长,原因:易班需要活跃度,辅导员安排班上每个人必须去易班上 写文章,写评论,发投票... 我觉得 ...
- python requests请求方式_Python Requests库使用2:请求方法
GitHub API HTTP verbs Where possible, API v3 strives to use appropriate HTTP verbs for each action. ...
- python requests超时时间_python - requests 库 使用过程中timeout值最大可设值?
问 题 请问 requests 库 使用过程中timeout错误的默认时间是多长呢? 查看源码 理论上 timeout值可以任意设? 默认 timeout 值 是怎么来的呢? 如果我想设一个比较大的t ...
最新文章
- ArduinoYun教程之通过网络为Arduino Yun编程
- 【NLP】四万字全面详解 | 深度学习中的注意力机制(四,完结篇)
- HttpClient的几个实现类
- Struts2中 Path (getContextPath与basePath)
- 配置mysql环境变量
- python classmethod函数_在python中使用与instance和classmethod相同的函数
- Daily Scrum M2 11-5
- 是否可以在网络共享磁盘上创建数据库?
- 【天梯选拔月赛】寻宝路线(dp)
- kappa一致性检验教程_Kappa一致性分析
- 点击进入我的QQ空间
- 以过来人经验---分享从学生--工程师之--怎么写好一份从事技术工作的简历及面试技巧(以嵌入式为例)(中)
- 计算机英语教学设计反思,小学五年级英语教学设计与反思
- JVM-SandBox使用入门
- Linux 安全缓解机制总结
- 总价加激励费用合同计算
- 视频中为什么需要这么多的颜色空间?
- Lenovo Y750 7-15IMH05 LA-J561P Rev 1.0笔记本原理图
- 卸载流氓软件/删除顽固文件教程
- 硬盘柱面损坏怎么办_硬盘有坏道就不能用了吗?别再吃哑巴亏了,今天跟人人再说一次...
热门文章
- Matlab高光谱样本相关性分析
- Leetcode--152. 乘积最大子数组(java)
- MYSQL--一条SQL更新语句是如何执行的?
- Leetcode--300. 最长上升子序列
- linux java amr转mp3_本工具用于将微信语音 amr 格式转换为 mp3 格式以便在 html5 的 audio 标签中进行播放...
- php mysql会员注册_PHP实现会员注册系统
- mongodb 监听不到端口_干货|MongoDB简单操作和通过python进行操作
- 查看ie保存的表单_小学信息技术gt;搜索保存网页教师资格证面试模板
- centos jupyter 安装_centos7安装 jupyter
- CompletableFuture详解~supplyAsync