Files
DenozordecandClaude Opus 5.5 89ffe4375b
docker / build (push) Successful in 39s
Документация: кодек-строки, аудит дорожек, текущие метрики
README: метрики модели 02.11.2026 (test 4 377 строк, e2e по трекерам), размер
датасета, kinozal-вкладки. dataset.md: размер снимка, колонки studio_source и
audio_raw. architecture.md: кодек-строки как позитивы сегментатора, E2E_MODEL.
collecting.md: tools/audit_tracks.py. training-windows.md: доразметка, сравнение
кандидата и постановка в models/best и Docker. plan.md: шаг «аудит дорожек».

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 21:55:43 +07:00

18 KiB
Raw Permalink Blame History

Сбор датасета: tools/collect.py

Интерактивный сборщик страниц rutracker / nnm-club / kinozal. Логин делает человек в обычном окне Chrome, скрипт пароли и cookie не видит.

.venv\Scripts\python tools\collect.py          # меню

Главное меню состоит из двух пунктов и подменю:

  1. Собрать датасет: окна, вход, сбор (новые и/или дособрать размеченные), build, prepare_data.
  2. Переобучить и протестировать: prepare_data, обучение сегментатора в models/segmenter_v2 (по желанию ещё и основной модели), tests/run_tests.py, таблица «правила / старые веса / новые веса» по трекерам и вывод, лучше ли новые; подмена весов только после вашего «y» (старые уходят в models/segmenter_old_<время>).
  3. Дополнительно: отдельные шаги из таблицы ниже.

Подменю «Дополнительно»:

