Python批量处理PDF合同与发票的实战案例
更新时间:2026年07月07日 08:49:09 作者:张老师技术栈
别再手动一个个生成合同、提取发票了!这篇实战教程手把手教你用Python批量处理PDF合同和自动提取发票信息,直接上手就能用,学会这两个案例,办公效率翻倍,再也不用加班,需要的朋友可以参考下
之前讲了很多 PDF 的基础操作,这次用两个完整的实战案例把知识串起来——批量处理 PDF 合同和批量提取发票信息。
一、实战案例一:批量生成 PDF 合同
把 Excel 里的客户数据批量生成合同 PDF,这是办公自动化里最高频的需求。
1. 准备数据
import pandas as pd
# 模拟客户数据
data = {
"客户编号": ["KH001", "KH002", "KH003"],
"客户名称": ["北京科技有限公司", "上海信息有限公司", "广州贸易有限公司"],
"合同金额": [150000, 98000, 210000],
"签订日期": ["2026-07-01", "2026-07-05", "2026-07-10"],
"项目内容": ["数据分析系统开发", "爬虫数据采集服务", "可视化平台搭建"],
}
df = pd.DataFrame(data)
df.to_excel("客户数据.xlsx", index=False)
2. 安装依赖
pip install python-docx docx2pdf # 先生成 Word,再转 PDF
3. 生成合同
from docx import Document
from docx.shared import Pt, Cm, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
import pandas as pd
from datetime import datetime
import os
class ContractGenerator:
"""合同批量生成器"""
def __init__(self, template_path):
self.template_path = template_path
def generate_contract(self, customer):
"""为单个客户生成合同"""
doc = Document(self.template_path)
# 替换占位符
replacements = {
"{{客户编号}}": customer["客户编号"],
"{{客户名称}}": customer["客户名称"],
"{{合同金额}}": f"{customer['合同金额']:,.0f}",
"{{大写金额}}": self._num_to_cn(customer["合同金额"]),
"{{签订日期}}": customer["签订日期"],
"{{项目内容}}": customer["项目内容"],
}
for p in doc.paragraphs:
for key, val in replacements.items():
if key in p.text:
for run in p.runs:
if key in run.text:
run.text = run.text.replace(key, val)
# 保存
filename = f"合同_{customer['客户编号']}_{customer['客户名称']}.docx"
filepath = os.path.join("生成合同", filename)
os.makedirs("生成合同", exist_ok=True)
doc.save(filepath)
return filepath
def _num_to_cn(self, num):
"""金额转大写(简化版)"""
c_num = "零壹贰叁肆伍陆柒捌玖"
c_unit = "分角元拾佰仟万拾佰仟亿"
# 实际项目需要完善的大写金额转换
return f"{num}元整"
def batch_generate(self, excel_path):
"""批量生成"""
df = pd.read_excel(excel_path)
files = []
for _, row in df.iterrows():
path = self.generate_contract(row)
files.append(path)
print(f"已生成: {os.path.basename(path)}")
return files
# 使用
generator = ContractGenerator("合同模板.docx")
files = generator.batch_generate("客户数据.xlsx")
4. Word 转 PDF
from docx2pdf import convert
def batch_docx_to_pdf(docx_dir="生成合同", pdf_dir="生成PDF"):
"""批量把 Word 合同转成 PDF"""
os.makedirs(pdf_dir, exist_ok=True)
for f in os.listdir(docx_dir):
if f.endswith(".docx"):
docx_path = os.path.join(docx_dir, f)
pdf_path = os.path.join(pdf_dir, f.replace(".docx", ".pdf"))
convert(docx_path, pdf_path)
print(f"已转换: {f} → {os.path.basename(pdf_path)}")
# 使用
batch_docx_to_pdf()
二、实战案例二:批量提取发票信息
从一堆 PDF 发票中自动提取关键字段,导出到 Excel。
1. 文字型发票提取
import pdfplumber
import pandas as pd
import re
import os
class InvoiceExtractor:
"""发票信息提取器"""
def __init__(self):
self.fields = ["发票号码", "开票日期", "金额", "税额", "价税合计",
"销售方名称", "购买方名称", "货物名称"]
def extract_from_text(self, pdf_path):
"""从文字型 PDF 发票中提取信息"""
info = {"文件": os.path.basename(pdf_path)}
text = ""
with pdfplumber.open(pdf_path) as pdf:
for page in pdf.pages:
text += page.extract_text() or ""
# 发票号码
match = re.search(r"发票号码[::]\s*(\d+)", text)
if match:
info["发票号码"] = match.group(1)
# 开票日期
match = re.search(r"开票日期[::]\s*(\d{4}[\-\年]\d{1,2}[\-\月]\d{1,2})", text)
if match:
info["开票日期"] = match.group(1).replace("年", "-").replace("月", "-")
# 金额(价税合计)
match = re.search(r"价税合计[((]大写[))][^0-9]*([\d,]+\.\d{2})", text)
if match:
info["价税合计"] = match.group(1).replace(",", "")
# 销售方名称
match = re.search(r"销售方[名称]?[::]\s*(.+?)(?:\n|$)", text)
if match:
info["销售方名称"] = match.group(1).strip()
# 购买方名称
match = re.search(r"购买方[名称]?[::]\s*(.+?)(?:\n|$)", text)
if match:
info["购买方名称"] = match.group(1).strip()
return info
def extract_from_table(self, pdf_path):
"""从发票 PDF 的表格中提取商品明细"""
items = []
with pdfplumber.open(pdf_path) as pdf:
for page in pdf.pages:
tables = page.extract_tables()
for table in tables:
for row in table[1:]: # 跳过表头
if row and row[0] and len(row) >= 4:
items.append({
"货物名称": row[0],
"数量": row[1] if len(row) > 1 else "",
"单价": row[2] if len(row) > 2 else "",
"金额": row[3] if len(row) > 3 else "",
})
return items
def batch_extract(self, pdf_dir):
"""批量提取"""
all_data = []
for f in os.listdir(pdf_dir):
if f.endswith(".pdf"):
info = self.extract_from_text(os.path.join(pdf_dir, f))
all_data.append(info)
print(f"已提取: {f}")
df = pd.DataFrame(all_data)
df.to_excel("发票信息汇总.xlsx", index=False)
print(f"\n共提取 {len(all_data)} 张发票,已导出到 发票信息汇总.xlsx")
return df
# 使用
extractor = InvoiceExtractor()
extractor.batch_extract("发票PDF")
2. 扫描件发票(OCR)
import pytesseract
from PIL import Image
import pdfplumber
import io
def ocr_invoice(pdf_path):
"""OCR 识别扫描件发票"""
with pdfplumber.open(pdf_path) as pdf:
for i, page in enumerate(pdf.pages):
# 转图片
img = page.to_image(resolution=300)
img_path = f"temp_page_{i}.png"
img.save(img_path)
# OCR 识别
text = pytesseract.image_to_string(
Image.open(img_path),
lang="chi_sim+eng", # 中文 + 英文
)
# 提取关键信息
invoice_no = re.search(r"发票号码[::]\s*(\d+)", text)
total = re.search(r"价税合计[::]?\s*[¥¥]?([\d,]+\.\d{2})", text)
print(f"发票号码: {invoice_no.group(1) if invoice_no else '未识别'}")
print(f"价税合计: {total.group(1) if total else '未识别'}")
# 使用(需要安装 Tesseract-OCR 引擎)
# ocr_invoice("扫描发票.pdf")
三、实战案例三:合并多个 PDF
from PyPDF2 import PdfMerger, PdfReader, PdfWriter
import os
def merge_invoices(pdf_dir, output="合并发票.pdf"):
"""合并多个发票 PDF 为一个文件"""
merger = PdfMerger()
files = sorted([f for f in os.listdir(pdf_dir) if f.endswith(".pdf")])
for f in files:
merger.append(os.path.join(pdf_dir, f))
merger.write(output)
merger.close()
print(f"合并完成,共 {len(files)} 个文件 → {output}")
def split_into_single_pages(pdf_path, output_dir="拆分明细"):
"""将合并的 PDF 按页拆分为单张"""
os.makedirs(output_dir, exist_ok=True)
reader = PdfReader(pdf_path)
for i in range(len(reader.pages)):
writer = PdfWriter()
writer.add_page(reader.pages[i])
output = os.path.join(output_dir, f"第{i+1}页.pdf")
with open(output, "wb") as f:
writer.write(f)
print(f"已拆分 {len(reader.pages)} 页到 {output_dir}")
四、完整工作流
def daily_invoice_pipeline(input_dir):
"""每日发票处理流水线"""
print("开始发票处理流水线...")
# 1. 提取信息
extractor = InvoiceExtractor()
df = extractor.batch_extract(input_dir)
# 2. 合并 PDF
merge_invoices(input_dir, f"发票汇总_{datetime.now().strftime('%Y%m%d')}.pdf")
# 3. 生成统计报表
if not df.empty and "价税合计" in df.columns:
total = df["价税合计"].sum()
count = len(df)
print(f"\n统计:共 {count} 张发票,总金额 {total:,.2f} 元")
print("处理完成!")
# 使用
daily_invoice_pipeline("发票PDF")
五、各场景注意事项
| 场景 | 注意事项 |
|---|---|
| 合同模板 | 占位符不要用 {name} 要用 {{name}},避免正则冲突 |
| 发票提取 | 不同公司的发票格式不同,需要针对性调整正则 |
| 扫描件 OCR | 必须安装 Tesseract 引擎和中文语言包 |
| PDF 合并 | 按文件名排序保证顺序,建议文件名加日期前缀 |
| 批量处理 | 先处理一个样本调通,再批量全跑 |
以上就是Python批量处理PDF合同与发票的实战案例的详细内容,更多关于Python批量处理PDF合同与发票的资料请关注脚本之家其它相关文章!
相关文章
PyCharm+Pipenv虚拟环境开发和依赖管理的教程详解
这篇文章主要介绍了PyCharm+Pipenv虚拟环境作开发和依赖管理的教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2020-04-04
Python使用PaddleOCR实现PDF/图片文字识别与版面还原
本文介绍了如何利用 PaddleOCR 实现对 PDF 文件或图片 的文字识别,并在识别后将文本内容按照 原始版面位置 进行还原重建,感兴趣的小伙伴可以了解下2025-11-11
Python+pandas编写命令行脚本操作excel的tips详情
这篇文章主要介绍了Python+pandas编写命令行脚本操作excel的tips详情,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下2022-07-07


最新评论