Содержание
  1. Архитектура продукта и границы версии
  2. Учебный вход и ручной эталон
  3. Копируемый маршрут конвертации
  4. Точные поля и отрицательные случаи
  5. Чужие замеры и выводы о качестве
  6. Неизвестные значения и условия отказа
  7. Сверка оговорки и пар из plan.html
  8. Частые вопросы
Обзоры

MarkItDown: проверка результата конвертации

7 ноября 2026 · 11 минут чтения

MarkItDown: проверка результата конвертации сводится к сверке вывода с ручным эталоном. Конвертируйте один локальный HTML-файл, затем сравните заголовок, столбцы таблицы, пары значений и оговорку. Ниже — заданный вход, копируемый код и три отрицательные проверки.

Архитектура продукта и границы версии

MarkItDown — это библиотека Python и утилита командной строки для перевода разных файлов в Markdown. В документации проекта на GitHub перечислены поддерживаемые семейства: PDF, PowerPoint, Word, Excel, изображения с метаданными EXIF, аудио, HTML, текстовые форматы вроде CSV, JSON и XML, а также ZIP-архивы, ссылки YouTube и EPub. Там же сказано, что вывод рассчитан на текстовые анализаторы и может уступать решениям для полиграфической точности.

Границы версии важны для проверки. На странице пакета PyPI указана версия 0.1.9 с датой выпуска 21 октября 2026 года, лицензия MIT, два сопровождающих и требование Python от 3.10 до 3.14. Тот же источник перечисляет дополнительные наборы зависимостей: [all], [pdf], [docx], [pptx], [xlsx], [xls], [outlook], [az-doc-intel], [az-content-understanding], [audio-transcription], [youtube-transcription].

Архитектурно продукт собран вокруг конвертеров под конкретные форматы. Документация проекта описывает три уровня: встроенные конвертеры, интеграцию с Azure Document Intelligence и интеграцию с Azure Content Understanding. Встроенные конвертеры работают локально, извлекают данные по формату и не дают структурированных полей. Две облачные интеграции возвращают YAML-блок в начале документа и требуют оплачиваемых вызовов Azure. Для аудио и видео документация называет Content Understanding единственным вариантом с полноценной поддержкой.

Плагины расширяют набор конвертеров. Документация проекта сообщает, что сторонние плагины отключены по умолчанию, включаются флагом --use-plugins, а список установленных выводится командой markitdown --list-plugins. Отдельный плагин markitdown-ocr добавляет распознавание текста на встроенных изображениях в PDF, DOCX, PPTX и XLSX, используя тот же шаблон llm_client и llm_model, что и для описания картинок. Без переданного клиента плагин загружается, а распознавание пропускается.

Эта архитектура задаёт рамку проверки. Базовая конвертация локального HTML-файла опирается на встроенный конвертер. Она сохраняет структуру документа, которую видит парсер: заголовки, списки, таблицы, ссылки. Она не восстанавливает печатную вёрстку и не распознаёт текст со скана. Эти задачи решают облачные интеграции и плагин распознавания.

Учебный вход и ручной эталон

Для проверки нужен вход, полностью заданный заранее. Возьмём один локальный файл plan.html с заголовком, таблицей и примечанием в одном источнике:

HTML6 строк
<!doctype html><meta charset="utf-8">
<h1>Plans</h1>
<table><tr><th>plan</th><th>limit</th></tr>
<tr><td>Start</td><td>12</td></tr>
<tr><td>Team</td><td>30</td></tr></table>
<p>Limit per project, not per user.</p>

Файл учебный. Его обработка редакцией не выполнялась, поэтому ниже задан ручной эталон ожидаемого результата.

Ручной эталон перечисляет то, что читатель сверяет глазами:

Что проверяем Ожидаемое значение
Заголовок Plans
Столбцы таблицы plan и limit как отдельные столбцы
Первая строка Start → 12
Вторая строка Team → 30
Примечание Limit per project, not per user. целиком

Точное форматирование выходной таблицы не обещается. Markdown допускает разные способы выравнивания и разделителей, поэтому проверяем смысловые единицы: заголовок, два столбца, две пары значений и целое предложение примечания.

Почему вход собран именно так. Таблица и примечание лежат в одном HTML-файле. Оговорка Limit per project, not per user. физически присутствует в источнике, поэтому её появление в выводе проверяемо. Если бы примечание жило в отдельном CSV, его отсутствие в результате конвертации HTML ничего бы не доказывало.

Эталон держит три уровня. Первый — структура: заголовок и разделение на столбцы. Второй — данные: пары Start→12 и Team→30. Третий — текст: полное предложение с оговоркой. Проверка по всем трём уровням отличает полный результат от частичного.

Копируемый маршрут конвертации

