从零开始仿写一个B站客户端之抓包接口

栏目: Html5 · 发布时间: 7年前

内容简介:从零开始仿写一个B站客户端之-抓包B站接口

从零开始仿写一个B站客户端之-编译ijkplayer

从零开始仿写一个B站客户端之-抓包B站接口

从零开始仿写一个B站客户端之-使用ijkplayer打造一个通用的播放器

从零开始仿写一个B站客户端之-整体架构设计和网络请求封装

既然要仿写一个客户端,那么数据从哪儿来呢?刚开始打算用springboot自己写后端,然后去学吧,第一个hello world项目就运行不起了(;′⌒`),这不是明示我劝退吗。所以果断抓包B站接口,不需要花费时间写后端代码,还还不缺数据来源。

抓包 工具 使用的是 fiddler ,对手机上的B站客户端进行抓包。需要注意的是必须确保安装 fiddler 的电脑和手机在同一个局域网环境下 。

电脑上的配置

fiddler

安装好 fiddler 之后,在Tools->Options->Connections中这样配:

从零开始仿写一个B站客户端之抓包接口
从零开始仿写一个B站客户端之抓包接口

Fiddler listens on port是手机连接fiddler时的代理端口号,.Allow remote computers to connect是允许远程(手机端)发送请求。

配置Https:

从零开始仿写一个B站客户端之抓包接口

点击ok之后,在手机上访问电脑ip+8888,电脑ip查看方式是在cmd中输入ipconfig:

从零开始仿写一个B站客户端之抓包接口

手机上的配置

我这里的ip是192.168.0.134,手机端用自带的浏览器访问: http://192.168.0.134:8888下载证书并安装。点击最下面那个蓝色链接安装证书:

从零开始仿写一个B站客户端之抓包接口

emmm...小米手机不能直接安装,需要从更多设置 ->系统安全->加密与凭据->从sd卡中安装证书

安装证书完成之后,需要修改wifi的网络,手动设置代理,代理服务器主机名为电脑的IP地址,代理端口为在fiddler里设置的端口号,保存后,fiddler将能够收到手机上的请求信息:

从零开始仿写一个B站客户端之抓包接口

准备就绪,可以在手机上打开B站客户端开始抓包了:

从零开始仿写一个B站客户端之抓包接口

接口分析

以直播up主的粉丝榜接口为例,抓到的接口是这个样子的:

http://api.live.bilibili.com/rankdb/v2/RoomRank/mobileMedalRank?actionKey=appkey&appkey=1d8b6e7d45233436&build=5400000&channel=bilibiil140&device=android&mobi_app=android&page=1&platform=android&roomid=2910685&ruid=33588706&ts=1556159005&sign=fdc0eb4340508ad9a62d1a27146a4183
复制代码

这太长了,可以剔除一些无用信息,变为下面这样:

http://api.live.bilibili.com/rankdb/v2/RoomRank/mobileMedalRank?page=1&roomid=2910685&ruid=33588706
复制代码

其中 page 表示第一页, roomid 表示房间号, ruid 表示up主的uid。

有些接口是可以剔除的,但是有些接口是必须要一家人整整齐齐的,比如获取直播up主的uid信息就需要全部参数:

http://api.live.bilibili.com/xlive/app-room/v1/index/getInfoByRoom?actionKey=appkey&appkey=1d8b6e7d45233436&build=5400000&channel=bilibiil140&device=android&mobi_app=android&platform=android&room_id=2910685&ts=1556157467&sign=811b018c9e54efad87e4ec16a76cd111
复制代码

前面的参数几乎都是固定的,除了最后的 roomidts 以及 sign ,如果有一个参数不正确,服务器就会返回下面的错误:

{
	"code": -3,
	"message": "API校验密匙错误",
	"ttl": 1
}
复制代码

API校验密匙就是最后一个参数 sign ,它是通过前面的参数 排序 之后,加上 SecretKey 做md5生成的,其中 SecretKey 存放在了so库中,具体操作参考了@Misery_Dx的:

仿B站Android客户端系列(启动篇)

获取sign的代码:

fun getSign(map: Map<String, Any>): String {
        //拼接参数(按顺序) + SecretKey
        val orignSign = getUrlParamsByMap(map) + SECRET_KEY
        //进行MD5加密
        var sign = ""
        try {
            sign = MD5Util.getMD5(orignSign).trim()
            Log.i(TAG, "加密后的sign: $sign")
        } catch (e: NoSuchAlgorithmException) {
            Log.e(TAG, "sign encryption failed: ${e.printStackTrace()}")
        }
        return sign
    }

/**
     * 将map转换成url参数
     * @param map
     * @return
     */
    fun getUrlParamsByMap(map: Map<String, Any>): String {
        var params =  StringBuffer()
        val it = map.iterator()
        while (it.hasNext()) {
            val str = it.next()
            params.append(str.key)
            params.append("=")
            params.append(str.value)
            if (it.hasNext()) {
                params.append("&")
            }
        }
        return params.toString()
    }
复制代码

能获取到 sign ,大部分的问题就解决了。

直播弹幕的获取参考 @lovelyyoshino直播弹幕 WebSocket 协议 ,嗯。。。没搞定,不知道是我发送的封包数据有问题还是B站直播弹幕协议变了,如果有大佬能搞定,希望能不吝赐教,感谢感谢~。

这是发送数据封包的方法:

/**
     * @param cmd 命令
     * @param data 数据包
     */
    private fun sendCmd(cmd: Int, data: ByteArray, webSocket: WebSocket){
        var buffer = ByteBuffer.allocate(16 + data.size)
        buffer.order(ByteOrder.BIG_ENDIAN)  //字节序为大端模式
        buffer.putInt(16 + data.size)
        buffer.putShort(16)  //头部长度
        buffer.putShort(1)  //协议版本,目前是1
        buffer.putInt(cmd)  //操作码(封包类型)
        buffer.putInt(1)  //sequence,可以取常数1
        buffer.put(data)
        webSocket.send(ByteString.of(buffer))
    }
复制代码

这是使用okhttp3自带的websocket实现的加入房间:

private var webSocket: okhttp3.WebSocket? =null
    fun joinRoom(roomId:Int){
        var client = OkHttpClient.Builder().build()
        var request = Request
            .Builder()
            .url(GlobalProperties.LIVE_DANMAKU_URL)
            .build()
        webSocket = client.newWebSocket(request,object : WebSocketListener(){
            override fun onOpen(webSocket: okhttp3.WebSocket, response: Response) {
                super.onOpen(webSocket, response)
                var inRoomMessage = JSONObject()
                inRoomMessage.put("clientver","1.6.3")
                inRoomMessage.put("platform","web")
                inRoomMessage.put("protover",2)
                inRoomMessage.put("roomid",roomId)  //必填
                inRoomMessage.put("type",2)
                var bytes = inRoomMessage.toString().toByteArray(Charsets.UTF_8)
                sendCmd(7, bytes, webSocket)
                Log.d(TAG,"websocket连接成功,发送进房消息$inRoomMessage")
            }

            override fun onMessage(webSocket: WebSocket, bytes: ByteString) {
                super.onMessage(webSocket, bytes)
                Log.d(TAG,"websocket接收消息$bytes")
            }
            override fun onClosed(webSocket: okhttp3.WebSocket, code: Int, reason: String) {
                super.onClosed(webSocket, code, reason)
                Log.d(TAG,"websocket断开连接")
                exitRoom()
            }

            override fun onFailure(webSocket: okhttp3.WebSocket, t: Throwable, response: Response?) {
                super.onFailure(webSocket, t, response)
                Log.d(TAG,"websocket连接失败: $response , throw: $t")
                exitRoom()
            }
        })
    }
复制代码

第一次连接成功之后,发送进房消息,然后连接就立即断开了,应该是我发送的数据不对,才导致服务端主动断开连接的。

目前暂时是使用直播历史评论抓取,而不是实时的:

http://api.live.bilibili.com/xlive/app-room/v1/dM/gethistory?room_id=2910685
复制代码

直播弹幕的获取暂时就放后面再说了~

目前我抓取的接口都放在 GlobalProperties 这个类里面,不想自己抓包的同学可以去这里看:

项目地址: 仿BiliBili客户端


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Shallows

The Shallows

Nicholas Carr / W. W. Norton & Company / 2011-6-6 / USD 15.95

"Is Google making us stupid?" When Nicholas Carr posed that question, in a celebrated Atlantic Monthly cover story, he tapped into a well of anxiety about how the Internet is changing us. He also crys......一起来看看 《The Shallows》 这本书的介绍吧!

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具