利用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根據表格的具體情況設定。
- 隨時檢查中間結果!隨時檢查中間結果!隨時檢查中間結果!