压缩HTTP请求正文
当我们在 Web 服务器上启动 gzip 压缩后,会极大提高加载网页的速度。 同样,将 gzip 用于发送 HTTP 请求,也可以加快请求的响应速度。
gzip库
Python 内置标准库 gzip,像 GNU 程序 gzip 和 gunzip 一样提供文件压缩和解压缩功能。 Python 2 和 Python 3 的使用方法略有不同。
Python 2
需要使用 StringIO
模块的 StringIO
类,创建 StringIO
对象当做一个文件,传给 gzip 的 GzipFile
对象,GzipFile
会将字符串压缩后写入 StringIO
对象。
使用 getvalue
方法从 StringIO
中获取压缩后的字符串。
s = StringIO.StringIO()
g = gzip.GzipFile(fileobj=s, mode='w')
g.write(post_data)
g.close()
gzipped_data = s.getvalue()
Python 3
Python 3 的 gzip 库提供更方面的 compress
和 decompress
函数,可以直接压缩/解压缩字符串(bytes)。
gzipped_data = gzip.compress(bytes(post_data), 'utf-8'))
解压缩
post_data = gzip.decompress(gzipped_data).decode('utf-8'))
使用Requests发送压缩的请求
发送经 gzip 压缩过的 HTTP 请求时,需要将 HTTP 头属性 content-encoding
设为 gzip。
使用 Requests 可以用下面的方式发送请求:
response = requests.post(url, data=gzipped_data, headers={
'content-encoding': 'gzip'
})
使用Flask接收压缩的请求
接收经 gzip 压缩过的 HTTP 请求时,需要使用 gzip 对数据解压。
在 Flask 中需要检测请求 request 的 headers
属性中的 content-encoding
属性是否为 gzip。
如果是,则需要调用 gzip 模块对请求数据 request.data
进行解压。
content_encoding = request.headers.get('content-encoding', '').lower()
if content_encoding == 'gzip':
gzipped_data = request.data
data_string = gzip.decompress(gzipped_data)
body = json.loads(data_string.decode('utf-8'))
else:
body = request.form
上面代码中接收的是压缩过的 json 字符串。
效率测试
下面是做得一个测试,向阿里云服务器发送HTTPS请求,同样的数据对比压缩前和压缩后的响应时间。
第一组
方式 | 长度 | 占用空间 | 时间 (秒) |
---|---|---|---|
原始 | 2206325 | 2.2MB | 2.592873 |
gzip | 74111 | 75KB | 0.162942 |
另一组
方式 | 长度 | 占用空间 | 时间 (秒) |
---|---|---|---|
原始 | 631433 | 631KB | 0.322468 |
gzip | 34018 | 34KB | 0.083316 |
从上面两组可以看到,使用 gzip 压缩数据可以大量减少整个请求的响应时间。 相对于压缩解压缩所需要的额外时间,带宽才是更关键的制约因素,所以减少传输的数据量对提高速度至关重要。