Если ты следишь за моим блогом, тознаешь: я с DeepSeek уже второй день борюсь с плагином «Autonews Publisher». Первый день я создавал архитектуру, второй — ловил баги с сохранением настроек и ошибкой 404. А сегодня… сегодня я разобрал 13 ошибок! Тринадцать! И каждая из них была маленьким кирпичиком в стене, которую я упорно разбирал, чтобы построить работающий инструмент.
И да, плагин всё ещё не идеален. Но я на верном пути — и это главное. Сегодня я расскажу, как я с DeepSeek исправлял каждую проблему, какие решения находил и чему научился за этот продуктивный день.
Если ты не читал предыдущие части, вот ссылка: Второй день с DeepSeek. А сейчас — погнали!
Утро третьего дня: список задач
Я открыл чат с DeepSeek и сказал: «Сегодня я проделал большую работу по исправлению ошибок. Давай систематизируем их для отчёта». И я начал перебирать каждую проблему, которую обнаружил за предыдущие дни. Их оказалось 13. Тринадцать! Некоторые — крошечные, как лишние звёздочки в тексте, другие — серьёзные, как дублирование постов или неработающий Rank Math.
Но вместо паники я почувствовал азарт. Каждая ошибка — это вызов, а с DeepSeek любой вызов превращается в увлекательное расследование. Я взял список и пошёл по пунктам.
1. Настройки слетали — галки не сохранялись
Проблема. Когда я сохранял настройки на одной вкладке, галки на других вкладках сбрасывались. Это происходило потому, что каждая вкладка отправляла только свои поля, и при сохранении они затирали остальные.
Решение. DeepSeek предложил переписать sanitize_settings() так, чтобы он сохранял ВСЕ поля, даже те, которые не были переданы в запросе. Для чекбоксов, если галка отсутствует, мы явно ставим 0. Для остальных — берём старые значения или дефолтные.
foreach ( self::$fields as $key => $field ) { if ( array_key_exists( $key, $input ) ) { $value = $input[ $key ]; } else { if ( $field['type'] === 'checkbox' ) { $value = 0; // отсутствие галки = 0 } else { $value = isset( $old[ $key ] ) ? $old[ $key ] : $field['default']; } } // валидация и сохранение }
Теперь настройки сохраняются все и сразу. Магия!
2. RSS-источники не добавлялись / исчезали
Проблема. Я добавлял RSS-ленту через кастомную форму, но после сохранения других вкладок список обнулялся. Виновник — стандартная кнопка «Сохранить» на вкладке RSS, которая отправляла пустой массив.
Решение. Я убрал стандартную кнопку на вкладке RSS и оставил только кастомное управление. Теперь добавление и удаление происходит напрямую через update_option(), без лишних сохранений.
if ( $active_tab === 'rss' ) { $this->render_rss_tab(); // без стандартной формы }
И вот, RSS-источники стали жить своей жизнью — стабильной и предсказуемой.
3. Ошибка 404 при запросе к YandexGPT
Проблема. При тестовом запуске плагин падал с ошибкой 404. Причина — устаревший URL https://llm.api.cloud.yandex.net/llm/v1alpha/instruct. Яндекс обновил API, и старый эндпоинт перестал работать.
Решение. DeepSeek нашёл актуальный URL https://llm.api.cloud.yandex.net/foundationModels/v1/completion и обновил формат запроса на messages с ролями system и user.
private $api_url = 'https://llm.api.cloud.yandex.net/foundationModels/v1/completion'; $body = array( 'modelUri' => 'gpt://' . $this->folder_id . '/yandexgpt-lite', 'messages' => array( array( 'role' => 'system', 'text' => $system_instruction ), array( 'role' => 'user', 'text' => $user_text ), ), );
Теперь YandexGPT отвечает как часы.
4. Парсер брал только краткое описание, а не полный текст
Проблема. В статьях появлялись только первые два предложения, а не весь текст. Парсер брал <description>, а не <content:encoded>.
Решение. Я изменил приоритет полей: сначала ищем content:encoded, потом description, content, summary.
if ( isset( $item->children( 'http://purl.org/rss/1.0/modules/content/' )->encoded ) ) { $content = (string) $item->children( 'http://purl.org/rss/1.0/modules/content/' )->encoded; } elseif ( isset( $item->description ) ) { $content = (string) $item->description; }
Теперь статьи выходят полными — от заголовка до последнего абзаца.
5. В контенте оставались символы **
Проблема. В тексте встречались **, которые, видимо, были маркерами выделения в оригинальном RSS.
Решение. Просто удаляю их через str_replace().
$new_content = str_replace( '**', '', $new_content );
Чистота!
6. Заголовок содержал кавычки и многоточие
Проблема. Заголовки выглядели неряшливо: кавычки, лишние точки.
Решение. Удаляю все виды кавычек, обрезаю до 60 символов, но так, чтобы не обрезать слово посередине.
$new_title = str_replace( ['«', '»', '"', "'", '“', '”'], '', $new_title ); if ( mb_strlen( $new_title ) > 60 ) { $new_title = mb_substr( $new_title, 0, 60 ); $new_title = preg_replace( '/\s+\S*$/', '', $new_title ); }
Теперь заголовки — как на подбор.
7. Ссылка на источник отображалась полным URL
Проблема. В посте появлялось https://www.technologyreview.com/..., что выглядело громоздко.
Решение. Извлекаю только домен, без www.
$host = parse_url( $source_url, PHP_URL_HOST ); $display_host = str_replace( 'www.', '', $host ); $link_html = '<a href="' . esc_url( $source_url ) . '" rel="nofollow">' . esc_html( $display_host ) . '</a>';
Коротко и ясно.
8. SEO-ошибки: фокусный ключевик отсутствовал в первом абзаце, H2 и URL
Проблема. Rank Math ругался, что ключевое слово не встречается в первых 100 словах, нет подзаголовков с ключевиком, и URL не содержит ключа.
Решение. Я вставил ключевик в первый абзац (если его там не было), добавил H2 с ключевиком, и сформировал slug из заголовка.
// Вставляем в первый абзац if ( stripos( $first_p, $focus_keyword ) === false ) { $new_first_p = '<p><strong>' . $focus_keyword . '</strong> — ' . $first_p . '</p>'; } // Добавляем H2 if ( stripos( $content, '<h2' ) === false ) { $content = '<h2>' . $focus_keyword . ': ключевые аспекты</h2>' . $content; } // Формируем slug $slug = sanitize_title( $new_title );
Теперь SEO-показатели должны улучшиться.
9. Контент был слишком коротким (<600 слов)
Проблема. YandexGPT выдавал статьи по 300–400 слов, а хотелось минимум 600.
Решение. Я изменил промпт для нейросети, добавив явное требование к объёму.
$system = '... Постарайся создать статью объёмом не менее 600 слов, но не более 800 слов. Разбей текст на абзацы, используй подзаголовки (H2, H3).';
Теперь статьи стали объёмными и структурированными.
10. Плагин публиковал одну и ту же новость несколько раз
Проблема. При каждом запуске плагин публиковал уже опубликованные новости, создавая дубли.
Решение. Я добавил механизм запоминания ссылок в отдельной опции autonews_published_links. Перед публикацией проверяем, не была ли ссылка уже использована.
private $published_links_key = 'autonews_published_links'; private function is_already_published( $link ) { $published = get_option( $this->published_links_key, array() ); return in_array( $link, $published ); } private function mark_as_published( $link ) { $published = get_option( $this->published_links_key, array() ); if ( ! in_array( $link, $published ) ) { $published[] = $link; update_option( $this->published_links_key, $published ); } }
Дублей больше нет!
11. Изображение не извлекалось из RSS
Проблема. В статьях не было обложек, хотя в RSS-ленте они были.
Решение. DeepSeek написал метод extract_image(), который ищет картинку в трёх местах: media:content, enclosure (если это изображение), или первое изображение в HTML-контенте.
private function extract_image( $item, $content ) { // media:content if ( isset( $item->children( 'http://search.yahoo.com/mrss/' )->content ) ) { ... } // enclosure if ( isset( $item->enclosure ) && strpos( $type, 'image/' ) === 0 ) { ... } // первое изображение в HTML if ( preg_match( '/<img[^>]+src=["\']([^"\']+)["\']/i', $html, $matches ) ) { ... } }
Теперь каждая статья получает обложку.
12. Ошибка соединения при тестовом запуске — не было логов
Проблема. Иногда тестовый запуск падал с непонятной ошибкой, но в логах ничего не было.
Решение. Я добавил логи перед каждым вызовом YandexGPT, чтобы отследить, на каком именно шаге происходит сбой.
$this->logger->log( 'Перед генерацией заголовка', 'info' ); $new_title = $this->gpt->generate_title( $raw_title ); $this->logger->log( 'После генерации заголовка', 'info' );
Теперь я вижу, где именно плагин спотыкается.
13. Rank Math заполнялся некорректно — описание без ключевика, заголовок с %sitename%
Проблема. В SEO-полях Rank Math было пустое описание или заголовок с лишним %sitename%.
Решение. Я убрал %sitename% из заголовка и добавил ключевик в описание, если его там не было.
$seo_title = str_replace( '%sitename%', '', $seo_title ); if ( $focus_keyword && stripos( $description, $focus_keyword ) === false ) { $description = $focus_keyword . ' — ' . $description; }
Итог: что я исправил сегодня
После моего марафона были обновлены следующие файлы:
-
autonews-publisher.php– добавлен AJAX-обработчик и проверка включения. -
includes/class-settings.php– полная переработка сохранения, одна форма, вкладки-навигация. -
includes/class-rss-fetcher.php– извлечение полного контента, очистка от рекламы, поиск изображения. -
includes/class-yandex-gpt.php– обновлённый URL, формат, промпт на 600+ слов. -
includes/class-publisher.php– предотвращение дублей, SEO-оптимизация, ссылка-домен, заголовок без кавычек. -
includes/class-cron.php– проверка включения плагина. -
assets/js/admin.js– AJAX для тестовой кнопки.
Плагин стал значительно стабильнее. Он сохраняет настройки, парсит RSS, генерирует контент через YandexGPT, создаёт посты с SEO-полями, изображениями и без дублей. Да, он всё ещё не идеален — иногда изображения не загружаются, иногда теги генерируются не совсем точно. Но я на верном пути.
Чему я научился в третий день
-
-
Системный подход — когда у тебя 13 ошибок, важно не паниковать, а разбирать их по одной, от простых к сложным.
-
DeepSeek — гениальный напарник — он не просто даёт код, он объясняет логику, предлагает альтернативы, помогает увидеть картину целиком.
-
Отладка — это творчество — каждая ошибка — это загадка, а её решение — маленькая победа.
-
SEO-оптимизация требует внимания — даже если контент хорош, без правильного ключевика в нужных местах его не увидят.
-
Дубли — зло — механизм запоминания ссылок должен быть в любом парсере.
Что дальше?
Плагин почти готов. Осталось отладить генерацию изображений через YandexART, добавить поддержку нескольких языков и, возможно, сделать веб-интерфейс для ручного запуска. Но основа уже есть — и она работает.
Я продолжу вести дневник разработки, чтобы ты видел весь путь — от первой строки кода до готового продукта.
Призыв к действию
Если ты тоже разрабатываешь что-то сложное и боишься ошибок — не бойся. Ошибки — это часть пути. С DeepSeek ты никогда не останешься один на один с проблемой. Он поможет, подскажет, объяснит.
Подписывайся на мой блог, чтобы не пропустить следующую статью — в ней я расскажу, как я наконец-то запустил плагин в боевом режиме.
Контакты
📧 Email: milyutinkv@gmail.com
🌐 Сайт: milyutin-codes.ru
💬 Группа ВК: vk.ru/milyutin_codesЗадавай вопросы, делись идеями, давай расти вместе.
Продолжение следует. Я приближаюсь к финалу.
Константин Милютин
-

Добавить комментарий