This commit is contained in:
jxxghp 2023-10-12 17:51:20 +08:00
parent a902b79684
commit 5f44f07515
4 changed files with 160 additions and 39 deletions

View File

@ -115,16 +115,18 @@ class ChainBase(metaclass=ABCMeta):
""" """
return self.run_module("recognize_media", meta=meta, mtype=mtype, tmdbid=tmdbid) return self.run_module("recognize_media", meta=meta, mtype=mtype, tmdbid=tmdbid)
def match_doubaninfo(self, name: str, mtype: str = None, def match_doubaninfo(self, name: str, imdbid: str = None,
year: str = None, season: int = None) -> Optional[dict]: mtype: str = None, year: str = None, season: int = None) -> Optional[dict]:
""" """
搜索和匹配豆瓣信息 搜索和匹配豆瓣信息
:param name: 标题 :param name: 标题
:param imdbid: imdbid
:param mtype: 类型 :param mtype: 类型
:param year: 年份 :param year: 年份
:param season: :param season:
""" """
return self.run_module("match_doubaninfo", name=name, mtype=mtype, year=year, season=season) return self.run_module("match_doubaninfo", name=name, imdbid=imdbid,
mtype=mtype, year=year, season=season)
def obtain_images(self, mediainfo: MediaInfo) -> Optional[MediaInfo]: def obtain_images(self, mediainfo: MediaInfo) -> Optional[MediaInfo]:
""" """

View File

@ -1,4 +1,3 @@
from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import List, Optional, Tuple, Union from typing import List, Optional, Tuple, Union
@ -406,17 +405,23 @@ class DoubanModule(_ModuleBase):
return ret_medias return ret_medias
@retry(Exception, 5, 3, 3, logger=logger) @retry(Exception, 5, 3, 3, logger=logger)
def match_doubaninfo(self, name: str, mtype: str = None, def match_doubaninfo(self, name: str, imdbid: str = None,
year: str = None, season: int = None) -> dict: mtype: str = None, year: str = None, season: int = None) -> dict:
""" """
搜索和匹配豆瓣信息 搜索和匹配豆瓣信息
:param name: 名称 :param name: 名称
:param imdbid: IMDB ID
:param mtype: 类型 电影/电视剧 :param mtype: 类型 电影/电视剧
:param year: 年份 :param year: 年份
:param season: 季号 :param season: 季号
""" """
result = self.doubanapi.search(f"{name} {year or ''}".strip(), if imdbid:
ts=datetime.strftime(datetime.now(), '%Y%m%d%H%M%S')) # 优先使用IMDBID查询
result = self.doubanapi.imdbid(imdbid)
if result:
return result
# 搜索
result = self.doubanapi.search(f"{name} {year or ''}".strip())
if not result: if not result:
logger.warn(f"未找到 {name} 的豆瓣信息") logger.warn(f"未找到 {name} 的豆瓣信息")
return {} return {}

View File

