rogerxavier's picture
Upload 258 files
0aee47a verified
"""
bilibili_api.rank
和哔哩哔哩视频排行榜相关的 API
"""
from enum import Enum
from typing import Union
from .utils.utils import get_api
from .utils.credential import Credential
from .utils.network import Api
API = get_api("rank")
class RankAPIType(Enum):
"""
排行榜 API 接口类型
- PGC: https://api.bilibili.com/pgc/web/rank/list
- V2: https://api.bilibili.com/x/web-interface/ranking/v2
"""
PGC = "pgc"
V2 = "x"
class RankDayType(Enum):
"""
RankAPIType.PGC 排行榜时间类型
- THREE_DAY: 三日排行
- WEEK: 周排行
"""
THREE_DAY = 3
WEEK = 7
class RankType(Enum):
"""
排行榜类型
- All: 全部
- Bangumi: 番剧
- GuochuangAnime: 国产动画
- Guochuang: 国创相关
- Documentary: 纪录片
- Douga: 动画
- Music: 音乐
- Dance: 舞蹈
- Game: 游戏
- Knowledge: 知识
- Technology: 科技
- Sports: 运动
- Car: 汽车
- Life: 生活
- Food: 美食
- Animal: 动物圈
- Kitchen: 鬼畜
- Fashion: 时尚
- Ent: 娱乐
- Cinephile: 影视
- Movie: 电影
- TV: 电视剧
- Variety: 综艺
- Original: 原创
- Rookie: 新人
"""
All = {"api_type": "x", "rid": 0, "type": "all"}
Bangumi = {"api_type": "pgc", "season_type": 1}
GuochuangAnime = {"api_type": "pgc", "season_type": 4}
Guochuang = {"api_type": "x", "rid": 168, "type": "all"}
Documentary = {"api_type": "pgc", "season_type": 3}
Douga = {"api_type": "x", "rid": 1, "type": "all"}
Music = {"api_type": "x", "rid": 3, "type": "all"}
Dance = {"api_type": "x", "rid": 129, "type": "all"}
Game = {"api_type": "x", "rid": 4, "type": "all"}
Knowledge = {"api_type": "x", "rid": 36, "type": "all"}
Technology = {"api_type": "x", "rid": 188, "type": "all"}
Sports = {"api_type": "x", "rid": 234, "type": "all"}
Car = {"api_type": "x", "rid": 223, "type": "all"}
Life = {"api_type": "x", "rid": 160, "type": "all"}
Food = {"api_type": "x", "rid": 211, "type": "all"}
Animal = {"api_type": "x", "rid": 217, "type": "all"}
Kichiku = {"api_type": "x", "rid": 119, "type": "all"}
Fashion = {"api_type": "x", "rid": 155, "type": "all"}
Ent = {"api_type": "x", "rid": 5, "type": "all"}
Cinephile = {"api_type": "x", "rid": 181, "type": "all"}
Movie = {"api_type": "pgc", "season_type": 2}
TV = {"api_type": "pgc", "season_type": 5}
Variety = {"api_type": "pgc", "season_type": 7}
Original = {"api_type": "x", "rid": 0, "type": "origin"}
Rookie = {"api_type": "x", "rid": 0, "type": "rookie"}
class VIPRankType(Enum):
"""
大会员中心热播榜单类型,即 rank_id
- VIP: 会员
- BANGUMI: 番剧
- GUOCHUANG: 国创
- MOVIE: 电影
- DOCUMENTARY: 纪录片
- TV: 电视剧
- VARIETY: 综艺
"""
VIP = 279
BANGUMI = 118
GUOCHUANG = 119
MOVIE = 174
DOCUMENTARY = 175
TV = 176
VARIETY = 177
class MangeRankType(Enum):
"""
漫画排行榜类型
- NEW: 新作
- BOY: 男生
- GRIL: 女生
- GUOCHUANG: 国漫
- JAPAN: 日漫
- SOUTHKOREA: 韩漫
- OFFICAL: 宝藏
- FINISH: 完结
"""
NEW = 7
BOY = 11
GRIL = 12
GUOCHUANG = 1
JAPAN = 0
SOUTHKOREA = 2
OFFICAL = 5
FINISH = 13
class LiveRankType(Enum):
"""
直播通用榜类型
- SAIL_BOAT_VALUE: 主播舰队榜
- SAIL_BOAT_TICKET: 船员价值榜
- SAIL_BOAT_NUMBER: 舰船人数榜
- MASTER_LEVEL: 主播等级榜
- USER_LEVEL: 用户等级榜
"""
SAIL_BOAT_VALUE = "sail_boat_value"
SAIL_BOAT_TICKET = "sail_boat_ticket"
SAIL_BOAT_NUMBER = "sail_boat_number"
MASTER_LEVEL = "master_level"
USER_LEVEL = "user_level"
class LiveEnergyRankType(Enum):
"""
直播超能用户榜类型
- MONTH: 本月
- PRE_MONTH: 上月
"""
MONTH = "month"
PRE_MONTH = "pre_month"
async def get_rank(
type_: RankType = RankType.All, day: RankDayType = RankDayType.THREE_DAY
) -> dict:
"""
获取视频排行榜
Args:
type_ (RankType): 排行榜类型. Defaults to RankType.All
day (RankDayType): 排行榜时间. Defaults to RankDayType.THREE_DAY
仅对 api_type 为 RankAPIType.PGC 有效
Returns:
dict: 调用 API 返回的结果
"""
params = {}
# 确定 API 接口类型
if type_.value["api_type"] == RankAPIType.V2.value:
api = API["info"]["v2_ranking"]
params["rid"] = type_.value["rid"]
elif type_.value["api_type"] == RankAPIType.PGC.value:
api = API["info"]["pgc_ranking"]
params["season_type"] = type_.value["season_type"]
params["day"] = day.value
else:
raise Exception("Unknown RankType")
return await Api(**api).update_params(**params).result
async def get_music_rank_list() -> dict:
"""
获取全站音乐榜每周信息(不包括具体的音频列表)
Returns:
dict: 调用 API 返回的结果
"""
api = API["info"]["music_weekly_series"]
params = {"list_type": 1}
return await Api(**api).update_params(**params).result
async def get_music_rank_weekly_detail(week: int = 1) -> dict:
"""
获取全站音乐榜一周的详细信息(不包括具体的音频列表)
Args:
week(int): 第几周. Defaults to 1.
Returns:
dict: 调用 API 返回的结果
"""
api = API["info"]["music_weekly_details"]
params = {"list_id": week}
return await Api(**api).update_params(**params).result
async def get_music_rank_weekly_musics(week: int = 1) -> dict:
"""
获取全站音乐榜一周的音频列表(返回的音乐的 id 对应了 music.Music 类创建实例传入的 id)
Args:
week(int): 第几周. Defaults to 1.
Returns:
dict: 调用 API 返回的结果
"""
api = API["info"]["music_weekly_content"]
params = {"list_id": week}
return await Api(**api).update_params(**params).result
async def get_vip_rank(type_: VIPRankType = VIPRankType.VIP) -> dict:
"""
获取大会员中心的排行榜
Args:
type_ (VIPRankType): 排行榜类型. Defaults to VIPRankType.VIP
Returns:
dict: 调用 API 返回的结果
"""
api = API["info"]["VIP_rank"]
params = {"rank_id": type_.value}
return await Api(**api).update_params(**params).result
async def get_manga_rank(type_: MangeRankType = MangeRankType.NEW, credential: Credential = None) -> dict:
"""
获取漫画专属排行榜
Args:
credential (Credential): 凭据类
Returns:
dict: 调用 API 返回的结果
"""
credential = credential if credential else Credential()
credential.raise_for_no_sessdata()
api = API["info"]["manga_rank"]
params = {"device": "pc", "platform": "web"}
data = {"id": type_.value}
return (
await Api(**api, no_csrf=True, credential=credential)
.update_data(**data)
.update_params(**params)
.result
)
async def get_live_hot_rank() -> dict:
"""
获取直播首页人气排行榜
Returns:
dict: 调用 API 返回的结果
"""
api = API["info"]["live_hot_rank"]
return await Api(**api).result
async def get_live_sailing_rank() -> dict:
"""
获取首页直播大航海排行榜
Returns:
dict: 调用 API 返回的结果
"""
api = API["info"]["live_sailing_rank"]
return await Api(**api).update_params(**{}).result
async def get_live_energy_user_rank(
date: LiveEnergyRankType = LiveEnergyRankType.MONTH, pn: int = 1, ps: int = 20
) -> dict:
"""
获取直播超能用户榜
Args:
date (LiveEnergyRankType): 月份. Defaults to LiveEnergyRankType.MONTH
pn (int): 页码. Defaults to 1
ps (int): 每页数量. Defaults to 20
Returns:
dict: 调用 API 返回的结果
"""
api = API["info"]["live_energy_user_rank"]
params = {"date": date.value, "page": pn, "page_size": ps}
return await Api(**api).update_params(**params).result
async def get_live_rank(
_type: LiveRankType = LiveRankType.SAIL_BOAT_VALUE, pn: int = 1, ps: int = 20
) -> dict:
"""
获取直播通用榜单
Args:
_type (LiveRankType): 榜单类型. Defaults to LiveRankType.VALUE
pn (int): 页码. Defaults to 1
ps (int): 每页数量. Defaults to 20
Returns:
dict: 调用 API 返回的结果
"""
api = API["info"]["live_web_top"]
params = {
"type": _type.value,
"page": pn,
"page_size": ps,
"is_trend": 1,
"area_id": None,
}
return await Api(**api).update_params(**params).result
async def get_live_user_medal_rank(pn: int = 1, ps: int = 20) -> dict:
"""
获取直播用户勋章榜
Args:
pn (int): 页码. Defaults to 1
ps (int): 每页数量. Defaults to 20
Returns:
dict: 调用 API 返回的结果
"""
api = API["info"]["live_medal_level_rank"]
params = {"page": pn, "page_size": ps}
return await Api(**api).update_params(**params).result
async def subscribe_music_rank(
status: bool = True, credential: Union[Credential, None] = None
) -> dict:
"""
设置关注全站音乐榜
Args:
status (bool) : 关注状态. Defaults to True.
credential (Credential): 凭据类. Defaults to None.
"""
credential = credential if credential else Credential()
credential.raise_for_no_sessdata()
credential.raise_for_no_bili_jct()
api = API["operate"]["subscribe"]
data = {"list_id": 1, "state": (1 if status else 2)}
return await Api(**api, credential=credential).update_data(**data).result
async def get_playlet_rank_phases() -> dict:
"""
获取全站短剧榜期数
Returns:
dict: 调用 API 返回的结果
"""
api = API["info"]["playlet_rank_phase"]
return await Api(**api, json_body=True, no_csrf=True).result
async def get_playlet_rank_info(phase_id: int) -> dict:
"""
获取全站短剧榜
https://www.bilibili.com/v/popular/drama/
Args:
phase_id (int): 期数,从 get_playlet_rank_phase 获取
Returns:
dict: 调用 API 返回的结果
"""
api = API["info"]["playlet_rank_info"]
data = {"phaseID": phase_id}
return await Api(**api, json_body=True, no_csrf=True).update_data(**data).result