Files
rf4-spotter/docs/data-sources.md
T
ik 787a5065bc
CI / backend-and-migrations (push) Canceled after 0s
CI / astro-build (push) Canceled after 0s
CI / dependency-audit (push) Canceled after 0s
CI / compose-e2e (push) Canceled after 0s
data: review next prioritized media assets
2026-09-13 16:53:19 +07:00

18 KiB
Raw Blame History

Источники данных RF4: исследование этапа 0

Дата первоначальной проверки: 2 сентября 2026 года. Повторная проверка страницы и robots.txt: 3 сентября 2026 года. Исследовалась только публичная веб-страница; игровой клиент, его трафик и закрытые протоколы не исследовались.

Краткий вывод

Для первого адаптера следует получать серверный HTML страницы https://rf4game.de/records/region/RU/. На момент проверки таблица уже находится в исходном HTML и не требует JavaScript, авторизации или обхода защиты. Доступного JSON/XHR endpoint именно для рекордов не обнаружено.

Страница содержит общий WordPress AJAX-клиент с адресом /wp-admin/admin-ajax.php, но опубликованные на странице действия gajax_Ratings относятся к рейтингу игроков (rating, rating_list, best). Действия для таблицы рекордов не объявлены. Поэтому использовать или подбирать недокументированные AJAX-параметры не рекомендуется.

Подтверждённые URL и параметры

  • Абсолютные рекорды региона RU: https://rf4game.de/records/region/RU/.
  • Недельная форма URL: https://rf4game.de/records/weekly/region/RU/.
  • В навигации страницы перечислены регионы: GL, RU, DE, US, FR, CN, PL, KR, JP, EN.
  • В навигации категорий видны: records, ultralight, recordslight, bottomlight, sea, telestick.

Категория и регион кодируются сегментами URL, а не query-параметрами. Фактический успешный ответ абсолютной страницы был 200, text/html; charset=UTF-8, с Cache-Control: no-cache. Запрос GET /robots.txt вернул 404, то есть явных инструкций для роботов на этом пути при проверке не было. Это не является разрешением на интенсивный сбор.

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

Подтверждённый DOM-контракт

Корень таблицы: div.records.flex_table. Верхняя строка имеет шесть семантических классов в таком порядке:

  1. fish — рыба;
  2. weight — вес;
  3. location — водоём;
  4. bait — приманка/наживка (отображаемое значение находится в атрибуте title у .bait_icon);
  5. gamername — игрок;
  6. data — дата (именно data, не date).

Каждый div.records_subtable объединяет до нескольких результатов одной рыбы. Название рыбы находится только в заголовочной строке группы (.fish .text); вложенные строки имеют пустую ячейку рыбы и наследуют название группы.

Подтверждённые внутренние поля OfficialRecord:

Поле Источник/нормализация
region сегмент URL, верхний регистр
category сегмент URL/аргумент запуска
fish .fish .text заголовка группы
weight_g .weight; kg/g приводятся к целым граммам
waterbody .location
bait .bait_icon[title], nullable
player .gamername, nullable
record_date .data, формат D.MM.YY/DD.MM.YY
source_url URL полученной страницы

Изображения официального сайта

Проверка 12 сентября 2026 года не обнаружила стабильного публичного каталога вида канонический slug → изображение для рыб, водоёмов или снастей. Официальная галерея водоёмов и категория рыб содержат тематические публикации, а руководство — иллюстрации интерфейса, оснасток и карт. Это медиа-галереи, а не полный справочник с устойчивыми entity ID.

Повторная сверка локальной альфы показала 2 рыбы, 2 водоёма и 3 приманки. Первый userguide-manifest содержал 69 кандидатов: 67 общих reference и 2 изображения карт. После расширения сбора локальный audit на 13 сентября показывает 24 approved-ассета: 2 рыбы, 12 приманок/наживок и 10 общих reference. Наличие картинки в очереди всё равно не считается покрытием каталога; coverage появляется только после сохранения, визуальной проверки и назначения canonical entity_key.

Прямой индекс /media/fische/ вернул только общие изображения оформления (flags/de.png, banner_de.png): содержимое галереи загружается динамически. Эти файлы остаются reference, а не ошибочно маркируются как рыбы. Исследование допустимого gallery endpoint должно использовать обычный публичный контракт сайта и тот же общий cooldown, без обхода защит.

Контрольная сверка 12–13 сентября 2026 года: RF4DB показывает 19 водоёмов и 252 вида рыб. Страница RF4MAP /fishes дала 228 уникальных кандидатов изображений рыб и 149 изображений приманок. Это означает минимум 24 отсутствующие рыбьи иконки; 149 нельзя считать числом всех снастей, поскольку в него не входят полные каталоги удилищ, катушек, лесок, крючков и прочих компонентов. Общие userguide-карты являются reference, а не картами конкретных сущностей, поэтому текущее waterbody-покрытие равно 0/19. Канонически подтверждены 2 из 252 fish-кандидатов и 12 tackle/bait-кандидатов; остальные entity-кандидаты остаются карантинными.

Страница рекордов визуально использует .bait_icon, но подтверждённый parser-контракт извлекает только .bait_icon[title]. Ни parser, ни Fish/Waterbody/Bait модели и API-схемы сейчас не сохраняют image URL. Даже если URL удастся извлечь из CSS или обновлённого DOM, он может быть presentation asset, меняться независимо от названия и покрывать только приманки, попавшие в рекорды.

