列出 PDF 中的指定目的地

列出 PDF 中的指定目的地

如何在 PDF 文件中列出指定的目的地?

命名目的地是您所谓的锚点的正式名称。foo当您点击 的链接时,主要浏览器会跳转到指定的目的地http://example.com/some.pdf#foo

我有可以看到锚点工作的文档,但我似乎找不到列出锚点的方法。 Evince、okular 和 xpdf 会在收到指示时跳转到它们,但似乎没有列出它们的界面。pdftk dump_data列出书签,但这不是同一件事(这是内容条目表,它很可能与指定目的地位于同一位置,但不能用作锚点)。

我正在寻找一个命令行解决方案(例如,适用于在诸如 之类的完成函数之后使用evince -n)。由于这很有意义,我想按照目的地在文档中出现的顺序列出目的地。奖励:显示目标页码和其他有助于确定目标位置的信息。

也可以看看查看有关软件推荐的 PDF 文档中的锚点对于 GUI 查看器。

答案1

波普勒的 pdf信息命令行实用程序将为您提供 PDF 中所有指定目标的页码、位置和名称。您至少需要 0.58 版本的 Poppler。

$ pdfinfo -dests input.pdf
Page  Destination                 Name
   1 [ XYZ null null null      ] "F1"
   1 [ XYZ  122  458 null      ] "G1.1500945"
   1 [ XYZ   79  107 null      ] "G1.1500953"
   1 [ XYZ   79   81 null      ] "G1.1500954"
   1 [ XYZ null null null      ] "P.1"
   2 [ XYZ null null null      ] "L1"
   2 [ XYZ null null null      ] "P.2"
(...)

答案2

pyPDF库可以列出锚点:

#!/usr/bin/env python
import sys
from pyPdf import PdfFileReader
def pdf_list_anchors(fh):
    reader = PdfFileReader(fh)
    destinations = reader.getNamedDestinations()
    for name in destinations:
        print name
pdf_list_anchors(open(sys.argv[1]))

对于完成用例来说这已经足够好了,但是锚点是以随机顺序列出的。只有 pyPdf 1.13 的稳定接口,我找不到按顺序列出锚点的方法。我还没有尝试过 pyPdf2 。

答案3

(也在这里回答:查看 PDF 文档中的锚点

我有同样的问题,最终通过以下方式找到了一个很好的答案如何直观地检查 PDF 的结构以对其进行逆向工程?

答案是使用Python包pdfminer.six。是均匀的文档中的示例之一!将此代码剪切并粘贴到终端中:

pip install pdfminer.six
cat >extract.py <<EOF
import sys
import pdfminer.pdfparser, pdfminer.pdfdocument
with open(sys.argv[1], "rb") as f:
  parser = pdfminer.pdfparser.PDFParser(f)
  document = pdfminer.pdfdocument.PDFDocument(parser)
  for (level, title, dest, a, se) in document.get_outlines():
    print('  ' * level, title, dest or a, se)
EOF
python extract.py myInputFile.pdf

在我的特定 PDF 上,输出如下所示:

$ python extract.py ~/Desktop/p2786r3.pdf | head
   Abstract {'S': /'GoTo', 'D': b'section.1'} None
   Revision History {'S': /'GoTo', 'D': b'section.2'} None
     R3: October 2023 (midterm mailing)r3-october-2023-midterm-mailing {'S': /'GoTo', 'D': b'section*.2'} None
     R2: June 2023 (Varna meeting)r2-june-2023-varna-meeting {'S': /'GoTo', 'D': b'section*.3'} None
     R1: May 2023 (pre-Varna mailing)r1-may-2023-pre-varna-mailing {'S': /'GoTo', 'D': b'section*.4'} None
     R0: Issaquah 2023r0-issaquah-2023 {'S': /'GoTo', 'D': b'section*.5'} None
   Introduction {'S': /'GoTo', 'D': b'section.3'} None
   Motivating Use Cases {'S': /'GoTo', 'D': b'section.4'} None
     Efficient vector growth {'S': /'GoTo', 'D': b'subsection.4.1'} None
     Moving types without empty states {'S': /'GoTo', 'D': b'subsection.4.2'} None

事实上,p2786r3.pdf#subsection.4.2在我的浏览器中导航到该特定部分会打开 PDF。

答案4

pypdf 库中有一些更改。在这里您可以找到该版本原剧本修改后的脚本使用 python3 和 pypdf:

#!/usr/bin/env python3
import sys
from pypdf import PdfReader

def pdf_get_anchors(fh):
    reader = PdfReader(fh)
    destinations = reader.named_destinations                    #completely unsorted order, does not include pagenums
    L=list();
    np =  len(reader.pages)
    for PageNum in range(1,np+1) :
        ThisPage = reader.pages[PageNum-1]
        PageTop = ThisPage['/MediaBox'][3]
        for name in destinations:
            ThisDest = destinations[name]
            ThisDestPage = ThisDest.page.get_object()
            if ThisDestPage == ThisPage:                        #have to do this to identify the pagenum
                DownPage = (PageTop - ThisDest.top) / PageTop   # calc fraction of page down
                Position = PageNum + DownPage                   # a sortable number down the whole pdf
                L.append((name, PageNum, Position));            # put everything in a sortable list         
    return L, len (destinations), np

def pdf_print_anchors ( L ) :
    for dest in L :
        name=dest[0]
        PageNum=dest[1]
        Position= round(dest[2]*100)/100
        print ("%8.2f % %s" % Position % name) #ThisDest.title

HeaderLine="\n    Page Name"                     
pdf_get_anchors(open(sys.argv[1],'rb'))
L, NumDests, NumPages =pdf_get_anchors(open(sys.argv[1],'rb'))
print (HeaderLine)
L.sort(key=lambda dest: dest[0])                        #sort name order
pdf_print_anchors(L);     
print (HeaderLine)
L.sort(key=lambda dest: dest[2])                        #sort in order down the pdf
pdf_print_anchors(L);
print ("Number of NamedDestinations: ", NumDests, "NumPages: ", NumPages)

相关内容