From d0f70e45eb774f334d3fabd2bfc616b668ae7efb Mon Sep 17 00:00:00 2001 From: jxxghp Date: Tue, 20 Oct 2026 12:09:50 +0800 Subject: [PATCH] fix(music): strip Gazelle slash-separated release specs --- app/domain/meta/metamusic.py | 16 ++++++++++- tests/fixtures/music_pt_corpus.json | 2 +- tests/test_music_resource_names.py | 42 +++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/app/domain/meta/metamusic.py b/app/domain/meta/metamusic.py index a7b87872a..11509e3d3 100644 --- a/app/domain/meta/metamusic.py +++ b/app/domain/meta/metamusic.py @@ -239,6 +239,15 @@ _MUSIC_FORMAT_TOKEN_ALT = ( r"DSD(?:64|128|256|512)?|DSF|DFF|SACD|FLAC|ALAC|APE|CUE|WAV|WAVE|AIFF?|PCM|" r"MP3|AAC|M4A|OGG|VORBIS|OPUS|WMA|WEB-?DL|WEBRip|WEB" ) +# Gazelle 将音质、抓轨日志、介质与年份串成斜杠尾链。只匹配完整规格尾链, +# 避免删除作品正文中的斜杠、CD 或 Log;末尾年份仍交由解析器提取。 +_MUSIC_SLASH_SPEC_TAIL_RE = re.compile( + rf"\s+(?:{_MUSIC_FORMAT_TOKEN_ALT})" + rf"(?:\s*/\s*(?:{_MUSIC_FORMAT_TOKEN_ALT}|lossless|Log(?:\s*\(\d{{1,3}}%\))?|" + r"CD|Vinyl|分[轨軌]|整[轨軌]|原抓|自抓|自扫|自掃))+" + r"(?:\s*/\s*(?P(?:19|20)\d{2}))?\s*$", + re.IGNORECASE, +) _MUSIC_VIDEO_TOKEN_ALT = ( r"1080[pi]|720p|2160[pi]|480[pi]|4k|8k|uhd|" r"bluray|blu-ray|bdrip|uhd\s*bd|hddvd|hdvd|hdtv|webrip|remux|" @@ -1474,9 +1483,14 @@ class MetaMusic(MetaBase): 为两种解析引擎统一清理有格式证据的发行尾标与音频文件曲序。 点分发行类型只在音频规格前生效;版本括号保留语义,介质和目录编号 - 不进入检索。文件曲序先于艺人拆分,避免 ``01. Artist`` 成为艺人名。 + 不进入检索。斜杠规格尾链整段剥离并保留年份,正文中的斜杠仍保留。 + 文件曲序先于艺人拆分,避免 ``01. Artist`` 成为艺人名。 + + :param value: 原始音乐资源标题或文件名 + :return: 两种引擎共用的解析文本及待恢复的编号文件曲名 """ text, file_title = self._prepare_filename_input(value) + text = _MUSIC_SLASH_SPEC_TAIL_RE.sub(r" \g", text) text = _MUSIC_EDITION_BRACKET_RE.sub(r"(\1)", text) text = _MUSIC_CATALOG_SPEC_RE.sub("", text) if re.search(r"(?:19|20)\d{2}", text) and len(_SCENE_DOT_RE.findall(value)) >= 3: diff --git a/tests/fixtures/music_pt_corpus.json b/tests/fixtures/music_pt_corpus.json index e2fb79bfa..c43da35fc 100644 --- a/tests/fixtures/music_pt_corpus.json +++ b/tests/fixtures/music_pt_corpus.json @@ -8263,7 +8263,7 @@ "subtitle": "朴树 - 猎户星座 [2017] [专辑] FLAC / Lossless / Log (100%) / Cue", "id": "torrent-1126", "expected": { - "title": "Lie Hu Xing Zuo", + "title": "猎户星座", "artists": [ "Pu Shu" ], diff --git a/tests/test_music_resource_names.py b/tests/test_music_resource_names.py index 94782e01c..d6316be63 100644 --- a/tests/test_music_resource_names.py +++ b/tests/test_music_resource_names.py @@ -9,6 +9,7 @@ from app.chain.search import SearchChain from app.domain.context import MusicInfo, TorrentInfo from app.domain.meta import runtime from app.domain.meta.metamusic import MetaMusic +from app.domain.metainfo import MetaInfo from app.domain.music import match_music_resource from app.schemas.types import MediaType @@ -125,3 +126,44 @@ def test_release_names_without_group_or_cjk_credit(title, artists): """ meta = MetaMusic.parse_resource(title) assert (meta.title, meta.artists, meta.year, meta.audio_format) == ("Album", artists, 2022, "FLAC") + + +@pytest.mark.usefixtures("music_engine") +@pytest.mark.parametrize("title,expected,year", [ + ( + "程响 (Cheng Xiang) - 江南多雨时 [2020] [单曲专辑] FLAC / Lossless / WEB / 2020", + "江南多雨时", 2020, + ), + ( + "群星 (Various Artists) - âge 20th Archives Song Archives [2020] [合辑] " + "FLAC / Lossless / Log (100%) / Cue / CD / 2020", + "âge 20th Archives Song Archives", 2020, + ), + ( + "群星 - 南泥湾 (Nanni Bay) [1990] [专辑] " + "FLAC / Lossless / Log (100%) / Cue / CD / 自抓 / 1990", + "南泥湾 (Nanni Bay)", 1990, + ), + ("Artist - Album FLAC / Lossless / WEB / 2020", "Album", 2020), + ("Artist - Example Album [2020] FLAC / Lossless / Log (100%) / Cue / CD", "Example Album", 2020), + ("Artist - Love / Hate [2020] FLAC / Lossless / WEB / 2020", "Love / Hate", 2020), + ("Artist - Captain's Log (100%) [2020] FLAC / Lossless / CD / 2020", "Captain's Log (100%)", 2020), + ("Artist - CD [2020] FLAC / Lossless / CD / 2020", "CD", 2020), + ("Artist - Album (Live) [2020] FLAC / Lossless / WEB / 2020", "Album (Live)", 2020), +]) +def test_gazelle_slash_specs_preserve_music_identity(title: str, expected: str, year: int) -> None: + """ + Gazelle 规格尾链不进入作品名,正文斜杠、抓轨同名词与版本说明仍须保留。 + + :param title: 含规格尾链的站点资源标题 + :param expected: 应保留的真实作品名 + :param year: 应提取的发行年份 + """ + meta = MetaInfo(title, mtype=MediaType.MUSIC) + + assert meta.title == expected + assert meta.year == year + assert meta.org_string == title + assert meta.artists == [title.partition(" - ")[0]] + assert meta.audio_format == "FLAC" + assert meta.audio_lossless is True