哔哩哔哩投稿工具抓包分析

2021年01月21日 1245点热度 0人点赞 0条评论

很久之前说过, B站转载视频是放在服务器上托管了, 也一直再用一个叫做bilibiliupload的包. 经过几次改版, 部分接口需要改动, 可能是作者没有时间维护这个包, 导致部分功能失效, 准备着手自己抓包看看.

准备

其实还有个原因, 2021年呢, 准备做个全职UP主, 所以不但算在主账号上发布转载视频了, 但是也不想放弃这个转载视频(关注的人不多, 但是不少用户还是会求更新的), 就在小号中转载, 但是这个账号吧, 在网页端不支持分P, 转载视频一般都用添加分P来规避专车检查.

之前用的这个包, 上传部分用的就是网页端接口, 于B站客服沟通得知, 说是网页端更新导致, 使用投稿工具就可以分P了. 所以就自己造个轮子吧.

  • Proxifier
  • Fiddler 或 Charles

Proxifier用来使投稿工具走代理, Fiddler Charles 负责抓包.

分析

具体抓包过程就不发截图了, 因为都没有什么难点, 只要这几个工具都知道怎么使用(基础操作)就行了. 有需要可以在评论回复.

登录

这部分就两个POST请求, 先获取用来加密的公钥以及盐, 接着访问登录接口就好了.

POST https://passport.bilibili.com/api/oauth2/getKey
#参数
appkey	aae92bc66f3edfab
platform	pc
sign	89c2f1e93c09fedd2a1c5f0a3a678326
ts	1610018294

appkey可以理解为是用来区分客户端的, 几乎所有操作请求都需要这个参数. platform就是平台的意思, 这类参数一般不用考虑默认就行. sign是对整个请求的参数进行加盐后MD5的校验值. 这个盐和appkey是对应的每个客户端一对, 具体可以在这里查看: https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/other/API_auth.md, ts不多说了时间戳.

#返回数据
{
	"ts": 1610018294,
	"code": 0,
	"data": {
		"hash": "0cff56e2df266d5b",
		"key": "-----BEGIN PUBLIC KEY-----xxxxxxx-----END PUBLIC KEY-----\n"
	}
}

返回数据data中, hash就是盐, hash+密码之后的值进行rsa加密, 加密所需的公钥就是另一个数据key.

POST https://passport.bilibili.com/api/v3/oauth2/login
#参数
appkey	aae92bc66f3edfab

password	3oQkoLueIK1xxxx
platform	pc
sign	a8b948458bf2e11da33dfda14717b7e1
ts	1610018295
username	xxxxxxx

和上面唯一不通的就是usernamepassword, 用户名和密码, 用户名是明文, 密码就是上面所说的加密方式.

{
	"ts": 1610018295,
	"code": 0,
	"data": {
		"status": 0,
		"token_info": {
			"mid": 729739818,
			"access_token": "c7f172ea71144cb922ead8bd2e86155e",
			"refresh_token": "a737bdf10f504fc299d2ed34e03a337d",
			"expires_in": 2592000
		},
		"cookie_info": {},
		"sso": []
	}
}

返回值中就当前的功能我们所需的就是token_info中的四个属性值. mid用户ID, access_token请求令牌, 有了这个令牌就有了整个账户的控制权限. refresh_token刷新令牌, 就是为了刷新请求令牌用的, expires_in就是请求令牌的时效, B站的令牌一般都是30天, 所以快到30天的时候可以用refresh_token来刷新令牌. 其余的cookie_info和sso是有值的, 只是用不上就不说讲.

这两个请求需要注意的就是, 请求头Content-Type: application/x-www-form-urlencoded, 以及一个空白的User-Agent. 另外就是getKey的请求会生成一个Cookie: sid=xxxxxxxx, 这个建议带上.

上传视频

这部分三个请求, 预上传, 上传, 添加视频

预上传

GET http://member.bilibili.com/preupload

access_key	c7f172ea71144cb922ead8bd2e86155e
mid	729739818
profile	 ugcfr/pc3

预上传, access_keymid分别是上一步登录成功获取的请求令牌以及用户ID, profile可能是上传工具的一个标志吧, 不用改变原封不动添加上就行.

{
	"complete": "http://upcdn-szqn.bilivideo.com/vs814/xxxxx",
	"OK": 1,
	"url": "http://upcdn-szqn.bilivideo.com/xxxx5",
	"filename": "xxxxxxxxxxxxxxxxxxx"
}

返回值, OK代表状态, 不是1就说明出现错误了. url就是下一步视频上传所需要的地址, complete是上传完毕的请求, 告诉服务器之前的视频(分片)传完了. filename是服务器中的文件名字, 后续添加视频的时候要用到.

上传视频

上传就用截图解释了, POST请求, 地址就是预上传请求返回的url, Content-Type为 multipart/form-data. 发送参数如下.

返回值如果正常上传只有两个返回值, {"OK": 1, "info": "Successful."}.

上传完毕通知

POST http://upcdn-szqn.bilivideo.com/vs814/xxxxxxxxxx
chunks	75

filesize	155245475

md5	a975ee0a86c1460e074ba3fd604157f4

name	xxxxx.mp4

version	2.2.0.1057

上传完毕的通知请求, chunks文件块的数量, filesize文件大小, md5文件MD5, name本地文件名, version上传工具版本号. 其请求正常返回值也是只有OK 和 info两个参数.

添加视频

POST http://member.bilibili.com/x/vu/client/add

access_key    c7f172ea71144cb922ead8bd2e86155e
sign    8354da9b8dc51f2051d9cb844e060265
{
    "build": 1057,
    "copyright": 2,
    "cover": "http://i0.hdslb.com/bfs/archive/424ff37639d5cd727b222bea87af5761ee624b20.png",
    "desc": "youtube",
    "no_reprint": 0,
    "open_elec": 1,
    "source": "转载来源",
    "tag": "\u82F1\u96C4\u8054\u76DF",
    "tid": 171,
    "title": "视频标题",
    "videos": [
        {
            "desc": "",
            "filename": "xxxxxxxxxxxx",
            "title": "P1视频标题"
        },
        {
            "desc": "",
            "filename": "xxxxxxxxxxxx",
            "title": "P2视频标题"
        }
    ]
}

具体参数的解释可以查看文末提供的Python代码, 已经分享到GitHub Gist上面了. 也是目前正在使用的上传脚本.

{
    "code": 0,
    "message": "0",
    "ttl": 1,
    "data": {
        "aid": 288600734,
        "bvid": "BV1hf4y1y75f"
    }
}

返回值一目了然 两个ID, 现在用的就是BV了.

成品

Python编写的脚本, 使用到的第三方模块只有requests. 脚本中还提到了预览图上传以及刷新token的功能.

地址: https://gist.github.com/Virace/f6036bfd2baa8129ec6b142230b10924

注释感觉挺多的, 如果有什么问题可以在本文下方评论反馈, 也可以在Github上反馈.

整体分析过程没什么难度, 因为已经有前人铺路了, 很多轮子都有. 比如说参数签名等. 而且在上传工具登录过程中没有出现过验证码, 如果出现了验证码, 那就手动处理一下验证码, 后续只用刷新token就可以了.

文章评论