تحويل HTML إلى Markdown باستخدام Python: دليل شامل

بايثون لتحويل HTML إلى ماركداون نظيف ومُعدّ لمحركات التعلم العميق

Page content

تحويل HTML إلى Markdown هو مهمة أساسية في تدفقات العمل الحديثة، خاصة عند إعداد محتوى الويب للنماذج اللغوية الكبيرة (LLMs)، ونظامي الوثائق أو المولّدات الثابتة مثل Hugo.

بينما تم تصميم HTML للاستخدام في متصفحات الويب مع تصميم غني وبنية، فإن Markdown يوفر تنسيقًا نظيفًا وقابلًا للقراءة، وهو مثالي لمعالجة النصوص، والتحكم في الإصدارات، والاستهلاك من قبل الذكاء الاصطناعي. إذا كنت تبدأ في استخدام ترميز Markdown، فراجع دليل Markdown لدينا للحصول على مرجعي شامل.

رسم توضيحي: تحويل صفحة من HTML إلى Markdown

في هذا المراجعة الشاملة، سنستعرض ستة حزم Python لتحويل HTML إلى Markdown، مع أمثلة عملية على الكود، ونتائج معايير الأداء، وحالات استخدام واقعية. سواء كنت تبني أنبوبًا تدريبيًا لنموذج لغوي كبير، أو تقوم بتحويل مدونة إلى Hugo، أو تقوم بتنقيب الوثائق، فسوف تجد الأداة المثالية لتدفق عملك.

نهج بديل: إذا كنت بحاجة إلى استخراج محتوى ذكي مع فهم دلالي، فقد ترغب أيضًا في النظر في تحويل HTML إلى Markdown باستخدام LLM وOllama، والذي يقدم تحويلًا مدعومًا بالذكاء الاصطناعي للهياكل المعقدة.

ما ستتعلمه:

  • مقارنة تفصيلية لـ 6 مكتبات مع مزايا وعيوب لكل منها
  • معايير أداء باستخدام عينات HTML واقعية
  • أمثلة كود جاهزة لحالات الاستخدام الشائعة
  • أفضل الممارسات لتدفقات عمل معالجة LLM
  • توصيات محددة بناءً على متطلباتك

لماذا Markdown لمعالجة LLM؟

قبل الغوص في الأدوات، دعنا نفهم لماذا Markdown مفيد بشكل خاص لتدفقات عمل LLM:

  1. كفاءة الرموز: يستخدم Markdown عددًا أقل بكثير من الرموز مقارنةً بـ HTML لنفس المحتوى
  2. الوضوح الدلالي: يحتفظ Markdown ببنية المستند دون استخدام علامات مفرطة
  3. القراءة: يمكن للبشر والـ LLMs تحليل ترميز Markdown بسهولة
  4. التوافق: يقلل التنسيق المعياري من الغموض في إدخالات النموذج
  5. التخزين: أحجام ملفات أصغر للبيانات التدريبية ونافذة السياق

تتنوع مرونة Markdown عن تطبيقات تحويل HTML، يمكنك أيضًا تحويل مستندات Word إلى Markdown لتدفقات عمل الوثائق، أو استخدامه في أنظمة إدارة المعرفة مثل Obsidian لإدارة المعرفة الشخصية.

TL;DR - جدول المقارنة السريع

إذا كنت مسرعًا، إليك مقارنة شاملة لجميع المكتبات في نظرة واحدة. سيساعدك هذا الجدول على تحديد الأداة التي تتناسب مع متطلباتك بسرعة:

الميزة html2text markdownify html-to-markdown trafilatura domscribe html2md
دعم HTML5 جزئي جزئي كامل كامل كامل كامل
العلامات النمطية لا لا نعم جزئي لا جزئي
التعاملات المخصصة محدود ممتاز جيد محدود جيد محدود
دعم الجداول أساسي أساسي متقدم جيد جيد جيد
الدعم غير المتزامن لا لا لا لا لا نعم
استخراج المحتوى لا لا لا ممتاز لا جيد
استخراج البيانات لا لا نعم ممتاز لا نعم
أداة سطر الأوامر لا لا نعم نعم لا نعم
السرعة متوسطة بطيئة سريعة 매우 سريعة متوسطة 매우 سريعة
التطوير النشط لا نعم نعم نعم محدود نعم
نسخة Python 3.6+ 3.7+ 3.9+ 3.6+ 3.8+ 3.10+
الاعتماديات لا شيء BS4 lxml lxml BS4 aiohttp

دليل الاختيار السريع:

  • تحتاج إلى السرعة؟ → trafilatura أو html2md
  • تحتاج إلى التخصيص؟ → markdownify
  • تحتاج إلى الأمان النمطي؟ → html-to-markdown
  • تحتاج إلى البساطة؟ → html2text
  • تحتاج إلى استخراج المحتوى؟ → trafilatura

