Konwersja HTML na Markdown za pomocą Pythona: Kompletny przewodnik

Python do konwersji HTML na czysty, gotowy do przetwarzania przez LLM Markdown

Page content

Konwersja HTML na Markdown to fundamentalna czynność w nowoczesnych przepływach pracy programistycznych, szczególnie przygotowując treści sieciowe do Large Language Models (LLM), systemów dokumentacji lub generatorów stron statycznych takich jak Hugo. Niniejszy przewodnik jest częścią naszego Narzędzi do Dokumentacji w 2026: Markdown, LaTeX, PDF i Pracy z Drukowaniem.

Choć HTML jest zaprojektowany dla przeglądarek internetowych z bogatym stylizowaniem i strukturą, Markdown oferuje czysty, czytelny format idealny do przetwarzania tekstu, kontroli wersji i konsumpcji przez AI. Jeśli jesteś nowy w składni Markdown, sprawdź nasz Podręcznik skrótów Markdown dla kompletnego odniesienia.

infografika: konwersja strony z HTML na Markdown

W tej szczegółowej recenzji omówimy sześć pakietów Pythona do konwersji HTML na Markdown, dostarczając praktyczne przykłady kodu, wyniki testów wydajności i rzeczywiste przypadki użycia. Niezależnie od tego, czy budujesz pipeline treningowy LLM, czy migrujesz bloga do Hugoa, czy skrapujesz dokumentację, znajdziesz idealne narzędzie dla swojego przepływu pracy.

Alternatywny podejście: Jeśli potrzebujesz bardziej inteligentnego wyodrębniania treści z zrozumieniem semantycznym, rozważ również konwersję HTML na Markdown za pomocą LLM i Ollama, która oferuje AI-powered konwersję dla złożonych układów.

Nauczysz się:

  • Szczegółowa analiza 6 bibliotek z zaletami i wadami każdej
  • Wyniki testów wydajności z rzeczywistymi przykładami HTML
  • Przykłady kodu gotowe do produkcji dla typowych przypadków użycia
  • Najlepsze praktyki dla przepływów pracy przygotowania danych do LLM
  • Konkretnych rekomendacji na podstawie Twoich wymagań

Dlaczego Markdown dla przygotowania danych do LLM?

Przed zanurzeniem się w narzędziach, zrozummy dlaczego Markdown jest szczególnie wartościowy dla przepływów pracy LLM:

  1. Efektywność tokenów: Markdown zużywa znacznie mniej tokenów niż HTML dla tej samej treści
  2. Jasność semantyczna: Markdown zachowuje strukturę dokumentu bez zbędnych tagów
  3. Czytelność: zarówno ludzie, jak i LLM mogą łatwo przetwarzać składnię Markdown
  4. Spójność: standardowy format zmniejsza niejednoznaczność we wejściach modelu
  5. Przechowywanie: mniejsze rozmiary plików dla danych treningowych i okien kontekstowych

Wersatylność Markdown rozciąga się poza konwersję HTML – możesz również konwertować dokumenty Word na Markdown dla przepływów pracy dokumentacji, lub używać go w systemach zarządzania wiedzą takich jak Obsidian do zarządzania osobistą wiedzą. Aby dowiedzieć się więcej o konwersji dokumentów i formatowaniu w Markdown, LaTeX i PDF, zobacz Hub Narzędzi do Dokumentacji.

TL;DR - Macierz szybkiego porównania

Jeśli jesteś w pośpiechu, oto kompletny przegląd wszystkich sześciu bibliotek w jednym wzorcu. Ta tabela pomoże Ci szybko zidentyfikować, które narzędzie pasuje do Twoich konkretnych wymagań:

Funkcja html2text markdownify html-to-markdown trafilatura domscribe html2md
Wsparcie HTML5 Częściowe Częściowe Pełne Pełne Pełne Pełne
Wskazówki typu Brak Brak Tak Częściowe Brak Częściowe
Niestandardowe procedury Ograniczone Wspaniałe Dobre Ograniczone Dobre Ograniczone
Wsparcie dla tabel Podstawowe Podstawowe Zaawansowane Dobre Dobre Dobre
Wsparcie asynchroniczne Brak Brak Brak Brak Brak Tak
Wyodrębnianie treści Brak Brak Brak Wspaniałe Brak Dobre
Wyodrębnianie metadanych Brak Brak Tak Wspaniałe Brak Tak
Narzędzie CLI Brak Brak Tak Tak Brak Tak
Szybkość Średnia Wolna Szybka Bardzo szybka Średnia Bardzo szybka
Aktywne rozwijanie Brak Tak Tak Tak Ograniczone Tak
Wersja Pythona 3.6+ 3.7+ 3.9+ 3.6+ 3.8+ 3.10+
Zależności Brak BS4 lxml lxml BS4 aiohttp

