اعرض علامات PDF مع الصفحات والمستويات
حوّل شجرة المخطط التفصيلي لملف PDF إلى قائمة علامات مرجعية واضحة ومرتبة يسهل فحصها واختبارها وتصديرها وإدخالها في سير عمل آخر.
شغّل الأداة مجانًا
تعمل هذه الأداة داخل متصفحك — مجانًا، ولا تُرسل بياناتك إلى أي خادم
يحتوي كل عنصر على عنوان العلامة ومستوى التداخل الذي يبدأ من 1 وصفحة الوجهة التي يبدأ ترقيمها كذلك من 1. يحافظ الاجتياز على ترتيب المخطط الأصلي ويضع كل عنصر فرعي بعد العنصر الأب مباشرة. تُرفض المخططات الفارغة بوضوح، ولذلك لا يمكن الخلط بين غياب جدول المحتويات وبين نتيجة ناجحة لا تحتوي على بيانات.
حوّل المخطط المتداخل إلى صفوف عملية
تُمثّل علامات PDF عادةً في شجرة مخطط تفصيلي. تقع الفصول في المستوى الأعلى، وتظهر الأقسام تحتها، وقد تستمر العناوين الفرعية في مستويات أعمق. تناسب هذه البنية قارئ PDF، لكنها تصبح غير عملية عند تدقيق التنقل أو إعداد تقرير أو مقارنة إصدارين أو إرسال المعلومات إلى جدول بيانات. تجتاز هذه الإمكانية الشجرة بالترتيب السابق: تعرض العنصر الأب أولًا، ثم جميع فروعه بالترتيب الأصلي، وبعد ذلك تنتقل إلى العنصر الشقيق التالي. يتضمن كل صف البيانات اللازمة لجرد العلامات، وهي العنوان والمستوى وصفحة الوجهة. يبدأ ترقيم المستويات والصفحات من 1. وهكذا تحافظ القائمة على ترتيب القراءة الظاهر مع إزالة التداخل التكراري. لا تفتح الإمكانية ملف PDF ولا تعدّله؛ بل تستقبل شجرة المخطط التي استخرجها مسبقًا محلل PDF أو خطوة سابقة لمعالجة المستند.
افهم التحقق والترتيب الحتمي
يجب أن تكون كل علامة كائنًا له عنوان غير فارغ وصفحة يمثّلها عدد صحيح موجب. وإذا وُجدت عناصر فرعية، فيجب أن تكون مصفوفة من كائنات علامات أخرى. تُحذف المسافات الزائدة من طرفي العنوان، مع الحفاظ على النص الداخلي كما هو. لا ترتب الخوارزمية العلامات أبجديًا أو بحسب الصفحة، لأن ذلك قد يغيّر الترتيب الذي قصده المؤلف. إنها تتبع التسلسل المستلم وتحسب المستوى من عمق العنصر في الشجرة. لذلك تنتج المدخلات نفسها المخرجات نفسها دائمًا من دون شبكة أو وقت أو معرّفات عشوائية أو سلوك يعتمد على البيئة. ينتج عن المخطط الأعلى الفارغ خطأ إدخال غير صالح، وبذلك يستطيع سير العمل التوقف عند غياب العلامات بدل نشر فهرس فارغ يبدو صحيحًا. كما تُرفض العناصر الفرعية غير السليمة والعناوين المفقودة والصفحات الباطلة والعمق المفرط والحلقات والأشجار الكبيرة جدًا برسائل واضحة.
استخدم القائمة في مسارات معالجة المستندات
توفر قائمة العلامات المسطحة حدًا واضحًا بين تحليل PDF ومنطق العمل اللاحق. يمكنكم عرضها كجدول محتويات، أو التأكد من وجود جميع الفصول المتوقعة، أو مقارنة العناوين والوجهات بين إصدارات المستند، أو ربط الصفحات بأسماء الأقسام لاستخراج المحتوى لاحقًا. تتضمن الاستجابة العدد الإجمالي والسجلات المرتبة، ولذلك يستطيع النظام التحقق من العدد قبل معالجة العناصر الفردية. تتيح قيمة المستوى إعادة إنشاء المسافة البادئة أو بناء الشجرة من جديد، بينما تفيد قيمة الصفحة في التنقل وحساب النطاقات. تذكّروا أن الإمكانية تعرض المخطط الذي تستلمه فقط؛ فهي لا تتحقق من وجود صفحات الوجهة في ملف بعينه، ولا تستنتج العناوين من النص، ولا تصلح الروابط المعطلة. تحقّقوا من الحدود على نحو منفصل عندما يقدم المحلل عدد الصفحات. يتوفر التنفيذ التفاعلي مجانًا في المتصفح، وتبلغ تكلفة طلب API الآلي $0.002، ويستخدم المساران التنفيذ الحتمي نفسه.
حالات الاستخدام
دققوا تنقل المستند
راجعوا كل علامة بترتيب ظهورها واكتشفوا الفصول المفقودة أو التداخل غير المتوقع أو الوجهات الخاطئة قبل النشر.
أنشئوا جدول محتويات
حوّلوا ناتج المحلل إلى صفوف يمكن إزاحتها حسب المستوى وربطها بصفحات الوجهة.
قارنوا إصدارات PDF
أنشئوا قوائم ثابتة لإصدارين وقارنوا العناوين والتسلسل الهرمي والترتيب وصفحات الوجهة.
الأسئلة الشائعة
هل تقرأ هذه الإمكانية ملف PDF نفسه؟
لا. إنها تستقبل شجرة مخطط أنشأها محلل PDF وتحولها إلى سجلات علامات مرجعية.
ما الترتيب المستخدم في النتيجة؟
يُستخدم الترتيب السابق؛ فيظهر كل عنصر أب قبل فروعه، وتحافظ العناصر الشقيقة على ترتيب المستند المستلم.
كيف تُرقّم مستويات العلامات؟
تحمل العلامات العليا المستوى 1، وتحمل فروعها المستوى 2، وتضيف كل طبقة متداخلة مستوى واحدًا.
ماذا يحدث عندما يكون المخطط فارغًا؟
يفشل الطلب بخطأ إدخال غير صالح حتى لا يُفهم غياب العلامات على أنه تقرير فارغ صحيح.
هل تتحقق الإمكانية من وجود صفحات الوجهة؟
تشترط أن تكون كل وجهة عددًا صحيحًا موجبًا، لكن مقارنتها بعدد صفحات الملف تتطلب تحققًا منفصلًا.
ما تكلفة طلب API؟
تبلغ تكلفة طلب API مقدار $0.002. ويمكنكم أيضًا تشغيل المنطق الحتمي نفسه مجانًا في المتصفح.
للمطوّرين — الوصول عبر API
كل ما في هذه الصفحة متاح برمجيًا. هذا القسم موجّه للفرق التقنية التي تريد ربط الأداة بأنظمتها الخاصة؛ بقية المستخدمين يمكنهم استخدام الأداة أعلاه مباشرة دون الحاجة لقراءة ما يلي.
الـEndpoint
صادِق على طلبك بترويسة Bearer، وأرسل طلب POST واحدًا لتدخل مهمتك قائمة التنفيذ فورًا؛ ثم تستلم النتيجة عبر webhook أو رابط موقّع.
استدعِ الخدمة من بيئتك
curl -X POST https://api.kit.forhosting.com/pdf/bookmarks-list \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"outline":[{"title":"Introduction","page":1,"children":[{"title":"Background","page":3}]},{"title":"Methods","page":8}]}'const res = await fetch("https://api.kit.forhosting.com/pdf/bookmarks-list", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"outline": [
{
"title": "Introduction",
"page": 1,
"children": [
{
"title": "Background",
"page": 3
}
]
},
{
"title": "Methods",
"page": 8
}
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/pdf/bookmarks-list",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"outline": [
{
"title": "Introduction",
"page": 1,
"children": [
{
"title": "Background",
"page": 3
}
]
},
{
"title": "Methods",
"page": 8
}
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/pdf/bookmarks-list", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"outline":[{"title":"Introduction","page":1,"children":[{"title":"Background","page":3}]},{"title":"Methods","page":8}]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"outline":[{"title":"Introduction","page":1,"children":[{"title":"Background","page":3}]},{"title":"Methods","page":8}]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/pdf/bookmarks-list", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)مثال على الطلب
{
"outline": [
{
"title": "Introduction",
"page": 1,
"children": [
{
"title": "Background",
"page": 3
}
]
},
{
"title": "Methods",
"page": 8
}
]
}مثال على الاستجابة
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "pdf.bookmarks_list",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}الواجهة غير متزامنة: تستلم task_id فور الإرسال، ويمكنك الاستعلام عن الحالة بمعدل طلب واحد في الثانية.
الأسعار
السعر معلن كما تراه: لا tokens ولا نظام نقاط؛ وإن فشلت المهمة فلن تُحاسَب عليها.
الحدود
max_mb | 25 |
max_pages | 200 |
الأخطاء
| HTTP | الرمز | المعنى |
|---|---|---|
401 | unauthorized | مفتاح الوصول مفقود أو غير صالح؛ تحقق من ترويسة Bearer في طلبك. |
402 | insufficient_balance | رصيدك لا يكفي لتنفيذ هذه المهمة؛ أعد شحن الرصيد ثم أعد المحاولة. |
404 | unknown_type | نوع المهمة المطلوب غير موجود في الكتالوج — راجع الاسم المرسل في الطلب. |
429 | rate_limited | تجاوزت الحد المسموح من الطلبات؛ انتظر قليلًا ثم أعد المحاولة. |