【问题标题】:Extract text content from PDF从 PDF 中提取文本内容
【发布时间】:2013-02-05 19:45:03
【问题描述】:

我一直在使用 pdftotext 从 PDF 中提取文本。我也用 Ghostscript 做到了这一点。最近,一家实用程序提供商更改了他们的 PDF,因此这些方法无法提取其中的一部分。具体来说,我错过了到期日和到期总额。当我在阅读器中打开 PDF 时,可以突出显示、复制“缺失”文本并将其粘贴到外部编辑器中。当我在 Acrobat Pro 中打开它并查看内容(查看 -> 显示/隐藏 -> 导航窗格 -> 内容)时,我需要的文本就在那里。如何在不手动复制和粘贴的情况下将其取出? (这不是一个选项,因为我将在数千个 PDF 上执行此操作)?

这是我正在处理的示例。我已删除所有敏感数据:

link to PDF

编辑:我在发布此内容后注意到,当您点击文件的链接(托管在 Google Drive 上)时,它将允许您选择和复制页面上的大部分文本,但不是我缺少的内容。下载文件时,您可以在 PDF 阅读器中选择缺少的文本。

【问题讨论】:

    标签: pdf ghostscript pdftotext


    【解决方案1】:

    最近发布的 Ghostscript 有一个可能值得一试的 txtwrite 设备。

    【讨论】:

    • 我已经尝试了 txtwrite 设备,它给我的结果与 pdftotext 相同 — 仍然缺少到期日期和帐户总数。
    • 到底缺少什么?我以为是“2012 年 11 月 12 日 - 2012 年 12 月 12 日”,但我在 txtwrite 的输出中看到了这一点。
    • 我缺少右上角:“请在 2012 年 12 月 28 日之前付款”和“应付总额 $1,839.42”
    • 该文本是 Type 3 字体,evince/poppler 不会渲染(Ghostscript 会渲染它,但 txtwrite 似乎看不到它,这很奇怪)。没时间详细看,看txtwrite的工程师放假了,不过如果你提bug,附上文件(bugs.ghostscript.com),起码应该能解释一下原因它不起作用 - 在某些时候。
    • 文本输出缺失是由于txtwrite设备中的一些严重的逻辑错误导致无法从PDF文件中提取Unicode信息,并一直回退到原始字符代码。现在已解决此问题。如果您在 Ghostscript 中发现错误,请向我们报告,以便我们修复它.....txtwrite 设备现在可以正确提取此文档中的所有文本。
    【解决方案2】:

    有一种非常 HACKY 的方法来提取数据,但它只适用于旧版本的 ghostscript,如 8.51 或 8.62。在旧版本的 ghostscript 中,PDF 命令定义在 /lib/pdf_ops.ps 中,新版本做了一些别的事情。

    此处提供了 8.62 版的测试版本。

    http://sourceforge.net/projects/ghostscript/files/GPL%20Ghostscript/8.62/gs862w32.exe/download
    

    使用/Tj {} def/TJ {} def 通过在每个定义的开头添加dup == 来打印您要查找的文本。 (这可以变得更复杂)我也不必担心字体警告消息,但如果将数据写入文件,这些将被过滤掉。

    因为字距调整,一些单词被分割成小块和单独的字母。给定时间,这也可以被过滤。

    从 pdf_ops.ps 修改 /Tj /Tj { 重复 == 0 0 moveto 显示 settextposition } bdef

    从 pdf_ops.ps 修改 /TJ

    /TJ { dup == 
      0 0 moveto {
        dup type /stringtype eq {
          Show
        } { -1000 div
          currentfont /ScaleMatrix .knownget { 0 get mul } if
          0 Vexch rmoveto
        } ifelse
      } forall settextposition
    } bdef
    

    输出

    (Help a neighbor within your county each month by contributing to The Salvation )
    (Army's Project SHARE and Georgia Power will match your gift. To help, simply check )
    ($1, $2, $5, or $10 on the return portion of this bill. Starting next month, your pledge )
    (amount will be included on your monthly bill.)
    (Our business offices will be closed on December 24 and 25 for Christmas and January )
    (1 for New Year's Day. In case of an emergency, please call us at the number on your )
    (bill 24 hours a day, 7 days a week.)
    (PLEASE KEEP THIS PORTION FOR YOUR RECORDS.)
    (PLEASE RETURN THIS PORTION WITH YOUR PAYMENT, MAKING SURE THE RETURN ADDRESS SHOWS IN THE ENVELOPE WINDOW.)
    (Account Number)
    (Mail To:)
    

    后记是不是很有趣?

    【讨论】:

    • 尝试此操作后,尝试运行 ghostscript 时出现“找不到初始化文件 gs_init.ps”。使用 8.62。此外,我的 pdf_ops.ps 位于 lib\,而不是 bin\。我认为它应该只留在 lib\.
    • 并且 gs_init.ps 存在于 lib\ 中。
    • 很奇怪,gs_init.ps 是在访问 pdf_ops.ps 之前被读取的,所以我怀疑这可能是一个不相关的问题。尝试在不修改的情况下运行 GS,看看该错误是否消失。 gs_init.ps 在GPL Ghostscript 8.62 (2008-02-29) 之前被读取,您看到该消息了吗? pdf_ops.ps 在This software comes with NO WARRANTY: see the file PUBLIC for details. 之后被读取,如果错误发生在此消息之前,那么肯定会发生其他事情。是的,director 应该是 \lib 而不是 \bin,并且文件应该保留在 \lib 中。
    【解决方案3】:

    我通过从 git 获取最新的未发布版本的 Ghostscript 并构建它来解决这个问题。现在 txtwrite 设备正好给了我我需要的东西。感谢 chrisl 的回答和 cmets 将我引向正确的方向。

    【讨论】:

    • 您好,您是否曾尝试从 pdf 中删除图像,以便 pdf 仅包含文本?我正在寻找一种方法来做到这一点。您有任何使用 ghostScript 或任何其他 cli 工具的解决方案吗?请帮忙。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-17
    • 1970-01-01
    相关资源
    最近更新 更多