Szybki przewodnik wyboru:

  • Potrzebujesz szybkości? → trafilatura lub html2md
  • Potrzebujesz dostosowania? → markdownify
  • Potrzebujesz bezpieczeństwa typu? → html-to-markdown
  • Potrzebujesz prostoty? → html2text
  • Potrzebujesz wyodrębniania treści? → trafilatura

Konkurenci: 6 porównanych pakietów Pythona

Zanurzmy się głęboko w każdy z bibliotek z praktycznymi przykładami kodu, opcjami konfiguracji i rzeczywistymi wglądami. Każda sekcja zawiera instrukcje instalacji, wzorce użycia i szczere oceny zalet i ograniczeń.

1. html2text - Klasyczna opcja

Oryginalnie opracowany przez Aaron Swartza, html2text był stalowym elementem w ekosystemie Pythona przez ponad dekadę. Skupia się na generowaniu czystego, czytelnego wyjścia w formacie Markdown.

Instalacja:

pip install html2text

Podstawowe użycie:

import html2text

# Utwórz instancję konwertera
h = html2text.HTML2Text()

# Skonfiguruj opcje
h.ignore_links = False
h.ignore_images = False
h.ignore_emphasis = False
h.body_width = 0  # Nie zapisuj linii

html_content = """
<h1>Witaj w Web Scraping</h1>
<p>To jest <strong>kompleksowy przewodnik</strong> po wyodrębnianiu treści.</p>
<ul>
    <li>Łatwe w użyciu</li>
    <li>Przetestowane w praktyce</li>
    <li>Szeroko stosowane</li>
</ul>
<a href="https://example.com">Dowiedz się więcej</a>
"""

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

Wyjście:

# Witaj w Web Scraping

To jest **kompleksowy przewodnik** po wyodrębnianiu treści.

  * Łatwe w użyciu
  * Przetestowane w praktyce
  * Szeroko stosowane

[Wyświetl więcej](https://example.com)

Zaawansowana konfiguracja:

import html2text

h = html2text.HTML2Text()

# Pominięcie określonych elementów
h.ignore_links = True
h.ignore_images = True

# Kontrola formatowania
h.body_width = 80  # Zapisuj przy 80 znakach
h.unicode_snob = True  # Użyj znaków unicode
h.emphasis_mark = '*'  # Użyj * do podkreślania zamiast _
h.strong_mark = '**'

# Obsługa tabel
h.ignore_tables = False

# Ochrona tekstu sformatowanego
h.protect_links = True

Zalety:

  • Dojrzała i stabilna (15+ lat rozwoju)
  • Rozszerzona konfiguracja opcji
  • Dobrze radzi sobie z przypadkami granicznymi
  • Brak zależności zewnętrznych

Wady:

  • Ograniczone wsparcie dla HTML5
  • Może generować niezgodne odstępy
  • Nie jest aktywnie utrzymywany (ostatnia większa aktualizacja w 2020 roku)
  • Tylko przetwarzanie w jednym wątku

Najlepsze do: Prostych dokumentów HTML, systemów legacy, gdy stabilność jest najważniejsza


2. markdownify - Opcja elastyczna

markdownify wykorzystuje BeautifulSoup4, aby zapewnić elastyczne parsowanie HTML z niestandardowymi procedurami obsługi tagów.

Instalacja:

pip install markdownify

Podstawowe użycie:

from markdownify import markdownify as md

html = """
<article>
    <h2>Nowoczesne Web Development</h2>
    <p>Budowanie z <code>Python</code> i <em>nowoczesnymi frameworkami</em>.</p>
    <blockquote>
        <p>Prostota to ostateczna elegancja.</p>
    </blockquote>
</article>
"""

markdown = md(html)
print(markdown)

Wyjście:


## Nowoczesne Web Development

Budowanie z `Python` i *nowoczesnymi frameworkami*.

> Prostota to ostateczna elegancja.

Zaawansowane użycie z niestandardowymi procedurami:

from markdownify import MarkdownConverter

class CustomConverter(MarkdownConverter):
    """
    Utwórz niestandardowy konwerter z konkretnym obsługą tagów
    """
    def convert_img(self, el, text, convert_as_inline):
        """Niestandardowa obsługa obrazu z tekstem alternatywnym"""
        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):
        """Zwiększone obsługa bloków kodu z wykrywaniem języka"""
        code = el.find('code')
        if code:
            # Wyodrębnij język z atrybutu klasy (np. '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'

