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>
18 KiB
Сбор датасета: tools/collect.py
Интерактивный сборщик страниц rutracker / nnm-club / kinozal. Логин делает человек в обычном окне Chrome, скрипт пароли и cookie не видит.
.venv\Scripts\python tools\collect.py # меню
Главное меню состоит из двух пунктов и подменю:
- Собрать датасет: окна, вход, сбор (новые и/или дособрать размеченные),
build,prepare_data. - Переобучить и протестировать:
prepare_data, обучение сегментатора вmodels/segmenter_v2(по желанию ещё и основной модели),tests/run_tests.py, таблица «правила / старые веса / новые веса» по трекерам и вывод, лучше ли новые; подмена весов только после вашего «y» (старые уходят вmodels/segmenter_old_<время>). - Дополнительно: отдельные шаги из таблицы ниже.
Подменю «Дополнительно»:
| Пункт | Что делает |
|---|---|
| 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 → «Пересобрать всё заново».