从PDF中提取文本内容

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

编辑:我在发布后注意到,当您跟随链接到文件(托管在Google Drive上)时,它将允许您选择并复制页面上的大多数文本,但不包括我缺失的内容。当您下载文件时,可以在PDF阅读器中选择缺失的文本。

3个回答

2
最近发布的Ghostscript版本中有一个名为txtwrite的设备,值得一试。

我已经尝试了txtwrite设备,但它给我的结果和pdftotext一样 - 仍然缺少到期日期和账户总额。 - Ben Walker
到底缺什么?我以为是“2012年11月12日至12月12日”,但我在txtwrite的输出中看到了它。 - chrisl
我缺少右上角的内容:“请在2012年12月28日前付款”和“应付总额1,839.42美元”。 - Ben Walker
1
那段文本是Type 3字体,evince/poppler无法渲染(Ghostscript可以渲染它,但txtwrite似乎看不到它,这很奇怪)。我没有时间详细查看,负责txtwrite的工程师正在度假,但如果您提出一个错误,并附上文件(http://bugs.ghostscript.com/),您至少应该得到一个解释为什么它不起作用-在某个时候。 - chrisl
1
缺乏文本输出是由于txtwrite设备中的一些严重逻辑错误造成的,当无法从PDF文件中提取Unicode信息并回退到原始字符代码时。现在已经修复了这个问题。如果您在Ghostscript中发现了一个bug,请务必向我们报告,以便我们及时修复它...... txtwrite设备现在可以正确地提取此文档中的所有文本。 - KenS
显示剩余4条评论

1
我已经通过从Git获取最新的未发布版本的Ghostscript并构建它来解决了这个问题。现在,txtwrite设备给了我我需要的东西。感谢chrisl的答案和评论,让我朝着正确的方向前进。

你好,你有没有尝试过从PDF中删除图像,以便PDF仅包含文本?我正在寻找一种方法来做到这一点。您是否有使用ghostScript或任何其他cli工具的解决方案?请帮忙。 - hussainb

0

有一种非常“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 { dup == 0 0 moveto Show 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:)

PostScript 不是很有趣吗?


尝试后,当我尝试运行Ghostscript时,出现“找不到初始化文件gs_init.ps”的错误。使用的版本是8.62。此外,我的pdf_ops.ps文件位于lib\而不是bin\中。我认为它应该保留在lib\中。 - Ben Walker
并且gs_init.ps存在于lib\中。 - Ben Walker
非常奇怪,gs_init.ps在读取pdf_ops.ps之前就被读取了,所以我怀疑这可能是一个无关的问题。尝试在没有修改的情况下运行GS,看看是否会消除该错误。gs_init.ps在GPL Ghostscript 8.62(2008-02-29)之前被读取,您看到了那条消息吗?如果错误发生在此消息之前,则肯定会发生其他事情。是的,目录应该是\lib而不是\bin,并且文件应该保留在\lib中。 - Fred F

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接