# Użyj niestandardowego konwertera
html = '<pre><code class="language-python">def hello():\n    print("world")</code></pre>'
markdown = CustomConverter().convert(html)
print(markdown)

Dla więcej szczegółów na temat pracy z blokami kodu w Markdown i podświetlania składni, zobacz nasz przewodnik Użycie bloków kodu w Markdown.

Wybór konwersji tagów:

from markdownify import markdownify as md

# Usuń określone tagi całkowicie
markdown = md(html, strip=['script', 'style', 'nav'])

# Konwertuj tylko określone tagi
markdown = md(
    html,
    heading_style="ATX",  # Użyj # dla nagłówków
    bullets="-",  # Użyj - dla punktów
    strong_em_symbol="*",  # Użyj * dla podkreślania
)

Zalety:

  • Oparty na BeautifulSoup4 (solidne parsowanie HTML)
  • Bardzo elastyczny dzięki dziedziczeniu
  • Aktywne utrzymanie
  • Dobra dokumentacja

Wady:

  • Wymaga zależności BeautifulSoup4
  • Może być wolniejszy dla dużych dokumentów
  • Ograniczone wsparcie dla tabel

Najlepsze do: Niestandardowej konwersji, projektów już korzystających z BeautifulSoup4


3. html-to-markdown - Nowoczesna potęga

html-to-markdown to kompletnie typowana, nowoczesna biblioteka z wszechstronnym wsparciem HTML5 i szerokimi opcjami konfiguracji.

Instalacja:

pip install html-to-markdown

Podstawowe użycie:

from html_to_markdown import convert

html = """
<article>
    <h1>Dokumentacja techniczna</h1>
    <table>
        <thead>
            <tr>
                <th>Funkcja</th>
                <th>Wsparcie</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>HTML5</td>
                <td>✓</td>
            </tr>
            <tr>
                <td>Tabele</td>
                <td>✓</td>
            </tr>
        </tbody>
    </table>
</article>
"""

markdown = convert(html)
print(markdown)

Zaawansowana konfiguracja:

from html_to_markdown import convert, Options

# Utwórz niestandardowe opcje
options = Options(
    heading_style="ATX",
    bullet_style="-",
    code_language_default="python",
    strip_tags=["script", "style"],
    escape_special_chars=True,
    table_style="pipe",  # Użyj | dla tabel
    preserve_whitespace=False,
    extract_metadata=True,  # Wyodrębnij tagi meta
)

markdown = convert(html, options=options)

Interfejs wiersza poleceń:

# Konwertuj pojedynczy plik
html-to-markdown input.html -o output.md

# Konwertuj z opcjami
html-to-markdown input.html \
    --heading-style atx \
    --strip-tags script,style \
    --extract-metadata

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

Zalety:

  • Pełne wsparcie HTML5 w tym elementy semantyczne
  • Typowo bezpieczne z komprehensywnymi wskazówkami typu
  • Zwiększone obsługa tabel (scalane komórki, wyrównanie)
  • Możliwość wyodrębniania metadanych
  • Aktywne rozwijanie i nowoczesna baza kodu

Wady:

  • Wymaga Pythona 3.9+
  • Większa ilość zależności
  • Wysoki poziom nauczania

Najlepsze do: Złożonych dokumentów HTML5, projektów typowo bezpiecznych, systemów produkcyjnych


4. trafilatura - Specjalista do wyodrębniania treści

trafilatura to nie tylko konwerter HTML na Markdown – to inteligentna biblioteka do wyodrębniania treści specjalnie zaprojektowana do skrapowania sieci i ekstrakcji artykułów.

