HTML naar Markdown converteren met Python: Een uitgebreid overzicht

Python voor het converteren van HTML naar nette, LLM-klare Markdown

Inhoud

HTML naar Markdown converteren is een fundamentele taak in moderne ontwikkelingsworkflows, vooral wanneer je webinhoud voor Large Language Models (LLMs), documentatiesystemen of statische sitegeneratoren zoals Hugo voorbereidt.

Hoewel HTML is ontworpen voor webbrowsers met rijke stijl en structuur, biedt Markdown een schone, leesbare indeling die ideaal is voor tekstverwerking, versiebeheer en AI-consumptie. Als je nieuw bent met Markdown-syntaxis, raadpleeg dan onze Markdown Cheatsheet voor een uitgebreid overzicht.

infographic: pagina converteren van html naar markdown

In dit uitgebreide overzicht bespreken we zes Pythonbibliotheken voor het converteren van HTML naar Markdown, met praktische codevoorbeelden, prestatiebenchmarks en reële toepassingen. Of je nu een LLM-trainingspijplijn bouwt, een blog migreert naar Hugo of documentatie scrapes, je vindt hier het juiste gereedschap voor je workflow.

Alternatieve aanpak: Als je intelligentere inhoudsextractie met semantische begrip nodig hebt, kun je ook overwegen HTML naar Markdown converteren met LLM en Ollama, wat AI-gestuurde conversie biedt voor complexe lay-outs.

Wat je leert:

  • Gedetailleerde vergelijking van 6 bibliotheken met voor- en nadelen per bibliotheek
  • Prestatiebenchmarks met reële HTML-voorbeelden
  • Productie-klare codevoorbeelden voor veelvoorkomende toepassingen
  • Beste praktijken voor LLM-preprocessing-workflows
  • Specifieke aanbevelingen op basis van je eisen

Waarom Markdown voor LLM-preprocessing?

Voor we in de tools duiken, laten we begrijpen waarom Markdown in het bijzonder waardevol is voor LLM-workflows:

  1. Token-efficiëntie: Markdown gebruikt aanzienlijk minder tokens dan HTML voor dezelfde inhoud
  2. Semantische duidelijkheid: Markdown behoudt documentstructuur zonder vervelende tags
  3. Leesbaarheid: Zowel mensen als LLMs kunnen Markdown-syntaxis gemakkelijk parsen
  4. Consistentie: Standaardindeling vermindert onduidelijkheid in modelinputs
  5. Opslag: Kleinere bestandsgroottes voor trainingsgegevens en contextvensters

Markdowns flexibiliteit strekt zich uit tot HTML-conversie—je kunt ook Worddocumenten converteren naar Markdown voor documentatieworkflows gebruiken, of het gebruiken in kennisbeheersysteem zoals Obsidian voor persoonlijke kennisbeheer.

TL;DR - Snelle vergelijkingstabel

Als je haast hebt, hier is een overzicht van alle zes de bibliotheken op een blik. Deze tabel helpt je snel te identificeren welk gereedschap overeenkomt met je specifieke eisen:

Kenmerk html2text markdownify html-to-markdown trafilatura domscribe html2md
HTML5-ondersteuning Gedeeltelijk Gedeeltelijk Volledig Volledig Volledig Volledig
Typehints Nee Nee Ja Gedeeltelijk Nee Gedeeltelijk
Aangepaste handlers Beperkt Uitstekend Goed Beperkt Goed Beperkt
Tabelondersteuning Basis Basis Geavanceerd Goed Goed Goed
Asynchrone ondersteuning Nee Nee Nee Nee Nee Ja
Inhoudsextractie Nee Nee Nee Uitstekend Nee Goed
Metadataverzameling Nee Nee Ja Uitstekend Nee Ja
CLI-tool Nee Nee Ja Ja Nee Ja
Snelheid Gemiddeld Langzaam Snel Zeer snel Gemiddeld Zeer snel
Actieve ontwikkeling Nee Ja Ja Ja Beperkt Ja
Pythonversie 3.6+ 3.7+ 3.9+ 3.6+ 3.8+ 3.10+
Afhankelijkheden Geen BS4 lxml lxml BS4 aiohttp

