我在银行做对公业务的时候,每个季度要处理几百份财务报表PDF。那些表格数据散落在不同页面,有的还跨页。手工复制粘贴真的崩溃,眼睛花了脑袋也大了。后来发现一个python库叫camelot-py,简直救了我的命。
这个库专门对付PDF里的表格。它不处理文字排版,不处理图片,只管表格。三行代码就能把表格完整提取出来。你不需要懂什么复杂算法,不需要折腾图像识别,甚至不需要搞清楚PDF的结构规范。
先安装:pip install camelot-py opencv-python ghostscript。注意版本问题,camelot目前只到0.10版本,opencv-py用4.5以上就行。ghostscript是必须的,它是底层引擎。如果不想装ghostscript,也可以用pdfminer.six代替,但camelot默认依赖它。
来看核心代码,真的只需要这么点:
import camelot tables = camelot.read_pdf('年报.pdf', pages='1-3')
tables[0].to_excel('年报_表格1.xlsx')第一行引入库。第二行读取PDF的1到3页,返回一个表格对象列表。第三行把第一个表格保存成Excel文件。这就是三行代码。实际工作里你可能需要指定页码范围,或者处理跨页表格,那只需要加一个参数。
pages参数支持单页'1'、范围'1-5'、甚至用逗号隔开多个页如'1,3,5'。跨页表格加上参数flavor='stream'就能处理。stream模式适合无边框的表格,比如word转出来的PDF。默认的lattice模式适合有线条边框的表格。
我处理过的案例,一个200页的PDF,里面包含20张表格。手工复制要两天,用这个库跑一遍,包括检查和调整参数的时间,总共不到一小时。表格里的日期、金额、数字完全准确,不需要二次核验。
遇到表格格式混乱的问题怎么办?比如同一页既有表格又有图片,或者表格里包含合并单元格。camelot提供了visual debugging功能。你可以在jupyter notebook里调用tables[0].df查看表格内容,调用tables[0].parsing_report查看提取的准确率。准确率低于80%的表格,需要调整参数。
参数调整主要两个方向:edge_tol控制单元格边缘检测的容差,默认50。数值太大容易合并单元格,数值太小会拆分单元格。 还有一个row_tol控制行高容差。我通常从50开始调,往低调到20,往高调到80,看哪个效果最好。
文件格式支持。camelot可以直接保存为csv、excel、json、html。我常用excel,因为会计部门只要xlsx文件。保存的时候注意文件名不能有中文,否则可能报错。如果保存excel报错,可以换成tables[0].to_csv('table.csv')再手动改后缀。
遇到PDF是扫描件的情况,camelot就没用了。扫描件本质是图片,需要先做OCR。你可以用pytesseract配合pdfplumber处理。但扫描件里的表格结构复杂,准确率会打折扣。有预算的话可以用商业库比如Adobe Extract API。
还有个坑要注意:camelot默认只处理文本类PDF,不能处理图片型PDF。判断方法很简单,用pdfplumber打开PDF,如果能看到文字内容就是文本型,否则可能是扫描件。文本型PDF三行代码搞定。扫描件可以先用ocrmyPDF转成文本型PDF,再用camelot提取。
我在项目群里分享过这个库,同事用了都说好。有个审计部的老哥,之前每个月花三天手工抄写年报数据,现在直接跑脚本,下午茶时间就能交差。他专门请我喝了杯星巴克。
如果你经常处理PDF表格,建议把这三行代码存成脚本,或者写个批处理文件。 放在桌面,拖拽文件进去就能跑。人生苦短,别跟PDF过不去。
夜雨聆风