Sort_YM/README.ru.md
Andrew Pimenov 544765db3f split docs into EN/RU, add MIT license
README/ARCHITECTURE now bilingual (EN default, .ru.md cross-linked) per public-repo convention; added MIT license and Credits/License sections; tightened .gitignore against stray AI-tool files.
2026-08-09 11:59:39 +03:00

8.1 KiB
Raw Blame History

English

Sort YM

Раскладывает лайкнутые треки Яндекс.Музыки по плейлистам вида Жанр — RU / Жанр — INT.

$ python -m sort_ym report

Распределение по плейлистам:
  Рок — INT: 143
  Рок — RU: 287
  Рэп — RU: 512
  ...

Отчёт сохранён: out/report.csv

Установка

Требования: Python 3.11+ (используется tomllib из стандартной библиотеки), Windows/Linux/macOS, доступ в интернет.

python -m venv .venv
.venv\Scripts\pip install -r requirements.txt

Для разработки (тесты):

.venv\Scripts\pip install -r requirements-dev.txt

Что делает

.venv\Scripts\python -m sort_ym auth                    # войти в аккаунт Яндекса через device-flow и сохранить токен в .token
.venv\Scripts\python -m sort_ym fetch                   # скачать лайкнутые треки (cache/tracks.json) и жанры их артистов (cache/artist_genres.json); аккаунт не меняет
.venv\Scripts\python -m sort_ym report                  # посчитать жанр и язык каждого трека, сохранить out/report.csv (аккаунт не меняет)
.venv\Scripts\python -m sort_ym apply --limit 20 --yes  # пробный запуск: создать плейлисты и добавить в них первые 20 треков
.venv\Scripts\python -m sort_ym apply --yes             # создать плейлисты и добавить в них все треки (меняет аккаунт)

При повторных запусках fetch докачивает только новые треки, а apply не дублирует уже добавленные треки.

Полная очистка кэша

Если требуется начать с чистого листа (переполучить все данные с нуля), удалите папку cache/:

Remove-Item -Recurse -Force cache

Кэш состоит из четырёх файлов:

  • cache/tracks.json — список лайкнутых треков и их метаданные (включая id артистов);
  • cache/artist_genres.json — жанровые теги каждого артиста (может быть несколько на артиста);
  • cache/genre_catalog.json — снимок дерева жанров Яндекса на момент последнего запуска;
  • cache/lyrics_lang.json — определённые языки текстов для каждого трека.

Удаление cache/ заставит fetch и report переполучить всё с нуля при следующем запуске.

Также можно удалить сгенерированный отчёт:

Remove-Item -Recurse -Force out

Это просто результаты анализа, их удаление не повлияет на следующий запуск report.

Важно: файл .token (OAuth-токен) не входит в кэш и не удаляется при очистке cache/. Очистка кэша вас не разлогирует. Если нужна повторная авторизация, удалите .token отдельно:

Remove-Item .token

Как определяется жанр и язык

  • Жанр определяется на под-жанровом уровне (Рок, Панк, Инди, Альтернатива, Метал, ..., не только 11 крупных групп), комбинируя два сигнала:

    1. Жанр альбома трека (genre_raw) — сигнал по конкретному треку.
    2. Жанры артиста (Artist.genres, может быть несколько тегов на артиста, точнее одного альбомного жанра) — сигнал по исполнителю в целом.

    Если сигналы совпадают — берётся под-жанр как есть. При конфликте: если альбомный тег общий ("зонтичный", вроде rock/alternative/pop — типичный дефолт Яндекса низкой уверенности) — побеждает жанр артиста; если альбомный тег точный/специфичный (numetal, dnb, shanson) — побеждает он, потому что это, скорее всего, реальный эксперимент артиста в другом жанре, а не шум. Так один и тот же артист с разными по духу треками (например, рОк-трек и панк-трек) раскладывается по разным плейлистам, а не весь скопом по одному "основному" жанру.

    Под-жанровые группы меньше small_group_min (по умолчанию 12 треков, config.toml) схлопываются в родительскую крупную корзину (Поп, Рок, Метал, Рэп, Электроника, Джаз и блюз, Классика, Фолк и world, Инди и альтернатива, Саундтреки, Разное), чтобы не плодить плейлисты на 1-2 трека. Реализация — sort_ym/genres.py (classify_track, ROOT_BUCKET) — таблица корней легко дополняется, если Яндекс вернёт незнакомый корневой жанр.

  • Язык — гибрид:

    1. Если у трека есть текст песни — реальный язык из API (ru → RU, иначе → INT).
    2. Иначе — подсказка по жанру (rusrap, shanson, bard, ...).
    3. Иначе — по алфавиту названия/исполнителя (кириллица/латиница).
    4. Если ничего не сработало — трек попадает в ... — Не определено.

После report в консоли также печатается список нераспознанных жанров (попавших в «Разное»), чтобы можно было дополнить таблицу в sort_ym/genres.py.

Handy things

  • Первый прогон apply делайте с --limit 20 --yes и проверьте результат в приложении, прежде чем запускать на все ~2000 треков.
  • Настройки задержек между запросами — в config.toml ([throttle]).
  • Минимальный размер под-жанрового плейлиста — config.toml ([classify] small_group_min).

Риски (неофициальный API)

Официального API для личной библиотеки Яндекс.Музыки нет — инструмент использует неофициальную библиотеку yandex-music. OAuth-токен в .token даёт полный доступ к аккаунту Яндекса — храните его локально и не публикуйте. Инструмент выполняет только безопасные действия (чтение лайков, создание плейлистов, добавление треков) и ничего не удаляет.

For developers

Python 3.11+, yandex-music==3.0.0, стандартная библиотека (tomllib, csv, unicodedata).

.venv\Scripts\python -m pytest tests/ -v
.venv\Scripts\python -m sort_ym auth
.venv\Scripts\python -m sort_ym fetch
.venv\Scripts\python -m sort_ym report
.venv\Scripts\python -m sort_ym apply --limit 20 --yes

Структура кода и поток данных — в ARCHITECTURE.ru.md.

Credits

Andrew Pimenov

License

MIT License