🌐 English | 简体中文
在保持内容可读的前提下,批量把 PDF 文件压缩到目标大小比例(默认极限模式 25%)。 按文件类型自动选择最优压缩策略:矢量无损、扫描件降采样、单色线条图 1-bit 栅格化。
- 🎯 目标比例校准:自动把总大小压到指定比例(默认极限 25%,实测 86.3MB → 22.3MB)
- 🧠 按类型自动决策:分析每个文件的构成(图片/矢量/颜色/墨迹),选择最优策略
- 🛡️ 三重复保护:彩色文件跳过栅格化(不丢颜色);栅格化变大自动回滚;gs 膨胀自动回退无损
- 📄 保留文字层:矢量/文字文件默认保留可搜索文字;仅对纯单色图纸栅格化
- ✅ 自动验证:页数一致性、可打开性、空白页检测、文字保留率、总比例
- 📁 原文件不动:输出到独立子目录,文件名不变
真实案例:42 个工程投标 PDF(CAD 图纸 + 扫描件 + 文字文档),总 86.3MB。
| 档位 | 总大小 | 比例 | 策略 |
|---|---|---|---|
| 原始 | 86.3 MB | 100% | - |
| 保守 | 51.9 MB | 60% | 400dpi 1-bit × 2 文件 + gs 120dpi |
| 极限(默认) | 22.3 MB | 25% | 全部单色图 1-bit 300dpi + gs 100dpi |
典型文件压缩效果:
| 文件 | 原大小 | 极限后 | 方法 |
|---|---|---|---|
| 结构图 24 页 | 7.9 MB | 2.2 MB (27%) | 1-bit 300dpi |
| 建筑图 11 页 | 7.1 MB | 2.0 MB (28%) | 1-bit 300dpi |
| 设备布置 8 页 | 6.5 MB | 1.5 MB (23%) | 1-bit 300dpi |
| 区域位置图 | 2.4 MB | 680 KB (28%) | gs 100dpi(彩色保留) |
| 人力计划甘特图 | 971 KB | 295 KB (30%) | gs 100dpi(彩色保留) |
| 承诺书(公章) | 768 KB | 179 KB (23%) | gs 100dpi(红章保留) |
- Python 3.8+ 与依赖:
python -m pip install pymupdf - Ghostscript 10.x:Windows 安装包从 ArtifexSoftware/ghostpdl-downloads 下载
gs*64.exe,静默安装:./gs10071w64.exe /S - 已在 Windows 环境验证(Git Bash / Python subprocess)
# 1. 安装依赖
python -m pip install pymupdf
# 2. 极限压缩(默认 25%)
python scripts/compress_pdfs.py D:\PDF目录
# 3. 验证结果
python scripts/verify_pdfs.py D:\PDF目录 D:\PDF目录\压缩后输出在 D:\PDF目录\压缩后\,原文件不动。
python scripts/compress_pdfs.py <PDF目录> \
--target-ratio 25 \ # 目标比例,默认 25(实测极限)
--output-dir <PDF目录>/压缩后 \
--force-raster "附件17,附件36" # 可选: 强制栅格化(数字按附件编号精确匹配)python scripts/compress_pdfs.py <PDF目录> --target-ratio 60 --dpi 120 --raster-dpi 400| 参数 | 默认 | 说明 |
|---|---|---|
--target-ratio |
25 | 目标总大小比例 % |
--dpi |
100 | 图片降采样 DPI(极限) |
--raster-dpi |
300 | 1-bit 栅格化 DPI(图纸可读下限) |
--output-dir |
<输入>/压缩后 |
输出目录 |
--force-raster |
空 | 强制栅格化关键词 |
python scripts/analyze_pdfs.py <PDF目录>
# 输出: 页数/图像数/文本量/DPI/墨迹%/彩色% + 分类建议gs -dNOPAUSE -dBATCH -dQUIET -sDEVICE=pdfwrite -dCompatibilityLevel=1.5 \
-dPDFSETTINGS=/ebook \
-dColorImageResolution=100 -dGrayImageResolution=100 -dMonoImageResolution=300 \
-dColorImageDownsampleType=/Bicubic -dGrayImageDownsampleType=/Bicubic \
-sOutputFile=out.pdf in.pdf- 矢量文字层完整保留(可搜索)
- 效果:扫描件 20
50% / 矢量文字型 4595%
import fitz
doc = fitz.open(src)
doc.subset_fonts() # CID 字体子集化(如 SimSun)
doc.save(dst, garbage=4, deflate=True, clean=True)- gs 输出 ≥ 输入时自动使用(常见:CID 字体被完整嵌入)
- 效果:93~97%,零损失
gs pngmono -r300 → PyMuPDF 重建 → gs pdfwrite /printer 转 CCITT G4
- 条件:纯单色(彩色 < 0.1%)、栅格化后更小、接受失去文字层
- 效果:A0 图纸 4~28%;400dpi 更清晰但体积 +30%
- 为什么:JPEG 对线条图效率极差;1-bit CCITT G4 是线条图正确编码
- 全部文件先常规处理
- 未达标时按压缩后大小从大到小依次栅格化单色文件
- 三重保护:彩色跳过 / 变大回滚 / gs 膨胀回退无损
| 类型 | 极限状态 | 风险 |
|---|---|---|
| 图纸(300dpi 1-bit) | 与原始几乎无差别 | 无(行业归档标准) |
| 扫描件(100dpi) | 文字可读,放大有颗粒感 | 比 120dpi 略糊 |
| 彩色文件 | 颜色完整保留 | 从不栅格化 |
| 高墨迹文字表 | 保留 gs 方案 | 栅格化反而变大 |
80dpi 以下不可用(文字糊成一片)。 保守场景(招标)建议 120dpi + 400dpi 栅格化。
python scripts/verify_pdfs.py <原始目录> <压缩后目录> --target-ratio 25检查:文件数 / 可打开 / 页数一致 / 空白页 / 文字保留率 / 总比例
# 目视抽检(招标场景 ≥ 60% 文件)
import fitz, glob
for f in glob.glob('压缩后/*.pdf')[:N]:
doc = fitz.open(f)
pix = doc[0].get_pixmap(dpi=120)
pix.save(f'preview_{i:02d}.png') # 用英文短名,避免中文路径问题
doc.close()本仓库同时是一个 ZCode / Claude Code 风格的 AI 技能(Skill)包。
复制到 ~/.zcode/skills/pdf-batch-compress/ 后,模型会在用户提到"压缩 PDF / PDF 太大 / 批量减小 PDF"等需求时自动触发完整流程(分析 → 压缩 → 验证)。
pdf-batch-compress/
├── SKILL.md # 技能主文档
├── README.md # 本文档(中文)
├── README.en.md # 英文文档
├── scripts/
│ ├── analyze_pdfs.py # 分析 PDF 构成
│ ├── compress_pdfs.py # 主压缩(自动决策+校准)
│ └── verify_pdfs.py # 验证结果
└── references/
└── troubleshooting.md # 16 条实战坑点
MIT © Galo-Arc