Документация проекта показывает базовый вызов Python API: создать объект MarkItDown, вызвать метод конвертации и прочитать поле markdown результата. Для локального файла документация рекомендует узкий метод convert_local(), который читает файл с диска и не ходит по сети.

Копируемый код для нашего входа:

PYTHON5 строк
from markitdown import MarkItDown

converter = MarkItDown(enable_plugins=False)
result = converter.convert_local('plan.html')
print(result.markdown)

Необходимые файлы: plan.html в текущем каталоге и установленный пакет. Установка по документации проекта выполняется командой pip install 'markitdown[all]' либо из исходников через pip install -e 'packages/markitdown[all]'. Для HTML достаточно базовой установки, набор [all] добавляет зависимости остальных форматов.

Флаг enable_plugins=False оставляет включёнными только встроенные конвертеры. Это соответствует учебной задаче: проверяем базовый путь без сторонних расширений.

Документация проекта отдельно описывает безопасность. MarkItDown выполняет ввод-вывод с правами текущего процесса и получает доступ к тем же ресурсам, что open() или requests.get(). Для недоверенных входов документация советует проверять и ограничивать данные, а также вызывать самый узкий метод конвертации под задачу: convert_stream() или convert_local(). Метод convert() намеренно широкий и умеет работать с локальными файлами, удалёнными адресами и потоками байтов.

Командная строка даёт тот же результат. Документация проекта приводит форму markitdown path-to-file.pdf > document.md и вариант с флагом -o для указания выходного файла. Для нашего случая подойдёт markitdown plan.html -o plan.md.

Точные поля и отрицательные случаи

Проверка начинается с положительного сценария: заголовок Plans найден, столбцы plan и limit разделены, пары Start→12 и Team→30 на месте, примечание Limit per project, not per user. присутствует целиком.

Дальше идут три отрицательные проверки. Каждая ловит свой класс ошибки.

Отрицательный случай Что подменяем Какой класс ошибки ловим
Число 12 → 20 ошибка значения
Структура одна слитая колонка вместо двух ошибка структуры
Текст потеря not per user неполный источник

Первая проверка отвечает на вопрос, совпадают ли числа. Если в выводе стоит 20 там, где в источнике 12, приёмка останавливается: данные искажены.

Вторая проверка отвечает на вопрос, сохранилось ли разделение столбцов. Слитая колонка вида Start 12 теряет границу между полями, и таблица перестаёт быть таблицей.

Третья проверка отвечает на вопрос, дошёл ли текст примечания целиком. Обрывок Limit per project без not per user меняет смысл оговорки, поэтому результат нельзя принять.

Код проверки должен покрывать все три случая. Проверка только наличия Start и Team пропускает и подмену числа, и потерю структуры, и обрывок текста. Ниже — пример функции приёмки, которая сверяет вывод с эталоном:

PYTHON41 строка
import re

def check_markdown(md: str) -> list[str]:
    problems = []
    if 'Plans' not in md:
        problems.append('нет заголовка Plans')

    def cells(line: str) -> list[str]:
        if '|' not in line:
            return []
        return [part.strip().strip('`') for part in line.strip().strip('|').split('|')]

    lines = md.splitlines()
    table = None
    for index, line in enumerate(lines[:-1]):
        header = cells(line)
        separator = cells(lines[index + 1])
        if [part.lower() for part in header] != ['plan', 'limit']:
            continue
        if len(separator) != 2 or not all(re.fullmatch(r':?-{3,}:?', part) for part in separator):
            continue
        table = []
        for data_line in lines[index + 2:]:
            row = cells(data_line)
            if not row:
                break
            table.append(row)
        break

    if table is None or any(len(row) != 2 for row in table):
        problems.append('нет таблицы с двумя отдельными столбцами plan и limit')
    actual_pairs = [tuple(row) for row in (table or []) if len(row) == 2]
    if actual_pairs.count(('Start', '12')) != 1:
        problems.append('нет единственной пары Start -> 12')
    if actual_pairs.count(('Team', '30')) != 1:
        problems.append('нет единственной пары Team -> 30')
    if len(actual_pairs) != 2:
        problems.append('ожидались две строки данных')
    if 'Limit per project, not per user.' not in md:
        problems.append('примечание неполное')
    return problems

Функция возвращает список расхождений для заданного учебного Markdown с таблицей через вертикальные разделители. Пустой список означает, что структура этой таблицы, обе пары и примечание прошли заданные проверки. При другом представлении таблицы её структуру дополнительно сверяют вручную по исходному HTML.

Чужие замеры и выводы о качестве

В обзорах встречаются собственные маршруты. Christophe Avonture описывает личный рабочий процесс с Docker: сборку образа, файл compose и обёртку для конвертации документов. В его тексте видны артефакты извлечения вокруг переносов строк, поэтому код оттуда читают глазами по сохранённой странице и переносят осознанно.

