如何从Perl中全文搜索PDF文件?
我有一堆PDF文件,我的Perl程序需要对它们进行全文搜索,以返回包含特定字符串的文件。
到目前为止,我一直在使用它:
my @search_results = `grep -i -l \"$string\" *.pdf`;
$ string是要查找的文本。
但是,这对于大多数pdf来说都是失败的,因为文件格式显然不是ASCII。
我最简单的方法是什么?
澄清:
大约有300个pdf,我不知道其名字。 PDF :: Core可能过于矫kill过正。我正在尝试使pdftotext和grep相互配合,因为我不知道pdf的名称,但我找不到正确的语法。
使用亚当·贝莱尔(Adam Bellaire)的建议的最终解决方案:
@search_results = `for i in $( ls ); do pdftotext $i - | grep --label="$i" -i -l "$search_string"; done`;
解决方案
这里的PerlMonks线程讨论了这个问题。
看来,根据情况,获取pdftotext(命令行工具)可能是最简单的,然后可以执行以下操作:
my @search_results = `pdftotext myfile.pdf - | grep -i -l \"$string\"`;
我第二次提出亚当·贝莱尔的解决方案。我使用pdftotext实用程序来创建我的电子书库的全文本索引。它有点慢,但是可以完成它的工作。至于全文,请尝试使用PLucene或者KinoSearch来存储全文索引。
我们可能需要查看PDF :: Core。
我使用的最简单的全文索引/搜索是mysql。我们只需插入具有适当索引的表即可。我们需要花费一些时间来计算字段的相对权重(标题中的匹配项可能比主体中的匹配项得分更高),但这是可能的,尽管使用了一些毛茸茸的sql。
不赞成使用Plucene(在过去两年中afaik尚未对其进行任何积极的工作),而推荐使用KinoSearch。 KinoSearch在某种程度上是由于了解Plucene的体系结构局限性而发展起来的。
如果我们有大约300个pdf,则一旦我们从PDF中提取了文本(假设PDF具有文本,而不仅仅是文本图像;)并且根据查询量,我们可能会发现grep就足够了。
但是,我强烈建议我们使用mysql / kinosearch路由,因为它们涵盖了很多方面(阻塞,停用词,术语权重,令牌解析),我们无法从中受益。
KinoSearch可能比mysql路由快,但是mysql路由为我们提供了更广泛使用的标准软件/工具/开发人员经验。这样我们就可以使用sql的功能来扩展自由文本搜索查询。
因此,除非我们在谈论巨大的数据集和疯狂的查询量,否则我的钱将花在mysql上。
我的库CAM :: PDF支持提取文本,但是考虑到PDF语法的图形方向,这是一个固有的难题。因此,有时输出会变得乱七八糟。 CAM :: PDF捆绑了一个getpdftext.pl程序,或者我们可以像这样调用功能:
my $doc = CAM::PDF->new($filename) || die "$CAM::PDF::errstr\n"; for my $pagenum (1 .. $doc->numPages()) { my $text = $doc->getPageText($pagenum); print $text; }
我们可以尝试使用Lucene(Perl端口称为Plucene)。搜索非常快,我知道PDFBox已经知道如何使用Lucene索引PDF文件。 PDFBox是Java,但CPAN中的某些地方很有可能会出现类似的情况。即使我们找不到已经将PDF文件添加到Lucene索引中的内容,也不要超过几行代码来自己做。 Lucene将为我们提供更多的搜索选项,而不仅仅是在文件中查找字符串。
还有一种非常快捷和肮脏的方法。 PDF文件中的文本实际上存储为纯文本。如果我们在文本编辑器中打开PDF或者使用"字符串",则可以在其中看到文本。二进制垃圾通常是嵌入的字体,图像等。