المتنافسون: مقارنة 6 حزم Python

لنغوص في كل مكتبة مع أمثلة كود عملية، خيارات التكوين، والرؤى الواقعية. يحتوي كل قسم على تعليمات التثبيت، أنماط الاستخدام، وتقييم صادق للمزايا والقيود.

1. html2text - الخيار الكلاسيكي

تم تطوير html2text في الأصل من قبل أaron Swartz، وهو عنصر أساسي في بيئة Python منذ أكثر من عقد. يركز على إنتاج إخراج Markdown نظيف وقابل للقراءة.

التركيب:

pip install html2text

الاستخدام الأساسي:

import html2text

# إنشاء مثيل المحوّل
h = html2text.HTML2Text()

# تكوين الخيارات
h.ignore_links = False
h.ignore_images = False
h.ignore_emphasis = False
h.body_width = 0  # لا تلف السطور

html_content = """
<h1>مرحباً بكم في تجميع البيانات من الويب</h1>
<p>هذا هو دليل شامل لاستخراج المحتوى.</p>
<ul>
    <li>سهل الاستخدام</li>
    <li>تم اختباره</li>
    <li>مُعتمد على نطاق واسع</li>
</ul>
<a href="https://example.com">اعرف المزيد</a>
"""

markdown = h.handle(html_content)
print(markdown)

الناتج:

# مرحباً بكم في تجميع البيانات من الويب

هذا هو **دليل شامل** لاستخراج المحتوى.

  * سهل الاستخدام
  * تم اختباره
  * مُعتمد على نطاق واسع

