Files
rf4-spotter/docs/data-source-audit.md
T

17 KiB
Raw Blame History

Аудит источников и парсеров

Дата последней проверки: 5 сентября 2026 года. Аудит охватывает код репозитория, контрольные запросы к публичным HTML-страницам и публично описанные возможности потенциальных источников. Владелец RF4 Spotter подтвердил наличие разрешений на получение данных RF4DB и RF4-STAT; для новых кандидатов такого подтверждения пока нет.

Итог

Сейчас у проекта два реально работающих канала данных, но только один автоматический внешний источник:

Канал Статус Что даёт Координаты Доверие
Официальная таблица rf4game.de подключена, HTML-импорт рекорд, рыба, вес, водоём, приманка, игрок, дата нет 100
Собственная форма RF4 Spotter подключена, после модерации обычный улов, точка, снасть, игрок, скриншот да назначается приложением

manual_import существует в модели и seed, но отдельного пользовательского CSV/JSON-импортера нет. Seed — демонстрационные данные, а не источник. MinIO хранит доказательство пользовательской записи и также не является самостоятельным источником.

Текущие парсеры

В репозитории два HTML-парсера одной официальной таблицы:

  1. rf4_research.records.parse_records_html — исследовательский адаптер и CLI;
  2. app.importer.parse_html — продуктивный адаптер с HTTP-кэшем, повторами, журналом и сохранением.

Оба ожидают один DOM-контракт div.records.flex_table, одинаковый порядок шести колонок и одинаково нормализуют вес, дату и пустые поля. Добавлен общий контрактный тест: на одной фикстуре парсеры обязаны вернуть одинаковые кортежи полей и оба обязаны отклонить изменённую структуру колонок.

Контрольный HTML https://rf4game.de/records/region/RU/ имел размер 1 147 837 байт. Оба парсера успешно прочитали 1260 записей, результаты по восьми общим полям полностью совпали. Временный HTML в репозиторий не добавлен.

Обнаруженные ограничения согласования

  • Дублирование кода двух парсеров остаётся риском. Контрактный тест защищает результат, но при следующем рефакторинге общую чистую функцию разбора лучше вынести в пакет, доступный и исследовательскому CLI, и API-контейнеру.
  • Источник настроен на немецкий домен. Регион RU фильтрует игроков, но названия рыб, водоёмов и приманок остаются немецкими. Они не совпадают с русскими названиями пользовательской формы и могут создать параллельные сущности.
  • Русский URL https://rf4game.ru/records/region/RU/ при контрольном запросе вернул небольшую JavaScript-защитную страницу без таблицы; текущий парсер корректно завершился ошибкой records table not found. Обход защиты не рассматривается.
  • source_external_id надёжно убирает повтор одной и той же локализованной строки, но локализованные копии одной записи получат разные хеши. Нельзя считать разные языковые домены независимыми подтверждениями.
  • Официальная запись не содержит координат и поэтому не участвует в индексе конкретной точки. Автоматически связывать её с точкой нельзя.
  • Для новых агрегаторов одного enum source_type недостаточно: нужен стабильный source_system, внешний ID внутри этого источника, исходная ссылка и отдельное правило доверия.

Где можно получить новые данные

Приоритет A — тот же официальный источник

Официальная навигация публикует абсолютные и недельные таблицы, а также категории records, ultralight, recordslight, bottomlight, sea и telestick. Это расширение охвата существующего источника, а не независимые подтверждения. Текущий DOM-парсер, вероятно, можно переиспользовать, но каждую комбинацию нужно сначала проверить отдельной фикстурой. Регулярный обход нельзя включать без согласования допустимой частоты с владельцем сайта.

Рекомендуемый первый эксперимент — недельные RU-рекорды одной категории. Они полезнее абсолютных для свежести, не требуют новой схемы, но всё ещё не дают координат.

Приоритет A — согласованные каналы сообщества

Telegram, Discord и VK могут давать свежие координаты, оснастку, игровое время и скриншоты. Подключать следует только конкретные каналы, администраторы которых письменно разрешили импорт. Для каждого сообщения нужны permalink/message ID, время публикации, имя канала, версия правил и возможность удалить запись по запросу.

Наиболее безопасная реализация — бот или форма, куда автор сам пересылает сообщение и подтверждает распознанные поля. Это лучше скрытого чтения групп и позволяет использовать существующую очередь модерации.

Приоритет B — RF4DB (разрешение подтверждено владельцем проекта)

https://rf4db.com/ru показывает актуальные пользовательские уловы, координаты, игровое время, погоду, снасть и изображения; публичная страница заявляет 19 водоёмов, 252 вида рыб и тысячи точек. Страница об источниках поясняет, что игровые справочники взяты из игры, а точки и комментарии собраны игроками в открытом доступе.

Серверный HTML пригоден для адаптера; пилотный fail-closed парсер добавлен. Перед регулярным запуском нужно сохранить подтверждение разрешения и его условия: атрибуцию, частоту, удаление и допустимость ссылок на изображения.

