コンテンツにスキップ

後段のツールで抽出できるテキストコンテンツを生成する

NextPDF Core は PDF のプロデューサーです。PDF からテキストを読み取る公開リーダーは同梱していません。Core のコンテキストで「テキストコンテンツを抽出する」とは、ドキュメントのテキストが抽出可能になるように作成することを意味します。グリフには /ToUnicode CMap が保持され、ドキュメントにはタグ付きの論理構造が含まれます。これにより、仕様に準拠したリーダーまたは後段の抽出ツールが、読み上げ順序で Unicode テキストを復元できます。

サードパーティ製の任意の PDF からテキストを読み取ることは、コンシューマー側の関心事です。その作業は Core プロデューサーのサーフェスではなく、Inspect モジュールのサイドカーまたは外部ツールの担当範囲です。

Terminal window
composer require nextpdf/core:^3

コンテンツストリーム内のテキスト表示演算子が、ページ上にテキストを配置します(ISO 32000-2 §9.4.3)。グリフコードは Unicode そのものではありません。/ToUnicode CMap により、リーダーは抽出のためにそれらのコードを Unicode へマッピングし直せます(ISO 32000-2 §9.10.2)。タグ付き構造ツリーは論理的な読み上げ順序を記録するため、抽出時には描画順序ではなくドキュメント順序でテキストを復元できます(ISO 32000-2 §14.8)。

enableTaggedPdf() はこの構造ツリーを構築し、埋め込みサブセットフォント用に /ToUnicode CMap を保持します。この組み合わせにより、出力は確実に抽出可能になります。

Document::enableTaggedPdf(string $lang = 'en') は構造ツリーを構築し、/ToUnicode CMap を保持する準拠モードを設定します。Document::setLanguage(string $lang) は BCP-47 の自然言語を記録します。コンテンツを書き込む前に、両方を呼び出します。その後、通常の setFont() / cell() / multiCell() サーフェスでテキストを書き込みます。

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setLanguage('en');
$doc->enableTaggedPdf('en'); // structure tree + ToUnicode retention
$doc->addPage();
$doc->setFont('helvetica', '', 12);
$doc->multiCell(0, 7, 'This text is extractable by a downstream reader.');
file_put_contents(__DIR__ . '/extractable.pdf', $doc->getPdfData());

このプログラムは自己完結型で、ハーネスから実行できます。サンプル examples/38-extract-text-content.php の内容に沿っています。テキストについて /ToUnicode CMap と論理的な読み上げ順序を保持するタグ付きドキュメントを作成し、その後、後段の抽出ツールが順序どおりに Unicode テキストを復元します。

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$paragraphs = [
'NextPDF produces documents whose text content is extractable.',
'A tagged structure tree records the logical reading order.',
'The ToUnicode CMap lets a reader recover Unicode from glyph codes.',
];
$doc = Document::createStandalone();
$doc->setTitle('Extractable text content');
$doc->setAuthor('NextPDF Cookbook');
$doc->setLanguage('en'); // BCP 47; validated on enableTaggedPdf()
// Configure tagged mode BEFORE content so the structure tree captures the
// text in reading order and the /ToUnicode CMap is retained.
$doc->enableTaggedPdf('en');
$doc->addPage();
$doc->setFont('helvetica', '', 12);
foreach ($paragraphs as $p) {
$doc->multiCell(0, 7, $p); // captured in reading order
$doc->ln(2);
}
$pdf = $doc->getPdfData();
// $pdf contains a /StructTreeRoot and per-font /ToUnicode CMaps; an external
// extractor (or the Inspect sidecar) recovers the Unicode text in order.
echo "Wrote a tagged PDF with extractable text content\n";
echo 'Paragraphs authored: ' . count($paragraphs) . "\n";
echo "Text is recoverable via the /ToUnicode CMap + tagged reading order.\n";
// The harness sets NEXTPDF_COOKBOOK_OUTPUT and runs this script under the
// semantic profile; emit the document to the side-channel.
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');
file_put_contents($out !== false && $out !== '' ? $out : __DIR__ . '/extractable.pdf', $pdf);

期待される STDOUT:

Wrote a tagged PDF with extractable text content
Paragraphs authored: 3
Text is recoverable via the /ToUnicode CMap + tagged reading order.
  • リーダーではなくプロデューサーです。 Core には公開されている extractText() はありません。既存のサードパーティ製 PDF からテキストを読み取ることは、コンシューマー側のタスクです。Spectrum サイドカーを備えた Inspect モジュール、または外部の抽出ツールを使用してください。このレシピで抽出可能にするのは、あなたの出力です。
  • タグ付けを最初に構成します。 コンテンツを書き込む前に enableTaggedPdf() を呼び出し、構造ツリーが読み上げ順序でテキストを取り込めるようにします。コンテンツが追加された後に呼び出しても、それ以前のコンテンツにはタグが付きません。
  • 無効な言語タグ。 enableTaggedPdf() は BCP-47 タグを検証し、無効な場合は InvalidConfigException をスローします。たとえば enzh-Hant-TW、または ja のような登録済みのタグを使用してください。
  • プレーン(タグなし)の出力。 enableTaggedPdf() を使用しない場合、プレーンな出力ではサイズ削減のために、事前定義された CMap フォントについて /ToUnicode CMap が抑制される場合があります。その場合、それらのフォントでは抽出が信頼できなくなります。抽出可能性が重要な場合は、ドキュメントにタグを付けてください。

タグ付けは構造ツリーを追加し、/ToUnicode CMap を保持するため、出力サイズがわずかに増加します。コストはコンテンツ量に比例し、シングルパスのレンダリングモデルを変更することはありません。

タグ付きのテキストコンテンツは、設計上、機械可読です。抽出可能なテキストはファイルを持つ誰でも抽出できるため、機密情報をドキュメントのテキストに配置して隠されたままになると期待してはいけません。これはプロデューサーの正確性に関するレシピであり、機密保持のための制御ではありません。機密保持については、暗号化のレシピを参照してください。

記述仕様箇条リファレンス ID(reference_id)
ToUnicode CMap は、テキスト抽出のために文字コードを Unicode へマッピングします。ISO 32000-2§9.10.2
テキスト表示演算子は、コンテンツストリーム内でページ上に文字列を配置します。ISO 32000-2§9.4.3
タグ付き構造ツリーは、抽出のために論理的な読み上げ順序を記録します。ISO 32000-2§14.8

このレシピは、抽出可能なテキストコンテンツを生成します。PDF/UA-2 への準拠を主張するものではなく、その判断はチェッカーの役割です。アクセシビリティのレシピを参照してください。