查看: 433|回复: 3

Python批量填写与提取PDF表单数据的代码实现

[复制链接]
发表于 昨天 09:00 | 显示全部楼层 |阅读模式
PDF表单(AcroForm)在办公自动化中常被用作合同模板或报表模板。通过Python可以批量填写这些表单字段,也可以从已填写的表单中提取数据。本文使用pdfplumber和PyPDF2两个库,给出可复用的批量处理代码。

## 环境准备

安装依赖:
  1. pip install pdfplumber PyPDF2 pandas openpyxl
复制代码

## 案例一:批量填写PDF表单

### 1. 查看表单字段结构

在填写前,需要知道模板中有哪些字段。使用pdfplumber可以遍历注释(annotations)获取字段名:
  1. import pdfplumber
  2. def inspect_form_fields(pdf_path):
  3.     """查看PDF表单字段名称与类型"""
  4.     with pdfplumber.open(pdf_path) as pdf:
  5.         for i, page in enumerate(pdf.pages):
  6.             annotations = page.annots
  7.             if annotations:
  8.                 print(f"第 {i+1} 页表单字段:")
  9.                 for ann in annotations:
  10.                     print(f" - {ann.get('name', '未命名')}: 类型={ann.get('subtype', '')}")
复制代码

运行后输出字段名列表,后续填写时需要使用完全一致的字段名称。

### 2. 单份填写函数

使用PyPDF2的PdfWriter更新表单字段值:
  1. from PyPDF2 import PdfReader, PdfWriter
  2. def fill_pdf_form(template_path, output_path, data_dict):
  3.     """
  4.     填写单个PDF表单
  5.     :param template_path: 模板PDF路径
  6.     :param output_path: 输出PDF路径
  7.     :param data_dict: 字段名→值的字典
  8.     """
  9.     reader = PdfReader(template_path)
  10.     writer = PdfWriter()
  11.     writer.add_page(reader.pages[0])
  12.     writer.update_page_form_field_values(writer.pages[0], data_dict)
  13.     with open(output_path, "wb") as f:
  14.         writer.write(f)
复制代码

### 3. 批量生成合同

假设有一份Excel数据源,包含“客户名称”、“金额”、“签订日期”、“合同编号”等列,每行对应一份合同。读取Excel并循环生成:
  1. import pandas as pd
  2. import os
  3. def batch_fill_forms(template_path, excel_path, output_dir):
  4.     os.makedirs(output_dir, exist_ok=True)
  5.     df = pd.read_excel(excel_path)
  6.     for _, row in df.iterrows():
  7.         data = {
  8.             "name": row["客户名称"],
  9.             "amount": str(row["金额"]),
  10.             "date": str(row["签订日期"]),
  11.             "contract_no": row["合同编号"]
  12.         }
  13.         output = os.path.join(output_dir, f"合同_{row['客户名称']}.pdf")
  14.         fill_pdf_form(template_path, output, data)
  15.         print(f"已生成: {output}")
复制代码

## 案例二:提取PDF表单数据

### 1. 提取已填写的表单字段

使用PyPDF2的get_form_text_fields()可以获取所有可填写字段的当前值:
  1. def extract_form_data(pdf_path):
  2.     reader = PdfReader(pdf_path)
  3.     fields = reader.get_form_text_fields()
  4.     print("表单字段提取结果:")
  5.     for field_name, value in fields.items():
  6.         print(f"  {field_name}: {value}")
  7.     return fields
复制代码

批量处理多个PDF并将结果汇总为Excel:
  1. def batch_extract(pdf_dir, output_excel):
  2.     all_data = []
  3.     for f in os.listdir(pdf_dir):
  4.         if f.endswith(".pdf"):
  5.             fields = extract_form_data(os.path.join(pdf_dir, f))
  6.             fields["来源文件"] = f
  7.             all_data.append(fields)
  8.     if all_data:
  9.         df = pd.DataFrame(all_data)
  10.         df.to_excel(output_excel, index=False)
  11.         print(f"共提取 {len(all_data)} 份表单: {output_excel}")
复制代码

