如何从PDF中提取文本?

187

有没有人可以推荐一个用于从PDF中提取文本和图像的库/API?

我们需要能够获取文档中预先已知区域内的文本,因此API需要为我们提供每个元素在页面上的位置信息。

我们希望将该数据输出为xmljson格式。目前我们正在研究PdfTextStream,它看起来非常不错,但我们想听听其他人的经验和建议。

有没有其他的方法(商业或免费)可以程序化地从PDF中提取文本?


2
对于那些只需要非常简单的内容(没有位置信息)的人来说,这个Perl正则表达式可能已经足够了:/^\s*\[?\((.*?)\)\]?\s*T[Jj]/mg。它只是寻找Tj/TJ运算符,这表示PDF中的所有普通文本。 - Alex R
1
使用TomRoush PdfBox库在安卓上运行良好。 - FaisalAhmed
1
在Stack Overflow上,图书馆推荐不属于话题范围。这类问题可能适用于https://softwarerecs.stackexchange.com/。在那里提问之前,请阅读他们的帮助中心和提问指南。 - Dalija Prasnikar
15个回答

149

我收到了一份包含数据表格的,共400页的pdf文件需要导入 - 幸运的是没有图片。 Ghostscript 对我很有帮助:

gswin64c -sDEVICE=txtwrite -o output.txt input.pdf

输出文件被拆分成了包含头部等信息的页面,但是很容易编写一个应用程序来剔除空行等内容,并导入所有30,000条记录。在这种情况下,-dSIMPLE-dCOMPLEX没有任何区别。


49
在Linux和Cygwin上,命令是gs而不是gswin64c。效果完美,没有专利付费的垃圾,它只起作用。 - Jannes
4
好的,没问题!现在我可以毫不顾忌地在我的PDF文件中使用“grep”了。由于我比阅读更擅长使用“grep”,这是一种胜利!(:-)点赞。 - David Elson
1
我使用它处理嵌入了“旧”字体的PDF文件时遇到了唯一的问题。对于本地生成的PDF文件,它完美运行,但对于来自不常见来源的PDF文件则更加困难。除此之外,这是一个非常出色的脚本。 - Jon M
“-sDEVICE=txtwrite”是什么意思?我在阅读《如何使用Ghostscript | 选择输出设备》之后并没有完全理解。 - Ooker
对于标准输出而不是保存为文本文件,请使用gswin64c -sDEVICE=txtwrite -o- input.pdf。来源(稍作修改):https://gist.github.com/drmohundro/560d72ed06baaf16f191ee8be34526ac - LuH
非常感谢!我已经苦苦挣扎了将近三天,试图阅读一个包含表格的PDF,但这个简单的CSharp脚本解决了我的问题。比Word、Adobe Acrobat DC、Tabula或其他任何我尝试过的工具都要好。真是救命稻草。 - RomanPort

43

一款高效的命令行工具,开源且不收取任何费用,在 Linux 和 Windows 平台上均可使用:名称简单,叫做 pdftotext。该工具是 xpdf 库的一部分。

http://en.wikipedia.org/wiki/Pdftotext


8
顺便提一下:使用“-layout”开关可以保留表格,效果不错。 - sebastian
是的,PDFToText的表现出人意料的好。虽然没有完美的东西,但它是我尝试过的最好的工具。我喜欢它有几个不同的算法可以选择。一些算法在处理表格时更有效,另一些算法适用于多列文本,还有一些保留空格,而另一些则削减空格等。它也出人意料地快速。我有一个庞大的1200页 PDF 文件,它只用了几秒钟就提取出了文本,比 Ghostscript 快了约5-10倍。 - Simon East
官方网站是 https://www.xpdfreader.com。 - Simon East
太好了!比使用 gs 获得了更好的结果。pdftext 在行末合并了连字符单词(除非选项 -layout 激活),并保留了一些词间空格,而 gs 则奇怪地合并了这些空格。 - loved.by.Jesus
2023 注意:这确实是最佳解决方案。如果您使用的是 macOS,则需要执行“brew install poppins”以获取“pdftotext”和其他实用程序。 - snarik

