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

130 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Аудит источников и парсеров
Дата последней проверки: **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-доступа;
- массовое копирование чужих изображений и пользовательских постов без разрешения;
- разные локализации официальной записи как разные подтверждения.
## Схема согласования новых адаптеров
Каждый адаптер должен выдавать промежуточную запись со следующими группами полей:
```text
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`.
## Проверенные ссылки
- официальный абсолютный рейтинг: <https://rf4game.de/records/region/RU/>
- официальный недельный рейтинг: <https://rf4game.de/records/weekly/region/RU/>
- RF4DB: <https://rf4db.com/ru> и <https://rf4db.com/ru/about/data>
- RF4-STAT: <https://rf4-stat.ru/help/>
- RF4MAP: <https://rf4map.ru/>
- RF4 Posts: <https://rf4-posts.com/ru/about>
- отложенные кандидаты: <https://rf4pro.com/> и <https://rr4farmtrof.com/RF4Records/>
- исследовательский проект: <https://github.com/hurfy/rf4-api>