czp3009 / bilibili-api

Bilibili API library for Kotlin
GNU General Public License v3.0
511 stars 50 forks source link

小电视抽奖, 丰收庆典, 新春抽奖 等的执行过程 #4

Closed czp3009 closed 5 years ago

czp3009 commented 6 years ago

在弹幕推送 socket 中, 小电视抽奖通知对应 SYS_MSG, 数据包差不多如下

{
  "cmd": "SYS_MSG",
  "msg": "\u3010\u5e7d\u5c0f\u591c\u5929\u5c0f\u52ab\u3011:?\u5728\u76f4\u64ad\u95f4:?\u3010392\u3011:?\u8d60\u9001 \u5c0f\u7535\u89c6\u4e00\u4e2a\uff0c\u8bf7\u524d\u5f80\u62bd\u5956",
  "msg_text": "\u3010\u5e7d\u5c0f\u591c\u5929\u5c0f\u52ab\u3011:?\u5728\u76f4\u64ad\u95f4:?\u3010392\u3011:?\u8d60\u9001 \u5c0f\u7535\u89c6\u4e00\u4e2a\uff0c\u8bf7\u524d\u5f80\u62bd\u5956",
  "rep": 1,
  "styleType": 2,
  "url": "http:\/\/live.bilibili.com\/392",
  "roomid": 392,
  "real_roomid": 71084,
  "rnd": 44332151,
  "tv_id": "29349"
}

丰收庆典以及新春抽奖等普通抽奖对应 SYS_GIFT

{
  "cmd": "SYS_GIFT",
  "msg": "sakamakiryoryo\u5728\u76f4\u64ad\u95f471084\u5f00\u542f\u4e86\u4e30\u6536\u796d\u5178\uff0c\u4e00\u8d77\u6765\u5206\u4eab\u6536\u83b7\u7684\u798f\u5229\u5427\uff01",
  "msg_text": "sakamakiryoryo\u5728\u76f4\u64ad\u95f471084\u5f00\u542f\u4e86\u4e30\u6536\u796d\u5178\uff0c\u4e00\u8d77\u6765\u5206\u4eab\u6536\u83b7\u7684\u798f\u5229\u5427\uff01",
  "tips": "sakamakiryoryo\u5728\u76f4\u64ad\u95f471084\u5f00\u542f\u4e86\u4e30\u6536\u796d\u5178\uff0c\u4e00\u8d77\u6765\u5206\u4eab\u6536\u83b7\u7684\u798f\u5229\u5427\uff01",
  "url": "http:\/\/live.bilibili.com\/71084",
  "roomid": 71084,
  "real_roomid": 71084,
  "giftId": 102,
  "msgTips": 0
}

ACTIVITY_EVENT 带有某种活动的进度信息

{
  "cmd": "ACTIVITY_EVENT",
  "data": {
    "keyword": "newspring_2018",
    "type": "cracker",
    "limit": 300000,
    "progress": 158912
  }
}

小电视和普通抽奖的通知都会带有一个 URL, 在 web 上进入这个 URL, 点击悬浮窗即可抽奖.

尚不明确 Android 上看直播时有没有 SYS_MSG 和 SYS_GIFT 的提示(印象中好像没见到过).

尚不明确 Android 上参与抽奖的 API(是一个 Restful API, 不是发弹幕, 发弹幕只是副作用)(不太清楚 Android 上能不能抽奖).

抽奖之后开奖有两种, 一种是 socket 内直接推送的大奖获得者信息(例如 TV_END)(不明确除了小电视抽奖, 其他普通抽奖会不会有类似的大奖推送).

另一种是通过 Restful API 拉取的奖励(参与抽奖至少有辣条, 所以人人都有), 这在 Android 上的 API 是怎么样的也不明确(如果 Android 不能抽奖的话那这个 API 也肯定是没有的).

以上问题尚未解决, 先留存案.

lkeme commented 6 years ago

新春抽奖应该是这个,

