Files
rf4-spotter/docs/community-source-pilot.md
T

11 KiB
Raw Blame History

Пилот парсинга RF4DB и RF4-STAT

Текущий статус разрешений, атрибуции и консервативных лимитов зафиксирован в docs/data-permissions.md.

Дата контрольного запуска: 3 сентября 2026 года. Владелец RF4 Spotter подтвердил наличие разрешений на получение данных из обоих сервисов. Пилот использует только публичный HTML, не обращается к закрытым API, не обходит авторизацию/Premium и не скачивает изображения.

RF4DB

Проверенная страница: https://download.rf4db.com/ru/catches.

HTML формируется Next.js, но готовые карточки присутствуют в серверном ответе. Из карточки извлекаются:

  • UUID улова и каноническая detail-ссылка;
  • русское название и внешний slug рыбы;
  • русское название и внешний ID водоёма;
  • координаты;
  • игровое время;
  • приманка и её внешний ID;
  • оснастка;
  • погода и температура воды.

На контрольной странице найдено 24 элемента catch-card: 23 являлись уловами с detail-ссылкой, один — неполным/служебным элементом и безопасно пропущен. У всех 23 уловов были координаты. Вес, игрок и абсолютное время публикации отсутствовали и не подменяются догадками.

Detail-страница дополнительно содержит ветер, клипсу, выпуск лески, направление заброса и полный список снастей, но по-прежнему не содержит вес. Добавлен отдельный RF4DBCatchDetail: контрольная живая страница вернула ветер, три числовых параметра заброса и 11 элементов снасти. Detail-запросы не выполняются автоматически для всей выдачи, чтобы не умножать нагрузку на источник.

robots.txt на download-домене запрещает автоматический обход для User-Agent: * и /api/. Наличие отдельного разрешения нужно сохранить в документации проекта. Публичный API не исследовался и не использовался; для пилота взят только серверный HTML одной страницы.

RF4-STAT

Проверенные страницы:

  • https://rf4-stat.ru/fishing/;
  • https://rf4-stat.ru/posts/;
  • https://rf4-stat.ru/active-spots/.

Запросы выполнялись последовательно с Crawl-delay: 5, указанным в robots.txt.

Из таблицы /fishing/ извлекаются ID, ссылка, рыба и slug, вес, водоём, приманка, игрок, время публикации, клипса, стиль ловли и ссылка на изображение. Контрольный результат: 100 из 100 строк. Вес присутствовал во всех 100 строках; координаты в публичном представлении были замаскированы и не извлекались.

Из /posts/ один пост разворачивается в одно или несколько наблюдений по числу рыб. Извлекаются ID post:fish_index, время публикации Unix, рыба, вес, водоём, приманки, игрок, клипса, стиль и URL миниатюр-доказательств. Контрольный результат: 16 наблюдений из 10 постов, у всех 16 были вес и доказательства. Координаты и погода, помеченные position-locked/locked weather, намеренно не извлекались.

/active-spots/ содержит десять агрегированных карточек, но публично видимые координаты и интерактивная статистика заблокированы, а стабильного ID наблюдения и рыбы нет. Эти карточки не преобразуются в уловы. Значения из скрытых data-position не используются.

Общий контракт

Парсеры возвращают ExternalCatch и никогда не записывают данные непосредственно в БД. Поля weight_g, координаты, игрок и время nullable, потому что источники дополняют друг друга, но не должны склеиваться только из-за похожих значений.

Текущие пространства идентификаторов разделены:

  • rf4db + UUID;
  • rf4stat-fishing + числовой ID;
  • rf4stat-post + post_id:fish_index.
  • rf4map + числовой ID отдельного наблюдения;
  • rf4posts-spot + spot_uuid:fish_slug.

Следующий слой импорта должен хранить source_system отдельно от внешнего ID. Автоматическое объединение RF4DB и RF4-STAT пока запрещено: одна и та же публикация может присутствовать в обоих агрегаторах, но надёжного общего первичного ключа нет.

Реализовано

  • rf4_research/community_sources.py — fail-closed HTML-парсеры уловов, точек и вторичных каталогов;
  • parse_rf4map_waterbodies — отдельный fail-closed каталог вторичных RF4MAP candidates;
  • parse_rf4stat_waterbodies — отдельный fail-closed каталог вторичных RF4-STAT metrics;
  • parse_rf4db_detail — отдельное обогащение одного RF4DB-улова;
  • python -m rf4_research.community_cli — read-only CLI одного ограниченного снимка;
  • обезличенные минимальные фикстуры для каждого контракта;
  • тесты всех извлекаемых полей, locked-координат и отказа на постороннем HTML;
  • живой контрольный прогон без сохранения персональных данных и изображений в репозиторий.

На живых HTML-снимках RF4MAP и RF4 Posts получены соответственно 30 индивидуальных наблюдений и 6 видов рыб одной точки. Оба результата укладываются в nullable-контракт, имеют отдельные пространства ID и не смешиваются с RF4DB/RF4-STAT. Для RF4MAP добавлен отдельный ручной parser каталога /lakes: он возвращает только вторичные candidates имени, внешнего ID и видового счётчика, не создаёт canonical waterbody и не назначает media. Разрешение и минимальный интервал 30 минут подтверждены; все источники включены миграцией 0012. RF4 Posts трактуется как агрегированная точка, а не индивидуальный улов.

Перед продуктивным импортом

  1. Сохранить подтверждение разрешения и согласованные лимиты запросов.
  2. Расширять добавленные алиасы рыб и водоёмов по мере ручной проверки новых значений.
  3. При необходимости пересмотреть консервативные начальные уровни доверия 70/65/60/55/50.
  4. Расширять контрольную выборку автопубликации по мере появления полных наблюдений.
  5. Не хранить и не проксировать изображения без отдельного условия разрешения; на первом этапе достаточно исходной ссылки.

Staging

Миграция 0008 добавляет справочник data_source и таблицу external_observation. Уникальность (source_system, source_external_id) делает повторную загрузку идемпотентной; first_seen_at сохраняется, last_seen_at и payload обновляются. Вес, координаты и время могут отсутствовать.

Загрузка принимает только известные источники, HTTPS-ссылки соответствующего домена и значения в допустимых диапазонах. Все записи получают статус staged; таблица не связана с расчётом активности. Тест доказывает путь HTML → ExternalCatch → JSON → external_observation без потери provenance.

Контрольная загрузка в PostgreSQL создала 139 staging-записей: 23 rf4db с координатами, 100 rf4stat-fishing с весом и 16 rf4stat-post с весом. Немедленный повтор дал created=0, updated=139, подтвердив идемпотентность на реальной БД. Миграция 0012 включает все пять разрешённых источников.

Миграция 0009 добавляет устойчивые алиасы внешних рыб и водоёмов, канонические ссылки и состояние ручной проверки. Страница /admin/external-sources позволяет сопоставить, отклонить или явно опубликовать наблюдение. После миграции 0012 повторный импорт автоматически публикует запись только при одновременном наличии подтверждённых алиасов конкретного источника, координат и веса; остальные записи остаются в staging. Поэтому текущие 139 неполных записей не опубликованы.