Python自动化办公:Word文档与PDF处理实战
文章目录
- Python自动化办公:Word文档与PDF处理实战
-
- 前言
- 一、python-docx:创建与编辑Word文档
- 二、读取和修改现有Word文档
- 三、实战:批量生成Word合同
- 四、PyPDF2:PDF合并、拆分与提取
- 五、提取PDF文本和元数据
- [✅ 亮点总结](#✅ 亮点总结)
- 适用场景
- 扩展方向
前言
在日常办公中,Word文档的生成与编辑、PDF文件的合并拆分提取是极其常见的需求。无论是自动生成合同、批量修改报告模板,还是整理扫描件PDF,手动操作都耗时耗力,而且容易出错。Python的python-docx 和PyPDF2库让我们能够以编程方式高效完成这些任务,实现真正的"一键自动化"。本文将带你系统学习这两个库的核心用法,从零基础到实战应用全覆盖。
学习建议:自动化办公的核心思路是"模板 + 数据填充"------先将文档的固定格式设计好(Word模板),再用Python程序动态填入变化的数据。这样的效率远高于每次都从零构建整个文档。对于追求高效率的开发者来说,这是一项投入产出比极高的技能。
一、python-docx:创建与编辑Word文档
python-docx是操作Office Open XML格式(.docx)的纯Python库。它不依赖Windows系统上的Word软件,可以在任何平台的服务器上运行------这意味着你写的自动化脚本可以直接部署到Linux服务器上批量处理文档。
bash
pip install python-docx
安装注意 :python-docx处理的是.docx格式(Office 2007之后的版本),不支持老旧的.doc格式。如果需要处理.doc文件,推荐使用
textract库或先将.doc手动转换为.docx。
理解对象模型:Document(文档) → Paragraph(段落) → Run(文本片段)。Run是python-docx中最小的样式单元------同一个段落中,如果前半部分是普通文字、后半部分需要加粗显示,就必须把这两部分分别放到不同的Run中。这是初学者最容易混淆的概念,也是面试中常被问到的知识点。
以下代码演示了从创建文档到添加标题、段落、表格、图片的完整流程:
python
from docx import Document
from docx.shared import Inches, Pt, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
doc = Document()
# 添加标题
doc.add_heading("项目计划书", level=1)
doc.add_heading("一、项目背景", level=2)
# 添加段落
paragraph = doc.add_paragraph("这是一个关于Python自动化办公的")
run = paragraph.add_run("示例项目")
run.bold = True
run.font.size = Pt(14)
run.font.color.rgb = RGBColor(0x42, 0x7C, 0xC4)
# 添加带样式的文本
doc.add_paragraph("项目目标:实现办公流程自动化", style="List Bullet")
doc.add_paragraph("预计周期:3个月", style="List Bullet")
# 添加表格
table = doc.add_table(rows=4, cols=3, style="Light Grid Accent 1")
headers = ["阶段", "任务", "负责人"]
for i, header in enumerate(headers):
table.rows[0].cells[i].text = header
data = [
["需求分析", "收集整理需求文档", "张三"],
["开发实现", "编码与单元测试", "李四"],
["测试上线", "集成测试与部署", "王五"],
]
for i, row_data in enumerate(data, 1):
for j, value in enumerate(row_data):
table.rows[i].cells[j].text = value
# 添加图片
doc.add_picture("logo.png", width=Inches(2.0))
doc.save("项目计划书.docx")
代码解读 :
Document()创建一个空白文档对象,这相当于Word软件中的"新建空白文档"。add_heading()添加标题,level参数从0到9对应不同的标题层级。add_paragraph()返回一个Paragraph对象,通过它的add_run()方法可以在段落后追加不同样式的文本。add_table(rows=4, cols=3)创建4行3列的表格------注意这里需要提前知道行列数,后续可以通过表格对象的add_row()方法动态追加行。
常见陷阱 :保存文档时,如果目标文件已被其他程序(如Word软件)打开,会抛出PermissionError。务必在保存前确保文件未被占用。另外,图片路径建议使用绝对路径,或者确保相对路径在运行脚本的工作目录下正确解析。
二、读取和修改现有Word文档
在实际工作中,我们更多时候是在已有文档模板的基础上做修改,而非从零创建。python-docx提供了完整的读取和遍历文档的能力:
python
from docx import Document
doc = Document("项目计划书.docx")
# 遍历所有段落
for para in doc.paragraphs:
print(f"[{para.style.name}] {para.text}")
# 读取表格
for table in doc.tables:
for row in table.rows:
cells = [cell.text for cell in row.cells]
print("\t".join(cells))
# 修改内容并保存
doc.paragraphs[1].text = "(更新版)项目背景"
doc.save("项目计划书_修订版.docx")
遍历技巧 :
doc.paragraphs返回文档中所有段落的列表,包括标题、正文、空白段落等。需要注意的是,表格中的文字不在doc.paragraphs中,需要单独通过doc.tables遍历。这也是初学者查找内容时常踩的坑------明明看到表格中有文字,遍历段落却找不到。
实际应用 :修改模板文档时,常见的做法是在模板中放入占位符(如{``{甲方}}、{``{金额}}),然后遍历所有段落和表格单元格,用str.replace()替换占位符内容。这样模板的设计和数据的填充完全分离,非技术人员也可以独立调整模板样式。
三、实战:批量生成Word合同
这是自动化办公最经典的应用场景之一。假设你需要为几十甚至上百家合作方生成格式一致的合同,手工操作不仅费时,还容易遗漏或出错。下面的代码展示了如何用Python批量生成:
python
from docx import Document
contracts = [
{"甲方": "公司A", "乙方": "公司X", "金额": 50000},
{"甲方": "公司B", "乙方": "公司Y", "金额": 80000},
{"甲方": "公司C", "乙方": "公司Z", "金额": 120000},
]
for contract in contracts:
doc = Document()
doc.add_heading("合作协议", level=1)
doc.add_paragraph(f"甲方:{contract['甲方']}")
doc.add_paragraph(f"乙方:{contract['乙方']}")
doc.add_paragraph(f"合同金额:{contract['金额']:,}元")
doc.add_paragraph("一、合作内容")
doc.add_paragraph("双方本着互利共赢的原则,就技术开发项目达成以下合作协议...")
filename = f"合同_{contract['甲方']}_{contract['乙方']}.docx"
doc.save(filename)
print(f"已生成: {filename}")
性能建议 :当合同数量很大(比如上千份)时,每份都
Document()然后save()的开销不小。优化的思路有两个:一是将模板作为文件复制后打开修改,而不是每次从零创建;二是使用多进程并行处理,充分利用多核CPU。但在实际项目中,数百份以内单进程足以在几秒到一两分钟内完成。
实际痛点:如果合同内容包含复杂的表格嵌套或特定排版,纯用python-docx构建会比较吃力。此时更好的方案是先用Word设计好模板文件,Python只负责打开模板、替换占位符、另存为新文件。这在面试中也经常被问到:"如何高效地批量生成复杂格式的Word文档?"
四、PyPDF2:PDF合并、拆分与提取
与Word操作不同,PDF是一种"只读友好"的格式------它主要用于分发和展示,而非编辑。Python处理PDF的库主要分为"创建PDF"和"操作现有PDF"两类。PyPDF2属于后者,专注于对已有PDF文件进行合并、拆分、旋转、元数据提取等操作。
bash
pip install PyPDF2
库的选择 :Python的PDF库生态比较复杂。
PyPDF2适合基础的合并拆分;pdfplumber擅长提取表格数据;reportlab用于从零创建PDF;fpdf2同样用于创建PDF但API更简单。选择哪个库取决于你的具体需求,不要用一个库做所有事。
合并多个PDF文件:
python
from PyPDF2 import PdfMerger
merger = PdfMerger()
pdf_files = ["报告_第一部分.pdf", "报告_第二部分.pdf", "报告_第三部分.pdf"]
for pdf in pdf_files:
merger.append(pdf)
merger.write("合并后的完整报告.pdf")
merger.close()
print("PDF合并完成!")
关键细节 :
merger.append()将PDF文件追加到合并列表中,顺序决定了最终输出文件的页面顺序。merger.close()不能省略------它负责写入输出文件并释放资源。如果你忘记调用close(),输出的PDF文件可能不完整或损坏,这是最常见的bug之一。
进阶用法 :merger.merge()方法可以在特定位置插入PDF页面。例如,你要在一份100页报告的"第5页"后插入一页封面,可以使用merger.merge(5, cover_pdf)实现精确的页面插入。
拆分PDF(提取指定页码范围):
python
from PyPDF2 import PdfReader, PdfWriter
reader = PdfReader("合并后的完整报告.pdf")
total_pages = len(reader.pages)
print(f"文档共 {total_pages} 页")
# 提取前5页另存为新文件
writer = PdfWriter()
for i in range(min(5, total_pages)):
writer.add_page(reader.pages[i])
with open("前5页摘录.pdf", "wb") as f:
writer.write(f)
# 按页码分组拆分
for start in range(0, total_pages, 10):
writer = PdfWriter()
end = min(start + 10, total_pages)
for i in range(start, end):
writer.add_page(reader.pages[i])
with open(f"拆分_第{start+1}-{end}页.pdf", "wb") as f:
writer.write(f)
拆分场景:实际工作中拆分PDF有两种意思------按页码范围拆分(如代码所示)和按内容拆分(如"按发票号码将合并的扫描PDF拆分为单张发票")。后者需要借助OCR或文本提取,单纯靠PyPDF2无法做到。
内存注意 :reader.pages会将整个PDF的页面对象加载到内存中。对于数百页的大PDF,内存消耗可以接受;但如果处理数千页的巨型PDF,建议考虑流式处理或分块读取。在实际项目中,100页以内的PDF用PyPDF2完全没问题。
五、提取PDF文本和元数据
python
from PyPDF2 import PdfReader
reader = PdfReader("合并后的完整报告.pdf")
# 提取元数据
meta = reader.metadata
print(f"标题: {meta.title}")
print(f"作者: {meta.author}")
print(f"页数: {len(reader.pages)}")
# 逐页提取文本
for i, page in enumerate(reader.pages):
text = page.extract_text()
print(f"\n--- 第{i+1}页 ---")
print(text[:200]) # 打印前200字符预览
文本提取的局限 :
extract_text()提取的文本质量取决于PDF本身的生成方式。如果PDF是从Word/文本转换而来的,提取效果很好;但如果是扫描件生成的图片型PDF,extract_text()无法提取任何文字------此时需要使用OCR技术(如Tesseract库)配合PyPDF2将图片转换为可编辑文本。
面试场景:"如何批量提取大量PDF中的关键信息?"------这道面试题考查的综合能力是:先用PyPDF2遍历PDF页面提取文本,再用正则表达式从文本中匹配日期、金额、合同号等关键字段,最后汇总到Excel中。这是自动化办公中非常典型的ETL流程。
python-docx的API设计直观,通过段落、Run、表格 等核心对象即可完成Word文档的创建与编辑;PyPDF2则提供了PDF合并、拆分、文本提取等基础而实用的功能。两者结合可以实现文档自动化处理的完整闭环。实际工作中,建议将模板文档预先设计好,Python只负责填充数据和生成,这样效率最高且输出质量最稳定。
✅ 亮点总结
python-docx的核心对象模型:Document → Paragraph → Run,层级清晰易于理解- Word 模板填充:通过占位符替换实现批量生成合同、报告、通知书
PyPDF2的 PDF 合并、拆分、旋转、元数据提取,覆盖日常 PDF 操作需求- 表格操作、图片插入、样式设置等进阶功能,满足报告类文档的生成需求
适用场景
- 合同/协议批量生成:用 Python 读取数据表,自动填充 Word 模板生成数百份合同
- 报告自动化:从数据库提取数据,生成带图表和分析文字的月报/年报 Word 文档
- PDF 文档管理:合并扫描件、提取 PDF 中的文本用于全文检索、按页拆分导出
扩展方向
- 学习
reportlab库,用纯 Python 代码生成高质量的 PDF 文档(无需 Word 模板) - 探索
pdfplumber库,获得比 PyPDF2 更强大的 PDF 表格数据提取能力 - 结合
python-pptx库,进一步实现 PowerPoint 演示文稿的自动化生成