{
"cmd": "SYS_GIFT",
"msg": "小螃海白翼OuO在直播间5540554开启了新春抽奖,红包大派送啦!一起来沾沾喜气吧!",
"msg_text": "小螃海白翼OuO在直播间5540554开启了新春抽奖,红包大派送啦!一起来沾沾喜气吧!",
"tips": "小螃海白翼OuO在直播间5540554开启了新春抽奖,红包大派送啦!一起来沾沾喜气吧!",
"url": "http://live.bilibili.com/5540554 ",
"roomid": 5540554,
"real_roomid": 5540554,
"giftId": 113,
"msgTips": 0
}

新春抽奖好像今天就结束了!

czp3009 commented 6 years ago

那看来除了小电视之外的抽奖全部都是 SYS_GIFT。 我把issue改一下。

lkeme commented 6 years ago
{
  "cmd": "ACTIVITY_EVENT",
  "data": {
    "keyword": "newspring_2018",
    "type": "cracker",
    "limit": 300000,
    "progress": 148984
  }
}

这个应该是 赠送红灯笼的总数吧,

有人赠送红灯笼,就会收到ACTIVITY_EVENT信息,

progress也会相应增加。

czp3009 commented 6 years ago

在 "newspring_2018" 这个活动里确实是灯笼数量,其他活动里可能表示其他含义,所以这个数据包的含义是不固定的。

lkeme commented 6 years ago

ACTIVITY_EVENT就一个活动提醒,"newspring_2018" 就应该是现有的活动...

lkeme commented 6 years ago

有关于节奏风暴等礼物的Api吗

czp3009 commented 6 years ago

这个 ACTIVITY_EVENT 现在这段时间确实只有 "newspring_2018" 这一个活动, 但是其他时间段会有别的活动.

之前小米那个什么电量有多久就直播多久的活动(好像每次发新手机都有这个活动)(跟B站合作的), 我看到过名字叫 xiaomi 什么什么的活动名(数据包里), 说明这个活动有多种情况.

礼物 API 不太清楚是什么意思, 指送礼么. 抽奖的话我不太清楚, 很少看直播.

czp3009 commented 6 years ago

@lkeme 我大概知道节奏风暴是什么东西了.

Android 客户端在进入直播间时, 会先访问两个 API, 一个是

http://api.live.bilibili.com/SpecialGift/room/{roomId}

另一个是

http://api.live.bilibili.com/AppSmallTV/index?roomid={roomId}

出现小电视抽奖时(在 socket 里有通知, 即 SYS_MSG), 客户端上会有一个图标, 点击一下就可以进入对应直播间. 而进入直播间时, 会访问上面第二个 API 来获取当前房间是否有小电视, 如果有的话, 大概是这样的返回值

{
    "code": 0,
    "msg": "OK",
    "message": "OK",
    "data": {
        "lastid": 0,
        "join": [],
        "unjoin": [
            {
                "id": 39674,
                "dtime": 32
            }
        ]
    }
}

最里面的 id 就是小电视ID, 然后再通过 http://api.live.bilibili.com/AppSmallTV/join 进行抽奖.

(以上都是听来的, 我自己从来没见到过这个抽奖图标是怎么样的, 也没有抽过小电视)

而节奏风暴, 也是类似的一种抽奖.

(以前截到这两个数据包的时候完全不能理解是干嘛的, 现在大概是知道了)

我看了你的 一个项目 中, 关于节奏风暴的 socket 通知是 SEPECIAL_GIFT, 但是我从来没收到过这个数据包(当然也没在客户端上见过通知的 UI 是怎么样的). 我写了一个挂机脚本在服务器上, 用来检查还未发现的数据包类型.

如果可以的话, 希望您帮我对 Android 客户端上可能出现的几种抽奖通知截个图(可以的话还希望有抽奖和开奖的图), 我想了解一下在原生 APP 上的抽奖是怎么样的一个操作过程(我挂机了一晚上也没见到过一次, 不知道是什么回事).

lkeme commented 6 years ago

关于小电视抽奖,我使用的是web端api, socket 通知SYS_MSG里,有roomid,msg等

SEPECIAL_GIFT是我在另一个项目上看到的,去年的,估计已经被废弃了

节奏风暴的数据包 ,我在SYS_MSG里捕获到了,