Snelle keuzegids:

  • Nood aan snelheid? → trafilatura of html2md
  • Nood aan aanpassing? → markdownify
  • Nood aan typesicherheid? → html-to-markdown
  • Nood aan eenvoud? → html2text
  • Nood aan inhoudsextractie? → trafilatura

De kandidaten: 6 Pythonbibliotheken vergeleken

Laten we dieper ingaan op elke bibliotheek met praktische codevoorbeelden, configuratieopties en reële inzichten. Elke sectie bevat installatieinstructies, gebruiksmogelijkheden en eerlijke beoordelingen van sterktes en beperkingen.

1. html2text - De klassieke keuze

Oorspronkelijk ontwikkeld door Aaron Swartz, is html2text al meer dan tien jaar een standaard in de Python-ecosysteem. Het richt zich op het produceren van schone, leesbare Markdown-uitvoer.

Installatie:

pip install html2text

Basisgebruik:

import html2text

# Maak converterinstantie
h = html2text.HTML2Text()

# Stel opties in
h.ignore_links = False
h.ignore_images = False
h.ignore_emphasis = False
h.body_width = 0  # Geen regels omschrijven

html_content = """
<h1>Welkom bij web scraping</h1>
<p>Dit is een <strong>uitgebreide gids</strong> voor het extraheren van inhoud.</p>
<ul>
    <li>Eenvoudig te gebruiken</li>
    <li>Bewezen in de praktijk</li>
    <li Breed aangenomen</li>
</ul>
<a href="https://example.com">Meer informatie</a>
"""

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

Uitvoer:

# Welkom bij web scraping

Dit is een **uitgebreide gids** voor het extraheren van inhoud.

  * Eenvoudig te gebruiken
  * Bewezen in de praktijk
  * Breed aangenomen

[Meer informatie](https://example.com)

Geavanceerde configuratie:

import html2text

h = html2text.HTML2Text()

# Overslaan van specifieke elementen
h.ignore_links = True
h.ignore_images = True

# Beheer van opmaak
h.body_width = 80  # Omschrijf op 80 tekens
h.unicode_snob = True  # Gebruik Unicode-tekens
h.emphasis_mark = '*'  # Gebruik * voor nadruk in plaats van _
h.strong_mark = '**'

# Beheer van tabellen
h.ignore_tables = False

# Bescherm vooraf opgemaakte tekst
h.protect_links = True

Voordelen:

  • Volwassen en stabiel (meer dan 15 jaar ontwikkeling)
  • Uitgebreide configuratieopties
  • Goed met randgevallen
  • Geen externe afhankelijkheden

Nadelen:

  • Beperkte HTML5-ondersteuning
  • Kan onregelmatige spaties produceren
  • Niet actief onderhouden (laatste grote update in 2020)
  • Alleen single-threaded verwerking

Beste voor: Eenvoudige HTML-documenten, legacy-systemen, wanneer stabiliteit van cruciaal belang is


2. markdownify - De flexibele optie

markdownify maakt gebruik van BeautifulSoup4 om flexibele HTML-parsen met aanpasbare tagbehandeling te bieden.

Installatie:

pip install markdownify

Basisgebruik:

from markdownify import markdownify as md

html = """
<article>
    <h2>Modern webontwikkeling</h2>
    <p>Bouwen met <code>Python</code> en <em>moderne frameworks</em>.</p>
    <blockquote>
        <p>Eenvoud is de uiteindelijke sofisticatie.</p>
    </blockquote>
</article>
"""

markdown = md(html)
print(markdown)

Uitvoer:


## Modern webontwikkeling

Bouwen met `Python` en *moderne frameworks*.

> Eenvoud is de uiteindelijke sofisticatie.

Geavanceerd gebruik met aangepaste handlers:

from markdownify import MarkdownConverter

class CustomConverter(MarkdownConverter):
    """
    Maak aangepaste converter met specifieke tagbehandeling
    """
    def convert_img(self, el, text, convert_as_inline):
        """Aangepaste beeldhandler met alternatieve tekst"""
        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):
        """Versterkte codeblokbehandeling met taaldetectie"""
        code = el.find('code')
        if code:
            # Extraheer taal uit class-attribuut (bijv. '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'