31

我从今天开始知道了一个事实:从PDF中提取文本的最佳工具TET文本提取工具包。TET是PDFlib.com产品系列的一部分。

PDFlib.com是Thomas Merz的公司。如果您不认识他的名字:Thomas Merz是“PostScript和PDF圣经”的作者。

TET的第一个版本是。它很可能可以满足Budda006的所有需求,包括页面上每个元素的位置信息。哦,它还可以提取图像。它重新组合了被分成多个片段的图像。

pdflib.com还提供了这项技术的另一种版本,即Acrobat TET插件。第三种版本是PDFlib TET iFilter。这是一个面向用户桌面的独立工具。这两者都可以免费(就像啤酒一样)用于私人非商业用途。

它确实很强大。比Adobe自己的文本提取效果要好得多。它可以从其他工具(包括Adobe的)无法正确输出的文本中提取出有用内容。

我刚刚测试了桌面独立工具,他们网站上说的都是真的。它具有非常好的命令行功能。一些我“有问题”的PDF测试文件,该工具完全满足了我的需求。

从现在开始,这将是我为所有复杂和挑战性的PDF文本提取需求推荐的工具。

TET非常棒。它能检测表格,并识别跨多个列的单元格。它可以分别识别表格行和每个单元格的内容。它还很好地处理断字:它会去除连字符并恢复完整的单词。它支持非ASCII语言(包括CJK、阿拉伯语和希伯来语)。遇到连字时,它会恢复原始字符......

请试用一下。


38
没有试用版,花$440只是为了“试试看”有点贵了。 - Rok Strniša
1
我测试了一下,它无法识别列。我扫描了一份英文小报的封面。纸上的文字被分成了3列,但是这个插件把句子混在一起,使其看起来像乱码。免费的Ghostscript输出完全相同。 - NoWhereToBeSeen
1
@RedHotScalability:顺便说一句,如果使用正确的参数,TET确实可以识别列。但是我将其留给有雄心壮志的JS脚本编写者阅读文档并找出如何做为练习... - Kurt Pfeifle
5
刚刚对比了TET、Xpdf pdftotext以及Ghostscript的结果。PDF文件包含拉丁文和西里尔文,并采用多列布局。其中,Xpdf pdftotext表现最好,其次是Ghostscript,而最差的则是TET。 - zoran
显示剩余3条评论

22

13

这是我的建议。 如果您想从PDF中提取文本,可以将PDF文件导入Google Docs,然后将其导出到更友好的格式,例如.html、.odf、.rtf、.txt等。所有这些都使用Drive API。这是免费的*和强大的。请查看:

https://developers.google.com/drive/v2/reference/files/insert https://developers.google.com/drive/v2/reference/files/get

由于它是rest API,它与所有编程语言兼容。我发布的链接具有许多语言的工作示例,包括:Java、.NET、Python、PHP、Ruby等。

希望对您有所帮助。


3
我使用过该选项,但我不建议使用。谷歌的PDF文本提取并不如许多替代方案(特别是针对非英语部分),而且速度也非常慢。 - Björn Lindqvist
我刚在标准的Google Docs UI中测试了这个功能,实际上我对它的表现感到惊讶。它可以正确解析具有多个文本列的文档,并且是我尝试过的唯一一个工具,可以在认为文本是单个段落的延续时删除行返回,但在其他地方保留行返回。它并不完美,需要一些手动调整,但似乎比大多数其他工具更好,这些工具只会在PDF的每一行末尾强制换行。 - Simon East
我对谷歌的隐私问题非常担忧:他们到底如何处理您上传到他们云盘的数据/文件。通常情况下,我总是更喜欢使用离线方法:gspdftotext。在我看来,将文件上传到谷歌,使用他们的服务器,然后再下载似乎是一种浪费能源和资源的行为——这是我的观点。 - loved.by.Jesus

11

PdfTextStream(你说你一直在看的)现在适用于单线程应用程序,且免费。在我看来,它的质量比其他库要好得多(尤其是对于像时髦的嵌入字体等东西)。它有Java和C#版本。

