基于Python实现简单的PDF批量压缩工具

作者:

文章目录
  • 在日常工作中,我们经常会遇到 PDF 文件太大、不便于传输或上传的问题。虽然网上有许多 PDF 压缩工具,但: 有些要付费 有些限制文件大小 有些需要上传到不可信的网站 因此,使用 Python + Ghostscript 自己写一个“本地 PDF 压缩工具”就非常有必要。 本文提供一个 完整的可运行脚本: 支持 单文件压缩 支持 批量扫描目录压缩(可逐个确认) 支持选择不同压缩等级 自动检测 Ghostscript 输出压缩结果总结 非常适合作为实用脚本收藏!
  • #!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import subprocess import sys import platform import shutil # ===== 配置 ===== BATCH_INPUT_DIR = “output_pdfs” # 批量模式默认扫描此文件夹 output_dir = “pdf_output” # 输出目录 # 压缩等级选项 COMPRESSION_LEVELS = { “1”: (“/screen”, “屏幕查看 (72dpi, 最小文件)”), “2”: (“/ebook”, “电子书 (150dpi, 平衡质量)”), “3”: (“/printer”, “打印 (300dpi, 高质量)”), “4”: (“/prepress”, “印刷 (300dpi+, 最高保真)”) } DEFAULT_LEVEL = “2” # ===== 交互式选择压缩等级 ===== def select_compression_level(): print(“n请选择压缩等级:”) for k, (_, desc) in COMPRESSION_LEVELS.items(): print(f” {k}. {desc}”) print(f”默认: {COMPRESSION_LEVELS[DEFAULT_LEVEL][1]}”) while True: choice = input(f”n请输入编号 (1-4) [回车默认 {DEFAULT_LEVEL}]: “).strip() if not choice: choice = DEFAULT_LEVEL if choice in COMPRESSION_LEVELS: level, desc = COMPRESSION_LEVELS[choice] print(f”n已选择: {desc}”) return level print(“无效输入,请输入 1-4”) # ===== 自动检测 Ghostscript ===== def find_gs_command(): system = platform.system() candidates = [“gs”] if system != “Windows” else [“gswin64c”, “gswin32c”, “gs”] for cmd in candidates: if shutil.which(cmd): return cmd return None gs_cmd = find_gs_command() if not gs_cmd: print(“未找到 Ghostscript!”) print(“n请先安装:”) if platform.system() == “Windows”: print(” 下载:https://www.ghostscript.com/download/gsdnld.html”) elif platform.system() == “Darwin”: print(” brew install ghostscript”) else: print(” sudo apt install ghostscript”) sys.exit(1) print(f”使用 Ghostscript: `{gs_cmd}`”) # ===== 选择输入:单文件 or 批量 ===== print(“n” + “=”*60) print(” PDF 压缩工具 – 逐个确认压缩”) print(“=”*60) input_path = input(f”n输入 PDF 文件路径(或回车扫描 `{BATCH_INPUT_DIR}`): “).strip() # 收集待处理文件 if input_path: if not os.path.exists(input_path): print(“文件不存在”) sys.exit(1) if not input_path.lower().endswith(“.pdf”): print(“仅支持 .pdf”) sys.exit(1) pdf_files = [(os.path.basename(input_path), input_path)] print(f”单文件模式: {input_path}”) else: if not os.path.isdir(BATCH_INPUT_DIR): print(f”目录不存在: {BATCH_INPUT_DIR}”) sys.exit(1) pdf_files = [ (f, os.path.join(BATCH_INPUT_DIR, f)) for f in os.listdir(BATCH_INPUT_DIR) if f.lower().endswith(“.pdf”) and os.path.isfile(os.path.join(BATCH_INPUT_DIR, f)) ] if not pdf_files: print(f”`{BATCH_INPUT_DIR}` 中无 PDF 文件”) sys.exit(0) print(f”批量模式: 共 {len(pdf_files)} 个文件”) # ===== 选择压缩等级 ===== compression_level = select_compression_level() # ===== 创建输出目录 ===== os.makedirs(output_dir, exist_ok=True) # ===== 逐个确认压缩 ===== failed = [] skipped = [] compressed = [] print(“n” + “-“*60) print(“开始处理(输入 y=压缩, n=跳过, a=全部压缩, q=退出)”) print(“-“*60) all_yes = False for idx, (filename, input_path) in enumerate(pdf_files, 1): if all_yes: action = ‘y’ else: while True: prompt = f”n[{idx}/{len(pdf_files)}] 压缩 ‘{filename}’? (y/n/a/q): ” action = input(prompt).strip().lower() if action in {‘y’, ‘n’, ‘a’, ‘q’}: break print(“请输入 y, n, a 或 q”) if action == ‘q’: print(“用户退出”) break if action == ‘n’: print(f”跳过: {filename}”) skipped.append(filename) continue if action == ‘a’: all_yes = True print(f”全部压缩(剩余 {len(pdf_files)-idx} 个)”) output_path = os.path.join(output_dir, filename) cmd = [ gs_cmd, “-sDEVICE=pdfwrite”, “-dCompatibilityLevel=1.4″, f”-dPDFSETTINGS={compression_level}”, “-dNOPAUSE”, “-dQUIET”, “-dBATCH”, f”-sOutputFile={output_path}”, input_path ] try: print(f”压缩中: {filename} …”, end=””) subprocess.run(cmd, check=True, capture_output=True, text=True) print(” 完成”) compressed.append(filename) except subprocess.CalledProcessError as e: print(f” 失败”) failed.append(filename) except Exception as e: print(f” 错误: {e}”) failed.append(filename) # ===== 最终总结 ===== total = len(pdf_files) done = len(compressed) + len(skipped) + len(failed) print(“n” + “=”*60) print(“压缩总结”) print(f” 总文件: {total}”) print(f” 已压缩: {len(compressed)}”) print(f” 已跳过: {len(skipped)}”) print(f” 失败: {len(failed)}”) if failed: print(f” 失败文件: {‘, ‘.join(failed)}”) if skipped: print(f” 跳过文件: {‘, ‘.join(skipped[:10])}{‘…’ if len(skipped)>10 else ”}”) print(f” 输出目录: {os.path.abspath(output_dir)}”) print(“=”*60)
  • Windows:下载地址 macOS brew install ghostscript Linux sudo apt install ghostscript
  • Q1:压缩后图片模糊怎么办? 使用 /printer 或 /prepress: 打印模式(300dpi) 印刷模式(最高质量)
  • 这是一个非常实用的 Python 工具脚本: 零依赖(只需要 Ghostscript) 支持批量、单文件 支持交互式选择 安全(完全本地) 以上就是基于Python实现简单的PDF批量压缩工具的详细内容,更多关于Python PDF压缩的资料请关注风君子博客其它相关文章! 您可能感兴趣的文章: Python+Ghostscript实现一个简单的PDF批量压缩工具(含进度条) Python批量处理PDF图片的操作指南(插入、压缩、提取、替换、分页、旋转、删除) Python高效实现PDF文件压缩的三大库使用指南 使用python实现PDF本地化压缩 使用python实现压缩PDF文件大小的方法 Python实现压缩pdf文件大小
  • 目录
    • 前言
    • 功能特点
      • 1. 支持四种压缩等级
      • 2. 支持两种输入模式
      • 3. 逐个确认压缩
      • 4. 自动检测 Ghostscript
    • 程序代码(可直接运行)
      • 安装 Ghostscript(必须)
        • 常见问题
          • 总结

            在日常工作中,我们经常会遇到 PDF 文件太大、不便于传输或上传的问题。虽然网上有许多 PDF 压缩工具,但:

            • 有些要付费
            • 有些限制文件大小
            • 有些需要上传到不可信的网站

            因此,使用 Python + Ghostscript 自己写一个“本地 PDF 压缩工具”就非常有必要。

            本文提供一个 完整的可运行脚本

            • 支持 单文件压缩
            • 支持 批量扫描目录压缩(可逐个确认)
            • 支持选择不同压缩等级
            • 自动检测 Ghostscript
            • 输出压缩结果总结

            非常适合作为实用脚本收藏!

            • /screen:最低质量,体积最小
            • /ebook:推荐,平衡质量
            • /printer:适合打印
            • /prepress:最高质量(印刷)

            • 输入文件路径 → 压缩单个 PDF
            • 直接回车 → 自动扫描 output_pdfs 目录批量处理

            每个文件你都可以选择:

            • y 压缩
            • n 跳过
            • a 剩余全部压缩
            • q 退出

            支持 Windows / macOS / Linux。

            #!/usr/bin/env python3
            # -*- coding: utf-8 -*-
            
            import os
            import subprocess
            import sys
            import platform
            import shutil
            
            # ===== 配置 =====
            BATCH_INPUT_DIR = "output_pdfs"     # 批量模式默认扫描此文件夹
            output_dir = "pdf_output"           # 输出目录
            
            # 压缩等级选项
            COMPRESSION_LEVELS = {
                "1": ("/screen",   "屏幕查看 (72dpi, 最小文件)"),
                "2": ("/ebook",    "电子书 (150dpi, 平衡质量)"),
                "3": ("/printer",  "打印 (300dpi, 高质量)"),
                "4": ("/prepress", "印刷 (300dpi+, 最高保真)")
            }
            DEFAULT_LEVEL = "2"
            
            # ===== 交互式选择压缩等级 =====
            def select_compression_level():
                print("n请选择压缩等级:")
                for k, (_, desc) in COMPRESSION_LEVELS.items():
                    print(f"  {k}. {desc}")
                print(f"默认: {COMPRESSION_LEVELS[DEFAULT_LEVEL][1]}")
            
                while True:
                    choice = input(f"n请输入编号 (1-4) [回车默认 {DEFAULT_LEVEL}]: ").strip()
                    if not choice:
                        choice = DEFAULT_LEVEL
                    if choice in COMPRESSION_LEVELS:
                        level, desc = COMPRESSION_LEVELS[choice]
                        print(f"n已选择: {desc}")
                        return level
                    print("无效输入,请输入 1-4")
            
            # ===== 自动检测 Ghostscript =====
            def find_gs_command():
                system = platform.system()
                candidates = ["gs"] if system != "Windows" else ["gswin64c", "gswin32c", "gs"]
                for cmd in candidates:
                    if shutil.which(cmd):
                        return cmd
                return None
            
            gs_cmd = find_gs_command()
            if not gs_cmd:
                print("未找到 Ghostscript!")
                print("n请先安装:")
                if platform.system() == "Windows":
                    print("   下载:https://www.ghostscript.com/download/gsdnld.html")
                elif platform.system() == "Darwin":
                    print("   brew install ghostscript")
                else:
                    print("   sudo apt install ghostscript")
                sys.exit(1)
            
            print(f"使用 Ghostscript: `{gs_cmd}`")
            
            # ===== 选择输入:单文件 or 批量 =====
            print("n" + "="*60)
            print("     PDF 压缩工具 - 逐个确认压缩")
            print("="*60)
            
            input_path = input(f"n输入 PDF 文件路径(或回车扫描 `{BATCH_INPUT_DIR}`): ").strip()
            
            # 收集待处理文件
            if input_path:
                if not os.path.exists(input_path):
                    print("文件不存在")
                    sys.exit(1)
                if not input_path.lower().endswith(".pdf"):
                    print("仅支持 .pdf")
                    sys.exit(1)
                pdf_files = [(os.path.basename(input_path), input_path)]
                print(f"单文件模式: {input_path}")
            else:
                if not os.path.isdir(BATCH_INPUT_DIR):
                    print(f"目录不存在: {BATCH_INPUT_DIR}")
                    sys.exit(1)
                pdf_files = [
                    (f, os.path.join(BATCH_INPUT_DIR, f))
                    for f in os.listdir(BATCH_INPUT_DIR)
                    if f.lower().endswith(".pdf") and os.path.isfile(os.path.join(BATCH_INPUT_DIR, f))
                ]
                if not pdf_files:
                    print(f"`{BATCH_INPUT_DIR}` 中无 PDF 文件")
                    sys.exit(0)
                print(f"批量模式: 共 {len(pdf_files)} 个文件")
            
            # ===== 选择压缩等级 =====
            compression_level = select_compression_level()
            
            # ===== 创建输出目录 =====
            os.makedirs(output_dir, exist_ok=True)
            
            # ===== 逐个确认压缩 =====
            failed = []
            skipped = []
            compressed = []
            
            print("n" + "-"*60)
            print("开始处理(输入 y=压缩, n=跳过, a=全部压缩, q=退出)")
            print("-"*60)
            
            all_yes = False
            
            for idx, (filename, input_path) in enumerate(pdf_files, 1):
                if all_yes:
                    action = 'y'
                else:
                    while True:
                        prompt = f"n[{idx}/{len(pdf_files)}] 压缩 '{filename}'? (y/n/a/q): "
                        action = input(prompt).strip().lower()
                        if action in {'y', 'n', 'a', 'q'}:
                            break
                        print("请输入 y, n, a 或 q")
            
                if action == 'q':
                    print("用户退出")
                    break
                if action == 'n':
                    print(f"跳过: {filename}")
                    skipped.append(filename)
                    continue
                if action == 'a':
                    all_yes = True
                    print(f"全部压缩(剩余 {len(pdf_files)-idx} 个)")
            
                output_path = os.path.join(output_dir, filename)
            
                cmd = [
                    gs_cmd,
                    "-sDEVICE=pdfwrite",
                    "-dCompatibilityLevel=1.4",
                    f"-dPDFSETTINGS={compression_level}",
                    "-dNOPAUSE",
                    "-dQUIET",
                    "-dBATCH",
                    f"-sOutputFile={output_path}",
                    input_path
                ]
            
                try:
                    print(f"压缩中: {filename} ...", end="")
                    subprocess.run(cmd, check=True, capture_output=True, text=True)
                    print(" 完成")
                    compressed.append(filename)
                except subprocess.CalledProcessError as e:
                    print(f" 失败")
                    failed.append(filename)
                except Exception as e:
                    print(f" 错误: {e}")
                    failed.append(filename)
            
            # ===== 最终总结 =====
            total = len(pdf_files)
            done = len(compressed) + len(skipped) + len(failed)
            
            print("n" + "="*60)
            print("压缩总结")
            print(f"   总文件: {total}")
            print(f"   已压缩: {len(compressed)}")
            print(f"   已跳过: {len(skipped)}")
            print(f"   失败: {len(failed)}")
            if failed:
                print(f"   失败文件: {', '.join(failed)}")
            if skipped:
                print(f"   跳过文件: {', '.join(skipped[:10])}{'...' if len(skipped)>10 else ''}")
            print(f"   输出目录: {os.path.abspath(output_dir)}")
            print("="*60)
            

            Windows:下载地址

            macOS

            brew install ghostscript
            

            Linux

            sudo apt install ghostscript
            

            Q1:压缩后图片模糊怎么办?

            使用 /printer/prepress

            • 打印模式(300dpi)
            • 印刷模式(最高质量)

            这是一个非常实用的 Python 工具脚本:

            • 零依赖(只需要 Ghostscript)
            • 支持批量、单文件
            • 支持交互式选择
            • 安全(完全本地)

            以上就是基于Python实现简单的PDF批量压缩工具的详细内容,更多关于Python PDF压缩的资料请关注风君子博客其它相关文章!

            您可能感兴趣的文章:

            • Python+Ghostscript实现一个简单的PDF批量压缩工具(含进度条)
            • Python批量处理PDF图片的操作指南(插入、压缩、提取、替换、分页、旋转、删除)
            • Python高效实现PDF文件压缩的三大库使用指南
            • 使用python实现PDF本地化压缩
            • 使用python实现压缩PDF文件大小的方法
            • Python实现压缩pdf文件大小

            站内搜索