mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-06 07:56:52 +08:00
为Bangumi和Douban模块添加异步API支持
This commit is contained in:
@@ -82,6 +82,29 @@ class BangumiModule(_ModuleBase):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
async def async_recognize_media(self, bangumiid: int = None,
|
||||||
|
**kwargs) -> Optional[MediaInfo]:
|
||||||
|
"""
|
||||||
|
识别媒体信息(异步版本)
|
||||||
|
:param bangumiid: 识别的Bangumi ID
|
||||||
|
:return: 识别的媒体信息,包括剧集信息
|
||||||
|
"""
|
||||||
|
if not bangumiid:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 直接查询详情
|
||||||
|
info = await self.async_bangumi_info(bangumiid=bangumiid)
|
||||||
|
if info:
|
||||||
|
# 赋值TMDB信息并返回
|
||||||
|
mediainfo = MediaInfo(bangumi_info=info)
|
||||||
|
logger.info(f"{bangumiid} Bangumi识别结果:{mediainfo.type.value} "
|
||||||
|
f"{mediainfo.title_year}")
|
||||||
|
return mediainfo
|
||||||
|
else:
|
||||||
|
logger.info(f"{bangumiid} 未匹配到Bangumi媒体信息")
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
def search_medias(self, meta: MetaBase) -> Optional[List[MediaInfo]]:
|
def search_medias(self, meta: MetaBase) -> Optional[List[MediaInfo]]:
|
||||||
"""
|
"""
|
||||||
搜索媒体信息
|
搜索媒体信息
|
||||||
@@ -99,6 +122,23 @@ class BangumiModule(_ModuleBase):
|
|||||||
or meta.name.lower() in str(info.get("name_cn")).lower()]
|
or meta.name.lower() in str(info.get("name_cn")).lower()]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
async def async_search_medias(self, meta: MetaBase) -> Optional[List[MediaInfo]]:
|
||||||
|
"""
|
||||||
|
搜索媒体信息(异步版本)
|
||||||
|
:param meta: 识别的元数据
|
||||||
|
:reutrn: 媒体信息
|
||||||
|
"""
|
||||||
|
if settings.SEARCH_SOURCE and "bangumi" not in settings.SEARCH_SOURCE:
|
||||||
|
return None
|
||||||
|
if not meta.name:
|
||||||
|
return []
|
||||||
|
infos = await self.bangumiapi.async_search(meta.name)
|
||||||
|
if infos:
|
||||||
|
return [MediaInfo(bangumi_info=info) for info in infos
|
||||||
|
if meta.name.lower() in str(info.get("name")).lower()
|
||||||
|
or meta.name.lower() in str(info.get("name_cn")).lower()]
|
||||||
|
return []
|
||||||
|
|
||||||
def bangumi_info(self, bangumiid: int) -> Optional[dict]:
|
def bangumi_info(self, bangumiid: int) -> Optional[dict]:
|
||||||
"""
|
"""
|
||||||
获取Bangumi信息
|
获取Bangumi信息
|
||||||
@@ -110,6 +150,17 @@ class BangumiModule(_ModuleBase):
|
|||||||
logger.info(f"开始获取Bangumi信息:{bangumiid} ...")
|
logger.info(f"开始获取Bangumi信息:{bangumiid} ...")
|
||||||
return self.bangumiapi.detail(bangumiid)
|
return self.bangumiapi.detail(bangumiid)
|
||||||
|
|
||||||
|
async def async_bangumi_info(self, bangumiid: int) -> Optional[dict]:
|
||||||
|
"""
|
||||||
|
获取Bangumi信息(异步版本)
|
||||||
|
:param bangumiid: BangumiID
|
||||||
|
:return: Bangumi信息
|
||||||
|
"""
|
||||||
|
if not bangumiid:
|
||||||
|
return None
|
||||||
|
logger.info(f"开始获取Bangumi信息:{bangumiid} ...")
|
||||||
|
return await self.bangumiapi.async_detail(bangumiid)
|
||||||
|
|
||||||
def bangumi_calendar(self) -> Optional[List[MediaInfo]]:
|
def bangumi_calendar(self) -> Optional[List[MediaInfo]]:
|
||||||
"""
|
"""
|
||||||
获取Bangumi每日放送
|
获取Bangumi每日放送
|
||||||
@@ -119,6 +170,15 @@ class BangumiModule(_ModuleBase):
|
|||||||
return [MediaInfo(bangumi_info=info) for info in infos]
|
return [MediaInfo(bangumi_info=info) for info in infos]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
async def async_bangumi_calendar(self) -> Optional[List[MediaInfo]]:
|
||||||
|
"""
|
||||||
|
获取Bangumi每日放送(异步版本)
|
||||||
|
"""
|
||||||
|
infos = await self.bangumiapi.async_calendar()
|
||||||
|
if infos:
|
||||||
|
return [MediaInfo(bangumi_info=info) for info in infos]
|
||||||
|
return []
|
||||||
|
|
||||||
def bangumi_credits(self, bangumiid: int) -> List[schemas.MediaPerson]:
|
def bangumi_credits(self, bangumiid: int) -> List[schemas.MediaPerson]:
|
||||||
"""
|
"""
|
||||||
根据TMDBID查询电影演职员表
|
根据TMDBID查询电影演职员表
|
||||||
@@ -129,6 +189,16 @@ class BangumiModule(_ModuleBase):
|
|||||||
return [schemas.MediaPerson(source='bangumi', **person) for person in persons]
|
return [schemas.MediaPerson(source='bangumi', **person) for person in persons]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
async def async_bangumi_credits(self, bangumiid: int) -> List[schemas.MediaPerson]:
|
||||||
|
"""
|
||||||
|
根据TMDBID查询电影演职员表(异步版本)
|
||||||
|
:param bangumiid: BangumiID
|
||||||
|
"""
|
||||||
|
persons = await self.bangumiapi.async_credits(bangumiid)
|
||||||
|
if persons:
|
||||||
|
return [schemas.MediaPerson(source='bangumi', **person) for person in persons]
|
||||||
|
return []
|
||||||
|
|
||||||
def bangumi_recommend(self, bangumiid: int) -> List[MediaInfo]:
|
def bangumi_recommend(self, bangumiid: int) -> List[MediaInfo]:
|
||||||
"""
|
"""
|
||||||
根据BangumiID查询推荐电影
|
根据BangumiID查询推荐电影
|
||||||
@@ -139,6 +209,16 @@ class BangumiModule(_ModuleBase):
|
|||||||
return [MediaInfo(bangumi_info=subject) for subject in subjects]
|
return [MediaInfo(bangumi_info=subject) for subject in subjects]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
async def async_bangumi_recommend(self, bangumiid: int) -> List[MediaInfo]:
|
||||||
|
"""
|
||||||
|
根据BangumiID查询推荐电影(异步版本)
|
||||||
|
:param bangumiid: BangumiID
|
||||||
|
"""
|
||||||
|
subjects = await self.bangumiapi.async_subjects(bangumiid)
|
||||||
|
if subjects:
|
||||||
|
return [MediaInfo(bangumi_info=subject) for subject in subjects]
|
||||||
|
return []
|
||||||
|
|
||||||
def bangumi_person_detail(self, person_id: int) -> Optional[schemas.MediaPerson]:
|
def bangumi_person_detail(self, person_id: int) -> Optional[schemas.MediaPerson]:
|
||||||
"""
|
"""
|
||||||
获取人物详细信息
|
获取人物详细信息
|
||||||
@@ -156,6 +236,23 @@ class BangumiModule(_ModuleBase):
|
|||||||
})
|
})
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
async def async_bangumi_person_detail(self, person_id: int) -> Optional[schemas.MediaPerson]:
|
||||||
|
"""
|
||||||
|
获取人物详细信息(异步版本)
|
||||||
|
:param person_id: 豆瓣人物ID
|
||||||
|
"""
|
||||||
|
personinfo = await self.bangumiapi.async_person_detail(person_id)
|
||||||
|
if personinfo:
|
||||||
|
return schemas.MediaPerson(source='bangumi', **{
|
||||||
|
"id": personinfo.get("id"),
|
||||||
|
"name": personinfo.get("name"),
|
||||||
|
"images": personinfo.get("images"),
|
||||||
|
"biography": personinfo.get("summary"),
|
||||||
|
"birthday": personinfo.get("birth_day"),
|
||||||
|
"gender": personinfo.get("gender")
|
||||||
|
})
|
||||||
|
return None
|
||||||
|
|
||||||
def bangumi_person_credits(self, person_id: int) -> List[MediaInfo]:
|
def bangumi_person_credits(self, person_id: int) -> List[MediaInfo]:
|
||||||
"""
|
"""
|
||||||
根据TMDBID查询人物参演作品
|
根据TMDBID查询人物参演作品
|
||||||
@@ -166,6 +263,16 @@ class BangumiModule(_ModuleBase):
|
|||||||
return [MediaInfo(bangumi_info=credit) for credit in credits_info]
|
return [MediaInfo(bangumi_info=credit) for credit in credits_info]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
async def async_bangumi_person_credits(self, person_id: int) -> List[MediaInfo]:
|
||||||
|
"""
|
||||||
|
根据TMDBID查询人物参演作品(异步版本)
|
||||||
|
:param person_id: 人物ID
|
||||||
|
"""
|
||||||
|
credits_info = await self.bangumiapi.async_person_credits(person_id=person_id)
|
||||||
|
if credits_info:
|
||||||
|
return [MediaInfo(bangumi_info=credit) for credit in credits_info]
|
||||||
|
return []
|
||||||
|
|
||||||
def bangumi_discover(self, **kwargs) -> Optional[List[MediaInfo]]:
|
def bangumi_discover(self, **kwargs) -> Optional[List[MediaInfo]]:
|
||||||
"""
|
"""
|
||||||
发现Bangumi番剧
|
发现Bangumi番剧
|
||||||
@@ -174,3 +281,12 @@ class BangumiModule(_ModuleBase):
|
|||||||
if infos:
|
if infos:
|
||||||
return [MediaInfo(bangumi_info=info) for info in infos]
|
return [MediaInfo(bangumi_info=info) for info in infos]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
async def async_bangumi_discover(self, **kwargs) -> Optional[List[MediaInfo]]:
|
||||||
|
"""
|
||||||
|
发现Bangumi番剧(异步版本)
|
||||||
|
"""
|
||||||
|
infos = await self.bangumiapi.async_discover(**kwargs)
|
||||||
|
if infos:
|
||||||
|
return [MediaInfo(bangumi_info=info) for info in infos]
|
||||||
|
return []
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import requests
|
|||||||
|
|
||||||
from app.core.cache import cached
|
from app.core.cache import cached
|
||||||
from app.core.config import settings
|
from app.core.config import settings
|
||||||
from app.utils.http import RequestUtils
|
from app.utils.http import RequestUtils, AsyncRequestUtils
|
||||||
|
|
||||||
|
|
||||||
class BangumiApi(object):
|
class BangumiApi(object):
|
||||||
@@ -29,6 +29,7 @@ class BangumiApi(object):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._session = requests.Session()
|
self._session = requests.Session()
|
||||||
self._req = RequestUtils(session=self._session)
|
self._req = RequestUtils(session=self._session)
|
||||||
|
self._async_req = AsyncRequestUtils()
|
||||||
|
|
||||||
@cached(maxsize=settings.CONF.bangumi, ttl=settings.CONF.meta)
|
@cached(maxsize=settings.CONF.bangumi, ttl=settings.CONF.meta)
|
||||||
def __invoke(self, url, key: Optional[str] = None, **kwargs):
|
def __invoke(self, url, key: Optional[str] = None, **kwargs):
|
||||||
@@ -46,6 +47,22 @@ class BangumiApi(object):
|
|||||||
print(e)
|
print(e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@cached(maxsize=settings.CONF.bangumi, ttl=settings.CONF.meta)
|
||||||
|
async def __async_invoke(self, url, key: Optional[str] = None, **kwargs):
|
||||||
|
req_url = self._base_url + url
|
||||||
|
params = {}
|
||||||
|
if kwargs:
|
||||||
|
params.update(kwargs)
|
||||||
|
resp = await self._async_req.get_res(url=req_url, params=params)
|
||||||
|
try:
|
||||||
|
if not resp:
|
||||||
|
return None
|
||||||
|
result = resp.json()
|
||||||
|
return result.get(key) if key else result
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return None
|
||||||
|
|
||||||
def search(self, name):
|
def search(self, name):
|
||||||
"""
|
"""
|
||||||
搜索媒体信息
|
搜索媒体信息
|
||||||
@@ -55,6 +72,15 @@ class BangumiApi(object):
|
|||||||
return result.get("list")
|
return result.get("list")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
async def async_search(self, name):
|
||||||
|
"""
|
||||||
|
搜索媒体信息(异步版本)
|
||||||
|
"""
|
||||||
|
result = await self.__async_invoke("search/subject/%s" % name)
|
||||||
|
if result:
|
||||||
|
return result.get("list")
|
||||||
|
return []
|
||||||
|
|
||||||
def calendar(self):
|
def calendar(self):
|
||||||
"""
|
"""
|
||||||
获取每日放送,返回items
|
获取每日放送,返回items
|
||||||
@@ -153,12 +179,29 @@ class BangumiApi(object):
|
|||||||
ret_list.extend(item.get("items") or [])
|
ret_list.extend(item.get("items") or [])
|
||||||
return ret_list
|
return ret_list
|
||||||
|
|
||||||
|
async def async_calendar(self):
|
||||||
|
"""
|
||||||
|
获取每日放送,返回items(异步版本)
|
||||||
|
"""
|
||||||
|
ret_list = []
|
||||||
|
result = await self.__async_invoke(self._urls["calendar"], _ts=datetime.strftime(datetime.now(), '%Y%m%d'))
|
||||||
|
if result:
|
||||||
|
for item in result:
|
||||||
|
ret_list.extend(item.get("items") or [])
|
||||||
|
return ret_list
|
||||||
|
|
||||||
def detail(self, bid: int):
|
def detail(self, bid: int):
|
||||||
"""
|
"""
|
||||||
获取番剧详情
|
获取番剧详情
|
||||||
"""
|
"""
|
||||||
return self.__invoke(self._urls["detail"] % bid, _ts=datetime.strftime(datetime.now(), '%Y%m%d'))
|
return self.__invoke(self._urls["detail"] % bid, _ts=datetime.strftime(datetime.now(), '%Y%m%d'))
|
||||||
|
|
||||||
|
async def async_detail(self, bid: int):
|
||||||
|
"""
|
||||||
|
获取番剧详情(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke(self._urls["detail"] % bid, _ts=datetime.strftime(datetime.now(), '%Y%m%d'))
|
||||||
|
|
||||||
def credits(self, bid: int):
|
def credits(self, bid: int):
|
||||||
"""
|
"""
|
||||||
获取番剧人物
|
获取番剧人物
|
||||||
@@ -175,18 +218,48 @@ class BangumiApi(object):
|
|||||||
ret_list.append(actor_info)
|
ret_list.append(actor_info)
|
||||||
return ret_list
|
return ret_list
|
||||||
|
|
||||||
|
async def async_credits(self, bid: int):
|
||||||
|
"""
|
||||||
|
获取番剧人物(异步版本)
|
||||||
|
"""
|
||||||
|
ret_list = []
|
||||||
|
result = await self.__async_invoke(self._urls["characters"] % bid,
|
||||||
|
_ts=datetime.strftime(datetime.now(), '%Y%m%d'))
|
||||||
|
if result:
|
||||||
|
for item in result:
|
||||||
|
character_id = item.get("id")
|
||||||
|
actors = item.get("actors")
|
||||||
|
if character_id and actors and actors[0]:
|
||||||
|
actor_info = actors[0]
|
||||||
|
actor_info.update({'career': [item.get('name')]})
|
||||||
|
ret_list.append(actor_info)
|
||||||
|
return ret_list
|
||||||
|
|
||||||
def subjects(self, bid: int):
|
def subjects(self, bid: int):
|
||||||
"""
|
"""
|
||||||
获取关联条目信息
|
获取关联条目信息
|
||||||
"""
|
"""
|
||||||
return self.__invoke(self._urls["subjects"] % bid, _ts=datetime.strftime(datetime.now(), '%Y%m%d'))
|
return self.__invoke(self._urls["subjects"] % bid, _ts=datetime.strftime(datetime.now(), '%Y%m%d'))
|
||||||
|
|
||||||
|
async def async_subjects(self, bid: int):
|
||||||
|
"""
|
||||||
|
获取关联条目信息(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke(self._urls["subjects"] % bid, _ts=datetime.strftime(datetime.now(), '%Y%m%d'))
|
||||||
|
|
||||||
def person_detail(self, person_id: int):
|
def person_detail(self, person_id: int):
|
||||||
"""
|
"""
|
||||||
获取人物详细信息
|
获取人物详细信息
|
||||||
"""
|
"""
|
||||||
return self.__invoke(self._urls["person_detail"] % person_id, _ts=datetime.strftime(datetime.now(), '%Y%m%d'))
|
return self.__invoke(self._urls["person_detail"] % person_id, _ts=datetime.strftime(datetime.now(), '%Y%m%d'))
|
||||||
|
|
||||||
|
async def async_person_detail(self, person_id: int):
|
||||||
|
"""
|
||||||
|
获取人物详细信息(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke(self._urls["person_detail"] % person_id,
|
||||||
|
_ts=datetime.strftime(datetime.now(), '%Y%m%d'))
|
||||||
|
|
||||||
def person_credits(self, person_id: int):
|
def person_credits(self, person_id: int):
|
||||||
"""
|
"""
|
||||||
获取人物参演作品
|
获取人物参演作品
|
||||||
@@ -199,6 +272,18 @@ class BangumiApi(object):
|
|||||||
ret_list.append(item)
|
ret_list.append(item)
|
||||||
return ret_list
|
return ret_list
|
||||||
|
|
||||||
|
async def async_person_credits(self, person_id: int):
|
||||||
|
"""
|
||||||
|
获取人物参演作品(异步版本)
|
||||||
|
"""
|
||||||
|
ret_list = []
|
||||||
|
result = await self.__async_invoke(self._urls["person_credits"] % person_id,
|
||||||
|
_ts=datetime.strftime(datetime.now(), '%Y%m%d'))
|
||||||
|
if result:
|
||||||
|
for item in result:
|
||||||
|
ret_list.append(item)
|
||||||
|
return ret_list
|
||||||
|
|
||||||
def discover(self, **kwargs):
|
def discover(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
发现
|
发现
|
||||||
@@ -207,6 +292,14 @@ class BangumiApi(object):
|
|||||||
key="data",
|
key="data",
|
||||||
_ts=datetime.strftime(datetime.now(), '%Y%m%d'), **kwargs)
|
_ts=datetime.strftime(datetime.now(), '%Y%m%d'), **kwargs)
|
||||||
|
|
||||||
|
async def async_discover(self, **kwargs):
|
||||||
|
"""
|
||||||
|
发现(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke(self._urls["discover"],
|
||||||
|
key="data",
|
||||||
|
_ts=datetime.strftime(datetime.now(), '%Y%m%d'), **kwargs)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if self._session:
|
if self._session:
|
||||||
self._session.close()
|
self._session.close()
|
||||||
|
|||||||
@@ -485,6 +485,62 @@ class DoubanModule(_ModuleBase):
|
|||||||
else:
|
else:
|
||||||
return __douban_movie() or __douban_tv()
|
return __douban_movie() or __douban_tv()
|
||||||
|
|
||||||
|
@rate_limit_exponential(source="douban_info")
|
||||||
|
async def async_douban_info(self, doubanid: str, mtype: MediaType = None, raise_exception: bool = True) -> Optional[
|
||||||
|
dict]:
|
||||||
|
"""
|
||||||
|
获取豆瓣信息(异步版本)
|
||||||
|
:param doubanid: 豆瓣ID
|
||||||
|
:param mtype: 媒体类型
|
||||||
|
:param raise_exception: 触发速率限制时是否抛出异常
|
||||||
|
:return: 豆瓣信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
async def __async_douban_tv():
|
||||||
|
"""
|
||||||
|
获取豆瓣剧集信息(异步版本)
|
||||||
|
"""
|
||||||
|
info = await self.doubanapi.async_tv_detail(doubanid)
|
||||||
|
if info:
|
||||||
|
if "subject_ip_rate_limit" in info.get("msg", ""):
|
||||||
|
msg = f"触发豆瓣IP速率限制,错误信息:{info} ..."
|
||||||
|
logger.warn(msg)
|
||||||
|
raise APIRateLimitException(msg)
|
||||||
|
celebrities = await self.doubanapi.async_tv_celebrities(doubanid)
|
||||||
|
if celebrities:
|
||||||
|
info["directors"] = celebrities.get("directors")
|
||||||
|
info["actors"] = celebrities.get("actors")
|
||||||
|
return info
|
||||||
|
|
||||||
|
async def __async_douban_movie():
|
||||||
|
"""
|
||||||
|
获取豆瓣电影信息(异步版本)
|
||||||
|
"""
|
||||||
|
info = await self.doubanapi.async_movie_detail(doubanid)
|
||||||
|
if info:
|
||||||
|
if "subject_ip_rate_limit" in info.get("msg", ""):
|
||||||
|
msg = f"触发豆瓣IP速率限制,错误信息:{info} ..."
|
||||||
|
logger.warn(msg)
|
||||||
|
raise APIRateLimitException(msg)
|
||||||
|
celebrities = await self.doubanapi.async_movie_celebrities(doubanid)
|
||||||
|
if celebrities:
|
||||||
|
info["directors"] = celebrities.get("directors")
|
||||||
|
info["actors"] = celebrities.get("actors")
|
||||||
|
return info
|
||||||
|
|
||||||
|
if not doubanid:
|
||||||
|
return None
|
||||||
|
logger.info(f"开始获取豆瓣信息:{doubanid} ...")
|
||||||
|
if mtype == MediaType.TV:
|
||||||
|
return await __async_douban_tv()
|
||||||
|
elif mtype == MediaType.MOVIE:
|
||||||
|
return await __async_douban_movie()
|
||||||
|
else:
|
||||||
|
movie_result = await __async_douban_movie()
|
||||||
|
if movie_result:
|
||||||
|
return movie_result
|
||||||
|
return await __async_douban_tv()
|
||||||
|
|
||||||
def douban_discover(self, mtype: MediaType, sort: str, tags: str,
|
def douban_discover(self, mtype: MediaType, sort: str, tags: str,
|
||||||
page: int = 1, count: int = 30) -> Optional[List[MediaInfo]]:
|
page: int = 1, count: int = 30) -> Optional[List[MediaInfo]]:
|
||||||
"""
|
"""
|
||||||
@@ -513,6 +569,34 @@ class DoubanModule(_ModuleBase):
|
|||||||
and "tv_large.jpg" not in media.poster_path]
|
and "tv_large.jpg" not in media.poster_path]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
async def async_douban_discover(self, mtype: MediaType, sort: str, tags: str,
|
||||||
|
page: int = 1, count: int = 30) -> Optional[List[MediaInfo]]:
|
||||||
|
"""
|
||||||
|
发现豆瓣电影、剧集(异步版本)
|
||||||
|
:param mtype: 媒体类型
|
||||||
|
:param sort: 排序方式
|
||||||
|
:param tags: 标签
|
||||||
|
:param page: 页码
|
||||||
|
:param count: 数量
|
||||||
|
:return: 媒体信息列表
|
||||||
|
"""
|
||||||
|
logger.info(f"开始发现豆瓣 {mtype.value} ...")
|
||||||
|
if mtype == MediaType.MOVIE:
|
||||||
|
infos = await self.doubanapi.async_movie_recommend(start=(page - 1) * count, count=count,
|
||||||
|
sort=sort, tags=tags)
|
||||||
|
else:
|
||||||
|
infos = await self.doubanapi.async_tv_recommend(start=(page - 1) * count, count=count,
|
||||||
|
sort=sort, tags=tags)
|
||||||
|
if infos and infos.get("items"):
|
||||||
|
medias = [MediaInfo(douban_info=info) for info in infos.get("items")]
|
||||||
|
return [media for media in medias if media.poster_path
|
||||||
|
and "movie_large.jpg" not in media.poster_path
|
||||||
|
and "tv_normal.png" not in media.poster_path
|
||||||
|
and "movie_large.jpg" not in media.poster_path
|
||||||
|
and "tv_normal.jpg" not in media.poster_path
|
||||||
|
and "tv_large.jpg" not in media.poster_path]
|
||||||
|
return []
|
||||||
|
|
||||||
def movie_showing(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
def movie_showing(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
||||||
"""
|
"""
|
||||||
获取正在上映的电影
|
获取正在上映的电影
|
||||||
@@ -523,6 +607,16 @@ class DoubanModule(_ModuleBase):
|
|||||||
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
async def async_movie_showing(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
||||||
|
"""
|
||||||
|
获取正在上映的电影(异步版本)
|
||||||
|
"""
|
||||||
|
infos = await self.doubanapi.async_movie_showing(start=(page - 1) * count,
|
||||||
|
count=count)
|
||||||
|
if infos and infos.get("subject_collection_items"):
|
||||||
|
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
||||||
|
return []
|
||||||
|
|
||||||
def tv_weekly_chinese(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
def tv_weekly_chinese(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
||||||
"""
|
"""
|
||||||
获取豆瓣本周口碑国产剧
|
获取豆瓣本周口碑国产剧
|
||||||
@@ -533,6 +627,16 @@ class DoubanModule(_ModuleBase):
|
|||||||
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
async def async_tv_weekly_chinese(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
||||||
|
"""
|
||||||
|
获取豆瓣本周口碑国产剧(异步版本)
|
||||||
|
"""
|
||||||
|
infos = await self.doubanapi.async_tv_chinese_best_weekly(start=(page - 1) * count,
|
||||||
|
count=count)
|
||||||
|
if infos:
|
||||||
|
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
||||||
|
return []
|
||||||
|
|
||||||
def tv_weekly_global(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
def tv_weekly_global(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
||||||
"""
|
"""
|
||||||
获取豆瓣本周口碑外国剧
|
获取豆瓣本周口碑外国剧
|
||||||
@@ -543,6 +647,16 @@ class DoubanModule(_ModuleBase):
|
|||||||
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
async def async_tv_weekly_global(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
||||||
|
"""
|
||||||
|
获取豆瓣本周口碑外国剧(异步版本)
|
||||||
|
"""
|
||||||
|
infos = await self.doubanapi.async_tv_global_best_weekly(start=(page - 1) * count,
|
||||||
|
count=count)
|
||||||
|
if infos and infos.get("subject_collection_items"):
|
||||||
|
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
||||||
|
return []
|
||||||
|
|
||||||
def tv_animation(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
def tv_animation(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
||||||
"""
|
"""
|
||||||
获取豆瓣动画剧
|
获取豆瓣动画剧
|
||||||
@@ -553,6 +667,16 @@ class DoubanModule(_ModuleBase):
|
|||||||
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
async def async_tv_animation(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
||||||
|
"""
|
||||||
|
获取豆瓣动画剧(异步版本)
|
||||||
|
"""
|
||||||
|
infos = await self.doubanapi.async_tv_animation(start=(page - 1) * count,
|
||||||
|
count=count)
|
||||||
|
if infos and infos.get("subject_collection_items"):
|
||||||
|
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
||||||
|
return []
|
||||||
|
|
||||||
def movie_hot(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
def movie_hot(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
||||||
"""
|
"""
|
||||||
获取豆瓣热门电影
|
获取豆瓣热门电影
|
||||||
@@ -563,6 +687,16 @@ class DoubanModule(_ModuleBase):
|
|||||||
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
async def async_movie_hot(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
||||||
|
"""
|
||||||
|
获取豆瓣热门电影(异步版本)
|
||||||
|
"""
|
||||||
|
infos = await self.doubanapi.async_movie_hot_gaia(start=(page - 1) * count,
|
||||||
|
count=count)
|
||||||
|
if infos and infos.get("subject_collection_items"):
|
||||||
|
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
||||||
|
return []
|
||||||
|
|
||||||
def tv_hot(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
def tv_hot(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
||||||
"""
|
"""
|
||||||
获取豆瓣热门剧集
|
获取豆瓣热门剧集
|
||||||
@@ -573,6 +707,16 @@ class DoubanModule(_ModuleBase):
|
|||||||
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
async def async_tv_hot(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
||||||
|
"""
|
||||||
|
获取豆瓣热门剧集(异步版本)
|
||||||
|
"""
|
||||||
|
infos = await self.doubanapi.async_tv_hot(start=(page - 1) * count,
|
||||||
|
count=count)
|
||||||
|
if infos and infos.get("subject_collection_items"):
|
||||||
|
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
||||||
|
return []
|
||||||
|
|
||||||
def search_medias(self, meta: MetaBase) -> Optional[List[MediaInfo]]:
|
def search_medias(self, meta: MetaBase) -> Optional[List[MediaInfo]]:
|
||||||
"""
|
"""
|
||||||
搜索媒体信息
|
搜索媒体信息
|
||||||
@@ -606,6 +750,39 @@ class DoubanModule(_ModuleBase):
|
|||||||
media.season = meta.begin_season
|
media.season = meta.begin_season
|
||||||
return ret_medias
|
return ret_medias
|
||||||
|
|
||||||
|
async def async_search_medias(self, meta: MetaBase) -> Optional[List[MediaInfo]]:
|
||||||
|
"""
|
||||||
|
搜索媒体信息(异步版本)
|
||||||
|
:param meta: 识别的元数据
|
||||||
|
:reutrn: 媒体信息
|
||||||
|
"""
|
||||||
|
if settings.SEARCH_SOURCE and "douban" not in settings.SEARCH_SOURCE:
|
||||||
|
return None
|
||||||
|
if not meta.name:
|
||||||
|
return []
|
||||||
|
result = await self.doubanapi.async_search(meta.name)
|
||||||
|
if not result or not result.get("items"):
|
||||||
|
return []
|
||||||
|
# 返回数据
|
||||||
|
ret_medias = []
|
||||||
|
for item_obj in result.get("items"):
|
||||||
|
if meta.type and meta.type != MediaType.UNKNOWN and meta.type.value != item_obj.get("type_name"):
|
||||||
|
continue
|
||||||
|
if item_obj.get("type_name") not in (MediaType.TV.value, MediaType.MOVIE.value):
|
||||||
|
continue
|
||||||
|
if meta.name not in item_obj.get("target", {}).get("title"):
|
||||||
|
continue
|
||||||
|
ret_medias.append(MediaInfo(douban_info=item_obj.get("target")))
|
||||||
|
# 将搜索词中的季写入标题中
|
||||||
|
if ret_medias and meta.begin_season:
|
||||||
|
# 小写数据转大写
|
||||||
|
season_str = cn2an.an2cn(meta.begin_season, "low")
|
||||||
|
for media in ret_medias:
|
||||||
|
if media.type == MediaType.TV:
|
||||||
|
media.title = f"{media.title} 第{season_str}季"
|
||||||
|
media.season = meta.begin_season
|
||||||
|
return ret_medias
|
||||||
|
|
||||||
def search_persons(self, name: str) -> Optional[List[MediaPerson]]:
|
def search_persons(self, name: str) -> Optional[List[MediaPerson]]:
|
||||||
"""
|
"""
|
||||||
搜索人物信息
|
搜索人物信息
|
||||||
@@ -624,6 +801,24 @@ class DoubanModule(_ModuleBase):
|
|||||||
}) for item in result.get('items') if name in item.get('target', {}).get('title')]
|
}) for item in result.get('items') if name in item.get('target', {}).get('title')]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
async def async_search_persons(self, name: str) -> Optional[List[MediaPerson]]:
|
||||||
|
"""
|
||||||
|
搜索人物信息(异步版本)
|
||||||
|
"""
|
||||||
|
if not name:
|
||||||
|
return []
|
||||||
|
result = await self.doubanapi.async_person_search(keyword=name)
|
||||||
|
if result and result.get('items'):
|
||||||
|
return [MediaPerson(source='douban', **{
|
||||||
|
'id': item.get('target_id'),
|
||||||
|
'name': item.get('target', {}).get('title'),
|
||||||
|
'url': item.get('target', {}).get('url'),
|
||||||
|
'images': item.get('target', {}).get('cover', {}),
|
||||||
|
'avatar': (item.get('target', {}).get('cover_img', {}).get('url')
|
||||||
|
or '').replace("/l/public/", "/s/public/"),
|
||||||
|
}) for item in result.get('items') if name in item.get('target', {}).get('title')]
|
||||||
|
return []
|
||||||
|
|
||||||
@retry(Exception, 5, 3, 3, logger=logger)
|
@retry(Exception, 5, 3, 3, logger=logger)
|
||||||
@rate_limit_exponential(source="match_doubaninfo")
|
@rate_limit_exponential(source="match_doubaninfo")
|
||||||
def match_doubaninfo(self, name: str, imdbid: str = None,
|
def match_doubaninfo(self, name: str, imdbid: str = None,
|
||||||
@@ -696,6 +891,16 @@ class DoubanModule(_ModuleBase):
|
|||||||
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
async def async_movie_top250(self, page: int = 1, count: int = 30) -> List[MediaInfo]:
|
||||||
|
"""
|
||||||
|
获取豆瓣电影TOP250(异步版本)
|
||||||
|
"""
|
||||||
|
infos = await self.doubanapi.async_movie_top250(start=(page - 1) * count,
|
||||||
|
count=count)
|
||||||
|
if infos and infos.get("subject_collection_items"):
|
||||||
|
return [MediaInfo(douban_info=info) for info in infos.get("subject_collection_items")]
|
||||||
|
return []
|
||||||
|
|
||||||
def metadata_nfo(self, mediainfo: MediaInfo, season: int = None, **kwargs) -> Optional[str]:
|
def metadata_nfo(self, mediainfo: MediaInfo, season: int = None, **kwargs) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
获取NFO文件内容文本
|
获取NFO文件内容文本
|
||||||
|
|||||||
+340
-1
@@ -11,7 +11,7 @@ import requests
|
|||||||
|
|
||||||
from app.core.cache import cached
|
from app.core.cache import cached
|
||||||
from app.core.config import settings
|
from app.core.config import settings
|
||||||
from app.utils.http import RequestUtils
|
from app.utils.http import RequestUtils, AsyncRequestUtils
|
||||||
from app.utils.singleton import WeakSingleton
|
from app.utils.singleton import WeakSingleton
|
||||||
|
|
||||||
|
|
||||||
@@ -154,6 +154,7 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._session = requests.Session()
|
self._session = requests.Session()
|
||||||
|
self._async_req = AsyncRequestUtils()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def __sign(cls, url: str, ts: str, method='GET') -> str:
|
def __sign(cls, url: str, ts: str, method='GET') -> str:
|
||||||
@@ -177,6 +178,13 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
"""
|
"""
|
||||||
return self.__invoke(url, **kwargs)
|
return self.__invoke(url, **kwargs)
|
||||||
|
|
||||||
|
@cached(maxsize=settings.CONF.douban, ttl=settings.CONF.meta)
|
||||||
|
async def __async_invoke_recommend(self, url: str, **kwargs) -> dict:
|
||||||
|
"""
|
||||||
|
推荐/发现类API(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke(url, **kwargs)
|
||||||
|
|
||||||
@cached(maxsize=settings.CONF.douban, ttl=settings.CONF.meta)
|
@cached(maxsize=settings.CONF.douban, ttl=settings.CONF.meta)
|
||||||
def __invoke_search(self, url: str, **kwargs) -> dict:
|
def __invoke_search(self, url: str, **kwargs) -> dict:
|
||||||
"""
|
"""
|
||||||
@@ -184,6 +192,13 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
"""
|
"""
|
||||||
return self.__invoke(url, **kwargs)
|
return self.__invoke(url, **kwargs)
|
||||||
|
|
||||||
|
@cached(maxsize=settings.CONF.douban, ttl=settings.CONF.meta)
|
||||||
|
async def __async_invoke_search(self, url: str, **kwargs) -> dict:
|
||||||
|
"""
|
||||||
|
搜索类API(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke(url, **kwargs)
|
||||||
|
|
||||||
def __invoke(self, url: str, **kwargs) -> dict:
|
def __invoke(self, url: str, **kwargs) -> dict:
|
||||||
"""
|
"""
|
||||||
GET请求
|
GET请求
|
||||||
@@ -212,6 +227,32 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return resp.json()
|
return resp.json()
|
||||||
return resp.json() if resp else {}
|
return resp.json() if resp else {}
|
||||||
|
|
||||||
|
@cached(maxsize=settings.CONF.douban, ttl=settings.CONF.meta)
|
||||||
|
async def __async_invoke(self, url: str, **kwargs) -> dict:
|
||||||
|
"""
|
||||||
|
GET请求(异步版本)
|
||||||
|
"""
|
||||||
|
req_url = self._base_url + url
|
||||||
|
|
||||||
|
params: dict = {'apiKey': self._api_key}
|
||||||
|
if kwargs:
|
||||||
|
params.update(kwargs)
|
||||||
|
|
||||||
|
ts = params.pop(
|
||||||
|
'_ts',
|
||||||
|
datetime.strftime(datetime.now(), '%Y%m%d')
|
||||||
|
)
|
||||||
|
params.update({
|
||||||
|
'os_rom': 'android',
|
||||||
|
'apiKey': self._api_key,
|
||||||
|
'_ts': ts,
|
||||||
|
'_sig': self.__sign(url=req_url, ts=ts)
|
||||||
|
})
|
||||||
|
resp = await self._async_req.get_res(url=req_url, params=params)
|
||||||
|
if resp is not None and resp.status_code == 400 and "rate_limit" in resp.text:
|
||||||
|
return resp.json()
|
||||||
|
return resp.json() if resp else {}
|
||||||
|
|
||||||
@cached(maxsize=settings.CONF.douban, ttl=settings.CONF.meta)
|
@cached(maxsize=settings.CONF.douban, ttl=settings.CONF.meta)
|
||||||
def __post(self, url: str, **kwargs) -> dict:
|
def __post(self, url: str, **kwargs) -> dict:
|
||||||
"""
|
"""
|
||||||
@@ -241,6 +282,22 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return resp.json()
|
return resp.json()
|
||||||
return resp.json() if resp else {}
|
return resp.json() if resp else {}
|
||||||
|
|
||||||
|
@cached(maxsize=settings.CONF.douban, ttl=settings.CONF.meta)
|
||||||
|
async def __async_post(self, url: str, **kwargs) -> dict:
|
||||||
|
"""
|
||||||
|
POST请求(异步版本)
|
||||||
|
"""
|
||||||
|
req_url = self._api_url + url
|
||||||
|
params = {'apikey': self._api_key2}
|
||||||
|
if kwargs:
|
||||||
|
params.update(kwargs)
|
||||||
|
if '_ts' in params:
|
||||||
|
params.pop('_ts')
|
||||||
|
resp = await self._async_req.post_res(url=req_url, data=params)
|
||||||
|
if resp is not None and resp.status_code == 400 and "rate_limit" in resp.text:
|
||||||
|
return resp.json()
|
||||||
|
return resp.json() if resp else {}
|
||||||
|
|
||||||
def imdbid(self, imdbid: str,
|
def imdbid(self, imdbid: str,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -248,6 +305,13 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
"""
|
"""
|
||||||
return self.__post(self._urls["imdbid"] % imdbid, _ts=ts)
|
return self.__post(self._urls["imdbid"] % imdbid, _ts=ts)
|
||||||
|
|
||||||
|
async def async_imdbid(self, imdbid: str,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
IMDBID搜索(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_post(self._urls["imdbid"] % imdbid, _ts=ts)
|
||||||
|
|
||||||
def search(self, keyword: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
def search(self, keyword: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')) -> dict:
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')) -> dict:
|
||||||
"""
|
"""
|
||||||
@@ -256,6 +320,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_search(self._urls["search"], q=keyword,
|
return self.__invoke_search(self._urls["search"], q=keyword,
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_search(self, keyword: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')) -> dict:
|
||||||
|
"""
|
||||||
|
关键字搜索(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_search(self._urls["search"], q=keyword,
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def movie_search(self, keyword: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
def movie_search(self, keyword: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -264,6 +336,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_search(self._urls["movie_search"], q=keyword,
|
return self.__invoke_search(self._urls["movie_search"], q=keyword,
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_movie_search(self, keyword: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
电影搜索(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_search(self._urls["movie_search"], q=keyword,
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def tv_search(self, keyword: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
def tv_search(self, keyword: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -272,6 +352,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_search(self._urls["tv_search"], q=keyword,
|
return self.__invoke_search(self._urls["tv_search"], q=keyword,
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_tv_search(self, keyword: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
电视搜索(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_search(self._urls["tv_search"], q=keyword,
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def book_search(self, keyword: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
def book_search(self, keyword: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -280,6 +368,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_search(self._urls["book_search"], q=keyword,
|
return self.__invoke_search(self._urls["book_search"], q=keyword,
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_book_search(self, keyword: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
书籍搜索(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_search(self._urls["book_search"], q=keyword,
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def group_search(self, keyword: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
def group_search(self, keyword: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -288,6 +384,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_search(self._urls["group_search"], q=keyword,
|
return self.__invoke_search(self._urls["group_search"], q=keyword,
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_group_search(self, keyword: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
小组搜索(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_search(self._urls["group_search"], q=keyword,
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def person_search(self, keyword: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
def person_search(self, keyword: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -296,6 +400,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_search(self._urls["search_subject"], type="person", q=keyword,
|
return self.__invoke_search(self._urls["search_subject"], type="person", q=keyword,
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_person_search(self, keyword: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
人物搜索(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_search(self._urls["search_subject"], type="person", q=keyword,
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def movie_showing(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
def movie_showing(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -304,6 +416,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_recommend(self._urls["movie_showing"],
|
return self.__invoke_recommend(self._urls["movie_showing"],
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_movie_showing(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
正在热映(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_recommend(self._urls["movie_showing"],
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def movie_soon(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
def movie_soon(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -312,6 +432,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_recommend(self._urls["movie_soon"],
|
return self.__invoke_recommend(self._urls["movie_soon"],
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_movie_soon(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
即将上映(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_recommend(self._urls["movie_soon"],
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def movie_hot_gaia(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
def movie_hot_gaia(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -320,6 +448,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_recommend(self._urls["movie_hot_gaia"],
|
return self.__invoke_recommend(self._urls["movie_hot_gaia"],
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_movie_hot_gaia(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
热门电影(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_recommend(self._urls["movie_hot_gaia"],
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def tv_hot(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
def tv_hot(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -328,6 +464,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_recommend(self._urls["tv_hot"],
|
return self.__invoke_recommend(self._urls["tv_hot"],
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_tv_hot(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
热门剧集(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_recommend(self._urls["tv_hot"],
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def tv_animation(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
def tv_animation(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -336,6 +480,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_recommend(self._urls["tv_animation"],
|
return self.__invoke_recommend(self._urls["tv_animation"],
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_tv_animation(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
动画(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_recommend(self._urls["tv_animation"],
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def tv_variety_show(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
def tv_variety_show(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -344,6 +496,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_recommend(self._urls["tv_variety_show"],
|
return self.__invoke_recommend(self._urls["tv_variety_show"],
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_tv_variety_show(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
综艺(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_recommend(self._urls["tv_variety_show"],
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def tv_rank_list(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
def tv_rank_list(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -352,6 +512,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_recommend(self._urls["tv_rank_list"],
|
return self.__invoke_recommend(self._urls["tv_rank_list"],
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_tv_rank_list(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
电视剧排行榜(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_recommend(self._urls["tv_rank_list"],
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def show_hot(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
def show_hot(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -360,36 +528,74 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_recommend(self._urls["show_hot"],
|
return self.__invoke_recommend(self._urls["show_hot"],
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_show_hot(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
综艺热门(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_recommend(self._urls["show_hot"],
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def movie_detail(self, subject_id: str):
|
def movie_detail(self, subject_id: str):
|
||||||
"""
|
"""
|
||||||
电影详情
|
电影详情
|
||||||
"""
|
"""
|
||||||
return self.__invoke_search(self._urls["movie_detail"] + subject_id)
|
return self.__invoke_search(self._urls["movie_detail"] + subject_id)
|
||||||
|
|
||||||
|
async def async_movie_detail(self, subject_id: str):
|
||||||
|
"""
|
||||||
|
电影详情(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_search(self._urls["movie_detail"] + subject_id)
|
||||||
|
|
||||||
def movie_celebrities(self, subject_id: str):
|
def movie_celebrities(self, subject_id: str):
|
||||||
"""
|
"""
|
||||||
电影演职员
|
电影演职员
|
||||||
"""
|
"""
|
||||||
return self.__invoke_search(self._urls["movie_celebrities"] % subject_id)
|
return self.__invoke_search(self._urls["movie_celebrities"] % subject_id)
|
||||||
|
|
||||||
|
async def async_movie_celebrities(self, subject_id: str):
|
||||||
|
"""
|
||||||
|
电影演职员(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_search(self._urls["movie_celebrities"] % subject_id)
|
||||||
|
|
||||||
def tv_detail(self, subject_id: str):
|
def tv_detail(self, subject_id: str):
|
||||||
"""
|
"""
|
||||||
电视剧详情
|
电视剧详情
|
||||||
"""
|
"""
|
||||||
return self.__invoke_search(self._urls["tv_detail"] + subject_id)
|
return self.__invoke_search(self._urls["tv_detail"] + subject_id)
|
||||||
|
|
||||||
|
async def async_tv_detail(self, subject_id: str):
|
||||||
|
"""
|
||||||
|
电视剧详情(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_search(self._urls["tv_detail"] + subject_id)
|
||||||
|
|
||||||
def tv_celebrities(self, subject_id: str):
|
def tv_celebrities(self, subject_id: str):
|
||||||
"""
|
"""
|
||||||
电视剧演职员
|
电视剧演职员
|
||||||
"""
|
"""
|
||||||
return self.__invoke_search(self._urls["tv_celebrities"] % subject_id)
|
return self.__invoke_search(self._urls["tv_celebrities"] % subject_id)
|
||||||
|
|
||||||
|
async def async_tv_celebrities(self, subject_id: str):
|
||||||
|
"""
|
||||||
|
电视剧演职员(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_search(self._urls["tv_celebrities"] % subject_id)
|
||||||
|
|
||||||
def book_detail(self, subject_id: str):
|
def book_detail(self, subject_id: str):
|
||||||
"""
|
"""
|
||||||
书籍详情
|
书籍详情
|
||||||
"""
|
"""
|
||||||
return self.__invoke_search(self._urls["book_detail"] + subject_id)
|
return self.__invoke_search(self._urls["book_detail"] + subject_id)
|
||||||
|
|
||||||
|
async def async_book_detail(self, subject_id: str):
|
||||||
|
"""
|
||||||
|
书籍详情(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_search(self._urls["book_detail"] + subject_id)
|
||||||
|
|
||||||
def movie_top250(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
def movie_top250(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -398,6 +604,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_recommend(self._urls["movie_top250"],
|
return self.__invoke_recommend(self._urls["movie_top250"],
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_movie_top250(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
电影TOP250(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_recommend(self._urls["movie_top250"],
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def movie_recommend(self, tags='', sort='R', start: Optional[int] = 0, count: Optional[int] = 20,
|
def movie_recommend(self, tags='', sort='R', start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -406,6 +620,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_recommend(self._urls["movie_recommend"], tags=tags, sort=sort,
|
return self.__invoke_recommend(self._urls["movie_recommend"], tags=tags, sort=sort,
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_movie_recommend(self, tags='', sort='R', start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
电影探索(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_recommend(self._urls["movie_recommend"], tags=tags, sort=sort,
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def tv_recommend(self, tags='', sort='R', start: Optional[int] = 0, count: Optional[int] = 20,
|
def tv_recommend(self, tags='', sort='R', start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -414,6 +636,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_recommend(self._urls["tv_recommend"], tags=tags, sort=sort,
|
return self.__invoke_recommend(self._urls["tv_recommend"], tags=tags, sort=sort,
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_tv_recommend(self, tags='', sort='R', start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
电视剧探索(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_recommend(self._urls["tv_recommend"], tags=tags, sort=sort,
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def tv_chinese_best_weekly(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
def tv_chinese_best_weekly(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -422,6 +652,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_recommend(self._urls["tv_chinese_best_weekly"],
|
return self.__invoke_recommend(self._urls["tv_chinese_best_weekly"],
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_tv_chinese_best_weekly(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
华语口碑周榜(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_recommend(self._urls["tv_chinese_best_weekly"],
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def tv_global_best_weekly(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
def tv_global_best_weekly(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -430,6 +668,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_recommend(self._urls["tv_global_best_weekly"],
|
return self.__invoke_recommend(self._urls["tv_global_best_weekly"],
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_tv_global_best_weekly(self, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
全球口碑周榜(异步版本)
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_recommend(self._urls["tv_global_best_weekly"],
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def doulist_detail(self, subject_id: str):
|
def doulist_detail(self, subject_id: str):
|
||||||
"""
|
"""
|
||||||
豆列详情
|
豆列详情
|
||||||
@@ -437,6 +683,13 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
"""
|
"""
|
||||||
return self.__invoke_search(self._urls["doulist"] + subject_id)
|
return self.__invoke_search(self._urls["doulist"] + subject_id)
|
||||||
|
|
||||||
|
async def async_doulist_detail(self, subject_id: str):
|
||||||
|
"""
|
||||||
|
豆列详情(异步版本)
|
||||||
|
:param subject_id: 豆列id
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_search(self._urls["doulist"] + subject_id)
|
||||||
|
|
||||||
def doulist_items(self, subject_id: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
def doulist_items(self, subject_id: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -449,6 +702,18 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_search(self._urls["doulist_items"] % subject_id,
|
return self.__invoke_search(self._urls["doulist_items"] % subject_id,
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_doulist_items(self, subject_id: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
豆列列表(异步版本)
|
||||||
|
:param subject_id: 豆列id
|
||||||
|
:param start: 开始
|
||||||
|
:param count: 数量
|
||||||
|
:param ts: 时间戳
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_search(self._urls["doulist_items"] % subject_id,
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def movie_recommendations(self, subject_id: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
def movie_recommendations(self, subject_id: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -461,6 +726,18 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_recommend(self._urls["movie_recommendations"] % subject_id,
|
return self.__invoke_recommend(self._urls["movie_recommendations"] % subject_id,
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_movie_recommendations(self, subject_id: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
电影推荐(异步版本)
|
||||||
|
:param subject_id: 电影id
|
||||||
|
:param start: 开始
|
||||||
|
:param count: 数量
|
||||||
|
:param ts: 时间戳
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_recommend(self._urls["movie_recommendations"] % subject_id,
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def tv_recommendations(self, subject_id: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
def tv_recommendations(self, subject_id: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -473,6 +750,18 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_recommend(self._urls["tv_recommendations"] % subject_id,
|
return self.__invoke_recommend(self._urls["tv_recommendations"] % subject_id,
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_tv_recommendations(self, subject_id: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
电视剧推荐(异步版本)
|
||||||
|
:param subject_id: 电视剧id
|
||||||
|
:param start: 开始
|
||||||
|
:param count: 数量
|
||||||
|
:param ts: 时间戳
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_recommend(self._urls["tv_recommendations"] % subject_id,
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def movie_photos(self, subject_id: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
def movie_photos(self, subject_id: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -485,6 +774,18 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_search(self._urls["movie_photos"] % subject_id,
|
return self.__invoke_search(self._urls["movie_photos"] % subject_id,
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_movie_photos(self, subject_id: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
电影剧照(异步版本)
|
||||||
|
:param subject_id: 电影id
|
||||||
|
:param start: 开始
|
||||||
|
:param count: 数量
|
||||||
|
:param ts: 时间戳
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_search(self._urls["movie_photos"] % subject_id,
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def tv_photos(self, subject_id: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
def tv_photos(self, subject_id: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
"""
|
"""
|
||||||
@@ -497,6 +798,18 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
return self.__invoke_search(self._urls["tv_photos"] % subject_id,
|
return self.__invoke_search(self._urls["tv_photos"] % subject_id,
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_tv_photos(self, subject_id: str, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
电视剧剧照(异步版本)
|
||||||
|
:param subject_id: 电视剧id
|
||||||
|
:param start: 开始
|
||||||
|
:param count: 数量
|
||||||
|
:param ts: 时间戳
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_search(self._urls["tv_photos"] % subject_id,
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def person_detail(self, subject_id: int):
|
def person_detail(self, subject_id: int):
|
||||||
"""
|
"""
|
||||||
用户详情
|
用户详情
|
||||||
@@ -505,6 +818,14 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
"""
|
"""
|
||||||
return self.__invoke_search(self._urls["person_detail"] + str(subject_id))
|
return self.__invoke_search(self._urls["person_detail"] + str(subject_id))
|
||||||
|
|
||||||
|
async def async_person_detail(self, subject_id: int):
|
||||||
|
"""
|
||||||
|
用户详情(异步版本)
|
||||||
|
:param subject_id: 人物 id
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_search(self._urls["person_detail"] + str(subject_id))
|
||||||
|
|
||||||
def person_work(self, subject_id: int, start: Optional[int] = 0, count: Optional[int] = 20,
|
def person_work(self, subject_id: int, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
sort_by: Optional[str] = "time",
|
sort_by: Optional[str] = "time",
|
||||||
collection_title: Optional[str] = "影视",
|
collection_title: Optional[str] = "影视",
|
||||||
@@ -523,6 +844,24 @@ class DoubanApi(metaclass=WeakSingleton):
|
|||||||
collection_title=collection_title,
|
collection_title=collection_title,
|
||||||
start=start, count=count, _ts=ts)
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
|
async def async_person_work(self, subject_id: int, start: Optional[int] = 0, count: Optional[int] = 20,
|
||||||
|
sort_by: Optional[str] = "time",
|
||||||
|
collection_title: Optional[str] = "影视",
|
||||||
|
ts=datetime.strftime(datetime.now(), '%Y%m%d')):
|
||||||
|
"""
|
||||||
|
用户作品集(异步版本)
|
||||||
|
:param subject_id: work_collection id
|
||||||
|
:param start: 开始页
|
||||||
|
:param count: 数量
|
||||||
|
:param sort_by: collection or time or vote
|
||||||
|
:param collection_title: 影视 or 图书 or 音乐
|
||||||
|
:param ts: 时间戳
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
return await self.__async_invoke_search(self._urls["person_work"] % subject_id, sortby=sort_by,
|
||||||
|
collection_title=collection_title,
|
||||||
|
start=start, count=count, _ts=ts)
|
||||||
|
|
||||||
def clear_cache(self):
|
def clear_cache(self):
|
||||||
"""
|
"""
|
||||||
清空LRU缓存
|
清空LRU缓存
|
||||||
|
|||||||
Reference in New Issue
Block a user