Python+Ghostscript实现一个简单的PDF批量压缩工具(含进度条)
作者:weixin_46244623
在日常工作中,我们经常会遇到 PDF 文件体积过大的问题,手动一个个压缩不仅麻烦,还容易忘参数,今天分享一个用 Python + Ghostscript 实现的 自动批量压缩 PDF 脚本,有需要的可以了解下
在日常工作中,我们经常会遇到 PDF 文件体积过大的问题:要么发邮件超出限制、要么上传系统被拒绝、要么手机查看太慢。
手动一个个压缩不仅麻烦,还容易忘参数。今天分享一个用 Python + Ghostscript 实现的 自动批量压缩 PDF 脚本,支持:
- 智能推荐压缩等级
- 进度条显示
- 记忆上次选择
- 跨平台(Windows / macOS / Linux)
一、脚本功能概览
脚本主要做了以下几件事:
- 自动检测 Ghostscript 是否安装
- 扫描指定目录下所有 PDF 文件
- 根据文件总大小 智能推荐 压缩等级
- 用户可手动选择压缩模式(共 5 种)
- 逐个压缩 PDF 文件并显示进度条
- 统计压缩结果、计算压缩率、输出报告
二、Ghostscript 简介
Ghostscript (gs) 是一款强大的 PDF 与 PostScript 处理工具,几乎所有 PDF 压缩软件(包括 Adobe Acrobat)都基于它。
安装方式如下:
Windows:官方下载地址
macOS(Homebrew):
brew install ghostscript
Linux(Debian/Ubuntu):
sudo apt install ghostscript
安装完成后,执行命令验证:
gs --version
三、完整 Python 脚本
保存为 pdf_compress.py:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os, subprocess, sys, platform, shutil, json
from tqdm import tqdm
# ===== 配置 =====
input_dir = "output_pdfs" # 待压缩PDF目录
output_dir = "pdf_output" # 输出目录
config_file = "compress_config.json" # 保存上次选择
# ===== 压缩等级定义 =====
COMPRESSION_LEVELS = {
"1": { "name": "屏幕 (72dpi)", "level": "/screen", "desc": "网页/手机,超小文件" },
"2": { "name": "电子书 (150dpi)", "level": "/ebook", "desc": "阅读,平衡大小" },
"3": { "name": "打印 (300dpi)", "level": "/printer", "desc": "打印,高清" },
"4": { "name": "印刷 (300+dpi)", "level": "/prepress", "desc": "专业印刷,保真" },
"5": { "name": "无损优化", "level": "/default", "desc": "仅优化结构,不降质量" }
}
# ===== 保存/加载配置 =====
def load_last_config():
try:
with open(config_file, 'r') as f:
return json.load(f).get('level', '2')
except:
return '2'
def save_config(level):
with open(config_file, 'w') as f:
json.dump({'level': level}, f)
# ===== 工具函数 =====
def get_file_size_mb(path):
try:
return os.path.getsize(path) / (1024 * 1024)
except:
return 0
def recommend_level(pdf_files):
total_size = sum(get_file_size_mb(os.path.join(input_dir, f)) for f in pdf_files)
if total_size > 50:
return "1"
elif total_size > 10:
return "2"
else:
return "3"
# ===== 检测 Ghostscript =====
def find_gs_command():
system = platform.system()
candidates = ["gswin64c", "gswin32c", "gs"] if system == "Windows" else ["gs"]
for cmd in candidates:
if shutil.which(cmd):
return cmd
return None
gs_cmd = find_gs_command()
if not gs_cmd:
print("❌ 未找到 Ghostscript!请先安装。")
sys.exit(1)
print(f"✅ Ghostscript: `{gs_cmd}`")
os.makedirs(output_dir, exist_ok=True)
# ===== 获取 PDF 文件 =====
pdf_files = [f for f in os.listdir(input_dir)
if f.lower().endswith(".pdf") and os.path.isfile(os.path.join(input_dir, f))]
if not pdf_files:
print(f"❌ `{input_dir}` 中未找到 PDF 文件")
sys.exit(0)
total_size = sum(get_file_size_mb(os.path.join(input_dir, f)) for f in pdf_files)
print(f"📁 发现 {len(pdf_files)} 个 PDF,总大小: {total_size:.1f}MB")
# ===== 选择压缩等级 =====
print("\n" + "="*60)
print("📋 请选择压缩等级 (上次选择: {})".format(load_last_config()))
print("="*60)
for key, info in COMPRESSION_LEVELS.items():
print(f" {key}. {info['name']} - {info['desc']}")
print("="*60)
recommended = recommend_level(pdf_files)
print(f"🤖 智能推荐: {recommended} (基于文件大小)")
while True:
choice = input("\n请输入编号 (1-5): ").strip()
if choice in COMPRESSION_LEVELS:
compression_level = COMPRESSION_LEVELS[choice]["level"]
selected_name = COMPRESSION_LEVELS[choice]["name"]
save_config(choice)
break
else:
print("❌ 请输入 1-5")
print(f"\n🎯 确认使用: {selected_name}")
# ===== 批量压缩 =====
failed = []
pbar = tqdm(pdf_files, desc="压缩进度", unit="文件")
for pdf_file in pbar:
input_path = os.path.join(input_dir, pdf_file)
output_path = os.path.join(output_dir, pdf_file)
pbar.set_postfix({"文件": pdf_file[:30]})
cmd = [
gs_cmd, "-sDEVICE=pdfwrite", "-dCompatibilityLevel=1.4",
f"-dPDFSETTINGS={compression_level}", "-dNOPAUSE", "-dQUIET", "-dBATCH",
f"-sOutputFile={output_path}", input_path
]
try:
subprocess.run(cmd, check=True, capture_output=True)
except subprocess.CalledProcessError:
failed.append(pdf_file)
# ===== 输出结果 =====
success = len(pdf_files) - len(failed)
orig_total = sum(get_file_size_mb(os.path.join(input_dir, f)) for f in pdf_files)
comp_total = sum(get_file_size_mb(os.path.join(output_dir, f)) for f in os.listdir(output_dir) if f.lower().endswith('.pdf'))
print("\n" + "="*60)
print("🎉 压缩完成!")
print("="*60)
print(f"📊 成功: {success}/{len(pdf_files)}")
print(f"📦 原始: {orig_total:.1f}MB → 压缩后: {comp_total:.1f}MB")
print(f"📉 压缩率: {((orig_total-comp_total)/orig_total*100):.1f}%")
print(f"📁 输出目录: {os.path.abspath(output_dir)}")
if failed:
print(f"\n❌ 失败文件 ({len(failed)}):")
for f in failed:
print(f" - {f}")
print("="*60)
四、压缩等级说明
| 等级 | 模式 | 分辨率 | 说明 |
|---|---|---|---|
| 1 | /screen | 72dpi | 适合网页、手机端,体积最小 |
| 2 | /ebook | 150dpi | 适合电子阅读,画质平衡 |
| 3 | /printer | 300dpi | 打印清晰,常用推荐 |
| 4 | /prepress | 300+dpi | 出版印刷级 |
| 5 | /default | 无损 | 不降质,仅结构优化 |
五、运行效果
运行:
python3 pdf_compress.py
输出示例:
✅ Ghostscript: `gs`
📁 发现 8 个 PDF,总大小: 42.5MB
🤖 智能推荐: 2 (基于文件大小)
🎯 确认使用: 电子书 (150dpi)
压缩进度: 100%|████████████████████| 8/8 [00:12<00:00, 0.65文件/s]
🎉 压缩完成!
📦 原始: 42.5MB → 压缩后: 15.3MB
📉 压缩率: 64.0%
📁 输出目录: /home/user/pdf_output
到此这篇关于Python+Ghostscript实现一个简单的PDF批量压缩工具(含进度条)的文章就介绍到这了,更多相关Python PDF批量压缩内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
