Ne v kontakte Asocial programmer's blog

Перенос постов из Drupal в Acrylamid

Feature image

В этой заметке я постараюсь рассказать о процессе переноса постов из старого блога на Drupal в новый на Acrylamid.

Прежде всего надо отдать ему должное — он из коробки неплохо умеет импортировать контент из произвольных движков через RSS или дамп в формате Wordpress. В простых случаях этого более, чем достаточно, но мне нужно было нечто большее.

Задачу перед собой я поставил так:

  • Перенести все посты и комментарии к ним.
  • Содержимое постов:
    • По возможности сохранить форматирование, в том числе и в самых старых постах, где я использовал bbcode.
    • Преобразовать html в markdown для тех случаев, где это возможно.
    • Заменить метки друпаловского модуля Inline на обычные ссылки.
    • Извлечь из тела поста «feature images» (не могу подобрать адекватный перевод :-( «Картинка для привлечения внимания»?..) и перенести в мета-информацию о посте, чтобы можно было правильно ее стилизовать и размещать без лишней мороки.
    • Аналогично поступить с музыкальными видео, которые я добавляю в конец поста в виде постскриптума, при этом необходимо сохранить и их правильные заголовки.
  • Структура адресов:
    • Сделать более-менее вменяемые URL постов. Например, транслитерированный кошмар вроде /blog/aleks/ispolzuem-svn-v-upravlenii-saitom-chast-pervaya-teoreticheskie-soobrazheniya превратить в более вменяемое /2008/Use-SVN-website-governance-Part-one-theoretical-considerations.html.
    • Скорректировать все внутренние ссылки на посты, чтобы они указывали на правильные адреса постов. Попутно — все внутренние ссылки, картинки и тому подобное с полными адресами виде http://nevkontakte.(com|org.ru)/whatever позаменять на просто /whatever, чтобы обезопасить себя от проблем в случае смены домена или, например, перехода на https.
    • Организовать редиректы со старых адресов постов на новые для поисковиков и внешних ссылок.

Желающие могут сразу отправляться изучать репозиторий на ГитХабе, в который я залил скрипты, выполняющие всю эту работу.

Для того, чтобы решить все эти задачи, мне нужно было добыть из базы данных Друпала сведения из четырех таблиц: drupal_node и drupal_node_revisions (посты, sql), drupal_comments (комментарии, sql) и drupal_url_alias («человекопонятные» адреса постов, sql). В целом процесс импорта выглядел примерно так: извлечение нужных данных из БД → конвертация базовой мета-информации в объекты Python → приведение её в формат, близкий к тому, что используется в Acrylamid → присвоение посту нового, аккуратного URL → применение цепочки фильтров к содержимому постов, решающих большую часть из поставленных задач → экспорт постов в формат Acrylamid → построение карт переадресаций для поисковиков и людей, приходящих по старым внешним ссылкам.

Генерация URL постов

Как я уже упомянул, на Drupal адрес поста генерировался путем банальной транслитерации русского заголовка поста, и выглядел он совершенно нечитаемо. Как мне сейчас кажется, лучше уж было использовать короткие адреса /node/1234. С другой стороны, в переходить на такую схему адресов мне представлялось неудобным, так как на новом движке пришлось бы нумеровать из вручную, а это уничтожает второе достоинство такого подхода.

Единственная альтернатива — использовать в адресе не транслитерацию, а перевод заголовка на английский. И чтобы не насиловать себя переводом заголовков двухсот с лишним постов (233-х, если быть точным) стоило воспользоваться машинным переводом. С одной стороны, это неизбежно даст некоторое количество ляпов, с другой стороны это не критично и в большинстве случаев перевод вполне адекватен.

К моему разочарованию, у Google Translate не оказалось нормального API и даже «пиратской» обертки на python к их веб-интерфейсу. Я уже было собрался лезть и с помощью Firebug выяснять, как он общается с сервером, когда меня неожиданно выручил Яндекс со своим Яндекс.Переводчиком. Качество перевода у него было похуже, но зато имелся вполне официальный API и даже готовый модуль для питона.

Для полноты счастья, я сделал кэширование обращений к переводчику, чтобы, с одной стороны, не делать двести HTTP запросов при всяком тестовом запуске скрипта и, с другой, не схлопотать ненароком бан со стороны Яндекса за подозрительную активность. С этой милой привычкой Яндекса я познакомился еще давно. Сделать это оказалось предельно просто с помощью модуля filecache.

Преобразование формата постов

По началу именно эта часть работы пугала меня больше всего. Пытаться сделать все на регулярных выражениях — известный способ получить себе еще одну проблему.

Some people, when confronted with a problem, think: “I know, I’ll use regular expressions.” Now they have two problems.

Jamie Zawinski

Спасла меня, как оказалось, довольно известная библиотека: Beautiful Soup 4. Несмотря на довольно странное название, она позволяет буквально творить чудеса с HTML-кодом. Помимо достаточно богатых возможностей по манипулированию DOM, она умеет искать в нем по самым разным хитрым критериям, вплоть до самописных функций-предикатов.

Этот код сначала находит тег <iframe> и <object>, которые могут быть вставленным кодом youtube, потом ищет перед ним тег <h3>, откуда извлекает название и исполнителя песни, добавляет их в мета-информацию поста и вырезает уже ненужные теги из тела. Как бы я это безумие делал рерулярками — страшно подумать…

Остальные преобразования я делал аналогичным методом: найти нужный тег, вырезать, преобразовать его содержимое, вставить на место.

To be continued…

В следующем посте я подробнее рассмотрю проблему смены структуры URL блога и создания редиректов на месте старых ссылок.

P.S. Savatage — Morphine Child