ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Python PDF办公自动化:格式解析、合并拆分、文本表格提取指南

Python PDF办公自动化:格式解析、合并拆分、文本表格提取指南 在日常办公和数据处理中PDF 是出现频率极高的文件格式。无论是阅读合同、整理报价单、合并扫描件、提取报销发票信息还是把系统导出的 PDF 报表转成 Excel 再汇总都会涉及大量重复操作。手动处理这些文件不仅浪费时间还容易出错。而 Python 恰好提供了一套比较成熟的 PDF 处理方案借助几个第三方库就可以把重活交给脚本完成。本篇文章属于 Python 办公自动化系列中 PDF 主题的开篇会从 PDF 的基础概念讲起结合代码演示常见操作方法包括读取页面信息、合并拆分 PDF、提取文本和表格以及 PDF 转 Word 的思路。适合对 Python 语法有基本了解、想在办公场景中提升效率的读者也适合刚接触办公自动化的新手对照练习。1. PDF 文件格式与办公自动化场景1.1 PDF 格式的基本特点PDF 的全称是 Portable Document Format中文一般叫“便携式文档格式”由 Adobe 公司提出现在由国际标准化组织 ISO 维护。它最大的特点是“版式固定”无论在 Windows、macOS、Linux还是在不同品牌的打印机上打开字体、图片、表格位置都能保持一致。对需要跨平台流转、打印、存档的正式文件来说这是很明显的优势。但从另一个角度看PDF 也更像“一张电子纸”。它内部保存的是文字、矢量图形、图片对象以及它们的坐标位置而不是像 Word 那样按段落和样式保存。所以 PDF 中的文字可以被复制阅读但想直接改段落布局就比较麻烦。日常办公中常见的“PDF 怎么编辑”“PDF 转 Word 后排版乱了”等问题的根源往往就在这里。1.2 办公自动化中的常见 PDF 需求在办公自动化的实际项目里PDF 相关的需求大致可以分成几类需求类型典型场景常用处理方式读取信息获取 PDF 页数、标题、作者、创建时间PyPDF2、pypdf内容提取从简历、发票、合同中提取文本pdfplumber、PyMuPDF表格抽取把 PDF 中的表格数据转为 Excelpdfplumber pandas合并拆分多个 PDF 合并成一个或按页拆分pypdf、PyPDF2格式转换PDF 转 Word、图片转 PDF、HTML 打印 PDFpdf2docx、img2pdf 等批量处理给 PDF 添加水印、加密、拆分成单页pypdf 等库组合使用如果是做财务报销、人力资源简历筛选、招投标文件整理、订单单据归档这类工作上面这些需求几乎每天都会遇到。用 Python 写一个脚本就能把几分钟手动操作缩短到几秒钟。1.3 为什么选择 Python 做 PDF 文件处理选择 Python主要是因为它的库生态完整语法相对简洁。处理 PDF 时不需要去理解 PDF 标准内部的复杂字节结构只需要调用库提供的 API就能读取页面、文字和表格。另外 Python 本身擅长文本处理和数据分析提取出 PDF 内容后可以很方便地和 Excel、CSV、数据库对接容易形成一条完整的自动化流程。不过需要注意Python 并没有一个能解决所有 PDF 需求的“万能库”。不同库各有特长有的擅长读取元数据有的擅长定位表格坐标有的擅长重新排版生成新 PDF。因此本文会从了解和选型开始帮大家建立正确的知识框架。2. Python 处理 PDF 的常用库2.1 pypdf / PyPDF2PDF 基础操作PyPDF2 是老牌 Python PDF 处理库很多早期教程都会提到它。不过它的维护节奏不太稳定后来社区推出了 pypdf可以看作 PyPDF2 的延续版本。新项目建议优先使用 pypdfAPI 兼容性较好仍在持续更新。pypdf 适合做以下操作读取 PDF 页数、作者、标题等元数据。按页合并、拆分 PDF。给 PDF 旋转页面。给 PDF 添加水印。对 PDF 设置密码或解密。它的优点是安装简单、API 直观不足是提取复杂版式文本时表现一般。2.2 pdfplumber文本与表格精确提取pdfplumber 是一个专注于“从 PDF 中提取信息”的库。它会把页面中的每一个字符、线条、矩形都解析成对象然后提供基于坐标的访问方式。因此当需要从带边框表格、报销单、物流单中抽取数据时pdfplumber 通常比 pypdf 更可靠。pdfplumber 的典型用途提取纯文本和指定坐标区域的文字。提取表格每个单元格中的内容会以二维列表返回。查看页面中的线条、矩形位置定位图片。缺点是对复杂排版的处理需要一定调试成本而且提取速度会比简单读取页数慢一些。2.3 reportlab从零生成 PDF前面几个库偏重“读”reportlab 则偏重“写”。它可以根据代码动态生成 PDF适合在办公自动化流程中创建对账单、报告、标签等文件。reportlab 功能强大但上手曲线比 pypdf 高一些因为需要理解 canvas、platypus 等概念。2.4 PyMuPDF高性能渲染与操作PyMuPDF 是对 MuPDF 库的封装特点是速度快、功能全。它可以把 PDF 页面渲染成图片也可以提取文本、图片和矢量图形还支持在 PDF 上做注释。它的 API 名称以 fitz 开头所以代码中常常看到import fitz。如果觉得 pdfplumber 提取速度太慢可以尝试 PyMuPDF。2.5 库的选型建议目标推荐库合并、拆分、读取页数pypdf提取带坐标的文本pdfplumber、PyMuPDF提取表格并转 Excelpdfplumber openpyxl/pandas从零生成 PDFreportlab扫描版 PDF 文字识别OCR 库如 PaddleOCR、TesseractPDF 转 Wordpdf2docx实际项目中可以根据需求组合使用比如先用 pypdf 拆分 PDF再用 pdfplumber 提取特定页面的表格。3. 环境准备与基础概念3.1 Python 与第三方库安装本文示例使用 Python 3.8 以上版本。如果电脑还没有安装 Python可以到 Python 官网下载安装包安装时记得勾选“Add Python to PATH”。安装完成后在命令行输入下面命令确认版本python --version接着安装本文需要的第三方库pip install pypdf pdfplumber pdf2docx如果你的项目同时需要操作 Excel可以继续安装 openpyxl 或 pandaspip install openpyxl pandas安装过程如果提示 pip 版本较旧可以先升级 pippython -m pip install --upgrade pip3.2 示例文件准备为了便于后续练习建议创建一个独立的项目目录并放入几个测试 PDF。比如pdf_auto/ ├── file1.pdf ├── file2.pdf └── demo.py如果手头没有现成的 PDF可以先用 WPS 或浏览器打印功能生成一个带表格的 PDF也可以在 Word 里简单制作后另存为 PDF。为了方便验证表格提取建议准备一个带有明显边框表格的 PDF 文件。3.3 PDF 对象模型的基础认识在开始写代码前先简单了解 PDF 的内部逻辑。一个 PDF 文件通常由 4 类对象组成内容流Content Stream描述页面上的文字、图形如何绘制。页面对象Page Object对应一页里面包含该页的媒体框、旋转角度、内容流引用等。字体和资源对象描述页面使用的字体、图片资源。元数据Metadata如标题、作者、创建时间通常存储在 DocumentInfo 或 XMP 元数据中。pypdf 读取 PDF 后会把整个文档封装成一个 PdfReader 对象。这个对象里面有一个 pages 列表每个元素代表一页。理解了这个结构后面的代码就会显得很自然先打开文件再遍历页面或读取页面属性。4. 实战一读取 PDF 基础信息4.1 需求描述我们有多个 PDF 文件需要查看每个文件的页数、作者、创建日期等基本信息。这是 PDF 办公自动化中最入门的操作适合理解 pypdf 的 API 用法。4.2 编写代码创建read_pdf_info.py代码如下# 文件路径pdf_auto/read_pdf_info.py from pypdf import PdfReader def show_pdf_info(pdf_path): reader PdfReader(pdf_path) meta reader.metadata print(f文件{pdf_path}) print(f页数{len(reader.pages)}) if meta: print(f标题{meta.title}) print(f作者{meta.author}) print(f创建时间{meta.creation_date}) # 读取第一页的尺寸 first_page reader.pages[0] width first_page.mediabox.width height first_page.mediabox.height print(f第一页尺寸{width} x {height}) print(- * 60) if __name__ __main__: show_pdf_info(file1.pdf) show_pdf_info(file2.pdf)4.3 运行与输出在项目目录下执行python read_pdf_info.py可能的输出效果如下文件file1.pdf 页数3 标题产品报价单 作者Administrator 创建时间2024-01-15 10:24:00 第一页尺寸595.0 x 842.0 ------------------------------------------------------------ 文件file2.pdf 页数1 标题报销申请表 作者None 创建时间None 第一页尺寸595.0 x 842.0 ------------------------------------------------------------4.4 代码关键点解释上面的代码虽然短但有三个关键点值得展开。reader.metadata返回的是一组文档属性不同软件导出的 PDF 携带的元数据不一样。比如 Word 导出的 PDF 可能有标题和作者而某些网页打印生成的 PDF 可能没有这些信息。因此打印时要用if meta做判断避免属性为 None 时程序报错。len(reader.pages)用于获取总页数。pypdf 会把 PDF 的页面对象全部加载到 pages 列表中所以后期想按页拆分或提取也都会通过这个 pages 列表操作。reader.pages[0]是第一个页面对象类型为 PageObject。mediabox表示页面的媒体框也就是整页在 PDF 坐标系中的范围。对于 A4 纸常见尺寸是 595 磅 × 842 磅这里使用的单位是“磅”而不是“厘米”。如果在办公场景需要把 PDF 页面尺寸和实际纸张对应要注意单位换算。在实际办公中这个脚本的用途不仅是查看单个文件。可以配合os.listdir()遍历某个目录下所有 PDF再把信息输出到 Excel形成一份“PDF 档案清单”。这一步先理解单个文件处理后面再扩展到批量会更稳。5. 实战二合并与拆分 PDF5.1 合并场景在办公场景里经常需要把多个 PDF 合并成一个文件。比如从不同部门收集了若干合同附件需要汇总成一份完整档案或者扫描了多页文件每一页保存成了单独 PDF最后要合并成一个文档。使用 pypdf 的 PdfWriter 可以很轻松完成合并操作。5.2 编写合并脚本创建merge_pdfs.py代码如下# 文件路径pdf_auto/merge_pdfs.py from pypdf import PdfWriter def merge_pdf_list(pdf_list, output_path): writer PdfWriter() for pdf_file in pdf_list: # append 方法会把整个 PDF 追加到输出文件末尾 writer.append(pdf_file) with open(output_path, wb) as out_file: writer.write(out_file) print(f合并完成共生成 {len(pdf_list)} 个 PDF 的合并文件{output_path}) if __name__ __main__: merge_pdf_list([file1.pdf, file2.pdf], merged.pdf)5.3 按页拆分脚本创建split_pdfs.py把一个 PDF 中指定的页面拆出来保存成新的 PDF 文件。# 文件路径pdf_auto/split_pdfs.py from pypdf import PdfReader, PdfWriter def split_pdf_by_pages(pdf_path, page_numbers, output_path): 从 pdf_path 中抽取指定页码组成新 PDF。 page_numbers 使用从 1 开始的编号例如 [1, 3, 5] reader PdfReader(pdf_path) writer PdfWriter() for page_num in page_numbers: # 用户输入的页码减 1才是 pages 列表的索引 page reader.pages[page_num - 1] writer.add_page(page) with open(output_path, wb) as out_file: writer.write(out_file) print(f已抽取 {len(page_numbers)} 页生成{output_path}) if __name__ __main__: # 抽取 file1.pdf 的第 1 页和第 3 页 split_pdf_by_pages(file1.pdf, [1, 3], file1_part.pdf)5.4 运行与边界情况说明执行命令python merge_pdfs.py python split_pdfs.py执行后项目目录下会生成merged.pdf和file1_part.pdf。这里有一个很容易踩的坑页码从 1 开始还是从 0 开始用户看到的 PDF 页码习惯从 1 开始而 Python 列表索引从 0 开始。上面代码把参数定义为从 1 开始内部再page_num - 1转换更符合办公程序的使用习惯。如果写成从 0 开始用户传页码时很容易出错。另外merge 场景需要关注失败回滚。如果中途某个文件损坏脚本可能抛异常。生产环境建议先对文件做可读性校验比如用 try-except 捕获 PdfReader 异常或者把已经写入的临时文件放到临时目录等所有文件处理成功后再覆盖最终文件。这样可以避免输出一个半成品 PDF。6. 实战三提取 PDF 文本与表格6.1 提取纯文本从 PDF 中复制文字是办公常事但遇到多个 PDF 需要批量提取时用脚本更高效。pdfplumber 的 extract_text 方法可以提取整页文字。创建extract_text.py# 文件路径pdf_auto/extract_text.py import pdfplumber def extract_all_text(pdf_path): with pdfplumber.open(pdf_path) as pdf: total_text [] for page in pdf.pages: text page.extract_text() total_text.append(text) return \n.join(filter(None, total_text)) if __name__ __main__: result extract_all_text(file1.pdf) print(result)说明page.extract_text()返回该页文本如果页面是扫描图片且没有 OCR那 text 可能为 None这时需要使用 OCR 工具识别。6.2 提取表格表格提取比纯文本更实用也更有挑战。pdfplumber 是根据页面上的线条和文字位置判断表格结构的因此要求表格必须有清晰边框或分隔线。创建extract_tables.py# 文件路径pdf_auto/extract_tables.py import pdfplumber def extract_tables_from_pdf(pdf_path, page_number): 提取指定页中的多个表格 with pdfplumber.open(pdf_path) as pdf: page pdf.pages[page_number] tables page.extract_tables() for idx, table in enumerate(tables, start1): print(f第 {page_number 1} 页第 {idx} 个表格) for row in table: print(row) print(- * 60) if __name__ __main__: # 0 表示第一页 extract_tables_from_pdf(file1.pdf, 0)6.3 把表格输出到 Excel办公自动化项目往往不满足于在控制台打印表格而希望把多个 PDF 表格汇总到 Excel。下面利用 pandas 和 openpyxl 完成写入。创建pdf_table_to_excel.py# 文件路径pdf_auto/pdf_table_to_excel.py import pdfplumber import pandas as pd def pdf_table_to_excel(pdf_path, excel_path): all_rows [] with pdfplumber.open(pdf_path) as pdf: for page in pdf.pages: tables page.extract_tables() for table in tables: for row in table: # 单元格为 None 时填空字符串避免写入 Excel 报错 cleaned_row [ if cell is None else cell for cell in row] all_rows.append(cleaned_row) if not all_rows: print(未提取到任何表格数据) return df pd.DataFrame(all_rows) df.to_excel(excel_path, indexFalse, headerFalse) print(f已导出 {len(all_rows)} 行数据到 {excel_path}) if __name__ __main__: pdf_table_to_excel(file1.pdf, table_output.xlsx)6.4 表格提取的常见坑表格提取并不是“万能识别”。如果 PDF 中的表格是图片或者通过扫描件生成pdfplumber 看不到文字对象这时需要先做 OCR。另外如果表格是跨页显示的不同页的列宽可能不一致直接拼接会错位需要指定提取边界并做后处理。常见做法是先用page.find_tables()查看 pdfplumber 检测到的表格区域再根据需求微调参数。例如tables page.find_tables() for table in tables: print(table.bbox) # 输出 bbox 左上角和右下角坐标这样能更清楚表格的识别范围便于调试。7. 实战四PDF 转 Word 的思路7.1 使用 pdf2docx 实现转换“把 PDF 转成 Word”是很多办公人员的高频需求但也是技术上容易踩坑的需求。PDF 本身保存的是固定版式转 Word 本质上是重新分析页面布局并生成可编辑段落。目前比较流行的方案是 pdf2docx 库。安装库pip install pdf2docx转换脚本# 文件路径pdf_auto/pdf_to_word.py from pdf2docx import Converter def pdf_to_word(pdf_path, docx_path): cv Converter(pdf_path) cv.convert(docx_path) cv.close() print(f转换完成{docx_path}) if __name__ __main__: pdf_to_word(file1.pdf, file1.docx)7.2 pdf2docx 的适用边界pdf2docx 转换的效果取决于源文件质量。如果 PDF 本身是从 Word 导出的纯文字文档转换后版式相对理想如果 PDF 是复杂宣传画册、艺术字体、多层图片背景转换结果可能会乱。扫描件转 Word 则需要先用 OCR 识别再按识别结果重新排版。因此在办公自动化流程中建议先明确需求是真的需要“可编辑 Word”还是只要“文字可复制”。如果只需要复制文字直接用 pdfplumber 提取文本再写入 Word 会更稳定。7.3 备选方案用 python-docx 生成结构化 Word如果只是把从 PDF 中清洗好的数据写入 Word 模板建议使用 python-docx。它比 pdf2docx 更容易控制最终样式。# 文件路径pdf_auto/write_docx.py from docx import Document def write_text_to_word(text_lines, output_path): doc Document() for line in text_lines: doc.add_paragraph(line) doc.save(output_path) print(fWord 文件已生成{output_path}) if __name__ __main__: write_text_to_word([第一行内容, 第二行内容], output.docx)注意使用前需要安装pip install python-docx很多办公自动化的报表生成、通知生成、会议纪要归档核心思路都是先用 pdfplumber 把 PDF 的内容读取为结构化数据再用 python-docx 生成带指定格式的新文档。这个方向比“格式还原”更实用也更可靠。8. 常见问题与排查思路8.1 问题列表在实际操作中读者容易遇到以下错误或异常。问题现象常见原因解决思路ModuleNotFoundError: No module named pypdf未安装或安装到了其他 Python 环境执行 pip install pypdf用 pip list 检查安装位置PdfReader 读取文件报错PDF 文件损坏或加密先用其他阅读器打开有密码则先用工具解除密码extract_text() 返回 None页面为扫描图片没有可提取的文字层改用 OCR 工具识别pdfplumber 提取表格乱行表格线条不清晰或跨页使用 page.find_tables() 查看 bbox调整 table_settings中文写入 Excel 乱码缺少字体或者编码配置问题使用 openpyxl/pandas 引擎时确认不是编码问题Excel 打开时注意内容格式PDF 转 Word 后排版变化大PDF 版式复杂转换算法无法完全还原调整需求改提取内容并使用模板生成 Word运行脚本后没有输出代码路径写错或文件在当前目录找不到使用 os.path.abspath 查看路径确认文件和脚本在同一目录8.2 加密 PDF 的处理办公中收到的 PDF 有时带有打开密码。此时使用 pypdf 读取前需要先用密码解密from pypdf import PdfReader reader PdfReader(encrypted.pdf) if reader.is_encrypted: reader.decrypt(your_password) print(reader.pages)需要提醒的是处理他人文件前要确保有合法授权。密码破解或绕过他人设置的访问控制可能涉及法律和安全问题在自动化项目中不要盲目操作。8.3 中文乱码问题从 PDF 提取中文文本时如果控制台出现乱码通常不是提取失败而是终端编码问题。Windows 命令行可以设置 UTF-8 编码或在代码中把文本写入文件后查看。如果是 pdfplumber 无法提取中文则考虑是字体编码映射问题可以尝试 PyMuPDF 提取对比。9. 最佳实践与工程建议9.1 善于使用备份和只读模式PDF 处理脚本在办公中常常需要覆盖或生成新文件。稳妥做法是先备份原始文件避免处理中途损坏。比如合并前把多个源 PDF 放到“待合并”目录输出到“合并结果”目录而不是在原目录上直接覆盖。这样即使脚本出现问题也不会丢失原始资料。9.2 日志与异常处理处理一个文件可能很简单但处理几百个文件时某个单独文件报错会导致整个流程中断。建议写一个统一的函数对每个文件做独立 try-except把失败信息记录到日志或结果列表中而不是直接让程序崩溃。import traceback result_log [] def safe_process_pdf(pdf_path): try: # 业务处理代码 pass except Exception: result_log.append({ path: pdf_path, error: traceback.format_exc() })这样可以在循环结束后统一查看哪些文件有问题再针对异常文件检查。9.3 批量文件遍历技巧如果要处理一个目录下所有 PDF常用的遍历方式是from pathlib import Path pdf_dir Path(./pdfs) for pdf_file in pdf_dir.glob(*.pdf): print(pdf_file)使用 Path 对象能避免 Windows 和 Linux 路径分隔符不一致的问题。glob 模式可根据文件名前缀精确匹配比如finance_*.pdf。9.4 提取结果尽量保留元数据从 PDF 提取文本或表格时建议在输出结果中保留来源文件名、页码、表格序号。这样在 Excel 汇总多份文件时可以追溯每行数据来自哪个 PDF 的哪一页方便后续核对。这一点很容易被忽略但在正式办公交付中非常重要。9.5 不要过度追求一步到位初学办公自动化时容易想写一个大脚本完成所有需求。更好的方式是先拆成小模块PDF 读取模块、表格清洗模块、Excel 输出模块、日志模块。后续即使更换具体库也能快速替换不至于重写全部逻辑。PDF 相关库的迭代不算慢模块化能降低维护成本。10. 后续学习与实践建议本篇文章完成了 PDF 办公自动化的“了解”阶段覆盖了基础概念、库选型和 4 个实战脚本算是入门 Python PDF 处理的完整闭环。如果你在实践中已经顺利完成上面例子下一步可以围绕以下方向继续练习用 schedule 库定时执行 PDF 归档脚本把脚本升级为守护式工具。将 pypdf、pdfplumber、pandas 组合把批量 PDF 报表的页面提取成标准化 Excel。把 pdf2docx、python-docx 结合制作“PDF 信息抽取 → 术语清洗 → Word 报告生成”的流水线。遇到扫描版 PDF 时引入 OCR 流程实现扫描文档文字识别。将多个脚本打包成简单的 Web 工具或带界面的桌面小软件方便不会 Python 的同事使用。办公自动化的价值不在代码本身而在于把重复劳动变成稳定可靠的自动化流程。只要在真实项目中把一个小环节打通接下来就会越用越顺手。
返回列表