كل مستخرج نص هندسي يخمّن. يقرأ المحارف التي ترسمها صفحة، ويرتبها حسب خط الأساس والموضع الأفقي، ويأمل أن يطابق الترتيب البصري الترتيب الذي سيقرأ به إنسان. وفي تقرير أحادي العمود يكون ذلك التخمين صائبا. وفي مقال صحفي بعمودين، أو نموذج بشريط جانبي، أو جدول صدرت خلاياه عمودا بعمود، يكون خطأ بطرق يصعب ملاحظتها ومكلف اكتشافها لاحقا في المسار. يجيب HotPDF عن ذلك بـ ExtractLoadedPageStructureText، التي تتجاهل الهندسة كليا: تجوب شجرة بنية المستند بترتيب التأليف كما يعرفه ISO 32000-1 §14.8.4، ثم تعيد تجميع محارف الصفحة بمعرف المحتوى الموسوم لديها. وفي PDF موسوم فهذا ليس استدلالا بل هو الترتيب الذي صرح به التطبيق المنتج
تعيد الدالة False عندما لا تملك الصفحة شجرة بنية قابلة للاستخدام، وهو الإشارة إلى الرجوع إلى المستخرج الهندسي بدل الفشل. ذلك التصميم ذو المسارين أهم من الخوارزمية: استقبال المستندات الحقيقي يرى نماذج حكومية موسومة ومخرجات ماسح ضوئي في المجلد نفسه، والمسار الذي يعالج أحدهما فقط ليس مسارا
لماذا يخطئ الاستخراج الهندسي في ترتيب القراءة؟
لأن مسار محتوى PDF لا يحمل أي ترتيب قراءة. إنه تسلسل معاملات رسم، والمنتج حر في إصدارها بأي تسلسل يناسب محرك التخطيط لديه. معالجات الكلمات تصدر عادة بترتيب السريان فيبدو الترتيب الهندسي سليما. أدوات التخطيط ومصممو النماذج ومولدات التقارير كثيرا ما لا تفعل: يمكن أن يصدر تذييل الصفحة قبل المتن، ويمكن أن يملأ جدول بالأعمدة أولا، ويمكن لصفحة بعمودين أن تتداخل أسطرها من العمودين لأن المصمم حلهما معا
نمط الإخفاق صامت. المستخرج الهندسي لا يفيد عن خطأ أبدا، بل يسلم نثرا جُرّت جمله من عمودين. وكل ما يستهلك ذلك النص، فهرس بحث أو موصل حقول فواتير إلكترونية أو مسار استرجاع يغذي نموذج لغة، يرث الضرر بلا تحذير. تشحن HotPDF أيضا المستخرجات الهندسية للمستندات المحملة، وهي تبقى الأداة الصحيحة للملفات غير الموسومة؛ والغاية من مسار ترتيب البنية هي كف التخمين عندما يحمل المستند الجواب أصلا
ما تخزنه شجرة البنية فعلا
يحمل PDF الموسوم وصفا ثانيا موازيا للصفحة. يشير الفهرس إلى /StructTreeRoot، وأبناء /K لديه يشكلون شجرة عناصر بنية: /Document و/Sect و/P و/Table و/TR و/TD وهكذا. وأوراق تلك الشجرة مراجع محتوى موسوم، أعداد صحيحة تسمي مدى من مسار محتوى الصفحة. ومن جهة المحتوى، تفتح تلك المدايات بمعامل BDC يحمل /MCID وتغلق بـ EMC. وكل عنصر بنية يحمل أيضا مدخلة /Pg تسمي الصفحة التي ينتمي إليها، وهو ما يجعل الاجتياز لكل صفحة ممكنا في مستند تمتد شجرة بنية لمئات الصفحات
تجتاز HotPDF تلك الشجرة بسقف عمق 128 مستوى وترشح على /Pg كي تساهم الصفحة الحالية فقط. وخرج الاجتياز ليس نصا بل قائمة مرتبة من قيم MCID: ترتيب التأليف لمدايات المحتوى الموسوم في هذه الصفحة. وإعادة تجميع النص تصبح بعدها مسألة عرض المحارف بهذا الترتيب
يُسجل MCID أثناء استخراج المحارف لا يُبحث عنه بعد ذلك
هذا هو تفصيل التنفيذ الذي يجعل الميزة رخيصة. تسجل HotPDF أصلا معرف المحتوى الموسوم النشط على كل حرف تستخرجه، في حقل MCID من THPDFGlyphRecord، لأن مفسر مسار المحتوى يعرف أي نطاق BDC مفتوح لحظة معالجة كل معامل Tj أو TJ. لا يحتاج استخراج ترتيب البنية إذن إلى مرور ثان على مسار المحتوى. يجمع تسلسل MCID من شجرة البنية، ثم يصنف المحارف المستخرجة أصلا في مجموعات بحسب MCID ويصدرها بذلك التسلسل
var
Pdf: THotPDF;
PageCount, I, Untagged: Integer;
PageText, AllText: UnicodeString;
Report: TStrings; // حوض تشخيصات يملكه المستدع
begin
Pdf := THotPDF.Create(nil);
try
PageCount := Pdf.LoadFromFile('accessible-form.pdf');
AllText := '';
for I := 0 to PageCount - 1 do
begin
if Pdf.ExtractLoadedPageStructureText(I, PageText, Untagged) then
begin
// ترتيب التأليف مباشرة من شجرة البنية
if Untagged > 0 then
Report.Add(Format('page %d: %d glyphs outside the structure tree',
[I, Untagged]));
end
else
// لا شجرة بنية قابلة للاستخدام في هذه الصفحة: بديل هندسي
Pdf.ExtractLoadedPageText(I, PageText);
AllText := AllText + PageText + #13#10;
end;
finally
Pdf.Free;
end;
end;
المحارف غير الموسومة تُعد ولا تُسقط بصمت أبدا
يمكن أن تكون الصفحة موسومة جزئيا. يضيف المنتجون خطا زخرفيا أو رقم صفحة أو علامة مائية متأخرة خارج أي نطاق BDC، وتلك المحارف لا تنتمي إلى أي MCID. إسقاطها سيكون التنفيذ المرتب والتنفيذ الخاطئ، لأن الفجوة نفسها تظهر أيضا عندما يوسم المنتج المتن وينسى الجدول، فستفقد الجدول دون أن تنتبه
تلحق HotPDF المحارف غير المدعاة كذيل هندسي بعد النص المرتب بالبنية وتفيد عن عددها عبر معامل الخرج UntaggedGlyphCount. ذلك العدد إشارة جودة يمكنك التصرف على أساسها. حفنة محارف في صفحة من ألفين هي أثاث صفحة ويمكن تجاهلها. وأربعون بالمئة من الصفحة خارج شجرة البنية يعني أن الوسم زخرفي وأن المستخرج الهندسي هو الجواب الأصدق لذلك الملف
function ExtractPageBestEffort(Pdf: THotPDF; PageIndex: Integer;
out AText: UnicodeString; out UsedStructure: Boolean): Boolean;
var
Untagged, TotalGlyphs: Integer;
Glyphs: THPDFGlyphArray;
begin
UsedStructure := False;
if Pdf.ExtractLoadedPageStructureText(PageIndex, AText, Untagged) then
begin
TotalGlyphs := 0;
if Pdf.ExtractLoadedPageGlyphs(PageIndex, Glyphs) then
TotalGlyphs := Length(Glyphs);
// ثق بشجرة البنية فقط عندما تدعي معظم الصفحة
if (TotalGlyphs = 0) or (Untagged * 4 <= TotalGlyphs) then
begin
UsedStructure := True;
Result := True;
Exit;
end;
end;
Result := Pdf.ExtractLoadedPageText(PageIndex, AText);
end;
ما الذي يجعل الدالة تعيد False
ثلاث حالات تستحق التمييز لأن واحدة منها فقط عيب في المستند. الأولى PDF عادي غير موسوم: لا /StructTreeRoot، ولا شيء للجوبان، وFalse هي الحقيقة ببساطة. والثانية صفحة ممسوحة ضوئيا يأتي نصها من طبقة OCR لم توسم قط. والثالثة هي المثيرة: محتوى يحمل معاملات BDC بقيم /MCID لكن صفحته بلا مدخلة /StructParents وشجرة بنية لا تشير إلى تلك المعرفات أبدا. المحتوى الموسوم موجود، وجهة البنية غير موجودة، ولا ترتيب لاستعادته. تفيد HotPDF بـ False بدل اختراع ترتيب
تظهر الحالة الأخيرة في ملفات حررتها يدويا وفي مخرجات أدوات تصدر محتوى موسوما لأغراض المحتوى الاختياري أو الأثر دون بناء شجرة بنية. وإن كنت تنتج ملفات PDF موسومة بنفسك، فإن عدم التماثل نفسه هو ما يفحصه تحقق PDF/UA، والنظير في جانب الكاتب مشمول في DOM التخطيط الذي يصدر مخرجات موسومة مرقمة الصفحات
أين يسدد ترتيب البنية كلفته
تدقيق إمكانية الوصول هو المثال البديهي: إن كنت تصادق على مستند مقابل PDF/UA، فإن ترتيب القراءة الذي سيعلنه قارئ الشاشة هو ترتيب البنية بالضبط، فاستخراجه هو طريقة مراجعته من دون قارئ شاشة. والتقاط البيانات هو الحالة التجارية الأكبر. النماذج الحكومية الموسومة والإفصاحات المنظمة ومرفقات الفواتير الإلكترونية تحمل عناوين الحقول وقيمها بترتيب مصرح به، وقراءتها بهذا الترتيب يزيل صنفا كاملا من عيوب الربط التي يصنعها الاستخراج الهندسي على التخطيطات متعددة الأعمدة
أحدث المستهلكين هو الاسترجاع لنماذج اللغة. تقطيع مستند للتمثيل التضميني لا يكون جيدا أفضل من ترتيب النص، والقطعة التي تخيط عمودين تنتج جملا لم توجد قط. استخراج ترتيب البنية أرخص إصلاح متاح لذلك، لأن الترتيب الصحيح موجود في الملف أصلا للمستندات الموسومة ويحتاج فقط إلى القراءة
HotPDF مكون VCL أصلي لـ Delphi وC++Builder، فيعمل اجتياز شجرة البنية وعرض المحارف كلاهما داخل العملية مقابل مستند محمل دون أي مصير خارجي. وتفاصيل الواجهة البرمجية الكاملة لعائلة الاستخراج للمستندات المحملة في صفحة منتج HotPDF Delphi PDF component