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