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合同与发票的资料请关注脚本之家其它相关文章!

相关文章

  • Django基础知识与基本应用入门教程

    Django基础知识与基本应用入门教程

    这篇文章主要介绍了Django基础知识与基本应用,结合实例形式分析了Django框架基本的项目创建、启动、查看版本等操作,并结合一个简单的blog应用示例分析了Django的基本使用方法,需要的朋友可以参考下
    2018-07-07
  • PyCharm+Pipenv虚拟环境开发和依赖管理的教程详解

    PyCharm+Pipenv虚拟环境开发和依赖管理的教程详解

    这篇文章主要介绍了PyCharm+Pipenv虚拟环境作开发和依赖管理的教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • Python排序函数的使用方法详解

    Python排序函数的使用方法详解

    这篇文章主要给大家介绍了关于Python排序函数使用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • 使用Python旋转PDF页面的多种方法与实用技巧

    使用Python旋转PDF页面的多种方法与实用技巧

    在处理 PDF 文档时,页面方向不正确是一个常见的问题,本文将详细介绍如何使用 Spire.PDF for Python 库旋转 PDF 页面,涵盖创建新 PDF 时设置旋转,旋转现有 PDF 页面等多种场景,帮助你构建完整的 PDF 页面管理解决方案
    2026-06-06
  • Python使用PaddleOCR实现PDF/图片文字识别与版面还原

    Python使用PaddleOCR实现PDF/图片文字识别与版面还原

    本文介绍了如何利用 PaddleOCR 实现对 PDF 文件或图片 的文字识别,并在识别后将文本内容按照 原始版面位置 进行还原重建,感兴趣的小伙伴可以了解下
    2025-11-11
  • 详解Python3 pickle模块用法

    详解Python3 pickle模块用法

    pickle模块中的两个主要函数是dump()和load(),这篇文章主要介绍了Python3 pickle模块用法,需要的朋友可以参考下
    2019-09-09
  • Python+pandas编写命令行脚本操作excel的tips详情

    Python+pandas编写命令行脚本操作excel的tips详情

    这篇文章主要介绍了Python+pandas编写命令行脚本操作excel的tips详情,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
    2022-07-07
  • python3.x 将byte转成字符串的方法

    python3.x 将byte转成字符串的方法

    今天小编就为大家分享一篇python3.x 将byte转成字符串的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07
  • Python PEP8代码规范常见问题以及解决方案

    Python PEP8代码规范常见问题以及解决方案

    PEP8是Python的代码规范,本文总结了常见的PEP8代码规范问题及解决方法,帮助开发者编写规范的代码
    2024-11-11
  • Python实现双轴组合图表柱状图和折线图的具体流程

    Python实现双轴组合图表柱状图和折线图的具体流程

    这篇文章主要介绍了Python双轴组合图表柱状图+折线图,Python绘制双轴组合的关键在plt库的twinx()函数,具体实例代码跟随小编一起看看吧
    2021-08-08

最新评论