{
    "cmd": "SYS_GIFT",
    "msg": "胖日残:? 在直播间 :?282:? 使用了 20 倍节奏风暴,大家快去跟风领取奖励吧!",
    "tips": "【胖日残】在直播间【282】使用了 20 倍节奏风暴,大家快去跟风领取奖励吧!",
    "giftId": 39,
    "msgTips": 1,
    "url": "http:\/\/live.bilibili.com\/282",
    "roomid": 62840,
    "rnd": 1519998177
}
czp3009 commented 6 years ago

我服务器挂机了大概两天,现在好像确实没有 SEPECIAL_GIFT 这个数据包了。

我用手机看了好久的直播, 还是没看到抽奖的提示。能帮我截个图么, 我想看一下手机上的抽奖提示和抽奖的过程。

lkeme commented 6 years ago

手机上我不知道,我的基于电脑网页的,没用手机看过直播,不知道是否有提示

lkeme commented 6 years ago

梦幻扭蛋是什么,就是扭蛋币吗?

czp3009 commented 6 years ago

梦幻扭蛋就是 普通扭蛋 隔壁的那个. 现在在"装修", 但是 API 已经知道了.

扭蛋币是用来抽扭蛋的东西, 送礼物可以加扭蛋币的进度, 到了之后就可以得到一个扭蛋币(梦幻扭蛋币好像不能通过送礼来自然获得).

然后一些任务也可以获得扭蛋币, 具体还不清楚,

czp3009 commented 6 years ago

@lkeme 我有个问题, "每日背包奖励" 是什么东西.

Android 客户端经常莫名其妙的去访问 http://api.live.bilibili.com/AppBag/sendDaily 这个地址, 我不知道是干嘛的, 他的返回值总是如下

{
    "code": 0,
    "msg": "ok",
    "message": "ok",
    "data": {
        "result": 2
    }
}

看这个 URL 大概就是 "每日背包奖励", 能请教一下这个是干嘛的么

lkeme commented 6 years ago

好像是能领取每日道具的 对应的web端的api,应该是这个

https://api.live.bilibili.com/giftBag/sendDaily

czp3009 commented 6 years ago

这个 API, 每次访问, 里面似乎都没有什么内容. 它确实是这样还是应该是有内容的.

lkeme commented 6 years ago

我猜测应该每天的第一次这个访问API才有想要的数据, "result": 2或许是已经领取的吧

czp3009 commented 6 years ago

我明天试一下

lkeme commented 6 years ago

我拿了个新账号打算试一下的,但是web端API显示维护中

lkeme commented 6 years ago

今天web端的API很多都在维护,不知道是不是要大改,客户端的API有改或者维护吗

czp3009 commented 6 years ago

客户端API我测了一些,都正常。

客户端API通常不会突然失效或者改动,因为肯定要兼容旧版app。

czp3009 commented 6 years ago

我刚看了一下挂机的收获, 真的截到了 SPECIAL_GIFT 这个数据包, 有两种, 一种是节奏风暴开始, 一种是节奏风暴结束(就跟你的项目中的代码是一样的)

{
  "cmd": "SPECIAL_GIFT",
  "data": {
    "39": {
      "id": 202089,
      "time": 90,
      "hadJoin": 0,
      "num": 1,
      "content": "我要吃狗肉火锅",
      "action": "start",
      "storm_gif": "http://static.hdslb.com/live-static/live-room/images/gift-se
ction/mobilegift/2/jiezou.gif?2017011901"
    }
  }
}
{
  "cmd": "SPECIAL_GIFT",
  "data": {
    "39": {
      "id": 202089,
      "action": "end"
    }
  }
}

所以节奏风暴跟小电视的抽奖原理应该是一样的, 如果在节奏风暴的持续过程中访问

http://api.live.bilibili.com/SpecialGift/room/{roomId}

就可以得到节奏风暴的详细信息, 然后就可以参与抽奖了.

但是客户端上没见过抽奖提示, 所以也不知道客户端的 API 是怎么样的.

如果调用 Web API 来进行抽奖的话, 就感觉代码很脏.

抽奖的事情我再去了解一下.

