Python中Requests库如何处理gzip压缩问题?

requests 在请求的时候会自动使用 gizp 压缩,因为请求服务器不支持 gzip 怎么取消 gzip 压缩?
Python中Requests库如何处理gzip压缩问题?

20 回复

服务器不支持, response 的时候就是原始数据 客户端就自动使用原始数据。


在Python的Requests库中处理gzip压缩非常简单,因为库已经内置了自动解压支持。你基本什么都不用做,Requests会帮你搞定。

当你用Requests发送请求时,默认的请求头里就包含了 Accept-Encoding: gzip, deflate。这意味着你告诉服务器:“哥们,我能理解gzip和deflate压缩的数据,你发压缩的过来就行。”

服务器看到这个头,如果它支持并且内容适合压缩(比如文本),就会把响应体用gzip压缩后发回来,并在响应头里带上 Content-Encoding: gzip

关键就在这里:Requests收到响应后,会自动检查 Content-Encoding 头。如果发现是gzip或deflate,它会立刻、自动、默默地在后台把数据解压,然后把解压后的文本内容交给你。 你操作的 response.text 或者 response.content 就已经是解压后的原始数据了。

你感受不到压缩和解压的过程,整个过程对你是透明的。下面是个例子:

import requests

url = 'https://httpbin.org/gzip'  # 这个测试地址会返回gzip压缩的数据

response = requests.get(url)

# 检查响应头,确认服务器用了gzip压缩
print('响应头:', response.headers.get('Content-Encoding'))  # 输出: gzip

# 但你看,直接打印内容,已经是解压后的明文了
print('响应内容前100字符:', response.text[:100])

# 如果你想看原始的压缩字节流,可以用response.raw
# 但通常你不需要这么做

什么情况下需要手动处理? 极少数情况,比如你设置了 stream=True 进行流式传输,并且想自己处理原始压缩流,或者服务器错误地没有设置 Content-Encoding 头但数据确实是压缩的。这时你可以手动处理:

import requests
import gzip
import io

response = requests.get('https://some.url', stream=True)
# 假设你知道数据是gzip压缩的,但响应头里没有指明
compressed_data = response.raw.data

# 手动解压
buffer = io.BytesIO(compressed_data)
with gzip.GzipFile(fileobj=buffer, mode='rb') as f:
    decompressed_data = f.read()

print(decompressed_data.decode('utf-8'))

但再次强调,99.9%的情况下你不需要这么做。Requests的自动解压非常可靠,是默认且推荐的行为。你只需要知道有这么回事,别被“压缩”这个词吓到。

总结:Requests默认自动处理gzip,你直接用就行。

一楼正解。只要服务端正规来, response header 不申明 gzip 压缩客户端就不会解压缩

是 requests 发送数据到服务器的时候压缩了,服务器识别不了,直接返回错误了

使用的是 post

楼上几位是不是没理解?
提问者说的 requests 是一个库的名字,而不是和 response 对应的那个词

好像没听说过 HTTP 请求能压缩的……

楼上几位都没有错,你理解错了。客户端就是在这里就是指 requests 这个库, http 报文没有说用 gzip 那么 requests 就不会用 gzip 解压,会使用原始报文。上面几楼解释得相当浅白了。
至于 post 不接受 gzip, 此为一个解决方法可以参考 https://github.com/kennethreitz/requests/issues/1753

正常理解当然是 他用了 requests 库去请求 请求头里支持 gzip ,而服务器不支持 gzip 压缩,只能以原始数据回复。这并不影响使用


如果 client 希望 request 的 body 使用 gzip ,这个应该是非标准的。这也是为什么服务器会不支持。

requests 本身默认 post 数据不会使用 gzip 进行压缩

标准的返回会标识是否 gzip , reqiests 会根据这个标识来处理(是否 gzip 解压)

谢谢各位回答,我是初学 python 的,我感觉是不是我哪里弄错了

关于请求是否能压缩,前几年我还特地读过标准,是可以的,不过当年的 nginx 不支持……

你说的“ http 报文没有说用 gzip ”是什么?请用标准术语描述一遍

http 头部中的 Accept-Encoding 不带 gzip

上面说错了, requests 是根据 http 头部的 Content-Encoding 或者 Transfer-Encoding 来决定是否启用 gzip 。但是楼主现在不是这个情况,他是发送请求给服务器,服务器不支持 gzip 压缩,但是 requests 发出 POST 请求的时候却会自动启用 gzip 。

这样吧,我来用规范的语言表达一下我的意思
1 从标准的角度来说, HTTP 请求的 POST body 可以是压缩的(当然需要同时在 header 里声明)。但考虑到 HTTP 是一个先请求后响应的协议,服务器没办法提前声明自己的能力,所以正经客户端都不会发压缩的 POST 请求。我之前只遇到过某 android 模拟器会发压缩的
2 很多服务器不认识压缩的 POST body ,也没有义务认识
3 经过试验和阅读代码,我确认 python 的 requests 库在不指定的情况下,不会用压缩的方式发送 POST 请求
4 尝试了给 requests.post 增加 Content-Encoding:gzip 的 header ,但发出去的请求依然是原文
所以还是请 lz 先确认一下自己的问题是不是正确

我试过了,加这个 header 并不会使 requests 把需要 post 的数据先压缩了再发

Accept-Encoding 是客户端向服务器声明自己是否支持压缩用的,和 post body 没什么关系

回到顶部