使用 PdfMiner 和 PyPDF2 合并列提取文本

2023-11-27

我正在尝试使用 pdfMiner 解析 pdf 文件文本,但提取的文本被合并。我正在使用以下链接中的 pdf 文件 [编辑:链接已损坏/指向潜在的恶意软件]

我擅长任何类型的输出(文件/字符串)。这是为我返回提取的文本作为字符串的代码,但由于某种原因,列被合并。

from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfinterp import PDFResourceManager, process_pdf
import StringIO

def convert_pdf(filename):
    rsrcmgr = PDFResourceManager()
    retstr = StringIO()
    codec = 'utf-8'
    laparams = LAParams()
    device = TextConverter(rsrcmgr, retstr, codec=codec)

    fp = file(filename, 'rb')
    process_pdf(rsrcmgr, device, fp)
    fp.close()
    device.close()

    str = retstr.getvalue()
    retstr.close()
    return str

我也尝试过 PyPdf2,但遇到了同样的问题。这是 PyPDF2 的示例代码

from PyPDF2 import PdfReader
import StringIO

def get_data_using_pypdf2(filename):
    reader = PdfReader(filename)
    content = ""

    for page in reader.pages:
        extracted_text = page.extract_text()
        content +=  extracted_text + "\n"
    
    content = " ".join(content.replace("\xa0", " ").strip().split())
    return content.encode("ascii", "ignore")

我也尝试过pdf2txt.py但无法获得格式化输出。


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

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

TextConverter(和 PDFPageAggregator)的问题在于,它们对文档结构的递归程度不够深,无法正确提取不同的列。另外两个转换器需要一些有关文档结构的信息以用于显示目的,因此它们收集更详细的数据。在您的示例 pdf 中,两个简单设备仅解析(粗略地)包含列的整个文本框,这使得不可能(或至少非常困难)正确分隔不同的行。我发现这个问题的解决方案效果很好,要么

  • 创建一个继承自 PDFPageAggregator 的新类,或者
  • 使用 XMLConverter 并使用例如解析生成的 XML 文档美丽汤

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

