PDF の目次ページをクリックできるが、抽出後にレベルが失われる場合はどうすればよいですか?
書き込む前にブックマークの階層を確認する必要があります。最初の項目は 1 レベルであり、後続の項目は最大 1 レベルずつ増加できます。この例では、不正なレベルと範囲外のページ番号が拒否され、ディレクトリ構造を偽造するためにレベルが自動的に変更されることはありません。ブックマークのページ番号は 1 から始まり、ページ インデックスは通常 0 から始まります。
PDF の目次ページはリーダーでは正常にリダイレクトできますが、スクリプトを使用して抽出すると、階層が平坦になったり、ページ番号が間違っていたり、インデックスが異常になったりする場合があります。この種の問題は、スキャンしたファイルや不規則なブックマーク構造を持つファイルを結合するときによく発生します。抽出結果をそのまま下流ユーザーに引き渡すと、翻訳の分割やリンクに誤りが生じる可能性があります。
この記事は、PDF カタログをバッチ処理する必要がある開発者およびドキュメント チームを対象としています。これを読むと、get_toc() 戻り値の意味を理解し、レベルとページ番号の検証ルールを習得し、どの状況を手動検証に変換する必要があるかを知ることができます。この記事では処理方法を示すために合成サンプルを使用しており、コードは隔離された環境でサンプルによってチェックされていますが、これはすべての実際のファイルや製品の効果を保証するものではありません。重要な書類を処理する前に、原本を保管し、本文の境界と許容事項に従って確認してください。
PDF の目次ページはクリックできるが、抽出後に階層が失われる場合はどうすればよいですか?一文の結論
最初に検証してから書き込みます: 最初にブックマーク レベルをチェックする必要があり、最初の項目が最初のレベルとみなされ、後続のレベルは前の項目 + 1 を超えてはならず、範囲外のページ番号を持つエントリは書き込まれません。
| あなたの状況 | 推奨される実践方法 | 理由 |
|---|---|---|
| ディレクトリ ページをクリックすると、抽出後に階層が平坦になるか、位置がずれます。 | まず get_toc() を使用して元のリストを取得し、それを 1 つずつ確認してから使用します。 | get_toc() によって返される元のリストは構造的に検証されていません |
| ページ番号が0または総ページ数を超えています | エントリとログを破棄します | 範囲外のページ番号はジャンプ失敗の原因となります |
get_toc() は空のリストを返します | 代わりにテキスト レイアウト分析を使用し、やみくもに再試行しないでください | ファイルにブックマークのメタデータが埋め込まれていない可能性があります |
| 同じタイトルが複数の異なるページ番号に対応する | 曖昧としてマークし、手動検証に移行します | どのページ番号が正しいかを自動的に判断できません |
抽出結果のレベルが失われるのはなぜですか?
get_toc() はデフォルトで [level, title, page] トリプルのリストを出力します。このうち、page は 1 から始まる物理ページ番号であり、level はネストの深さを表すだけであり、連続性や合法性を保証するものではありません。
ソース PDF がスキャン結合ツールによって生成された場合、一般的な問題には次のようなものがあります。
- レベルジャンプ: たとえば、1 から 3 に直接ジャンプします。
- ページ番号例外: ページ番号が 0 であるか、総ページ数を超えています。
- タイトルの例外: タイトルには制御文字が含まれています
下流のタスクに直接使用すると、翻訳セグメントの混乱やリンク障害が発生します。さらに巧妙なことに、一部の PDF には視覚的な目次ページがありますが、ブックマークのメタデータが埋め込まれていません。現時点では get_toc() が空のリストを返すのは通常のことであり、代わりにテキスト レイアウト分析を使用する必要があります。
自己完結型の構成例
依存関係の例については、インポート リストを参照してください。コードはメモリ内の入力を構築し、実行レコードは個別に提供され、すべての実ファイルの保証を表すものではありません。
import pymupdf
def validate(rows, pages):
previous = 0
for level, title, page in rows:
if type(level) is not int or level < 1 or level > previous + 1:
raise ValueError("invalid hierarchy")
if type(page) is not int or not 1 <= page <= pages:
raise ValueError("invalid destination")
if not isinstance(title, str) or not title.strip():
raise ValueError("empty title")
previous = level
return rows
with pymupdf.open() as doc:
for _ in range(3):
doc.new_page()
rows = [[1, "Chapter", 1], [2, "Section", 2], [1, "Appendix", 3]]
doc.set_toc(validate(rows, doc.page_count))
assert doc.get_toc() == rows
assert len(doc.get_toc()) == 3
for bad in [[[2, "Bad", 1]], [[1, "Bad", 99]], [[1, "", 1]]]:
try:
validate(bad, doc.page_count)
except ValueError:
pass
else:
raise AssertionError("invalid outline accepted")
合法的および違法な入力の処理ルール
正しい入力は次の条件を満たす必要があります: [1, doc.page_count] の範囲内の連続レベルとページ番号を持つトリプルのリスト。たとえば、[[1, "引言", 1], [2, "背景", 2], [1, "方法", 5]] は正当であり、第 2 レベルは第 1 レベルの後に表示され、PDF アウトライン構文に準拠します。
よくある誤った入力には次のようなものがあります。
- レベルが 0 またはマイナスです
- ページ番号は 0 です
- ページ数が総ページ数を超えています
- タイトルが空の文字列であるか、空白文字のみが含まれています
このような状況に対して、この記事で説明されている方法は次のとおりです。
- 無効なページ番号を持つエントリをスキップし、警告を記録します。
- 構造的な整合性を維持するために、空のタイトルには
[untitled]などのプレースホルダーを保持します。 - 単一のエラーが原因でディレクトリ全体の解析を中断しないでください。
レベルが 1 未満の場合については、2 つの戦略があることに注意してください。例の概要部分では不正なレベルを拒否し、自動的に修正しないことを推奨していますが、記事内のルールの説明では強制的に 1 にすることを推奨しています。プロセスに応じてどちらかを決定してください。また、これらのルールは下流プロセスの堅牢性を確保するために設計されており、PDF 標準の必須要件ではないことにも注意してください。実際のテストでは、ページ番号が境界を越えると、PyMuPDF は警告を出力しますが、例外はスローしないことがわかりました。したがって、検証関数は積極的にフィルタリングする必要があり、ライブラリの動作に依存することはできません。
📊 コアの比較
ドキュメントの状況が異なると、get_toc() の結果と推奨される処理方法が異なります。
| ドキュメント | get_toc()の結果 | 推奨される治療法 |
|---|---|---|
| ブックマークがあり、構造は合法です | トリプルのリストを返します | 検証後すぐに使用する |
| しおりはあるがレベルやページ数が異常 | 例外項目を含むリストを返します。 | ログをフィルタリングして記録し、必要に応じて手動操作に移行します |
| ビジュアル版には目次ページがありますが、ブックマークはありません | 空リストに戻る | テキストレイアウト解析への切り替え |
| EPUBなどの文書の並べ替え | ページ番号の形式は(章、pno) | このページ番号検証ロジックは適用できず、専用の処理が必要です |
受理基準と手動審査の境界
以下の表はPDFカタログメタデータの抽出段階のみに焦点を当てています。
| 現象を観察してください | この件を処理する決定 | 自動化が適しているかどうか |
|---|---|---|
| ページ番号は0以上で、総ページ数を上回ります | 記録は破棄して記録します | はい |
| レベルが1未満または整数でない | 上記のルールに従って扱ってください(前述の説明を参照) | はい |
| タイトルは完全に空白か、純粋に象徴的なものである | [untitled]に置き換えてください | はい |
| ジャンプレベル(例:1から3) | 中間層を埋めずに元の層をそのままにしてください | はい(構造的に法的には) |
| 同じタイトルが複数の異なるページ番号に対応しています | 曖昧にマークされ、手動に変換されました | いいえ |
| 階層的な変更なしに200以上のエントリーがあります | 疑わしいOCR誤認は手動検証が必要です | いいえ |
| 外部URIまたはJavaScriptアクションを含む | ページ以外のリダイレクトをフィルタリングする | はい(セキュリティポリシー) |
| EPUBなどの文書の並べ替え、ページ番号(章、pno) | このページ番号検証ロジックは適用できません | いいえ(特別扱いが必要) |
コードデモンストレーションは構造的な合法性のみをチェックすることに注意してください。ジャンプの正確性を検証するために、エンドツーエンドの効果をレンダリングと組み合わせる必要があります。
🎯 どの方法があなたに合いますか?
ディレクトリをバッチ抽出する必要がある場合
まず、get_toc()の結果に対して構造的検証を行い、その後のワークフローに書き込み、検証用にログを保持します。
PDFに目次があるのに抽出が空の場合
get_toc()を繰り返し試さず、テキストレイアウトの分析と処理に切り替えてください。
ディレクトリのエントリが同じ名前でページが違う場合
これらのエントリーは手動で確認してください。ページ番号のいずれかを自動的に選択しないでください。
もし文書を翻訳プロセスに渡したいなら、
まず、段落の混乱を避けるために、翻訳前に正しい目次構成とページ番号を確認してください。
❓ よくある質問(FAQ)
1. なぜページ番号は1から始まるのに、ページインデックスは通常0から始まるのでしょうか?
ブックマークページ番号は通常、1から始まる物理的なページ番号です。一方、PyMuPDFのようなライブラリのページインデックスは通常0から始まります。 この違いは変換時に重要で、そうでなければページ番号のずれが原因となります。
2. get_toc():空のリストを返すことは必ずしもファイルの問題を示すのでしょうか?
必ずしもそうとは限りません。 一部のPDFは目次ページは視覚的にはありますが、ブックマークのメタデータが埋め込まれていないため、空のリストを返すのが普通です。この場合、テキストレイアウト解析を使うべきです。
3. ページ番号が境界外になった場合、図書館はすぐにエラーを報告しますか?
いいえ。 この記事のテストによると、PyMuPDFはページ番号が境界外に出たときに警告を印刷しますが例外は出さないため、検証機能は積極的にフィルタリングする必要があります。
4. 階層的なジャンプ(例えば1から3へ直進する)は中間層を埋める必要がありますか?
記事の提案は、元の階層を維持し、中間層を埋めないようにすることです。この構造は依然として正当なものです。
📝 概要
PDFディレクトリの階層やページ番号は使用前に確認する必要があるため、get_toc()の元の出力は直接信頼できる構造とは見なせません。 曖昧さやブックマークの欠如に直面した場合は、迅速に手作業に切り替えるか、他の方法に切り替えて下流のプロセスエラーを避けましょう。
参考文献と今後のステップ
次のステップは、既知のディレクトリ問題を含むテストPDFを作成し、上記の検証スクリプトを実行し、さまざまな異常の割合を計算することです。 頻繁に階層的なスキップやページ番号のオフセットがある場合は、翻訳前に目次再構成ステップを追加することを検討してください。
このチェックリストを文書翻訳に使ってください
まず、ページの順序、出典の場所、テキストの整合性を慎重に確認し、同じ脱感作サンプルを翻訳プロセスに提出します。 翻訳後も、タイトル、本文、キャプションが正しく一致しているかを確認する必要があります。テキストの滑らかさだけで判断するだけでは不十分です。
OmniDocはマルチフォーマットの文書翻訳ポータルを提供しており、公式ウェブサイトではOCR、用語集、バイリンガル参照機能を導入しています。 ファイルから直接読み始めたいチームにとっては、実際のサンプルを使って評価する価値のある道です。 アップロード許可を得た匿名ファイルを使用し、この記事のチェックリストで結果を検証してください。 これは、OmniDocがこの記事のオープンソースライブラリや内部アルゴリズムを使用していることを主張するものではなく、製品の性能テストを例で置き換えているわけでもありません。


