Python 自动化之批量处理 PDF 合同与发票——实战案例 之前讲了很多 PDF 的基础操作这次用两个完整的实战案例把知识串起来——批量处理 PDF 合同和批量提取发票信息。一、实战案例一批量生成 PDF 合同把 Excel 里的客户数据批量生成合同 PDF这是办公自动化里最高频的需求。1. 准备数据importpandasaspd# 模拟客户数据data{客户编号:[KH001,KH002,KH003],客户名称:[北京科技有限公司,上海信息有限公司,广州贸易有限公司],合同金额:[150000,98000,210000],签订日期:[2026-07-01,2026-07-05,2026-07-10],项目内容:[数据分析系统开发,爬虫数据采集服务,可视化平台搭建],}dfpd.DataFrame(data)df.to_excel(客户数据.xlsx,indexFalse)2. 安装依赖pipinstallpython-docx docx2pdf# 先生成 Word再转 PDF3. 生成合同fromdocximportDocumentfromdocx.sharedimportPt,Cm,Inches,RGBColorfromdocx.enum.textimportWD_ALIGN_PARAGRAPHimportpandasaspdfromdatetimeimportdatetimeimportosclassContractGenerator:合同批量生成器def__init__(self,template_path):self.template_pathtemplate_pathdefgenerate_contract(self,customer):为单个客户生成合同docDocument(self.template_path)# 替换占位符replacements{{{客户编号}}:customer[客户编号],{{客户名称}}:customer[客户名称],{{合同金额}}:f{customer[合同金额]:,.0f},{{大写金额}}:self._num_to_cn(customer[合同金额]),{{签订日期}}:customer[签订日期],{{项目内容}}:customer[项目内容],}forpindoc.paragraphs:forkey,valinreplacements.items():ifkeyinp.text:forruninp.runs:ifkeyinrun.text:run.textrun.text.replace(key,val)# 保存filenamef合同_{customer[客户编号]}_{customer[客户名称]}.docxfilepathos.path.join(生成合同,filename)os.makedirs(生成合同,exist_okTrue)doc.save(filepath)returnfilepathdef_num_to_cn(self,num):金额转大写简化版c_num零壹贰叁肆伍陆柒捌玖c_unit分角元拾佰仟万拾佰仟亿# 实际项目需要完善的大写金额转换returnf{num}元整defbatch_generate(self,excel_path):批量生成dfpd.read_excel(excel_path)files[]for_,rowindf.iterrows():pathself.generate_contract(row)files.append(path)print(f已生成:{os.path.basename(path)})returnfiles# 使用generatorContractGenerator(合同模板.docx)filesgenerator.batch_generate(客户数据.xlsx)4. Word 转 PDFfromdocx2pdfimportconvertdefbatch_docx_to_pdf(docx_dir生成合同,pdf_dir生成PDF):批量把 Word 合同转成 PDFos.makedirs(pdf_dir,exist_okTrue)forfinos.listdir(docx_dir):iff.endswith(.docx):docx_pathos.path.join(docx_dir,f)pdf_pathos.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. 文字型发票提取importpdfplumberimportpandasaspdimportreimportosclassInvoiceExtractor:发票信息提取器def__init__(self):self.fields[发票号码,开票日期,金额,税额,价税合计,销售方名称,购买方名称,货物名称]defextract_from_text(self,pdf_path):从文字型 PDF 发票中提取信息info{文件:os.path.basename(pdf_path)}textwithpdfplumber.open(pdf_path)aspdf:forpageinpdf.pages:textpage.extract_text()or# 发票号码matchre.search(r发票号码[:]\s*(\d),text)ifmatch:info[发票号码]match.group(1)# 开票日期matchre.search(r开票日期[:]\s*(\d{4}[\-\年]\d{1,2}[\-\月]\d{1,2}),text)ifmatch:info[开票日期]match.group(1).replace(年,-).replace(月,-)# 金额价税合计matchre.search(r价税合计[(]大写[)][^0-9]*([\d,]\.\d{2}),text)ifmatch:info[价税合计]match.group(1).replace(,,)# 销售方名称matchre.search(r销售方[名称]?[:]\s*(.?)(?:\n|$),text)ifmatch:info[销售方名称]match.group(1).strip()# 购买方名称matchre.search(r购买方[名称]?[:]\s*(.?)(?:\n|$),text)ifmatch:info[购买方名称]match.group(1).strip()returninfodefextract_from_table(self,pdf_path):从发票 PDF 的表格中提取商品明细items[]withpdfplumber.open(pdf_path)aspdf:forpageinpdf.pages:tablespage.extract_tables()fortableintables:forrowintable[1:]:# 跳过表头ifrowandrow[0]andlen(row)4:items.append({货物名称:row[0],数量:row[1]iflen(row)1else,单价:row[2]iflen(row)2else,金额:row[3]iflen(row)3else,})returnitemsdefbatch_extract(self,pdf_dir):批量提取all_data[]forfinos.listdir(pdf_dir):iff.endswith(.pdf):infoself.extract_from_text(os.path.join(pdf_dir,f))all_data.append(info)print(f已提取:{f})dfpd.DataFrame(all_data)df.to_excel(发票信息汇总.xlsx,indexFalse)print(f\n共提取{len(all_data)}张发票已导出到 发票信息汇总.xlsx)returndf# 使用extractorInvoiceExtractor()extractor.batch_extract(发票PDF)2. 扫描件发票OCRimportpytesseractfromPILimportImageimportpdfplumberimportiodefocr_invoice(pdf_path):OCR 识别扫描件发票withpdfplumber.open(pdf_path)aspdf:fori,pageinenumerate(pdf.pages):# 转图片imgpage.to_image(resolution300)img_pathftemp_page_{i}.pngimg.save(img_path)# OCR 识别textpytesseract.image_to_string(Image.open(img_path),langchi_simeng,# 中文 英文)# 提取关键信息invoice_nore.search(r发票号码[:]\s*(\d),text)totalre.search(r价税合计[:]?\s*[¥]?([\d,]\.\d{2}),text)print(f发票号码:{invoice_no.group(1)ifinvoice_noelse未识别})print(f价税合计:{total.group(1)iftotalelse未识别})# 使用需要安装 Tesseract-OCR 引擎# ocr_invoice(扫描发票.pdf)三、实战案例三合并多个 PDFfromPyPDF2importPdfMerger,PdfReader,PdfWriterimportosdefmerge_invoices(pdf_dir,output合并发票.pdf):合并多个发票 PDF 为一个文件mergerPdfMerger()filessorted([fforfinos.listdir(pdf_dir)iff.endswith(.pdf)])forfinfiles:merger.append(os.path.join(pdf_dir,f))merger.write(output)merger.close()print(f合并完成共{len(files)}个文件 →{output})defsplit_into_single_pages(pdf_path,output_dir拆分明细):将合并的 PDF 按页拆分为单张os.makedirs(output_dir,exist_okTrue)readerPdfReader(pdf_path)foriinrange(len(reader.pages)):writerPdfWriter()writer.add_page(reader.pages[i])outputos.path.join(output_dir,f第{i1}页.pdf)withopen(output,wb)asf:writer.write(f)print(f已拆分{len(reader.pages)}页到{output_dir})四、完整工作流defdaily_invoice_pipeline(input_dir):每日发票处理流水线print(开始发票处理流水线...)# 1. 提取信息extractorInvoiceExtractor()dfextractor.batch_extract(input_dir)# 2. 合并 PDFmerge_invoices(input_dir,f发票汇总_{datetime.now().strftime(%Y%m%d)}.pdf)# 3. 生成统计报表ifnotdf.emptyand价税合计indf.columns:totaldf[价税合计].sum()countlen(df)print(f\n统计共{count}张发票总金额{total:,.2f}元)print(处理完成)# 使用daily_invoice_pipeline(发票PDF)五、各场景注意事项场景注意事项合同模板占位符不要用 {name} 要用 {{name}}避免正则冲突发票提取不同公司的发票格式不同需要针对性调整正则扫描件 OCR必须安装 Tesseract 引擎和中文语言包PDF 合并按文件名排序保证顺序建议文件名加日期前缀批量处理先处理一个样本调通再批量全跑 觉得有用的话点赞 关注【张老师技术栈】吧每周更新 Java/Python/爬虫 实战干货不让你白来。