Приоритет B — RF4-STAT (разрешение подтверждено владельцем проекта)

https://rf4-stat.ru/help/ сообщает, что рекорды берутся с официального сайта, а точки и посты — из VK, Discord, Telegram и собственной формы. Сервис обновляет записи регулярно, часть доступа является Premium.

Пилотные парсеры публичных /fishing/ и /posts/ добавлены с соблюдением Crawl-delay. Заблокированные координаты, погода, комментарии и интерактивная статистика не извлекаются. Данные, пришедшие туда с официального сайта, нельзя считать вторым независимым подтверждением.

Исследовательские адаптеры — RF4MAP и RF4 Posts

Публичная detail-страница RF4MAP содержит в серверном HTML устойчивый ID наблюдения, координаты, ID и название рыбы, ID водоёма, дату, клипсу, необязательные приманку, автора и изображения. Контрольная точка содержала 30 отдельных наблюдений. Веса нет. robots.txt разрешает публичные страницы и запрещает /api/; исследование использует только HTML одной страницы.

Публичная detail-страница RF4 Posts содержит устойчивый UUID точки, координаты, slug водоёма, список slug рыб, способ ловли, оснастку, клипсу, дату и ссылки на доказательства. Русская локализация позволяет связать slug с отображаемым названием. Контрольный пост дал 6 записей видов рыб из одной точки. Это инструкция по точке, а не шесть доказанных индивидуальных уловов, поэтому вес остаётся null, а происхождение сохраняет общий UUID поста.

Оба fail-closed парсера добавлены в read-only исследовательский CLI и разрешены владельцем проекта с интервалом не менее 30 минут на сайт. CLI резервирует домен до запроса и отклоняет слишком ранний повтор любого endpoint, включая повтор после ошибки. В production все разрешённые адаптеры подключены к scheduler и staging; полные записи с подтверждёнными алиасами публикуются автоматически, остальные требуют проверки. RF4 Posts считается агрегированной точкой, а не набором взвешенных уловов.

Также проверены два менее пригодных кандидата:

  • rf4pro.com отдаёт минимальную SPA-оболочку, а robots.txt запрещает /api/ и JSON; защищённые маршруты не исследовались, адаптер не добавлен;
  • rr4farmtrof.com/RF4Records/ загружает таблицу клиентским запросом и по смыслу агрегирует официальные рекорды; это не независимое подтверждение, endpoint не запрашивался и адаптер не добавлен.

Приоритет C — справочники

Списки рыб, водоёмов, снастей, трофейных весов и переводов полезны для канонизации, но не для оценки текущего клёва. Источниками-кандидатами являются официальные страницы/патчноуты и разрешённый справочный экспорт партнёра. Нужны версия игры, язык и устойчивый внутренний ключ; сопоставление только по отображаемому имени недостаточно.

Что не использовать

  • перехват трафика клиента, внедрение в игру и закрытые протоколы;
  • боты автоматической рыбалки и данные, полученные с нарушением правил игры;
  • обход JavaScript-защиты, CAPTCHA, авторизации или Premium-доступа;
  • массовое копирование чужих изображений и пользовательских постов без разрешения;
  • разные локализации официальной записи как разные подтверждения.

Схема согласования новых адаптеров

Каждый адаптер должен выдавать промежуточную запись со следующими группами полей:

provenance: source_system, source_external_id, source_url, observed_at, fetched_at
identity: fish_external_id/name/language, waterbody_external_id/name/language
catch: weight_g, caught_at, game_time, bait, method, rig, retrieve
spot: x, y или null
actor: player_name или null
evidence: screenshot_url/key, raw_payload
quality: moderation_status, source_confidence

До записи в catch_report должны последовательно выполняться:

  1. валидация контракта источника;
  2. нормализация единиц, времени и пустых значений;
  3. сопоставление рыб/водоёмов по таблице алиасов с языком и версией игры;
  4. дедупликация внутри source_system;
  5. выявление кросс-источниковых копий без автоматического объединения сомнительных записей;
  6. назначение доверия и модерации по политике источника;
  7. сохранение происхождения и минимально необходимого сырого фрагмента.

Рекомендуемый порядок работ

  1. Добавить сущности data_source и entity_alias; включить источник в уникальный ключ внешней записи.
  2. Вынести общий официальный DOM-парсер и оставить два тонких клиента вокруг него.
  3. Добавить фикстуру недельной таблицы и проверить одну официальную категорию без расписания.
  4. Согласовать экспорт/API с RF4DB и RF4-STAT; до ответа не писать их парсеры.
  5. Выбрать один добровольный Telegram/Discord/VK-канал для пилота и зафиксировать согласие/правила удаления.
  6. Только затем добавлять адаптер, контрактные тесты и калибровку source_confidence.

Проверенные ссылки