Преобразование HTML в Markdown с помощью Python: Полное руководство
Python для преобразования HTML в чистый, готовый для LLM Markdown
Преобразование HTML в Markdown — это фундаментальная задача в современных разработческих процессах, особенно при подготовке веб-контента для больших языковых моделей (LLM), систем документации или статических генераторов сайтов, таких как Hugo.
Хотя HTML разработан для веб-браузеров с богатым стилем и структурой, Markdown предлагает чистый, удобочитаемый формат, идеальный для обработки текста, системы контроля версий и потребления ИИ. Если вы новичок в синтаксисе Markdown, ознакомьтесь с нашим Шпаргалкой по Markdown для всестороннего справочника.

В этом всестороннем обзоре мы рассмотрим шесть пакетов Python для преобразования HTML в Markdown, предоставим практические примеры кода, бенчмарки производительности и реальные сценарии использования. Будь то создание конвейера обучения LLM, миграция блога в Hugo или скрейпинг документации, вы найдете идеальный инструмент для вашего рабочего процесса.
Альтернативный подход: Если вам нужна более интеллектуальная извлечение контента с семантическим пониманием, вы также можете рассмотреть преобразование HTML в Markdown с использованием LLM и Ollama, которое предлагает преобразование с использованием ИИ для сложных макетов.
Что вы узнаете:
- Подробное сравнение 6 библиотек с преимуществами и недостатками каждой
- Бенчмарки производительности с реальными образцами HTML
- Готовые к производству примеры кода для распространенных сценариев использования
- Лучшие практики для конвейеров предварительной обработки LLM
- Конкретные рекомендации на основе ваших требований
Почему Markdown для предварительной обработки LLM?
Прежде чем погружаться в инструменты, давайте поймем, почему Markdown особенно ценен для рабочих процессов LLM:
- Эффективность токенов: Markdown использует значительно меньше токенов, чем HTML для того же контента
- Семантическая ясность: Markdown сохраняет структуру документа без громоздких тегов
- Читаемость: И люди, и LLM могут легко разбирать синтаксис Markdown
- Согласованность: Стандартизированный формат снижает неоднозначность во входных данных модели
- Хранение: Меньшие размеры файлов для данных обучения и окон контекста
Гибкость Markdown выходит за рамки преобразования HTML — вы также можете преобразовать документы Word в Markdown для рабочих процессов документации или использовать его в системах управления знаниями, таких как Obsidian для управления личными знаниями.
TL;DR - Быстрая матрица сравнения
Если вы торопитесь, вот всестороннее сравнение всех шести библиотек сразу. Эта таблица поможет вам быстро определить, какой инструмент соответствует вашим конкретным требованиям:
| Функция | html2text | markdownify | html-to-markdown | trafilatura | domscribe | html2md |
|---|---|---|---|---|---|---|
| Поддержка HTML5 | Частичная | Частичная | Полная | Полная | Полная | Полная |
| Указания типов | Нет | Нет | Да | Частичная | Нет | Частичная |
| Пользовательские обработчики | Ограниченные | Отличные | Хорошие | Ограниченные | Хорошие | Ограниченные |
| Поддержка таблиц | Базовая | Базовая | Расширенная | Хорошая | Хорошая | Хорошая |
| Асинхронная поддержка | Нет | Нет | Нет | Нет | Нет | Да |
| Извлечение контента | Нет | Нет | Нет | Отличное | Нет | Хорошее |
| Извлечение метаданных | Нет | Нет | Да | Отличное | Нет | Да |
| Инструмент командной строки | Нет | Нет | Да | Да | Нет | Да |
| Скорость | Средняя | Медленная | Быстрая | Очень быстрая | Средняя | Очень быстрая |
| Активная разработка | Нет | Да | Да | Да | Ограниченная | Да |
| Версия Python | 3.6+ | 3.7+ | 3.9+ | 3.6+ | 3.8+ | 3.10+ |
| Зависимости | Нет | BS4 | lxml | lxml | BS4 | aiohttp |
Быстрое руководство по выбору:
- Нужна скорость? → trafilatura или html2md
- Нужна настройка? → markdownify
- Нужна безопасность типов? → html-to-markdown
- Нужна простота? → html2text
- Нужно извлечение контента? → trafilatura
Участники: сравнение 6 пакетов Python
Давайте углубимся в каждую библиотеку с практическими примерами кода, вариантами конфигурации и реальными инсайтами. Каждый раздел включает инструкции по установке, шаблоны использования и честные оценки сильных и слабых сторон.
1. html2text - Классический выбор
Разработанный Аароном Свартцем, html2text уже более десяти лет является основой экосистемы Python. Он сосредоточен на создании чистого, удобочитаемого вывода Markdown.
Установка:
pip install html2text
Базовое использование:
import html2text
# Создать экземпляр конвертера
h = html2text.HTML2Text()
# Настроить параметры
h.ignore_links = False
h.ignore_images = False
h.ignore_emphasis = False
h.body_width = 0 # Не переносить строки
html_content = """
<h1>Добро пожаловать в веб-скрейпинг</h1>
<p>Это **комплексное руководство** по извлечению контента.</p>
<ul>
<li>Легко в использовании</li>
<li>Проверено в боях</li>
<li>Широко принято</li>
</ul>
<a href="https://example.com">Узнать больше</a>
"""
markdown = h.handle(html_content)
print(markdown)
Вывод:
# Добро пожаловать в веб-скрейпинг
Это **комплексное руководство** по извлечению контента.
* Легко в использовании
* Проверено в боях
* Широко принято
[Узнать больше](https://example.com)
Расширенная конфигурация:
import html2text
h = html2text.HTML2Text()
# Пропустить определенные элементы
h.ignore_links = True
h.ignore_images = True
# Управление форматированием
h.body_width = 80 # Переносить на 80 символах
h.unicode_snob = True # Использовать юникод-символы
h.emphasis_mark = '*' # Использовать * для выделения вместо _
h.strong_mark = '**'
# Обработка таблиц
h.ignore_tables = False
# Защита предварительно отформатированного текста
h.protect_links = True
Преимущества:
- Зрелый и стабильный (более 15 лет разработки)
- Обширные варианты конфигурации
- Хорошо обрабатывает крайние случаи
- Нет внешних зависимостей
Недостатки:
- Ограниченная поддержка HTML5
- Может производить непостоянные отступы
- Не активно поддерживается (последнее крупное обновление в 2020 году)
- Только однопоточная обработка
Лучше всего для: Простых HTML-документов, устаревших систем, когда стабильность имеет первостепенное значение
Современное веб-разработка
Создание с использованием Python и современных фреймворков.
Простота — высшая степень изысканности.
Расширенное использование с пользовательскими обработчиками:
from markdownify import MarkdownConverter
class CustomConverter(MarkdownConverter):
"""
Создание пользовательского конвертера с конкретной обработкой тегов
"""
def convert_img(self, el, text, convert_as_inline):
"""Пользовательский обработчик изображений с текстом alt"""
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):
"""Улучшенная обработка блоков кода с детекцией языка"""
code = el.find('code')
if code:
# Извлечение языка из атрибута class (например, 'language-python')
classes = code.get('class', [''])
language = classes[0].replace('language-', '') if classes else ''
return f'\n```{language}\n{code.get_text()}\n```\n'
return f'\n```\n{text}\n```\n'
# Использование пользовательского конвертера
html = '<pre><code class="language-python">def hello():\n print("world")</code></pre>'
markdown = CustomConverter().convert(html)
print(markdown)
Для получения дополнительной информации о работе с блоками кода Markdown и синтаксическим выделением, см. наше руководство по Использованию блоков кода Markdown.
Селективная конвертация тегов:
from markdownify import markdownify as md
# Полное удаление определенных тегов
markdown = md(html, strip=['script', 'style', 'nav'])
# Конвертация только определенных тегов
markdown = md(
html,
heading_style="ATX", # Использование # для заголовков
bullets="-", # Использование - для маркеров
strong_em_symbol="*", # Использование * для выделения
)
Преимущества:
- Основано на BeautifulSoup4 (надежный парсинг HTML)
- Высокая настраиваемость через подклассирование
- Активное сопровождение
- Хорошая документация
Недостатки:
- Требуется зависимость BeautifulSoup4
- Может быть медленнее для больших документов
- Ограниченная встроенная поддержка таблиц
Лучше всего подходит для: пользовательской логики конвертации, проектов, уже использующих BeautifulSoup4
3. html-to-markdown - Современный мощный инструмент
html-to-markdown — это полностью типизированная, современная библиотека с всеобъемлющей поддержкой HTML5 и широкими возможностями конфигурации.
Установка:
pip install html-to-markdown
Базовое использование:
from html_to_markdown import convert
html = """
<article>
<h1>Техническая документация</h1>
<table>
<thead>
<tr>
<th>Функция</th>
<th>Поддержка</th>
</tr>
</thead>
<tbody>
<tr>
<td>HTML5</td>
<td>✓</td>
</tr>
<tr>
<td>Таблицы</td>
<td>✓</td>
</tr>
</tbody>
</table>
</article>
"""
markdown = convert(html)
print(markdown)
Расширенная конфигурация:
from html_to_markdown import convert, Options
# Создание пользовательских опций
options = Options(
heading_style="ATX",
bullet_style="-",
code_language_default="python",
strip_tags=["script", "style"],
escape_special_chars=True,
table_style="pipe", # Использование | для таблиц
preserve_whitespace=False,
extract_metadata=True, # Извлечение мета-тегов
)
markdown = convert(html, options=options)
Интерфейс командной строки:
# Конвертация одного файла
html-to-markdown input.html -o output.md
# Конвертация с опциями
html-to-markdown input.html \
--heading-style atx \
--strip-tags script,style \
--extract-metadata
# Пакетная конвертация
find ./html_files -name "*.html" -exec html-to-markdown {} -o ./markdown_files/{}.md \;
Преимущества:
- Полная поддержка HTML5, включая семантические элементы
- Типобезопасность с всеобъемлющими аннотациями типов
- Улучшенная обработка таблиц (объединенные ячейки, выравнивание)
- Возможности извлечения метаданных
- Активное развитие и современная кодовая база
Недостатки:
- Требуется Python 3.9+
- Больший объем зависимостей
- Более крутая кривая обучения
Лучше всего подходит для: сложных документов HTML5, типобезопасных проектов, производственных систем
4. trafilatura - Специалист по извлечению контента
trafilatura — это не просто конвертер HTML в Markdown, а интеллектуальная библиотека извлечения контента, специально разработанная для веб-скрейпинга и извлечения статей.
Установка:
pip install trafilatura
Базовое использование:
import trafilatura
# Загрузка и извлечение из URL
url = "https://example.com/article"
downloaded = trafilatura.fetch_url(url)
markdown = trafilatura.extract(downloaded, output_format='markdown')
print(markdown)
Примечание: Trafilatura включает встроенную загрузку URL, но для более сложных HTTP-операций вы можете найти наш cURL Cheatsheet полезным при работе с API или аутентифицированными конечными точками.
Расширенное извлечение контента:
import trafilatura
from trafilatura.settings import use_config
# Создание пользовательской конфигурации
config = use_config()
config.set("DEFAULT", "EXTRACTION_TIMEOUT", "30")
html = """
<html>
<head><title>Название статьи</title></head>
<body>
<nav>Навигационное меню</nav>
<article>
<h1>Основная статья</h1>
<p>Важный контент здесь.</p>
</article>
<aside>Реклама</aside>
<footer>Контент в подвале</footer>
</body>
</html>
"""
# Извлечение только основного контента
markdown = trafilatura.extract(
html,
output_format='markdown',
include_comments=False,
include_tables=True,
include_images=True,
include_links=True,
config=config
)
# Извлечение с метаданными
result = trafilatura.extract(
html,
output_format='markdown',
with_metadata=True
)
if result:
print(f"Название: {result.get('title', 'N/A')}")
print(f"Автор: {result.get('author', 'N/A')}")
print(f"Дата: {result.get('date', 'N/A')}")
print(f"\nКонтент:\n{result.get('text', '')}")
Пакетная обработка:
import trafilatura
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path
def process_url(url):
"""Извлечение markdown из URL"""
downloaded = trafilatura.fetch_url(url)
if downloaded:
return trafilatura.extract(
downloaded,
output_format='markdown',
include_links=True,
include_images=True
)
return None
# Обработка нескольких URL параллельно
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')
Преимущества:
- Интеллектуальное извлечение контента (удаляет шаблонный контент)
- Встроенная загрузка URL с надежной обработкой ошибок
- Извлечение метаданных (название, автор, дата)
- Детекция языка
- Оптимизировано для новостных статей и блогов
- Быстрый C-основанный парсинг
Недостатки:
- Может удалять слишком много контента для общего HTML
- Сфокусировано на извлечении статей (не универсальное)
- Сложность конфигурации для крайних случаев
Лучше всего подходит для: веб-скрейпинга, извлечения статей, подготовки данных для обучения LLM
5. domscribe - Сохранитель семантики
domscribe фокусируется на сохранении семантического смысла HTML при конвертации в Markdown.
Установка:
pip install domscribe
Базовое использование:
from domscribe import html_to_markdown
html = """
<article>
<header>
<h1>Понимание семантического HTML</h1>
<time datetime="2024-10-24">24 октября 2024</time>
</header>
<section>
<h2>Введение</h2>
<p>Семантический HTML придает <mark>смысл</mark> контенту.</p>
</section>
<aside>
<h3>Связанные темы</h3>
<ul>
<li>Доступность</li>
<li>SEO</li>
</ul>
</aside>
</article>
"""
markdown = html_to_markdown(html)
print(markdown)
Пользовательские опции:
from domscribe import html_to_markdown, MarkdownOptions
options = MarkdownOptions(
preserve_semantic_structure=True,
include_aria_labels=True,
strip_empty_elements=True
)
markdown = html_to_markdown(html, options=options)
Преимущества:
- Сохраняет семантическую структуру HTML5
- Хорошо обрабатывает современные веб-компоненты
- Чистый дизайн API
Недостатки:
- Все еще в ранней стадии разработки (API может измениться)
- Ограниченная документация по сравнению с проверенными альтернативами
- Меньшее сообщество и меньше примеров доступны
Лучше всего подходит для: документов HTML5 с семантикой, проектов, ориентированных на доступность, когда сохранение семантической структуры HTML5 критически важно
Примечание: Хотя domscribe новее и менее проверен, чем альтернативы, он заполняет конкретную нишу для сохранения семантики HTML, которую другие инструменты не приоритизируют.
6. html2md - Мощный асинхронный инструмент
html2md разработан для высокопроизводительных пакетных конвертаций с асинхронной обработкой.
Установка:
pip install html2md
Использование командной строки:
# Конвертация всего каталога
m1f-html2md convert ./website -o ./docs
# С пользовательскими настройками
m1f-html2md convert ./website -o ./docs \
--remove-tags nav,footer \
--heading-offset 1 \
--detect-language
# Конвертация одного файла
m1f-html2md convert index.html -o readme.md
Программное использование:
import asyncio
from html2md import convert_html
async def convert_files():
"""Асинхронная пакетная конвертация"""
html_files = [
'page1.html',
'page2.html',
'page3.html'
]
tasks = [convert_html(file) for file in html_files]
results = await asyncio.gather(*tasks)
return results
# Запуск конвертации
results = asyncio.run(convert_files())
Преимущества:
- Асинхронная обработка для высокой производительности
- Интеллектуальное обнаружение селекторов контента
- Генерация YAML frontmatter (отлично для Hugo!)
- Детекция языка кода
- Поддержка параллельной обработки
Недостатки:
- Требуется Python 3.10+
- Ориентирован на CLI (менее гибкий API)
- Документация могла бы быть более всеобъемлющей
Лучше всего подходит для: масштабных миграций, пакетных конвертаций, миграций Hugo/Jekyll
Производительность и тестирование
Производительность имеет значение, особенно при обработке тысяч документов для обучения LLM или крупномасштабных миграций. Понимание относительных различий в скорости между библиотеками помогает вам принимать обоснованные решения для вашего рабочего процесса.
Сравнительный анализ производительности:
На основе типичных паттернов использования, вот как эти библиотеки сравниваются в трех реалистичных сценариях:
- Простой HTML: Базовый блог с текстом, заголовками и ссылками (5КБ)
- Сложный HTML: Техническая документация с вложенными таблицами и блоками кода (50КБ)
- Реальный сайт: Полная веб-страница, включая навигацию, подвал, боковую панель и рекламу (200КБ)
Вот пример кода для тестирования, который вы можете использовать для проверки этих библиотек самостоятельно:
import time
import html2text
from markdownify import markdownify
from html_to_markdown import convert
import trafilatura
def benchmark(html_content, iterations=100):
"""Тестирование скорости конвертации"""
# html2text
start = time.time()
h = html2text.HTML2Text()
for _ in range(iterations):
_ = h.handle(html_content)
html2text_time = time.time() - start
# markdownify
start = time.time()
for _ in range(iterations):
_ = markdownify(html_content)
markdownify_time = time.time() - start
# html-to-markdown
start = time.time()
for _ in range(iterations):
_ = convert(html_content)
html_to_markdown_time = time.time() - start
# trafilatura
start = time.time()
for _ in range(iterations):
_ = trafilatura.extract(html_content, output_format='markdown')
trafilatura_time = time.time() - start
return {
'html2text': html2text_time,
'markdownify': markdownify_time,
'html-to-markdown': html_to_markdown_time,
'trafilatura': trafilatura_time
}
Типичные характеристики производительности (представительные относительные скорости):
| Пакет | Простой (5КБ) | Сложный (50КБ) | Реальный сайт (200КБ) |
|---|---|---|---|
| html2text | Умеренная | Медленнее | Медленнее |
| markdownify | Медленнее | Медленнее | Самый медленный |
| html-to-markdown | Быстрый | Быстрый | Быстрый |
| trafilatura | Быстрый | Очень быстрый | Очень быстрый |
| html2md (асинхронный) | Очень быстрый | Очень быстрый | Самый быстрый |
Ключевые наблюдения:
html2mdиtrafilaturaсамые быстрые для сложных документов, что делает их идеальными для пакетной обработкиhtml-to-markdownпредлагает лучший баланс скорости и функций для производственного использованияmarkdownifyмедленнее, но наиболее гибкий — компромисс стоит того, когда вам нужны пользовательские обработчикиhtml2textпоказывает свой возраст с более медленной производительностью, но остается стабильным для простых случаев использования
Примечание: Различия в производительности становятся значительными только при обработке сотен или тысяч файлов. Для случайных конвертаций любая библиотека будет работать нормально. Сосредоточьтесь на функциях и возможностях настройки вместо этого.
Реальные сценарии использования
Теория полезна, но практические примеры демонстрируют, как эти инструменты работают в производственной среде. Вот четыре распространенных сценария с полным, готовым к производству кодом, который вы можете адаптировать для своих проектов.
Сценарий 1: Подготовка данных для обучения LLM
Требование: Извлечение чистого текста из тысяч страниц документации
Рекомендуется: trafilatura + параллельная обработка
import trafilatura
from pathlib import Path
from concurrent.futures import ProcessPoolExecutor
def process_html_file(html_path):
"""Конвертация HTML-файла в markdown"""
html = Path(html_path).read_text(encoding='utf-8')
markdown = trafilatura.extract(
html,
output_format='markdown',
include_links=False, # Удалите для более чистых данных обучения
include_images=False,
include_comments=False
)
if markdown:
output_path = html_path.replace('.html', '.md')
Path(output_path).write_text(markdown, encoding='utf-8')
return len(markdown)
return 0
# Обработка 10,000 файлов параллельно
html_files = list(Path('./docs').rglob('*.html'))
with ProcessPoolExecutor(max_workers=8) as executor:
token_counts = list(executor.map(process_html_file, html_files))
print(f"Обработано {len(html_files)} файлов")
print(f"Общее количество символов: {sum(token_counts):,}")
Сценарий 2: Миграция блога в Hugo
Требование: Миграция блога WordPress в Hugo с frontmatter
Рекомендуется: html2md CLI
Hugo — это популярный генератор статических сайтов, который использует Markdown для контента. Для более специфичных для Hugo советов, ознакомьтесь с нашим Hugo Cheat Sheet и узнайте о Добавлении структурированных данных в Hugo для лучшего SEO.
# Конвертация всех постов с frontmatter
m1f-html2md convert ./wordpress-export \
-o ./hugo/content/posts \
--generate-frontmatter \
--heading-offset 0 \
--remove-tags script,style,nav,footer
Или программно:
from html_to_markdown import convert, Options
from pathlib import Path
import yaml
def migrate_post(html_file):
"""Конвертация HTML WordPress в markdown Hugo"""
html = Path(html_file).read_text()
# Извлечение заголовка и даты из HTML
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'html.parser')
title = soup.find('h1').get_text() if soup.find('h1') else 'Без названия'
# Конвертация в markdown
options = Options(strip_tags=['script', 'style', 'nav', 'footer'])
markdown = convert(html, options=options)
# Добавление frontmatter Hugo
frontmatter = {
'title': title,
'date': '2024-10-24',
'draft': False,
'tags': []
}
output = f"---\n{yaml.dump(frontmatter)}---\n\n{markdown}"
# Сохранение
output_file = html_file.replace('.html', '.md')
Path(output_file).write_text(output, encoding='utf-8')
# Обработка всех постов
for html_file in Path('./wordpress-export').glob('*.html'):
migrate_post(html_file)
Сценарий 3: Скрейпер документации с пользовательским форматированием
Требование: Скрейпинг технической документации с пользовательской обработкой блоков кода
Рекомендуется: markdownify с пользовательским конвертером
Этот подход особенно полезен для миграции документации из wiki-систем. Если вы управляете документацией, вам также может быть интересно DokuWiki - саморазмещаемый wiki и альтернативы для решений саморазмещаемой документации.
from markdownify import MarkdownConverter
import requests
class DocsConverter(MarkdownConverter):
"""Пользовательский конвертер для технической документации"""
def convert_pre(self, el, text, convert_as_inline):
"""Улучшенный блок кода с подсветкой синтаксиса"""
code = el.find('code')
if code:
# Извлечение языка из класса
classes = code.get('class', [])
language = next(
(c.replace('language-', '') for c in classes if c.startswith('language-')),
'text'
)
return f'\n```{language}\n{code.get_text()}\n```\n'
return super().convert_pre(el, text, convert_as_inline)
def convert_div(self, el, text, convert_as_inline):
"""Обработка специальных блоков документации"""
classes = el.get('class', [])
# Блоки предупреждений
if 'warning' in classes:
return f'\n> ⚠️ **Предупреждение**: {text}\n'
# Информационные блоки
if 'info' in classes or 'note' in classes:
return f'\n> 💡 **Примечание**: {text}\n'
return text
def scrape_docs(url):
"""Скрейпинг и конвертация страницы документации"""
response = requests.get(url)
markdown = DocsConverter().convert(response.text)
return markdown
# Использование
docs_url = "https://docs.example.com/api-reference"
markdown = scrape_docs(docs_url)
Path('api-reference.md').write_text(markdown)
Сценарий 4: Архив рассылки в Markdown
Требование: Конвертация HTML-рассылок в читаемый markdown
Рекомендуется: html2text с конкретной конфигурацией
import html2text
import email
from pathlib import Path
def convert_newsletter(email_file):
"""Конвертация HTML-письма в markdown"""
# Парсинг письма
with open(email_file, 'r') as f:
msg = email.message_from_file(f)
# Получение HTML-части
html_content = None
for part in msg.walk():
if part.get_content_type() == 'text/html':
html_content = part.get_payload(decode=True).decode('utf-8')
break
if not html_content:
return None
# Настройка конвертера
h = html2text.HTML2Text()
h.ignore_images = False
h.images_to_alt = True
h.body_width = 0
h.protect_links = True
h.unicode_snob = True
# Конвертация
markdown = h.handle(html_content)
# Добавление метаданных
subject = msg.get('Subject', 'Без темы')
date = msg.get('Date', '')
output = f"# {subject}\n\n*Дата: {date}*\n\n---\n\n{markdown}"
return output
# Обработка архива рассылок
for email_file in Path('./newsletters').glob('*.eml'):
markdown = convert_newsletter(email_file)
if markdown:
output_file = email_file.with_suffix('.md')
output_file.write_text(markdown, encoding='utf-8')
Рекомендации по сценариям
Все еще не уверены, какую библиотеку выбрать? Вот мое окончательное руководство на основе конкретных сценариев использования. Эти рекомендации основаны на практическом опыте работы с каждой библиотекой в производственных средах.
Для веб-скрейпинга и предварительной обработки LLM
Победитель: trafilatura
Trafilatura преуспевает в извлечении чистого контента, удаляя шаблонные элементы. Идеально для:
- Создания наборов данных для обучения LLM
- Агрегации контента
- Сбора исследовательских статей
- Извлечения новостных статей
Для миграции Hugo/Jekyll
Победитель: html2md
Асинхронная обработка и генерация frontmatter делают массовые миграции быстрыми и простыми:
- Пакетные конвертации
- Автоматическое извлечение метаданных
- Генерация YAML frontmatter
- Настройка уровня заголовков
Для пользовательской логики конвертации
Победитель: markdownify
Создавайте подклассы конвертера для полного контроля:
- Пользовательские обработчики тегов
- Конвертации, специфичные для домена
- Специальные требования к форматированию
- Интеграция с существующим кодом BeautifulSoup
Для типобезопасных производственных систем
Победитель: html-to-markdown
Современный, типобезопасный и функционально полный:
- Полная поддержка HTML5
- Подробные аннотации типов
- Улучшенная обработка таблиц
- Активное сопровождение
Для простых и стабильных конвертаций
Победитель: html2text
Когда вам нужно что-то, что “просто работает”:
- Нет зависимостей
- Проверено в боях
- Расширенная конфигурация
- Широкая поддержка платформ
Лучшие практики предварительной обработки LLM
Независимо от выбранной библиотеки, соблюдение этих лучших практик обеспечит высококачественный вывод Markdown, оптимизированный для потребления LLM. Эти шаблоны оказались необходимыми в производственных рабочих процессах, обрабатывающих миллионы документов.
1. Очистка перед преобразованием
Всегда удаляйте ненужные элементы перед преобразованием, чтобы получить более чистый вывод и лучшую производительность:
from bs4 import BeautifulSoup
import trafilatura
def clean_and_convert(html):
"""Удаление ненужных элементов перед преобразованием"""
soup = BeautifulSoup(html, 'html.parser')
# Удаление ненужных элементов
for element in soup(['script', 'style', 'nav', 'footer', 'header', 'aside']):
element.decompose()
# Удаление рекламы и трекинга
for element in soup.find_all(class_=['ad', 'advertisement', 'tracking']):
element.decompose()
# Преобразование очищенного HTML
markdown = trafilatura.extract(
str(soup),
output_format='markdown'
)
return markdown
2. Нормализация пробелов
Разные конвертеры по-разному обрабатывают пробелы. Нормализуйте вывод, чтобы обеспечить согласованность по всему корпусу:
import re
def normalize_markdown(markdown):
"""Очистка форматирования markdown"""
# Удаление множественных пустых строк
markdown = re.sub(r'\n{3,}', '\n\n', markdown)
# Удаление конечных пробелов
markdown = '\n'.join(line.rstrip() for line in markdown.split('\n'))
# Обеспечение одиночного переноса строки в конце
markdown = markdown.rstrip() + '\n'
return markdown
3. Проверка вывода
Контроль качества имеет решающее значение. Реализуйте проверку для выявления ошибок преобразования на ранних стадиях:
def validate_markdown(markdown):
"""Проверка качества markdown"""
issues = []
# Проверка на остатки HTML
if '<' in markdown and '>' in markdown:
issues.append("Обнаружены HTML-теги")
# Проверка на некорректные ссылки
if '[' in markdown and ']()' in markdown:
issues.append("Обнаружена пустая ссылка")
# Проверка на избыточное количество блоков кода
code_block_count = markdown.count('```')
if code_block_count % 2 != 0:
issues.append("Незакрытый блок кода")
return len(issues) == 0, issues
4. Шаблон пакетной обработки
При обработке больших коллекций документов используйте этот производственный шаблон с правильной обработкой ошибок, ведением журнала и параллельной обработкой:
from pathlib import Path
from concurrent.futures import ProcessPoolExecutor
import trafilatura
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def process_file(html_path):
"""Обработка одного HTML-файла"""
try:
html = Path(html_path).read_text(encoding='utf-8')
markdown = trafilatura.extract(
html,
output_format='markdown',
include_links=True,
include_images=False
)
if markdown:
# Нормализация
markdown = normalize_markdown(markdown)
# Проверка
is_valid, issues = validate_markdown(markdown)
if not is_valid:
logger.warning(f"{html_path}: {', '.join(issues)}")
# Сохранение
output_path = Path(str(html_path).replace('.html', '.md'))
output_path.write_text(markdown, encoding='utf-8')
return True
return False
except Exception as e:
logger.error(f"Ошибка при обработке {html_path}: {e}")
return False
def batch_convert(input_dir, max_workers=4):
"""Преобразование всех HTML-файлов в директории"""
html_files = list(Path(input_dir).rglob('*.html'))
logger.info(f"Найдено {len(html_files)} HTML-файлов")
with ProcessPoolExecutor(max_workers=max_workers) as executor:
results = list(executor.map(process_file, html_files))
success_count = sum(results)
logger.info(f"Успешно преобразовано {success_count}/{len(html_files)} файлов")
# Использование
batch_convert('./html_docs', max_workers=8)
Заключение
Экосистема Python предлагает зрелые, готовые к производству инструменты для преобразования HTML в Markdown, каждый из которых оптимизирован для различных сценариев. Ваш выбор должен соответствовать вашим конкретным требованиям:
- Быстрые преобразования: Используйте
html2textза его простоту и отсутствие зависимостей - Гибкая логика: Используйте
markdownifyдля максимальной гибкости через подклассификацию - Веб-скрейпинг: Используйте
trafilaturaдля интеллектуального извлечения контента с удалением шаблонов - Массовые миграции: Используйте
html2mdдля асинхронной производительности в крупных проектах - Производственные системы: Используйте
html-to-markdownдля безопасности типов и всеобъемлющей поддержки HTML5 - Сохранение семантики: Используйте
domscribeдля поддержания семантической структуры HTML5
Рекомендации для рабочих процессов LLM
Для рабочих процессов предварительной обработки LLM рекомендуется двухступенчатый подход:
- Начните с
trafilaturaдля первоначального извлечения контента — он интеллектуально удаляет навигацию, рекламу и шаблоны, сохраняя основной контент - Используйте
html-to-markdownдля сложных документов, требующих точного сохранения структуры, таких как техническая документация с таблицами и блоками кода
Это сочетание эффективно решает 95% реальных сценариев.
Следующие шаги
Все эти инструменты (кроме html2text) активно поддерживаются и готовы к производству. Лучше:
- Установить 2-3 библиотеки, соответствующие вашему случаю использования
- Проверить их с вашими реальными образцами HTML
- Замерить производительность с типичными размерами документов
- Выбрать на основе качества вывода, а не только скорости
Экосистема Python для преобразования HTML в Markdown значительно созрела, и вы не ошибетесь с любым из этих выборов для их предназначенных случаев использования.
Дополнительные ресурсы
- Документация html2text
- markdownify на PyPI
- html-to-markdown на GitHub
- Документация trafilatura
- Документация html2md
- domscribe на PyPI
Примечание: Это сравнение основано на анализе официальной документации, обратной связи сообщества и архитектуры библиотек. Характеристики производительности представляют типичные паттерны использования. Для конкретных случаев использования запускайте собственные бенчмарки с вашими реальными образцами HTML.
Другие полезные статьи
- Шпаргалка по Markdown
- Использование блоков кода в Markdown
- Преобразование документов Word в Markdown: Полное руководство
- Преобразование HTML-контента в Markdown с использованием LLM и Ollama
- Шпаргалка по cURL
- Шпаргалка по генератору статических сайтов Hugo
- Добавление разметки структурированных данных в Hugo
- Dokuwiki - самохостинговая вики и альтернативы
- Использование Obsidian для управления личными знаниями