【问题标题】:Export PDF page labels on command line在命令行上导出 PDF 页面标签
【发布时间】:2012-10-16 21:56:00
【问题描述】:

我想导出存储在一些 PDF 文档中的页面标签以便于解析。我知道我可以在使用qpdf 转换 PDF 文档后深入研究,但这似乎有点矫枉过正。

是否没有命令行工具可以简单地打印每个页面(或与其他元数据一起)的页面标签?我知道 PDFSpy 会导出标签,但 300 美元不是一个选项,最好是免费的解决方案。

【问题讨论】:

    标签: pdf command-line page-numbering


    【解决方案1】:

    简短回答:
    我不知道有任何(免费)工具可以“简单地打印”每个页面的页面标签。

    此外,您将无法使用 qpdf 之类的工具或具有同等功能的工具来规避扩展压缩对象和对象流。

    长答案:
    没有这样的工具,因为这些是您在页面标签方面可以安全依赖的仅有的几件事。它们如下:

    1. 每个 PDF 文档必须包含一个根对象。
    2. 该根对象必须属于/Type /Catalog
    3. 文档的预告片将使用键 /Root 后跟间接对象编号引用来显示在哪里可以找到对象。
    4. 如果 PDF 文档使用非标准页面标签,则文档根对象必须有一个名为 /PageLabels 的条目。

    这里是相对容易的地方。因为/PageLabels 键所指的对象可能包含在压缩对象 中。这意味着您必须扩展该对象流。

    如果您真的成功地将页面标签描述为 ASCII,您会发现它不是一个易于解析的平面列表(就像 dictionary 一样):它是一个数字树

    我不会详细介绍这些复杂性,因为要描述所有可能的变化需要很长的文章。您最好直接在official ISO PDF-1.7 specification 中阅读。

    但我会用 ASCII PDF 代码给你一个例子:

    213 0 obj
      << /Type /Catalog
         /PageLabels 
            << 
               /Nums 
                     [ 
                       0 <<           % start labeling from page no. 1
                           /S /r      % label with lowercase roman numbers
                         >> 
                       7 <<           % start new labeling from page no. 8
                           /S /D      % label with standard decimal numbers
                         >> 
                       11 <<          % start labeling page no. 12
                           /S /D      % label with decimal numbers...
                           /P (ABCD-) %   ...but using label prefix 'ABCD-'...
                           /St 3      %   ...followed by '3' as the start decimal.
                         >>
                      ]
            >>
         %%...........................
         %%...more root object keys...
         %%........................... 
      >>
    endobj
    

    上面的例子会将页码 1, 2, 3, ... (last) 像这样标记:

    i
    ii
    iii
    iv
    v
    vi
    1
    2
    3
    4
    ABCD-3
    ABCD-4
    ABCD-5
    ABCD-6
    ...and so on until last page...
    

    如您所见,PDF 标记页面的方法(将页码映射到页面名称)完全不直观。只有学习PDF规范才能理解。

    【讨论】:

    • 感谢您对情况的出色总结。我之前发现了大部分。我意识到它要么是我自己的迷你解析器,要么是其他人以前写​​过的(我希望如此)。我很乐意自己根据根对象中的信息计算它们,但不幸的是,在简单的 jscript 实现(我想使用它)中并不总是很容易找到根对象。 QPDF 很容易让我访问页面对象,但无法要求它直接返回预告片或根对象,因此无法知道在哪里查找目录
    • 好的,经过进一步挖掘,我实际上找到了一个相当简单的解决方案:PDFtk(我之前看过,但是这个功能文档很少)。
    • pdftk.exe document.pdf dump_data output report.txt 将生成一个 txt 文件,其中不仅列出了诸如书签之类的元数据,还列出了页面标签。它看起来像这样:PageLabelNewIndex: 1 PageLabelStart: 1 PageLabelPrefix: C PageLabelNumStyle: DecimalArabicNumberals PageLabelNewIndex: 3 PageLabelStart: 1 PageLabelNumStyle: LowercaseRomanNumerals PageLabelNewIndex: 15 PageLabelStart: 1 PageLabelNumStyle: DecimalArabicNumerals 即 C1,C2,i,ii,...,xiii,1,2,... 易于解析,正是我需要的。 @Kurt,无论如何,谢谢,非常感谢!
    • @grovel: 哦,是的,好棒的 pdftk!现在我想起来了。是的,几年前我什至用过pdftk。然而,当时它不能可靠地为 PageLabel 信息工作,也许这就是我再次忘记它的原因。很高兴您再次为我重新发现了此功能。也将对其进行测试。
    • @Sasha,您可能想在下面查看我的新答案。和你一样,我发现 pdftk 并不总能胜任。
    【解决方案2】:

    我编写了一个基于 Poppler 的小型命令行实用程序来完成这项任务:https://github.com/HeimMatthias/pdfpagelabels

    免责声明:我是 OP,并在另一个帐户下创建了原始帖子。多年来,我一直在通过 pdftk(在上面的评论中列出)成功地使用该解决方案。然而,去年是时候从头开始重新实现我们的系统了,我们遇到了许多实例,我们的实现无法解析 pdf-tk 输出。

    新的命令行工具遵循doing just one thing, but doing it well 的理念,简单地打印pdf 文件的所有或选定页面的页面标签。如果有人觉得这很有用,并在这里偶然发现它,那就更好了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-20
      • 2015-02-27
      • 1970-01-01
      • 2013-06-16
      • 2016-12-06
      • 2021-11-18
      • 2013-06-02
      相关资源
      最近更新 更多