Docker-сервис, выбор основы и сравнение моделей, сборщик датасета
docker / build (push) Failing after 39s
docker / build (push) Failing after 39s
- Docker: Dockerfile (CPU), compose с FlareSolverr, настройка через DUB_* переменные, токен доступа к /predict, tools/pack_models.py, workflow Gitea Actions, docs/docker.md - Модель грузится офлайн (config.json рядом с весами); общий код вынесен в src/spans.py, сервису не нужны sklearn/matplotlib/pandas - Обучение: профили tiny2/base/large/modern, запуски в models/runs, реестр и честное сравнение на одной тестовой выборке (src/runs.py), пункт меню «Модели» - Датасет: язык и аудио-параметры дорожек, 18+ по строкам «Аудио», ручные метки по ссылкам, переиндексация сохранённого HTML, параллельная сборка, сбалансированная выборка - Тексты страниц (data/pages) больше не хранятся в git Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d155b8584b
commit
efc9a4f56a
411 files changed
+87495
-27363
No files matched your search
@@ -0,0 +1,187 @@
|
||||
# Сбор датасета: `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`), поэтому они
|
||||
повторяют логику правил. Для нарезки внутри строки («Дублированный,
|
||||
многоголосый») нужна ручная проверка — режим ревью ещё не сделан.
|
||||
|
||||
## Разнообразная выборка (режим 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 → «Пересобрать всё заново».
|
||||
Reference in new issue
Block a user