求助:Python Requests与cURL请求返回不同响应的原因排查
1. GET请求携带空Body的差异
你的Python代码中使用了data=payload(空字典),对于GET请求,requests会将data参数转换为请求Body发送;而cURL的GET请求默认不会发送任何Body内容。虽然HTTP规范不禁止GET带Body,但部分服务器会对这种情况返回不同响应。
解决:GET请求无需传递Body,删除data=payload参数:
response = requests.request("GET", url, headers=headers, allow_redirects=False)
2. 缺失Accept请求头
cURL和Postman会自动添加Accept头(比如cURL默认值为text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8),但你的requests代码未设置该头,服务器可能根据Accept头返回不同格式的内容。
解决:在headers中添加与cURL/Postman一致的Accept头:
headers = { 'host': '<HOST>', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', 'Accept-Encoding': 'gzip, deflate', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' }
3. 重定向处理差异
你的cURL命令使用了--location参数(默认跟随重定向),而requests设置了allow_redirects=False。即使你说Postman不跟随重定向且与cURL返回一致,也可能存在隐性重定向:cURL跟随重定向后的响应与Postman实际返回一致,而requests阻止重定向后拿到的是跳转页面内容。
验证:将requests的allow_redirects改为True,观察返回内容是否与cURL一致:
response = requests.request("GET", url, headers=headers, allow_redirects=True)
4. 压缩解码差异
cURL的--compressed会自动处理服务器返回的gzip/deflate压缩内容,requests默认也会自动解码,但2.25.1版本可能存在解码异常。可以手动验证响应是否被正确解码:
print(response.content) # 手动尝试解码 import gzip try: print(gzip.decompress(response.content).decode('utf-8')) except: pass
5. Host头格式问题
确保手动设置的host头与cURL完全一致(比如是否包含端口号、有无空格或大小写差异)。requests会自动根据URL生成Host头,手动设置可能出现格式错误。
解决:删除手动设置的host头,让requests自动生成:
headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', 'Accept-Encoding': 'gzip, deflate', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' }
6. 对比完整请求详情
直接对比cURL和requests发送的完整请求内容,是定位差异最精准的方法:
- 让cURL输出完整请求日志:
curl --location '<URL>' \ --header 'host: <HOST>' \ --header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \ --header 'Accept-Encoding: gzip, deflate' \ --compressed -v
- 在requests中开启DEBUG日志查看请求详情:
import requests import logging logging.basicConfig(level=logging.DEBUG) url = "<URL>" headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', 'Accept-Encoding': 'gzip, deflate', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' } response = requests.request("GET", url, headers=headers, allow_redirects=True)
内容的提问来源于stack exchange,提问作者Adrian B

