为业务开发了个小工具,才发现自己也有类似需求,但从没想过为自己服务!!

663 阅读3分钟

背景介绍

最近业务有个需求是从大量文件夹内根据关键字提取文件关键字附近的段落,并将文件位置及段落内容输出到表格,方便业务从表格中获取关键信息。
转念一想,这不是跟前段时间我学习遇到的需求差不多嘛,情况是要打开每章材料的文件夹,再打开里边每节材料的文件夹,再打开PPT才能获取到文件内容,看的非常费劲,但是因为量不大,索性就一次次的打开文件夹了,也没想过开发代码解决。。。

具体需求

具体需求是大概有40多个项目,每个项目中有各类材料,包括word文档(doc和docx)、PDF文档(包括扫描件),其中扫描件不太好处理,需要用到OCR识别等工具。需要获取到这些文件的内容,并根据关键字对所有文件检索,将检索到符合的段落及文件位置输出到表格,使不用再大量打开文件进行查看。
经过调研,Python能实现上述需求。能开发完成,要多感谢豆包同志的帮助(发现AI可能以后真的能独立开发,豆包给的代码可实现性挺高的)。

代码

import fitz  # PyMuPDF
from openpyxl import load_workbook
# # # 获取文件夹内所有文件内容,对PDF和扫描件区分
import os
import docx
from paddleocr import PaddleOCR
import logging
# 表格
import pandas as pd
import win32com.client as win32

logging.disable(logging.DEBUG)  # 关闭DEBUG日志的打印
logging.disable(logging.WARNING)  # 关闭WARNING日志的打印
# 关键字表格列表
excel_path = 'D:\目录.xlsx'

# 文件夹名称
file_path = input("请输入文件或文件夹的路径: ")
# file_path = 'D:\项目文件'

# 表格输出位置
# outputUrl = ''
 
df = pd.DataFrame({
   '关键词': [],
   '文件位置': [],
   '关键词前后文': []  
})

# 打开Excel文件
wb = load_workbook(excel_path)
sheet = wb.active

# 打开文件夹内所有文件
def read_files_in_subfolders(base_folder):
    for root, dirs, files in os.walk(base_folder):
        for file_name in files:
            file_path = os.path.join(root, file_name)
            file_content_compare(file_path)
    excel_export(df) 

# 遍历关键词并将对应到关键词的内容添加到表格
def reflectWord(content, file_path):
    global df
    for row in sheet.iter_rows():
        search_term = row[3].value  # 假设第4列是要搜索的内容
        if search_term is not None:
            search_term = search_term.split('、')
            if search_term:
                for item in list(filter(None, search_term)):
                    if item in content:
                        new_row = {'关键词': item, '文件位置': file_path, '关键词前后文': content}
                        df = pd.concat([df, pd.DataFrame([new_row])], ignore_index=True)

def file_content_compare(file_path):
    if file_path.endswith('.docx') or file_path.endswith('.doc'):
        if file_path.endswith('.doc'):
            word = win32.Dispatch("Word.Application")
            doc = word.Documents.Open(file_path)
            for text in doc.paragraphs:
                reflectWord(text.Range.Text, file_path)
            doc.Close()

        elif file_path.endswith('.docx'): 
            doc = docx.Document(file_path)
            for text in doc.paragraphs:
                reflectWord(text.text, file_path)

    elif file_path.endswith('.pdf'): 
        document = fitz.open(file_path)
        # 初始化判定变量
        is_scanned_document = False
        for page in document:
            # 检查是否有图像
            images = page.get_images()
            if images:
                is_scanned_document = True
                break
    
        if is_scanned_document: 
            ocr = PaddleOCR(use_angle_cls=True, lang="ch")
            # 每句文字的位置
            result = ocr.ocr(file_path)
            # 用于存储所有页面的文字内容
            all_txtsNew = []
            for page_index, page in enumerate(result):
                # 获取当前页面的所有行文字内容
                page_txtsNew = [line[1][0] for line in page]
                all_txtsNew.extend(page_txtsNew)
                for pageGra in page_txtsNew:
                    reflectWord(pageGra, file_path)
        else:
            pdf = fitz.open(file_path)
            text = ""
            # 遍历每一页
            for page_num in range(len(pdf)):
                page = pdf[page_num]
                # 获取文本块
                for block in page.get_text("blocks"):
                    text += block[4].strip()  # 获取文本块的字符串并去除前后空白
                    reflectWord(text, file_path)
    
def excel_export(df):  
    # 导出为Excel文件
    df.to_excel(r'D:\output.xlsx', index=False)

read_files_in_subfolders(file_path)


工作只是养活自己的途径,生活才是最重要的。