私は PDF のパーサー (テキスト抽出) に取り組んでいます。
ページが必要な場合Flate のデコード(zlib 圧縮から)、私のコードはコンテンツ ストリームを解凍することができ、次のような出力 (ストリーム オブジェクト) が得られます。
BT
56.8 721.3 Td
/F2 12 Tf
[<01>2<0203>2<04>-10<0503>2<04>-2<0506070809>2<0A>1<0B>]TJ
ET
文字列配列(TJ のオペランド)に興味があります。
この配列には 16 進数でエンコードされた文字列が複数含まれているようですが、対応する 16 進数値は意味をなさないようです。代わりに、010203... のようなシーケンスが表示されます。これは lz77 圧縮の一種です。
- PDF には複数のレベルの圧縮がありますか?
- 上記の文字列配列からプレーンテキストを取得するにはどうすればよいですか?
ベストアンサー1
このような野心的なプロジェクトを始める前に、完了 公式 PDF-1.7 仕様警告:これは756ページの文書であり、約90の他の文書を参照しており、それらも「規範的な」PDF 用。
PDFソースコードをテキストコンテンツに逆変換するには、エンコーディングフォントによって使用されます。仕様で定義された 5 つの標準エンコーディングを使用できます。
StandardEncoding
MacRomanEncoding
WinAnsiEncoding
PDFDocEncoding
MacExpertEncoding
それに加えて、CustomEncoding
(これは、埋め込まれたフォントがサブセットであり、フォントで定義されたすべてのグリフではなく、ドキュメントに必要なグリフのみが含まれている場合に有効になります)。PDF/ToUnicode
内にテーブルが定義されている場合にのみ、CustomEncode されたテキストを逆順にすることができます。その場合にのみ、エンコードされた文字を文字名に逆順にマップできます。
また、1つ、しかし、四テキスト文字列を表示するために使用できる演算子:
Tj
:「テキストを表示」TJ
:「テキストを表示し、個別のグリフ配置を許可します」'
:「次の行に移動してテキストを表示」"
:「単語と文字の間隔を設定し、次の行に移動してテキストを表示します」
さらに、テキスト文字列を表現する3つの異なる方法ここでは、文字列の例を示します"弦":
(string)
: これは標準の印刷可能括弧内の ASCII 文字 (ラテン語/ASCII テキスト部分でのみ可能)。(\163\164\162\151\156\147)
: これは8進数文字コード(括弧内も含む)は、「付録 D (規範) 文字セットとエンコーディング」仕様書の。<737472696E67>
: これは16進数エンコード山括弧内の文字コード。
テキスト抽出の問題は次のとおりです。
使用印刷可能なASCII文字(
1.
上記)および8進文字コード(2.
(上記)は混在可能です。以下はすべて、文字列の「正当な」表現です。"弦"(リストは完全ではありません!):(\163tring)Tj (\163\164\162\151\156g) Tj (st\162i\156g) Tj ...
使用16進数でエンコードされた文字コード(
3.
上記の表現も簡単ではありません。以下の表現はすべて同等だからです。<73 74 72 69 6E 67> TJ <73 7472 696E67> TJ <7 374 7 269 6E 67>TJ <73 74 72696E 67> TJ <73 74 7 2 69 6E 67> TJ
PDF 仕様で許可されている (または Adobe ビューアで許容されている) その他の奇妙な点については、たとえば以下も参照してください。
私自身、最近、手作業でコーディングした一連の PDF ファイルを作成しました。これは、欠落したテーブル、間違ったテーブル、操作されたテーブル、または正しい/ToUnicode
テーブルが、PDF からテキストへの逆変換の結果にどのように影響するかを示しています。
- テキスト抽出がすべてのPDFで機能しない理由
(この同じリポジトリには、PDF 構文の他の部分と演算子を強調した、手動でコーディングされた PDF 形式の学習資料がさらにいくつか含まれています。)
最後に、OP が提供した PDF ソース コードの小さなスニペットを見てみましょう。
BT
56.8 721.3 Td
/F2 12 Tf
[<01>2<0203>2<04>-10<0503>2<04>-2<0506070809>2<0A>1<0B>]TJ
ET
BT
ET
テキスト表示セクションの始まりと終わりを示す56.8 721.3 Td
現在の点を座標に配置する「水平方向に56.8ポイント、垂直方向に721.3ポイント」。12 Tf
フォントサイズを 12 ポイントに設定します。/F1
使用するフォントをPDF文書内の他の場所で定義されているものに設定します。そのフォントはどこかでフォントエンコーディング(場合によっては/ToUnicode
テーブルも)。フォント エンコーディングによって、テキスト文字列に特定の文字コードが見つかった場合に描画するグリフの形状が決まります。[<01>2<0203>2<04>-10<0503>2<04>-2<0506070809>2<0A>1<0B>]TJ
この最後の部分は、以下の部分に分解できます。
<01>2
:は<01>
最初の文字コードです。2
は「個々のグリフの配置」テキスト表示演算子を使用する場合に許可されますTJ
。<0203>2
: は<0203>
2つの文字コードです。2
again は「個々のグリフの配置」のためにTJ
。<04>-10
:は4<04>
番目の文字コードです。-10
「個々のグリフの配置」とTJ
。<0503>2
:<05>
は5番目の文字コード、<03>
は3番目の文字コード(以前使用)です2
。「個々のグリフの配置」...- 等
個々のグリフの位置: の個々のグリフの位置次のように動作します:
- ポジティブ数字は次のグリフを左(次のグリフまでのグリフ間隔を狭めます)。
- ネガティブ数字は次のグリフを右(次のグリフにスペースを追加します)。
- 数字自体は、現在の単位の 1000 分の 1 を表すものとみなされます。
文字コードの意味: 最初、2 番目、3 番目、... 最後の文字コードの意味を知るには、/ToUnicode
PDF の表でこれらを調べる必要があります。そのような表が埋め込まれていない場合は、運が悪いです。
テキストの抽出容易性をチェックする: PDF が簡単にテキスト抽出に適しているかどうかを確認するには、コマンドライン ツールを使用できますpdffonts
。出力例を次に示します。
$ pdffonts sample.pdf
name type encoding emb sub uni object ID
------------------------- ------------- ------------ --- --- --- ---------
IADKRB+Arial-BoldMT CID TrueType Identity-H yes yes yes 10 0
SSKFGJ+ArialMT CID TrueType Custom yes yes no 11 0
上記の例では、サブセット化されたフォントはSSKFGJ+ArialMT
カスタム エンコーディングを使用しますが、/ToUnicode
という見出しの列に示されているように、PDF にはこのフォントがありませんuni
。したがって、このフォントで表示されるテキストを抽出するのは簡単ではありません (抽出には手動のリバース エンジニアリングが必要になりますが、その後は PDF ページを「読み取る」こともできます)。