Введение
В этой статье — без воды и общих фраз — собраны типичные ошибки, которые встречаются в проектах по RSS‑парсингу и контент‑агрегации, и конкретные способы их устранения на корню. Материал основан на реальных кейсах и проверенных приёмах из практики «Контент‑Агент».
Классификация ошибок
Ошибки условно делим на блоки: данные (формат, кодировка), доступ (rate‑limit, блокировки), структурные (изменение DOM/фида), логика (дедупликация, даты), инфраструктурные (сбои очередей, idempotency при публикации через REST API для публикации).
Таблица: виды ошибок и краткие контрмеры
| Ошибка |
Причина |
Быстрое решение |
| Кодировка |
UTF-8/Windows‑1251/ISO mismatch |
Определять заголовки HTTP + BOM + принудительная перекодировка |
| Изменение структуры сайта |
Подвёрстка/редизайн |
CSS/XPath с fallbacks, тесты селекторов |
| Дубли |
Несоответствие canonical/разные URL |
Фингерпринтинг контента, canonical checks |
| Rate limits/403 |
Частые запросы, боты |
Exponential backoff, прокси, тайминги |
| Ошибки в API публикации |
Пропущенные поля, гонки |
Валидация, idempotency keys, транзакционные ответы |
Данные и кодировки — точка №1
Симптомы: странные символы в тексте, обрезанные теги, ошибки XML парсера. Причина почти всегда — неверная кодировка или некорректный заголовок Content-Type.
Практические правила
- Читай HTTP‑заголовок Content-Type; если он отсутствует или неконкретен, анализируй BOM и используемые символы в первых 1024 байтах.
- При RSS‑парсинге проверяй <?xml encoding=’…’ ?> и HTTP отдельно — они могут противоречить друг другу. Доверяй HTTP, но логируй несоответствия и отправляй на отдельный пайплайн исправления.
- Всегда приводите текст к UTF‑8 в единой точке передачи данных дальше по цепочке.
Структурные изменения источника
Кейс: крупный провайдер новостей сменил HTML‑шаблон — ваш парсер перестал извлекать заголовки и изображения. Частая ошибка — жёстко зашитые XPath/CSS селекторы без fallback’ов.
Решения
- Составьте набор приоритетных селекторов (primary/secondary/tertiary). Если primary возвращает пусто, пробуйте следующий.
- Используйте схемы (JSON Schema) для валидации результата парсинга: если обязательное поле отсутствует — отправляйте задачу на ручную проверку или автоматический рескреннинг.
- Быстрый мониторинг: сравнивайте частотные изменения селекторов по X‑paths за сутки — если падение >50% по новостям — триггерите алерт.
Логические ошибки: дубли и неправильные метаданные
Ошибка: одна и та же статья попадает в агрегатор несколько раз под разными URL — из‑за параметров, UTM или мобильных поддоменов.
Стратегии устранения
- Создавайте фингерпринт на основе нормализованного тела: strip HTML, remove whitespace, compute sha1. Храните fingerprint и отклоняйте дубли.
- Проверяйте <link rel=’canonical’> в HTML и используйте его как приоритет при сопоставлении URL.
- Нормализуйте URL: убирайте UTM, параметры сессии, приводите домен к одному виду (www/non‑www).
Ошибки доступа: rate limits, капча, блокировки
Симптомы: 429, 403, redirect на капчу или блокировочную страницу. Частая ошибка — агрессивный параллелизм без бэкенд‑политики.
Рекомендации
- Реализуйте глобальную политику rate‑limit по доменам; для известных источников используйте SLA‑параметры.
- Обрабатывайте 429 и 503 с экспоненциальным бэкоффом и jitter. Логируйте Retry‑After.
- Если сайт требует JavaScript, переключайте на headless‑парсинг только для таких URL, а не для всего потока.
Интеграция: REST API для публикации — где чаще всего ломается
Когда вы отправляете готовый контент в CMS или партнёрам через REST API для публикации, ошибки появляются на уровне схемы, аутентификации и идемпотентности.
Типовые проблемы и фикс
- 422 Unprocessable Entity — значит, не прошла валидация. Решение: до публикации прогоняйте JSON Schema и исключайте контент с нарушениями в отдельный поток.
- Двойная публикация/гонки — используйте idempotency key (например, X‑Idempotency‑Key) и храните mapping external_id → internal_id.
- Аутентификация — короткие токены: реализуйте автоматическое обновление токена и ретраи на 401 с refresh.
Пример запроса на публикацию (curl):
curl -X POST 'https://cms.example/publish' \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
-H 'X-Idempotency-Key: 123e4567-e89b-12d3-a456-426614174000' \
-d '{"title":"Пример","body":"Текст статьи","source":"example.com"}'
Если ответ 409 Conflict — считывайте тело ответа: часто там возвращают уже созданную запись с id, что позволяет синхронизировать состояние.
Тестовые кейсы и мониторинг
Минимальный набор тестов и метрик, которые спасают от большинства проблем:
- Unit-tests для парсеров: проверка селекторов на наборе контрольных страниц.
- End‑to‑end тесты: полный цикл от получения RSS‑фида до публикации через REST API для публикации в тестовом окружении.
- Мониторинг качества: процент валидных записей, процент дублей, latency публикации, rate limit hits.
Конкретный кейс: переход источника с RSS на JSON API
Ситуация: один источник закрыл RSS и предоставил JSON API с иной моделью. Ошибка: команда отключила CSS‑парсер, не добавив поддержку новых полей, из‑за чего картинка и категория потерялись.
Как мы исправили
- Добавили адаптер, который мапит новые поля API на внутреннюю модель с fallback’ом на парсинг HTML, если поля пусты.
- Ввели автоматическую проверку при первом получении новостей из нового источника: если обязательные поля пусты — ставим статус «на разбор» и уведомляем редактора.
- Для скорости — сделали кэширование ответов API с условием инвалидации по заголовку Last‑Modified/ETag.
Заключение: как строить систему, чтобы парсинг не ломался
- Стандартизируйте вход: единый этап нормализации (UTF‑8, remove scripts, extract canonical).
- Валидация по схеме и фингерпринтинг для дедупликации — это треть от работы, но 80% пользы.
- Интеграция через REST API для публикации должна быть идемпотентной и возвращать понятные статусы; ошибки 4xx/5xx логируйте и ретрайте с бэкоффом.
- Автоматический мониторинг изменений структуру источников и набор fallback‑селекторов снижает время простоя парсеров в несколько раз.
Эти рекомендации позволяют устранить большинство типичных ошибок парсинга «на корню» и построить устойчивый pipeline для RSS‑парсинга и контент‑агрегации.