从pdf中提取已知bbox中的文本,PDFQuery太慢

2023-12-11

我在 lxml 文件中找到了 bbox 坐标,并设法使用 PDFQuery 提取了所需的数据。然后我将数据写入 csv 文件。

def pdf_scrape(pdf):
    """
    Extract each relevant information individually
    input: pdf to be scraped
    returns: dataframe of scraped data
    """
    # Define coordinates of text to be extracted
    CUSTOMER             = pdf.pq('LTTextLineHorizontal:overlaps_bbox("356.684, 563.285, 624.656, 580.888")').text() 
    CUSTOMER_REF         = pdf.pq('LTTextLineHorizontal:overlaps_bbox("356.684, 534.939, 443.186, 552.542")').text()
    SALES_ORDER          = pdf.pq('LTTextLineHorizontal:overlaps_bbox("356.684, 504.692, 414.352, 522.295")').text()
    ITEM_NUMBER          = pdf.pq('LTTextLineHorizontal:overlaps_bbox("356.684, 478.246, 395.129, 495.849")').text()
    KEY                  = '0000'+ SALES_ORDER + '-' + '00' + ITEM_NUMBER
    # Combine all relevant information into a single pandas dataframe
    page = pd.DataFrame({
        'KEY'          : KEY,
        'CUSTOMER'     : CUSTOMER,
        'CUSTOMER REF.': CUSTOMER_REF,
        'SALES ORDER'  : SALES_ORDER,
        'ITEM NUMBER'  : ITEM_NUMBER
                       }, index=[0])
    return(page)

pdf_search = Path("files/").glob("*.pdf")

pdf_files = [str(file.absolute()) for file in pdf_search]

master = list()
for pdf_file in pdf_files: 
    pdf = pdfquery.PDFQuery(pdf_file)
    pdf.load(0)

# Iterate over all pages in document and add scraped data to df
    page = pdf_scrape(pdf) 
    master.append(page)

master = pd.concat(master, ignore_index=True)
master.to_csv('scraped_PDF_as_csv\scraped_PDF_DataFrame.csv', index = False)

问题是我每天需要阅读数百个 PDF,而此脚本需要约 13-14 秒才能从仅有 10 个 PDF 的第一页中挖掘四个元素。

有没有办法加快我的代码速度? 我看过这个:https://github.com/py-pdf/benchmarks这意味着 PDFQuery 与其他库相比非常慢。

我尝试过使用 PyMuPDF,因为它应该更快,但我在实现它以提供与 PDFQuery 相同的输出时遇到问题。有谁知道如何做到这一点?

重申一下,我知道所需文本在文档中的位置,但我不一定知道它说的是什么。


我在回答其他问题时对 PyMuPDF 进行了一些探索,但我没有个人/实践经验。在这篇文章之前我对 PDFQuery 一无所知。不过,我可以展示我对一个非常基本的示例的看法,即使用 PyMuPDF 根据位置获取一段文本。

另外,您不需要从这些时间推断 PDFQuery 很慢,作者指出这一点在文档中多次:

性能说明:对 pdf.load() 的初始调用运行速度非常慢,因为底层 pdfminer 库必须将页面上的每个元素与其他每个元素进行比较。请参阅缓存部分以避免在后续运行中出现这种情况。

PDFQuery

import pdfquery

query1 = (176.4, 629.28, 176.4, 629.28)  # "Text 1" in simple.pdf
pdf = pdfquery.PDFQuery("simple.pdf")

# query1 = (130, 407, 130, 407)  # Looking for "Gaussian" in more_complicated.pdf
# pdf = pdfquery.PDFQuery("more_complicated.pdf")

pdf.load(0)

text1 = pdf.pq('LTTextLineHorizontal:overlaps_bbox("%d, %d, %d, %d")' % query1).text()

print(text1)

PyMuPDF

我仍然不确定如何使用 PyMuPDF 最好地完成这项任务,但这里有一种方法至少可以为我提供简单和复杂的目标文本:

from fitz import open as fitz_open, Document, Page, Rect

query1 = Rect(165.6, 165.6, 165.6, 165.6)  # "Text 1" in simple.pdf
doc: Document = fitz_open("simple.pdf")

# query1 = Rect(130, 381, 130, 381)  # Looking for "Gaussian" in more_complicated.pdf
# doc: Document = fitz_open("more_complicated.pdf")

page: Page = doc.load_page(0)

page_dict: dict = page.get_text("dict")

bbox: Rect  # a variable we'll reuse as we work down to our query
text1 = ""  # the text we're looking for with query1

block: dict
for block in page_dict["blocks"]:
    if block["type"] == 1:  # skip, it's an image
        continue

    bbox = Rect(block["bbox"])
    if not bbox.contains(query1):
        continue

    line: dict
    for line in block["lines"]:

        bbox = Rect(line["bbox"])
        if not bbox.contains(query1):
            continue

        span: dict
        for span in line["spans"]:

            bbox = Rect(span["bbox"])
            if not bbox.contains(query1):
                continue

            text1 = span["text"]

print(text1)

Analysis

(您可能已经注意到,PDFQuery 和 PyMuPDF 之间的查询坐标不同,这是因为 PDFQuery 使用bottom-left 作为原点,PyMuPDF 使用upper- 左为原点。)

我还用以下方法测量了运行时间timemacOS 12.4 上的命令; 3次运行的平均值。以下是我针对 simple.pdf 和 more_complicated.pdf 运行 PDFQuery 和 PyMuPDF 的结果:

simple.pdf more_complicated.pdf
file simple complicated
PDFQuery timing (s) 0.123 0.258
PyMuPDF timing (s) 0.069 0.070

PyMuPDF 几乎在同一时间运行两个 PDF,我认为我们看到 PDFQuery 需要更长的时间才能生成这些 PDFn**2/2交叉比较。

我认为你会放弃很多便利来尝试自己做这件事。如果您的 PDF 是一致的,您可能可以调整 PyMuPDF 并使其正确,但如果它们的创建方式存在差异,则可能需要更长的时间才能正确(如果有的话,因为 PDF 中的文本非常棘手)。

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

从pdf中提取已知bbox中的文本,PDFQuery太慢 的相关文章