UPGPTs публикует учебник с установкой через командную строку, конвертацией, пятью проверками вывода и пакетным циклом PowerShell. Этот материал даёт собственный чек-лист чистоты Markdown, поэтому утверждение, что конкуренты не проверяют результат, было бы неверным.

Оба маршрута считаются полноценными ответами на задачу конвертации. Наш контроль пар ячеек отличается: мы сверяем конкретные пары Start→12 и Team→30 и целое предложение примечания. Это собственные условия учебного примера.

Чужие замеры, тарифы и выводы о качестве на наш учебный вход не переносятся. Числа из чужих обзоров описывают их собственные файлы и настройки. Наш эталон задан здесь и проверяется здесь.

Неизвестные значения и условия отказа

Часть значений в выводе остаётся неизвестной до запуска. Точное форматирование таблицы, порядок строк, наличие пустых строк вокруг блока — эти детали зависят от версии и настроек. Их сверяют содержательно по исходному документу.

Результат нельзя принять в нескольких случаях. Число в паре не совпадает с источником. Столбцы слиты в один. Примечание оборвано или отсутствует. Заголовок потерян. Любой из этих признаков означает, что вывод неполон или искажён.

Отдельно стоит помнить о природе инструмента. Документация проекта прямо говорит, что вывод рассчитан на текстовые анализаторы и может уступать решениям для полиграфической точности. Базовая конвертация локального HTML сохраняет структуру, которую видит парсер. Восстановление печатной вёрстки и распознавание текста со скана решают другие компоненты: облачные интеграции Azure и плагин markitdown-ocr.

Если задача требует структурированных полей, документация проекта называет Azure Content Understanding: он возвращает YAML-блок с извлечёнными полями и поддерживает документы, изображения, аудио и видео. Каждый вызов для формата, направленного в этот сервис, оплачивается как обращение к Azure API.

Сверка оговорки и пар из plan.html

Финальный шаг — сверка английской оговорки и пар значений именно из plan.html. Оговорка звучит так: Limit per project, not per user. Она проверяется целиком, включая отрицание not per user. Обрывок без отрицания меняет смысл.

Пары значений сверяются по строкам таблицы:

Строка План Лимит
Первая Start 12
Вторая Team 30

Обе пары берутся из одного источника. Подмена 12 на 20 ломает первую строку. Потеря разделения столбцов ломает обе. Обрывок примечания ломает текстовый уровень.

Полный порядок приёмки:

  1. Открыть plan.html и убедиться, что таблица и примечание внутри одного файла.
  2. Запустить конвертацию через convert_local('plan.html').
  3. Сверить заголовок Plans.
  4. Сверить столбцы plan и limit.
  5. Сверить пары Start→12 и Team→30.
  6. Сверить примечание Limit per project, not per user. целиком.
  7. Прогнать три отрицательные проверки из таблицы выше.

Если все семь шагов проходят, результат принят. Если хотя бы один шаг даёт расхождение, вывод возвращается на доработку: проверяют вход, версию пакета и настройки конвертера.

Частые вопросы

Что такое MarkItDown и для чего он нужен?
MarkItDown — библиотека Python и утилита командной строки для перевода разных файлов в Markdown. Документация проекта перечисляет PDF, Office-форматы, изображения, аудио, HTML, текстовые форматы, архивы и ссылки YouTube. Вывод рассчитан на текстовые анализаторы и пайплайны обработки текста.

Как проверить результат конвертации MarkItDown?
Сверьте вывод с ручным эталоном по трём уровням: структура, данные, текст. Для учебного plan.html это заголовок Plans, столбцы plan и limit, пары Start→12 и Team→30, примечание Limit per project, not per user. целиком. Добавьте три отрицательные проверки на подмену числа, слияние столбцов и обрывок текста.

Почему стоит использовать convert_local вместо convert?
Документация проекта рекомендует вызывать самый узкий метод под задачу. Метод convert() намеренно широкий и умеет работать с локальными файлами, удалёнными адресами и потоками байтов. Метод convert_local() читает файл с диска и не ходит по сети, что сужает поверхность доступа.

Почему примечание может пропасть при конвертации?
Примечание пропадает, если его нет в исходном файле или если конвертер не разобрал содержащий его блок. В нашем учебном входе таблица и примечание лежат в одном HTML-файле, поэтому оговорка физически присутствует в источнике. Проверка целого предложения ловит обрывок текста.

Распознаёт ли MarkItDown текст со скана?
Базовая конвертация локального файла сохраняет структуру, которую видит парсер. Распознавание текста на изображениях добавляет плагин markitdown-ocr для PDF, DOCX, PPTX и XLSX. Для сканов и сложных таблиц документация проекта называет облачные интеграции Azure с оплачиваемыми вызовами.

Читайте также

3 материала