camelot-py默认提取pdf表格不可靠,因其lattice模式依赖显式边框、stream模式易受页眉页脚干扰,且不返回坐标与置信度;需结合pdfplumber定位区域,混合flavor、手动设table_areas和columns,并校验accuracy、空值及可视化覆盖。

camelot-py 能提取 PDF 表格,但默认设置下极易漏行、错列、吞空格,尤其对带合并单元格、浅色边框或扫描件(哪怕 OCR 过)的报表完全失效——这不是你代码写错了,是它根本没被设计来处理真实业务 PDF。
为什么 camelot.read_pdf() 直接调用基本不可靠
camelot 默认用 lattice 模式找线框、stream 模式靠文字位置聚类,但实际报表中:边框常被加粗/虚线/颜色淡化;表头和数据行字体大小不一致;页眉页脚干扰坐标;多页表格结构微调就会让后续页识别崩坏。更关键的是,read_pdf() 不返回原始坐标或置信度,出错了只能盲猜调参。
-
flavor="lattice"对无显式边框的 PDF(如 Word 导出 PDF)直接返回空列表 -
flavor="stream"在跨页表格中常把页脚文字误判为表尾,截断数据 - 未指定
pages时,默认只读第一页,且不报错提示 -
suppress_warnings=True会掩盖Unable to parse table这类关键日志
必须手动限定区域 + 切换 flavor 的实操组合
先用 pdfplumber 快速打开 PDF 看布局(不用装新库:pip install pdfplumber),定位表格左上右下坐标(单位:pt),再喂给 camelot 做精准切割。同一份 PDF 往往需要混合两种 flavor:表头用 stream(靠字体大小区分),主体用 lattice(若边框清晰)。
import camelot
# 例:从第3页提取坐标 (x0=100, y0=250, x1=500, y1=600) 内的表格
tables = camelot.read_pdf(
"report.pdf",
pages="3",
flavor="lattice",
table_areas=["100,600,500,250"], # 注意:y 坐标倒置,y0 是上边界,y1 是下边界
columns=["150,200,300,400"], # 强制竖线位置,防列错位
split_text=True, # 处理被空格/换行切开的单元格
flag_size=True # 把字号突变当标题信号(对表头有效)
)
-
table_areas必须是字符串列表,格式为"x0,y1,x1,y0"(PDF 坐标系 y 向上为正,但 camelot 输入要求 y1 > y0,即数值上“上边界”比“下边界”小) - 多个表格区域用多个字符串,如
["100,600,500,250", "100,200,500,100"] -
columns不是列数,是每条竖线的 x 坐标(从左到右),少写一条就可能合并两列
提取后必须校验的三个硬指标
camelot 返回的 tables 是 TableList 对象,不是 DataFrame。不做清洗直接 .df 会埋雷:
- 检查
tables[0].parsing_report["accuracy"]—— 低于 85 表示识别质量差,别硬用 - 执行
tables[0].to_pandas().isna().sum().sum(),非零说明有空单元格被吞(常见于合并单元格未展开) - 对比原始 PDF 页:用
tables[0].plot()可视化识别框,确认是否覆盖全部行,尤其注意最后几行是否被截断
遇到合并单元格,camelot 默认不展开。得手动补:df = tables[0].df.replace('', pd.NA).ffill(axis=0)(按列向下填充),但前提是能确认哪些列是主键列。
真正难的不是调通 camelot,而是判断哪一页、哪个区域、用哪种 flavor、配哪组 columns 坐标——这些没法自动化,必须人工看三页样例 PDF 才能定。别指望一个参数跑全量,也别在 lattice 失败时反复调 line_scale,先切到 stream + 坐标限定试试。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