Instalacja:

pip install trafilatura

Podstawowe użycie:

import trafilatura

# Pobierz i wyodrębnij z URL
url = "https://example.com/article"
downloaded = trafilatura.fetch_url(url)
markdown = trafilatura.extract(downloaded, output_format='markdown')
print(markdown)

Uwaga: Trafilatura zawiera wbudowane pobieranie URL, ale dla bardziej złożonych operacji HTTP, możesz znaleźć pomocny nasz Podręcznik cURL przy pracy z API lub punktami końcowymi uwierzytelnionymi.

Zaawansowane wyodrębnianie treści:

import trafilatura
from trafilatura.settings import use_config

# Utwórz niestandardową konfigurację
config = use_config()
config.set("DEFAULT", "EXTRACTION_TIMEOUT", "30")

html = """
<html>
<head><title>Tytuł artykułu</title></head>
<body>
    <nav>Menu nawigacyjne</nav>
    <article>
        <h1>Główny artykuł</h1>
        <p>Ważna treść tutaj.</p>
    </article>
    <aside>Reklama</aside>
    <footer>Treść stopki</footer>
</body>
</html>
"""

# Wyodrębnij tylko główną treść
markdown = trafilatura.extract(
    html,
    output_format='markdown',
    include_comments=False,
    include_tables=True,
    include_images=True,
    include_links=True,
    config=config
)

# Wyodrębnij z metadane
result = trafilatura.extract(
    html,
    output_format='markdown',
    with_metadata=True
)

if result:
    print(f"Tytuł: {result.get('title', 'N/A')}")
    print(f"Autor: {result.get('author', 'N/A')}")
    print(f"Data: {result.get('date', 'N/A')}")
    print(f"\nTreść:\n{result.get('text', '')}")

Przetwarzanie wsadowe:

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

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

# Przetwarzanie wielu URL w równoległości
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')

Zalety:

  • Inteligentne wyodrębnianie treści (usuwa boilerplate)
  • Wbudowane pobieranie URL z solidnymi mechanizmami obsługi błędów
  • Wyodrębnianie metadanych (tytuł, autor, data)
  • Wykrywanie języka
  • Optymalizacja dla artykułów i blogów
  • Szybkie przetwarzanie w C

Wady:

  • Może zbyt dużo usuwać treści dla ogólnego HTML
  • Skupiony na ekstrakcji artykułów (nie ogólne)
  • Złożoność konfiguracji dla przypadków granicznych

Najlepsze do: Skrapowania sieci, ekstrakcji artykułów, przygotowania danych treningowych dla LLM


5. domscribe - Przechowujący znaczenie semantyczne

domscribe skupia się na zachowaniu znaczenia semantycznego HTML podczas konwersji na Markdown.

Instalacja:

pip install domscribe

Podstawowe użycie:

from domscribe import html_to_markdown

html = """
<article>
    <header>
        <h1>Zrozumienie semantycznego HTML</h1>
        <time datetime="2024-10-24">24 października 2024</time>
    </header>
    <section>
        <h2>Wprowadzenie</h2>
        <p>Semantyczne HTML nadaje <mark>znaczenie</mark> treści.</p>
    </section>
    <aside>
        <h3>Powiązane tematy</h3>
        <ul>
            <li>Dostępność</li>
            <li>SEO</li>
        </ul>
    </aside>
</article>
"""

markdown = html_to_markdown(html)
print(markdown)

Niestandardowe opcje:

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)

Zalety:

  • Zachowuje strukturę HTML5 semantyczną
  • Dobrze radzi sobie z nowoczesnymi komponentami sieciowymi
  • Czysty projekt API

Wady:

  • Nadal w wczesnym rozwoju (API może się zmienić)
  • Ograniczona dokumentacja w porównaniu do dojrzałych alternatyw
  • Mniejsza społeczność i mniej dostępnych przykładów

Najlepsze do: Dokumentów HTML5 semantycznych, projektów skupionych na dostępności, gdy zachowanie struktury semantycznej HTML5 jest krytyczne

Uwaga: Choć domscribe jest nowszy i mniej testowany niż alternatywy, wypełnia konkretny niszowy wymóg dla zachowania semantycznego HTML, którego inne narzędzia nie priorytetyzują.


