python读取pdf表格_【Python 库】解析PDF文本及表格——pdfminer、tabula、pdfplumber 的用法及对比...
pdf 是個異常坑爹的東西,有很多處理 pdf 的庫,但是沒有完美的。
一、pdfminer3k
pdfminer3k 是 pdfminer 的 python3 版本,主要用于讀取 pdf 中的文本。
網上有很多 pdfminer3k 的代碼示例,看過以后,只想吐槽一下,太復雜了,有違 python 的簡潔。
from pdfminer.pdfparser importPDFParser, PDFDocumentfrom pdfminer.pdfinterp importPDFResourceManager, PDFPageInterpreterfrom pdfminer.converter importPDFPageAggregatorfrom pdfminer.layout importLAParams, LTTextBoxfrom pdfminer.pdfinterp importPDFTextExtractionNotAllowed
path= "test.pdf"
#用文件對象來創建一個pdf文檔分析器
praser = PDFParser(open(path, 'rb'))#創建一個PDF文檔
doc =PDFDocument()#連接分析器 與文檔對象
praser.set_document(doc)
doc.set_parser(praser)#提供初始化密碼#如果沒有密碼 就創建一個空的字符串
doc.initialize()#檢測文檔是否提供txt轉換,不提供就忽略
if notdoc.is_extractable:raisePDFTextExtractionNotAllowedelse:#創建PDf 資源管理器 來管理共享資源
rsrcmgr =PDFResourceManager()#創建一個PDF設備對象
laparams =LAParams()
device= PDFPageAggregator(rsrcmgr, laparams=laparams)#創建一個PDF解釋器對象
interpreter =PDFPageInterpreter(rsrcmgr, device)#循環遍歷列表,每次處理一個page的內容
for page indoc.get_pages():
interpreter.process_page(page)#接受該頁面的LTPage對象
layout =device.get_result()#這里layout是一個LTPage對象,里面存放著這個 page 解析出的各種對象
#包括 LTTextBox, LTFigure, LTImage, LTTextBoxHorizontal 等
for x inlayout:ifisinstance(x, LTTextBox):print(x.get_text().strip())
pdfminer 對于表格的處理非常的不友好,能提取出文字,但是沒有格式:
pdf表格截圖:
代碼運行結果:
想把這個結果還原成表格可不容易,加的規則太多必然導致通用性的下降。
二、tabula-py
tabula 是專門用來提取PDF表格數據的,同時支持PDF導出為CSV、Excel格式,但是這工具是用 java 寫的,依賴 java7/8。tabula-py 就是對它做了一層 python 的封裝,所以也依賴 java7/8。
代碼很簡單:
importtabula
path= 'test.pdf'df= tabula.read_pdf(path, encoding='gbk', pages='all')for indexs indf.index:print(df.loc[indexs].values)#tabula.convert_into(path, os.path.splitext(path)[0]+'.csv', pages='all')
雖然號稱是專業處理 pdf 中的表格的,但實際效果也不咋地。還是 pdfminer 中使用的 pdf,運行結果如下:
這結果真的很尷尬啊,表頭識別就錯了,還有 pdf 中有兩張表,我沒發現怎么區分表。
三、pdfplumber
pdfplumber 是按頁來處理 pdf 的,可以獲得頁面的所有文字,并且提供的單獨的方法用于提取表格。
importpdfplumber
path= 'test.pdf'pdf=pdfplumber.open(path)for page inpdf.pages:#獲取當前頁面的全部文本信息,包括表格中的文字
#print(page.extract_text())
for table inpage.extract_tables():#print(table)
for row intable:print(row)print('---------- 分割線 ----------')
pdf.close()
得到的 table 是個 string 類型的二維數組,這里為了跟 tabula 比較,按行輸出顯示。
可以看到,跟 tabula 相比,首先是可以區分表格,其次,準確率也提高了很多,表頭的識別完全正確。對于表格中有換行的,識別還不是很正確,但至少列的劃分沒問題,所以還是能處理的。
importpdfplumberimportre
path= 'test1.pdf'pdf=pdfplumber.open(path)for page inpdf.pages:print(page.extract_text())for pdf_table inpage.extract_tables():
table=[]
cells=[]for row inpdf_table:if notany(row):#如果一行全為空,則視為一條記錄結束
ifany(cells):
table.append(cells)
cells=[]elifall(row):#如果一行全不為空,則本條為新行,上一條結束
ifany(cells):
table.append(cells)
cells=[]
table.append(row)else:if len(cells) ==0:
cells=rowelse:for i inrange(len(row)):if row[i] is notNone:
cells[i]= row[i] if cells[i] is None else cells[i] +row[i]for row intable:print([re.sub('\s+', '', cell) if cell is not None else None for cell inrow])print('---------- 分割線 ----------')
pdf.close()
經過處理后,運行得到結果:
這結果已經完全正確了,而用 tabula,即便是經過處理也是無法得到這樣的結果的。當然對于不同的 pdf,可能需要不同的處理,實際情況還是要自己分析。
pdfplumber 也有處理不準確的時候,主要表現在缺列:
我找了另一個 pdf,表格部分截圖如下:
解析結果如下:
4列變成了兩列,另外,如果表格有合并單元格的情況,也會有這種問題,我挑這個表格展示是因為比較特殊,沒有合并單元格也缺列了。這應該跟 pdf 生成的時候有關。
但其實數據是獲取完整的,并沒有丟,只是被認為是非表格了。輸出 page.extract_text() 如下:
然后,我又用 tabula 試了下,結果如下:
列是齊了,但是,表頭呢???
pdfplumber 還提供了圖形Debug功能,可以獲得PDF頁面的截圖,并且用方框框起識別到的文字或表格,幫助判斷PDF的識別情況,并且進行配置的調整。要使用這個功能,還需要安裝ImageMagick。因為沒有用到,所以暫時沒有去細究。
四、后記
我們在做爬蟲的時候,難免會遇到 pdf 需要解析,主要還是針對文本和表格的數據提取。而 python 處理 pdf 的庫實在是太多太多了,比如還有 pypdf2,網上資料也比較多,但是我試了,讀出來是亂碼,沒有仔細的讀源碼所以這個問題也沒有解決。
而我對比較常用的3個庫比較后覺得,還是 pdfplumber 比較好用,對表格的支持最好。
相關博文推薦:
總結
以上是生活随笔為你收集整理的python读取pdf表格_【Python 库】解析PDF文本及表格——pdfminer、tabula、pdfplumber 的用法及对比...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python实现图形旋转_python轻
- 下一篇: python文件编码与解码_Python