File size: 10,272 Bytes
0aee47a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 |
"""
bilibili_api.search
搜索
"""
import json
from enum import Enum
from typing import List, Union, Callable
from .utils.utils import get_api
from .video_zone import VideoZoneTypes
from .utils.network import Api, get_session
from .utils.credential import Credential
API = get_api("search")
class SearchObjectType(Enum):
"""
搜索对象。
+ VIDEO : 视频
+ BANGUMI : 番剧
+ FT : 影视
+ LIVE : 直播
+ ARTICLE : 专栏
+ TOPIC : 话题
+ USER : 用户
+ LIVEUSER : 直播间用户
"""
VIDEO = "video"
BANGUMI = "media_bangumi"
FT = "media_ft"
LIVE = "live"
ARTICLE = "article"
TOPIC = "topic"
USER = "bili_user"
LIVEUSER = "live_user"
PHOTO = "photo"
class OrderVideo(Enum):
"""
视频搜索类型
+ TOTALRANK : 综合排序
+ CLICK : 最多点击
+ PUBDATE : 最新发布
+ DM : 最多弹幕
+ STOW : 最多收藏
+ SCORES : 最多评论
Ps: Api 中 的 order_sort 字段决定顺序还是倒序
"""
TOTALRANK = "totalrank"
CLICK = "click"
PUBDATE = "pubdate"
DM = "dm"
STOW = "stow"
SCORES = "scores"
class OrderLiveRoom(Enum):
"""
直播间搜索类型
+ NEWLIVE 最新开播
+ ONLINE 综合排序
"""
NEWLIVE = "live_time"
ONLINE = "online"
class OrderArticle(Enum):
"""
文章的排序类型
+ TOTALRANK : 综合排序
+ CLICK : 最多点击
+ PUBDATE : 最新发布
+ ATTENTION : 最多喜欢
+ SCORES : 最多评论
"""
TOTALRANK = "totalrank"
PUBDATE = "pubdate"
CLICK = "click"
ATTENTION = "attention"
SCORES = "scores"
class OrderUser(Enum):
"""
搜索用户的排序类型
+ FANS : 按照粉丝数量排序
+ LEVEL : 按照等级排序
"""
FANS = "fans"
LEVEL = "level"
class OrderCheese(Enum):
"""
课程搜索排序类型
+ RECOMMEND: 综合
+ SELL : 销量最高
+ NEW : 最新上架
+ CHEEP : 售价最低
"""
RECOMMEND = -1
SELL = 1
NEW = 2
CHEEP = 3
class CategoryTypePhoto(Enum):
"""
相册分类
+ All 全部
+ DrawFriend 画友
+ PhotoFriend 摄影
"""
All = 0
DrawFriend = 2
PhotoFriend = 1
class CategoryTypeArticle(Enum):
"""
文章分类
+ All 全部
+ Anime 动画
+ Game 游戏
+ TV 电视
+ Life 生活
+ Hobby 兴趣
+ LightNovel 轻小说
+ Technology 科技
"""
All = 0
Anime = 2
Game = 1
TV = 28
Life = 3
Hobby = 29
LightNovel = 16
Technology = 17
async def search(keyword: str, page: int = 1) -> dict:
"""
只指定关键字在 web 进行搜索,返回未经处理的字典
Args:
keyword (str): 搜索关键词
page (int): 页码. Defaults to 1.
Returns:
dict: 调用 API 返回的结果
"""
api = API["search"]["web_search"]
params = {"keyword": keyword, "page": page}
return await Api(**api).update_params(**params).result
async def search_by_type(
keyword: str,
search_type: Union[SearchObjectType, None] = None,
order_type: Union[OrderUser, OrderLiveRoom, OrderArticle, OrderVideo, None] = None,
time_range: int = -1,
video_zone_type: Union[int, VideoZoneTypes, None] = None,
order_sort: Union[int, None] = None,
category_id: Union[CategoryTypeArticle, CategoryTypePhoto, int, None] = None,
page: int = 1,
page_size: int = 42,
debug_param_func: Union[Callable, None] = None,
) -> dict:
"""
指定分区,类型,视频长度等参数进行搜索,返回未经处理的字典
类型:视频(video)、番剧(media_bangumi)、影视(media_ft)、直播(live)、直播用户(liveuser)、专栏(article)、话题(topic)、用户(bili_user)
Args:
debug_param_func (Callable | None, optional) : 参数回调器,用来存储或者什么的
order_sort (int | None, optional) : 用户粉丝数及等级排序顺序 默认为0 由高到低:0 由低到高:1
category_id (CategoryTypeArticle | CategoryTypePhoto | int | None, optional) : 专栏/相簿分区筛选,指定分类,只在相册和专栏类型下生效
time_range (int, optional) : 指定时间,自动转换到指定区间,只在视频类型下生效 有四种:10分钟以下,10-30分钟,30-60分钟,60分钟以上
video_zone_type (int | ZoneTypes | None, optional) : 话题类型,指定 tid (可使用 channel 模块查询)
order_type (OrderUser | OrderLiveRoom | OrderArticle | OrderVideo | None, optional): 排序分类类型
keyword (str) : 搜索关键词
search_type (SearchObjectType | None, optional) : 搜索类型
page (int, optional) : 页码
page_size (int, optional) : 每一页的数据大小
Returns:
dict: 调用 API 返回的结果
"""
params = {"keyword": keyword, "page": page, "page_size": page_size}
if search_type:
params["search_type"] = search_type.value
else:
raise ValueError("Missing arg:search_type")
# params["search_type"] = SearchObjectType.VIDEO.value
# category_id
if (
search_type.value == SearchObjectType.ARTICLE.value
or search_type.value == SearchObjectType.PHOTO.value
):
if category_id:
if isinstance(category_id, int):
params["category_id"] = category_id
else:
params["category_id"] = category_id.value
# time_code
if search_type.value == SearchObjectType.VIDEO.value:
if time_range > 60:
time_code = 4
elif 30 < time_range <= 60:
time_code = 3
elif 10 < time_range <= 30:
time_code = 2
elif 0 < time_range <= 10:
time_code = 1
else:
time_code = 0
params["duration"] = time_code
# zone_type
if video_zone_type:
if isinstance(video_zone_type, int):
params["tids"] = video_zone_type
elif isinstance(video_zone_type, VideoZoneTypes):
params["tids"] = video_zone_type.value
else:
params["tids"] = video_zone_type
# order_type
if order_type:
params["order"] = order_type.value
# order_sort
if search_type.value == SearchObjectType.USER.value:
params["order_sort"] = order_sort
if debug_param_func:
debug_param_func(params)
api = API["search"]["web_search_by_type"]
return await Api(**api).update_params(**params).result
async def get_default_search_keyword() -> dict:
"""
获取默认的搜索内容
Returns:
dict: 调用 API 返回的结果
"""
api = API["search"]["default_search_keyword"]
return await Api(**api).result
async def get_hot_search_keywords() -> dict:
"""
获取热搜
Returns:
dict: 调用 API 返回的结果
"""
api = API["search"]["hot_search_keywords"]
sess = get_session()
return json.loads((await sess.request("GET", api["url"])).text)
async def get_suggest_keywords(keyword: str) -> List[str]:
"""
通过一些文字输入获取搜索建议。类似搜索词的联想。
Args:
keyword(str): 搜索关键词
Returns:
List[str]: 关键词列表
"""
keywords = []
sess = get_session()
api = API["search"]["suggest"]
params = {"term": keyword}
res = await Api(**api).update_params(**params).result
for key in res["tag"]:
keywords.append(key["value"])
return keywords
async def search_games(keyword: str) -> dict:
"""
搜索游戏特用函数
Args:
keyword (str): 搜索关键词
Returns:
dict: 调用 API 返回的结果
"""
api = API["search"]["game"]
params = {"keyword": keyword}
return await Api(**api).update_params(**params).result
async def search_manga(
keyword: str, page_num: int = 1, page_size: int = 9, credential: Credential = None
):
"""
搜索漫画特用函数
Args:
keyword (str): 搜索关键词
page_num (int): 页码. Defaults to 1.
page_size (int): 每一页的数据大小. Defaults to 9.
credential (Credential): 凭据类. Defaults to None.
Returns:
dict: 调用 API 返回的结果
"""
credential = credential if credential else Credential()
api = API["search"]["manga"]
data = {"key_word": keyword, "page_num": page_num, "page_size": page_size}
return (
await Api(**api, credential=credential, no_csrf=True).update_data(**data).result
)
async def search_cheese(
keyword: str,
page_num: int = 1,
page_size: int = 30,
order: OrderCheese = OrderCheese.RECOMMEND,
):
"""
搜索课程特用函数
Args:
keyword (str) : 搜索关键词
page_num (int) : 页码. Defaults to 1.
page_size (int) : 每一页的数据大小. Defaults to 30.
order (OrderCheese): 排序方式. Defaults to OrderCheese.RECOMMEND
Returns:
dict: 调用 API 返回的结果
"""
api = API["search"]["cheese"]
params = {
"word": keyword,
"page": page_num,
"page_size": page_size,
"sort_type": order.value,
}
return await Api(**api).update_params(**params).result
|