lkeme commented 6 years ago

我大概了解了节奏的流程,和小电视差不多,

socket SYS_GIFT -> check -> join

只是加入节奏的api,有几个POST参数我没暂时还没搞懂 但是有时候很奇怪,我在SYS_GIFT里截到了节奏风暴的包, 但是没有关于SPECIAL_GIFT的包,很困惑

这个API我是第一次看见,这是客户端上面的吗?

http://api.live.bilibili.com/SpecialGift/room/{roomId}

这个好像是web端检测节奏风暴的API

http://api.live.bilibili.com/lottery/v1/Storm/check?roomid={roomId}

kuertianshi commented 6 years ago

web端的节奏风暴抽奖参数就是颜色,验证码和cookies里的bili_jct,app端的不太了解

kuertianshi commented 6 years ago

sendDaily 是用来获取每日奖励的,比如勋章到一定等级每天赠送几个亿元

czp3009 commented 6 years ago

@lkeme SPECIAL_GIFT,TV_START,TV_END 这三个包用来表示 节奏风暴, 小电视 的开始和结束, 只在发生 节奏风暴 或 小电视 抽奖的房间才会发生(即出现这些数据包)。在其他直播间只会出现 SYS_MSG 和 SYS_GIFT(用来通知全站哪个直播间出现 抽奖)。

这个 API 确实是在 APP 的 API, 用来确认一个房间有没有节奏风暴用的, 返回值还不明确。

lkeme commented 6 years ago

每天的节奏风暴感觉太少了,导致截包不全面,我测试的时候一直默认到3房间,貌似一直没有过节奏风暴,所以一直没截获到SPECIAL_GIFT

czp3009 commented 6 years ago

@lkeme 我找了另一个人的号,来测试 http://api.live.bilibili.com/AppBag/sendDaily,这个号今天是第一次访问这个 API, 返回的 result 为 1, 再次访问, 也是 1, 再访问 还是 1.

现在过了零点, 我用我自己的号访问这个 API, result 继续为 2, 之后的访问也是 2.

似乎每个账号访问这个 API 的返回值是固定的, 不同的账号可能不一样。

B站一些 API 是 cookies 验证和 token 验证只要有一个满足就可以通过鉴权, 这个 API 也是如此, 你直接在浏览器打开看一下返回值是什么。

我估计这个 result 可能是权限组(老爷什么之类的,因为我借来的那个号是年费老爷)。

czp3009 commented 6 years ago

@lkeme 3号直播间是不会有小电视,节奏风暴什么之类的, 因为不会有人给官方直播间刷这种昂贵的礼物。

我是在隔壁 宫本狗雨 的直播间自动挂机看到的 节奏风暴 数据包。

lkeme commented 6 years ago

确实,我刚才用2个号测试,都不是老爷

//第一个
{"code":0,"msg":"ok","message":"ok","data":{"result":1}}
//第二个
{"code":0,"msg":"ok","message":"ok","data":{"result":2}}
czp3009 commented 6 years ago

都不是老爷, 但是返回值不一样, 那估计这个值不是权限组的意思。

lkeme commented 6 years ago

3号直播间,是我忽略了这个问题,明天晚上再修改下房间,采集一下数据包

lkeme commented 6 years ago

我今天晚上也尝试在客户端上看了半个小时左右的直播,但是一直没有看到小电视等礼物提示

czp3009 commented 6 years ago

我问了一些人, 好像都没有注意到手机端有抽奖提示。 但是手机端确实存在 socket 数据包 和 抽小电视的 Restful API(AppSmallTV/join 参数未知), 所以不知道是怎么回事情

lkeme commented 6 years ago

我网页和客户端都打开的,网页端有小电视提醒了,但是客户端么有,不知道在哪里提醒的

czp3009 commented 6 years ago

在互联网搜索 "小电视直播抽奖" 时, 能搜到这样的一条新闻(很多网站转发) http://www.sohu.com/a/113845802_114822

时间是 2016 年, 说明当时确实是有在手机上抽小电视的功能的, 可能后来把这个功能去掉了.