6. html2md - Potęga asynchroniczna

html2md jest zaprojektowany do wysokiej wydajności wsadowej konwersji z asynchronicznym przetwarzaniem.

Instalacja:

pip install html2md

Użycie wiersza poleceń:

# Konwertuj całą katalog
m1f-html2md convert ./website -o ./docs

# Z niestandardowymi ustawieniami
m1f-html2md convert ./website -o ./docs \
    --remove-tags nav,footer \
    --heading-offset 1 \
    --detect-language

# Konwertuj pojedynczy plik
m1f-html2md convert index.html -o readme.md

Użycie programistyczne:

import asyncio
from html2md import convert_html

async def convert_files():
    """Asynchroniczna konwersja wsadowa"""
    html_files = [
        'page1.html',
        'page2.html',
        'page3.html'
    ]

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

# Uruchom konwersję
results = asyncio.run(convert_files())

Zalety:

  • Asynchroniczne przetwarzanie dla wysokiej wydajności
  • Inteligentne wykrywanie selektorów treści
  • Generowanie YAML frontmatter (wspaniałe dla Hugoa!)
  • Wykrywanie języka kodu
  • Wsparcie dla przetwarzania równoległego

Wady:

  • Wymaga Pythona 3.10+
  • CLI-orientowane (mniej elastyczny API)
  • Dokumentacja mogła być bardziej kompletna

Najlepsze do: Dużych migracji, konwersji wsadowych, migracji Hugo/Jekyll


Testowanie wydajności

Wydajność ma znaczenie, szczególnie przy przetwarzaniu tysięcy dokumentów do treningu LLM lub dużych migracji. Zrozumienie różnic w prędkości między bibliotekami pomaga w podejmowaniu świadomych decyzji dla Twojego przepływu pracy.

Porównanie wydajności:

Na podstawie typowych wzorców użycia, oto jak te biblioteki porównują się w trzech realistycznych scenariuszach:

  1. Prosty HTML: Podstawowy wpis blogowy z tekstem, nagłówkami i linkami (5KB)
  2. Złożony HTML: Dokumentacja techniczna z zagnieżdżonymi tabelami i blokami kodu (50KB)
  3. Rzeczywista strona internetowa: Pełna strona internetowa zawierająca nawigację, stopkę, sidebar i reklamy (200KB)

Oto przykład kodu testowego, który możesz użyć, aby samodzielnie przetestować te biblioteki:

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

def benchmark(html_content, iterations=100):
    """Testowanie szybkości konwersji"""

    # 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': html2线时间,
        'markdownify': markdownify_time,
        'html-to-markdown': html_to_markdown_time,
        'trafilatura': trafilatura_time
    }

Typowe cechy wydajności (przykładowe względne prędkości):

Pakiet Prosty (5KB) Złożony (50KB) Rzeczywista strona (200KB)
html2text Średnia Wolniejsza Wolniejsza
markdownify Wolniejsza Wolniejsza Najwolniejsza
html-to-markdown Szybka Szybka Szybka
trafilatura Szybka Bardzo szybka Bardzo szybka
html2md (asynchronicznie) Bardzo szybka Bardzo szybka Najbardziej szybka

Główne obserwacje:

  • html2md i trafilatura są najszybsze dla złożonych dokumentów, czyniąc je idealnymi do przetwarzania wsadowego
  • html-to-markdown oferuje najlepszy zrównoważony stosunek szybkości i funkcji dla użycia produkcyjnego
  • markdownify jest wolniejszy, ale najbardziej elastyczny – poświęcenie jest warte, gdy potrzebujesz niestandardowych procedur
  • html2text pokazuje swoje wiekowe powolność, ale nadal jest stabilny dla prostych przypadków użycia

Uwaga: Różnice w wydajności stają się znaczące tylko przy przetwarzaniu setek lub tysięcy plików. Dla rzadkich konwersji, dowolna biblioteka zadziała dobrze. Skup się na funkcjach i opcjach dostosowania zamiast tego.


Przypadki użycia w praktyce

Teoria jest pomocna, ale praktyczne przykłady pokazują, jak te narzędzia działają w produkcji. Oto cztery typowe scenariusze z kompletnym, gotowym do produkcji kodem, który możesz dostosować do swoich własnych projektów.

Przypadek użycia 1: Przygotowanie danych treningowych dla LLM

