Перейти к содержимому

Создание текстового содержимого для извлечения внешними инструментами

NextPDF Core выступает как создатель PDF. В нём нет публичного средства чтения для преобразования PDF в текст. В контексте Core “извлечение текстового содержимого” означает, что вы создаёте документ так, чтобы его текст можно было извлечь. Для глифов задаётся CMap /ToUnicode, а в документе есть тегированная логическая структура. Благодаря этому совместимое средство чтения или внешний инструмент извлечения сможет восстановить текст в Unicode в порядке чтения.

Извлечение текста из произвольного стороннего PDF — задача потребителя. Для этого используйте дополнительный компонент модуля Inspect или внешний инструмент, а не интерфейс создателя Core.

Окно терминала
composer require nextpdf/core:^3

Операторы вывода текста в потоке содержимого размещают текст на странице (ISO 32000-2 §9.4.3). Коды глифов сами по себе не являются Unicode. CMap /ToUnicode позволяет средству чтения преобразовать эти коды обратно в Unicode для извлечения (ISO 32000-2 §9.10.2). Тегированное дерево структуры фиксирует логический порядок чтения, поэтому при извлечении можно восстановить текст в порядке документа, а не в порядке отрисовки (ISO 32000-2 §14.8).

enableTaggedPdf() создаёт это дерево структуры и сохраняет CMap /ToUnicode для шрифтов со встроенным подмножеством. Вместе эти возможности делают выходной PDF надёжно доступным для извлечения текста.

Document::enableTaggedPdf(string $lang = 'en') создаёт дерево структуры и включает режим соответствия, при котором сохраняется CMap /ToUnicode. 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. Она создаёт тегированный документ, в котором для текста сохраняются CMap /ToUnicode и логический порядок чтения. Поэтому внешний инструмент извлечения сможет восстановить текст в 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 — задача потребителя. Используйте модуль Inspect с дополнительным компонентом Spectrum или внешний инструмент извлечения. Этот рецепт делает ваш результат доступным для извлечения.
  • Сначала настройте тегирование. Вызовите enableTaggedPdf() до добавления содержимого, чтобы дерево структуры зафиксировало текст в порядке чтения. Вызов после добавления содержимого не тегирует ранее добавленное содержимое.
  • Недопустимый языковой тег. enableTaggedPdf() проверяет тег BCP-47 и выбрасывает InvalidConfigException, если тег недопустим. Используйте зарегистрированный тег, например en, zh-Hant-TW или ja.
  • Обычный (нетегированный) результат. Без enableTaggedPdf() обычный результат может не включать CMap /ToUnicode для шрифтов с предопределённым CMap, чтобы уменьшить размер. Тогда извлечение текста для этих шрифтов становится ненадёжным. Тегируйте документ, когда вам нужен извлекаемый текст.

Тегирование добавляет дерево структуры и сохраняет CMap /ToUnicode, поэтому размер результата умеренно увеличивается. Затраты растут с объёмом содержимого и не меняют однопроходную модель отрисовки.

Тегированное текстовое содержимое изначально рассчитано на машинное чтение. Не размещайте секреты в тексте документа, рассчитывая, что они останутся скрытыми. Любой, у кого есть файл, может извлечь такой текст. Этот рецепт про корректную работу создателя, а не про контроль конфиденциальности. О конфиденциальности см. рецепт по шифрованию.

УтверждениеСпецификацияРазделreference_id (идентификатор ссылки)
CMap ToUnicode сопоставляет коды символов с Unicode для извлечения текста.ISO 32000-2§9.10.2
Операторы вывода текста размещают строки на странице в потоке содержимого.ISO 32000-2§9.4.3
Тегированное дерево структуры фиксирует логический порядок чтения для извлечения.ISO 32000-2§14.8

Этот рецепт создаёт текстовое содержимое, доступное для извлечения. Он не заявляет о соответствии PDF/UA-2; это определяет средство проверки. См. рецепт по доступности.