[2026-09-27] eagle: personal/plans/music-artist-albumartist-repair.md personal/tech/id3-tag-repair.md personal/tech/scripts/find_va_author.py

This commit is contained in:
Alexey Martemyanov committed 2026-09-27 14:24:18 +06:00
1 parent 85b682701a
commit c4e44ac277
3 files changed
+302 -8

No files matched your search

+62
View File
@@ -0,0 +1,62 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Класс A2 (второй детектор): albumartist='Various Artists', но это АЛЬБОМ ОДНОГО АВТОРА.
Признак: папка названа по автору (или автор доминирует в artist), а стоит 'Various Artists'.
Дополняет find_va_misuse.py (тот ловит «>50% один artist» без учёта имени папки).
Питфолл: 47 папок-сборников дают «кандидат» ложно (Sbornik_Novij_Rok, !Retro, !Radio/*,
Final Fantasy VI, трибьюты, Gazgolder) — они в SKIP. Остаток после чистки:
`Блестящие, Фриске` и `Eminem,50cent` — папки-склейки, Various Artists там ВЕРЕН.
Использование: python3 find_va_author.py
Итог сессии 10: кандидатов 2 (оба защитимые).
"""
import csv
import collections
import os
P = '/Users/admin/Downloads/music-tags/APPLY-PLAN.csv'
rows = list(csv.DictReader(open(P, encoding='utf-8-sig', newline='')))
def s(v):
return (v or '').strip()
# музыкальные папки-КОНТЕЙНЕРЫ, где Various Artists законен сам по себе
SKIP_PARTS = ('!Radio', 'Sbornik', 'Трибьют', 'VA ', 'Сборник', 'Сборка')
SKIP_EXACT = {
'!Retro', '!Rock&Folk/!rock_o_pop', '!Классика', '!Rock&Folk/Неголубой огонёк НГ 2004',
'!A Not sorted/Sbornik_Novij_Rok',
}
by = collections.defaultdict(list)
for r in rows:
if s(r['new_albumartist']) == 'Various Artists':
by[r['folder']].append(r)
print("КАНДИДАТЫ: папка-АВТОР + Various Artists\n")
hits = 0
for folder, rs in sorted(by.items()):
if any(p in folder for p in SKIP_PARTS):
continue
if folder in SKIP_EXACT or any(folder.startswith(x) for x in SKIP_EXACT):
continue
fam = os.path.basename(folder) # имя самой папки
parent = os.path.basename(os.path.dirname(folder)) # имя родителя
arts = collections.Counter(s(r['new_artist']) for r in rs if s(r['new_artist']))
top, cnt = arts.most_common(1)[0] if arts else ('', 0)
n = len(rs)
# автор = доминирующий artist, и он же имя родительской папки
if top and cnt >= 2 and (top == parent or top in parent or parent in top):
print(f" {n:4d} файлов top={top!r} ({cnt}/{n}) автор-папка={parent!r}")
print(f" {folder}")
hits += 1
# либо альбом назван так же, как папка, и 1 исполнитель
elif n <= 20 and cnt >= max(2, n * 0.4):
print(f" {n:4d} файлов top={top!r} ({cnt}/{n}) папка={fam!r}")
print(f" {folder}")
hits += 1
print(f"\nвсего кандидатов: {hits}")