部品に基づいたPDF文書の分割

部品に基づいたPDF文書の分割

これはXYの問題、最後にコンテキストの詳細)

章のタイトルに基づいてPDFをプログラムで分割する方法はありますか?それは

このPDFから2つのPDFを生成します。 1つは「XY」部分まですべてを含み、2番目は他のすべてを含みます。

ページ番号に基づいてPDFを分割する方法を学ぶしかし、より多くの「意味」を使用できますか?

(簡単に言えば、元の質問は次のとおりです。NSFは、ある文書に参照リストを持ち、別の文書に説明をしたく、LaTeX / pandocを使用して文書を生成しているので、すべての内容を含めたいです。する方が簡単で、リンクは重要ではありません。)

答え1

pdftk私はこの種の作業に使用するのが好きです。

Latexを使用して基本文書を作成すると、次のようになります。

\documentclass{report}
\usepackage{blindtext} % For lorem ipsum text
\usepackage{hyperref} % Turns chapters/sections into bookmarks

\begin{document}

\chapter{First Chapter}
\Blindtext[10]

\section{Subsection of chapter 1}
\Blindtext[3]

\chapter{Second Chapter}
\Blindtext[20]

\chapter{Third Chapter}
\Blindtext

\pdfbookmark{Example bookmark}{A}
\Blindtext

\end{document}

を実行すると、pdflatex各章の自動ブックマーク、セクション1.1の詳細なブックマーク、その後の手動ブックマーク、および多くのlorem ipsumフレーズを含む13ページのPDFが生成されます。

これでPDFファイルがあるので、それを使用してpdftkその洞察を得ることができます。資料が多すぎて興味深い部分だけ切りました。

$ pdftk sample.pdf dump_data
InfoBegin
...
NumberOfPages: 13
BookmarkBegin
BookmarkTitle: First Chapter
BookmarkLevel: 1
BookmarkPageNumber: 1
BookmarkBegin
BookmarkTitle: Subsection of chapter 1
BookmarkLevel: 2
BookmarkPageNumber: 3
BookmarkBegin
BookmarkTitle: Second Chapter
BookmarkLevel: 1
BookmarkPageNumber: 5
BookmarkBegin
BookmarkTitle: Third Chapter
BookmarkLevel: 1
BookmarkPageNumber: 11
BookmarkBegin
BookmarkTitle: Example bookmark
BookmarkLevel: 1
BookmarkPageNumber: 12
PageMediaBegin
...

ラベルをクリックすると、ブックマークがBookmarkBeginあることがわかります。それを見ると、BookmarkTitle: X私たちはパート1に達したことがわかりますXBookmarkPageNumber:各ブックマークには関連するブックマークがあります。これを分割に使用できます。BookmarkLevel分割したいレベル(章、セクション、サブセクション)をフィルタリングするためにも使用できます。


チャプター1とチャプター2に分割したいとしましょう。 4ページ前に分割を追加する必要があるというデータを見ると、次のようになります。

BookmarkTitle: Second Chapter
BookmarkPageNumber: 5

これでページ番号があるので、それをpdftk分割に使用できます。これには実際にcat特定のページでの使用が含まれます。

pdftk sample.pdf cat 1-4 output sample-1.pdf
pdftk sample.pdf cat 5-end output sample-2.pdf

より一般的なアプローチをとり、.pdfというpdfスクリプトで書いてみましょうsample.pdf。各高度なブックマークでPDFを分割してみましょう(該当部分のフィルタリング)。

