求解决方案:构建PDF文本查找替换应用并实现PDF自动化处理
Python实现PDF文本替换自动化方案
核心逻辑
PDF并非可直接编辑的文本文件,直接替换文本不可行,需采用先擦除目标文本区域,再叠加新文本的思路,完全匹配你的需求流程:读取数据源→遍历PDF文件夹→处理单文件→重命名+生成报告→备份原文件。
依赖库安装
先安装必备工具包,执行以下命令:
pip install PyPDF2 reportlab pandas sqlalchemy pdfplumber python-dotenv
PyPDF2:读写PDF页面内容reportlab:绘制白色覆盖层擦除文本、添加新文本pdfplumber:精准定位文本坐标(比PyPDF2的文本提取更可靠)pandas:读取Excel数据源sqlalchemy:连接SQL数据库
分步代码实现
1. 读取数据源(Excel/SQL二选一)
import pandas as pd from sqlalchemy import create_engine # 读取Excel配置(假设Excel列名:原文件名, 目标文本, 替换文本, 新文件名) def load_excel_config(excel_path): df = pd.read_excel(excel_path) return df.set_index('原文件名').to_dict('index') # 读取SQL配置 def load_sql_config(db_params): engine = create_engine(f"mysql+pymysql://{db_params['user']}:{db_params['pwd']}@{db_params['host']}/{db_params['db']}") query = "SELECT 原文件名, 目标文本, 替换文本, 新文件名 FROM pdf_replace_rules" df = pd.read_sql(query, engine) return df.set_index('原文件名').to_dict('index')
2. PDF文本替换核心函数
from PyPDF2 import PdfReader, PdfWriter from reportlab.pdfgen import canvas import io import pdfplumber def replace_target_text(input_pdf, output_pdf, target_text, new_text): # 读取原PDF reader = PdfReader(input_pdf) writer = PdfWriter() with pdfplumber.open(input_pdf) as pdf: for page_num in range(len(reader.pages)): pdf_page = pdf.pages[page_num] page = reader.pages[page_num] page_w = float(page.mediabox[2]) page_h = float(page.mediabox[3]) upper_third_top = page_h * 2/3 # 页面上三分之一区域的顶部边界(pdfplumber的top从页面顶部开始计算) # 创建白色覆盖层,用于擦除目标文本 packet = io.BytesIO() can = canvas.Canvas(packet, pagesize=(page_w, page_h)) can.setFillColorRGB(1,1,1) # 白色完全覆盖原文本 # 遍历页面上三分之一区域的文本,定位目标文本并覆盖 for word in pdf_page.extract_words(): if word['text'] == target_text and word['top'] <= upper_third_top: # 转换坐标:pdfplumber的y轴从顶部算,reportlab从底部算 rect_x = word['x0'] rect_y = page_h - word['bottom'] rect_w = word['x1'] - word['x0'] rect_h = word['bottom'] - word['top'] can.rect(rect_x, rect_y, rect_w, rect_h, fill=True) # 在原文本位置添加新文本(取第一个匹配位置的坐标) target_words = [w for w in pdf_page.extract_words() if w['text'] == target_text and w['top'] <= upper_third_top] if target_words: first_word = target_words[0] can.setFillColorRGB(0,0,0) can.setFont("Helvetica", 12) # 需替换为原文档的字体、字号 can.drawString(first_word['x0'], page_h - first_word['top'], new_text) can.save() packet.seek(0) overlay = PdfReader(packet).pages[0] page.merge_page(overlay) writer.add_page(page) # 写入新PDF文件 with open(output_pdf, "wb") as f: writer.write(f)
3. 主流程:批量处理+备份+生成报告
import os import shutil from datetime import datetime def batch_process_pdfs(folder_path, config_data): report_rows = [] backup_dir = os.path.join(folder_path, "原始文件备份") os.makedirs(backup_dir, exist_ok=True) report_path = f"./PDF处理报告_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx" for filename in os.listdir(folder_path): if not filename.endswith(".pdf"): continue file_path = os.path.join(folder_path, filename) # 跳过备份文件夹中的文件 if os.path.abspath(file_path).startswith(os.path.abspath(backup_dir)): continue # 匹配替换规则 if filename not in config_data: report_rows.append({ "原文件名": filename, "新文件名": "-", "处理状态": "无对应替换规则" }) continue rule = config_data[filename] target_text = rule['目标文本'] new_text = rule['替换文本'] new_filename = f"{rule['新文件名']}.pdf" output_path = os.path.join(folder_path, new_filename) try: replace_target_text(file_path, output_path, target_text, new_text) # 备份原文件 shutil.copy(file_path, os.path.join(backup_dir, filename)) report_rows.append({ "原文件名": filename, "新文件名": new_filename, "处理状态": "成功" }) except Exception as e: report_rows.append({ "原文件名": filename, "新文件名": "-", "处理状态": f"失败:{str(e)}" }) # 生成Excel格式的处理报告 pd.DataFrame(report_rows).to_excel(report_path, index=False) print(f"批量处理完成,报告已保存到:{report_path}") # 执行示例 if __name__ == "__main__": # 选择一种数据源加载方式 # config = load_excel_config("./pdf替换规则.xlsx") db_params = { "user": "你的数据库用户名", "pwd": "你的数据库密码", "host": "localhost", "db": "你的数据库名" } config = load_sql_config(db_params) pdf_folder = "./待处理PDF" batch_process_pdfs(pdf_folder, config)
关键注意点
- 扫描件PDF处理:如果是扫描生成的PDF(图片格式),需先通过
pytesseract+pdf2image做OCR转文本,否则无法提取和替换文本。 - 字体匹配:若要求新文本与原文本字体一致,可通过
pdfplumber提取原文本的字体信息,再在reportlab中加载对应字体文件。 - 坐标转换:
pdfplumber与reportlab的y轴计算方向相反,必须转换坐标才能精准覆盖目标文本。 - 异常扩展:可补充捕获PDF文件损坏、权限不足、数据源格式错误等异常场景,提升代码稳定性。
原代码故障排查方向
如果之前的代码无法运行,优先检查以下几点:
- 是否为扫描件PDF?扫描件无法直接提取文本,必须先做OCR处理。
- 依赖库版本冲突:旧版
PyPDF2的API与新版差异较大,可尝试锁定版本PyPDF2==2.12.0。 - 文本定位错误:原代码可能未过滤上三分之一区域,或存在坐标转换错误。
- 文件路径问题:是否使用了相对路径但工作目录不正确,或存在中文路径编码问题。
内容的提问来源于stack exchange,提问作者RadoFafo
相关产品推荐
相关产品推荐

