Hacker News 中文摘要

RSS订阅

你想解析PDF文件吗? -- So you want to parse a PDF?

文章摘要

解析PDF文件看似简单,实则复杂。首先需定位文件开头的版本头注释,接着找到交叉引用指针,再获取所有对象的偏移量,最后构建指向目录字典的尾部字典。PDF对象包含有效内容,如数字、字符串等,并通过间接引用相互关联。尽管规范要求某些对象类型,但生产者应用可自由分割文件内容。

文章总结

解析PDF文件的挑战与技巧

如果你对解析PDF文件感兴趣,那么这篇文章将为你揭示其中的复杂性与挑战。虽然PDF文件的结构在理论上看似简单,但实际操作中却充满了各种意外和陷阱。

理想中的PDF解析流程

根据PDF规范,解析一个PDF文件的流程如下:

  1. 定位版本头注释:首先,找到文件开头的版本头注释。
  2. 定位交叉引用表指针:接着,找到指向交叉引用表(xref)的指针。
  3. 查找所有对象的偏移量:通过交叉引用表,找到所有对象的偏移量。
  4. 构建尾字典:最后,定位并构建尾字典,它指向目录字典。

PDF对象简介

PDF对象将一些有效的内容(如数字、字符串、字典等)包装在对象和生成号中。对象内容被obj/endobj标记包围。例如,一个简单的数字可以有自己的PDF对象:

16 0 obj 620 endobj

这表示对象16(生成号0)包含数字620。PDF文件实际上是一个对象图,对象之间可以通过间接引用相互引用。例如,“16 0 R”表示内容应位于对象16中。

查找交叉引用表偏移量

为了避免扫描整个文件,PDF文件声明了一个交叉引用表(xref),它指向文件中每个对象的位置。文件末尾通常有一个指向交叉引用表的指针:

<< %trailer >> startxref 116 %%EOF

这告诉解析器跳转到字节偏移量116处查找交叉引用表。理论上,这个指针应位于文件末尾,但实际上,情况要复杂得多。例如,Adobe Acrobat只要求%%EOF标记位于文件的最后1024字节内,而在实际文件中,它可能出现在任何位置。

查找所有对象的偏移量

在指定的偏移量处,你应该找到一个格式良好的交叉引用表:

xref 7 4 0000000000 65535 f 0000109882 00000 n 0000109933 00000 n 0000140066 00000 n

xref指示符后,第一行给出起始对象号和对象数量。每行提供字节偏移量、生成号和状态(n表示使用中,f表示空闲)。通过这个表,我们可以找到对象8-10的位置。

定位尾字典

startxref标记上方,你会找到尾字典。它提供了关键元数据,最重要的是根对象的位置。一旦找到根对象,你就可以开始解析内容。

现实中的挑战

虽然理论上解析PDF文件看似简单,但实际情况却复杂得多。PDF文件并不总是遵循规范,解析器需要处理各种意外情况。

  1. 交叉引用表指针问题:指针可能不在文件末尾,可能拼写错误,或者格式不符合预期。在3977个随机样本文件中,有23个文件的交叉引用表声明存在问题,失败率约为0.5%。

  2. 非零偏移量问题:有些文件在%PDF-版本头之前有垃圾数据,导致所有字节偏移量都发生偏移。例如,声明的startxref指针可能是960,但由于开头的10字节垃圾数据,实际位置在970。

  3. 指针指向交叉引用表中间:有些文件的指针指向交叉引用表内容的随机位置,而不是表的开头。

  4. 指针接近交叉引用表:有时指针几乎指向交叉引用表,但可能因为一个空格或换行符而偏离。

  5. 交叉引用表偏移量错误:有时指针正确指向xref标记,但表中的对象偏移量是错误的。

  6. 前一个偏移量错误:当文件被修改时,尾字典中的/Prev指针可能指向错误的位置。

  7. 交叉引用表格式错误:交叉引用表本身可能格式不正确,例如缺少换行符、对象数量声明错误或表中包含垃圾数据。

结论

本文探讨了根据PDF规范解析PDF文件的流程,并通过样本文件调查揭示了实际中的挑战。尽管PDF规范有1300页,但仅解析其中的22页内容就足以让人头疼。大多数PDF阅读器(如PDF.js、Adobe、Sumatra)都能打开这些非规范文件,因为它们扩展了对非规范文件的支持。

解析PDF文件不仅需要理解规范,还需要应对各种意外情况。如果你决定编写一个PDF解析器,准备好迎接挑战吧!

评论总结

评论主要围绕PDF解析的复杂性和挑战展开,观点多样,既有对PDF格式的批评,也有对现有解决方案的讨论。以下是总结:

  1. PDF格式的复杂性

    • 多位评论者指出PDF格式设计复杂,尤其是其混合了二进制和文本的特性,导致解析困难。
    • 引用:userbinator提到“PDF是混合了二进制和文本的奇怪格式”,leeter的老板曾表示“PDF是混沌的,无法从中恢复”。
  2. 解析PDF的挑战

    • 评论者普遍认为解析PDF非常困难,尤其是处理多次编辑后的文件或复杂的布局。
    • 引用:farkin88提到“增量保存链”问题,simonw则建议将PDF转换为图像后再处理。
  3. 现有解决方案

    • 一些评论者分享了使用计算机视觉、OCR和LLM(大语言模型)来解析PDF的经验。
    • 引用:diptanu提到“将PDF转换为图像并应用布局理解模型”,sergiotapia表示“LLM帮助解析PDF,但过程依然艰难”。
  4. 对PDF格式的批评

    • 部分评论者认为PDF格式已经过时,建议使用更简单的格式如Markdown。
    • 引用:throwaway840932呼吁“PDF应像Flash一样被淘汰”,anon-3988抱怨“PDF的复杂性让人头疼”。
  5. 开源工具的重要性

    • 开源工具如pymupdf被多次提及,被认为是解析PDF的重要支持。
    • 引用:sergiotapia称赞“开源开发者是解析PDF的关键”。

总结:PDF解析因其复杂的格式设计而充满挑战,尽管现有技术如计算机视觉和LLM提供了一些解决方案,但许多开发者仍认为PDF格式本身存在问题,呼吁使用更简单的替代方案。