# Gebruik aangepaste converter
html = '<pre><code class="language-python">def hello():\n    print("world")</code></pre>'
markdown = CustomConverter().convert(html)
print(markdown)

Voor meer informatie over het werken met Markdown-codeblokken en syntaxismarkering, zie onze gids over Markdown-codeblokken.

Selectieve tagconversie:

from markdownify import markdownify as md

# Verwijder specifieke tags volledig
markdown = md(html, strip=['script', 'style', 'nav'])

# Converteer alleen specifieke tags
markdown = md(
    html,
    heading_style="ATX",  # Gebruik # voor koppen
    bullets="-",  # Gebruik - voor lijstitems
    strong_em_symbol="*",  # Gebruik * voor nadruk
)

Voordelen:

  • Gebaseerd op BeautifulSoup4 (robuste HTML-parsen)
  • Zeer aanpasbaar via subclassing
  • Actief onderhouden
  • Goede documentatie

Nadelen:

  • Vereist BeautifulSoup4-afhankelijkheid
  • Kan trager zijn voor grote documenten
  • Beperkte ingebouwde tabelondersteuning

Beste voor: Aangepaste conversielogica, projecten die al BeautifulSoup4 gebruiken


3. html-to-markdown - De moderne powerhouse

html-to-markdown is een volledig getypeerde, moderne bibliotheek met uitgebreide HTML5-ondersteuning en uitgebreide configuratieopties.

Installatie:

pip install html-to-markdown

Basisgebruik:

from html_to_markdown import convert

html = """
<article>
    <h1>Tech-documentatie</h1>
    <table>
        <thead>
            <tr>
                <th>Kenmerk</th>
                <th>Ondersteuning</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>HTML5</td>
                <td>✓</td>
            </tr>
            <tr>
                <td>Tabellen</td>
                <td>✓</td>
            </tr>
        </tbody>
    </table>
</article>
"""

markdown = convert(html)
print(markdown)

Geavanceerde configuratie:

from html_to_markdown import convert, Options

# Maak aangepaste opties
options = Options(
    heading_style="ATX",
    bullet_style="-",
    code_language_default="python",
    strip_tags=["script", "style"],
    escape_special_chars=True,
    table_style="pipe",  # Gebruik | voor tabellen
    preserve_whitespace=False,
    extract_metadata=True,  # Extraheer meta-tags
)

markdown = convert(html, options=options)

Command-line interface:

# Converteer enkel bestand
html-to-markdown input.html -o output.md

# Converteer met opties
html-to-markdown input.html \
    --heading-style atx \
    --strip-tags script,style \
    --extract-metadata

# Batchconversie
find ./html_files -name "*.html" -exec html-to-markdown {} -o ./markdown_files/{}.md \;

Voordelen:

  • Volledige HTML5-ondersteuning inclusief semantische elementen
  • Typeveilig met uitgebreide typehints
  • Versterkte tabelbehandeling (samengevoegde cellen, uitlijning)
  • Mogelijkheid tot metadataextrahering
  • Actieve ontwikkeling en moderne codebasis

Nadelen:

  • Vereist Python 3.9+
  • Grotere afhankelijkheidsvoetafdruk
  • Steilere leercurve

Beste voor: Complexe HTML5-documenten, typeveilig projecten, productiesystemen


4. trafilatura - De inhoudsextractie specialist

trafilatura is niet alleen een HTML-naar-Markdown-converter, het is ook een slimme inhoudsextractiebibliotheek die specifiek is ontworpen voor web scraping en artikel extrahering.

Installatie:

pip install trafilatura

Basisgebruik:

import trafilatura

# Download en extraher van URL
url = "https://example.com/artikel"
downloaded = trafilatura.fetch_url(url)
markdown = trafilatura.extract(downloaded, output_format='markdown')
print(markdown)

