mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-07 08:26:53 +08:00
fix: 优化TMDB搜索匹配优先级,title/original_title优先于别名匹配
将搜索结果匹配策略从"逐个结果完整匹配链"改为"两轮优先级匹配": 第一轮遍历所有结果只匹配title/original_title,第二轮再匹配别名译名。 避免排序靠前的无关影片因别名恰好匹配而抢先于正确结果。 Fixes #5719 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
2bd4a41cbe
commit
b6b5529d19
@@ -200,55 +200,45 @@ class TmdbApi:
|
|||||||
ret_info['media_type'] = MediaType.MOVIE if ret_info.get("media_type") == "movie" else MediaType.TV
|
ret_info['media_type'] = MediaType.MOVIE if ret_info.get("media_type") == "movie" else MediaType.TV
|
||||||
return ret_info
|
return ret_info
|
||||||
|
|
||||||
def _match_multi_item(self, name: str, multi: dict, get_info_func) -> Optional[dict]:
|
@staticmethod
|
||||||
|
def _match_multi_title(name_compare_func, name: str, multi: dict) -> bool:
|
||||||
"""
|
"""
|
||||||
匹配单个多媒体搜索结果项
|
匹配单个多媒体搜索结果项的标题/原标题
|
||||||
:param name: 查询名称
|
"""
|
||||||
:param multi: 搜索结果项
|
if multi.get("media_type") == "movie":
|
||||||
:param get_info_func: 获取详细信息的函数(同步或异步)
|
return (name_compare_func(name, multi.get('title'))
|
||||||
:return: 匹配的结果或None
|
or name_compare_func(name, multi.get('original_title')))
|
||||||
|
elif multi.get("media_type") == "tv":
|
||||||
|
return (name_compare_func(name, multi.get('name'))
|
||||||
|
or name_compare_func(name, multi.get('original_name')))
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _match_multi_names(self, name: str, multi: dict, get_info_func) -> Optional[dict]:
|
||||||
|
"""
|
||||||
|
匹配单个多媒体搜索结果项的别名、译名
|
||||||
"""
|
"""
|
||||||
if multi.get("media_type") == "movie":
|
if multi.get("media_type") == "movie":
|
||||||
if self.__compare_names(name, multi.get('title')) \
|
|
||||||
or self.__compare_names(name, multi.get('original_title')):
|
|
||||||
return multi
|
|
||||||
# 匹配别名、译名
|
|
||||||
if not multi.get("names"):
|
if not multi.get("names"):
|
||||||
multi = get_info_func(mtype=MediaType.MOVIE, tmdbid=multi.get("id"))
|
multi = get_info_func(mtype=MediaType.MOVIE, tmdbid=multi.get("id"))
|
||||||
if multi and self.__compare_names(name, multi.get("names")):
|
if multi and self.__compare_names(name, multi.get("names")):
|
||||||
return multi
|
return multi
|
||||||
elif multi.get("media_type") == "tv":
|
elif multi.get("media_type") == "tv":
|
||||||
if self.__compare_names(name, multi.get('name')) \
|
|
||||||
or self.__compare_names(name, multi.get('original_name')):
|
|
||||||
return multi
|
|
||||||
# 匹配别名、译名
|
|
||||||
if not multi.get("names"):
|
if not multi.get("names"):
|
||||||
multi = get_info_func(mtype=MediaType.TV, tmdbid=multi.get("id"))
|
multi = get_info_func(mtype=MediaType.TV, tmdbid=multi.get("id"))
|
||||||
if multi and self.__compare_names(name, multi.get("names")):
|
if multi and self.__compare_names(name, multi.get("names")):
|
||||||
return multi
|
return multi
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def _async_match_multi_item(self, name: str, multi: dict) -> Optional[dict]:
|
async def _async_match_multi_names(self, name: str, multi: dict) -> Optional[dict]:
|
||||||
"""
|
"""
|
||||||
匹配单个多媒体搜索结果项(异步版本)
|
匹配单个多媒体搜索结果项的别名、译名(异步版本)
|
||||||
:param name: 查询名称
|
|
||||||
:param multi: 搜索结果项
|
|
||||||
:return: 匹配的结果或None
|
|
||||||
"""
|
"""
|
||||||
if multi.get("media_type") == "movie":
|
if multi.get("media_type") == "movie":
|
||||||
if self.__compare_names(name, multi.get('title')) \
|
|
||||||
or self.__compare_names(name, multi.get('original_title')):
|
|
||||||
return multi
|
|
||||||
# 匹配别名、译名
|
|
||||||
if not multi.get("names"):
|
if not multi.get("names"):
|
||||||
multi = await self.async_get_info(mtype=MediaType.MOVIE, tmdbid=multi.get("id"))
|
multi = await self.async_get_info(mtype=MediaType.MOVIE, tmdbid=multi.get("id"))
|
||||||
if multi and self.__compare_names(name, multi.get("names")):
|
if multi and self.__compare_names(name, multi.get("names")):
|
||||||
return multi
|
return multi
|
||||||
elif multi.get("media_type") == "tv":
|
elif multi.get("media_type") == "tv":
|
||||||
if self.__compare_names(name, multi.get('name')) \
|
|
||||||
or self.__compare_names(name, multi.get('original_name')):
|
|
||||||
return multi
|
|
||||||
# 匹配别名、译名
|
|
||||||
if not multi.get("names"):
|
if not multi.get("names"):
|
||||||
multi = await self.async_get_info(mtype=MediaType.TV, tmdbid=multi.get("id"))
|
multi = await self.async_get_info(mtype=MediaType.TV, tmdbid=multi.get("id"))
|
||||||
if multi and self.__compare_names(name, multi.get("names")):
|
if multi and self.__compare_names(name, multi.get("names")):
|
||||||
@@ -366,18 +356,18 @@ class TmdbApi:
|
|||||||
key=lambda x: x.get('release_date') or '0000-00-00',
|
key=lambda x: x.get('release_date') or '0000-00-00',
|
||||||
reverse=True
|
reverse=True
|
||||||
)
|
)
|
||||||
|
# 过滤年份
|
||||||
|
if year:
|
||||||
|
movies = [m for m in movies
|
||||||
|
if (m.get('release_date') or '')[0:4] == year]
|
||||||
|
# 第一轮:优先匹配标题、原标题
|
||||||
for movie in movies:
|
for movie in movies:
|
||||||
# 年份
|
|
||||||
movie_year = movie.get('release_date')[0:4] if movie.get('release_date') else None
|
|
||||||
if year and movie_year != year:
|
|
||||||
# 年份不匹配
|
|
||||||
continue
|
|
||||||
# 匹配标题、原标题
|
|
||||||
if self.__compare_names(name, movie.get('title')):
|
if self.__compare_names(name, movie.get('title')):
|
||||||
return movie
|
return movie
|
||||||
if self.__compare_names(name, movie.get('original_title')):
|
if self.__compare_names(name, movie.get('original_title')):
|
||||||
return movie
|
return movie
|
||||||
# 匹配别名、译名
|
# 第二轮:匹配别名、译名
|
||||||
|
for movie in movies:
|
||||||
if not movie.get("names"):
|
if not movie.get("names"):
|
||||||
movie = self.get_info(mtype=MediaType.MOVIE, tmdbid=movie.get("id"))
|
movie = self.get_info(mtype=MediaType.MOVIE, tmdbid=movie.get("id"))
|
||||||
if movie and self.__compare_names(name, movie.get("names")):
|
if movie and self.__compare_names(name, movie.get("names")):
|
||||||
@@ -413,17 +403,18 @@ class TmdbApi:
|
|||||||
key=lambda x: x.get('first_air_date') or '0000-00-00',
|
key=lambda x: x.get('first_air_date') or '0000-00-00',
|
||||||
reverse=True
|
reverse=True
|
||||||
)
|
)
|
||||||
|
# 过滤年份
|
||||||
|
if year:
|
||||||
|
tvs = [t for t in tvs
|
||||||
|
if (t.get('first_air_date') or '')[0:4] == year]
|
||||||
|
# 第一轮:优先匹配标题、原标题
|
||||||
for tv in tvs:
|
for tv in tvs:
|
||||||
tv_year = tv.get('first_air_date')[0:4] if tv.get('first_air_date') else None
|
|
||||||
if year and tv_year != year:
|
|
||||||
# 年份不匹配
|
|
||||||
continue
|
|
||||||
# 匹配标题、原标题
|
|
||||||
if self.__compare_names(name, tv.get('name')):
|
if self.__compare_names(name, tv.get('name')):
|
||||||
return tv
|
return tv
|
||||||
if self.__compare_names(name, tv.get('original_name')):
|
if self.__compare_names(name, tv.get('original_name')):
|
||||||
return tv
|
return tv
|
||||||
# 匹配别名、译名
|
# 第二轮:匹配别名、译名
|
||||||
|
for tv in tvs:
|
||||||
if not tv.get("names"):
|
if not tv.get("names"):
|
||||||
tv = self.get_info(mtype=MediaType.TV, tmdbid=tv.get("id"))
|
tv = self.get_info(mtype=MediaType.TV, tmdbid=tv.get("id"))
|
||||||
if tv and self.__compare_names(name, tv.get("names")):
|
if tv and self.__compare_names(name, tv.get("names")):
|
||||||
@@ -575,12 +566,19 @@ class TmdbApi:
|
|||||||
# 按年份降序排列,电影在前面
|
# 按年份降序排列,电影在前面
|
||||||
multis = self._sort_multi_results(multis)
|
multis = self._sort_multi_results(multis)
|
||||||
|
|
||||||
|
# 第一轮:优先匹配标题、原标题
|
||||||
ret_info = {}
|
ret_info = {}
|
||||||
for multi in multis:
|
for multi in multis:
|
||||||
matched = self._match_multi_item(name, multi, self.get_info)
|
if self._match_multi_title(self.__compare_names, name, multi):
|
||||||
if matched:
|
ret_info = multi
|
||||||
ret_info = matched
|
|
||||||
break
|
break
|
||||||
|
# 第二轮:匹配别名、译名
|
||||||
|
if not ret_info:
|
||||||
|
for multi in multis:
|
||||||
|
matched = self._match_multi_names(name, multi, self.get_info)
|
||||||
|
if matched:
|
||||||
|
ret_info = matched
|
||||||
|
break
|
||||||
|
|
||||||
# 类型变更
|
# 类型变更
|
||||||
return self._convert_media_type(ret_info)
|
return self._convert_media_type(ret_info)
|
||||||
@@ -1521,18 +1519,18 @@ class TmdbApi:
|
|||||||
key=lambda x: x.get('release_date') or '0000-00-00',
|
key=lambda x: x.get('release_date') or '0000-00-00',
|
||||||
reverse=True
|
reverse=True
|
||||||
)
|
)
|
||||||
|
# 过滤年份
|
||||||
|
if year:
|
||||||
|
movies = [m for m in movies
|
||||||
|
if (m.get('release_date') or '')[0:4] == year]
|
||||||
|
# 第一轮:优先匹配标题、原标题
|
||||||
for movie in movies:
|
for movie in movies:
|
||||||
# 年份
|
|
||||||
movie_year = movie.get('release_date')[0:4] if movie.get('release_date') else None
|
|
||||||
if year and movie_year != year:
|
|
||||||
# 年份不匹配
|
|
||||||
continue
|
|
||||||
# 匹配标题、原标题
|
|
||||||
if self.__compare_names(name, movie.get('title')):
|
if self.__compare_names(name, movie.get('title')):
|
||||||
return movie
|
return movie
|
||||||
if self.__compare_names(name, movie.get('original_title')):
|
if self.__compare_names(name, movie.get('original_title')):
|
||||||
return movie
|
return movie
|
||||||
# 匹配别名、译名
|
# 第二轮:匹配别名、译名
|
||||||
|
for movie in movies:
|
||||||
if not movie.get("names"):
|
if not movie.get("names"):
|
||||||
movie = await self.async_get_info(mtype=MediaType.MOVIE, tmdbid=movie.get("id"))
|
movie = await self.async_get_info(mtype=MediaType.MOVIE, tmdbid=movie.get("id"))
|
||||||
if movie and self.__compare_names(name, movie.get("names")):
|
if movie and self.__compare_names(name, movie.get("names")):
|
||||||
@@ -1568,17 +1566,18 @@ class TmdbApi:
|
|||||||
key=lambda x: x.get('first_air_date') or '0000-00-00',
|
key=lambda x: x.get('first_air_date') or '0000-00-00',
|
||||||
reverse=True
|
reverse=True
|
||||||
)
|
)
|
||||||
|
# 过滤年份
|
||||||
|
if year:
|
||||||
|
tvs = [t for t in tvs
|
||||||
|
if (t.get('first_air_date') or '')[0:4] == year]
|
||||||
|
# 第一轮:优先匹配标题、原标题
|
||||||
for tv in tvs:
|
for tv in tvs:
|
||||||
tv_year = tv.get('first_air_date')[0:4] if tv.get('first_air_date') else None
|
|
||||||
if year and tv_year != year:
|
|
||||||
# 年份不匹配
|
|
||||||
continue
|
|
||||||
# 匹配标题、原标题
|
|
||||||
if self.__compare_names(name, tv.get('name')):
|
if self.__compare_names(name, tv.get('name')):
|
||||||
return tv
|
return tv
|
||||||
if self.__compare_names(name, tv.get('original_name')):
|
if self.__compare_names(name, tv.get('original_name')):
|
||||||
return tv
|
return tv
|
||||||
# 匹配别名、译名
|
# 第二轮:匹配别名、译名
|
||||||
|
for tv in tvs:
|
||||||
if not tv.get("names"):
|
if not tv.get("names"):
|
||||||
tv = await self.async_get_info(mtype=MediaType.TV, tmdbid=tv.get("id"))
|
tv = await self.async_get_info(mtype=MediaType.TV, tmdbid=tv.get("id"))
|
||||||
if tv and self.__compare_names(name, tv.get("names")):
|
if tv and self.__compare_names(name, tv.get("names")):
|
||||||
@@ -1897,12 +1896,19 @@ class TmdbApi:
|
|||||||
# 按年份降序排列,电影在前面
|
# 按年份降序排列,电影在前面
|
||||||
multis = self._sort_multi_results(multis)
|
multis = self._sort_multi_results(multis)
|
||||||
|
|
||||||
|
# 第一轮:优先匹配标题、原标题
|
||||||
ret_info = {}
|
ret_info = {}
|
||||||
for multi in multis:
|
for multi in multis:
|
||||||
matched = await self._async_match_multi_item(name, multi)
|
if self._match_multi_title(self.__compare_names, name, multi):
|
||||||
if matched:
|
ret_info = multi
|
||||||
ret_info = matched
|
|
||||||
break
|
break
|
||||||
|
# 第二轮:匹配别名、译名
|
||||||
|
if not ret_info:
|
||||||
|
for multi in multis:
|
||||||
|
matched = await self._async_match_multi_names(name, multi)
|
||||||
|
if matched:
|
||||||
|
ret_info = matched
|
||||||
|
break
|
||||||
|
|
||||||
# 类型变更
|
# 类型变更
|
||||||
return self._convert_media_type(ret_info)
|
return self._convert_media_type(ret_info)
|
||||||
|
|||||||
Reference in New Issue
Block a user