Wymagania: Wyodrębnienie czystego tekstu z tysięcy stron dokumentacji

Zalecany: trafilatura + przetwarzanie równoległe

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

def process_html_file(html_path):
    """Konwertuj plik HTML na markdown"""
    html = Path(html_path).read_text(encoding='utf-8')
    markdown = trafilatura.extract(
        html,
        output_format='markdown',
        include_links=False,  # Usuń dla czystszych danych treningowych
        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

# Przetwarzanie 10 000 plików równolegle
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"Przetworzono {len(html_files)} plików")
print(f"Łączna liczba znaków: {sum(token_counts):,}")

Przypadek użycia 2: Migracja bloga Hugo

Wymagania: Migracja bloga WordPress do Hugoa z frontmatter

Zalecany: html2md CLI

Hugo to popularny generator stron statycznych, który używa Markdown do treści. Dla więcej wskazówek specyficznych dla Hugoa, sprawdź nasz Podręcznik Hugoa i dowiedz się, jak Dodawać strukturalne znaczniki do Hugoa dla lepszego SEO. Nasz Hub Narzędzi do Dokumentacji zawiera więcej przewodników na temat przepływów pracy Markdown i konwersji dokumentów.

# Konwertuj wszystkie wpisy z frontmatter
m1f-html2md convert ./wordpress-export \
    -o ./hugo/content/posts \
    --generate-frontmatter \
    --heading-offset 0 \
    --remove-tags script,style,nav,footer

Lub programowo:

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

def migrate_post(html_file):
    """Konwertuj HTML WordPress na Markdown Hugoa"""
    html = Path(html_file).read_text()

    # Wyodrębnij tytuł i datę z HTML
    from bs4 import BeautifulSoup
    soup = BeautifulSoup(html, 'html.parser')
    title = soup.find('h1').get_text() if soup.find('h1') else 'Bez tytułu'

    # Konwertuj na Markdown
    options = Options(strip_tags=['script', 'style', 'nav', 'footer'])
    markdown = convert(html, options=options)

    # Dodaj frontmatter Hugoa
    frontmatter = {
        'title': title,
        'date': '2024-10-24',
        'draft': False,
        'tags': []
    }

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

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

# Przetwarzaj wszystkie wpisy
for html_file in Path('./wordpress-export').glob('*.html'):
    migrate_post(html_file)

Przypadek użycia 3: Skraper dokumentacji z niestandardowym formatowaniem

Wymagania: Skrapowanie dokumentacji technicznych z niestandardowym formatowaniem bloków kodu

Zalecany: markdownify z niestandardowym konwerterem

Ten podejście jest szczególnie przydatny przy migracji dokumentacji z systemów wiki. Jeśli zarządzasz dokumentacją, możesz być również zainteresowany DokuWiki - samozhostowany wiki i alternatywy dla rozwiązań samozhostowanych dokumentacji.

from markdownify import MarkdownConverter
import requests

class DocsConverter(MarkdownConverter):
    """Niestandardowy konwerter dla dokumentacji technicznej"""

    def convert_pre(self, el, text, convert_as_inline):
        """Zwiększone bloki kodu z podświetlaniem składni"""
        code = el.find('code')
        if code:
            # Wyodrębnij język z klasy
            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):
        """Obsługa specjalnych bloków dokumentacji"""
        classes = el.get('class', [])

        # Bloki ostrzeżeń
        if 'warning' in classes:
            return f'\n> ⚠️ **Ostrzeżenie**: {text}\n'

        # Bloki informacji
        if 'info' in classes or 'note' in classes:
            return f'\n> 💡 **Uwaga**: {text}\n'

        return text

def scrape_docs(url):
    """Skrapuj i konwertuj stronę dokumentacji"""
    response = requests.get(url)
    markdown = DocsConverter().convert(response.text)
    return markdown

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

Przypadek użycia 4: Konwersja newsletterów na archiwum Markdown

Wymagania: Konwersja HTML newsletterów na czytelny Markdown

Zalecany: html2text z konkretną konfiguracją

import html2text
import email
from pathlib import Path

