0

我需要从 pdf 流中提取一些信息。
提取相关文本非常简单,因为它类似于:

BT /Fo0 7.20 Tf 67.81 569.38 Td 0.000 Tc (TOTAL AMOUNT) Tj ET

我可以考虑固定 y 位置,而 x 位置由于 giustification 是可变的。但我的问题是识别页面的开头和结尾。

4

1 回答 1

2

您不应该确定您使用“信息提取器”遇到的所有 PDF 都表现得很好。或者你可以,因为你知道他们是?

否则,很可能您遇到的 PDF 代码如下所示:

BT 
  /Fo0 7.20 Tf 
  67.81 569.38 Td 
  0.000 Tc 
  (TO)12(T)13(AL A)11(M)14(OUNT) TJ 
ET

那是, ...

  • ...使用TJ而不是Tj, 以允许单独的字形定位,
  • ...有更多的换行符,
  • ...也许还有更多的修改。

为了可靠地获取页面的文本内容,您必须解析 PDF 的结构,简而言之:

  1. 找到/Type /Page;的所有对象
  2. 转到这些页面对象中的每一个并检索其各自的信息/Contents
    • 可能指向/Contents单个流,或
    • /Contents可能指向一个流数组;
  3. 转到此内容对象并提取其流。

实际上,上述步骤中的第一步可能会变得更复杂一些:

  • 找到并转到该trailer <<...>>部分
  • 在预告片中找到有关文档/Root对象的信息
  • 转到根对象
  • /Pages/Root对象中提取有关 的信息
  • 转到对象(这是一个带有孩子和父母/Pages的中间页面树节点;
  • /Kids通过检查对象找到此页面树节点的所有后代
  • 转到列出的每个相应对象/Kids
    • 它可能是/Type /Pages(在这种情况下,它是另一个页面树节点,而不是树叶,您必须进一步沿着树向下);
    • 它可能是/Type Page(在这种情况下,你到达了一个页面树叶,这意味着你真的到达了一个页面)。

在这一点上,我应该注意,您在此旅程之后找到的第一页是第 1 页。接下来是第 2 页,依此类推。请注意,没有任何页面有任何元数据说“我是第 N 页”——这完全取决于按照您解析从根对象开始的页面树的顺序。

现在您确实找到了内容流,您还面临两个问题:

  1. 您正在查找的内容流可能根本不是明文(如您的代码所示)。内容流经常被一种允许的压缩方案压缩,您必须先扩展它们,然后才能解析文本内容。

    要查看流是否被压缩,请注意相应的*Decode关键字(经常显示为 /Filter /FlateDecode)。

  2. 成功解压缩页面的内容流后,您可能会遇到描述文本的完全不直观的字符代码。它可能与您想象的和示例代码中显示的行为良好的 ASCII 类型完全不同。

    您必须查找字体(甚至像 CID 这样的多字节字体)、它们的编码、CMap 等等。

    除非,正如我在第一句话中所质疑的那样,您知道在您的特定用例中不会发生这种情况......

于 2012-10-02T09:50:29.730 回答