До отдельного разрешения на медиапубликацию изображения официального сайта не скачиваются, не хотлинкаются и не отображаются как собственные. Разрешение использовать фактические данные не трактуется как разрешение републиковать графические произведения.

Fallback строится на собственных лёгких SVG: осмысленные семейства силуэтов рыб, типовые глифы снастей и детерминированные абстрактные отпечатки водоёмов. Текстовое название всегда остаётся основным идентификатором; абстрактный контур водоёма не называется картой, а глиф приманки — изображением конкретной модели.

С 12 сентября 2026 года разрешён локальный сбор медиаресурсов. python -m rf4_research.media_cli URL делает один учтённый HTML-запрос и добавляет кандидатов в data/media/manifest.json; --download-one сохраняет ровно один ожидающий asset по SHA-256 в data/media/files/. Оба режима используют общий cooldown площадки. Перед записью проверяются raster-формат, совпадение MIME и предел 40 Мп; manifest получает размеры, объём и время загрузки. Постоянные 404/410, запрет доступа и невалидный файл получают отдельные статусы и не запирают начало очереди. Статус queued или stored не означает соответствие сущности или разрешение на публичный вывод. Ручная команда с --review-url, --decision, --entity-type и --entity-key переводит сохранённый файл в approved; неподходящий материал явно получает rejected.

python -m rf4_research.media_cli --audit не использует сеть: команда выводит сводку статусов и завершается с ошибкой при отсутствующем/изменённом файле, несовпадении SHA-256 или dimensions/MIME, некорректном approved-сопоставлении и наличии бесхозного файла.

python -m rf4_research.media_cli --queue-plan также не использует сеть. Он читает manifest и общий cooldown-state, группирует queued-ассеты по фактическому домену, показывает готовность и оставшееся время, состав очереди по типам и один следующий кандидат с приоритетом waterbody → fish → tackle → reference. Команда намеренно сообщает, что точные catalog gaps неизвестны, пока baseline содержит только количества без канонических имён.

python -m rf4_research.media_cli --coverage также работает локально и сравнивает manifest с датированным data/media/catalog-baseline.json. Неизвестные контрольные значения хранятся как null: отчёт не выдаёт число найденных приманок за полноту всего каталога снастей.

Координат, проводки, времени поимки и устойчивого внешнего идентификатора записи в этой таблице нет. Локализация зависит от домена/языка страницы: проверенная .de-страница возвращает немецкие названия рыб, водоёмов и приманок даже для региона RU.

Рекомендуемый режим получения

  • Один понятный User-Agent, таймаут 20 секунд.
  • Начать не чаще одного раза в 60 минут на выбранную комбинацию категории и региона.
  • Не запускать параллельный обход всех регионов/категорий.
  • Добавить кэш, ограниченные повторы с экспоненциальной задержкой и общий лимит запросов перед продуктивным импортом.
  • При исчезновении таблицы, изменении порядка классов или ошибке HTTP считать запуск неуспешным и сохранять прежние данные.
  • Повторно проверить условия использования и связаться с владельцем сайта до регулярного производственного сбора; отсутствие robots.txt не заменяет разрешения.

При повторной проверке 3 сентября 2026 года страница рекордов по-прежнему публично отдавала таблицу, а https://rf4game.de/robots.txt снова вернул 404. Явного разрешения на автоматический сбор это не даёт. Поэтому планировщик реализован как opt-in профиль Compose scheduler, не запускается обычной командой docker compose up и не должен включаться во внешнем окружении до проверки условий использования или согласования с владельцем сайта.

Сравнение с hurfy/rf4-api

Репозиторий hurfy/rf4-api создан в августе 2024 года; последний push, видимый через GitHub API на дату исследования, был 14 января 2025 года. README прямо называет проект находящимся в разработке. Он использует Django, Celery и браузерный WebDriver, перебирает регионы и категории, затем разбирает те же классы records_wrapper, records_subtable, gamername, weight, location, bait_icon, data.

Полезные архитектурные идеи:

  • отделить построение URL, получение HTML, разбор и сохранение;
  • передавать регион и категорию вместе с сырой страницей;
  • нормализовать вес и текст до записи в БД.

Что нельзя переносить без проверки:

  • список категорий проекта ограничен records, ultralight, telestick и уже не отражает всю текущую навигацию;
  • WebDriver избыточен для подтверждённой серверной HTML-страницы;
  • парсер опирается на позиционный поиск .rows и не проверяет контракт колонок;
  • заявленные в README охват и расписание сами по себе не доказывают текущую работоспособность.

Фикстура и исследовательский код

tests/fixtures/records_ru_sample.html — сокращённая обезличенная фикстура, сохраняющая подтверждённую вложенность и классы. Реальные ники и реальные сочетания уловов в неё не переносились. rf4_research/records.py получает ровно одну переданную страницу, проверяет контракт колонок и выдаёт список типизированных OfficialRecord.

Unit-тест покрывает заголовочную и вложенную записи, килограммы/граммы, большой вес с разделителем тысяч и отказ при изменении колонок.

Что остаётся предположением

  • Все перечисленные категории и регионы стабильно отдают таблицу при умеренной частоте запросов.
  • Формат двухзначного года сохранится; сейчас он интерпретируется стандартным правилом Python как 2000-е для наблюдаемых значений.
  • Сайт разрешит регулярный производственный опрос раз в час.
  • DOM-классы останутся стабильнее локализованных заголовков.
  • Отсутствие найденного JSON endpoint не доказывает, что внутреннего endpoint вообще нет; подтверждено лишь, что для публичного сценария он не нужен и на странице не объявлен.

Источники