def convert_newsletter(email_file):
    """Konwertuj HTML e-mail na Markdown"""
    # Parsuj e-mail
    with open(email_file, 'r') as f:
        msg = email.message_from_file(f)

    # Pobierz część 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

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

    # Konwertuj
    markdown = h.handle(html_content)

    # Dodaj metadane
    subject = msg.get('Subject', 'Brak tytułu')
    date = msg.get('Date', '')

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

    return output

# Przetwarzaj archiwum newsletterów
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')

Rekomendacje według scenariusza

Dalej nie jesteś pewien, który pakiet wybrać? Oto przewodnik oparty na konkretnych przypadkach użycia.

Dla skrapowania sieci i przygotowania danych do LLM

Zwycięzca: trafilatura

Trafilatura wyróżnia się w ekstrakcji czystej treści, usuwając boilerplate. Idealny do:

  • Budowania zestawów danych treningowych LLM
  • Agregacji treści
  • Zbierania artykułów naukowych
  • Ekstrakcji artykułów nowin

Dla migracji Hugo/Jekyll

Zwycięzca: html2md

Asynchroniczne przetwarzanie i generowanie frontmatter sprawia, że duże migracje są szybkie i łatwe:

  • Konwersje wsadowe
  • Automatyczne wyodrębnianie metadanych
  • Generowanie frontmatter YAML
  • Dostosowanie poziomu nagłówka

Dla niestandardowej konwersji

Zwycięzca: markdownify

Dziedziczenie konwertera umożliwia pełną kontrolę:

  • Niestandardowe procedury obsługi tagów
  • Konwersje specyficzne dla dziedziny
  • Specjalne wymagania formatowania
  • Integracja z istniejącym kodem BeautifulSoup

Dla bezpiecznych systemów produkcyjnych

Zwycięzca: html-to-markdown

Nowoczesny, typowo bezpieczny i pełny funkcjonalności:

  • Pełne wsparcie HTML5
  • Komprehensywne wskazówki typu
  • Zaawansowana obsługa tabel
  • Aktywne utrzymanie

Dla prostych, stabilnych konwersji

Zwycięzca: html2text

Gdy potrzebujesz czegoś, co „prosto działa”:

  • Brak zależności
  • Przetestowane w praktyce
  • Rozszerzona konfiguracja
  • Szeroka obsługa platform

Najlepsze praktyki przygotowania danych dla LLM

Niezależnie od wyboru biblioteki, przestrzeganie tych najlepszych praktyk zapewni wysokiej jakości wynik w formacie Markdown zoptymalizowany do przetwarzania przez modele językowe. Te wzorce udowodniły swoje znaczenie w produkcyjnych przepływach pracy przetwarzających miliony dokumentów.

1. Oczyszczanie przed konwersją

Zawsze usuwaj niechciane elementy przed konwersją, aby uzyskać czystszy wynik i lepszą wydajność:

from bs4 import BeautifulSoup
import trafilatura

def clean_and_convert(html):
    """Usuń niechciane elementy przed konwersją"""
    soup = BeautifulSoup(html, 'html.parser')

    # Usuń niechciane elementy
    for element in soup(['script', 'style', 'nav', 'footer', 'header', 'aside']):
        element.decompose()

    # Usuń reklamy i śledzenie
    for element in soup.find_all(class_=['ad', 'advertisement', 'tracking']):
        element.decompose()

    # Konwertuj oczyszczony HTML
    markdown = trafilatura.extract(
        str(soup),
        output_format='markdown'
    )

    return markdown

2. Normalizacja białych znaków

Różne konwertery obsługują białe znaki inaczej. Normalizuj wynik, aby zapewnić spójność w całym zbiorze danych:

import re

def normalize_markdown(markdown):
    """Oczyszczanie odstępow w markdownie"""
    # Usuń wielokrotne puste linie
    markdown = re.sub(r'\n{3,}', '\n\n', markdown)

    # Usuń końcowe białe znaki
    markdown = '\n'.join(line.rstrip() for line in markdown.split('\n'))

    # Upewnij się, że jest tylko jedna linia na końcu
    markdown = markdown.rstrip() + '\n'

    return markdown

3. Walidacja wyników

Kontrola jakości jest kluczowa. Zaimplementuj walidację, aby wczesnie wykrywać błędy konwersji:

