Python脚本—1.提取压缩包中的pdf文件

Python脚本:

在n个压缩包中,提取pdf文件。本文中代码有Qoder CN生成。

在整理毕业设计的材料时,需要让学生提交一个最终材料的压缩包,另外提交一个论文和指导手册的pdf文件。但是很多同学忘记交pdf了,那就用下面的程序提取。

  1. 下面是5个同学的压缩包,压缩包中包含pdf文件,我需要把他们的pdf文件提取出来。
  1. 使用程序:需要修改程序中的第224行SOURCE_FOLDER改为自己的文件夹路径。

    import os
    import zipfile
    import tarfile
    import shutil
    import subprocess
    from pathlib import Path
    """summary
    把压缩包中的 PDF 文件解压并保存为单独的文件,在最终材料中提取论文与指导手册得pdf文件

    Returns:
    type: description
    """

    尝试导入可选的库以支持更多格式

    try:
    import py7zr
    HAS_7Z_LIB = True
    except ImportError:
    HAS_7Z_LIB = False

    try:
    import rarfile
    HAS_RAR_LIB = True
    except ImportError:
    HAS_RAR_LIB = False

    配置 7-Zip 路径 (根据你的安装位置修改)

    优先尝试系统 PATH 中的 7z,如果没有,尝试常见安装路径

    SEVEN_ZIP_PATH = '7z'

    def is_tool_available(cmd):
    """检查命令行工具是否可用"""
    try:
    subprocess.run([cmd, '--help'],
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    timeout=5)
    return True
    except (FileNotFoundError, subprocess.TimeoutExpired):
    return False

    if not is_tool_available('7z'):
    possible_paths = [r"D:\InstallProgram\7-Zip\7z.exe"]
    for p in possible_paths:
    if os.path.exists(p):
    SEVEN_ZIP_PATH = p
    break

    def get_unique_filename(filepath):
    """如果文件已存在,生成一个新的唯一文件名 (例如 file(1).pdf)"""
    if not os.path.exists(filepath):
    return filepath

    复制代码
     base, ext = os.path.splitext(filepath)
     counter = 1
     while os.path.exists(filepath):
         filepath = f"{base}({counter}){ext}"
         counter += 1
     return filepath

    def flatten_output_directory(output_dir):
    """
    将 output_dir 下所有子文件夹中的文件移动到 output_dir 根目录
    并删除空的子文件夹
    """
    if not os.path.exists(output_dir):
    return

    复制代码
     # 遍历目录树
     for root, dirs, files in os.walk(output_dir, topdown=False):
         # 跳过根目录本身
         if root == output_dir:
             continue
    
         # 移动文件到根目录
         for filename in files:
             src_path = os.path.join(root, filename)
             dst_path = os.path.join(output_dir, filename)
    
             # 处理文件名冲突
             dst_path = get_unique_filename(dst_path)
    
             try:
                 shutil.move(src_path, dst_path)
                 # print(f"  移动文件: {filename} 到根目录")
             except Exception as e:
                 print(f"  移动文件失败 {filename}: {e}")
    
         # 删除空文件夹 (os.walk topdown=False 保证先处理子目录)
         try:
             if not os.listdir(root):  # 如果文件夹为空
                 os.rmdir(root)
         except Exception as e:
             pass  # 忽略删除错误

    def extract_pdf_from_zip(zip_path, output_dir):
    """从 zip 文件中提取 PDF (支持 GBK 编码文件名)"""
    try:
    with zipfile.ZipFile(zip_path, 'r', metadata_encoding='gbk') as z:
    for file_info in z.infolist():
    if file_info.is_dir():
    continue
    if file_info.filename.lower().endswith('.pdf'):
    filename = os.path.basename(file_info.filename)
    if not filename or not filename.strip():
    continue
    target_path = os.path.join(output_dir, filename)
    target_path = get_unique_filename(target_path)
    try:
    with z.open(file_info) as source, open(
    target_path, 'wb') as target:
    shutil.copyfileobj(source, target)
    except Exception as e:
    print(f" 提取 ZIP 中的 PDF 失败 {filename}: {e}")
    except Exception as e:
    print(f"错误: 无法打开或解压 ZIP 文件 {zip_path}: {e}")

    def extract_pdf_from_tar(tar_path, output_dir):
    """从 tar/tar.gz 文件中提取 PDF"""
    mode = 'r:gz' if tar_path.endswith('.gz') else 'r'
    try:
    with tarfile.open(tar_path, mode) as t:
    for member in t.getmembers():
    if member.isfile() and member.name.lower().endswith('.pdf'):
    filename = os.path.basename(member.name)
    if filename:
    target_path = os.path.join(output_dir, filename)
    target_path = get_unique_filename(target_path)
    with t.extractfile(member) as source, open(
    target_path, 'wb') as target:
    shutil.copyfileobj(source, target)
    except Exception as e:
    print(f"错误: 无法解压 {tar_path}: {e}")

    def extract_pdf_from_7z(sevenz_path, output_dir):
    """从 7z 文件中仅提取 PDF"""
    _extract_archive_with_filter(sevenz_path, output_dir, '7z')

    def extract_pdf_from_rar(rar_path, output_dir):
    """从 rar 文件中仅提取 PDF"""
    _extract_archive_with_filter(rar_path, output_dir, 'rar')

    def _extract_archive_with_filter(archive_path, output_dir, archive_type):
    """
    通用函数:使用 7-Zip 命令行工具,先列表筛选,再仅提取 PDF
    archive_type: '7z' or 'rar'
    """
    if not os.path.exists(archive_path):
    print(f"错误: 文件不存在 {archive_path}")
    return

    复制代码
     # 1. 列出压缩包内的所有文件
     # 7z l "archive.rar" -ba -slt 列出详细技术信息,便于解析
     cmd_list = [SEVEN_ZIP_PATH, 'l', archive_path, '-ba', '-slt']
    
     pdf_files_in_archive = []
    
     try:
         result = subprocess.run(cmd_list,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
         if result.returncode != 0:
             print(
                 f"  无法列出 {archive_type} 内容: {result.stderr.decode('gbk', errors='ignore')}"
             )
             return
    
         # 解析输出,寻找 Path 行
         output_text = result.stdout.decode('gbk',
                                            errors='ignore')  # 7z 中文输出通常是 gbk
         lines = output_text.splitlines()
    
         current_path = None
         for line in lines:
             if line.startswith('Path = '):
                 current_path = line[7:].strip()
                 if current_path.lower().endswith('.pdf'):
                     pdf_files_in_archive.append(current_path)
    
     except Exception as e:
         print(f"  解析 {archive_type} 列表时出错: {e}")
         return
    
     if not pdf_files_in_archive:
         print(f"  未在 {os.path.basename(archive_path)} 中找到 PDF 文件")
         return
    
     # 2. 仅提取筛选出的 PDF 文件
     # 7z x "archive.rar" -o"output_dir" -y "file1.pdf" "file2.pdf"
     if pdf_files_in_archive:
         # 构建提取命令
         cmd_extract = [
             SEVEN_ZIP_PATH, 'x', archive_path, f'-o{output_dir}', '-y'
         ] + pdf_files_in_archive
    
         try:
             result = subprocess.run(cmd_extract,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE)
             if result.returncode == 0:
                 print(
                     f"  成功从 {archive_type} 中提取了 {len(pdf_files_in_archive)} 个 PDF"
                 )
                 # 3. 扁平化处理:将子文件夹中的 PDF 移到根目录
                 flatten_output_directory(output_dir)
             else:
                 err_msg = result.stderr.decode('gbk', errors='ignore')
                 print(f"  提取 {archive_type} 中的 PDF 失败: {err_msg}")
         except Exception as e:
             print(f"  执行提取命令时出错: {e}")

    def main():
    # 配置部分
    SOURCE_FOLDER = 'C:/Users/Downloads/软件工程2309-2310-第四章作业/(pdf)'
    OUTPUT_FOLDER = 'extracted_pdfs'

    复制代码
     os.makedirs(OUTPUT_FOLDER, exist_ok=True)
    
     supported_extensions = ('.zip', '.tar', '.gz', '.tgz', '.7z', '.rar')
    
     processed_count = 0
    
     for filename in os.listdir(SOURCE_FOLDER):
         file_path = os.path.join(SOURCE_FOLDER, filename)
    
         if not os.path.isfile(file_path):
             continue
    
         lower_name = filename.lower()
         if not any(lower_name.endswith(ext) for ext in supported_extensions):
             continue
    
         print(f"正在处理: {filename}")
    
         try:
             if lower_name.endswith('.zip'):
                 extract_pdf_from_zip(file_path, OUTPUT_FOLDER)
             elif lower_name.endswith(('.tar', '.gz', '.tgz')):
                 extract_pdf_from_tar(file_path, OUTPUT_FOLDER)
             elif lower_name.endswith('.7z'):
                 extract_pdf_from_7z(file_path, OUTPUT_FOLDER)
             elif lower_name.endswith('.rar'):
                 extract_pdf_from_rar(file_path, OUTPUT_FOLDER)
    
             processed_count += 1
         except Exception as e:
             print(f"处理文件 {filename} 时发生未知错误: {e}")
    
     print(f"\n完成! 共处理了 {processed_count} 个压缩包。")
     print(f"PDF 文件已保存到: {os.path.abspath(OUTPUT_FOLDER)}")

    if name == 'main':
    main()

3.运行程序,显示处理了5个压缩包,提取的文件放到了extracted_pdfs文件夹中。

提取pdf文件完成


本文中代码有Qoder CN生成。

阿里云推出的AI智能体产品系列

Qoder CN,阿里云推出的AI智能体产品系列,覆盖软件开发与日常办公多元场景,包含面向编码场景的Qoder CN、面向日常工作的QoderWork CN、Qoder CN CLI等子产品。Qoder CN前身为阿里云旗下智能编码助手通义灵码。

相关推荐
_Jimmy_1 小时前
SQLAlchemy 复杂 SQL 执行指南与模板库
python·sql
FantasticPerson1 小时前
30 · 输出样式(Output Styles):换一档「节目」,不换主持人
ai编程
FantasticPerson1 小时前
31 · 钩子(Hooks):在固定时机自动扣扳机
ai编程
六个九十度1 小时前
用python脚本访问被网关隔离的嵌入式设备
开发语言·python
FantasticPerson2 小时前
29 · settings.json:用户级 / 项目级配置
ai编程
小虎AI生活2 小时前
90%的人 AI 副业一分钱没赚到,卡的地方出奇一致
ai编程
GEO_ai_zhijian2 小时前
饮料生产线质量检测系统供应商哪家强
大数据·python
名不经传的养虾人2 小时前
从0到1:企业级AI项目迭代日记 Vol.65|最危险的故障不是崩溃,是悄悄换掉了正确答案
数据库·人工智能·ai编程·ai-agent·企业ai
量化吞吐机3 小时前
近期量化工具怎么选,先看规则流程能否承接
人工智能·python