BiliAPI Python版本重构手记

和我有过邮件联系的dalao们应该会发现,两年前我就提及BiliAPI会有Python版本,然而……咕咕咕。然后最近,一股来自东方的神秘力量催使我又打开了这个项目。于是我翻了翻Python3.6的新特性,又跑过来填坑了。然而惨不忍睹的旧设计实在是没有改的空间了,于是我打算开始一波重构。repo位于码云:https://gitee.com/kaaass/biliapi_python,重构分支为reconstruct,欢迎Star、测试、issue、PR。

看commit和issue记录你会发现,其实已经有一次重构了,但是由于当时设计的时候并没有考虑到一些接口的特性,所以后续开发根本没法弄。现在借鉴了一下B站客户端的实现,重新进行了设计。

请求部分目前已经重写完成。采用了ISigner实现不同的签名方式,参数拼接采用了IParamAppender接口来实现。引入了Builder,采用链式调用让代码看着更舒服。旧的请求方法也是完全支持的,所以现在有三种接口请求的方法。

import biliapi
from biliapi.endpoint import Endpoint

AK = ""  # AppKey
SK = ""  # SecretKey
biliapi.set_default_key_pair(AK, SK, biliapi.AppType.phone_android)

if __name__ == '__main__':
    # 方法1:Endpoint
    @Endpoint(
        endpoint=biliapi.APP_HOST + '/x/v2/space',
        mapping={'mid': 'vmid'},
        index='data'
    )
    def space(mid, req=None):
        pass


    print(space(1))

    # 方法2:使用Builder
    data = biliapi.request.builder()\
        .host(biliapi.APP_HOST)\
        .path('/x/v2/space').param('vmid', 1).do_request()
    print(data)

    # 方法3:直接调用
    data = biliapi.request.get(biliapi.APP_HOST + '/x/v2/space', {'vmid': 1})
    print(data)

鉴权部分由Auth、Authenticator、AuthManager、AuthParamAppeder组成。Auth用于鉴权信息的存放,不具任何业务逻辑,类似POJO。AuthManager用于管理多用户的凭据和登录对象Authenticator的创建,全局持有一个默认对象,也可以创建一个手动管理。Authenticator存放登陆用逻辑,目前计划由IAuthenticator、ClientAuthenticator、QrCodeAuthenticator、WebAuthenticator组成。AuthParamAppeder用于和Request对接,增加登录凭据用,内部持有一个Auth对象。这部分目前咕咕咕

其实鉴权方面我还是比较纠结的。设计首先要和Request尽量分离。其次,客户端的鉴权我个人是很想去掉的,因为access_key=>cookies可行,但反着来目前还不是很清楚怎么搞。所以仅有cookie的情况很难管理,且会大大增加程序编写的难度。(部分接口需要兼容两种调用方式)于是一直纠结着也没开始动手写。(这就是你咕咕咕的理由?

接口还是采取客户端逆向为主要获取方式。上次逆向都是两年前的事情了,所以这次采用最新版本重新更新了下代码。由于时间限制,我也没处理逆向出来的代码(可运行、重命名)。具体的工作状态可以查看DIARY:https://blog.kaaass.net/diary/2018/bilidroid-decomplie-diary/ 。

还是想提及BiliAPI的设计理念——方便。我的目标就是,开发者可以在不显式声明任何BiliAPI对象的情况下使用BiliAPI的所有功能。复杂的内部结构是便于进一步开发和第三方再次开发的,而一般使用的开发者不应该关系这些内部实现。我的逻辑和之前翻译的文章里说的一样,code should be self-revealing(代码本身就应该可被理解)。文档是所有接口的介绍,注释是具体实现的说明,而这些通常会提供很多暂时无用的信息。而简洁的代码甚至能起到无需文档的效果。这就是我一直坚持把不同模块解耦的原因。

以我第一次重构后的接口为例,请求是通过Request对象实现的,而接口内部就有一个默认对象。App对象用于存放ak、sk和app_type,通用库也会持有一个默认对象。所以开发者只需要调用biliapi.set_default_key_pair(AK, SK, biliapi.AppType.phone_android)就会自动创建App对象和请求用的Request对象,而调用接口也不需要传入Request对象。比如获取某个用户的信息,两行足矣:

biliapi.set_default_key_pair(AK, SK, biliapi.AppType.phone_android)
data = biliapi.user.info(1)

(biliapi.user模块YY中)

鉴权都在biliapi.auth,无脑biliapi.auth.login(usr, pwd)。程序会自动向Request注册包含鉴权信息(access_key+cookies)的Auth对象(原先的设计是Request持有Auth对象)。唯一麻烦的就是oauth2(默认oauth2图片验证码,oauth3网页形式更加复杂)有个图片验证码,需要catch一个CapthcaRequire的Exception。具体可以看authtest.py(虽然名字叫test,但并没有单元测试,看起来更像是example 23333)。

最后还是咕咕咕。

分享到

KAAAsS

喜欢二次元的程序员,喜欢发发教程,或者偶尔开坑。(←然而并不打算填)

相关日志

  1. 没有图片
  2. 没有图片
  3. 没有图片
  4. 没有图片

评论

  1. JLoeve 2018.09.08 8:13下午

    链式调用让Python看起来更像是Java了 XD

    • KAAAsS 2018.09.09 10:16下午

      JavaJavaJa~

      • JLoeve 2018.09.09 10:50下午

        niconiconi~ (这是一条有声音的评论)

  2. 相宇 2018.09.13 3:46下午

    大佬啊。请问能搞一个bili视频投稿的API吗。。。。。萌新抱大腿

    • KAAAsS 2018.09.18 9:29下午

      会有的,视频投稿接口在开发计划之内。

  3. MCyiqiehuanying 2021.04.23 8:34下午

    BiliAPI用户调用端口403了

    • KAAAsS 2021.04.28 10:23上午

      登录接口暂时不维护了

在此评论中不能使用 HTML 标签。