Opmerking: Trafilatura bevat ingebouwde URL-downloading, maar voor complexere HTTP-acties kan je onze cURL Cheatsheet nuttig vinden wanneer je werkt met APIs of geauthenticeerde eindpunten.

Geavanceerde inhoudsextractie:

import trafilatura
from trafilatura.settings import use_config

# Maak aangepaste configuratie
config = use_config()
config.set("DEFAULT", "EXTRACTION_TIMEOUT", "30")

html = """
<html>
<head><title>Artikel titel</title></head>
<body>
    <nav>Navigatiemenu</nav>
    <article>
        <h1>Hoofdartikel</h1>
        <p>Belangrijke inhoud hier.</p>
    </article>
    <aside>Reclame</aside>
    <footer>Voettekst</footer>
</body>
</html>
"""

# Extraher alleen hoofdinhoud
markdown = trafilatura.extract(
    html,
    output_format='markdown',
    include_comments=False,
    include_tables=True,
    include_images=True,
    include_links=True,
    config=config
)

# Extraher met metadata
result = trafilatura.extract(
    html,
    output_format='markdown',
    with_metadata=True
)

if result:
    print(f"Titel: {result.get('title', 'N/A')}")
    print(f"Auteur: {result.get('author', 'N/A')}")
    print(f"Datum: {result.get('date', 'N/A')}")
    print(f"\nInhoud:\n{result.get('text', '')}")

Batchverwerking:

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

def process_url(url):
    """Extraher markdown van URL"""
    downloaded = trafilatura.fetch_url(url)
    if downloaded:
        return trafilatura.extract(
            downloaded,
            output_format='markdown',
            include_links=True,
            include_images=True
        )
    return None

# Verwerk meerdere URLs parallel
urls = [
    "https://example.com/artikel1",
    "https://example.com/artikel2",
    "https://example.com/artikel3",
]

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

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

Voordelen:

  • Slimme inhoudsextractie (verwijderd boilerplate)
  • Ingebouwde URL-downloading met robuuste foutafhandeling
  • Metadataextrahering (titel, auteur, datum)
  • Taaldetectie
  • Optimaliseerd voor nieuwsartikelen en blogposts
  • Snel C-gestuurde parsing

Nadelen:

  • Kan te veel inhoud verwijderen voor algemene HTML
  • Gericht op artikel extrahering (niet algemeen doeleindig)
  • Configuratiecomplexiteit voor randgevallen

Beste voor: Web scraping, artikel extrahering, LLM-trainingsgegevens voorbereiding


5. domscribe - De semantische behoudende

domscribe richt zich op het behouden van de semantische betekenis van HTML tijdens het converteren naar Markdown.

Installatie:

pip install domscribe

Basisgebruik:

from domscribe import html_to_markdown

html = """
<article>
    <header>
        <h1>Verstaan van semantische HTML</h1>
        <time datetime="2024-10-24">24 oktober 2024</time>
    </header>
    <section>
        <h2>Inleiding</h2>
        <p>Semantische HTML geeft <mark>betekenis</mark> aan inhoud.</p>
    </section>
    <aside>
        <h3>Gerelateerde onderwerpen</h3>
        <ul>
            <li>Toegankelijkheid</li>
            <li>SEO</li>
        </ul>
    </aside>
</article>
"""

markdown = html_to_markdown(html)
print(markdown)

Aangepaste opties:

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)

Voordelen:

  • Behoudt semantische HTML5-structuur
  • Goed met moderne webcomponenten
  • Sfeerige API-ontwerp

Nadelen:

  • Nog in vroege ontwikkeling (API kan veranderen)
  • Beperkte documentatie vergeleken met rijpere alternatieven
  • Kleiner community en minder voorbeelden beschikbaar

Beste voor: Semantische HTML5-documenten, toegankelijkheidsgerichte projecten, wanneer het behouden van HTML5-structuur van cruciaal belang is

Opmerking: Hoewel domscribe nieuw en minder getest is dan alternatieven, vult het een specifieke niche voor het behouden van semantische HTML die andere tools niet prioriteren.