对于新的设备类(我认为这更有说服力),您必须重写该方法receive_layout在渲染过程中每个页面都会调用该 get 方法。然后该方法递归地解析每个页面中的元素。例如,类似这样的事情可能会帮助您开始:

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 启发式方法无法将它们分离成自己的元素。您可以通过调整字边距参数(命令行工具 pdf2text.py 中的 -W 标志)来解决这个问题。无论如何,您可能需要通读(记录不充分)PDFMiner API以及浏览 PDFMiner 的源代码,您可以从 github 获取该源代码。 (唉,我无法粘贴链接,因为我没有足够的代表点:'

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 PdfMiner 和 PyPDF2 合并列提取文本 的相关文章

  • 如何更改 FacetGrid 中的边距标题颜色

    使用 Seaborn Facet Grids 如何仅更改边距标题的颜色 注意g set titles color red 更改两个标题 p sns load dataset penguins sns displot data p x fli
  • 从 SHAP 值中获取特征重要性

    我想要获得重要功能的数据框 通过下面的代码 我得到了 shap values 但我不确定这些值的含义是什么 在我的 df 中有 142 个特征和 67 个实验 但得到了一个带有 ca 的数组 2500 个值 explainer shap T
  • 嵌套字典中的 Django 模板

    我正在使用 Django 模板 并且遇到了嵌套字典的一个问题 Dict result dict type 0 file name abc count 0 type 1 file name xyz count 50 我的 HTML 文件中的模
  • 从sklearn PCA获取特征值和向量

    如何获取 PCA 应用程序的特征值和特征向量 from sklearn decomposition import PCA clf PCA 0 98 whiten True converse 98 variance X train clf f
  • Pandas dataframe:每批行的操作

    我有一个熊猫数据框df我想计算每批行的一些统计信息 例如 假设我有一个batch size 200000 对于每批batch sizerows 我想要一列的唯一值的数量ID我的数据框 我怎样才能做这样的事情呢 这是我想要的一个例子 prin
  • 字符串中的注释和注释中的字符串

    我正在尝试使用 Python 和 Regex 计算 C 代码中包含的注释中的字符数 但没有成功 我可以先删除字符串以删除字符串中的注释 但这也会删除注释中的字符串 结果会很糟糕 是否有机会通过使用正则表达式来询问不匹配注释中的字符串 反之亦
  • 使用 NLTK 在 Python 中获取大量名词(或形容词);或 Python Mad Libs

    Like 这个问题 https stackoverflow com questions 7439555 noun adjective etc word lists or dictionaries common words 我有兴趣按词性获取
  • PyTorch 给出 cuda 运行时错误

    我对我的代码做了一些小小的修改 以便它不使用 DataParallel and DistributedDataParallel 代码如下 import argparse import os import shutil import time
  • 将二维数组放入 Pandas 系列中

    我有一个 2D Numpy 数组 我想将其放入 pandas 系列 而不是 DataFrame 中 gt gt gt import pandas as pd gt gt gt import numpy as np gt gt gt a np
  • 小部件之间的自定义信号

    尝试将信号从一个 gtk EventBox 子级发送到另一个 在 init HeadMode 第 75 行 上出现错误 类型错误 未知信号名称 消息发送 why usr bin env python coding utf8 import p
  • 根据 Pandas 中的列表对多列进行排序

    感谢有关如何根据 pandas 中的倍数列表对给定多列进行排序的任何提示 如下所示 import pandas as pd sort a a d e sort b s1 s3 s6 sort c t1 t2 t3 df pd DataFra
  • 揭秘sharedctypes性能

    在 python 中 可以在多个进程之间共享 ctypes 对象 然而我注意到分配这些对象似乎非常昂贵 考虑以下代码 from multiprocessing import sharedctypes as sct import ctypes
  • Python、subprocess、call()、check_call 和 returncode 来查找命令是否存在

    我已经弄清楚如何使用 call 让我的 python 脚本运行命令 import subprocess mycommandline lumberjack sleep all night work all day subprocess cal
  • Werkzeug 中的线程和本地代理。用法

    首先 我想确保我正确理解了功能的分配 分配本地代理功能以通过线程内的模块 包 共享变量 对象 我对吗 其次 用法对我来说仍然不清楚 也许是因为我误解了作业 我用烧瓶 如果我有两个 或更多 模块 A B 我想将对象C从模块A导入到模块B 但我
  • 为什么我应该使用 WSGI?

    使用 mod python 一段时间了 我读了越来越多关于 WSGI 有多好的文章 但没有真正理解为什么 那么我为什么要切换到它呢 有什么好处 这很难吗 学习曲线值得吗 为了用 Python 开发复杂的 Web 应用程序 您可能会使用更全面
  • Django - 提交具有同一字段多个输入的表单

    预警 我对 Django 以及一般的 Web 开发 非常陌生 我使用 Django 托管一个基于 Web 的 UI 该 UI 将从简短的调查中获取用户输入 通过我用 Python 开发的一些分析来提供输入 然后在 UI 中呈现这些分析的可视
  • 以编程方式使用 Sphinx 特定指令解析 .rst 文件

    我希望能够在 Python 中解析基于 sphinx 的 rst 以便进一步处理和检查 就像是 import sphinx p sphinx parse path to file rst do something with p 似乎在 do
  • Flask 应用程序的测试覆盖率不起作用

    您好 想在终端的 Flask 应用程序中测试 删除路由 我可以看到测试已经过去 它说 test user delete test app LayoutTestCase ok 但是当我打开封面时 它仍然是红色的 这意味着没有覆盖它 请有人向我
  • PIL - 需要抖动,但限制调色板会导致问题

    我是 Python 新手 正在尝试使用 PIL 来执行 Arduino 项目所需的解析任务 这个问题涉及到Image convert 方法以及调色板 抖动等选项 我有一些硬件能够一次仅显示 16 种颜色的图像 但它们可以指定为 RGB 三元
  • tkinter:打开一个带有按钮提示的新窗口[关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 用户如何按下 tkinter GUI 中的按钮来打开新窗口 我只需要非常简单的解决方案 如果代码也能被解释那就太好了 这

随机推荐

  • 强制可选参数使用更广泛的类型,并具有更严格的默认值

    有没有办法进行可选参数f足够灵活 有类型 a gt b 但仍将其默认为identity 鉴于identity有类型 a gt a 之前的一个问题 begins通过准确地陈述我的问题 我想定义一个接受可选参数的函数 该参数是 一个函数 a g
  • 语音中的关键字识别[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 有谁知道有一个免费的关键字识别系统 并且可能提供 API CMU Sphinx 4 和 MS Speech API 是语音识别引擎 不能用于 KWS
  • 在 Java 的 main() 中对 Thread 实例运行 wait()

    我正在尝试 java lang Object 中 wait 的定时版本 并观察到它在两种不同场景中的行为有所不同 场景1 使用Thread中run 的默认定义 public static void main String args thro
  • scanf 是否保证在失败时不会更改值?

    If a scanffamily 函数无法匹配当前说明符 是否允许写入成功时存储该值的存储 在我的系统上有以下输出213两次 但这能保证吗 标准中的语言 C99或C11 似乎没有明确规定原始值应保持不变 无论是否不确定 include
  • JavaScript 错误 - 找不到变量:谷歌

    我编写的代码在浏览器上运行得非常好 但是当我连接到 iPhone 上的 wifi 时 我在调试器中收到错误 JavaScript 错误 找不到变量 谷歌 每当我调用任何谷歌地图 方向 地理位置对象时都会发生这种情况 代码如下 map new
  • 使用 SVN 和 Eclipse 正确设置 GWT 项目

    我正在尝试使用 Eclipse 和 Google Web Toolkit 开发一个小项目 这是一个 小型 小组项目 所以我想使用 SVN 到目前为止 我已经在 Eclipse 中创建了一个 GWT 项目并将其添加到我的 SVN 存储库中 问
  • 如何减少 Entity Framework 4 查询编译时间?

    摘要 我们遇到了 EF4 查询编译时间超过 12 秒的问题 缓存查询只能让我们到目前为止 有什么方法可以真正减少编译时间吗 我们可以寻找哪些可能做错的事情吗 谢谢 我们有一个通过 WCF 服务公开的 EF4 模型 对于每种实体类型 我们公开
  • 为什么 Scala 改变了关系运算符与相等运算符的相对优先级(与 Java 相比)?

    在Java中 更新 这实际上是语言规范中的一个错误 在 Scala 中 在Scala 中它不是相反的 尝试这个 val what 5 8 lt 4 我收到编译时警告 comparing values of types Boolean and
  • mysql group by 返回最小值并获取对应行数据

    我有一个像这样的数据表 PK table merchantName price Product 1 argos 7 4 2 comet 3 4 1 Dixon 1 3 1 argos 10 4 我希望在mysql中选择产品的最低价格和相应的
  • 将 ajax 结果附加到 div

    我正在对 IMDb API 进行 ajax 调用 以获取 肖申克的救赎 的电影数据 我希望将这些数据放入我创建的 div 中 div div 我当前的js代码 init function init ajax dataType json ur
  • 如何测量Java线程的执行时间?

    我想测量Java中线程的执行时间 现在我正在监视线程的开始和结束时间 但我认为它不太准确 因为线程在执行期间可能会被挂起 Java MXBeans 可以提供每线程 CPU 时间 import java lang management Man
  • “@+android:id/title”是什么意思?

    正常情况下 我们应该使用 id 定义一个 id 并使用 id引用一个 id 今天我发现 android id title in apps settings res layout preferenc progress xml 如何理解它以及如
  • 比较相等的日期时间返回 false

    我有一个关于如何在 C 中比较 存储日期时间的查询 考虑以下代码 var createdDate DateTime Now using cr new LanguageDictionaryRepository ds cr Add new Sy
  • 在 Rcpp 中构造 3D 数组

    我正在尝试使用提供的维度列表将 1D 数组映射到 3D 数组 这是我的组件 SEXP data my 1D array I can initialise new 3D vector in the following way NumericV
  • Angular ngx-mat-select-search 自定义组件

    我正在尝试使用 ngx mat select search 组件在我的应用程序中放置一个带有搜索栏的 mat select 样式下拉菜单 https www npmjs com package ngx mat select search 我
  • 如何在 Liferay portlet 中设置 Cookie?

    我在尝试设置会话 cookie 时遇到问题Liferay 6 0 portlet 我希望能够向客户端浏览器设置一个 cookie 以存储用于 linkedin 身份验证的应用程序密钥 然后其他 portlet 可以在其中检索它 我可以使用以
  • 如何在 ReadTheDocs 导航栏中链接生成的索引页面?

    我正在 ReadTheDocs 上使用 Sphinx 主题创建我的文档 构建过程会生成一个 genindex html 文件 可以通过以下方式引用该文件 Link to the ref genindex page 这会创建 链接到Index
  • 了解 Dagger 2 中的范围

    我在 Dagger 2 中遇到了与范围相关的错误 我正在尝试了解如何解决它 我有一个CompaniesActivity这表明公司 当用户选择一个项目时 所选公司的员工会显示在EmployeesActivity 当用户选择一名员工时 她的详细
  • 如何在 yii2 模态窗口中使用 pjax 更新小部件

    我的模态窗口中有两个 ActiveForm 提交第一个表单后 我需要更新第二个表单并保持模态 据我了解 pjax 可以处理这个问题 但无法让它正常工作 在 form php 中 我有 ActiveForm 和应该更新的小部件 need to
  • 使用 PdfMiner 和 PyPDF2 合并列提取文本

    我正在尝试使用 pdfMiner 解析 pdf 文件文本 但提取的文本被合并 我正在使用以下链接中的 pdf 文件 编辑 链接已损坏 指向潜在的恶意软件 我擅长任何类型的输出 文件 字符串 这是为我返回提取的文本作为字符串的代码 但由于某种