Импорт и экспорт контента

o{ "title": "Импорт и экспорт контента в WordPress: технический разбор, форматы и качество данных", "keywords": "импорт контента WordPress, экспорт WordPress, XML-RPC, WXR, массовый перенос записей, миграция WordPress, технические форматы данных", "description": "Подробный технический разбор процесса импорта и экспорта контента в WordPress. Рассматриваются форматы WXR, CSV, XML-RPC, требования к структуре данных, типичные ошибки и сценарии миграции.", "html_content": "

Исходная ситуация и техническая задача

Клиент — компания, занимающаяся производством корпусной мебели, владела тремя разрозненными сайтами на WordPress, каждый из которых использовал свою тему, свои типы записей и произвольные поля (ACF). Необходимо было объединить каталог продукции, включающий более 4000 товаров с техническими характеристиками, чертежами, спецификациями материалов и 3D-моделями, в единый портал. Задача осложнялась тем, что на старых сайтах использовались разные версии PHP (7.4, 8.0) и разные версии WordPress (5.8, 6.0), а также плагины, не поддерживающие стандартный WXR-формат.

Проблема была не в объёме данных, а в их гетерогенности: на одном сайте атрибуты товара хранились в сериализованных массивах в мета-полях, на втором — в кастомных таксономиях, на третьем — в виде шорткодов внутри контента. Прямой импорт через стандартный инструмент WordPress (Инструменты → Импорт) приводил к потере данных: выпадали изображения, ломались ссылки на спецификации, сбрасывались значения полей, отвечающих за ГОСТы и допуски.

Выбор протокола и формата данных

После аудита структуры баз данных было принято решение отказаться от стандартного WXR (WordPress eXtended RSS) в пользу комбинации: XML-RPC для сущностей (записи, страницы) и CSV с жёсткой схемой для метаданных. Стандартный WXR хорош только для блогов: он поддерживает основные поля (title, content, excerpt), таксономии и медиафайлы, но при попытке передать 15+ произвольных полей на каждый товар файл раздувается до гигабайтов, а парсинг на стороне приёмника виснет из-за ограничений memory_limit в 256 MB.

Для миграции была разработана многоэтапная процедура. На первом этапе выгружались все медиафайлы через FTP с сохранением структуры папок (uploads/YYYY/MM/). На втором этапе через XML-RPC с использованием библиотеки IXR_Client отправлялись базовые данные записей. Каждая запись получала новый ID на целевом сайте, а старые ID фиксировались в отдельной таблице соответствия для дальнейшей перелинковки. На третьем этапе через скрипт на Python (с обвязкой по cURL) происходил массовый импорт CSV-файлов со спецификациями в ACF-поля.

Проблемы с целостностью данных и ссылками

Первая тестовая миграция 500 товаров выявила критическую проблему: внутренние ссылки в описаниях товаров вели на старые ID записей. Например, в поле «Комплектация» была ссылка на другой товар из этого же каталога, но на новом сайте URL изменился. Стандартные плагины типа Velvet Blues Update URLs не справлялись с кастомными полями ACF типа «ссылка».

Пришлось писать SQL-запрос для поиска и замены в сериализованных данных. Сложность заключалась в том, что ACF хранит ссылки в формате a:1:{s:4:\"url\";s:XXX:\"http://...";}. Прямая замена подстроки в сериализованном массиве ломает его — PHP перестаёт распознавать данные. Решение — скрипт на PHP, который десериализует массив, заменяет URL, а затем ресериализует обратно. Дополнительно пришлось обработать 2300 ячеек в postmeta.

Вторая проблема касалась изображений. На старом сайте пресеты для thumbnails были разных размеров (300x200, 800x600), на новом — только 3 размера. При импорте через XML-RPC WordPress пытался сгенерировать все недостающие размеры кропов, что на 4000 товарах вызвало таймауты. Решение — предварительная генерация всех метаданных изображений через скрипт wp-cli media regenerate после загрузки оригиналов.

Технические спецификации и контроль качества

После импорта каждого этапа проводилась верификация данных по трём уровням. Первый уровень — автоматическая сверка количества записей и полей между базами через SQL-запросы (SELECT COUNT(*) FROM wp_posts WHERE post_type = 'product'). Второй уровень — проверка форматов: все даты должны быть в формате Y-m-d H:i:s, все URL — абсолютные, все числа с плавающей точкой — с точкой в качестве разделителя (не запятой).

Третий уровень — выборочная проверка 5% товаров вручную. Проверялось: соответствие таксономий (материалы: МДФ, ЛДСП, массив; фурнитура: Blum, Hettich), корректность ссылок на PDF-спецификации (ГОСТы), наличие всех 3D-моделей в папке /uploads/models/. Было выявлено, что в 3% случаев имена файлов кириллицей не конвертировались в латиницу — пришлось добавить обработчик transliteration на стороне импорта.

Отличия от стандартных плагинов миграции

На рынке существуют десятки плагинов для импорта/экспорта (WP All Import, Export All URLs, Migrate DB Pro). Однако в промышленных сценариях с большим объёмом кастомных полей и специфическими требованиями к форматам они либо слишком медленные, либо накладывают свои правила на структуру данных. WP All Import, например, при импорте CSV-файла с 4000 строк и 20 полями создаёт временные таблицы, которые при базовом лимите innodb_buffer_pool_size в 128 MB приводят к ошибке «MySQL server has gone away».

Кроме того, стандартные инструменты не умеют обрабатывать вложенные поля ACF (группы, повторители) без дополнительных надстроек. В нашем случае в товаре использовался repeater для списка комплектующих — плагин требовал ручного маппинга XML-узлов, что при 300 повторяющихся строках на один товар делало конфигурацию нечитаемой. Только написание собственного скрипта на Python с прямой записью в wp_postmeta через INSERT минуя абстракции WordPress дало нужную скорость (15 000 строк метаданных в минуту).

Стандартные плагины не гарантируют перенос таксономий, если slug отличается. Пришлось экспортировать все термины (материалы, типы покрытия, категории фурнитуры) вместе с их иерархией через отдельный скрипт, который создавал term_taxonomy записи с заданными term_id. Это позволило сохранить ссылки на родительские категории (например, «ДСП → Ламинированная ДСП → Кромка ПВХ»).

Результаты и эксплуатационные характеристики

Итоговая структура на целевом сайте полностью повторяла исходную логическую модель, но была приведена к единым стандартам: все даты — в UNIX timestamp, все URL — относительные (для гибкости при смене домена), все изображения — с явным указанием alt-тегов и данных EXIF (ISO, выдержка, фокусное расстояние — для технической документации).

Скорость загрузки каталога после миграции (замер через Lighthouse) осталась в пределах нормы — 1.2 секунды до LCP. Критическим фактором выступило то, что при импорте не были сгенерированы дублирующиеся мета-ключи — каждая запись имела ровно один набор полей, что ускорило выборки из БД на 18% по сравнению с исходным сайтом, где из-за плагинов-накопителей (вроде Yoast SEO) в таблице postmeta было до 15 записей с ключом _yoast_wpseo_title на одну страницу.

Заказчик получил полный контроль над данными: теперь для экспорта каталога в Excel (для закупщиков мебельной фурнитуры) не нужны плагины — достаточно SQL-запроса с JOIN по postmeta. Импорт новых товаров через XML-RPC настроен как CI/CD-процесс: дизайнер загружает 3D-модель, менеджер заполняет CSV, и через cron-задачу раз в час новые позиции появляются на сайте. Ошибки в данных (неверный формат толщины материала, отсутствие файла чертежа) логируются в отдельную таблицу и отправляются в Telegram-бота.

" }

Добавлено: 24.04.2026