Python实现HTTP上行请求体的gzip压缩

 更新时间:2026年07月29日 08:33:15   作者:detayun  
本文介绍了如何在Python中实现HTTP请求体的gzip压缩,通过自定义压缩函数和请求头Content-Encoding: gzip来实现,文章提供了多种HTTP客户端的实现示例,有需要的小伙伴可以参考下

前言

先重申核心原理:上行请求体压缩不是HTTP库自带功能,本质是你自己把body gzip压缩,带上 Content-Encoding: gzip 请求头,将压缩二进制作为请求体发送。

所有支持自定义请求body、自定义请求头的HTTP客户端都能实现,区别只是各个库传参名称不一样:

  • requests:data=
  • httpx:content=
  • aiohttp:data=
  • urllib:data=
  • pycurl:POSTFIELDS

下面分「同步库」「异步库」给出完整示例,统一复用gzip压缩函数。

通用压缩工具函数(所有示例共用)

import gzip
from io import BytesIO

def gzip_compress(raw_bytes: bytes) -> bytes:
    buf = BytesIO()
    with gzip.GzipFile(fileobj=buf, mode="wb") as f:
        f.write(raw_bytes)
    return buf.getvalue()

一、标准库:urllib(无需额外安装,内置)

无需安装第三方包,适合环境受限不能装requests的场景

import json
from urllib import request

url = "http://127.0.0.1:8000/api/upload"
payload = {"data": list(range(2000))}
raw = json.dumps(payload).encode("utf-8")
compressed_body = gzip_compress(raw)

headers = {
    "Content-Type": "application/json; charset=utf-8",
    "Content-Encoding": "gzip"
}

req = request.Request(url, data=compressed_body, headers=headers, method="POST")
with request.urlopen(req) as resp:
    print(resp.read().decode("utf-8"))

缺点:API简陋,不支持连接池、超时易用性差,生产一般不首选。

二、httpx(同步 + 异步,当前主流推荐)

新一代HTTP客户端,兼容requests风格,支持http1.1/http2

import httpx
import json

url = "http://127.0.0.1:8000/api/upload"
payload = {"data": list(range(2000))}
raw = json.dumps(payload).encode("utf-8")
compressed_body = gzip_compress(raw)

headers = {
    "Content-Type": "application/json; charset=utf-8",
    "Content-Encoding": "gzip"
}

# 同步
with httpx.Client(timeout=10) as client:
    res = client.post(url, headers=headers, content=compressed_body)
    print(res.text)

# 异步版本
"""
import asyncio
async def run():
    async with httpx.AsyncClient(timeout=10) as client:
        res = await client.post(url, headers=headers, content=compressed_body)
        print(res.text)
asyncio.run(run())
"""

httpx 传二进制body参数名是 content,不是data!

三、aiohttp(异步首选,高并发场景)

异步生态标准HTTP客户端,爬虫、异步微服务大量使用

import aiohttp
import asyncio
import json

async def main():
    url = "http://127.0.0.1:8000/api/upload"
    payload = {"data": list(range(2000))}
    raw = json.dumps(payload).encode("utf-8")
    compressed_body = gzip_compress(raw)

    headers = {
        "Content-Type": "application/json; charset=utf-8",
        "Content-Encoding": "gzip"
    }
    async with aiohttp.ClientSession() as session:
        async with session.post(url, data=compressed_body, headers=headers) as resp:
            print(await resp.text())

asyncio.run(main())

四、pycurl(底层封装libcurl,高性能)

基于C库libcurl,吞吐性能极强,适合超高并发场景;缺点:Windows安装麻烦、API晦涩

import pycurl
import json
from io import BytesIO

url = "http://127.0.0.1:8000/api/upload"
payload = {"data": list(range(2000))}
raw = json.dumps(payload).encode("utf-8")
compressed_body = gzip_compress(raw)

resp_buffer = BytesIO()
c = pycurl.Curl()
c.setopt(c.URL, url)
c.setopt(c.POST, 1)
c.setopt(c.POSTFIELDS, compressed_body)
c.setopt(c.WRITEDATA, resp_buffer)

headers = [
    "Content-Type: application/json; charset=utf-8",
    "Content-Encoding: gzip"
]
c.setopt(c.HTTPHEADER, headers)
c.perform()
c.close()

print(resp_buffer.getvalue().decode())

五、tornado.httpclient(Tornado框架内置异步客户端)

