إنشاء بنية فصول EPUB من إشارات PDF المرجعية
يحتاج ملف EPUB الجيد إلى ترتيب قراءة واضح، لكن ملف PDF قد يعبّر عن هذا الترتيب فقط من خلال مخطط الإشارات المرجعية.
شغّل الأداة مجانًا
تستقبل هذه الإمكانية قائمة إشارات مستخرجة من PDF وتحول كل إشارة من المستوى الأعلى إلى فصل في EPUB. وهي تحافظ على ترتيب الإشارات وعناوينها، وتعيّن أسماء XHTML ثابتة، وتنقل صفحات الوجهة عند توفرها. تبقى الإشارات المتداخلة معلومات خاصة بالأقسام ولا تتحول خطأً إلى فصول مستقلة. وإذا لم يتضمن المصدر إشارات من المستوى الأعلى، تفشل الطلبية برسالة واضحة بدل اختلاق بنية لم يقدمها المستند.
جهّز مخطط الإشارات المرجعية
ابدأ بمخطط الإشارات الذي أخرجه محلل PDF أو أداة فحص، لا بعناوين بارزة بصرياً منسوخة من محتوى الصفحات. قدّم السجلات بترتيب القراءة الأصلي. يحتاج كل سجل إلى عنوان ومستوى رقمي، ويعني المستوى 1 أنه إشارة عليا؛ أما صفحة الوجهة المرقمة بدءاً من 1 فهي اختيارية. يمكن لسجل من المستوى 2 أو أعمق أن يصف قسماً فرعياً أو ملحقاً أو شكلاً أو وجهة متداخلة أخرى. تُفحص هذه السجلات لأن البيانات المشوهة يجب ألا تمر بصمت، لكنها لا تُرفع إلى فصول EPUB. تُحذف المسافات من طرفي العنوان مع بقاء الإملاء وعلامات الترقيم وحالة الأحرف والمسافات الداخلية كما هي. ويجب أن تكون الصفحة، عند تقديمها، عدداً صحيحاً موجباً. يمنع هذا التمثيل الصريح التخمين من المسافة البادئة أو أسلوب الخط، ويجعل النتيجة قابلة للتكرار بين الأنظمة. كما يفصل استخراج PDF عن تخطيط النشر ضمن سير العمل.
افهم قائمة الفصول الناتجة
تحتوي النتيجة على عدد الفصول ومصفوفة مرتبة منها. يحصل كل فصل على فهرس يبدأ من 1، وعنوان منقح مأخوذ من الإشارة العليا المقابلة، واسم ثابت مثل chapter-001.xhtml. تعتمد الأسماء على الموضع لا العنوان، ولذلك لا تسبب علامات الترقيم أو العناوين المكررة أو النصوص غير اللاتينية أو قواعد slug اللاحقة أي تعارض. إذا تضمنت الإشارة العليا صفحة وجهة، يضاف source_page إلى الفصل؛ وإذا لم تُقدّم صفحة، يُحذف هذا الحقل الاختياري بدلاً من ضبطه على null. لا تستخرج الإمكانية نص الصفحات، ولا تقسّم PDF، ولا تكتب XHTML، ولا تنشئ مستند تنقل EPUB. بل تقدم بنية وسيطة نظيفة يستطيع الكود اللاحق استخدامها لتسمية الملفات، وإسناد المحتوى المستخرج، وإنشاء عناصر spine وروابط التنقل. يطابق العدد دائماً عدد سجلات المستوى 1 لأن الإشارات المتداخلة لا تصبح فصولاً.
تعامل مع المخططات الغائبة أو الناقصة
قد يعرض ملف PDF صفحاته بصورة سليمة مع أنه لا يحتوي على إشارات صالحة للاستخدام. عندئذ لا توجد دلالة موثوقة على الفصول العليا، لذلك تعيد الإمكانية خطأ إدخال غير صالح بدلاً من استنتاج الفصول من أرقام الصفحات أو أحجام الخطوط أو أنماط النص. هذا مهم في التحويل الآلي، لأن القائمة المختلقة قد تبدو معقولة لكنها تربط المحتوى بعنوان خاطئ أو تسطح تسلسلاً هرمياً مقصوداً. وإذا كان المخطط موجوداً لكن كل إشاراته أعمق من المستوى 1، يظهر الخطأ نفسه لتعذر تحديد حدود الفصول العليا. صحح الاستخراج السابق أو أضف مخططاً مقصوداً قبل إعادة المحاولة. وتنتج السجلات المشوهة الأخرى رسائل محددة للموقع، ومنها العناوين الفارغة والمستويات غير الصالحة والصفحات غير الموجبة. تمر الخوارزمية مرة واحدة على 10,000 سجل كحد أقصى، بلا شبكة أو اعتماد على الوقت. لذلك يعطي الإدخال نفسه الفهارس والأسماء نفسها مقابل $0.002 لكل طلب.
حالات الاستخدام
خطط لتحويل EPUB
حوّل مخطط PDF المستخرج إلى بيان فصول يستطيع مسار المعالجة ملأه بمحتوى XHTML.
راجع تنقل المستند
قارن عدد فصول EPUB المقصودة وترتيبها بالإشارات العليا في PDF قبل النشر.
أنشئ أسماء فصول ثابتة
عيّن أسماء XHTML موضعية بلا تعارض حتى مع تكرار العناوين أو وجود ترقيم وأحرف غير لاتينية.
الأسئلة الشائعة
ما التكلفة؟
سعر API هو $0.002 لكل طلب، ويمكن تشغيل التحويل الحتمي نفسه داخل المتصفح.
هل تقرأ هذه الإمكانية ملف PDF نفسه؟
لا. فهي تستقبل مخطط الإشارات المستخرج مسبقاً من PDF وتحوله إلى قائمة فصول.
ما الذي يُعد فصلاً؟
تتحول كل إشارة مستواها 1 بالضبط إلى فصل واحد وفق ترتيب الإدخال نفسه.
ماذا يحدث للإشارات المتداخلة؟
تُفحص ولا تُخرج كفصول، ويمكن لاحقاً التعامل معها كأقسام داخل الفصل الأعلى.
ماذا لو خلا PDF من الإشارات العليا؟
يعيد الطلب خطأ إدخال غير صالح لأن الإمكانية لا تختلق حدوداً للفصول.
هل صفحات الوجهة إلزامية؟
لا. تتحول الصفحة الموجودة إلى source_page، وإلا يُحذف الحقل الاختياري.
للمطوّرين — الوصول عبر API
كل ما في هذه الصفحة متاح برمجيًا. هذا القسم موجّه للفرق التقنية التي تريد ربط الأداة بأنظمتها الخاصة؛ بقية المستخدمين يمكنهم استخدام الأداة أعلاه مباشرة دون الحاجة لقراءة ما يلي.
الـEndpoint
صادِق على طلبك بترويسة Bearer، وأرسل طلب POST واحدًا لتدخل مهمتك قائمة التنفيذ فورًا؛ ثم تستلم النتيجة عبر webhook أو رابط موقّع.
استدعِ الخدمة من بيئتك
curl -X POST https://api.kit.forhosting.com/pdf/to-epub-structure \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"outline":[{"title":"Introduction","level":1,"page":1},{"title":"Background","level":2,"page":3},{"title":"Methods","level":1,"page":12}]}'const res = await fetch("https://api.kit.forhosting.com/pdf/to-epub-structure", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"outline": [
{
"title": "Introduction",
"level": 1,
"page": 1
},
{
"title": "Background",
"level": 2,
"page": 3
},
{
"title": "Methods",
"level": 1,
"page": 12
}
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/pdf/to-epub-structure",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"outline": [
{
"title": "Introduction",
"level": 1,
"page": 1
},
{
"title": "Background",
"level": 2,
"page": 3
},
{
"title": "Methods",
"level": 1,
"page": 12
}
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/pdf/to-epub-structure", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"outline":[{"title":"Introduction","level":1,"page":1},{"title":"Background","level":2,"page":3},{"title":"Methods","level":1,"page":12}]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"outline":[{"title":"Introduction","level":1,"page":1},{"title":"Background","level":2,"page":3},{"title":"Methods","level":1,"page":12}]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/pdf/to-epub-structure", 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",
"level": 1,
"page": 1
},
{
"title": "Background",
"level": 2,
"page": 3
},
{
"title": "Methods",
"level": 1,
"page": 12
}
]
}مثال على الاستجابة
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "pdf.to_epub_structure",
"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 | تجاوزت الحد المسموح من الطلبات؛ انتظر قليلًا ثم أعد المحاولة. |