因此 socket 中的有关数据包还是在的, Restful API 也还是在的. 但是因为截不到包, 所以参数要靠猜了

kuertianshi commented 6 years ago

如果没猜错http://api.live.bilibili.com/AppBag/sendDaily对应的应该是http://api.live.bilibili.com/gift/v2/live/receive_daily_bag

czp3009 commented 6 years ago

我今天早上访问 http://api.live.bilibili.com/AppBag/sendDaily 的时候, 里面的 result 是 1.

然后我访问了 http://api.live.bilibili.com/gift/v2/live/receive_daily_bag 里面包含了一条一个粉丝勋章对应的每日奖励的数据. 数据差不多如下

{  
    "code":0,
    "msg":"success",
    "message":"success",
    "data":{  
        "bag_status":2,
        "bag_expire_status":1,
        "bag_list":[  
            {  
                "type":1,
                "bag_name":"粉丝勋章礼包",
                "source":{  
                    "medal_id":"1306380",
                    "medal_name":"甜甜天",
                    "level":2
                },
                "gift_list":[  
                    {  
                        "gift_id":"1",
                        "gift_num":2,
                        "expire_at":1520870400
                    }
                ]
            },
            {  
                "type":2,
                "bag_name":"用户等级周常礼包",
                "source":{  
                    "user_level":25
                },
                "gift_list":[  
                    {  
                        "gift_id":"1",
                        "gift_num":50,
                        "expire_at":1521414895
                    }
                ]
            }
        ],
        "time":1520810140
    }
}

我尝试再次访问这两个 API, 返回值保持不变, 我立即打开 Android 客户端, 随便打开一个直播间, 收到了奖励消息的提示(模态框).

我现在(下午)访问这两个 API 时, sendDaily 返回了 2, 而 receive_daily_bag 返回了没有内容的数据, 差不多如下

{
    "code": 0,
    "msg": "success",
    "message": "success",
    "data": {
        "bag_status": 2,
        "bag_expire_status": 1,
        "bag_list": [],
        "time": 1520666253
    }
}

我之前在凌晨的时侯, 访问了两个账号的 sendDaily, 一个返回 1(没领取过每日任务), 一个返回2(没领取过每日任务). 现在(下午)又尝试了两个账号访问 sendDaily, 均返回 2(一个领过了一个没有). 所以完全不理解 sendDaily 的返回值到底是什么含义. 既不与领取过每日奖励有否有关, 也不与时间有关, 但是仿佛又都有点关系.

在 Android 客户端上, sendDaily 在每次进入一个直播间时都会访问, 而且返回的内容不包含任何有含义的内容.

跳出每日奖励是在查看背包时, 也就是说, 查看背包时会去检查是否有每日奖励. 我之前没有粉丝勋章, 所以假设这个流程确实是这样的, 我也截不到包.

所以这个 sendDaily 可能是没用的, 客户端查询是否有每日奖励是另一个 API. 我明天试着重新截包看一下.

lkeme commented 6 years ago

这个API很不明确意义,我刚才尝试2个号分别访问sendDaily,都返回2

访问receive_daily_bag ,bag_list里也是没有数据

czp3009 commented 6 years ago

我猜出参与小电视抽奖的 API 了, 是这样的

AppSmallTV/join

参数为 roomid 和 id

roomid 即房间号, id 是小电视 id.

返回值为

{"code":0,"msg":"OK","message":"OK","data":{"id":40151,"dtime":180,"status":1}}

查询小电视抽奖的 API 没有猜出来, 并不是 AppSmallTV/notice , 这和 Web API 不太一样.

lkeme commented 6 years ago

确实不一样,Web的是raffleId ,这里用id是"SYS_MSG里的tv_id吗?

在服务器上跑了2天,确实捕获到了SPECIAL_GIFT数据包

