当前位置: 首页 > news >正文

【工程实践/源码阅读】批量文件处理步骤以及如何并行处理

目录

  • 一、背景
  • 二、常用函数
    • 1.各类型统计
    • 2. 批量处理分块
    • 3.检查最大文件和最小文件
    • 3.删除大文件

一、背景


需要对3000份文件进行处理,内容、文件名不是很标准,而且文件类型多种多样,需要统一转成PDF,再从PDF解析为markdown。再各个处理的阶段,也会带来一些脏数据,比如doc转PDF的时候,就可能有部分doc转换失败。下面会罗列一些在文件处理阶段好用的函数。
在数据清洗过程,可能面临的问题有:

  • 文件类型不一样
  • 处理过程中带来的脏数据
  • 文件名(含有非法字符导致路径问题)
  • 批量处理如何分块?
  • 如何并行处理

二、常用函数


1.各类型统计

完成目录下各类型统计,并建立分类后的目录
在这里插入图片描述
使用字典这个数据结构来存储类型以及类型下的文件路径
shutil.move(file, dest_path) 是 Python 中用于移动文件或目录的函数。它的作用是将 file 移动到 dest_path。如果 dest_path 是一个目录,则会将 file 移动到该目录中,并保留原文件名。

def classify_and_move_files_by_type(folder_path, output_folder):
    # 创建一个字典来存储文件类型及其对应的文件路径
    file_dict = defaultdict(list)

    # 遍历文件夹及其子文件夹
    for root, dirs, files in os.walk(folder_path):
        for file in files:
            # 获取文件路径
            file_path = os.path.join(root, file)
            # 获取文件扩展名(类型)
            file_type = os.path.splitext(file)[1].lower()  # 转换为小写以便统一处理
            # 将文件路径添加到对应类型的列表中
            file_dict[file_type].append(file_path)

    # 创建输出文件夹(如果不存在)
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)

    # 将文件按类型分类并移动到新的文件夹中
    for file_type, files in file_dict.items():
        # 创建子文件夹(以文件类型命名)
        type_folder = os.path.join(output_folder, file_type if file_type else "no_extension")
        if not os.path.exists(type_folder):
            os.makedirs(type_folder)

        # 移动文件到对应的子文件夹
        for file in files:
            # 获取文件名
            file_name = os.path.basename(file)
            # 目标路径
            dest_path = os.path.join(type_folder, file_name)
            # 移动文件
            shutil.move(file, dest_path)
            print(f"Moved: {file} -> {dest_path}")

    print("文件分类和移动完成!")

2. 批量处理分块

此处是用的一个脚本,输入目录可以将目录下进行分块,便于并行处理

#!/bin/bash

# 定义源目录
SOURCE_DIR="/data/huyuqiang/简历分类/pdf"

# 检查源目录是否存在
if [ ! -d "$SOURCE_DIR" ]; then
    echo "Source directory not found: $SOURCE_DIR"
    exit 1
fi

# 创建 7 个子目录
for i in {1..7}; do
    mkdir -p "${SOURCE_DIR}/split_${i}"
    if [ ! -d "${SOURCE_DIR}/split_${i}" ]; then
        echo "Failed to create subdirectory: ${SOURCE_DIR}/split_${i}"
        exit 1
    fi
done

# 获取所有文件列表(排除子目录)
files=()
while IFS= read -r -d '' file; do
    files+=("$file")
done < <(find "$SOURCE_DIR" -maxdepth 1 -type f -print0)

