利用Camelot识别pdf文件中的表格,除了必须加上flavor = 'stream' ,以及指定 table_areas识别区域之外,补充下在识别pdf表格时遇到的如多行数据、上下标等情况时的参数设置。
Camelot的安装及基本用法见Python解析PDF表格——PDFPlumber vs Camelot,
'pages'指定识别的页码
世卫组织报告中的表格位于第3-6页(如下图),指定识别的页码用'pages'参数。
增大'edge_tol'自动扩大识别区域
默认参数下,Camelot未能识别出全部的表格区域。如上图,第3页只识别出了15行,远小于表格所在页的行数。
除了在Python解析PDF表格——PDFPlumber vs Camelot介绍的用camelot.plot()命令查看表格所在区域然后再指定table_areas来处理外,也可以将'edge_tol'参数指定为一个较大的数字,如本例中将edge_tol = 500,让Camelot自动扩大识别区域。
camelot.plot(tables[0], kind='contour')
table_areas=['1,680,600,1']
'row_tol'识别包含多行文字的表格行
本例中,表头和个别数据条,单元格中包含了多行文本,有可能需要将多行文字自动合并,此时涉及到'row_tel'参数的调整。将该参数数值增大,Camelot会自动将多行文字合并,但这样也有可能带来意想不到的结果。
如上图,指定row_tol = 40虽然表头部分的多行文字被自动合并为了一行,合并后的文字用'\n'连接;但下面的数据条部分,也被Camelot给合并到了一起,这显然不是我们希望看到的结果。所以对于'row_tol'参数一定是要视情况灵活处理,也提醒我们在识别表格时需要随时检查中间结果是否识别正确。
本例中一些国家名称文字较长,如伊朗在表格中为Iran (Islamic Republic of),被分作两行。默认设置下,数据所在单元格和国家名称一共被识别为3行;而适当加大row_tol后(将'row_tol'指定为12),识别的结果数据所在单元格自动向上融合到了国家名称所在列的第一行。这样更便于在后续处理时中修正国家名称。
'flag_size'是否识别上(下)标文字
当单元格中存在上标时,指定'flage_size = True',Camelot会在上标下标中自动加上<s> </s>标签,如下图所示。
'split_text'分割字符串
'flage_size参数用于指定是否分割识别的字符串,如下图,'flage_size = True'时,表格外的字符串被分割后分到了各列。在本例中,这种自动分割的结果看起来并不是必须的,因为我们感兴趣的是表格内的数据部分,表格以外的文字本就会舍去。
'strip_text'自动替换文字
'strip_text参数用于指定是否分割识别的字符串,如下图,strip_text= '†‡§\n(<>)(</).'*,Camelot会在识别出文字后,自动删去类似上下标标准'<s>'、'</s>',跨行单元格的'\n'等等。
pandas.to_numeric转化识别结果转换为数字型
Camelot识别后结果,各国的疫情数据是个字符串而不是数字,因此还需要利用pandas.to_numeric,或是astype(int)将数据类型转换为数字型。
本例中上述参数设置如下。
table_p3 = camelot.read_pdf(r'./20200318-sitrep-58-covid-19.pdf', flavor='stream',
pages='3', flag_size=True, row_tol=10, table_areas=['1,680,600,1'],#edge_tol=500,
split_text=False, strip_text='*†‡§\n(<>)(</).')
最后用Pyecharts绘制地图,结果如下:
结论
- 对于有文字和表格混合排版的页面,建议采用指定table_areas指定表格识别区域,而不是增大edge_tol,来处理。
- row_tol的设置需要根据待识别表格的情况灵活选择,除非确有必要,不建议将该参数设置为过大的数数值。
- 当单元格中有上下标时,指定**flage_size = True **更为稳妥,否则有可能将类似 误做 ,造成数据不准确。
- split_text、strip_text根据表格的具体情况设定。
- 随时检查中间结果!随时检查中间结果!随时检查中间结果!