或者,你可以看看开源的Apache PDFBox


PdfTextStream在Android中不受支持。是否有类似于此的好库可用于Android? - FaisalAhmed
@FaisalAhmed PDFBox怎么样? - Renaud
是的,PdfBox在Android上也不受支持... PdfTextStream和PdfBox都使用了一些在Android上不受支持的awt部分。 - FaisalAhmed
我正在使用这个库,它在安卓上运行良好:https://github.com/TomRoush/PdfBox-Android - FaisalAhmed
PdfTextStream仅适用于C#和Java。 - Simon East
@SimonEast 你可以将它封装为一个Java服务,然后从其他语言中调用它... - Renaud

7

这里有一个评论提到在Windows上使用gs,我也曾在Linux/OSX上尝试过,下面是语法:

gs \
 -q \
 -dNODISPLAY \
 -dSAFER \
 -dDELAYBIND \
 -dWRITESYSTEMDICT \
 -dSIMPLE \
 -f ps2ascii.ps \
 "${input}" \
 -dQUIET \
 -c quit

我使用了dSIMPLE而不是dCOMPLEX,因为后者每行输出一个字符。

6

Docotic.Pdf库可以用来将PDF文件中的文本作为纯文本或每个文本块的坐标集合提取出来。

Docotic.Pdf也可以用于从PDF中提取图像

免责声明:我在Bit Miracle工作。


5
作为这个问题特别关于从PDF提取数据的替代工具,你可能会对商业工具 "ByteScout PDF Extractor SDK" 感兴趣,它能够精确地从PDF中提取文本作为XML,并带有定位数据(x,y)和字体信息。
源PDF中的文本:
Products | Units | Price 

输出XML:

 <row>
 <column>
  <text fontName="Arial" fontSize="11.0" fontStyle="Bold" x="212" y="126" width="47" height="11">Products</text> 
  </column>
 <column>
  <text fontName="Arial" fontSize="11.0" fontStyle="Bold" x="428" y="126" width="27" height="11">Units</text> 
  </column>
 <column>
  <text fontName="Arial" fontSize="11.0" fontStyle="Bold" x="503" y="126" width="26" height="11">Price</text> 
  </column>
</row>

P.S.:此外,它还将文本分成基于表格的结构。

披露:我为ByteScout工作


3

目前我能想到的最好的(在“简单”工具列表中)是Ghostscript(当前版本为v.8.71)和PostScript实用程序ps2ascii.ps。 Ghostscript将其打包在其lib子目录中。在Windows上尝试以下操作:

gswin32c.exe ^
   -q ^
   -sFONTPATH=c:/windows/fonts ^
   -dNODISPLAY ^
   -dSAFER ^
   -dDELAYBIND ^
   -dWRITESYSTEMDICT ^
   -dCOMPLEX ^
   -f ps2ascii.ps ^
   -dFirstPage=3 ^
   -dLastPage=7 ^
   input.pdf ^
   -dQUIET ^
   -c quit

这个命令处理中第3-7页的内容。阅读文件中的注释,以了解“奇怪”的数字和附加信息的含义(它们表示字符串、位置、宽度、颜色、图片、矩形、字体和分页符等等...)。要获得“简单”的文本输出,请用-dSIMPLE替换-dCOMPLEX部分。


2
正如你所猜测的那样,这只输出ASCII文本。虽然免费,但对于计划使用其他语言编写软件来说并不是一个很好的选择。 - userx
3
@userx:正如你所猜测的那样,这是免费软件:因此源代码可用。可以扩展以支持非ASCII字符... - Kurt Pfeifle
@userx:今天我发现了来自pdflib.com的“TET”,即文本提取工具包。请查看我的其他答案。 - Kurt Pfeifle
Ghostscript 9.07 中的 ps2ascii 在我的 OpenBSD 系统上运行得非常好。我刚刚将一份 526 页的 PDF 转换为纯文本。现在我可以轻松地使用 grep 提取文本以供笔记使用。我使用了简单的命令 ps2ascii book.pdf notes.txt。如果您的文档主要是 ASCII,那么您很幸运。 - Clint Pachl

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