Konwersja HTML na Markdown za pomocą Pythona: Kompletny przewodnik
Python do konwersji HTML na czysty, gotowy do użycia przez LLM Markdown
Konwersja HTML na Markdown to podstawowe zadanie w współczesnych przepływach pracy programistycznych, szczególnie przygotowując treści internetowe do Large Language Models (LLM), systemów dokumentacji lub generatorów stron statycznych takich jak Hugo.
Choć HTML jest zaprojektowany do przeglądarek internetowych z bogatym stylizowaniem i strukturą, Markdown oferuje czysty, czytelny format, który jest idealny do przetwarzania tekstu, kontroli wersji i konsumpcji przez AI. Jeśli jesteś nowy w składni Markdown, sprawdź nasz Markdown Cheatsheet dla kompletnego odniesienia.

W tej szczegółowej recenzji omówimy sześć pakietów Pythona do konwersji HTML na Markdown, oferując praktyczne przykłady kodu, benchmarki wydajnościowe i rzeczywiste przypadki użycia. Niezależnie od tego, czy budujesz pipeline treningowy LLM, czy migrujesz bloga do Hugo, czy skrapujesz dokumentację, znajdziesz idealne narzędzie do swojej pracy.
Alternatywny podejście: Jeśli potrzebujesz bardziej inteligentnego wyodrębniania treści z zrozumieniem semantycznym, możesz również rozważyć konwersję HTML na Markdown za pomocą LLM i Ollama, która oferuje AI-powered konwersję dla złożonych układów.
Co się nauczysz:
- Szczegółowa analiza 6 bibliotek z zaletami i wadami każdej
- Benchmarki wydajnościowe z rzeczywistymi przykładami HTML
- Przykłady kodu gotowych do użycia w typowych przypadkach użycia
- Najlepsze praktyki dla przepływów pracy przygotowania danych do LLM
- Konkretnne rekomendacje w zależności od 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:
- Efektywność tokenów: Markdown wykorzystuje znacznie mniej tokenów niż HTML dla tej samej treści
- Jasność semantyczna: Markdown zachowuje strukturę dokumentu bez zbędnych tagów
- Czytelność: I ludzie, i LLM mogą łatwo przetwarzać składnię Markdown
- Spójność: Standardowy format zmniejsza niejednoznaczność we wejściach modelu
- Przechowywanie: Mniejsze rozmiary plików dla danych treningowych i okien kontekstowych
Zalety Markdown rozciągają 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 wiedzą osobistą.
TL;DR - Macierz szybkiego porównania
Jeśli jesteś w pośpiechu, oto kompletny przegląd wszystkich sześciu bibliotek na szybko. Ta tabela pomoże Ci szybko zidentyfikować, które narzędzie odpowiada Twoim konkretnym wymaganiom:
| Funkcja | html2text | markdownify | html-to-markdown | trafilatura | domscribe | html2md |
|---|---|---|---|---|---|---|
| Wsparcie HTML5 | Częściowe | Częściowe | Pełne | Pełne | Pełne | Pełne |
| Typy wskazówek | Nie | Nie | Tak | Częściowe | Nie | Częściowe |
| Własne procedury obsługi | Ograniczone | Wspaniałe | Dobre | Ograniczone | Dobre | Ograniczone |
| Wsparcie dla tabel | Podstawowe | Podstawowe | Zaawansowane | Dobre | Dobre | Dobre |
| Wsparcie asynchroniczne | Nie | Nie | Nie | Nie | Nie | Tak |
| Wyodrębnianie treści | Nie | Nie | Nie | Wspaniałe | Nie | Dobre |
| Wyodrębnianie metadanych | Nie | Nie | Tak | Wspaniałe | Nie | Tak |
| Narzędzie CLI | Nie | Nie | Tak | Tak | Nie | Tak |
| Szybkość | Średnia | Wolna | Szybka | Bardzo szybka | Średnia | Bardzo szybka |
| Aktywne rozwijanie | Nie | 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 typów? → html-to-markdown
- Potrzebujesz prostoty? → html2text
- Potrzebujesz wyodrębniania treści? → trafilatura
Konkurenci: Porównanie 6 pakietów Pythona
Zanurzmy się głębiej w każdy z bibliotek z praktycznymi przykładami kodu, opcjami konfiguracji i rzeczywistymi wskazówkami. Każda sekcja zawiera instrukcje instalacji, wzorce użycia i szczere oceny zalet i ograniczeń.
1. html2text - Klasyczna opcja
Oryginalnie opracowany przez Aaron Swartz, html2text był stalowym elementem ekosystemu Pythona przez ponad dekada. Skupia się na generowaniu czystego, czytelnego kodu 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 zawijaj linii
html_content = """
<h1>Witaj w Scrapingu Internetowym</h1>
<p>To jest <strong>kompleksowy przewodnik</strong> po wyodrębnianiu treści.</p>
<ul>
<li>Łatwe w użyciu</li>
<li>Testowane 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 Scrapingu Internetowym
To jest **kompleksowy przewodnik** po wyodrębnianiu treści.
* Łatwe w użyciu
* Testowane w praktyce
* Szeroko stosowane
[Dowiedz się więcej](https://example.com)
Zaawansowana konfiguracja:
import html2text
h = html2text.HTML2Text()
# Pominięcie konkretnych elementów
h.ignore_links = True
h.ignore_images = True
# Kontrola formatowania
h.body_width = 80 # Zawijaj przy 80 znakach
h.unicode_snob = True # Użyj znaków unicode
h.emphasis_mark = '*' # Użyj * dla 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
- 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 utrzymywane (ostatnia duża aktualizacja w 2020 roku)
- Tylko przetwarzanie jednowątkowe
Najlepsze do: Prostych dokumentów HTML, systemów legacy, kiedy stabilność jest kluczowa
2. markdownify - Opcja elastyczna
markdownify korzysta z BeautifulSoup4, aby zapewnić elastyczne parsowanie HTML z dostosowalną obsługą tagów.
Instalacja:
pip install markdownify
Podstawowe użycie:
from markdownify import markdownify as md
html = """
<article>
<h2>Nowoczesne rozwój internetowy</h2>
<p>Budowanie z <code>Python</code> i <em>nowoczesnymi frameworkami</em>.</p>
<blockquote>
<p>Prostota to najwyższa sofistykacja.</p>
</blockquote>
</article>
"""
markdown = md(html)
print(markdown)
Wyjście:
## Nowoczesne rozwój internetowy
Budowanie z `Python` i *nowoczesnymi frameworkami*.
> Prostota to najwyższa sofistykacja.
Zaawansowane użycie z dostosowanymi procedurami obsługi:
from markdownify import MarkdownConverter
class CustomConverter(MarkdownConverter):
"""
Utwórz niestandardowy konwerter z konkretną obsługą tagów
"""
def convert_img(self, el, text, convert_as_inline):
"""Niestandardowy handler obrazu z tekstem alternatywnym"""
alt = el.get('alt', '')
src = el.get('src', '')
title = el.get('title', '')
if title:
return f''
return f''
def convert_pre(self, el, text, convert_as_inline):
"""Zwiększone obsługę 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 Markdown i podświetlania składni, zobacz nasz przewodnik Użycie bloków kodu Markdown.
Wybórowy konwersja tagów:
from markdownify import markdownify as md
# Usuń konkretne tagi całkowicie
markdown = md(html, strip=['script', 'style', 'nav'])
# Konwertuj tylko konkretne 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
- Ograniczona wbudowana obsługa tabel
Najlepsze do: Niestandardowa konwersja, projekty już korzystające z BeautifulSoup4
3. html-to-markdown - Nowoczesna potęga
html-to-markdown to kompletnie typowany, nowoczesny pakiet z pełnym wsparciem dla 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
# Konwertuj w partii
find ./html_files -name "*.html" -exec html-to-markdown {} -o ./markdown_files/{}.md \;
Zalety:
- Pełne wsparcie dla HTML5 w tym elementów semantycznych
- Typowe bezpieczeństwo z komprehensywnymi wskazówkami typów
- 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ększy zasób zależności
- Wyższy poziom nauki
Najlepsze do: Złożonych dokumentów HTML5, projektów typowo bezpiecznych, systemów produkcyjnych
4. trafilatura - Ekspert w wyodrębnianiu treści
trafilatura nie jest tylko konwerterem HTML na Markdown – to inteligentna biblioteka wyodrębniania treści specjalnie zaprojektowana do skrapowania internetowego i ekstrakcji artykułów.
Instalacja:
pip install trafilatura
Podstawowe użycie:
import trafilatura
# Pobierz i wyodrębnij z adresu 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 cURL Cheatsheet 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 w partii:
import trafilatura
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path
def process_url(url):
"""Wyodrębnij markdown z adresu URL"""
downloaded = trafilatura.fetch_url(url)
if downloaded:
return trafilatura.extract(
downloaded,
output_format='markdown',
include_links=True,
include_images=True
)
return None
# Przetwarzaj wiele adresów URL równolegle
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 (usuwanie zbędnych elementów)
- Wbudowane pobieranie URL z solidnym obsługą błędów
- Wyodrębnianie metadanych (tytuł, autor, data)
- Wykrywanie języka
- Optymalizacja dla artykułów i blogów
- Szybkie parsowanie oparte na C
Wady:
- Może zbyt bardzo usuwać treści dla ogólnego HTML
- Skupia się na ekstrakcji artykułów (nie jest ogólnym narzędziem)
- Złożoność konfiguracji dla przypadków granicznych
Najlepsze do: Skrapowanie internetowe, ekstrakcja artykułów, przygotowanie danych treningowych dla LLM
5. domscribe - Przechowujący znaczenie
domscribe skupia się na zachowaniu znaczenia 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ę semantyczną HTML5
- Dobrze radzi sobie z nowoczesnymi komponentami sieciowymi
- Czysty projekt API
Wady:
- Nadal w wczesnym rozwoju (API może się zmienić)
- Mniejsza 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, kiedy 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óry inne narzędzia nie priorytetyzują.
6. html2md - Potęga asynchroniczna
html2md jest zaprojektowany do wysokiej wydajnościowej konwersji w partii z asynchronicznym przetwarzaniem.
Instalacja:
pip install html2md
Użycie wiersza poleceń:
# Konwertuj cały katalog
m1f-html2md convert ./website -o ./docs
# Z ustawieniami niestandardowymi
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():
"""Asynchroniczne przetwarzanie w partii"""
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 Hugo!)
- Wykrywanie języka kodu
- Wsparcie dla przetwarzania równoległego
Wady:
- Wymaga Pythona 3.10+
- Skupia się na CLI (mniej elastyczny API)
- Dokumentacja mogłaby być bardziej kompletna
Najlepsze do: Dużych migracji, konwersji w partii, migracji Hugo/Jekyll
Benchmarkowanie wydajności
Wydajność ma znaczenie, szczególnie przy przetwarzaniu tysięcy dokumentów dla treningu LLM lub dużych migracji. Zrozumienie różnic w prędkości pomiedzy bibliotekami pomaga w podejmowaniu świadomych decyzji dla Twojej pracy.
Porównanie wydajności:
Na podstawie typowych wzorców użycia, oto jak te biblioteki porównują się w trzech realistycznych scenariuszach:
- Prosty HTML: Prosty wpis blogowy z tekstem, nagłówkami i linkami (5KB)
- Złożony HTML: Dokumentacja techniczna z zagnieżdżonymi tabelami i blokami kodu (50KB)
- Rzeczywista strona internetowa: Pełna strona internetowa w tym nawigacja, stopka, boczny panel i reklamy (200KB)
Oto przykład kodu benchmarkowania, którego 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):
"""Benchmarkuj szybkość 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': html2text_time,
'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 | Najwolniejsza |
| markdownify | Wolniejsza | Wolniejsza | Najwolniejsza |
| html-to-markdown | Szybka | Szybka | Szybka |
| trafilatura | Szybka | Bardzo szybka | Bardzo szybka |
| html2md (asynchroniczny) | Bardzo szybki | Bardzo szybki | Najbardziej szybki |
Główne obserwacje:
html2mditrafilaturasą najbardziej szybkie dla złożonych dokumentów, idealne do przetwarzania w partiihtml-to-markdownoferuje najlepszy balans szybkości i funkcji dla użycia produkcyjnegomarkdownifyjest wolniejszy, ale najbardziej elastyczny – koszt-wartość warte, kiedy potrzebujesz niestandardowych procedur obsługihtml2textpokazuje swoje wiekowe ograniczenia z wolniejszą wydajnością, ale nadal 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 będzie działać dobrze. Skup się na funkcjach i możliwości dostosowania zamiast na wydajności.
Przykłady zastosowań w praktyce
Teoria jest pomocna, ale praktyczne przykłady pokazują, jak te narzędzia działają w środowisku produkcyjnym. Oto cztery typowe scenariusze z kompletnym, gotowym do użycia kodem, który możesz dostosować do własnych projektów.
Przypadek użycia 1: Przygotowanie danych treningowych dla LLM
Wymagania: Wyodrębnienie czystego tekstu z tysięcy stron dokumentacji
Zalecane: trafilatura + przetwarzanie równoległe
import trafilatura
from pathlib import Path
from concurrent.futures import ProcessPoolExecutor
def process_html_file(html_path):
"""Konwersja pliku HTML na markdown"""
html = Path(html_path).read_text(encoding='utf-8')
markdown = trafilatura.extract(
html,
output_format='markdown',
include_links=False, # Usuń, aby uzyskać czystsze dane treningowe
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: Przeniesienie bloga WordPress do Hugo z frontmatter
Zalecane: html2md CLI
Hugo to popularny generator statycznych stron internetowych, który korzysta z Markdown do zawartości. Dla dodatkowych wskazówek specyficznych dla Hugo, sprawdź nasz Hugo Cheat Sheet oraz dowiedz się, jak dodać strukturalne oznaczenia danych do Hugo w celu poprawienia SEO.
# Konwersja wszystkich wpisów 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):
"""Konwersja HTML z WordPressa na markdown dla Hugo"""
html = Path(html_file).read_text()
# Wyodrębnienie tytułu i daty 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'
# Konwersja na markdown
options = Options(strip_tags=['script', 'style', 'nav', 'footer'])
markdown = convert(html, options=options)
# Dodanie frontmatter dla Hugo
frontmatter = {
'title': title,
'date': '2024-10-24',
'draft': False,
'tags': []
}
output = f"---\n{yaml.dump(frontmatter)}---\n\n{markdown}"
# Zapis
output_file = html_file.replace('.html', '.md')
Path(output_file).write_text(output, encoding='utf-8')
# Przetwarzanie wszystkich wpisów
for html_file in Path('./wordpress-export').glob('*.html'):
migrate_post(html_file)
Przypadek użycia 3: Skraper dokumentacji z niestandardowym formatowaniem
Wymagania: Scrapowanie technicznych dokumentacji z niestandardowym obsługą bloków kodu
Zalecane: 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ń dokumentacji samozhostowanych.
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świetleniem składni"""
code = el.find('code')
if code:
# Wyodrębnienie języka 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):
"""Scrapowanie i konwersja strony dokumentacji"""
response = requests.get(url)
markdown = DocsConverter().convert(response.text)
return markdown
# Użycie
docs_url = "https://docs.example.com/api-reference"
markdown = scrape_docs(docs_url)
Path('api-reference.md').write_text(markdown)
Przypadek użycia 4: Newsletter do archiwum Markdown
Wymagania: Konwersja HTML newsletterów do czytelnego markdown
Zalecane: html2text z konfiguracją specyficzną
import html2text
import email
from pathlib import Path
def convert_newsletter(email_file):
"""Konwersja HTML newslettera na markdown"""
# Parsowanie e-maila
with open(email_file, 'r') as f:
msg = email.message_from_file(f)
# Pobranie części 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
# Konfiguracja konwertera
h = html2text.HTML2Text()
h.ignore_images = False
h.images_to_alt = True
h.body_width = 0
h.protect_links = True
h.unicode_snob = True
# Konwersja
markdown = h.handle(html_content)
# Dodanie metadanych
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
# Przetwarzanie 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')
Zalecenia według scenariusza
Wciąż nie wiesz, który bibliotekę wybrać? Oto moja ostateczna wskazówka oparta na konkretnych przypadkach użycia. Te rekomendacje wynikają z doświadczenia praktycznego z każdej biblioteki w środowiskach produkcyjnych.
Dla scrapowania sieci i przetwarzania LLM
Zwycięzca: trafilatura
Trafilatura wyróżnia się w ekstrakcji czystego tekstu, jednocześnie usuwając zbędny materiał. Idealna do:
- Budowania zestawów danych treningowych dla LLM
- Agregacji treści
- Zbierania prac naukowych
- Ekstrakcji artykułów prasowych
Dla migracji Hugo/Jekyll
Zwycięzca: html2md
Asynchroniczne przetwarzanie i generowanie frontmatter sprawia, że masowe migracje są szybkie i łatwe:
- Konwersje w partii
- Automatyczne wyodrębnianie metadanych
- Generowanie frontmatter w formacie YAML
- Dostosowanie poziomu nagłówków
Dla niestandardowej logiki konwersji
Zwycięzca: markdownify
Dziedziczenie konwertera pozwala na pełną kontrolę:
- Niestandardowe obsługiwane tagi
- Konwersje specyficzne dla dziedziny
- Wymagania dotyczące formatowania
- Integracja z istniejącym kodem BeautifulSoup
Dla systemów produkcyjnych z typowym bezpieczeństwem
Zwycięzca: html-to-markdown
Nowoczesny, typowo bezpieczny i pełen funkcji:
- Pełna obsługa HTML5
- Kompleksowe wskazówki typowe
- Zaawansowane obsługiwane tabele
- Aktywne utrzymanie
Dla prostych, stabilnych konwersji
Zwycięzca: html2text
Kiedy potrzebujesz czegoś, co “działa”:
- Brak zależności
- Testowane w praktyce
- Rozszerzalna konfiguracja
- Wsparcie na szerokim zakresie platform
Najlepsze praktyki dla przetwarzania LLM
Niezależnie od wybranego przez Ciebie biblioteki, przestrzeganie tych najlepszych praktyk zapewni wysokiej jakości wyjście w formacie Markdown zoptymalizowane do konsumpcji przez LLM. Te wzorce udowodniły swoje znaczenie w przepływach pracy produkcyjnych przetwarzających miliony dokumentów.
1. Oczyść 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 wyczyszczony HTML
markdown = trafilatura.extract(
str(soup),
output_format='markdown'
)
return markdown
2. Normalizuj białe znaki
Różne konwertery obsługują białe znaki inaczej. Normalizuj wynik, aby zapewnić spójność w całym zbiorze:
import re
def normalize_markdown(markdown):
"""Wyczyść spacje 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 jedna linia końcowa
markdown = markdown.rstrip() + '\n'
return markdown
3. Waliduj wynik
Kontrola jakości jest kluczowa. Zaimplementuj walidację, aby wczesnie wykrywać błędy konwersji:
def validate_markdown(markdown):
"""Walidacja jakości markdownu"""
issues = []
# Sprawdź resztki 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ź nadmierną liczbę bloków 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
Podczas przetwarzania dużych zbiorów dokumentów, użyj tego gotowego do użycia szablonu z odpowiednim obsługiwaniem 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 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
Ekosystem Pythona oferuje dojrzałe, gotowe do użycia 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
html2textz powodu prostoty i braku zależności - Niestandardowa logika: Użyj
markdownifydla maksymalnej elastyczności poprzez dziedziczenie - Scrapowanie sieci: Użyj
trafilaturado inteligentnej ekstrakcji treści z usuwaniem zbędnych elementów - Masowe migracje: Użyj
html2mddo asynchronicznej wydajności w dużych projektach - Systemy produkcyjne: Użyj
html-to-markdowndo bezpieczeństwa typów i pełnej obsługi HTML5 - Zachowanie semantyki: Użyj
domscribedo utrzymania struktury semantycznej HTML5
Zalecenia dla przepływów pracy LLM
Dla przepływów pracy LLM, zaleca się dwuetapowy podejście:
- Zacznij od
trafilaturado początkowej ekstrakcji treści – inteligentnie usuwa nawigację, reklamy i zbędne elementy, zachowując główną treść - Przejdź do
html-to-markdowndla skomplikowanych dokumentów wymagających precyzyjnego zachowania struktury, takich jak dokumentacja techniczna z tabelami i blokami kodu
To połączenie skutecznie obsługuje 95% rzeczywistych scenariuszy.
Kolejne kroki
Wszystkie te narzędzia (oprócz html2text) są aktywnie utrzymywane i gotowe do użycia w środowisku produkcyjnym. Lepsze jest:
- Zainstalowanie 2-3 bibliotek dopasowanych do Twojego przypadku użycia
- Testowanie ich z Twoimi rzeczywistymi próbkami HTML
- Testowanie wydajności z typowymi rozmiarami dokumentów
- Wybór na podstawie jakości wyników, a nie tylko prędkości
Ekosystem Pythona dla konwersji HTML na Markdown dojrzał znacząco, i nie możesz się pomylić z żadnym z tych wyborów dla ich przeznaczenia.
Dodatkowe zasoby
- Dokumentacja html2text
- markdownify na PyPI
- html-to-markdown na GitHub
- Dokumentacja trafilatura
- Dokumentacja html2md
- domscribe na PyPI
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, uruchom własne testy wydajnościowe z Twoimi rzeczywistymi próbkami HTML.
Inne przydatne artykuły
- Markdown Cheatsheet
- Użycie bloków kodu Markdown
- Konwertowanie dokumentów Word na Markdown: kompletny przewodnik
- Konwertowanie HTML na Markdown za pomocą LLM i Ollama
- cURL Cheatsheet
- Hugo Cheatsheet
- Dodawanie strukturalnych oznaczeń danych do Hugo
- Dokuwiki - samozhostowany wiki i alternatywy
- Użycie Obsidian do zarządzania wiedzą osobistą