相关新闻

最新新闻

OpenClaw智能体框架解析:从部署到多模型与Skill扩展实践

OpenClaw智能体框架解析:从部署到多模型与Skill扩展实践

这次我们来看 OpenClaw。项目本身不复杂,复杂的是它和微信、飞书、钉钉、本地模型、NAS、云服务器之间的组合玩法。OpenClaw 维护者圆桌视频已经上线,社区里关于安装、部署、模型切换、skill 编写、接入办公软件的讨论也明显多起来。如果你还没搞清楚 Op…

2026/8/31 17:50:36
Cohere Parse低价策略:文档解析如何成为AI应用数据管线的新基座?

Cohere Parse低价策略:文档解析如何成为AI应用数据管线的新基座?

做 AI 应用的人,应该都有过这样的体会:模型选型、Prompt 调优、向量库和评测体系都已经跑通了,结果被“文档解析”卡在原地。合同 PDF 里表格跨页、发票扫描件里文字歪斜、PPT 转出的文本丢掉了层级结构、Word 文件里的批注和页眉页脚混在一起…

2026/8/31 17:50:36
消费级GPS与单板电脑搭建Stratum 1 PTP Grandmaster全指南

消费级GPS与单板电脑搭建Stratum 1 PTP Grandmaster全指南

Stratum 1 PTP Grandmaster,简单说就是一台靠 GPS 接收卫星时间、再通过 PTP(精确时间协议)给局域网内设备提供高精度时间同步的“主时钟”。这类设备在实验室、测试平台、音视频同步、工业控制和网络时延测量场景里非常常见,但商…

2026/8/31 17:50:36
展销会临时工排班优化实战:运筹建模与人性约束

展销会临时工排班优化实战:运筹建模与人性约束

简介:本资源是2026年东三省数学建模竞赛B题——大型展销会临时工招聘与排班优化问题的完整解决方案,面向数学建模参赛学生、高校课程实践者及运筹优化初学者。内容涵盖问题分析、三阶段建模(组内排班、跨天跨组调度、日内动态调整&#xff09…

2026/8/31 17:50:36
低成本搭建Stratum 1 PTP Grandmaster:从原理到实践

低成本搭建Stratum 1 PTP Grandmaster:从原理到实践

我不是第一次看到有人想用低成本硬件搭一个Stratum 1 PTP Grandmaster。做网络和设备时间同步时,这个目标听起来像是专业机房才用得上的东西,但它的核心需求其实很普通:你需要一个能对外发布可信时间的主时钟,而且这个信号不能依赖…

2026/8/31 17:50:36
SpringBoot+Vue构建在线OJ:沙箱判题与全栈实践

SpringBoot+Vue构建在线OJ:沙箱判题与全栈实践

简介:本资源是一个面向计算机专业学生、后端与前端开发者及算法竞赛教学者的在线代码评测系统实战项目,解决OJ(Online Judge)平台从零搭建的核心需求,涵盖用户管理、题目维护与实时代码评测等典型场景。压缩包共120个文…

2026/8/31 17:45:36