تخطَّ إلى المحتوى

إنشاء محتوى نصي يمكن للأدوات اللاحقة استخراجه

⁨NextPDF Core⁩ هو مُنتِج لملفات ⁨PDF.⁩ وهو لا يتضمن قارئًا عامًا لتحويل ⁨PDF⁩ إلى نص. في سياق ⁨Core⁩، يعني “استخراج المحتوى النصي” أن تنشئ المستند بحيث يكون نصه قابلًا للاستخراج. تحمل المحارف خريطة /ToUnicode ⁨CMap⁩، ويكون للمستند بنية منطقية موسومة. عندها يستطيع قارئ متوافق أو أداة استخراج لاحقة استعادة نص ⁨Unicode⁩ وفق ترتيب القراءة.

أما قراءة النص من ملف ⁨PDF⁩ عشوائي من طرف ثالث فهي من مسؤولية المستهلك. استخدم رفيق وحدة ⁨Inspect⁩ أو أداة خارجية لهذه المهمة، لا واجهة المُنتِج في ⁨Core.⁩

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⁩ قائم من طرف ثالث هي مهمة المستهلك. استخدم وحدة ⁨Inspect⁩ مع رفيق ⁨Spectrum⁩، أو استخدم أداة استخراج خارجية. تجعل هذه الوصفة خرجك أنت قابلًا للاستخراج.
  • اضبط الوسم أولًا. استدعِ enableTaggedPdf() قبل كتابة المحتوى، حتى تلتقط شجرة البنية النص بترتيب القراءة. أما الاستدعاء بعد إضافة المحتوى فلا يوسم المحتوى السابق.
  • وسم لغة غير صالح. يتحقق enableTaggedPdf() من وسم ⁨BCP 47⁩ ويطرح InvalidConfigException عندما يكون الوسم غير صالح. استخدم وسمًا مسجَّلًا، مثل en أو zh-Hant-TW أو ja.
  • خرج عادي (غير موسوم). بدون enableTaggedPdf()، قد يحذف الخرج العادي خريطة /ToUnicode ⁨CMap⁩ للخطوط ذات خرائط ⁨CMap⁩ المعرَّفة مسبقًا لتقليل الحجم. عندها يصبح الاستخراج غير موثوق لتلك الخطوط. وسِم المستند عندما تحتاج إلى نص قابل للاستخراج.

يضيف الوسم شجرة البنية ويحتفظ بخرائط /ToUnicode ⁨CMap⁩، لذلك يزيد حجم الخرج زيادة طفيفة. وتتناسب التكلفة مع حجم المحتوى ولا تغيّر نموذج العرض ذي المرور الواحد.

المحتوى النصي الموسوم قابل للقراءة آليًا بحكم تصميمه. لا تضع أسرارًا في نص المستند وتتوقع أن تبقى مخفية. فأي شخص يملك الملف يستطيع استخراج النص القابل للاستخراج. هذه وصفة لصحة المُنتِج، وليست ضابطًا للسرّية. ولتحقيق السرّية، راجع وصفة التشفير.

العبارةالمواصفةالبند⁨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⁩؛ فذلك يحدّده المدقِّق. راجع وصفة إمكانية الوصول.