[اعرف المزيد](https://example.com)

التكوين المتقدم:

import html2text

h = html2text.HTML2Text()

# تجاهل عناصر معينة
h.ignore_links = True
h.ignore_images = True

# التحكم في التنسيق
h.body_width = 80  # تلف عند 80 حرف
h.unicode_snob = True  # استخدام الأحرف الأونيكود
h.emphasis_mark = '*'  # استخدام * للإثارة بدل _ 
h.strong_mark = '**'

# التعامل مع الجداول
h.ignore_tables = False

# حماية النصوص المُعدة مسبقًا
h.protect_links = True

المزايا:

  • ناضج ومستقر (15+ سنة من التطوير)
  • خيارات تكوين واسعة
  • يتعامل جيدًا مع الحالات الحدية
  • لا تعتمد على أي اعتماديات خارجية

العيوب:

  • دعم HTML5 محدود
  • يمكن أن ينتج مسافات غير متسقة
  • لا يتم تطويره نشطًا (آخر تحديث رئيسي في عام 2020)
  • معالجة متزامنة فقط

الأفضل له: الوثائق HTML البسيطة، الأنظمة القديمة، عندما يكون الاستقرار أولوية


2. markdownify - الخيار المرن

يستخدم markdownify BeautifulSoup4 لتقديم تحليل HTML مرن مع التعاملات المخصصة للعناصر.

التركيب:

pip install markdownify

الاستخدام الأساسي:

from markdownify import markdownify as md

html = """
<article>
    <h2>تطوير الويب الحديث</h2>
    <p>بناء باستخدام <code>Python</code> و <em>الإطارات الحديثة</em>.</p>
    <blockquote>
        <p>البساطة هي أقصى درجة من التطور.</p>
    </blockquote>
</article>
"""

markdown = md(html)
print(markdown)

الناتج:


## تطوير الويب الحديث

بناء باستخدام `Python` و *الإطارات الحديثة*.

> البساطة هي أقصى درجة من التطور.

الاستخدام المتقدم مع التعاملات المخصصة:

from markdownify import MarkdownConverter

class CustomConverter(MarkdownConverter):
    """
    إنشاء محوّل مخصص مع التعاملات الخاصة بالعناصر
    """
    def convert_img(self, el, text, convert_as_inline):
        """التعامل المخصص مع الصور مع نص البديل"""
        alt = el.get('alt', '')
        src = el.get('src', '')
        title = el.get('title', '')

        if title:
            return f'![{alt}]({src} "{title}")'
        return f'![{alt}]({src})'

    def convert_pre(self, el, text, convert_as_inline):
        """التعامل المحسن مع كتل الكود مع اكتشاف اللغة"""
        code = el.find('code')
        if code:
            # استخراج اللغة من سمة الفئة (مثلاً 'language-python')
            classes = code.get('class', [''])
            language = classes[0].replace('language-', '') if classes else ''
            return f'\n```{language}\n{code.get_text()}\n```\n'
        return f'\n```\n{text}\n```\n'

# استخدام المحوّل المخصص
html = '<pre><code class="language-python">def hello():\n    print("world")</code></pre>'
markdown = CustomConverter().convert(html)
print(markdown)

للمزيد من التفاصيل حول التعامل مع كتل الكود في Markdown والتوظيف، راجع دليلنا حول استخدام كتل الكود في Markdown.

التحويل المحدد للعناصر:

from markdownify import markdownify as md

# إزالة عناصر معينة تمامًا
markdown = md(html, strip=['script', 'style', 'nav'])

# تحويل عناصر معينة فقط
markdown = md(
    html,
    heading_style="ATX",  # استخدام # للعناوين
    bullets="-",  # استخدام - للنقاط
    strong_em_symbol="*",  # استخدام * للإثارة
)

المزايا:

  • مبني على BeautifulSoup4 (تحليل HTML قوي)
  • قابل للتخصيص عبر التراث
  • تطوير نشط
  • وثائق جيدة

العيوب:

  • يتطلب اعتمادية BeautifulSoup4
  • يمكن أن يكون أبطأ لمستندات كبيرة
  • دعم الجداول المُعبَّأة محدود

الأفضل له: التحويل المخصص، المشاريع التي تستخدم BeautifulSoup4 بالفعل


3. html-to-markdown - القوة الحديثة

html-to-markdown هو مكتبة حديثة تمامًا، مُصنفة تمامًا، مع دعم شامل لـ HTML5 وخيارات تكوين واسعة.

التركيب:

pip install html-to-markdown

الاستخدام الأساسي:

from html_to_markdown import convert

html = """
<article>
    <h1>التوثيق التقني</h1>
    <table>
        <thead>
            <tr>
                <th>الميزة</th>
                <th>الدعم</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>HTML5</td>
                <td>✓</td>
            </tr>
            <tr>
                <td>الجداول</td>
                <td>✓</td>
            </tr>
        </tbody>
    </table>
</article>
"""

markdown = convert(html)
print(markdown)

التكوين المتقدم:

from html_to_markdown import convert, Options

# إنشاء خيارات مخصصة
options = Options(
    heading_style="ATX",
    bullet_style="-",
    code_language_default="python",
    strip_tags=["script", "style"],
    escape_special_chars=True,
    table_style="pipe",  # استخدام | للجداول
    preserve_whitespace=False,
    extract_metadata=True,  # استخراج علامات التبويب
)

markdown = convert(html, options=options)

واجهة سطر الأوامر:

# تحويل ملف واحد
html-to-markdown input.html -o output.md

# تحويل مع خيارات
html-to-markdown input.html \
    --heading-style atx \
    --strip-tags script,style \
    --extract-metadata

# تحويل دفعة
find ./html_files -name "*.html" -exec html-to-markdown {} -o ./markdown_files/{}.md \;

المزايا:

  • دعم كامل لـ HTML5 بما في ذلك العناصر الدلالية
  • مصنفة تمامًا مع مؤشرات نوعية شاملة
  • معالجة الجداول المحسنة (الخلايا المدمجة، الترتيب)
  • قدرات استخراج البيانات
  • تطوير نشط وقاعدة كود حديثة

العيوب:

  • يتطلب Python 3.9+
  • حجم اعتماديات أكبر
  • منحنى تعلم أصعب

الأفضل له: الوثائق HTML5 المعقدة، المشاريع المصنفة تمامًا، الأنظمة الإنتاجية


4. trafilatura - خبير استخراج المحتوى

trafilatura ليس مجرد محوّل HTML إلى Markdown، بل هو مكتبة ذكية لاستخراج المحتوى مصممة خصيصًا لاستخراج المقالات والتنقيب عن الويب.

التركيب:

pip install trafilatura

الاستخدام الأساسي:

import trafilatura

# تنزيل واستخراج من عنوان URL
url = "https://example.com/article"
downloaded = trafilatura.fetch_url(url)
markdown = trafilatura.extract(downloaded, output_format='markdown')
print(markdown)

ملاحظة: تحتوي trafilatura على تنزيل مدمج من URL، ولكن عند التعامل مع عمليات HTTP معقدة، قد تجد دليلنا حول cURL مفيدًا عند العمل مع واجهات برمجة التطبيقات أو نقاط النهاية المصادقة.

استخراج المحتوى المتقدم:

import trafilatura
from trafilatura.settings import use_config

# إنشاء تكوين مخصص
config = use_config()
config.set("DEFAULT", "EXTRACTION_TIMEOUT", "30")

html = """
<html>
<head><title>عنوان المقالة</title></head>
<body>
    <nav>قائمة التنقل</nav>
    <article>
        <h1>المقالة الرئيسية</h1>
        <p>المحتوى المهم هنا.</p>
    </article>
    <aside>إعلان</aside>
    <footer>محتوى التذييل</footer>
</body>
</html>
"""

# استخراج المحتوى الرئيسي فقط
markdown = trafilatura.extract(
    html,
    output_format='markdown',
    include_comments=False,
    include_tables=True,
    include_images=True,
    include_links=True,
    config=config
)

# استخراج مع البيانات
result = trafilatura.extract(
    html,
    output_format='markdown',
    with_metadata=True
)

if result:
    print(f"العنوان: {result.get('title', 'غير متوفر')}")
    print(f"المؤلف: {result.get('author', 'غير متوفر')}")
    print(f"التاريخ: {result.get('date', 'غير متوفر')}")
    print(f"\nالمحتوى:\n{result.get('text', '')}")

المعالجة بالدفعة:

import trafilatura
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path

def process_url(url):
    """استخراج Markdown من عنوان URL"""
    downloaded = trafilatura.fetch_url(url)
    if downloaded:
        return trafilatura.extract(
            downloaded,
            output_format='markdown',
            include_links=True,
            include_images=True
        )
    return None

# معالجة عدة عناوين في وقت واحد
urls = [
    "https://example.com/article1",
    "https://example.com/article2",
    "https://example.com/article3",
]

with ThreadPoolExecutor(max_workers=5) as executor:
    results = list(executor.map(process_url, urls))

for i, markdown in enumerate(results):
    if markdown:
        Path(f"article_{i}.md").write_text(markdown, encoding='utf-8')

المزايا:

  • استخراج محتوى ذكي (إزالة المحتوى غير الضروري)
  • تنزيل مدمج مع معالجة أخطاء قوية
  • استخراج البيانات (العنوان، المؤلف، التاريخ)
  • اكتشاف اللغة
  • محسّن لاستخراج المقالات والمنشورات
  • معالجة سريعة مبنية على C

العيوب:

  • قد يزيل الكثير من المحتوى لـ HTML العام
  • مركّز على استخراج المقالات (ليس عامًا)
  • تعقيد التكوين للحالات الحدية

الأفضل له: التنقيب عن الويب، استخراج المقالات، إعداد بيانات تدريب LLM


5. domscribe - الحافظ على المعنى الدلالي

يركز domscribe على الحفاظ على المعنى الدلالي لـ HTML أثناء تحويله إلى Markdown.

التركيب:

pip install domscribe

الاستخدام الأساسي:

from domscribe import html_to_markdown

html = """
<article>
    <header>
        <h1>فهم HTML الدلالي</h1>
        <time datetime="2024-10-24">24 أكتوبر 2024</time>
    </header>
    <section>
        <h2>مقدمة</h2>
        <p>HTML الدلالي يوفر <mark>معنى</mark> للمحتوى.</p>
    </section>
    <aside>
        <h3>المواضيع المرتبطة</h3>
        <ul>
            <li>الوصول الشامل</li>
            <li>البحث في محركات البحث</li>
        </ul>
    </aside>
</article>
"""

markdown = html_to_markdown(html)
print(markdown)

خيارات مخصصة:

from domscribe import html_to_markdown, MarkdownOptions

options = MarkdownOptions(
    preserve_semantic_structure=True,
    include_aria_labels=True,
    strip_empty_elements=True
)

markdown = html_to_markdown(html, options=options)

المزايا:

  • الحفاظ على بنية HTML5 الدلالية
  • التعامل الجيد مع مكونات الويب الحديثة
  • تصميم واجهة برمجة نظيف

العيوب:

  • لا يزال في مراحل التطوير المبكرة (قد تتغير واجهة برمجة التطبيقات)
  • وثائق محدودة مقارنة بالبدائل الناضجة
  • مجتمع أصغر وعدد أقل من الأمثلة المتاحة

الأفضل له: الوثائق HTML5 الدلالية، المشاريع المركزة على الوصول الشامل، عندما يكون الحفاظ على بنية HTML5 الدلالية أمرًا حيويًا

ملاحظة: على الرغم من أن domscribe أحدث من البديل، إلا أنه يملأ فجوة معينة لحفظ HTML الدلالي التي لا تركز عليها الأدوات الأخرى.


6. html2md - القوة غير المتزامنة

تم تصميم html2md للتحويلات عالية الأداء بالجملة مع المعالجة غير المتزامنة.

التركيب:

pip install html2md

الاستخدام من سطر الأوامر:

# تحويل دليل كامل
m1f-html2md convert ./website -o ./docs

# مع إعدادات مخصصة
m1f-html2md convert ./website -o ./docs \
    --remove-tags nav,footer \
    --heading-offset 1 \
    --detect-language

# تحويل ملف واحد
m1f-html2md convert index.html -o readme.md

الاستخدام البرمجي:

import asyncio
from html2md import convert_html

async def convert_files():
    """تحويل جماعي غير متزامن"""
    html_files = [
        'page1.html',
        'page2.html',
        'page3.html'
    ]

    tasks = [convert_html(file) for file in html_files]
    results = await asyncio.gather(*tasks)
    return results

# تشغيل التحويل
results = asyncio.run(convert_files())

المزايا:

  • معالجة غير متزامنة للاستفادة من الأداء العالي
  • اكتشاف محدد للمحتوى
  • إنشاء YAML frontmatter (مثالي لـ Hugo!)
  • اكتشاف لغة الكود
  • دعم المعالجة المتزامنة

العيوب:

  • يتطلب Python 3.10+
  • مركّز على سطر الأوامر (أقل مرونة في واجهة برمجة التطبيقات)
  • يمكن أن تكون الوثائق أكثر شمولًا

الأفضل له: المهاجرات الكبيرة، التحويلات بالجملة، المهاجرات من Hugo/Jekyll


معايير الأداء

الأداء مهم، خاصة عند معالجة آلاف المستندات لتدريب LLM أو المهاجرات الكبيرة. تساعد فهم الفروقات في السرعة بين المكتبات في اتخاذ قرارات مبنية على المعرفة لتدفق عملك.

تحليل الأداء المقارن:

بناءً على الأنماط النموذجية للاستخدام، إليك كيف تقارن هذه المكتبات عبر ثلاث حالات واقعية:

  1. HTML بسيط: منشور مدونة بسيط مع نصوص، عناوين، وروابط (5KB)
  2. HTML معقد: وثائق تقنية مع جداول مدمجة وكتل كود (50KB)
  3. موقع ويب كامل: صفحة ويب كاملة تشمل التنقل، التذييل، الجانبي، والإعلانات (200KB)

إليك مثال على كود المعايير الذي يمكنك استخدامه لاختبار هذه المكتبات بنفسك:

import time
import html2text
from markdownify import markdownify
from html_to_markdown import convert
import trafilatura

def benchmark(html_content, iterations=100):
    """معايرة سرعة التحويل"""

    # html2text
    start = time.time()
    h = html2text.HTML2Text()
    for _ in range(iterations):
        _ = h.handle(html_content)
    html2text_time = time.time() - start

    # markdownify
    start = time.time()
    for _ in range(iterations):
        _ = markdownify(html_content)
    markdownify_time = time.time() - start

    # html-to-markdown
    start = time.time()
    for _ in range(iterations):
        _ = convert(html_content)
    html_to_markdown_time = time.time() - start

    # trafilatura
    start = time.time()
    for _ in range(iterations):
        _ = trafilatura.extract(html_content, output_format='markdown')
    trafilatura_time = time.time() - start

    return {
        'html2text': html2text_time,
        'markdownify': markdownify_time,
        'html-to-markdown': html_to_markdown_time,
        'trafilatura': trafilatura_time
    }

الخصائص الأداء المعتادة (السرعات النسبية الممثلة):

الحزمة HTML بسيط (5KB) HTML معقد (50KB) موقع ويب كامل (200KB)
html2text معتدل أبطأ أبطأ
markdownify أبطأ أبطأ الأبطأ
html-to-markdown سريع سريع سريع
trafilatura سريع سريع جدًا سريع جدًا
html2md (غير متزامن) سريع جدًا سريع جدًا الأسرع

الملاحظات الرئيسية:

  • html2md و trafilatura هما الأسرع لمستندات معقدة، مما يجعلهما مثاليين للمعالجة بالجملة
  • html-to-markdown يقدم أفضل توازن بين السرعة والميزات للاستخدام الإنتاجي
  • markdownify أبطأ لكنه أكثر مرونة - تبادل مقبول عندما تحتاج إلى التعاملات المخصصة
  • html2text يظهر علامته مع الأبطأ، لكنه مستقر للاستخدامات البسيطة

ملاحظة: تصبح الفروقات في الأداء ملحوظة فقط عند معالجة مئات أو آلاف الملفات. لتحويلات نادرة، تعمل أي مكتبة بشكل جيد. ركّز على الميزات وخيارات التخصيص بدلًا من ذلك.

أمثلة استخدام حقيقية

النظرية مفيدة، ولكن الأمثلة العملية توضح كيف تعمل هذه الأدوات في الإنتاج. إليك أربعة حالات شائعة مع كود كامل جاهز للإنتاج يمكنك تكييفه لمشاريعك الخاصة.

حالة الاستخدام 1: إعداد بيانات تدريب نموذج LLM

المتطلبات: استخراج نص نظيف من آلاف صفحات الوثائق

الموصى به: trafilatura + معالجة متوازية

import trafilatura
from pathlib import Path
from concurrent.futures import ProcessPoolExecutor

def process_html_file(html_path):
    """تحويل ملف HTML إلى markdown"""
    html = Path(html_path).read_text(encoding='utf-8')
    markdown = trafilatura.extract(
        html,
        output_format='markdown',
        include_links=False,  # إزالة هذا للحصول على بيانات تدريب نظيفة
        include_images=False,
        include_comments=False
    )

    if markdown:
        output_path = html_path.replace('.html', '.md')
        Path(output_path).write_text(markdown, encoding='utf-8')
        return len(markdown)
    return 0

# معالجة 10,000 ملف في وقت واحد
html_files = list(Path('./docs').rglob('*.html'))

with ProcessPoolExecutor(max_workers=8) as executor:
    token_counts = list(executor.map(process_html_file, html_files))

print(f"تم معالجة {len(html_files)} ملف")
print(f"الحروف الإجمالية: {sum(token_counts):,}")

حالة الاستخدام 2: نقل مدونة Hugo

المتطلبات: نقل مدونة WordPress إلى Hugo مع frontmatter

الموصى به: html2md من الطرفية

Hugo هو مولّد مواقع ثابت شائع يستخدم Markdown للمحتوى. للمزيد من النصائح الخاصة بـ Hugo، تحقق من ورقة مساعدة Hugo وتعلم حول إضافة ترميز بيانات منظمة إلى Hugo لتحسين SEO.

# تحويل جميع المنشورات مع frontmatter
m1f-html2md convert ./wordpress-export \
    -o ./hugo/content/posts \
    --generate-frontmatter \
    --heading-offset 0 \
    --remove-tags script,style,nav,footer

أو بشكل برمجي:

from html_to_markdown import convert, Options
from pathlib import Path
import yaml

def migrate_post(html_file):
    """تحويل HTML من WordPress إلى markdown لـ Hugo"""
    html = Path(html_file).read_text()

    # استخراج العنوان والتاريخ من HTML
    from bs4 import BeautifulSoup
    soup = BeautifulSoup(html, 'html.parser')
    title = soup.find('h1').get_text() if soup.find('h1') else 'غير مسمى'

    # تحويل إلى markdown
    options = Options(strip_tags=['script', 'style', 'nav', 'footer'])
    markdown = convert(html, options=options)

    # إضافة frontmatter لـ Hugo
    frontmatter = {
        'title': title,
        'date': '2024-10-24',
        'draft': False,
        'tags': []
    }

    output = f"---\n{yaml.dump(frontmatter)}---\n\n{markdown}"

    # حفظ
    output_file = html_file.replace('.html', '.md')
    Path(output_file).write_text(output, encoding='utf-8')

# معالجة جميع المنشورات
for html_file in Path('./wordpress-export').glob('*.html'):
    migrate_post(html_file)

حالة الاستخدام 3: مُستخرج وثائق مع تخصيص التنسيق

المتطلبات: استخراج وثائق تقنية مع معالجة كتل الكود المخصصة

الموصى به: markdownify مع مُحول مخصص

هذه الطريقة مفيدة بشكل خاص لنقل الوثائق من أنظمة ويكي. إذا كنت تدير الوثائق، فقد تكون مهتمًا أيضًا بـ DokuWiki - ويكي مُستضاف ذاتيًا والبدائل لحلول وثائق مُستضافة ذاتيًا.

from markdownify import MarkdownConverter
import requests

class DocsConverter(MarkdownConverter):
    """مُحول مخصص لوثائق تقنية"""

    def convert_pre(self, el, text, convert_as_inline):
        """كُتل كود مُحسّنة مع تلوين لغة الكود"""
        code = el.find('code')
        if code:
            # استخراج لغة من الفئة
            classes = code.get('class', [])
            language = next(
                (c.replace('language-', '') for c in classes if c.startswith('language-')),
                'text'
            )
            return f'\n```{language}\n{code.get_text()}\n```\n'
        return super().convert_pre(el, text, convert_as_inline)

    def convert_div(self, el, text, convert_as_inline):
        """معالجة كتل وثائق خاصة"""
        classes = el.get('class', [])

        # كتل تحذير
        if 'warning' in classes:
            return f'\n> ⚠️ **تحذير**: {text}\n'

        # كتل معلومات
        if 'info' in classes or 'note' in classes:
            return f'\n> 💡 **ملاحظة**: {text}\n'

        return text

def scrape_docs(url):
    """استخراج وتحويل صفحة وثائق"""
    response = requests.get(url)
    markdown = DocsConverter().convert(response.text)
    return markdown

# استخدامه
docs_url = "https://docs.example.com/api-reference"
markdown = scrape_docs(docs_url)
Path('api-reference.md').write_text(markdown)

حالة الاستخدام 4: تحويل نشرات إخبارية إلى ملفات markdown

المتطلبات: تحويل نشرات إخبارية HTML إلى markdown قابلة للقراءة

الموصى به: html2text مع تكوين محدد

import html2text
import email
from pathlib import Path

def convert_newsletter(email_file):
    """تحويل نشرة إخبارية HTML إلى markdown"""
    # تحليل البريد
    with open(email_file, 'r') as f:
        msg = email.message_from_file(f)

    # الحصول على جزء HTML
    html_content = None
    for part in msg.walk():
        if part.get_content_type() == 'text/html':
            html_content = part.get_payload(decode=True).decode('utf-8')
            break

    if not html_content:
        return None

    # تكوين المُحول
    h = html2text.HTML2Text()
    h.ignore_images = False
    h.images_to_alt = True
    h.body_width = 0
    h.protect_links = True
    h.unicode_snob = True

    # تحويل
    markdown = h.handle(html_content)

    # إضافة البيانات
    subject = msg.get('Subject', 'لا يوجد عنوان')
    date = msg.get('Date', '')

    output = f"# {subject}\n\n*التاريخ: {date}*\n\n---\n\n{markdown}"

    return output

# معالجة أرشيف النشرات
for email_file in Path('./newsletters').glob('*.eml'):
    markdown = convert_newsletter(email_file)
    if markdown:
        output_file = email_file.with_suffix('.md')
        output_file.write_text(markdown, encoding='utf-8')

التوصيات حسب السيناريو

هل لا تزال غير متأكد من أي مكتبة يجب اختيارها؟ إليك دليلي النهائي بناءً على حالات الاستخدام المحددة. هذه التوصيات تأتي من خبرة عملية مع كل مكتبة في بيئات الإنتاج.

لتحويل الويب والتحضير المسبق لـ LLM

الفائز: trafilatura

Trafilatura يتفوق في استخراج المحتوى النظيف مع إزالة النصوص الثانوية. مثالي لـ:

  • بناء مجموعات بيانات تدريب LLM
  • تجميع المحتوى
  • جمع أوراق بحثية
  • استخراج مقالات الأخبار

لتحويلات Hugo/Jekyll

الفائز: html2md

المعالجة غير المتزامنة وتكوين frontmatter تجعل تحويلات المجموعات سريعة وسهلة:

  • تحويلات دفقة
  • استخراج تلقائي للمetadata
  • إنشاء frontmatter YAML
  • تعديل مستويات العناوين

لمنطق التحويل المخصص

الفائز: markdownify

تخصيص المُحول من خلال فرزه للاستحواذ الكامل:

  • مُعالجات عناصر مخصصة
  • تحويلات مخصصة حسب المجال
  • متطلبات التنسيق الخاصة
  • دمج مع الكود الحالي لـ BeautifulSoup

لأنظمة الإنتاج ذات النوع الآمن

الفائز: html-to-markdown

حديث، آمن من حيث النوع، وشامل في الميزات:

  • دعم كامل لـ HTML5
  • إرشادات نوعية شاملة
  • معالجة متقدمة للجداول
  • صيانة نشطة

لتحويلات بسيطة ومستقرة

الفائز: html2text

عندما تحتاج إلى شيء “يعمل”:

  • لا توجد اعتمادات
  • اختبارت ميدانية
  • تكوين واسع
  • دعم منصات واسع

أفضل الممارسات لتحويلات LLM

بلا مبالاة بمكتبة تختارها، اتباع هذه الممارسات الأفضل سيضمن إخراج Markdown عالي الجودة مُحسّن لاستهلاك LLM. هذه الأنماط أثبتت ضرورتها في عمليات معالجة الملايين من الوثائق.

1. تنظيف قبل التحويل

احذف العناصر غير المرغوب فيها قبل التحويل للحصول على إخراج نظيف وتحسين الأداء:

from bs4 import BeautifulSoup
import trafilatura

def clean_and_convert(html):
    """إزالة العناصر غير المرغوب فيها قبل التحويل"""
    soup = BeautifulSoup(html, 'html.parser')

    # إزالة العناصر غير المرغوب فيها
    for element in soup(['script', 'style', 'nav', 'footer', 'header', 'aside']):
        element.decompose()

    # إزالة الإعلانات والمتابعة
    for element in soup.find_all(class_=['ad', 'advertisement', 'tracking']):
        element.decompose()

    # تحويل HTML النظيف
    markdown = trafilatura.extract(
        str(soup),
        output_format='markdown'
    )

    return markdown

2. تسوية المسافات البيضاء

تختلف المُحولات في التعامل مع المسافات البيضاء. تسوية الإخراج لضمان الاتساق عبر مجموعتك:

import re

def normalize_markdown(markdown):
    """تنظيف مسافات markdown"""
    # إزالة المسافات البيضاء المتعددة
    markdown = re.sub(r'\n{3,}', '\n\n', markdown)

    # إزالة المسافات البيضاء الزائدة
    markdown = '\n'.join(line.rstrip() for line in markdown.split('\n'))

    # التأكد من وجود مسافة واحدة في النهاية
    markdown = markdown.rstrip() + '\n'

    return markdown

3. التحقق من الإخراج

التحكم في الجودة ضروري. تطبيق التحقق لالتقاط أخطاء التحويل مبكرًا:

def validate_markdown(markdown):
    """التحقق من جودة markdown"""
    issues = []

    # التحقق من وجود بقايا HTML
    if '<' in markdown and '>' in markdown:
        issues.append("تم اكتشاف علامات HTML")

    # التحقق من وجود روابط معطوبة
    if '[' in markdown and ']()' in markdown:
        issues.append("تم اكتشاف رابط فارغ")

    # التحقق من عدد كتل الكود
    code_block_count = markdown.count('```')
    if code_block_count % 2 != 0:
        issues.append("تم اكتشاف كتلة كود غير مغلقة")

    return len(issues) == 0, issues

4. نموذج معالجة دفقة

عند معالجة مجموعات وثائق كبيرة، استخدم هذا النموذج الجاهز للإنتاج مع معالجة الأخطاء، والتسجيل، ومعالجة متوازية:

from pathlib import Path
from concurrent.futures import ProcessPoolExecutor
import trafilatura
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def process_file(html_path):
    """معالجة ملف HTML واحد"""
    try:
        html = Path(html_path).read_text(encoding='utf-8')
        markdown = trafilatura.extract(
            html,
            output_format='markdown',
            include_links=True,
            include_images=False
        )

        if markdown:
            # تسوية
            markdown = normalize_markdown(markdown)

            # التحقق
            is_valid, issues = validate_markdown(markdown)
            if not is_valid:
                logger.warning(f"{html_path}: {', '.join(issues)}")

            # حفظ
            output_path = Path(str(html_path).replace('.html', '.md'))
            output_path.write_text(markdown, encoding='utf-8')

            return True

        return False

    except Exception as e:
        logger.error(f"خطأ في معالجة {html_path}: {e}")
        return False

def batch_convert(input_dir, max_workers=4):
    """تحويل جميع الملفات HTML في الدليل"""
    html_files = list(Path(input_dir).rglob('*.html'))
    logger.info(f"تم العثور على {len(html_files)} ملف HTML")

    with ProcessPoolExecutor(max_workers=max_workers) as executor:
        results = list(executor.map(process_file, html_files))

    success_count = sum(results)
    logger.info(f"تم تحويل {success_count}/{len(html_files)} ملف")

# الاستخدام
batch_convert('./html_docs', max_workers=8)

الخاتمة

تُقدم بيئته Python أدوات ناضجة ومستعدة للإنتاج لتحويل HTML إلى Markdown، كلها مُحسّنة لسيناريوهات مختلفة. اختيارك يجب أن يتوافق مع متطلباتك الخاصة:

  • تحويلات سريعة: استخدم html2text لبساطته وغياب الاعتماديات
  • منطق مخصص: استخدم markdownify للحصول على مرونة كاملة من خلال الفرز
  • استخراج الويب: استخدم trafilatura لاستخراج المحتوى ذكياً مع إزالة النصوص الثانوية
  • تحويلات دفقة: استخدم html2md للمعالجة غير المتزامنة في المشاريع الكبيرة
  • أنظمة الإنتاج: استخدم html-to-markdown للحصول على أمان النوع والدعم الشامل لـ HTML5
  • الحفاظ على المعنى: استخدم domscribe للحفاظ على هيكل HTML5 المعنى

التوصيات لتدفق LLM

لتدفق LLM المسبق، يُنصح بنهج مزدوج:

  1. ابدأ بـ trafilatura لاستخراج المحتوى الأولي - يزيله ذكياً التنقل والإعلانات والنصوص الثانوية مع الحفاظ على المحتوى الرئيسي
  2. الرجوع إلى html-to-markdown للمستندات المعقدة التي تتطلب الحفاظ على الهيكل بدقة، مثل الوثائق التقنية مع الجداول وكتل الكود

هذا الجمع يتعامل مع 95% من السيناريوهات الواقعية بشكل فعال.

الخطوات التالية

جميع هذه الأدوات (باستثناء html2text) تُدار نشطًا وتكون جاهزة للإنتاج. من الأفضل:

  1. تثبيت 2-3 مكتبات تتوافق مع استخدامك
  2. اختبارها مع عينات HTML الخاصة بك
  3. قياس الأداء مع أحجام الوثائق المعتادة
  4. اختر بناءً على جودة الإخراج، وليس فقط السرعة

لقد نضجت بيئته Python بشكل كبير لتحويل HTML إلى Markdown، ولا يمكن أن تخطئ في أي من هذه الخيارات لاستخداماتها المقصودة.

موارد إضافية

ملاحظة: هذه المقارنة تعتمد على تحليل المستندات الرسمية، والردود المجتمعية، وبنية المكتبة. خصائص الأداء تمثل أنماط الاستخدام المعتادة. لحالات الاستخدام المحددة، قم بإجراء اختباراتك الخاصة مع عينات HTML الخاصة بك.

مقالات مفيدة إضافية