6. html2md - De asynchrone powerhouse

html2md is ontworpen voor hoge-prestatie batchconversies met asynchrone verwerking.

Installatie:

pip install html2md

Command-line gebruik:

# Converteer hele map
m1f-html2md convert ./website -o ./docs

# Met aangepaste instellingen
m1f-html2md convert ./website -o ./docs \
    --remove-tags nav,footer \
    --heading-offset 1 \
    --detect-language

# Converteer enkel bestand
m1f-html2md convert index.html -o readme.md

Programmatisch gebruik:

import asyncio
from html2md import convert_html

async def convert_files():
    """Asynchrone batchconversie"""
    html_files = [
        'page1.html',
        'page2.html',
        'page3.html'
    ]

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

# Voer conversie uit
results = asyncio.run(convert_files())

Voordelen:

  • Asynchrone verwerking voor hoge prestaties
  • Slimme inhoudsselectie detectie
  • YAML frontmatter generatie (uitstekend voor Hugo!)
  • Taal detectie
  • Ondersteuning voor parallelle verwerking

Nadelen:

  • Vereist Python 3.10+
  • CLI-gericht (minder flexibele API)
  • Documentatie zou uitgebreider kunnen zijn

Beste voor: Grote schaal migraties, batchconversies, Hugo/Jekyll migraties


Prestatiebenchmarks

Prestaties zijn belangrijk, vooral wanneer duizenden documenten worden verwerkt voor LLM-training of grote schaal migraties. Het begrijpen van de relatieve snelheidverschillen tussen bibliotheken helpt je om informele beslissingen te nemen voor je workflow.

Vergelijkende prestatieanalyse:

Op basis van typische gebruiksmogelijkheden, hier is hoe deze bibliotheken zich vergelijken over drie realistische scenario’s:

  1. Eenvoudige HTML: Basisblogpost met tekst, koppen en links (5KB)
  2. Complexe HTML: Technische documentatie met geneste tabellen en codeblokken (50KB)
  3. Echte website: Volledige webpagina inclusief navigatie, voettekst, zijbalk en advertenties (200KB)

Hier is een voorbeeldbenchmarkcode die je kunt gebruiken om deze bibliotheken zelf te testen:

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

def benchmark(html_content, iterations=100):
    """Benchmark conversiesnelheid"""

    # 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
    }

Typische prestatiekenmerken (representatieve relatieve snelheden):

Pakket Eenvoudig (5KB) Complexe (50KB) Echte site (200KB)
html2text Gemiddeld Langzaam Langzaam
markdownify Langzaam Langzaam Het langst
html-to-markdown Snel Snel Snel
trafilatura Snel Zeer snel Zeer snel
html2md (asynchrone) Zeer snel Zeer snel Snelst

Belangrijke observaties:

  • html2md en trafilatura zijn het snelst voor complexe documenten, waardoor ze ideaal zijn voor batchverwerking
  • html-to-markdown biedt het beste evenwicht tussen snelheid en functies voor productiegebruik
  • markdownify is trager maar het meest flexibel—de trade-off is waard wanneer je aangepaste handlers nodig hebt
  • html2text toont zijn leeftijd met trager prestaties, maar blijft stabiel voor eenvoudige toepassingen

Opmerking: Prestatieverschillen worden aanzienlijk wanneer honderden of duizenden bestanden worden verwerkt. Voor af en toe conversies werkt elke bibliotheek goed. Richt je aandacht op functies en aanpasbaarheid in plaats daarvan.

Real-World Use Cases

Theorie is nuttig, maar praktijkvoorbeelden laten zien hoe deze tools werken in productieomgevingen. Hier zijn vier veelvoorkomende scenario’s met volledige, productie-geoorloofde code die je kunt aanpassen voor je eigen projecten.

Use Case 1: LLM Training Data Preparation

Vereiste: Rein tekst extraheren uit duizenden documentatiepagina’s

Aanbevolen: trafilatura + parallelliseren

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

