当前位置:   article > 正文

python 文本分析库_【Python 库】解析PDF文本及表格

python pdf解析库解析table

pdf 是个异常坑爹的东西,有很多处理 pdf 的库,但是没有完美的。

一、pdfminer3k

pdfminer3k 是 pdfminer 的 python3 版本,主要用于读取 pdf 中的文本。

网上有很多 pdfminer3k 的代码示例,看过以后,只想吐槽一下,太复杂了,有违 python 的简洁。

215083257_1_20210207093113240.gif

from pdfminer.pdfparser import PDFParser, PDFDocument

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter

from pdfminer.converter import PDFPageAggregator

from pdfminer.layout import LAParams, LTTextBox

from pdfminer.pdfinterp import PDFTextExtractionNotAllowed

path = "test.pdf"

#用文件对象来创建一个pdf文档分析器

praser = PDFParser(open(path, 'rb'))

#创建一个PDF文档

doc = PDFDocument()

#连接分析器 与文档对象

praser.set_document(doc)

doc.set_parser(praser)

#提供初始化密码#如果没有密码 就创建一个空的字符串

doc.initialize()

#检测文档是否提供txt转换,不提供就忽略

if not doc.is_extractable:

raise PDFTextExtractionNotAllowed

else:

#创建PDf 资源管理器 来管理共享资源

rsrcmgr = PDFResourceManager()

#创建一个PDF设备对象

laparams = LAParams()

device = PDFPageAggregator(rsrcmgr, laparams=laparams)

#创建一个PDF解释器对象

interpreter = PDFPageInterpreter(rsrcmgr, device)

#循环遍历列表,每次处理一个page的内容

for page in doc.get_pages():

interpreter.process_page(page)

#接受该页面的LTPage对象

layout = device.get_result()

#这里layout是一个LTPage对象,里面存放着这个 page 解析出的各种对象

#包括 LTTextBox, LTFigure, LTImage, LTTextBoxHorizontal 等

for x in layout:

if isinstance(x, LTTextBox):

print(x.get_text().strip())

215083257_1_20210207093113240.gif

pdfminer 对于表格的处理非常的不友好,能提取出文字,但是没有格式:

pdf表格截图:

215083257_2_20210207093113287.png

代码运行结果:

215083257_3_20210207093113662.png

想把这个结果还原成表格可不容易,加的规则太多必然导致通用性的下降。

二、tabula-py

tabula 是专门用来提取PDF表格数据的,同时支持PDF导出为CSV、Excel格式,但是这工具是用 java 写的,依赖 java7/8。tabula-py 就是对它做了一层 python 的封装,所以也依赖 java7/8。

代码很简单:

215083257_1_20210207093113240.gif

import tabula

path = 'test.pdf'

df = tabula.read_pdf(path, encoding='gbk', pages='all')

for indexs in df.index:

print(df.loc[indexs].values)

#tabula.convert_into(path, os.path.splitext(path)[0]+'.csv', pages='all')

215083257_1_20210207093113240.gif

虽然号称是专业处理 pdf 中的表格的,但实际效果也不咋地。还是 pdfminer 中使用的 pdf,运行结果如下:

215083257_4_20210207093113803.png

这结果真的很尴尬啊,表头识别就错了,还有 pdf 中有两张表,我没发现怎么区分表。

三、pdfplumber

pdfplumber 是按页来处理 pdf 的,可以获得页面的所有文字,并且提供的单独的方法用于提取表格。

215083257_1_20210207093113240.gif

import pdfplumber

path = 'test.pdf'

pdf = pdfplumber.open(path)

for page in pdf.pages:

#获取当前页面的全部文本信息,包括表格中的文字

#print(page.extract_text())

for table in page.extract_tables():

#print(table)

for row in table:

print(row)

print('---------- 分割线 ----------')

pdf.close()

215083257_1_20210207093113240.gif

得到的 table 是个 string 类型的二维数组,这里为了跟 tabula 比较,按行输出显示。

215083257_5_20210207093113958.png

可以看到,跟 tabula 相比,首先是可以区分表格,其次,准确率也提高了很多,表头的识别完全正确。对于表格中有换行的,识别还不是很正确,但至少列的划分没问题,所以还是能处理的。

215083257_1_20210207093113240.gif

import pdfplumber

import re

path = 'test1.pdf'

pdf = pdfplumber.open(path)

for page in pdf.pages:

print(page.extract_text())

for pdf_table in page.extract_tables():

table = []

cells = []

for row in pdf_table:

if not any(row):

#如果一行全为空,则视为一条记录结束

if any(cells):

table.append(cells)

cells = []

elif all(row):

#如果一行全不为空,则本条为新行,上一条结束

if any(cells):

table.append(cells)

cells = []

table.append(row)

else:

if len(cells) == 0:

cells = row

else:

for i in range(len(row)):

if row[i] is not None:

cells[i] = row[i] if cells[i] is None else cells[i] + row[i]

for row in table:

print([re.sub('\s+', '', cell) if cell is not None else None for cell in row])

print('---------- 分割线 ----------')

pdf.close()

215083257_1_20210207093113240.gif

经过处理后,运行得到结果:

215083257_6_2021020709311483.png

这结果已经完全正确了,而用 tabula,即便是经过处理也是无法得到这样的结果的。当然对于不同的 pdf,可能需要不同的处理,实际情况还是要自己分析。

pdfplumber 也有处理不准确的时候,主要表现在缺列:

我找了另一个 pdf,表格部分截图如下:

215083257_7_20210207093114224.png

解析结果如下:

215083257_8_20210207093114490.png

4列变成了两列,另外,如果表格有合并单元格的情况,也会有这种问题,我挑这个表格展示是因为比较特殊,没有合并单元格也缺列了。这应该跟 pdf 生成的时候有关。

但其实数据是获取完整的,并没有丢,只是被认为是非表格了。输出 page.extract_text() 如下:

215083257_9_20210207093114693.png

然后,我又用 tabula 试了下,结果如下:

215083257_10_20210207093114803.png

列是齐了,但是,表头呢???

pdfplumber 还提供了图形Debug功能,可以获得PDF页面的截图,并且用方框框起识别到的文字或表格,帮助判断PDF的识别情况,并且进行配置的调整。要使用这个功能,还需要安装ImageMagick。因为没有用到,所以暂时没有去细究。

四、后记

我们在做爬虫的时候,难免会遇到 pdf 需要解析,主要还是针对文本和表格的数据提取。而 python 处理 pdf 的库实在是太多太多了,比如还有 pypdf2,网上资料也比较多,但是我试了,读出来是乱码,没有仔细的读源码所以这个问题也没有解决。

而我对比较常用的3个库比较后觉得,还是 pdfplumber 比较好用,对表格的支持最好。

相关博文推荐:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/51440?site
推荐阅读
相关标签
  

闽ICP备14008679号