urllib3.PoolManager请求无Set-Cookie头,如何获取该响应字段?
问题重现
使用urllib3的代码及输出
import urllib3 http = urllib3.PoolManager( timeout=10, ) response=http.request('GET','example.com') print(response.headers)
输出:
HTTPHeaderDict({'Cache-Control': 'private', 'Content-Type': 'text/html; charset=utf-8', 'Vary': 'Accept-Encoding', 'Server': 'Microsoft-IIS/10.0', 'X-AspNet-Version': '4.0.30319', 'X-Powered-By': 'ASP.NET', 'X-Powered-By-Plesk': 'PleskWin', 'Date': 'Tue, 16 Aug 2022 06:57:53 GMT', 'Content-Length': '5807'})
使用requests的代码及输出
import requests response = requests.get('example.com') print(response.headers)
输出:
{'Cache-Control': 'private', 'Content-Type': 'text/html; charset=utf-8', 'Content-Encoding': 'gzip', 'Vary': 'Accept-Encoding,Accept-Encoding', 'Server': 'Microsoft-IIS/10.0', 'Set-Cookie': 'ASP.NET_SessionId=2tygffzylqwnw3spoavb4lbe; path=/; HttpOnly; SameSite=Lax', 'X-AspNet-Version': '4.0.30319', 'X-Powered-By': 'ASP.NET', 'X-Powered-By-Plesk': 'PleskWin', 'Date': 'Tue, 16 Aug 2022 06:57:55 GMT', 'Content-Length': '40682'}
问题原因
核心原因是两个库默认发送的请求头存在差异,导致服务器返回不同的响应:
- requests库默认会发送一系列标准化请求头,比如
User-Agent(标识为Python requests客户端)、Accept-Encoding: gzip, deflate, br(表明支持压缩),这些标识会触发服务器返回包含Set-Cookie的响应(比如ASP.NET服务器会针对标准客户端创建会话Cookie)。 - urllib3的默认请求头非常简洁,缺少这些关键标识,服务器可能认为这是不支持标准会话或压缩的客户端,因此未返回
Set-Cookie字段。
从响应内容的差异也能印证这一点:requests的响应包含Content-Encoding: gzip,而urllib3的没有,说明请求头中Accept-Encoding的差异是服务器返回内容不同的原因之一。
解决方法
要让urllib3获取到Set-Cookie,需手动添加与requests一致的请求头,模拟标准客户端请求:
import urllib3 http = urllib3.PoolManager(timeout=10) # 添加requests默认的请求头 headers = { 'User-Agent': 'python-requests/2.28.1', # 可替换为当前requests版本或其他标准UA 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*' } response = http.request('GET', 'example.com', headers=headers) # 获取单个Set-Cookie字段 set_cookie = response.headers.get('Set-Cookie') # 如果存在多个Set-Cookie,用getlist获取全部 # set_cookies = response.headers.getlist('Set-Cookie') print(set_cookie)
添加请求头后,服务器会返回包含Set-Cookie的响应头,你可以通过response.headers.get('Set-Cookie')直接获取字段值;若存在多个Set-Cookie,则用response.headers.getlist('Set-Cookie')获取所有值的列表。
内容的提问来源于stack exchange,提问作者Rahman
相关产品推荐
相关产品推荐

