使用python调用podofogc文件 批量处理 pdf文件

文章目录

python 复制代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
批量使用podofogc处理PDF文件 - 简化版
功能:遍历顶级目录及子目录中的所有PDF,调用podofogc进行垃圾清理(GC),保存到另一个目录
"""

import subprocess
import time
from pathlib import Path
from typing import Dict, List

# ==================== 配置参数(直接修改这里) ====================
PODOFO_GC_PATH = r"D:\PDF_SOURCE\podofo_测试清理未使用对象\podofo_exe\podofogc.exe"  # podofogc.exe的路径
INPUT_DIR = r"D:\3_30\pdfcore2.0\input"      # 输入顶级目录
OUTPUT_DIR = r"D:\3_30\pdfcore2.0\output"    # 输出顶级目录
RECURSIVE = True                              # 是否递归子目录
PRESERVE_STRUCTURE = True                     # 是否保留目录结构(True:保留, False:所有文件直接输出到根目录)
OVERWRITE = False                             # 是否覆盖已存在的文件(False:跳过已存在的文件)
# =================================================================


class PodofoGCProcessor:
    """Podofo GC批量处理器"""
    
    def __init__(self):
        """初始化处理器"""
        self.podofo_gc_path = Path(PODOFO_GC_PATH)
        self.input_dir = Path(INPUT_DIR)
        self.output_dir = Path(OUTPUT_DIR)
        self.recursive = RECURSIVE
        self.preserve_structure = PRESERVE_STRUCTURE
        self.overwrite = OVERWRITE
        
        # 验证podofogc是否存在
        if not self.podofo_gc_path.exists():
            raise FileNotFoundError(f"找不到podofogc程序: {self.podofo_gc_path}")
        
        # 验证输入目录
        if not self.input_dir.exists():
            raise FileNotFoundError(f"输入目录不存在: {self.input_dir}")
        
        # 创建输出目录
        self.output_dir.mkdir(parents=True, exist_ok=True)
        
        # 统计信息
        self.stats = {
            'total': 0,
            'success': 0,
            'failed': 0,
            'skipped': 0,
            'input_size_total': 0,
            'output_size_total': 0
        }
    
    def get_pdf_files(self) -> List[Path]:
        """获取所有需要处理的PDF文件"""
        if self.recursive:
            # 递归查找所有PDF文件
            pdf_files = list(self.input_dir.glob("**/*.pdf"))
        else:
            # 只在当前目录查找
            pdf_files = list(self.input_dir.glob("*.pdf"))
        
        # 按路径排序,保持一致性
        pdf_files.sort()
        return pdf_files
    
    def get_output_path(self, input_path: Path) -> Path:
        """根据输入路径计算输出路径"""
        if self.preserve_structure:
            # 保留目录结构
            relative_path = input_path.relative_to(self.input_dir)
            output_path = self.output_dir / relative_path
        else:
            # 平坦结构,所有文件直接放在输出目录
            output_path = self.output_dir / input_path.name
        
        return output_path
    
    def process_single_file(self, input_path: Path) -> Dict:
        """处理单个PDF文件"""
        result = {
            'input': input_path,
            'output': None,
            'success': False,
            'error': None,
            'input_size': 0,
            'output_size': 0
        }
        
        try:
            # 获取输出路径
            output_path = self.get_output_path(input_path)
            result['output'] = output_path
            
            # 创建输出目录
            output_path.parent.mkdir(parents=True, exist_ok=True)
            
            # 检查输出文件是否已存在
            if output_path.exists() and not self.overwrite:
                result['error'] = "输出文件已存在,跳过"
                return result
            
            # 获取输入文件大小
            input_size = input_path.stat().st_size
            result['input_size'] = input_size
            
            print(f"处理: {input_path.name}")
            print(f"  源文件: {input_path}")
            print(f"  目标文件: {output_path}")
            
            # 构建命令: podofogc.exe input.pdf output.pdf
            cmd = [
                str(self.podofo_gc_path),
                str(input_path),
                str(output_path)
            ]
            
            # 执行命令
            start_time = time.time()
            process = subprocess.run(
                cmd,
                capture_output=True,
                text=True,
                encoding='utf-8',
                errors='ignore',
                timeout=300  # 5分钟超时
            )
            elapsed_time = time.time() - start_time
            
            if process.returncode == 0:
                # 成功
                output_size = output_path.stat().st_size if output_path.exists() else 0
                result['output_size'] = output_size
                result['success'] = True
                
                # 计算压缩率
                if input_size > 0:
                    compression_ratio = (1 - output_size/input_size) * 100
                else:
                    compression_ratio = 0
                
                print(f"  ✓ 成功! 耗时: {elapsed_time:.1f}s")
                print(f"    大小: {input_size/1024:.1f}KB -> {output_size/1024:.1f}KB (压缩率: {compression_ratio:.1f}%)")
            else:
                # 失败
                error_msg = process.stderr if process.stderr else process.stdout
                result['error'] = error_msg or f"返回码: {process.returncode}"
                print(f"  ✗ 失败: {result['error'][:100]}")
                
        except subprocess.TimeoutExpired:
            result['error'] = "处理超时(超过5分钟)"
            print(f"  ✗ 超时: {input_path.name}")
        except Exception as e:
            result['error'] = str(e)
            print(f"  ✗ 异常: {e}")
        
        return result
    
    def process_all(self) -> Dict:
        """批量处理所有PDF文件"""
        # 获取所有PDF文件
        print(f"\n{'='*60}")
        print(f"扫描目录: {self.input_dir}")
        pdf_files = self.get_pdf_files()
        
        if not pdf_files:
            print(f"未找到任何PDF文件!")
            return self.stats
        
        self.stats['total'] = len(pdf_files)
        print(f"找到 {len(pdf_files)} 个PDF文件")
        print(f"输出目录: {self.output_dir}")
        print(f"保留目录结构: {self.preserve_structure}")
        print(f"覆盖已存在文件: {self.overwrite}")
        print(f"{'='*60}\n")
        
        # 开始处理
        start_time = time.time()
        
        for i, pdf_file in enumerate(pdf_files, 1):
            print(f"\n[{i}/{len(pdf_files)}] 处理中...")
            result = self.process_single_file(pdf_file)
            
            if result['success']:
                self.stats['success'] += 1
                self.stats['input_size_total'] += result['input_size']
                self.stats['output_size_total'] += result['output_size']
            elif result['error'] and "跳过" in result['error']:
                self.stats['skipped'] += 1
                print(f"  ⊙ 跳过: {result['error']}")
            else:
                self.stats['failed'] += 1
        
        elapsed_time = time.time() - start_time
        self._print_summary(elapsed_time)
        
        return self.stats
    
    def _print_summary(self, elapsed_time: float):
        """打印处理总结"""
        print(f"\n{'='*60}")
        print("处理完成!统计信息:")
        print(f"  总文件数: {self.stats['total']}")
        print(f"  成功: {self.stats['success']}")
        print(f"  失败: {self.stats['failed']}")
        print(f"  跳过: {self.stats['skipped']}")
        
        if self.stats['success'] > 0:
            input_mb = self.stats['input_size_total'] / (1024 * 1024)
            output_mb = self.stats['output_size_total'] / (1024 * 1024)
            saved_mb = input_mb - output_mb
            compression_ratio = (saved_mb / input_mb) * 100 if input_mb > 0 else 0
            
            print(f"  总输入大小: {input_mb:.2f} MB")
            print(f"  总输出大小: {output_mb:.2f} MB")
            print(f"  节省空间: {saved_mb:.2f} MB ({compression_ratio:.1f}%)")
        
        print(f"  总耗时: {elapsed_time:.1f} 秒")
        print(f"{'='*60}")


def main():
    """主函数"""
    try:
        # 创建处理器并执行
        processor = PodofoGCProcessor()
        stats = processor.process_all()
        
        # 根据结果返回退出码
        return 0 if stats['failed'] == 0 else 1
        
    except Exception as e:
        print(f"程序执行失败: {e}")
        return 1


if __name__ == "__main__":
    exit(main())

使用方法

1. 直接修改配置参数

打开脚本,修改开头的配置部分:

python 复制代码
# ==================== 配置参数(直接修改这里) ====================
PODOFO_GC_PATH = r"D:\PDF_SOURCE\podofo_测试清理未使用对象\podofo_exe\podofogc.exe"
INPUT_DIR = r"D:\3_30\pdfcore2.0\input"
OUTPUT_DIR = r"D:\3_30\pdfcore2.0\output"
RECURSIVE = True                              # True:递归子目录, False:只处理当前目录
PRESERVE_STRUCTURE = True                     # True:保留目录结构, False:所有文件直接输出
OVERWRITE = False                             # True:覆盖已存在文件, False:跳过已存在文件
# =================================================================

2. 运行脚本

bash 复制代码
python pdf_gc_batch.py

极简版本(如果只想快速使用)

如果您想要更简单的代码,这是最小化版本:

python 复制代码
import subprocess
from pathlib import Path

# 配置路径
PODOFO_GC = r"D:\PDF_SOURCE\podofo_测试清理未使用对象\podofo_exe\podofogc.exe"
INPUT_DIR = r"D:\3_30\pdfcore2.0\input"
OUTPUT_DIR = r"D:\3_30\pdfcore2.0\output"

# 创建输出目录
Path(OUTPUT_DIR).mkdir(parents=True, exist_ok=True)

# 遍历所有PDF
success = 0
failed = 0

for pdf_file in Path(INPUT_DIR).glob("**/*.pdf"):
    # 计算输出路径(保留目录结构)
    relative_path = pdf_file.relative_to(INPUT_DIR)
    output_file = Path(OUTPUT_DIR) / relative_path
    
    # 创建输出子目录
    output_file.parent.mkdir(parents=True, exist_ok=True)
    
    # 跳过已存在的文件
    if output_file.exists():
        print(f"跳过(已存在): {pdf_file.name}")
        continue
    
    # 执行podofogc
    print(f"处理: {pdf_file.name}")
    result = subprocess.run(
        [PODOFO_GC, str(pdf_file), str(output_file)],
        capture_output=True
    )
    
    if result.returncode == 0:
        print(f"  ✓ 成功 -> {output_file}")
        success += 1
    else:
        print(f"  ✗ 失败")
        failed += 1

print(f"\n完成!成功: {success}, 失败: {failed}")

这个简化版本:

  • ✅ 没有多线程
  • ✅ 没有命令行参数
  • ✅ 直接修改代码中的路径即可使用
  • ✅ 保留目录结构
  • ✅ 自动跳过已存在的文件
  • ✅ 显示处理进度
相关推荐
qq_372154231 小时前
CSS如何改变单个网格项目的对齐方式
jvm·数据库·python
kexnjdcncnxjs1 小时前
CodeIgniter4安全加固指南:防御XSS与CSRF攻击
jvm·数据库·python
2401_871492851 小时前
Imagick PDF 处理失败的常见原因与解决方案
jvm·数据库·python
littleM1 小时前
深度拆解 HermesAgent(六):研究功能与测试体系
开发语言·人工智能·python·架构·ai编程
ji_shuke1 小时前
访问s3里pdf文件出现strict-origin-when-cross-origin问题修复
pdf
隔壁大炮1 小时前
CNN图像分类案例
人工智能·pytorch·python·深度学习·算法·分类·cnn
꯭爿꯭巎꯭1 小时前
洛雪音乐app下载 落雪音乐安卓/电脑版下载
windows
深邃-1 小时前
【Web安全】-Kali,Linux配置(2):Java环境配置,Python环境配置,Conda使用,PIP配置使用,SSH远程登录
java·linux·python·安全·web安全·网络安全·php
念恒123061 小时前
python(环境安装,输入输出,变量)
python·学习