如果你项目本身使用Tornado Web框架,可以直接使用内置客户端,无需额外依赖

import json
from tornado.httpclient import AsyncHTTPClient, HTTPRequest
import tornado.ioloop

async def fetch():
    url = "http://127.0.0.1:8000/api/upload"
    payload = {"data": list(range(2000))}
    raw = json.dumps(payload).encode("utf-8")
    compressed_body = gzip_compress(raw)

    req = HTTPRequest(
        url,
        method="POST",
        body=compressed_body,
        headers={
            "Content-Type": "application/json; charset=utf-8",
            "Content-Encoding": "gzip"
        }
    )
    client = AsyncHTTPClient()
    res = await client.fetch(req)
    print(res.body.decode())

tornado.ioloop.IOLoop.current().run_sync(fetch)

关键共性注意事项(所有库通用)

不要使用框架自带json参数:例如 httpx.post(json={})requests.post(json={}),这类接口会自动编码,无法替换成压缩二进制,必须手动序列化+使用原始body参数。

下行压缩 ≠ 上行压缩:

  • Accept-Encoding 只是告诉服务端:我能接收压缩响应;
  • Content-Encoding: gzip 才代表:本次请求body已经压缩。

服务端必须手动解压:绝大多数Web框架默认不会自动解压带有Content-Encoding的请求体,缺少解压代码会直接收到乱码二进制。

库选型建议

  1. 新项目、同步+异步都需要 → httpx
  2. 纯异步高并发服务/爬虫 → aiohttp
  3. 不能安装第三方包、极简环境 → urllib(标准库)
  4. 极致性能、熟悉libcurl → pycurl
  5. 老旧项目维持现状 → requests

到此这篇关于Python实现HTTP上行请求体的gzip压缩的文章就介绍到这了,更多相关Python HTTP请求体压缩内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python使用正则表达式获取网页中所需要的信息

    Python使用正则表达式获取网页中所需要的信息

    这篇文章主要介绍了Python使用正则获取网页中所需要的信息的相关资料,需要的朋友可以参考下
    2018-01-01
  • python安装virtualenv虚拟环境步骤图文详解

    python安装virtualenv虚拟环境步骤图文详解

    这篇文章主要介绍了python安装virtualenv虚拟环境步骤,本文通过图文并茂的形式给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-09-09
  • Python数据库sqlite3图文实例详解

    Python数据库sqlite3图文实例详解

    SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的SQL数据库引擎,下面这篇文章主要给大家介绍了关于Python数据库sqlite3的相关资料,需要的朋友可以参考下
    2022-09-09
  • pyqt5 实现多窗口跳转的方法

    pyqt5 实现多窗口跳转的方法

    今天小编就为大家分享一篇pyqt5 实现多窗口跳转的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-06-06
  • 使用Python读取.nc文件的方法详解

    使用Python读取.nc文件的方法详解

    .nc文件,即NetCDF(Network Common Data Form)文件,是一种用于存储科学数据的文件格式,本文主要为大家介绍了两种常见的读取方法,希望对大家有所帮助
    2024-03-03
  • 如何用Python合并lmdb文件

    如何用Python合并lmdb文件

    这篇文章主要为大家详细介绍了如何用Python合并lmdb文件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-07-07
  • python去除字符串中换行符的四种方法

    python去除字符串中换行符的四种方法

    python中换行符的作用就是将字符串划分为上下两行去输出显示,但是在有些情况下是不需要去用到换行符的,这个时候就要用方法将其给去除掉,这一篇文章小编会来给大家介绍一下python去除字符串中换行符的方法,感兴趣的话就一起往下看看吧
    2024-04-04
  • Python实现PS图像明亮度调整效果示例

    Python实现PS图像明亮度调整效果示例

    这篇文章主要介绍了Python实现PS图像明亮度调整效果,结合实例形式分析了Python基于skimage模块调整图片明亮度的原理与具体操作技巧,需要的朋友可以参考下
    2018-01-01
  • python实时监控cpu小工具

    python实时监控cpu小工具

    这篇文章主要为大家详细介绍了python实时监控cpu的小工具,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • Python字符串拼接的几种方法整理

    Python字符串拼接的几种方法整理

    这篇文章主要介绍了Python字符串拼接的几种方法整理的相关资料,这里提供了五种方法及实现,需要的朋友可以参考下
    2017-08-08

最新评论