SerpBase 快照归档:zstd 压缩与月包校验
磁盘涨得比数据快
采集跑了一年,原始快照占了二十多个 GB。数据本身不大,膨胀的是「每条响应一个文件」的存法:几十万个小 JSON,目录列表都慢。
归档目标很明确:按月打包、压缩、留校验,需要时能精确恢复到某一天。
为什么选 zstd
gzip 兼容性最好,但压缩比和速度都一般;zstd 在同等级别下压缩比更高、解压更快,Python 有现成的 zstandard 库。
对一个两千万行的 JSON 语料,zstd 通常能压到原来的十分之一左右,具体比例和字段重复度有关,先拿一个月的数据实测再定 level。
月包:一个 tar.zst 加一份清单
按月打包,每个月产出一个 snapshots-2026-09.tar.zst 和一份 snapshots-2026-09.manifest.json。
清单里记三样:文件数、总字节数、包的 sha256。回滚和审计都靠它。
import hashlib
import json
import tarfile
from pathlib import Path
import zstandard as zstd
def build_month(files: list[Path], out_path: Path):
manifest = {"files": [], "count": len(files), "bytes": 0}
cctx = zstd.ZstdCompressor(level=10)
with open(out_path, "wb") as fh:
with cctx.stream_writer(fh) as zw:
with tarfile.open(fileobj=zw, mode="w|") as tar:
for p in files:
tar.add(p, arcname=p.name)
manifest["files"].append(p.name)
manifest["bytes"] += p.stat().st_size
digest = hashlib.sha256()
with open(out_path, "rb") as fh:
for chunk in iter(lambda: fh.read(1 << 20), b""):
digest.update(chunk)
manifest["sha256"] = digest.hexdigest()
out_path.with_suffix(".manifest.json").write_text(
json.dumps(manifest, ensure_ascii=False), encoding="utf-8"
)
mode="w|" 是流式写入,不需要先把整月数据读进内存。几十万文件也扛得住。
校验:别只看文件存在
归档最容易出的问题是「文件在,内容坏了」。校验分两层:
- 包级:sha256 和清单对得上
- 抽检:随机解出三个文件,
json.loads能解析、request_id字段存在
def spot_check(archive: Path, names: list[str]):
dctx = zstd.ZstdDecompressor()
with open(archive, "rb") as fh, dctx.stream_reader(fh) as zr:
with tarfile.open(fileobj=zr, mode="r|") as tar:
for member in tar:
if member.name in names:
data = json.loads(tar.extractfile(member).read())
assert data.get("request_id"), member.name
包级校验防传输损坏,抽检防序列化错误——两层都做,归档才算完成。
恢复:按天取,不整包解
恢复某一天的数据时,不需要把整月解压到磁盘:
zstd -dc snapshots-2026-09.tar.zst | tar -xO 2026-09-15.json > day.json
-O 直接输出到标准输出,一个文件一个文件取。小团队排查问题,这个操作比「解压整包再找」快得多。
我做错的一版
第一版按文件 gzip:每条响应一个 .json.gz。压缩率不错,但文件数量翻了一倍,ls 一屏刷不完,上传对象存储时逐个请求,光网络往返就花了半天。
改成月包之后,一个月一个文件,清单落在旁边,上传、校验、恢复都变成单文件操作。
归档的单位应该是「批次」,不是「原文件」。 想清楚这点,后面的维护成本会低一个量级。
现在每月 1 号跑一次归档,清单进数据库,原始小文件删掉。一次网页搜索 1 credit,新账号 500 免费 credits,攒数据容易,管数据才是长期功课。
SerpBase 的字段结构见 SerpBase 文档。

浙公网安备 33010602011771号