def process_html_file(html_path):
    """Converteer HTML-bestand naar markdown"""
    html = Path(html_path).read_text(encoding='utf-8')
    markdown = trafilatura.extract(
        html,
        output_format='markdown',
        include_links=False,  # Verwijderen voor schoner training data
        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

# Verwerk 10.000 bestanden in parallel
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"Verwerkt {len(html_files)} bestanden")
print(f"Totaal aantal tekens: {sum(token_counts):,}")

Use Case 2: Hugo Blog Migration

Vereiste: Migreren van WordPress-blog naar Hugo met frontmatter

Aanbevolen: html2md CLI

Hugo is een populaire statische sitegenerator die Markdown gebruikt voor inhoud. Voor meer Hugo-specifieke tips, bekijk onze Hugo Cheat Sheet en leer over Structured data markup toevoegen aan Hugo voor betere SEO.

# Converteer alle berichten met frontmatter
m1f-html2md convert ./wordpress-export \
    -o ./hugo/content/posts \
    --generate-frontmatter \
    --heading-offset 0 \
    --remove-tags script,style,nav,footer

Of programmatisch:

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

def migrate_post(html_file):
    """Converteer WordPress HTML naar Hugo markdown"""
    html = Path(html_file).read_text()

    # Titel en datum extraheren uit HTML
    from bs4 import BeautifulSoup
    soup = BeautifulSoup(html, 'html.parser')
    title = soup.find('h1').get_text() if soup.find('h1') else 'Untitled'

    # Converteer naar markdown
    options = Options(strip_tags=['script', 'style', 'nav', 'footer'])
    markdown = convert(html, options=options)

    # Voeg Hugo frontmatter toe
    frontmatter = {
        'title': title,
        'date': '2024-10-24',
        'draft': False,
        'tags': []
    }

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

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

# Verwerk alle berichten
for html_file in Path('./wordpress-export').glob('*.html'):
    migrate_post(html_file)

Use Case 3: Documentatie Scraper met Aangepaste Opmaak

Vereiste: Scrape technische documentatie met aangepaste codeblokkenbehandeling

Aanbevolen: markdownify met aangepaste converter

Deze aanpak is vooral handig bij het migreren van documentatie van wiki-systemen. Als je documentatie beheert, zou je ook geïnteresseerd kunnen zijn in DokuWiki - zelfgehost wiki en alternatieven voor oplossingen voor zelfgehoste documentatie.

from markdownify import MarkdownConverter
import requests

class DocsConverter(MarkdownConverter):
    """Aangepaste converter voor technische documentatie"""

    def convert_pre(self, el, text, convert_as_inline):
        """Versterkte codeblokken met syntax highlighting"""
        code = el.find('code')
        if code:
            # Taal extraheren uit klasse
            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):
        """Behandel speciale documentatieblokken"""
        classes = el.get('class', [])

        # Waarschuwingsblokken
        if 'warning' in classes:
            return f'\n> ⚠️ **Waarschuwing**: {text}\n'

        # Info-blokken
        if 'info' in classes or 'note' in classes:
            return f'\n> 💡 **Opmerking**: {text}\n'

        return text

def scrape_docs(url):
    """Scrape en converteer documentatiepagina"""
    response = requests.get(url)
    markdown = DocsConverter().convert(response.text)
    return markdown

# Gebruik
docs_url = "https://docs.example.com/api-reference"
markdown = scrape_docs(docs_url)
Path('api-reference.md').write_text(markdown)

Use Case 4: Nieuwsbrief naar Markdown Archief

Vereiste: Converteer HTML-nieuwsbrieven naar leesbare markdown

Aanbevolen: html2text met specifieke configuratie

import html2text
import email
from pathlib import Path

def convert_newsletter(email_file):
    """Converteer HTML-nieuwsbrief naar markdown"""
    # Email parsen
    with open(email_file, 'r') as f:
        msg = email.message_from_file(f)

    # HTML-deel ophalen
    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

    # Converter configureren
    h = html2text.HTML2Text()
    h.ignore_images = False
    h.images_to_alt = True
    h.body_width = 0
    h.protect_links = True
    h.unicode_snob = True

    # Converteer
    markdown = h.handle(html_content)

    # Metadata toevoegen
    subject = msg.get('Subject', 'Geen onderwerp')
    date = msg.get('Date', '')

    output = f"# {subject}\n\n*Datum: {date}*\n\n---\n\n{markdown}"

    return output

