【问题标题】:Extracting text from PDF从 PDF 中提取文本
【发布时间】:2015-08-17 19:51:46
【问题描述】:

我正在尝试使用找到的代码 here 从 PDF 文件中提取文本。该代码使用zlib 库。

AFAICT 该程序通过在 pdf 文件中的文本“stream”和“endstream”出现之间查找内存块来工作。然后这些块被 zlib 膨胀。

该代码在一个示例 pdf 文档上完美运行,但在另一个示例中,zlib 的 inflate() 函数似乎在每次调用时都返回 -3 (Z_DATA_ERROR)。

我注意到,失败的 pdf 文件被设置为在 Adob​​e 阅读器中打开时没有“复制”选项。这可能与inflate() 错误有关吗?...如果是,有没有办法解决这个问题?

下面的代码 sn-p - 见 cmets

            //Now use zlib to inflate:
            z_stream zstrm; ZeroMemory(&zstrm, sizeof(zstrm));

            zstrm.avail_in = streamend - streamstart + 1;
            zstrm.avail_out = outsize;
            zstrm.next_in = (Bytef*)(buffer + streamstart);
            zstrm.next_out = (Bytef*)output;

            int rsti = inflateInit(&zstrm);
            if (rsti == Z_OK)
            {
                int rst2 = inflate (&zstrm, Z_FINISH); // HERE IT RETURNS -3
                if (rst2 >= 0)
                {
                    //Ok, got something, extract the text:
                    size_t totout = zstrm.total_out;
                    ProcessOutput(fileo, output, totout);
                }
            }

编辑:我通过名为zamzar 的在线 pdf 到文本转换器测试了从“加密”pdf 中提取文本,结果文本文件非常完美。因此,要么 zamzar 有一些超级骗子解密系统......或者它可能不是很困难。

编辑:刚刚发现A-pdf也转换成文字没有问题。

【问题讨论】:

  • 导致错误的示例文档会有所帮助。使用调试器找出错误所在会有所帮助。
  • 您引用的 codeproject 中的代码充满了假设,这些假设有时正确,有时不正确。 没有“复制”选项这一事实可能表明 PDF 已加密以应用限制。它看起来不像 codeproject 代码尝试解密。所以 zlib 试图膨胀显然无法工作的加密数据。正确的方法是使用适当的 PDF 库。
  • 其中一些库的安装和运行似乎非常复杂。我不愿意在没有任何迹象表明它们工作的可能性的情况下完成所有这些工作。

标签: c++ pdf visual-studio-2008 zlib


【解决方案1】:

PDF 中的流不需要使用 flate 编码。它们可以编码为:

  1. 什么都没有
  2. LZW
  3. 平淡
  4. ASCII85
  5. Crypt(可能是几种不同算法之一)

而且(惊喜,惊喜)这些方法中的任何一种也可以相互叠加!

如果没有复制选项,很可能它是用所有者密码加密的,没有用户密码。这允许作者创建读者应该尊重的访问权限,包括:

  1. 修改文档内容
  2. 复制文本/图形
  3. 添加/编辑注释
  4. 打印
  5. 表格填写
  6. 组装文档(插入、删除页面、创建书签、缩略图)
  7. 高/低质量打印

这种从 PDF 中获取文本的特殊方法充满了错误,我可以为您提供一组文档,由于字体重新编码、拆分文本,您将无法使用您的方法使用这些文档、奇怪的位置、形式 XObject、不寻常的变换等等。

要正确执行此操作,您需要一组更好的工具,这些工具不会对 PDF 文档的实际格式和结构视而不见。 iText 会这样做,DotImage 会这样做。

为了让您了解问题的范围,我在 Acrobat 1.0 中编写了原始文本搜索代码,并使用了所有可用的内部工具,我花了好几个月的时间才把它弄好,代码包括了能力查找不寻常的、非直线方向的文本(想想地图)、处理连字、重新编码、非罗马字体等等。当我在编写该代码时,有另一位工程师花了几年时间全职编写名为 Wordy 的代码,为全文提取和索引做类似(但更复杂)的事情(有关 Wordy 的更多信息,请参阅this answer )。

【讨论】:

  • 您会很高兴听到我对文本复制失败的标准建议仍然是“如果 Acrobat 做不到,没有人可以”!
  • 查看对原始帖子的编辑。两个不同的包在我不知道任何密码的情况下成功提取了文本。
  • 两个不同的包在我不知道任何密码的情况下成功提取了文本 - 这基本上意味着这些包不尊重 PDF 规范和作者明确设置的使用限制。
  • 在我看来,数据根本没有真正“加密”。听起来好像某处只有一个标志,上面写着“不允许”……但这并不能解释为什么 zlib 不能 inflate()。嗯,
  • PDF 文件可以有两个密码,一个用户密码和一个所有者密码。如果没有(空)用户密码并且有所有者密码,文件中的数据仍然是加密的,但是由于用户密码为空,任何阅读器都可以在没有所有者密码的情况下访问它。读者应该遵守所有者密码限制。有关所有详细信息,请参阅第 7.6 节,尤其是 PDF ISO 规范中的第 7.6.3 和 7.6.3.2。
【解决方案2】:

如果没有“复制”选项,则 pdf 被加密,流也是如此。普通的 zlib 不起作用,您必须先解密 pdf,现在您使用适当的库来提取文本,需要注意很多编码,并非所有内容都是 win ansi。

【讨论】:

  • 当您说 pdf 是“加密的”时 - 这是否意味着我需要知道一些密码才能解密? (我没有密码)......“适当的图书馆”甚至会有帮助吗?
  • 如果打开它不需要密码,那么它会在没有用户密码的情况下加密。我只知道 iText(免责声明,我是 iText 贡献者),但在 java 的免费选项中也有 pdfbox。
  • “没有用户密码加密”?这对我来说毫无意义。听起来像是文件被打乱了,但以任何人都可以解读的方式……是吗?
  • 所以,正如大家猜测的那样,PDF 被加密以限制使用权限,并且由于您没有密码,因此无法向 PDFBox 提供所有者密码,它正确地告诉您不允许提取文本。
  • @Mick 它听起来像是文件被打乱了,但以一种任何人都可以解读的方式......对吗? - 基本上是的,它主要用作提示 PDF 处理软件设置了权限限制。这种机制显然需要 PDF 处理器配合,它并没有真正执行限制。
【解决方案3】:

这是可能的,因为标题与另一个文档不同,对此请参阅相关问题ZLib Inflate() failing with -3 Z_DATA_ERROR

【讨论】:

  • 我尝试按照标记的答案使用 inflateInit2() ,但这并没有解决它:-(
猜你喜欢
  • 2019-12-13
  • 2023-04-06
  • 1970-01-01
  • 2011-04-30
  • 1970-01-01
  • 2013-02-05
  • 2019-12-05
  • 2015-03-19
相关资源
最近更新 更多