Преобразовать блокнот Jupyter в Markdown — бесплатно и приватно

Превратите блокнот .ipynb в чистый Markdown прямо в браузере. Сохраняет текст и код, убирает картинки в base64 и метаданные выполнения, которые раздувают исходный JSON.

Конвертация блокнота Jupyter в Markdown: оставить текст, выбросить обёртку

Блокнот — это два документа под одним именем файла. Есть то, что вы написали: заголовки, пояснения, код, напечатанный результат, ради которого всё и затевалось. И есть JSON-конверт, в котором формат всё это хранит. Откройте .ipynb в текстовом редакторе — и вы увидите конверт: каждая строка текста упакована в отдельный строковый литерал, "execution_count": 7 у каждой ячейки, пустые объекты "metadata": {} повсюду, а где-то в середине — четверть мегабайта base64, который отрисовывается в одну маленькую диаграмму рассеяния.

Конвертация в Markdown выбрасывает конверт и оставляет документ. Ваши markdown-ячейки и так были Markdown — они проходят насквозь без изменений. Ячейки с кодом становятся огороженными блоками с меткой языка ядра: это та форма, которую уже понимают любая модель, любой README и любой генератор статических сайтов. Перетащите .ipynb выше — конвертация произойдёт прямо в этой вкладке браузера, файл никуда не отправляется.

Где на самом деле лежит вес

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

  • Картинки вывода в base64. Каждый plt.show() записывает отрисованный PNG прямо в файл в виде base64. Одна фигура — это обычно 200–400 КБ символов. Блокнот с дюжиной графиков состоит в основном из графиков. Читателю текста они не говорят ровным счётом ничего.
  • HTML-представления датафреймов. Pandas выдаёт для одного и того же результата и text/plain, и text/html. HTML-версия тащит инлайновые стили и <table> с тегом на каждую ячейку, поэтому она бывает в двадцать раз больше текстовой, говоря ровно то же самое.
  • Кадры прогресс-баров. Цикл с tqdm пишет новую строку на каждое обновление, разделяя их возвратами каретки. В файле оседают сотни копий полоски, которая на экране показывалась один раз.
  • Метаданные каждой ячейки. По отдельности мелочь, вместе — нет: идентификаторы ячеек, счётчики выполнения, флаги свёрнутости и пустые объекты метаданных на несколько сотен ячеек складываются в заметный объём.

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

Почему огороженные блоки важнее, чем кажется

Самое полезное, что Markdown делает для блокнота, — явно размечает границу между текстом и кодом. В сыром JSON эта граница существует только как поле "cell_type" несколькими строками выше содержимого. Если сплющить файл небрежно, объяснение и код, который оно описывает, сливаются, и читателю — человеку или модели — приходится догадываться, где что, по одному лишь синтаксису.

Ограждение с меткой языка снимает эту загадку. Заодно оно переносит дальше язык ядра: конвертер читает language_info из метаданных блокнота, а при его отсутствии — kernelspec, поэтому блокнот на R или Julia получает метку R или Julia, а не тихо записывается в Python. Вывод получает собственный блок без метки под породившей его ячейкой, с простой строкой Output: впереди: причинно-следственная связь остаётся видимой, и при этом не выдумывается синтаксис, которого в Markdown нет.

Трейсбеки стоит оставлять

Есть соблазн вычистить вывод с ошибками вместе со всем остальным. Обычно это ошибка. Если вы отдаёте блокнот модели и спрашиваете, почему падает ячейка, трейсбек — это и есть весь вопрос. Неприятным в сыром виде его делает не содержимое, а ANSI-коды цвета, в которые IPython его заворачивает: escape-последовательности, которые в терминале выглядят как цвет, а везде ещё — как мусор вида ESC[0;31m.

Эти последовательности убираются, а текст трейсбека остаётся. Длинные сокращаются с середины, а не с конца: в глубоком стеке полезны первые и последние кадры, а двести строк внутренностей библиотек между ними — ровно то, что вы и так пролистали бы.

Блокноты внутри выгрузки репозитория

Та же конвертация работает внутри инструментов для GitHub, GitLab и локальной папки на этом сайте. Отметьте .ipynb в репозитории — и он попадёт в результат читаемыми ячейками, а не стеной JSON. Это важнее, чем звучит: в репозитории по анализу данных именно в блокнотах часто живут рассуждения, а до сих пор это были файлы, которые приходилось снимать с галочки, чтобы вывод оставался пригодным.

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

Старые блокноты тоже открываются

Четвёртая версия формата держит ячейки в массиве cells верхнего уровня. Третья, которая до сих пор разбросана по публичным репозиториям начала 2010-х, прячет их на уровень глубже внутри worksheets и называет поле с исходником input, а не source. Читаются обе формы. И тип вывода pyout из третьей версии — там, где в четвёртой стоит execute_result, — тоже.

Двух вещей здесь сознательно не делают. Виджеты блокнота — интерактивные ползунки и графики на ipywidgets — хранят состояние в отдельном блоке метаданных и в текст не превращаются ни во что осмысленное; заглушка просто сообщает, что виджет здесь был. И порядок выполнения ячеек сохраняется таким, каким он записан в файле, без сортировки по счётчику выполнения: блокнот читают в том порядке, в котором он написан.

Ничего не загружается на сервер

В блокнотах оседает то, о чём потом забывают: API-ключ, вставленный в ячейку во время отладки, строка подключения к базе, кусок боевых данных, распечатанный ради проверки джойна. Конвертация выполняется на JavaScript в этой вкладке. Здесь нет шага загрузки, нет копии на сервере и нечего потом просить удалить. Закройте вкладку — и всё исчезло.

Если вам нужен простой текст вместо Markdown — без ограждений, без структуры, только текст и код, — это делает конвертер блокнотов в текст, и выбранный файл переедет туда вместе с вами.