PDFの透明テキスト抽出における順序保持の課題と解決策
はじめに PDFファイルから透明テキストレイヤーを抽出する際、「テキストの順序が元のPDFと異なってしまう」という問題に直面しました。本記事では、この問題の原因と、JavaScriptとPythonそれぞれでの解決策について解説します。誤っている点もあるかもしれませんが、参考になりましたら幸いです。 PDFの透明テキストとは PDFの透明テキストレイヤーは、PDFファイル内に埋め込まれた検索可能なテキスト情報です。OCR処理されたPDFや、デジタル生成されたPDFには、この透明テキストレイヤーが含まれており、以下のような機能を実現しています: テキスト検索 コピー&ペースト スクリーンリーダーによる読み上げ 機械翻訳 問題:テキストの順序が乱れる理由 PDFの内部構造 PDFファイルは、テキストを「コンテンツストリーム」という形式で保存しています。このストリームには、テキストとその位置情報が含まれていますが、必ずしも読む順序で格納されているわけではありません。 例:PDFコンテンツストリームの概念図 [位置: x=100, y=200, テキスト="見出し"] [位置: x=300, y=400, テキスト="脚注"] [位置: x=100, y=300, テキスト="本文"] 一般的な抽出方法の問題点 多くのPDF処理ライブラリは、以下のような手順でテキストを抽出します: コンテンツストリームからテキストと位置情報を取得 座標でソート (上から下、左から右) ソート結果を出力 この「座標でソート」する処理が、テキスト順序の乱れを引き起こす主な原因です。 具体的な問題例 縦書きと横書きの混在 :日本語文書でよく見られる 複数カラムレイアウト :新聞や雑誌形式 図表の挿入 :本文の流れを分断する要素 ヘッダー・フッター :ページをまたぐ要素 解決策:言語別アプローチ JavaScript (PDF.js) での解決策 PDF.jsは、Mozillaが開発したJavaScriptベースのPDFレンダリングライブラリです。 順序を保持する実装 // PDF.jsを使用した順序保持テキスト抽出 async function extractTextWithOrder(page) { // getTextContent()はコンテンツストリームの順序を維持 const textContent = await page.getTextContent(); // itemsは元の順序を保持した配列 const orderedText = textContent.items.map(item => { return { text: item.str, x: item.transform[4], y: item.transform[5], width: item.width, height: item.height }; }); // 配列の順序をそのまま使用(座標ソートしない) return orderedText; } ポイント getTextContent()メソッドは、PDFの内部構造に忠実な順序でテキストを返す 配列のインデックスが元の順序を表現 座標による再ソートを行わない Python (PyMuPDF) での解決策 PyMuPDF(fitz)は、MuPDFライブラリのPythonバインディングです。 ...






