Files
grabber-ai/docs/collecting.md
T
DenozordecandClaude Opus 5.5 e3af778068 Студии из кодек-строк: codec_line_rows, доразметка, аудит дорожек
tools/audit_tracks.py и reports/tracks_audit.md — аудит всех дорожек
техданных по data/raw с планом. Пункт 1 плана: harvest_core.codec_line_rows
добавляет студии из строк «Аудио 2: AC3 … (MVO, LostFilm)», «Аудио Rus: … |
TVShows» (studio_source=codec), которых нет среди строк релиза; тот же шаг
в tools/relabel_studios.py (повторный запуск ничего не добавляет).
labels.csv: +6 428 строк в 2 862 релизах (kinozal 3 444, nnm 1 609,
rutracker 1 375), со студией 29 331 -> 35 759. tests/e2e_segmenter.py:
модель через E2E_MODEL.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-02 20:30:52 +07:00

213 lines
18 KiB
Markdown
Raw 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.
# Сбор датасета: `tools/collect.py`
Интерактивный сборщик страниц rutracker / nnm-club / kinozal. Логин делает
человек в обычном окне Chrome, скрипт пароли и cookie не видит.
```powershell
.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`.
Сборщик делает это при переиндексации. Для уже собранного `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 → «Пересобрать всё заново».