Пункт Что делает
1 Запускает Chrome (один процесс, общий профиль), открывает по окну на трекер, ждёт Enter, проверяет статус входа (вошли / гость / не определено)
2 Новые раздачи из списков разделов (viewforum.php?f=…, для kinozal — адрес списка). По потоку на трекер, у каждого своё окно. Продолжает с места остановки
3 Дособрать страницы для раздач, которые уже размечены, но страницы нет (nnm, kinozal)
4 data/raw → data/pages/*.txt + новые строки в data/labels.csv
5 Импорт старого harvest без браузера (только текст поста)
6 Статус по трекерам

Те же операции без меню: windows, collect, backfill, build, import-legacy, status (см. python tools/collect.py -h).

Интерфейс

Главное меню (rich) показывает сводку (размечено, страниц, meta, модели, порт Chrome). Пункт 3 — статистика по трекерам: покрытие и состав датасета (тип, разрешение, кодек, годы, языки). Во время сбора идёт живая панель: по каждому трекеру состояние, прогресс, сохранено, ошибки, скорость (стр/мин по последним сохранениям), время, ETA, текущий раздел и последняя раздача. Ctrl+C останавливает сбор после текущей раздачи.

Метаданные релизов: data/meta.csv

build (и команда meta) строит из сохранённых страниц таблицу, одна строка на релиз (tools/meta.py; заходить на трекеры повторно не нужно):

Группа Поля
Название title, ru_title, orig_title, year, kind (film / series / cartoon / anime), is_series, season, episodes, episodes_total, section
Видео quality, resolution, video_codec, hdr, bit_depth, fps, container, size_gb, duration_min
О фильме countries, genres, directors, cast, age_limit, mpaa, release_group, source_media
Звук audio_langs, orig_audio, n_audio, audio_tracks (JSON: язык, кодек, каналы, битрейт, тип DUB/MVO/DVO/AVO/VO/ORIG, студия, серии, 18+)
Субтитры sub_langs, sub_forced, sub_format

Для старых данных (импорт import-legacy) поля берутся из текста поста; размер раздачи rutracker и nnm виден только на полной странице, поэтому у них он заполнится после дозагрузки (пункт «Дособрать»).

Переиндексация без перекачки

HTML страниц хранится в data/raw, поэтому после правки парсеров данные пересобираются без захода на трекеры: пункт 2 «Переобучить» начинается с вопроса «Переиндексировать data/raw?» (то же: collect.py build --rewrite --relabel). Страницы, meta.csv и метки размеченных релизов строятся заново текущими парсерами; прежний labels.csv копируется в data/labels.bak_<время>.csv. Не трогаются ручные метки (пункт 6), релизы без HTML (импорт старого harvest) и релизы, по которым парсер ничего не нашёл.

Обучение по ссылкам

Пункт 6 главного меню: вставляете ссылки на раздачи (rutracker / nnm / kinozal), страницы скачиваются вашим Chrome, парсер строит метки, вы правите их в таблице («2 18» — переключить 18+, «3 d» — удалить, «1 t <тип>», «1 s <студия>») и сохраняете. Метки заменяют прежние строки релиза в data/labels.csv (studio_source=manual), id попадает в data/manual_ids.txt: такие релизы всегда в train и повторяются при обучении ×5. Дальше «Переобучить».

Метки и инференс берут 18+ и параметры дорожки (кодек, каналы, битрейт) не только из строк «Перевод», но и из строк «Аудио … |Студия| 18+» (src/audio18.py): у одной студии может быть обычная дорожка и дорожка 18+.

Автопоиск разделов

При первом запуске пункта 1 (режим «новые раздачи») после входа в аккаунты приложение само находит разделы с зарубежными фильмами и сериалами (tools/discover.py) и кэширует их в data/raw/_sections.json:

  • rutracker, nnm: разделы выбираются по названию (зарубежное кино и сериалы, мультфильмы, новинки, классика, годовые «Фильмы 2021-2025»; наше кино, азиатское, музыка, Apple, коллекции исключены). Форматы DVD / HD / UHD / 3D и годы покрываются самими разделами.
  • kinozal: ваши списки «все фильмы» (c=1002) и «сериалы» (c=46), затем сетка год × формат × категория (4K только с 2012 и т. д.).
  • Лимит делится между разделами поровну, чтобы выборка не состояла из одного.
  • Раздел, который не удалось проверить, остаётся в списке; результат неполной загрузки кэш не затирает. Искать заново: «Дополнительно» → 7 или collect.py discover --force.

Сохранённые страницы читаемы

В data/raw/<трекер>/<id>.html лежит снимок страницы «как на сайте»: UTF-8 (<meta charset>), <base> на адрес раздачи (картинки подгружаются с сайта), таблицы стилей вынесены в data/raw/_css/<хеш>.css (общие для всех страниц), скрипты убраны, чтобы страница из файла не уходила на сайт. Открывается двойным кликом. Таблицы стилей чужого домена (rutracker, nnm) остаются ссылкой на сайт и работают при наличии интернета.

Страницы, сохранённые раньше, чинит python tools/collect.py repair-html (кодировка, <base>, стили сайта одной загрузкой со страницы трекера; нужен Chrome и вход, --no-css — без браузера). Время файлов не меняется, кэши разбора остаются.

Где что лежит

  • data/raw/<трекер>/<id>.html|json — страница целиком (outerHTML после загрузки вкладок kinozal) и поля для парсера. В git не попадает.
  • Профиль Chrome — %LOCALAPPDATA%\dub-ai-harvest\chrome-profile, вне репозитория (DUB_CHROME_PROFILE, DUB_CHROME_PORT меняют каталог и порт).
  • tools/harvest/harvest_core.py — перенесённый dataset.py (CDP-клиент и парсеры меток), единственная правка — переменные окружения для путей.

id страниц

release_id в labels.csv совпадает с именем data/pages/<id>.txt. Раздачи, размеченные раньше, сохраняют прежний числовой id (их разбиение train/test не меняется); новые получают префикс rt-, nnm-, kz-, чтобы id разных трекеров не пересекались. Коллизий в текущих данных нет, но один id уже встречался в сырых данных двух трекеров.

Полные и урезанные страницы

Импорт старого harvest (пункт 5) даёт страницу из сохранённого текста поста: без шапки сайта, соседних раздач и заголовка. Такие страницы перечислены в data/pages_postonly.txt. При обучении и оценке сегментатора их стоит считать отдельно: на инференсе модель видит полную страницу.

Что в метках слабое

Метки строятся парсерами (tools/harvest/harvest_core.py), поэтому они повторяют логику правил. Для нарезки внутри строки («Дублированный, многоголосый») нужна ручная проверка — режим ревью ещё не сделан.

Студии, которые парсеры раньше теряли (доразметка от 02.11.2026):

  • nnm, «Перевод: Дублированный (Невафильм)» — строки «Перевод:» (tech) шли с «(не указана)», хотя студия названа в той же части. Модель училась её не извлекать. Теперь — nnm_part_studio (скобки или «… - Студия»; тип, «x2», «Лицензия», источник вроде iTunes/Blu-ray — не студия). +3 051 студия.
  • kinozal, заголовок «… / ПМ (LostFilm, HDrezka Studio), СТ / …» — во «Техданных» только «Перевод: Профессиональный многоголосый», студии названы в заголовке и в строках «Аудио Rus: … | LostFilm» без типа. Теперь — kz_title_rows: строка на каждую студию из заголовка, которой нет на странице (studio_source=title, вход — тот же сегмент, что строит сервис из заголовка; строка «Аудио» с этой студией — в audio_raw). +4 219 строк в 3 007 релизах.
  • Студии только в кодек-строках («Аудио 2: AC3 … (MVO, LostFilm)», «Аудио Rus: … | TVShows», «… • DUB | LeDoyen • UKR») — разметка шла по «Перевод:», кодек-строка была лишь audio_raw у найденной дорожки. Теперь — codec_line_rows: строка на каждую студию русской/украинской кодек-строки, которой нет среди меток релиза (studio_source=codec, вход — сегмент, как его режет сервис; тип — из строки, иначе единственный тип релиза, иначе «неизвестно»). Студия — из словаря меток (≥ 5 строк) или из скобок/|…|; раскладка, кодек, «поздний», «серии» — не студия. +6 428 строк в 2 862 релизах (kinozal 3 444, nnm 1 609, rutracker 1 375). Аудит, откуда взялась доработка: reports/tracks_audit.md.

Повторить аудит дорожек по data/raw (сколько студий из кодек-строк, «Перевод:» и заголовков не попало в метки, мусор в колонке студий, форматы, которые не ловят регулярки): .venv\Scripts\python tools\audit_tracks.py → reports/tracks_audit_numbers.md (--cache путь.pkl ускоряет повторный запуск). Выводы и план — reports/tracks_audit.md.

Сборщик делает это при переиндексации. Для уже собранного labels.csv без пересборки страниц: .venv\Scripts\python tools\relabel_studios.py (копия — data/labels.bak_relabel_*.csv; --dry-run — только статистика; повторный запуск ничего не добавляет).

Разнообразная выборка (режим balanced)

Списки разделов идут от новых к старым, поэтому чтение подряд даёт только свежие релизы. По умолчанию (Настройки → режим balanced, tools/diversity.py):

  • страницы раздела берутся вразброс по всей глубине (число страниц читается из пагинации; посещённые запоминаются в _state.json, круг по разделу продолжается с места остановки);
  • с каждой страницы берётся не всё, а per_page тем (по умолчанию 6) из самых малочисленных корзин «год (до 2010 — десятилетие) × качество (4K / 1080 / 720 / SD) × фильм/сериал»; уже собранное считается по data/meta.csv;
  • режим sequential — прежнее чтение подряд.

Скорость переиндексации

Разбор HTML (страницы, метки, meta.csv) идёт в нескольких процессах: по умолчанию число ядер минус два (до 12); меняется в «Настройки» (workers, 0 — авто, 1 — без процессов). meta.csv берёт текст из уже записанных data/pages, а не разбирает HTML второй раз. На выборке в 600 раздач — 45 с → 8 с при тех же результатах.

Если сбор «завис»

  • В панели у трекера теперь видно номер раздачи, которая качается: скачиваю 6894333.
  • Короткая страница (закрытая или перенесённая тема), которая загрузилась и не меняется, принимается через ~5 с; раньше сборщик ждал таймаут 45 с и повторял его.
  • Раздача дольше 40 с попадает в ошибки как «медленно, N с» (id можно открыть вручную).
  • Сторож: раздача дольше 150 с — вызов к вкладке обрывается, вкладка переподключается, сбор идёт дальше.

Скорость и повторный разбор

  • Вкладки. Сбор идёт в нескольких вкладках одного трекера (общий Chrome, общий вход). Число вкладок — пункт меню «Настройки» (1–4, по умолчанию 3), запоминается; в командах collect / backfill флаг --tabs. Больше вкладок — быстрее, но выше риск лимитов и проверок Cloudflare: при ошибках снизьте до 1–2.
  • Без лишних пауз. Ожидание вкладок kinozal и загрузки страниц опрашивает состояние, а не спит фиксированное время; тяжёлые темы не ждут complete; удалённые раздачи определяются сразу и запоминаются (data/raw/_dead.json).
  • Ничего не разбирается дважды. Сбор пропускает уже сохранённые, размеченные и удалённые раздачи и продолжает списки с места остановки. build запоминает «подпись» файлов (data/raw/_built.json, _meta_cache.json): повторный запуск разбирает только новое и изменённое (на 2800 релизах: 59 с → 2 с). Кэш сбрасывается сам, если поднять PARSE_VERSION (collect.py) или META_VERSION (meta.py) после правки парсеров; вручную: «Дополнительно» → 4 → «Пересобрать всё заново».