Python+Ghostscript实现一个简单的PDF批量压缩工具(含进度条)

Written by

in

文章目录
  • 脚本主要做了以下几件事: 自动检测 Ghostscript 是否安装 扫描指定目录下所有 PDF 文件 根据文件总大小 智能推荐 压缩等级 用户可手动选择压缩模式(共 5 种) 逐个压缩 PDF 文件并显示进度条 统计压缩结果、计算压缩率、输出报告
  • Ghostscript (gs) 是一款强大的 PDF 与 PostScript 处理工具,几乎所有 PDF 压缩软件(包括 Adobe Acrobat)都基于它。 安装方式如下: Windows:官方下载地址 macOS(Homebrew): brew install ghostscript Linux(Debian/Ubuntu): sudo apt install ghostscript 安装完成后,执行命令验证: gs –version
  • 保存为 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批量压缩内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: Python高效实现PDF文件压缩的三大库使用指南 使用python实现PDF本地化压缩 Python批量处理PDF图片的操作指南(插入、压缩、提取、替换、分页、旋转、删除) 使用python实现压缩PDF文件大小的方法 Python实现压缩pdf文件大小 Python利用缓存流实现压缩PDF文件
  • 目录
    • 一、脚本功能概览
    • 二、Ghostscript 简介
    • 三、完整 Python 脚本
    • 四、压缩等级说明
    • 五、运行效果

    在日常工作中,我们经常会遇到 PDF 文件体积过大的问题:要么发邮件超出限制、要么上传系统被拒绝、要么手机查看太慢。

    手动一个个压缩不仅麻烦,还容易忘参数。今天分享一个用 Python + Ghostscript 实现的 自动批量压缩 PDF 脚本,支持:

    • 智能推荐压缩等级
    • 进度条显示
    • 记忆上次选择
    • 跨平台(Windows / macOS / Linux)

    脚本主要做了以下几件事:

    • 自动检测 Ghostscript 是否安装
    • 扫描指定目录下所有 PDF 文件
    • 根据文件总大小 智能推荐 压缩等级
    • 用户可手动选择压缩模式(共 5 种)
    • 逐个压缩 PDF 文件并显示进度条
    • 统计压缩结果、计算压缩率、输出报告

    Ghostscript (gs) 是一款强大的 PDF 与 PostScript 处理工具,几乎所有 PDF 压缩软件(包括 Adobe Acrobat)都基于它。

    安装方式如下:

    Windows:官方下载地址

    macOS(Homebrew):

    brew install ghostscript 

    Linux(Debian/Ubuntu):

    sudo apt install ghostscript 

    安装完成后,执行命令验证:

    gs --version

    保存为 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批量压缩内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

    您可能感兴趣的文章:

    • Python高效实现PDF文件压缩的三大库使用指南
    • 使用python实现PDF本地化压缩
    • Python批量处理PDF图片的操作指南(插入、压缩、提取、替换、分页、旋转、删除)
    • 使用python实现压缩PDF文件大小的方法
    • Python实现压缩pdf文件大小
    • Python利用缓存流实现压缩PDF文件

    站内搜索