def validate_markdown(markdown):
    """Walidacja jakości markdownu"""
    issues = []

    # Sprawdź pozostałe fragmenty HTML
    if '<' in markdown and '>' in markdown:
        issues.append("Wykryto tagi HTML")

    # Sprawdź uszkodzone linki
    if '[' in markdown and ']()' in markdown:
        issues.append("Wykryto pusty link")

    # Sprawdź nadmiarowe bloki kodu
    code_block_count = markdown.count('```')
    if code_block_count % 2 != 0:
        issues.append("Nie zamknięty blok kodu")

    return len(issues) == 0, issues

4. Szablon przetwarzania w partii

Przy przetwarzaniu dużych zbiorów dokumentów, użyj tego gotowego do produkcji szablonu z odpowiednim obsługą błędów, logowaniem i przetwarzaniem równoległym:

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):
    """Przetwarzanie pojedynczego pliku 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:
            # Normalizacja
            markdown = normalize_markdown(markdown)

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

            # Zapis
            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"Błąd podczas przetwarzania {html_path}: {e}")
        return False

def batch_convert(input_dir, max_workers=4):
    """Konwersja wszystkich plików HTML w katalogu"""
    html_files = list(Path(input_dir).rglob('*.html'))
    logger.info(f"Znaleziono {len(html_files)} plików HTML")

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

    success_count = sum(results)
    logger.info(f"Pomyślnie przekonwertowano {success_count}/{len(html_files)} plików")

# Użycie
batch_convert('./html_docs', max_workers=8)

Podsumowanie

Eko system Pythona oferuje dojrzałe, gotowe do produkcji narzędzia do konwersji HTML na Markdown, każde zoptymalizowane dla różnych scenariuszy. Twój wybór powinien być zgodny z Twoimi konkretnymi wymaganiami:

  • Szybkie konwersje: Użyj html2text z powodu jego prostoty i braku zależności
  • Własna logika: Użyj markdownify dla maksymalnej elastyczności poprzez dziedziczenie
  • Przeglądanie stron internetowych: Użyj trafilatura dla inteligentnego wydobycia treści z usuwaniem zbędnych elementów
  • Wielkoskalowe migracje: Użyj html2md dla asynchronicznej wydajności przy dużych projektach
  • Systemy produkcyjne: Użyj html-to-markdown dla bezpieczeństwa typów i pełnego wsparcia dla HTML5
  • Zachowanie znaczenia: Użyj domscribe dla zachowania struktury semantycznej HTML5

Zalecenia dla przepływów pracy LLM

Dla przepływów pracy przygotowania danych do LLM zaleca się podejście dwuetapowe:

  1. Zacznij od trafilatura dla początkowego wydobycia treści – inteligentnie usuwa nawigację, reklamy i zbędne elementy, zachowując główną treść
  2. Zwróć się do html-to-markdown dla skomplikowanych dokumentów wymagających dokładnego zachowania struktury, takich jak dokumentacja techniczna z tabelami i blokami kodu

Ta kombinacja skutecznie radzi sobie z 95% rzeczywistych scenariuszy.

Kolejne kroki

Aby uzyskać więcej porad dotyczących Markdown, LaTeX, przetwarzania PDF i przepływów pracy druku dokumentów, zobacz Narzędzia dokumentacyjne w 2026: Markdown, LaTeX, PDF i przepływy pracy druku.

Wszystkie te narzędzia (z wyjątkiem html2text) są aktywnie utrzymywane i gotowe do produkcji. Lepszym wyborem jest:

  1. Zainstalowanie 2–3 bibliotek pasujących do Twojego przypadku użycia
  2. Testowanie ich przy użyciu Twoich rzeczywistych przykładów HTML
  3. Testowanie wydajności przy typowych rozmiarach dokumentów
  4. Wybieranie na podstawie jakości wyników, a nie tylko prędkości

Eko system Pythona dla konwersji HTML na Markdown dojrzał znacznie, i nie zrobisz błędu wybierając dowolne z tych narzędzi dla ich przeznaczenia.

Dodatkowe zasoby

Uwaga: Ta analiza opiera się na analizie oficjalnej dokumentacji, opinii społeczności i architekturze bibliotek. Charakterystyka wydajności jest reprezentatywna dla typowych wzorców użycia. Dla konkretnych przypadków użycia przeprowadź własne testy wydajnościowe przy użyciu rzeczywistych przykładów HTML.

Inne przydatne artykuły