# Nieuwsbriefarchief verwerken
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')

Aanbevelingen per Scenario

Nog steeds onzeker welk bibliotheek je moet kiezen? Hier is mijn definitieve gids gebaseerd op specifieke gebruiksscenario’s. Deze aanbevelingen komen uit praktijkervaring met elke bibliotheek in productieomgevingen.

Voor Web Scraping & LLM Voorverwerking

Winnaar: trafilatura

Trafilatura is uitstekend in het extraheren van schone inhoud terwijl boilerplate wordt verwijderd. Ideaal voor:

  • Bouwen van LLM training datasets
  • Inhoudsaggregatie
  • Onderzoeksrapporten verzamelen
  • Nieuwsartikel extractie

Voor Hugo/Jekyll Migraties

Winnaar: html2md

Asynchrone verwerking en frontmattergeneratie maken bulkmigraties snel en eenvoudig:

  • Batchconversies
  • Automatische metadataextractie
  • YAML frontmattergeneratie
  • Aanpassen van kopniveaus

Voor Aangepaste Conversie Logica

Winnaar: markdownify

Subklasseer de converter voor volledige controle:

  • Aangepaste taghandlers
  • Domein-specifieke conversies
  • Specifieke opmaakvereisten
  • Integratie met bestaande BeautifulSoup code

Voor Typeveilig Productiesystemen

Winnaar: html-to-markdown

Moderne, typeveilig en functievol:

  • Volledige HTML5-ondersteuning
  • Uitgebreide typehints
  • Geavanceerde tabelbehandeling
  • Actieve onderhoud

Voor Eenvoudige, Stabiele Conversies

Winnaar: html2text

Wanneer je iets nodig hebt dat “gewoon werkt”:

  • Geen afhankelijkheden
  • Getest in de strijd
  • Uitgebreide configuratie
  • Breed platformondersteuning

Beste Praktijken voor LLM Voorverwerking

Ongeacht welke bibliotheek je kiest, het volgen van deze beste praktijken zorgt ervoor dat de uitvoer van de Markdown van hoge kwaliteit is en geoptimaliseerd is voor LLM-consumptie. Deze patronen zijn essentieel geweest in productie workflows die miljoenen documenten verwerken.

1. Reinig voor het converteren

Verwijder altijd ongewenste elementen voor conversie om schoner output en betere prestaties te krijgen:

from bs4 import BeautifulSoup
import trafilatura

def clean_and_convert(html):
    """Verwijder ongewenste elementen voor conversie"""
    soup = BeautifulSoup(html, 'html.parser')

    # Verwijder ongewenste elementen
    for element in soup(['script', 'style', 'nav', 'footer', 'header', 'aside']):
        element.decompose()

    # Verwijder advertenties en tracking
    for element in soup.find_all(class_=['ad', 'advertisement', 'tracking']):
        element.decompose()

    # Converteer opgeschoonde HTML
    markdown = trafilatura.extract(
        str(soup),
        output_format='markdown'
    )

    return markdown

2. Witruimte Normaliseren

Verschillende converters behandelen witruimte op verschillende manieren. Normaliseer de uitvoer om consistentie te waarborgen over je corpus:

import re

def normalize_markdown(markdown):
    """Reinig markdown spaties"""
    # Verwijder meerdere lege lijnen
    markdown = re.sub(r'\n{3,}', '\n\n', markdown)

    # Verwijder achterliggende witruimte
    markdown = '\n'.join(line.rstrip() for line in markdown.split('\n'))

    # Zorg voor enkele newline aan het einde
    markdown = markdown.rstrip() + '\n'

    return markdown

3. Uitvoer Valideren

Kwaliteitscontrole is essentieel. Implementeer validatie om conversiefouten vroegtijdig te detecteren:

