WPLite

Как найти и удалить дубли страниц и записей в WordPress после импорта

После импорта сайта, переноса с другой CMS или массовой синхронизации контента в WordPress часто появляются дубли: одинаковые страницы, записи с одинаковыми заголовками, копии с разными slug и черновики, которые случайно стали опубликованными. Проблема не только в «мусоре» в админке. Дубли ломают внутреннюю перелинковку, размывают SEO-сигналы и усложняют поддержку сайта.

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

Когда это действительно дубли, а не похожие материалы

Сначала стоит отделить технические копии от нормальной структуры сайта. У WordPress это частая ловушка: одинаковые заголовки могут быть у разных типов записей, а похожий контент — это не всегда дубль. Ищите именно те случаи, где совпадает смысл и источник появления:

  • одинаковые записи появились после импорта из CSV, XML или через плагин миграции;
  • страницы продублировались из-за повторного запуска импорта;
  • у записей совпадает заголовок и почти полностью совпадает содержимое;
  • остались старые копии с другим post_name, но тем же текстом;
  • в админке видны серии записей с одинаковыми названиями и разными датами создания.

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

Диагностика проблемы: где искать дубли в WordPress

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

SQL-запрос для поиска одинаковых заголовков

SELECT post_title, post_type, COUNT(*) AS cnt
FROM wp_posts
WHERE post_status IN ('publish', 'draft', 'private', 'pending')
  AND post_type IN ('post', 'page')
GROUP BY post_title, post_type
HAVING COUNT(*) > 1
ORDER BY cnt DESC, post_title ASC;

Если префикс таблицы у вас не wp_, замените его на свой. Запрос покажет группы, где одинаковый заголовок встречается несколько раз. Дальше нужно открыть каждую группу и сравнить содержимое, даты и slug.

Что смотреть в админке

В списке записей обратите внимание на три вещи:

  • slug в URL — часто именно он показывает, что запись была создана как копия;
  • дата публикации — дубль обычно создаётся в один день с оригиналом или сразу после импорта;
  • автор и статус — импортированные копии нередко остаются в черновиках или «на проверке».

Если дубликаты появились после переноса сайта, полезно проверить и вложения, и кастомные типы записей. Но в этой статье мы фокусируемся на post и page, потому что именно они чаще всего создают SEO-проблемы.

Пошаговое решение: как удалить лишние копии без лишнего риска

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

Шаг 1. Сформируйте список кандидатов

Если у вас есть доступ к WP-CLI, можно быстро вывести записи с одинаковыми заголовками и руками проверить каждую группу:

wp db query "
SELECT ID, post_title, post_name, post_type, post_status, post_date
FROM wp_posts
WHERE post_type IN ('post', 'page')
  AND post_status IN ('publish', 'draft', 'private', 'pending')
ORDER BY post_title ASC, post_date DESC;
"

Дальше удобно выгрузить результат в таблицу и отметить, какая запись оригинал, а какая копия. Обычно оригинал — это более старая запись с нормальным slug и историей правок.

Шаг 2. Удалите только подтверждённые дубли

Если список уже проверен, удалять можно через админку или через WP-CLI. Для массовой работы WP-CLI безопаснее: вы точно видите ID и можете сначала отправить записи в корзину, а не удалять навсегда.

wp post delete 123 124 125 --force

Если хотите сначала оставить возможность отката, уберите флаг --force. Тогда записи уйдут в корзину, и вы сможете восстановить их при ошибке.

Шаг 3. Удаление дублей по правилу, а не вручную

Когда дублей много, можно использовать небольшой PHP-скрипт в виде разового сниппета в плагине или mu-plugin. Ниже пример: он ищет записи с одинаковым заголовком и оставляет самую старую, а остальные переводит в корзину. Перед запуском обязательно сделайте резервную копию базы.

