Files
UHD_Media_Tool/packages/domain/test/differential/identity/gen-identity-mp.py
T
rootandClaude Opus 5.5 03de030371 test(identity): MoviePilot differential on 113 HHClub titles (ID-2)
MP MetaInfo + TheMovieDbModule name matching vs parse/recall/resolveIdentity,
TMDB responses replayed offline; includes the category-alias misbinding
regression from the user stack.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 17:41:22 +08:00

97 lines
3.4 KiB
Python

"""身份匹配差分:用 MP 上游 MetaInfo + TheMovieDbModule 的名称识别链生成 mp.json。
用法(MP 仓库根目录,用其 .venv;TMDB 走本地缓存代理,见 docs/porting/moviepilot-identity-match.md):
cd /opt/moviepilot-plus/upstream/MoviePilot && PYTHONPATH=. TMDB_PROXY=http://127.0.0.1:18731 \
.venv/bin/python /opt/uhd_media_tool/packages/domain/test/differential/identity/gen-identity-mp.py
按 MP 实际识别顺序:MetaInfo(title, subtitle) → _prepare_search_names(cn_name, 简体 cn_name, en_name)
→ 逐个名称 _search_by_name(_build_match_plan:电视剧 [季年份+年份, 无年份];其他 [电影+年份, 电视剧+年份, multi])。
不含识别缓存、插件辅助识别与详情补全(只取匹配到的 id/类型/名称/年份)。只记录行为输出,不复制 MP 源码。
"""
import json
import os
import pathlib
import subprocess
from app.domain.metainfo import MetaInfo
from app.modules.themoviedb import TheMovieDbModule
from app.modules.themoviedb.tmdbapi import TmdbApi
from app.modules.themoviedb.tmdbv3api import tmdb as tmdb_mod
HERE = pathlib.Path(__file__).parent
PROXY = os.environ.get("TMDB_PROXY", "http://127.0.0.1:18731")
def _build_url(self, action, params=""):
return "%s/3%s?api_key=x&%s&language=%s" % (PROXY, action, params, self.language)
tmdb_mod.TMDb._build_url = _build_url
samples = json.loads((HERE / "samples.json").read_text(encoding="utf-8"))["samples"]
if os.environ.get("LIMIT"):
samples = samples[: int(os.environ["LIMIT"])]
# 只需名称匹配链:不走 init_module(识别缓存/分类配置需要启动层)
module = TheMovieDbModule.__new__(TheMovieDbModule)
module.tmdb = TmdbApi()
def val(v):
return getattr(v, "value", v)
def run(s: dict) -> dict:
meta = MetaInfo(s["title"], s.get("subtitle"))
out = {
"meta": {
"name": meta.name,
"cn_name": meta.cn_name,
"en_name": meta.en_name,
"year": meta.year,
"type": val(meta.type),
"begin_season": meta.begin_season,
"begin_episode": meta.begin_episode,
},
"names": module._prepare_search_names(meta),
"match": None,
}
if not meta.name:
return out
for name in out["names"]:
info = module._search_by_name(name, meta, [])
if info:
mtype = val(info.get("media_type"))
mtype = "movie" if mtype in ("movie", "电影") else "tv"
date = info.get("release_date") or info.get("first_air_date") or ""
out["match"] = {
"by": name,
"tmdbId": info.get("id"),
"type": mtype,
"title": info.get("title") or info.get("name"),
"year": int(date[:4]) if date[:4].isdigit() else None,
}
break
return out
result = {}
for s in samples:
try:
result[s["id"]] = run(s)
except Exception as e: # noqa: BLE001
result[s["id"]] = {"error": f"{type(e).__name__}: {e}"}
commit = subprocess.run(["git", "rev-parse", "--short", "HEAD"], capture_output=True, text=True).stdout.strip()
(HERE / "mp.json").write_text(
json.dumps(
{"generatedFrom": {"repo": "MoviePilot", "commit": commit, "entry": "MetaInfo + TheMovieDbModule._search_by_name"},
"results": result},
ensure_ascii=False,
indent=1,
)
+ "\n",
encoding="utf-8",
)
print(len(result))