批量提交 SERP API 查询,请求体动辄几百 KB。开启 gzip 压缩,带宽降 80%,处理更快。
1. 为什么压缩请求体
批量查询场景,请求体大:
json
{
"queries": [
{"q": "上海装修公司", "num": 10},
{"q": "北京装修公司", "num": 10},
// ... 1000 条
]
}
1000 条 query = 200KB+ 请求体。网络传输慢,服务端解析也慢。
2. gzip vs brotli
两种主流压缩:
| 格式 | 压缩率 | 压缩速度 | 解压速度 |
|---|---|---|---|
| gzip | 85-90% | 快 | 极快 |
| brotli | 88-93% | 中 | 快 |
兼容性:gzip 全支持,brotli 部分(新版浏览器 / 库支持)。
3. Python requests 压缩请求体
python
import gzip
import json
import requests
def search_compressed(queries):
"""gzip 压缩请求体"""
payload = json.dumps({'queries': queries}, ensure_ascii=False)
compressed = gzip.compress(payload.encode('utf-8'))
r = requests.post(
'https://api.example.com/google/search/batch',
headers={
'X-API-Key': os.environ['SERPBASE_API_KEY'],
'Content-Encoding': 'gzip', # 告诉服务端请求体是 gzip
'Content-Type': 'application/json'
},
data=compressed, # 传压缩后的字节
timeout=30
)
return r.json()
4. 服务端解压(FastAPI)
python
import gzip
from fastapi import FastAPI, Request
app = FastAPI()
@app.post('/google/search/batch')
async def search_batch(request: Request):
# 检查 Content-Encoding
encoding = request.headers.get('Content-Encoding', '')
body = await request.body()
if encoding == 'gzip':
# 解压
body = gzip.decompress(body)
data = json.loads(body)
# ... 处理批量查询
return process_batch(data['queries'])
5. httpx 自动压缩
httpx 支持自动请求压缩:
python
import httpx
# httpx 自动添加 Content-Encoding: gzip
r = httpx.post(
'https://api.example.com/google/search/batch',
headers={'X-API-Key': key},
json={'queries': queries},
timeout=30
)
部分 HTTP 库自动压缩,需确认。
6. 压缩效果实测
1000 条 query:
| 方式 | 请求体大小 | 传输时间(本地) | 服务端解析 |
|---|---|---|---|
| 未压缩 | 200KB | 40ms | 20ms |
| gzip | 25KB | 5ms | 25ms(+解压) |
| brotli | 18KB | 4ms | 30ms(+解压) |
带宽降 88%,传输降 8 倍。
7. 批量和流式结合
超大批量(10000 条),压缩 + 流式:
python
import gzip
import json
def search_huge_batch(queries, chunk_size=1000):
"""分块 + 压缩"""
for i in range(0, len(queries), chunk_size):
chunk = queries[i:i + chunk_size]
payload = json.dumps({'queries': chunk}, ensure_ascii=False)
compressed = gzip.compress(payload.encode('utf-8'))
r = requests.post(
'https://api.example.com/google/search/batch',
headers={'Content-Encoding': 'gzip'},
data=compressed
)
yield r.json()
# 10000 条,分 10 块,每块压缩传输
8. 压缩阈值
不是所有请求都该压缩。小请求压缩反而慢:
python
def should_compress(payload_bytes):
"""压缩阈值:> 4KB 才值得"""
return len(payload_bytes) > 4096
def smart_search(queries):
payload = json.dumps(queries, ensure_ascii=False).encode()
if should_compress(payload):
data = gzip.compress(payload)
headers = {'Content-Encoding': 'gzip'}
else:
data = payload
headers = {}
r = requests.post(url, headers=headers, data=data)
9. 响应压缩
不只请求,响应也可以压缩(SERP API 返回大 JSON):
python
r = requests.post(
url,
headers={'Accept-Encoding': 'gzip'}, # 请求 gzip 响应
json=payload
)
# requests 自动解压(如果服务端返回 gzip)
10. 监控
python
from prometheus_client import Counter
bytes_sent = Counter('serp_request_bytes', 'Request bytes', ['compressed'])
def monitored_search(queries):
payload = json.dumps(queries, ensure_ascii=False).encode()
if should_compress(payload):
data = gzip.compress(payload)
bytes_sent.labels(compressed='yes').inc(len(data))
else:
data = payload
bytes_sent.labels(compressed='no').inc(len(data))
11. 实战:30 天数据
跑 30 天批量压缩:
| 指标 | 未压缩 | gzip |
|---|---|---|
| 带宽 | 20GB/月 | 2.4GB/月 |
| 平均传输 | 40ms | 5ms |
| 服务端错误 | 0.3% | 0.1% |
| 成本 | - | 降 88% 带宽 |
12. 常见坑
坑 1:请求压缩但 Content-Encoding 头漏了,服务端把压缩字节当 JSON 解析 → 400。
坑 2:gzip.decompress 在超大 body 内存峰值高。用流式 gzip 解压:
python
import gzip
from io import BytesIO
def decompress_stream(body):
"""流式解压,不一次性加载"""
with gzip.GzipFile(fileobj=BytesIO(body)) as gz:
return json.load(gz)
坑 3:响应自动解压 vs 手动解压混淆(requests 默认自动解压响应)。
13. 总结
请求压缩 3 个要点:
- gzip 压缩请求体 + Content-Encoding 头
- 4KB 以上才值得压缩
- 批量 + 流式组合,超大请求分块
带宽降 88%,批量场景明显提速。
参考文档
本文 API 示例参考 serpbase 文档(serpbase.dev/docs),接口路径、参数和返回字段以官方文档为准。