استخراج نص PDF متعدد الأعمدة بترتيب القراءة الصحيح
أربع كتل مبعثرة من صفحة بعمودين تعود بالترتيب: الأيسر الأول، ثم الأيسر الثاني، ثم الأيمن الأول، ثم الأيمن الثاني. تُكتشف الأعمدة من تقارب الحواف اليسرى، وتُقرأ من اليسار إلى اليمين ومن الأعلى إلى الأسفل. مجاني في متصفحك.
- مجاني
- يعمل في متصفحك
- دون تسجيل
- بياناتك لا تغادر جهازك
شغّل الأداة مجانًا
قد يستخرج النظام جميع كلمات ملف PDF بدقة، لكنه يعيدها في تسلسل غير صالح للقراءة. ففي الصفحة ذات العمودين أو أكثر، يؤدي الفرز الرأسي البسيط إلى التناوب بين فقرات غير مترابطة. تستقبل هذه الإمكانية كتل النص مع إطاراتها، وتحدد الكتل التي تنتمي إلى العمود نفسه، ثم ترتب الأعمدة من اليسار إلى اليمين والكتل من الأعلى إلى الأسفل. تشمل النتيجة النص المعاد بناؤه والهندسة المرتبة كاملة لكي تتمكنوا من مراجعتها أو معالجتها لاحقاً.
لماذا يضيع ترتيب القراءة عند استخراج نص PDF
يصف ملف PDF عادةً مواضع رسم المحارف، لا الترتيب الدلالي الذي يقرأ به الإنسان. لذلك قد تعيد مكتبات الاستخراج الكتل وفق ترتيب كائنات الملف أو الرسم أو ترتيب رأسي عام يقفز بين الأعمدة. وقد يظهر مقال من عمودين بالترتيب الآتي: الفقرة الأولى اليسرى، ثم الأولى اليمنى، ثم الثانية اليسرى.
أرسلوا كل كتلة مع نصها وإحداثيها الأيسر والعلوي وعرضها وارتفاعها. تستخدم الإمكانية هذه الهندسة لاستنتاج مجموعات تتقارب حوافها اليسرى، ثم تضع الأعمدة من اليسار إلى اليمين وترتب كتل كل عمود من الأعلى إلى الأسفل. يجب أن تستخدم جميع الإحداثيات نظام الصفحة نفسه، وأن تمثل `y` الحافة العليا للكتلة.
كيف يبقى اكتشاف الأعمدة حتمياً
تُحدد عضوية العمود بحسب المسافة بين الإحداثيات اليسرى للكتل. تساوي السماحية الافتراضية ربع وسيط عروض الكتل الموجبة، فتتكيف مع مقاييس الصفحات الشائعة وتستوعب الإزاحات الصغيرة وضجيج الاستخراج. تفصل القيمة الأصغر الحواف التي تختلف قليلاً، بينما تضم القيمة الأكبر الفقرات المزاحة أو العناوين إلى العمود المحيط.
بعد التجميع، تُرتب الأعمدة وفق متوسط موضعها الأيسر، وتُرتب الكتل داخلها حسب الموضع العلوي ثم الأيسر ثم فهرسها الأصلي. تضمن قواعد الحسم هذه نتيجة ثابتة حتى عند تطابق الإحداثيات. لا تستخدم الخوارزمية شبكة أو عشوائية أو وقتاً حالياً أو OCR أو نموذجاً لغوياً.
وهي تفسر الإطارات المقدمة فقط، لذا تناسب مسارات المستندات القابلة للتكرار واختبارات الانحدار.
استخدام النتيجة المرتبة في مسار المستندات
تعرض الاستجابة صوراً متعددة للقرار نفسه. احتفظوا بالمصفوفات المنظمة عند الحاجة إلى تتبع المصدر أو التمييز أو العرض فوق الصفحة أو تصحيح الأخطاء، واستخدموا النص المجمع لفهرسة البحث أو التلخيص أو تسهيل الوصول أو التصدير. عالجوا صفحة PDF واحدة في كل طلب، لأن إحداثيات الصفحات المختلفة لا تُقارن من دون تطبيع.
لا تحلل هذه الإمكانية ملف PDF ولا تنفذ OCR؛ بل تستقبل كتل أداة الاستخراج لديكم. كما أنها لا تستنتج الجداول أو الأشرطة الجانبية أو العناوين الممتدة أو الحواشي أو الاستمرار بين الصفحات.
حالات الاستخدام
إعداد المقالات للبحث
حوّلوا كتل مجلة أو نشرة ذات عمودين إلى نص مترابط قبل فهرسته.
إنشاء صادرات ميسرة الوصول
أنشئوا تسلسلاً متوقعاً لقارئات الشاشة أو لتحويل المستندات الميسرة.
تدقيق مسار الاستخراج
احتفظوا بالإطارات المرتبة وفهارس المصدر لتفسير الموضع المخصص لكل فقرة.
الأسئلة الشائعة
هل تقبل هذه الإمكانية ملف PDF؟
لا. فهي تستقبل كتل النص المستخرجة مسبقاً من صفحة PDF واحدة، مع إطاراتها.
كيف تُكتشف الأعمدة؟
تُجمع الكتل ذات الإحداثيات اليسرى المتقاربة بما يكفي.
ما التكلفة؟
ويمكن تشغيل المنطق الحتمي نفسه في المتصفح بصفته إمكانية من الفئة A.
هل يمكنني إرسال عدة صفحات معًا؟
أرسل صفحة واحدة في كل مرة. لا يمكن مقارنة مواضع صفحات مختلفة إلا إذا وحّدت مقياسها بنفسك مسبقًا، لذا فإن خلط الصفحات يبعثر الأعمدة.
هل تتعرف الأداة على الجداول والأطر الجانبية والحواشي؟
لا. ترتّب النص حسب العمود والارتفاع في الصفحة فقط. لا تُستنتج الجداول ولا الأطر الجانبية ولا العناوين الممتدة عبر الأعمدة ولا الحواشي، لذا ميّزها مسبقًا أو اضبط هامش تقارب الأعمدة وراجع النتيجة.
أدوات ذات صلة
للمطوّرين — الوصول عبر API
كل ما في هذه الصفحة متاح برمجيًا. هذا القسم موجّه للفرق التقنية التي تريد ربط الأداة بأنظمتها الخاصة؛ بقية المستخدمين يمكنهم استخدام الأداة أعلاه مباشرة دون الحاجة لقراءة ما يلي.
الـEndpoint
صادِق على طلبك بترويسة Bearer، وأرسل طلب POST واحدًا لتدخل مهمتك قائمة التنفيذ فورًا؛ ثم تستلم النتيجة عبر webhook أو رابط موقّع.
استدعِ الخدمة من بيئتك
curl -X POST https://api.kit.forhosting.com/pdf/text-extract-column-order \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"blocks":[{"text":"Left heading","x":40,"y":40,"width":210,"height":20},{"text":"Right heading","x":320,"y":42,"width":210,"height":20},{"text":"Right body","x":322,"y":90,"width":208,"height":60},{"text":"Left body","x":42,"y":92,"width":208,"height":60}]}'const res = await fetch("https://api.kit.forhosting.com/pdf/text-extract-column-order", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"blocks": [
{
"text": "Left heading",
"x": 40,
"y": 40,
"width": 210,
"height": 20
},
{
"text": "Right heading",
"x": 320,
"y": 42,
"width": 210,
"height": 20
},
{
"text": "Right body",
"x": 322,
"y": 90,
"width": 208,
"height": 60
},
{
"text": "Left body",
"x": 42,
"y": 92,
"width": 208,
"height": 60
}
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/pdf/text-extract-column-order",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"blocks": [
{
"text": "Left heading",
"x": 40,
"y": 40,
"width": 210,
"height": 20
},
{
"text": "Right heading",
"x": 320,
"y": 42,
"width": 210,
"height": 20
},
{
"text": "Right body",
"x": 322,
"y": 90,
"width": 208,
"height": 60
},
{
"text": "Left body",
"x": 42,
"y": 92,
"width": 208,
"height": 60
}
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/pdf/text-extract-column-order", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"blocks":[{"text":"Left heading","x":40,"y":40,"width":210,"height":20},{"text":"Right heading","x":320,"y":42,"width":210,"height":20},{"text":"Right body","x":322,"y":90,"width":208,"height":60},{"text":"Left body","x":42,"y":92,"width":208,"height":60}]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"blocks":[{"text":"Left heading","x":40,"y":40,"width":210,"height":20},{"text":"Right heading","x":320,"y":42,"width":210,"height":20},{"text":"Right body","x":322,"y":90,"width":208,"height":60},{"text":"Left body","x":42,"y":92,"width":208,"height":60}]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/pdf/text-extract-column-order", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)مثال على الطلب
{
"blocks": [
{
"text": "Left heading",
"x": 40,
"y": 40,
"width": 210,
"height": 20
},
{
"text": "Right heading",
"x": 320,
"y": 42,
"width": 210,
"height": 20
},
{
"text": "Right body",
"x": 322,
"y": 90,
"width": 208,
"height": 60
},
{
"text": "Left body",
"x": 42,
"y": 92,
"width": 208,
"height": 60
}
]
}مثال على الاستجابة
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "pdf.text_extract_column_order",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}الواجهة غير متزامنة: تستلم task_id فور الإرسال، ويمكنك الاستعلام عن الحالة بمعدل طلب واحد في الثانية.
الأسعار
السعر معلن كما تراه: لا tokens ولا نظام نقاط؛ وإن فشلت المهمة فلن تُحاسَب عليها.
الحدود
max_items | 10000 |
الأخطاء
| HTTP | الرمز | المعنى |
|---|---|---|
401 | unauthorized | مفتاح الوصول مفقود أو غير صالح؛ تحقق من ترويسة Bearer في طلبك. |
402 | insufficient_balance | رصيدك لا يكفي لتنفيذ هذه المهمة؛ أعد شحن الرصيد ثم أعد المحاولة. |
404 | unknown_type | نوع المهمة المطلوب غير موجود في الكتالوج — راجع الاسم المرسل في الطلب. |
429 | rate_limited | تجاوزت الحد المسموح من الطلبات؛ انتظر قليلًا ثم أعد المحاولة. |
ملاحظات تقنية
لماذا يضيع ترتيب القراءة عند استخراج نص PDF
يحتفظ `reading_order` بالهندسة الأصلية وفهرس المصدر، وبذلك يمكنكم التحقق من موضع كل كتلة بدلاً من الاعتماد على تحويل نصي غامض.
كيف يبقى اكتشاف الأعمدة حتمياً
إذا كانت هندسة المستند غير معتادة، فحددوا `column_tolerance`.
استخدام النتيجة المرتبة في مسار المستندات
يعرض `columns` كل عمود مكتشف وكتله المرتبة، بينما يسطح `reading_order` الأعمدة إلى التسلسل الدقيق الذي ينبغي أن تستهلكه الخطوة التالية. يجمع `text` نصوص الكتل بفاصل قابل للضبط؛ والفاصل الافتراضي سطر فارغ يحافظ على حدود الفقرات. صنفوا هذه البنى مسبقاً عند الحاجة، أو اضبطوا `column_tolerance` وراجعوا تعيينات الأعمدة المعادة.
أسئلة تقنية
ماذا يحدث إذا لم تُرسل أي كتل؟
يفشل الطلب بخطأ `invalid_input`، إذ لا يمكن استنتاج ترتيب القراءة من دون كتل نصية.
أي نظام إحداثيات ينبغي استخدامه؟
يصلح أي نظام متسق للصفحة، بشرط أن يمثل `x` الحافة اليسرى و`y` الحافة العليا لكل كتلة.