python数据提取和合并_python – 使用PdfMiner和PyPDF2提取文本合并列

我最近遇到了类似的问题,尽管我的pdf结构稍微简单一些.

PDFMiner使用名为“devices”的类来解析pdf文件中的页面.基本设备类是PDFPageAggregator类,它只是解析文件中的文本框.转换器类,例如TextConverter,XMLConverter和HTMLConverter也将结果输出到文件中(或在示例中的字符串流中),并对内容进行更精细的解析.

TextConverter(和PDFPageAggregator)的问题在于它们没有足够深入地处理文档结构以正确提取不同的列.另外两个转换器需要一些有关文档结构的信息以供显示,因此它们可以收集更详细的数据.在您的示例中,两个简单设备仅解析(粗略地)包含列的整个文本框,这使得不可能(或至少非常困难)正确地分隔不同的行.我发现的解决方案非常好,也就是说

>创建一个继承自PDFPageAggregator的新类,或

>使用XMLConverter并使用例如解析生成的XML文档. Beautifulsoup

在这两种情况下,您都必须使用其边界框y坐标将不同的文本段组合到行.

在新设备类的情况下(我认为,这更有说服力),您必须覆盖在渲染过程中为每个页面调用的方法receive_layout.然后,此方法递归地解析每个页面中的元素.例如,像这样的东西可能会让你开始:

from pdfminer.pdfdocument import PDFDocument, PDFNoOutlines

from pdfminer.pdfparser import PDFParser

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter

from pdfminer.converter import PDFPageAggregator

from pdfminer.layout import LTPage, LTChar, LTAnno, LAParams, LTTextBox, LTTextLine

class PDFPageDetailedAggregator(PDFPageAggregator):

def __init__(self, rsrcmgr, pageno=1, laparams=None):

PDFPageAggregator.__init__(self, rsrcmgr, pageno=pageno, laparams=laparams)

self.rows = []

self.page_number = 0

def receive_layout(self, ltpage):

def render(item, page_number):

if isinstance(item, LTPage) or isinstance(item, LTTextBox):

for child in item:

render(child, page_number)

elif isinstance(item, LTTextLine):

child_str = ''

for child in item:

if isinstance(child, (LTChar, LTAnno)):

child_str += child.get_text()

child_str = ' '.join(child_str.split()).strip()

if child_str:

row = (page_number, item.bbox[0], item.bbox[1], item.bbox[2], item.bbox[3], child_str) # bbox == (x1, y1, x2, y2)

self.rows.append(row)

for child in item:

render(child, page_number)

return

render(ltpage, self.page_number)

self.page_number += 1

self.rows = sorted(self.rows, key = lambda x: (x[0], -x[2]))

self.result = ltpage

在上面的代码中,每个找到的LTTextLine元素都存储在一个有序的元组列表中,这些元组包含页码,边界框的坐标和该特定元素中包含的文本.然后你会做类似的事情:

from pprint import pprint

from pdfminer.pdfparser import PDFParser

from pdfminer.pdfdocument import PDFDocument

from pdfminer.pdfpage import PDFPage

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter

from pdfminer.layout import LAParams

fp = open('pdf_doc.pdf', 'rb')

parser = PDFParser(fp)

doc = PDFDocument(parser)

doc.initialize('password') # leave empty for no password

rsrcmgr = PDFResourceManager()

laparams = LAParams()

device = PDFPageDetailedAggregator(rsrcmgr, laparams=laparams)

interpreter = PDFPageInterpreter(rsrcmgr, device)

for page in PDFPage.create_pages(doc):

interpreter.process_page(page)

# receive the LTPage object for this page

device.get_result()

pprint(device.rows)

变量device.rows包含有序列表,其中所有文本行使用其页码和y坐标排列.您可以使用相同的y坐标循环文本行和组线以形成行,存储列数据等.

我尝试使用上面的代码解析你的pdf,并且列主要是正确解析的.但是,有些列非常接近,因此默认的PDFMiner启发式方法无法将它们分离为自己的元素.您可以通过调整margin参数一词(命令行工具pdf2text.py中的-W标志)来解决这个问题.在任何情况下,您可能想要阅读(文档记录不清)PDFMiner API以及浏览PDFMiner的源代码,您可以从github获取. (唉,我无法粘贴链接,因为我没有足够的重复点:’

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值