@ -18,28 +18,29 @@ class DoubanApi(metaclass=Singleton):
_urls = { _urls = {
# 搜索类 # 搜索类
# sort=U:近期热门 T:标记最多 S:评分最高 R:最新上映 # sort=U:近期热门 T:标记最多 S:评分最高 R:最新上映
# q=search_word&start=0&count=20&sort=U # q=search_word&start: int = 0&count: int = 20&sort=U
# 聚合搜索 # 聚合搜索
"search": "/search/weixin", "search": "/search/weixin",
"search_agg": "/search", "search_agg": "/search",
"imdbid": "/movie/imdb/%s",
# 电影探索 # 电影探索
# sort=U:综合排序 T:近期热度 S:高分优先 R:首播时间 # sort=U:综合排序 T:近期热度 S:高分优先 R:首播时间
# tags='日本,动画,2022'&start=0&count=20&sort=U # tags='日本,动画,2022'&start: int = 0&count: int = 20&sort=U
"movie_recommend": "/movie/recommend", "movie_recommend": "/movie/recommend",
# 电视剧探索 # 电视剧探索
"tv_recommend": "/tv/recommend", "tv_recommend": "/tv/recommend",
# 搜索 # 搜索
"movie_tag": "/movie/tag", "movie_tag": "/movie/tag",
"tv_tag": "/tv/tag", "tv_tag": "/tv/tag",
# q=search_word&start=0&count=20 # q=search_word&start: int = 0&count: int = 20
"movie_search": "/search/movie", "movie_search": "/search/movie",
"tv_search": "/search/movie", "tv_search": "/search/movie",
"book_search": "/search/book", "book_search": "/search/book",
"group_search": "/search/group", "group_search": "/search/group",
# 各类主题合集 # 各类主题合集
# start=0&count=20 # start: int = 0&count: int = 20
# 正在上映 # 正在上映
"movie_showing": "/subject_collection/movie_showing/items", "movie_showing": "/subject_collection/movie_showing/items",
# 热门电影 # 热门电影
@ -145,7 +146,9 @@ class DoubanApi(metaclass=Singleton):
"api-client/1 com.douban.frodo/7.3.0(207) Android/22 product/MI 9 vendor/Xiaomi model/MI 9 brand/Android rom/miui6 network/wifi platform/mobile nd/1"] "api-client/1 com.douban.frodo/7.3.0(207) Android/22 product/MI 9 vendor/Xiaomi model/MI 9 brand/Android rom/miui6 network/wifi platform/mobile nd/1"]
_api_secret_key = "bf7dddc7c9cfe6f7" _api_secret_key = "bf7dddc7c9cfe6f7"
_api_key = "0dad551ec0f84ed02907ff5c42e8ec70" _api_key = "0dad551ec0f84ed02907ff5c42e8ec70"
_api_key2 = "0ab215a8b1977939201640fa14c66bab"
_base_url = "https://frodo.douban.com/api/v2" _base_url = "https://frodo.douban.com/api/v2"
_api_url = "https://api.douban.com/v2"
_session = None _session = None
def __init__(self): def __init__(self):
@ -153,6 +156,9 @@ class DoubanApi(metaclass=Singleton):
@classmethod @classmethod
def __sign(cls, url: str, ts: int, method='GET') -> str: def __sign(cls, url: str, ts: int, method='GET') -> str:
"""
签名
"""
url_path = parse.urlparse(url).path url_path = parse.urlparse(url).path
raw_sign = '&'.join([method.upper(), parse.quote(url_path, safe=''), str(ts)]) raw_sign = '&'.join([method.upper(), parse.quote(url_path, safe=''), str(ts)])
return base64.b64encode( return base64.b64encode(
@ -164,7 +170,10 @@ class DoubanApi(metaclass=Singleton):
).decode() ).decode()
@lru_cache(maxsize=settings.CACHE_CONF.get('douban')) @lru_cache(maxsize=settings.CACHE_CONF.get('douban'))
def __invoke(self, url, **kwargs): def __invoke(self, url: str, **kwargs) -> dict:
"""
GET请求
"""
req_url = self._base_url + url req_url = self._base_url + url
params = {'apiKey': self._api_key} params = {'apiKey': self._api_key}
@ -189,119 +198,223 @@ class DoubanApi(metaclass=Singleton):
return resp.json() return resp.json()
return resp.json() if resp else {} return resp.json() if resp else {}
def search(self, keyword, start=0, count=20, @lru_cache(maxsize=settings.CACHE_CONF.get('douban'))
ts=datetime.strftime(datetime.now(), '%Y%m%d')): def __post(self, url: str, **kwargs) -> dict:
"""
POST请求
esponse = requests.post(
url="https://api.douban.com/v2/movie/imdb/tt29139455",
headers={
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
"Cookie": "bid=J9zb1zA5sJc",
},
data={
"apikey": "0ab215a8b1977939201640fa14c66bab",
},
)
"""
req_url = self._api_url + url
params = {'apiKey': self._api_key2}
if kwargs:
params.update(kwargs)
if '_ts' in params:
params.pop('_ts')
resp = RequestUtils(
session=self._session
).post_res(url=req_url, data=params)
if resp.status_code == 400 and "rate_limit" in resp.text:
return resp.json()
return resp.json() if resp else {}
def search(self, keyword: str, start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')) -> dict:
"""
关键字搜索
"""
return self.__invoke(self._urls["search"], q=keyword, return self.__invoke(self._urls["search"], q=keyword,
start=start, count=count, _ts=ts) start=start, count=count, _ts=ts)
def movie_search(self, keyword, start=0, count=20, def imdbid(self, imdbid: str,
ts=datetime.strftime(datetime.now(), '%Y%m%d')): ts=datetime.strftime(datetime.now(), '%Y%m%d')):
"""
IMDBID搜索
"""
return self.__post(self._urls["imdbid"] % imdbid, _ts=ts)
def movie_search(self, keyword: str, start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
"""
电影搜索
"""
return self.__invoke(self._urls["movie_search"], q=keyword, return self.__invoke(self._urls["movie_search"], q=keyword,
start=start, count=count, _ts=ts) start=start, count=count, _ts=ts)
def tv_search(self, keyword, start=0, count=20, def tv_search(self, keyword: str, start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')): ts=datetime.strftime(datetime.now(), '%Y%m%d')):
"""
电视搜索
"""
return self.__invoke(self._urls["tv_search"], q=keyword, return self.__invoke(self._urls["tv_search"], q=keyword,
start=start, count=count, _ts=ts) start=start, count=count, _ts=ts)
def book_search(self, keyword, start=0, count=20, def book_search(self, keyword: str, start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')): ts=datetime.strftime(datetime.now(), '%Y%m%d')):
"""
书籍搜索
"""
return self.__invoke(self._urls["book_search"], q=keyword, return self.__invoke(self._urls["book_search"], q=keyword,
start=start, count=count, _ts=ts) start=start, count=count, _ts=ts)
def group_search(self, keyword, start=0, count=20, def group_search(self, keyword: str, start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')): ts=datetime.strftime(datetime.now(), '%Y%m%d')):
"""
小组搜索
"""
return self.__invoke(self._urls["group_search"], q=keyword, return self.__invoke(self._urls["group_search"], q=keyword,
start=start, count=count, _ts=ts) start=start, count=count, _ts=ts)
def movie_showing(self, start=0, count=20, def movie_showing(self, start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')): ts=datetime.strftime(datetime.now(), '%Y%m%d')):
"""
正在热映
"""
return self.__invoke(self._urls["movie_showing"], return self.__invoke(self._urls["movie_showing"],
start=start, count=count, _ts=ts) start=start, count=count, _ts=ts)
def movie_soon(self, start=0, count=20, def movie_soon(self, start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')): ts=datetime.strftime(datetime.now(), '%Y%m%d')):
"""
即将上映
"""
return self.__invoke(self._urls["movie_soon"], return self.__invoke(self._urls["movie_soon"],
start=start, count=count, _ts=ts) start=start, count=count, _ts=ts)
def movie_hot_gaia(self, start=0, count=20, def movie_hot_gaia(self, start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')): ts=datetime.strftime(datetime.now(), '%Y%m%d')):
"""
热门电影
"""
return self.__invoke(self._urls["movie_hot_gaia"], return self.__invoke(self._urls["movie_hot_gaia"],
start=start, count=count, _ts=ts) start=start, count=count, _ts=ts)
def tv_hot(self, start=0, count=20, def tv_hot(self, start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')): ts=datetime.strftime(datetime.now(), '%Y%m%d')):
"""
热门剧集
"""
return self.__invoke(self._urls["tv_hot"], return self.__invoke(self._urls["tv_hot"],
start=start, count=count, _ts=ts) start=start, count=count, _ts=ts)
def tv_animation(self, start=0, count=20, def tv_animation(self, start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')): ts=datetime.strftime(datetime.now(), '%Y%m%d')):
"""
动画
"""
return self.__invoke(self._urls["tv_animation"], return self.__invoke(self._urls["tv_animation"],
start=start, count=count, _ts=ts) start=start, count=count, _ts=ts)
def tv_variety_show(self, start=0, count=20, def tv_variety_show(self, start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')): ts=datetime.strftime(datetime.now(), '%Y%m%d')):
"""
综艺
"""
return self.__invoke(self._urls["tv_variety_show"], return self.__invoke(self._urls["tv_variety_show"],
start=start, count=count, _ts=ts) start=start, count=count, _ts=ts)
def tv_rank_list(self, start=0, count=20, def tv_rank_list(self, start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')): ts=datetime.strftime(datetime.now(), '%Y%m%d')):
"""
电视剧排行榜
"""
return self.__invoke(self._urls["tv_rank_list"], return self.__invoke(self._urls["tv_rank_list"],
start=start, count=count, _ts=ts) start=start, count=count, _ts=ts)
def show_hot(self, start=0, count=20, def show_hot(self, start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')): ts=datetime.strftime(datetime.now(), '%Y%m%d')):
"""
综艺热门
"""
return self.__invoke(self._urls["show_hot"], return self.__invoke(self._urls["show_hot"],
start=start, count=count, _ts=ts) start=start, count=count, _ts=ts)
def movie_detail(self, subject_id): def movie_detail(self, subject_id: str):
"""
电影详情
"""
return self.__invoke(self._urls["movie_detail"] + subject_id) return self.__invoke(self._urls["movie_detail"] + subject_id)
def movie_celebrities(self, subject_id): def movie_celebrities(self, subject_id: str):
"""
电影演职员
"""
return self.__invoke(self._urls["movie_celebrities"] % subject_id) return self.__invoke(self._urls["movie_celebrities"] % subject_id)
def tv_detail(self, subject_id): def tv_detail(self, subject_id: str):
"""
电视剧详情
"""
return self.__invoke(self._urls["tv_detail"] + subject_id) return self.__invoke(self._urls["tv_detail"] + subject_id)
def tv_celebrities(self, subject_id): def tv_celebrities(self, subject_id: str):
"""
电视剧演职员
"""
return self.__invoke(self._urls["tv_celebrities"] % subject_id) return self.__invoke(self._urls["tv_celebrities"] % subject_id)
def book_detail(self, subject_id): def book_detail(self, subject_id: str):
"""
书籍详情
"""
return self.__invoke(self._urls["book_detail"] + subject_id) return self.__invoke(self._urls["book_detail"] + subject_id)
def movie_top250(self, start=0, count=20, def movie_top250(self, start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')): ts=datetime.strftime(datetime.now(), '%Y%m%d')):
"""
电影TOP250
"""
return self.__invoke(self._urls["movie_top250"], return self.__invoke(self._urls["movie_top250"],
start=start, count=count, _ts=ts) start=start, count=count, _ts=ts)
def movie_recommend(self, tags='', sort='R', start=0, count=20, def movie_recommend(self, tags='', sort='R', start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')): ts=datetime.strftime(datetime.now(), '%Y%m%d')):
"""
电影探索
"""
return self.__invoke(self._urls["movie_recommend"], tags=tags, sort=sort, return self.__invoke(self._urls["movie_recommend"], tags=tags, sort=sort,
start=start, count=count, _ts=ts) start=start, count=count, _ts=ts)
def tv_recommend(self, tags='', sort='R', start=0, count=20, def tv_recommend(self, tags='', sort='R', start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')): ts=datetime.strftime(datetime.now(), '%Y%m%d')):
"""
电视剧探索
"""
return self.__invoke(self._urls["tv_recommend"], tags=tags, sort=sort, return self.__invoke(self._urls["tv_recommend"], tags=tags, sort=sort,
start=start, count=count, _ts=ts) start=start, count=count, _ts=ts)
def tv_chinese_best_weekly(self, start=0, count=20, def tv_chinese_best_weekly(self, start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')): ts=datetime.strftime(datetime.now(), '%Y%m%d')):
"""
华语口碑周榜
"""
return self.__invoke(self._urls["tv_chinese_best_weekly"], return self.__invoke(self._urls["tv_chinese_best_weekly"],
start=start, count=count, _ts=ts) start=start, count=count, _ts=ts)
def tv_global_best_weekly(self, start=0, count=20, def tv_global_best_weekly(self, start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')): ts=datetime.strftime(datetime.now(), '%Y%m%d')):
"""
全球口碑周榜
"""
return self.__invoke(self._urls["tv_global_best_weekly"], return self.__invoke(self._urls["tv_global_best_weekly"],
start=start, count=count, _ts=ts) start=start, count=count, _ts=ts)
def doulist_detail(self, subject_id): def doulist_detail(self, subject_id: str):
""" """
豆列详情 豆列详情
:param subject_id: 豆列id :param subject_id: 豆列id
""" """
return self.__invoke(self._urls["doulist"] + subject_id) return self.__invoke(self._urls["doulist"] + subject_id)
def doulist_items(self, subject_id, start=0, count=20, def doulist_items(self, subject_id: str, start: int = 0, count: int = 20,
ts=datetime.strftime(datetime.now(), '%Y%m%d')): ts=datetime.strftime(datetime.now(), '%Y%m%d')):
""" """
豆列列表 豆列列表

View File

@ -587,6 +587,7 @@ class PersonMeta(_PluginBase):
time.sleep(sleep_time) time.sleep(sleep_time)
# 匹配豆瓣信息 # 匹配豆瓣信息
doubaninfo = self.chain.match_doubaninfo(name=mediainfo.title, doubaninfo = self.chain.match_doubaninfo(name=mediainfo.title,
imdbid=mediainfo.imdb_id,
mtype=mediainfo.type.value, mtype=mediainfo.type.value,
year=mediainfo.year, year=mediainfo.year,
season=season) season=season)