<?php
add_action('admin_init', function () {
    if (!current_user_can('manage_options')) {
        return;
    }

    if (empty($_GET['dedupe_posts'])) {
        return;
    }

    global $wpdb;

    $rows = $wpdb->get_results(
        "
        SELECT post_title, post_type, GROUP_CONCAT(ID ORDER BY post_date ASC) AS ids, COUNT(*) AS cnt
        FROM {$wpdb->posts}
        WHERE post_type IN ('post', 'page')
          AND post_status IN ('publish', 'draft', 'private', 'pending')
        GROUP BY post_title, post_type
        HAVING cnt > 1
        "
    );

    foreach ($rows as $row) {
        $ids = array_map('intval', explode(',', $row->ids));
        $keep_id = array_shift($ids);

        foreach ($ids as $duplicate_id) {
            wp_trash_post($duplicate_id);
        }
    }

    wp_die('Проверка завершена. Дубли отправлены в корзину.');
});

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

Сравнение подходов: плагин, SQL или код

СпособКогда подходитПлюсыМинусы
АдминкаДублей малоПросто, без кодаДолго и легко ошибиться
SQLНужно быстро найти группыТочно показывает данныеТребует аккуратности
WP-CLIМного записей и нужен контрольУдобно для массовых операцийНужен доступ к серверу
КодНужна повторяемая логикаМожно автоматизироватьНужна проверка условий

Если вы регулярно чистите импортированный контент, имеет смысл вынести проверку в разовый инструмент или админский скрипт. Для разовой задачи обычно достаточно SQL + WP-CLI.

Проверка результата после удаления

После очистки не ограничивайтесь просмотром списка записей. Проверьте, что сайт не потерял нужные URL и что поисковая структура осталась целой.

  • откройте удалённые URL и убедитесь, что они либо ведут на нужную запись, либо возвращают 404, если это действительно лишняя копия;
  • проверьте, не осталось ли в меню, хлебных крошках и внутренних ссылках старых адресов;
  • если дубли были проиндексированы, обновите sitemap и отправьте его в Search Console;
  • пройдитесь по списку записей с одинаковыми заголовками ещё раз и убедитесь, что группы исчезли или сократились до одного оригинала.

Для технической проверки удобно снова выполнить SQL-запрос из блока диагностики. Если он больше не возвращает группы с COUNT(*) > 1, значит, по выбранному правилу дубли убраны.

Частые ошибки и как их исправить

Удаляют по одному только заголовку

Это самая типичная ошибка. У двух записей может совпадать заголовок, но отличаться содержимое, язык, тип страницы или назначение. Исправление простое: сравнивайте не только title, но и текст, slug, дату, автора и таксономии.

Стирают записи без корзины и без бэкапа

Если использовать --force или удалять напрямую из базы, откат становится сложным. Перед чисткой сделайте резервную копию базы и сначала отправляйте сомнительные записи в корзину.

Не учитывают вложенные ссылки и меню

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

Путают дубль с редиректом

Иногда вместо удаления нужен 301-редирект со старого URL на оригинал. Это актуально, если дубль уже индексировался и имеет внешние ссылки. В таком случае удаление без редиректа может дать лишние 404.

Что делать, если дубли появляются снова

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

Практический чек-лист для профилактики:

  • проверяйте, по какому полю импортёр ищет существующую запись: ID, slug, внешний идентификатор;
  • не запускайте импорт повторно без теста на копии сайта;
  • ограничьте права на массовое создание записей у редакторов и внешних интеграций;
  • после импорта сразу сверяйте количество новых записей с ожидаемым;
  • если контент приходит из внешней системы, храните стабильный внешний ID и обновляйте запись по нему, а не по заголовку.

Безопасность и производительность при чистке дублей

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

Если вы используете плагины для очистки и оптимизации, выбирайте те, которые не скрывают действия за «магией». Для задач удаления дублей полезнее прозрачный инструмент, где видно, что именно будет удалено. Например, в экосистеме WPShop есть Clearfy Pro, который закрывает часть задач по чистке и SEO-обслуживанию сайта: https://wpshop.ru/plugins/clearfy. Но даже с плагином всё равно нужно сначала понять причину дублей, а не просто «почистить» их вслепую.

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

×
до 3225₽

Продавай темы и плагины WordPress!

Лови с каждой продажи

Начать ⋙