# 检查是否有文件
if [ ${#files[@]} -eq 0 ]; then
    echo "No files found in $SOURCE_DIR"
    exit 1
fi

# 计算每份文件的数量
total_files=${#files[@]}
files_per_split=$(( (total_files + 6) / 7 ))  # 向上取整

# 将文件分配到子目录
count=0
split_index=1
for file in "${files[@]}"; do
    # 移动文件到子目录
    mv "$file" "${SOURCE_DIR}/split_${split_index}/"

    # 更新计数器和子目录索引
    count=$((count + 1))
    if [ $count -ge $files_per_split ]; then
        count=0
        split_index=$((split_index + 1))
    fi
done

echo "Files have been split into 7 subdirectories."

3.检查最大文件和最小文件

在数据处理过程中,往往会形成一些超大文件(这些文件中可能是乱码),这些文件如果不处理会影响后续的处理效率。所以需要再过程中查看一下输出。
用一个元组列表来保存文件路径对应的文件页数
PyPDF2.PdfReader(f) 是 PyPDF2 库中用于读取 PDF 文件的类。它可以从文件对象 f 中加载 PDF 内容,并提供一个接口来访问 PDF 的页面、元数据、书签等信息。
然后利用sorted对列表进行排序

def sort_pdf_files_by_pages(root_dir, output_file):
    """
    收集指定目录下的所有PDF文件路径和页数,并按页数排序后写入文件
    
    参数:
    root_dir (str): 要搜索的根目录路径
    output_file (str): 输出文件路径
    """
    import os
    import PyPDF2
    
    # 收集所有PDF文件路径和页数
    pdf_files = []
    for dirpath, _, filenames in os.walk(root_dir):
        for filename in filenames:
            if filename.endswith(".pdf"):
                file_path = os.path.join(dirpath, filename)
                try:
                    # 打开PDF文件并读取页数
                    with open(file_path, "rb") as f:
                        reader = PyPDF2.PdfReader(f)
                        num_pages = len(reader.pages)
                        pdf_files.append((file_path, num_pages))
                except Exception as e:
                    print(f"无法读取文件 {file_path}: {e}")

    # 按页数排序(从大到小)
    pdf_files_sorted = sorted(pdf_files, key=lambda x: x[1], reverse=True)

    # 将结果写入txt文件
    with open(output_file, "w", encoding="utf-8") as f:
        for i, (file_path, num_pages) in enumerate(pdf_files_sorted, 1):
            f.write(f"{i}. {file_path} - {num_pages} 页\n")

排序完查看一下大文件和小文件,是不是最大文件是处理后乱码变成脏数据,还有最小文件是不是空白页没有进行处理

3.删除大文件

这里是估计了一下超过9页的文件可能是一个脏数据,然后就删除
直接用os.remove(pdf_path)

def count_pdf_pages(pdf_path):
    """计算 PDF 文件的页数"""
    try:
        with open(pdf_path, 'rb') as file:
            reader = PyPDF2.PdfReader(file)
            return len(reader.pages)
    except Exception as e:
        print(f"Error reading {pdf_path}: {e}")
        return 0

def delete_large_pdfs(directory, max_pages=9):
    """删除页数大于 max_pages 的 PDF 文件"""
    for filename in os.listdir(directory):
        if filename.endswith(".pdf"):
            pdf_path = os.path.join(directory, filename)
            num_pages = count_pdf_pages(pdf_path)
            if num_pages > max_pages:
                print(f"Deleting {filename} (pages: {num_pages})")
                os.remove(pdf_path)

https://gitcode.com/qq_43920838/module_code.git

相关文章:

  • Ubuntu下用QEMU模拟运行OpenBMC
  • 解决address already in use报错:如何查看占用某个端口的程序并杀死
  • 【uni-app】引用公共组件
  • 数据预处理流程与关键步骤解析
  • React 开发环境搭建
  • 多个内容滑动轮播图【前端】
  • 第十六次CCF-CSP认证(含C++源码)
  • c++图论(五)之判断图连通
  • 浪潮信息再塑AI+OS格局,联手龙蜥共筑未来
  • 元数据管理系列(一):元数据管理的前世今生
  • 实战3. 利用Pytorch预写好ResNet-18预测电视剧《辛普森一家》中的人物——图像分类
  • Ceph集群2025(Squid版)导出高可用NFS集群(上集)
  • 第一人称动作识别文献阅读——LSTA:用于自我中心动作识别的长短期注意力机制
  • 第二章 | 智能合约 区块链基础知识{介绍篇}
  • 三、重学C++—C语言内存管理
  • PyTorch 面试题及参考答案(精选100道)
  • 圆弧插补相关算法汇总(C++和ST源代码)
  • Spring6: 1概述
  • 拆解美团2024年报,业务协同、生态共赢、科技创新
  • POP点、LT、DX、YD
  • 建基建设集团网站/曹操seo博客
  • 查建筑材料的网站/杭州seo公司
  • 常见的网站建设技术/牡丹江seo
  • 建站成功是怎么回事/湖南关键词优化快速
  • 英文网站建设哪家强/域名注册流程
  • 河南网站seo费用/seo按照搜索引擎的