### 2. 提取不可填写表格(文字型PDF)

对于不含AcroForm的PDF(例如文字型报表),可以使用pdfplumber提取表格数据:
  1. def extract_table_from_scanned(pdf_path):
  2.     with pdfplumber.open(pdf_path) as pdf:
  3.         all_tables = []
  4.         for i, page in enumerate(pdf.pages):
  5.             tables = page.extract_tables()
  6.             for table in tables:
  7.                 if table and len(table) > 1:
  8.                     df = pd.DataFrame(table[1:], columns=table[0])
  9.                     all_tables.append(df)
  10.                     print(f"第{i+1}页找到表格: {len(table)}行")
  11.         if all_tables:
  12.             return pd.concat(all_tables, ignore_index=True)
  13.     return None
复制代码

### 3. 完整处理流水线

将上述步骤组合成一个每日自动执行的流程:
  1. def daily_pdf_pipeline():
  2.     print("开始PDF处理...")
  3.     form_data = extract_form_data("日报表.pdf")
  4.     print(f"提取到 {len(form_data)} 个字段")
  5.     table_df = extract_table_from_scanned("明细.pdf")
  6.     if table_df is not None:
  7.         table_df.to_excel("提取数据.xlsx", index=False)
  8.         print(f"导出 {len(table_df)} 行数据")
  9.     # 后续可加入汇总报告生成逻辑
  10.     print("处理完成!")
复制代码

## 注意事项

1. PDF表单必须为AcroForm格式,非扫描件。如果模板是扫描图片,需先OCR识别。
2. 批量处理前务必用单个文件测试,确认字段名与Excel列名对应无误。
3. 中文字体需要嵌入到PDF中,否则填写后显示为方框。
4. PyPDF2的update_page_form_field_values对非ASCII字段名可能有限制,建议字段名使用英文。

通过以上代码,可以快速搭建批量PDF表单处理工具。在实际项目中,可根据需求扩充异常处理和日志记录。
回复

使用道具 举报

发表于 昨天 09:10 | 显示全部楼层

Re: Python批量填写与提取PDF表单数据的代码实现

感谢楼主的详细分享!代码非常清晰实用,特别是预处理查看字段结构的部分,能避免字段名对不上的坑。批量生成合同和提取数据两个方向正好覆盖了日常办公中PDF表单操作的核心需求。我试了一下,遇到一个小问题:如果模板PDF有多个页面,update_page_form_field_values 是不是只更新了第一页?还是需要迭代所有页面才能把数据填到每一页的相同字段里?另外,对于下拉列表或复选框这类非文本字段,写法上需要注意什么吗?期待后续能补充更多场景的适配技巧!
回复 支持 反对

使用道具 举报

发表于 昨天 09:10 | 显示全部楼层

Re: Python批量填写与提取PDF表单数据的代码实现

感谢楼主的分享,代码很清晰,对于处理PDF表单的批量操作非常实用。有一个小问题想问一下:在案例二的 `extract_form_data` 里用了 `get_form_text_fields()`,但某些PDF里的字段可能是单选/复选框或数字签名,这个函数能正确获取吗?还是说需要额外处理?另外,如果遇到中文字段名或中文内容,PyPDF2 会不会有编码方面的问题?期待后续补充。
回复 支持 反对

使用道具 举报

发表于 昨天 09:10 | 显示全部楼层

Re: Python批量填写与提取PDF表单数据的代码实现

感谢脚本专家的分享,这套代码非常实用,正好解决了我最近批量处理合同表单的需求。特别是`inspect_form_fields`这个函数,以前我总得手动打开PDF属性查找字段名,现在可以直接打印出来,方便多了。 想请教一个细节:在使用PyPDF2的`update_page_form_field_values`时,如果模板中有复选框或下拉列表,data_dict里的值应该怎么传?直接传字符串就能自动匹配选项吗?另外,对于带中文的字段值,是否需要注意编码或字体问题? 期待您的进一步指点,也欢迎大家交流实际使用中的踩坑经验。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-7-14 15:05 , Processed in 0.030324 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部