まず、ブックマークタグをより簡単に解析できる形式に変換し、何かを書くことができるようにします。awk(別名で保存しますparser.awk

#!/bin/awk -f
BEGIN {
    FS=": "
    OFS=";"
}
/^BookmarkBegin/ {
  if (this_level > 1) { # Only handle high-level sections
    next
  }
  if (this_page == "" || this_title == ""){
    next
  }
  if (last_page != "" && last_title != "") {
    print last_title, last_page, this_page-1
  }
  last_title=this_title
  last_page=this_page
  this_title=this_page=this_level=""
}
/^BookmarkTitle:/ {
    this_title=$2
}
/^BookmarkPageNumber:/ {
    this_page=$2
}
/^BookmarkLevel:/ {
    this_level=$2
}
END {
  print last_title, last_page, this_page-1
  print this_title, this_page, "end"
}

ここでは、ヘッダーにaが含まれていないと仮定するため、;これを出力区切り文字として使用します。スクリプトは以下を出力します。

  1. 各部の名称
  2. このセクションのホームページ
  3. このセクションの最後のページです。
$ pdftk sample.pdf dump_data | awk -f parser.awk
First Chapter;1;4
Second Chapter;5;10
Third Chapter;11;11
Example bookmark;12;end

それでは、各行を繰り返して、pdftkbashでこれを呼び出してみましょう。

#!/bin/bash                                                                     
                                                                                
sequence=1                                                                      
                                                                                
pdftk sample.pdf dump_data | awk -f parser.awk | \                              
while IFS=";" \                                                                 
read -r title start end                                                         
do                                                                              
  pdftk sample.pdf cat "$start"-"$end" output sample-$sequence-"$title".pdf      
  sequence=$((sequence+1))                                                      
done                                                                                     

これにより、以下が残ります。

$ ls *.pdf
'sample-1-First Chapter.pdf'
'sample-2-Second Chapter.pdf'
'sample-3-Third Chapter.pdf'
'sample-4-Example bookmark.pdf'
sample.pdf

これに対する1つの制限は、同じページに複数のブックマークがある場合、または非常に少ないブックマークがある場合は少し混乱する可能性があることです。

答え2

昨年、私はPythonライブラリを使ってpy_pdf_parser同様の目標を達成しました。pdfplumberさらに、MathPix API(有料ですが最小限のコスト)を使用してLatexに最終変換しました。

ここで私のスクリプトをチェックして、役に立つかどうかを確認できます。https://github.com/sekerez/linear_algebra_done_right/blob/main/problems/extract_problems_from_pdf_book.pyこのスクリプトは本の問題をすべて抽出し、練習問題番号と問題番号に基づいてデータ構造に整理します。ほんの数行のコードでこれを行うことができるという事実は驚くべきことです。

ユースケースに合わせてスクリプトを調整する必要があります。各PDFは非常に異なるため、機械がPDFを処理するのは非常に困難です。したがって、PDF形式に基づいて独自のスクリプトを手動で作成する必要があります。

答え3

スチュアートの答えほとんどすべてのツールが提供されていますが、ソリューションに2つの重要な編集を行いました。

  1. 使用一貫性pdfディレクトリを維持します(pdftkはディレクトリを削除します)。
  2. コマンドは、ファイルを長さだけ多くの章に分割するのではなく、ファイルを2つの部分に分割します。

parser.awkソースコードが呼び出され、source.pdf文書を分割したいセクションが「付録」であると仮定し、Stewartsが共有したものを再利用すると、次のようになります。

pdftk source.pdf dump_data | \
awk -f parser.awk  | \
grep Appendix | \
{ 
    IFS=";" ; \
    read -r title start end; \
    ./cpdf source.pdf  1-"`expr $start - 1`" -o A.pdf; \
    ./cpdf source.pdf "$start"-"$end" -o B.pdf;
}

これ

  1. ファイルのメタデータをダンプします。
  2. 対応するビット(title ; page start ; page ends)を抽出し、
  3. 付録の関連部分をつかんで、
  4. read区切り記号を次のように設定します。;
  5. タイトルをtitle変数に保存し、開始ページをにstart、終了ページをに保存しますend
  6. start - 11から(付録開始前のページに該当)までのすべてのページをA.pdf
  7. 文書の残りの部分をB.pdf

関連情報