def validate_markdown(markdown):
    """Valideer markdown kwaliteit"""
    issues = []

    # Controleer op HTML restanten
    if '<' in markdown and '>' in markdown:
        issues.append("HTML tags gedetecteerd")

    # Controleer op gebroken links
    if '[' in markdown and ']()' in markdown:
        issues.append("Lege link gedetecteerd")

    # Controleer op te veel codeblokken
    code_block_count = markdown.count('```')
    if code_block_count % 2 != 0:
        issues.append("Niet gesloten codeblok")

    return len(issues) == 0, issues

4. Batchverwerkingstemplate

Bij het verwerken van grote documentcollecties, gebruik deze productie-geoorloofde template met juiste foutafhandeling, logboekregistratie en parallelliseren:

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):
    """Verwerk enkel HTML-bestand"""
    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:
            # Normaliseer
            markdown = normalize_markdown(markdown)

            # Valideer
            is_valid, issues = validate_markdown(markdown)
            if not is_valid:
                logger.warning(f"{html_path}: {', '.join(issues)}")

            # Opslaan
            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"Fout bij verwerken van {html_path}: {e}")
        return False

def batch_convert(input_dir, max_workers=4):
    """Converteer alle HTML-bestanden in map"""
    html_files = list(Path(input_dir).rglob('*.html'))
    logger.info(f"Gevonden {len(html_files)} HTML-bestanden")

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

    success_count = sum(results)
    logger.info(f"Met succes geconverteerd {success_count}/{len(html_files)} bestanden")

# Gebruik
batch_convert('./html_docs', max_workers=8)

Conclusie

Het Python-ecosysteem biedt rijpe, productie-geoorloofde tools voor HTML-naar-Markdown-conversie, elk geoptimaliseerd voor verschillende scenario’s. Je keuze moet overeenkomen met je specifieke vereisten:

  • Snelle conversies: Gebruik html2text vanwege zijn eenvoud en nul afhankelijkheden
  • Aangepaste logica: Gebruik markdownify voor maximale flexibiliteit via subclassing
  • Web scraping: Gebruik trafilatura voor slimme inhoudsextractie met boilerplateverwijdering
  • Bulkmigraties: Gebruik html2md voor asynchrone prestaties op grote schaalprojecten
  • Productiesystemen: Gebruik html-to-markdown voor typeveiligheid en uitgebreide HTML5-ondersteuning
  • Semantische behoud: Gebruik domscribe voor het behouden van HTML5-semantische structuur

Aanbevelingen voor LLM Workflows

Voor LLM-voorverwerking workflows wordt een tweestapsaanpak aanbevolen:

  1. Begin met trafilatura voor initiële inhoudsextractie – het verwijdert slim navigatie, advertenties en boilerplate terwijl het de hoofdinhoud behoudt
  2. Val terug op html-to-markdown voor complexe documenten die nauwkeurige structuurbehoud vereisen, zoals technische documentatie met tabellen en codeblokken

Deze combinatie behandelt 95% van de echte wereldscenario’s effectief.

Volgende stappen

Alleze tools (behalve html2text) worden actief onderhouden en zijn productie-geoorloofd. Het is beter om:

  1. 2-3 bibliotheekken te installeren die overeenkomen met je gebruiksscenario
  2. Ze testen met je eigen HTML-voorbeelden
  3. Prestaties te benchmarken met je typische documentgroottes
  4. Kiezen op basis van uitvoerkwaliteit, niet alleen snelheid

Het Python-ecosysteem voor HTML-naar-Markdown-conversie is aanzienlijk volwassen geworden, en je kan geen fout doen met welke van deze keuzes ook voor hun bedoelde gebruiksscenario’s.

Extra Resources

Opmerking: Deze vergelijking is gebaseerd op analyse van officiële documentatie, community feedback en bibliotheekarchitectuur. Prestatiekenmerken zijn representatief voor typische gebruiksmogelijkheden. Voor specifieke gebruiksscenario’s, voer je eigen benchmarks uit met je eigen HTML-voorbeelden.

Andere Nuttige Artikelen