指定された宛先をPDFとしてリスト

指定された宛先をPDFとしてリスト

PDFファイルで指定された宛先を一覧表示するには?

名前付き宛先は、アンカーポイントと呼ばれるものの公式名です。fooリンクをクリックすると、メインブラウザが指定された宛先に移動しますhttp://example.com/some.pdf#foo

アンカーが機能していることを確認できるドキュメントがありますが、リストする方法が見つからないようです。 Evince、okular、およびxpdfは、指示があるときにその項目に移動しますが、リストされたインターフェースはないようです。pdftk dump_dataブックマークを一覧表示しますが、これは同じではありません(指定されたターゲットと同じ場所にある可能性が最も高いがアンカーとして使用できないコンテンツアイテムテーブルです)。

私はコマンドラインソリューションを探しています(例:などの完成後に使用するのに適していますevince -n)。これは意味があるので、文書に表示される順序でターゲットを一覧表示したいと思います。ボーナス:ターゲットページ番号とターゲットの場所を決定するのに役立つその他の情報を表示します。

また、見ることができますソフトウェア推奨事項のPDF文書のアンカーを表示するGUIビューア用。

答え1

ポプラの PDFについてコマンドラインユーティリティは、PDFで指定されているすべての宛先のページ番号、場所、名前を提供します。 Popplerバージョン0.58以降が必要です。

$ 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)

関連情報