随机推荐

  • java 将字符串连接成 StringBuilder

    我有一个遗留的Java文件 它使用字符串连接来构建巨大的字符串对象 这是一个严重的性能问题 是否有一种方法可以执行以下操作 String test I am a very bad programmer to use concatenatio
  • PHP 到 Ruby 编译器 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 有谁知道 最好是开源的 PHP 到 ruby 编译器 即解析 PHP 代码并生成语义上等效的 ruby 代码的程序 我自己没用过 但你可能想看看Ph
  • 如何使用 awk 显示列中的文件名?

    我正在尝试执行一个添加到我的文件的命令 当前输入文件的名称 逗号数小于 5 的行索引 跨行的逗号数 I got awk F if NF gt 5 printf Filename d Index d Number of commas d n
  • VSS到SVN的迁移;工具建议? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 有人对将代码库从 VSS
  • 我可以在浏览器中查看 httpOnly cookie

    我认为 httpOnly cookie 只能在 http 请求中读取 但是 当我打开 Firefox 开发工具时 我可以看到 cookie 的值 这是正常的吗 是的 这很正常 HttpOnly 的作用是阻止 cookie 被访问JavaSc
  • Oracle分页策略

    我想从两个时间戳之间的表中获取数百万行 然后对其进行处理 触发单个查询并立即检索所有记录看起来是一个糟糕的策略 因为它可能超出我的 JVM 程序的内存容量 我读过这篇文章 http oracle readthedocs io en late
  • 对Java ThreadPool的困惑

    这是我第一次在我的新项目中使用Java线程池 在我遇到这个之后 关联http www javacodegeeks com 2013 01 java thread pool example using executors and thread
  • 以字符串作为分隔符分割字符串

    我正在尝试使用字符串 而不是字符 作为分隔符来拆分批处理文件中的字符串 该字符串的格式为 string1 by string2 txt 分隔符是by 是的 空格 by 一词 后面跟空格 我想要的输出是 string1 string2 所以
  • curl :(1) libcurl 中不支持或禁用协议 https

    我正在尝试在 Ubuntu 11 04 上安装 Rails 环境 当我启动命令时rvm install 1 9 2 with openssl dir usr local收到以下错误 curl 1 Protocol https not sup
  • (Windows 10) GitBash 未格式化颜色 - 找不到配置设置

    背景 我的 Git Bash 命令行没有显示颜色或格式 并且似乎正在转义字符 例如 The Entity shortcut name CarBundle Car C K7arBundle8a K7rBundle8r K7Bundle8B K
  • 如何从 Gemfire 获得独特的多头?

    我们正在开发一个直接与 Gemfire 对话的分层 Java 应用程序 我们需要能够生成唯一的 长 序列号 保证在应用程序的所有节点上都是唯一的 并非所有节点都集群 通常我会在 Oracle 中创建一个序列 但在这种情况下 即使我们的 Ge
  • 使网格项目重叠

    我正在尝试实现一个 css 网格图案 其中标题覆盖下一行 我添加了一段代码 标题位于顶部 所附图像应该向您展示我想要实现的目标 Thanks body display grid grid template areas header head
  • jquery href().addClass() 问题

    http jsfiddle net aBaw6 2 当您将鼠标悬停在列表项上时 此演示不会添加类 我在这里做错了什么 li hover function this addClass hover function this removeCla
  • 类列表在控制台中不断打印为类名称?

    好吧 也许我只是累了或者怎么了 但我似乎不明白为什么这种情况一直发生 每天都会针对我拥有的数据库中的数据点调用下面的代码 当我打印到控制台进行调试时 它只是打印为 NamespaceName SharePrices 不知道发生了什么事 pu
  • 如何监控SIM状态变化

    我希望能够在 SIM 状态发生变化时做一些事情 即在需要 SIM PIN 时播放声音 但我认为没有广播事件可以被广播接收器拦截 android intent action PHONE STATE 仅告诉您 CALL STATE 何时发生变化
  • 在 FOR 循环中使用 revgeocode 函数。需要帮助

    我的问题详细如下 我的输入数据的格式如下面的小示例所示 USERID LONGITUDE LATITUDE 1 8 79659 55 879554 2 6 874743 56 87896 3 3 874743 58 87896 4 10 8
  • 使用 gcc 未定义对“__gxx_personality_v0”的引用[重复]

    这个问题在这里已经有答案了 可能的重复 gxx personality v0 是做什么用的 我在编译 C 代码的上下文中看到了这个问题 不过我要编译一个pureC 代码并继续出现此错误 我被禁止使用 lstdc 作为解决此 gcc 问题的方
  • 加载 JSON-P 时可以避免使用全局回调函数吗?

    我想使用 JSON P 在我的网页上加载我的 Google 日历提要 为了使页面上的主要内容加载得更快 我仅在页面加载后将 JSON P 的脚本标签注入到 head 标签中 Google Calendar API 返回带有回调函数的脚本 请
  • 使用 pyodbc 连接到 PostgreSQL

    我有一个在本地主机上运行的 PostgreSQL 我安装了 psqlODBC 驱动程序 现在 当我尝试使用 pyodbc 连接到服务器时 import pyodbc connection pyodbc connect DRIVER psql
  • 从pdf中提取已知bbox中的文本,PDFQuery太慢

    我在 lxml 文件中找到了 bbox 坐标 并设法使用 PDFQuery 提取了所需的数据 然后我将数据写入 csv 文件 def pdf scrape pdf Extract each relevant information indi