Python requests请求API返回200但JSON解码失败响应乱码
问题产生原因
问题核心是响应内容使用了Brotli(br)压缩,但当前使用的requests库没有配置对应的解压能力:
- 你发送的请求头里
Accept-Encoding: gzip, deflate, br明确告知服务端客户端支持br格式压缩,服务端按规则返回了br压缩的响应体,响应头中的Content-Encoding: br字段可以直接佐证这一点。 - requests库默认内置了gzip、deflate两种压缩格式的自动解压能力,但不自带Brotli格式的解码依赖,拿到压缩后的二进制内容后直接按文本编码解析,就会出现你看到的乱码,后续调用
.json()方法自然会抛出解析失败的异常。 - Postman、Thunder Client这类接口测试工具内置了全量压缩格式的解码能力,不需要额外配置就能自动解压br内容,因此可以正常展示返回结果。
- node环境下的axios同样默认不携带brotli解码依赖,因此会出现和requests完全一致的乱码问题,修复逻辑通用。
修复方案
你可以任选以下一种方案解决:
方案1:安装Brotli解码依赖(推荐,无需修改业务代码)
安装对应解码库后,requests会在检测到br编码响应时自动完成解压,原有业务逻辑不需要做任何改动:
- 执行pip命令安装官方适配的brotli包:
pip install brotli
- 如果安装时遇到C编译相关报错,可以替换为兼容的cffi绑定包,urllib3/requests可以自动识别调用:
pip install brotlicffi
安装完成后重新运行原有代码,r.json()即可正常返回解析后的JSON数据。
方案2:修改请求头,禁用br压缩(无需安装额外依赖)
如果你不想安装第三方依赖,可以修改请求头中的Accept-Encoding字段,移除对br压缩的声明,服务端就不会返回br压缩的内容:
headers = { # 其余请求头保持不变,仅修改Accept-Encoding字段 "Accept-Encoding": "gzip, deflate", # 其他原有头信息保持原有配置即可 } r = requests.get(url, headers=headers) pprint(r.json())
requests原生支持gzip、deflate格式的自动解压,修改后即可正常拿到明文响应。
注意:不要手动读取
r.content调用解压方法处理,交给requests自动适配编码、分块传输的解析逻辑即可,手动处理很容易出现兼容问题。
内容的提问来源于stack exchange,提问作者eflat
相关产品推荐
相关产品推荐