|-- DANMU_MSG.txt
|-- GUARD_BUY.txt
|-- GUARD_MSG.txt
|-- LIVE.txt
|-- PREPARING.txt
|-- ROOM_BLOCK_MSG.txt
|-- ROOM_SILENT_ON.txt
|-- SEND_GIFT.txt
|-- SPECIAL_GIFT.txt
|-- SYS_GIFT.txt
|-- SYS_MSG.txt
|-- TV_END.txt
|-- TV_START.txt
|-- WELCOME_GUARD.txt
|-- WELCOME.txt
|-- WISH_BOTTLE.txt
{
    "cmd": "SPECIAL_GIFT",
    "data": {
        "39": {
            "id": 204225,
            "action": "end"
        }
    }
} 
{
    "cmd": "SPECIAL_GIFT",
    "data": {
        "39": {
            "id": 204226,
            "time": 90,
            "hadJoin": 0,
            "num": 1,
            "content": "狗先生敲里吗听见没敲里吗",
            "action": "start",
            "storm_gif": "http:\/\/static.hdslb.com\/live-static\/live-room\/images\/gift-section\/mobilegift\/2\/jiezou.gif?2017011901"
        }
    }
} 
{
    "cmd": "SPECIAL_GIFT",
    "data": {
        "39": {
            "id": 205377,
            "time": 90,
            "hadJoin": 0,
            "num": 1,
            "content": "月轮来袭",
            "action": "start",
            "storm_gif": "http:\/\/static.hdslb.com\/live-static\/live-room\/images\/gift-section\/mobilegift\/2\/jiezou.gif?2017011901"
        }
    }
}
czp3009 commented 6 years ago

是的, id 就是 SYS_MSG 里面的 tv_id.

czp3009 commented 6 years ago

我差不多猜到 APP 的抽小电视 API 了, 大概是

https://api.live.bilibili.com/AppSmallTV/getReward

参数为 id(tv_id)

有关节奏风暴, 我还没有见过节奏风暴, 所以我想了解一下参与节奏风暴是跟小电视一样的一种 Restful API 还是发送一个弹幕就可以了.

lkeme commented 6 years ago

我开始也以为发个弹幕就好了,后来发现也有个Api的

web端的节奏风暴,我大概摸清了

//检查

http://api.live.bilibili.com/lottery/v1/Storm/check?roomid={roomid}

//加入(需要id token captcha等参数)

http://api.live.bilibili.com/lottery/v1/Storm/join

//有几率会呼出验证码

https://api.live.bilibili.com/captcha/v1/Captcha/create?_={timestamp}&width=112&height=32

我打算测试的,但是最近两天不知道为什么,一直没抓到节奏风暴的包,一直没机会测试

czp3009 commented 6 years ago

最近两天我也没抓到节奏风暴的包. 我看了一下 B站 的说明, 必须要有 20倍 以上的节奏风暴, 才会全站广播, 一个节奏风暴 一百块, 那么就必须一次性花 两千块 才能广播一次. 再加上 B站直播 本来就不比隔壁什么斗鱼虎牙之类的火, 所以... =.=

lkeme commented 6 years ago

= =20倍才通告啊,我才知道...,这就更少了,要单独在一个房间,一天才几个

czp3009 commented 6 years ago

单独在一个房间等 SPECIAL_GIFT 的数据包的话, 基本是等不到的. 然后全站通告又要 20倍, 于是乎, 大海捞针. ORZ

lkeme commented 6 years ago

确实,就算做出来这个功能,感觉也很鸡肋

90s的时间,基本88s就已经结束了,如果服务器稍微有点延迟,就GG,

第二个就是验证码问题了,我测试2个号,基本都是百分百呼出验证码,而且验证码很不规则

等输入完了,早就结束了

lkeme commented 6 years ago

我看到一个项目的节奏风暴是这样写的,

直接取人气排行榜的房间,然后通过节奏风暴的api循环检查,

感觉效率很低,但也不是行不通,如果RP不好,全部都能错过

czp3009 commented 6 years ago

我想了一下, 由于 20倍 才广播, 所以取排行榜上的房间然后进去等 SPECIAL_GIFT 也不是不可行.

即使不使用异步模型, 使用简单的多线程, 开个二十个线程去连接二十个房间, 运行效率也不低, 然后在里面等 SPECIAL_GIFT 就行了, 不用轮询 Restful API.

APP 上的参与节奏风暴的 API 我还不清楚, 我估计是没有验证码的.