Merge remote-tracking branch 'upstream/master' into patch-1

This commit is contained in:
wuziqian211 2024-03-10 18:16:13 +08:00
commit f896727b3b
147 changed files with 32789 additions and 18605 deletions

View File

@ -3,6 +3,7 @@ on: [push]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
if: github.repository == 'SocialSisterYi/bilibili-API-collect'
steps:
- name: Checkout
uses: actions/checkout@master

3
.gitignore vendored
View File

@ -4,4 +4,5 @@ mkdocs/html/
/.vuepress/dist/
/node_modules/
.idea/
.vscode/
.vscode/
.DS_Store

8
.vuepress/client.js Normal file
View File

@ -0,0 +1,8 @@
import { defineClientConfig } from '@vuepress/client'
import Layout from './theme/layouts/Layout.vue'
export default defineClientConfig({
layouts: {
Layout,
},
})

View File

@ -1,38 +1,52 @@
module.exports = {
base: "/bilibili-API-collect/",
title: "BAC Document",
description: "社区开源的第三方哔哩哔哩 API 文档",
head: [
['link', { rel: 'icon', href: './logo2.jpg' }]
],
locales: {
'/': {
lang: 'zh-CN',
},
import { defaultTheme, defineUserConfig } from "vuepress";
import markdownItTaskLists from "markdown-it-task-lists";
import { copyCodePlugin } from "vuepress-plugin-copy-code2";
import { searchPlugin } from "@vuepress/plugin-search";
export default defineUserConfig({
base: "/bilibili-API-collect/",
lang: "zh-CN",
title: "BAC Document",
description: "社区开源的第三方哔哩哔哩 API 文档",
head: [["link", { rel: "icon", href: "/logo2.jpg" }]],
locales: {
"/": {
lang: "zh-CN",
},
themeConfig: {
logo: './logo2.jpg',
nav: [
{text: '首页', link: '/'},
{text: '目录', link: '/#🍴目录'},
{text: '贡献指南', link: '/CONTRIBUTING.html'},
{
text: '相关社群',
items: [
{text: 'QQ交流群', link: 'https://jq.qq.com/?_wv=1027&k=s1M0LCcu'},
{text: 'Telegram交流群', link: 'https://t.me/bilibili_API_collect_community'}
]
},
{text: 'GitHub', link: 'https://github.com/SocialSisterYi/bilibili-API-collect'},
},
theme: defaultTheme({
logo: "/logo2.jpg",
navbar: [
{ text: "首页", link: "/" },
{ text: "目录", link: "/#🍴目录" },
{ text: "贡献指南", link: "/CONTRIBUTING.html" },
{
text: "相关社群",
children: [
{
text: "QQ交流群综合技术交流",
link: "http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=2rRJXK3zgU5yi3e_4rNLeJYUjMLzw_Jj&authKey=L%2FN3EfZXo3QFjEuHq4ifTgh%2F384UmrYpjl7dbYPhYHtznhfJWxkymxQKObQunmEQ&noverify=0&group_code=560304737",
},
{
text: "Telegram交流群Github Bot推送",
link: "https://t.me/bilibili_API_collect_community",
},
],
sidebar: 'auto',
smoothScroll: true
},
plugins: [
'@vuepress/back-to-top',
},
],
markdown: {
lineNumbers: true,
plugins: ['task-lists']
}
}
sidebar: "auto",
repo: "https://github.com/SocialSisterYi/bilibili-API-collect",
docsBranch: "master",
editLinkText: "在 GitHub 上编辑此页",
colorMode: "auto"
}),
plugins: [copyCodePlugin({}), searchPlugin({})],
markdown: {
code: {
lineNumbers: true,
},
},
extendsMarkdown: (md) => {
md.use(markdownItTaskLists);
},
});

View File

@ -1,3 +0,0 @@
module.exports = {
extend: '@vuepress/theme-default'
}

View File

@ -1,21 +1,18 @@
<template>
<ParentLayout>
<template #page-bottom>
<footer style="text-align: center;">
Copyright © 2020-2023 <a href="https://github.com/SocialSisterYi/">SocialSisterYi</a> |
<a href="https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/LICENSE">CC-BY-NC-4.0 Licensed</a>
<footer style="text-align: center">
Copyright © 2020-2023
<a href="https://github.com/SocialSisterYi/">SocialSisterYi</a> |
<a
href="https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/LICENSE"
>CC-BY-NC-4.0 Licensed</a
>
</footer>
</template>
</ParentLayout>
</template>
<script>
import ParentLayout from '@parent-theme/layouts/Layout.vue'
export default {
name: 'Layout',
components: {
ParentLayout
}
}
</script>
<script setup>
import ParentLayout from '@vuepress/theme-default/layouts/Layout.vue';
</script>

View File

@ -4,12 +4,49 @@
## 总则
[bilibili-API-collect](https://github.com/SocialSisterYi/bilibili-API-collect) 项目(简称 BAC 或 b-a-c是一个仅用于学习研究、社区开源、公益性质的 [B站哔哩哔哩](https://www.bilibili.com/) API应用程序接口 文档,使用 [CC-BY-NC 4.0 协议](LICENSE) 开源,它将无差别收集整理相关的**主站业务接口**。
[bilibili-API-collect](https://github.com/SocialSisterYi/bilibili-API-collect) 项目(简称 BAC 或 b-a-c是一个仅用于学习研究、社区开源、公益性质的 [B站哔哩哔哩](https://www.bilibili.com/) API应用程序接口 文档,使用 [CC-BY-NC 4.0 协议](https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/LICENSE) 开源,它将无差别收集整理相关的**主站业务接口**。
该项目使用 [MarkDown](https://zh.wikipedia.org/zh-cn/Markdown) 语法进行文档书写,按照业务类型及功能以 **路径** + **文件** 形式索引,任何用户都可通过 Pull Request 提供自己分析出的接口地址与使用说明。
本项目收集的接口类型包括但不限于 REST API、gRPC、WebSocket文档内统一优先使用安全套接字协议如`https`、`securityRpc`、`wss`。
## Issue与社群讨论
对文档内容存在**不理解**之处、以及发现文档内容有所**缺失**或**错误**,可直接提出,强烈建议以发 **Issue** 的形式参与用户反馈,并希望关于本项目的各种交流都是**公开进行**的,因为这样才可以保证关键信息的一致性。
由于本项目属于文档型项目,故不设置 Issue 模板,同时允许中英文标题,但提交 Issue 请遵守以下原则:
1. 标题言简意骇,说明欲提出的问题要点,如`如何通过xx接口获取yy`、`xx接口地址已失效`、`关于xx字段意义的探讨`、` 建议将xx加入yy分类`等标题;切勿使用表意含糊不清或索取性的标题,如`怎么解决风控`、`补充`、`搜索的接口是什么`、`好兄弟有没有投稿的接口`等标题
2. Issue 正文应对问题进行尽可能详细的描述,展开并聚焦有关的信息,例如:“在前端页面某地址 / APP 某界面会访问某 API标明地址它的某参数与文档中不符标明文档地址
3. 提出问题时注意 [提问的智慧](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md) 并且 [别像弱智一样提问](https://github.com/tangx/Stop-Ask-Questions-The-Stupid-Ways)
同时,您还可以通过加入社群的方式参与讨论
- QQ 交流群:[邀请链接](https://jq.qq.com/?_wv=1027&k=s1M0LCcu)
- Telegram 交流群:[@bilibili_API_collect_community](https://t.me/bilibili_API_collect_community)
::: tip ✅提示
QQ 交流群为综合技术交流群(兼 Owner 的粉丝群),可交流探讨任何技术,包括但不限于 [BAC 项目](https://github.com/SocialSisterYi/bilibili-API-collect)
Telegram 交流群主要用作 [BAC 项目](https://github.com/SocialSisterYi/bilibili-API-collect) 的 Github Bot 接收,也可以进行项目相关的讨论,但不建议在此讨论交流其他内容(公开群)
:::
::: warning ⚠️注意
群内讨论同样需要遵守**公开交流**的原则,以及群内会定期清理不活跃成员。
**QQ 交流群** 的加群问题答案可以去 [Owner 的主页](https://github.com/SocialSisterYi) Contact 部分找到,如果您填写“我不知道,从 Github 来的“那么管理员将有理由禁止您进群讨论!
:::
::: danger 🈲禁止
项目 Issue 及其相关社群中 **禁止** 询问讨论 风控解除、爬虫(采集)、破解、漏洞利用、买卖代码和账号 相关内容,抵制基于本项目进行的一切黑产行为!
:::
## 目录与路径结构
### 目录
@ -214,22 +251,3 @@ message Author {
## 文档提交
TODO
## Issue与社群讨论
对文档内容存在**不理解**之处、以及发现文档内容有所**缺失**或**错误**,可直接提出,强烈建议以发 **Issue** 的形式参与用户反馈,并希望关于本项目的各种交流都是**公开进行**的,因为这样才可以保证关键信息的一致性。
由于本项目属于文档型项目,故不设置 Issue 模板,同时允许中英文标题,但提交 Issue 请遵守以下原则:
1. 标题言简意骇,说明欲提出的问题要点,如`如何通过xx接口获取yy`、`xx接口地址已失效`、`关于xx字段意义的探讨`、` 建议将xx加入yy分类`等标题;切勿使用表意含糊不清或索取性的标题,如`怎么解决风控`、`补充`、`搜索的接口是什么`、`好兄弟有没有投稿的接口`等标题
2. Issue 正文应对问题进行尽可能详细的描述,展开并聚焦有关的信息,例如:“在前端页面某地址 / APP 某界面会访问某 API标明地址它的某参数与文档中不符标明文档地址
3. 提出问题时注意 [提问的智慧](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md) 并且 [别像弱智一样提问](https://github.com/tangx/Stop-Ask-Questions-The-Stupid-Ways)
同时,你还可以通过加入社群的方式参与讨论(包括但不限于本项目
- QQ 交流群:[邀请链接](https://jq.qq.com/?_wv=1027&k=s1M0LCcu)
- Telegram 交流群:[@bilibili_API_collect_community](https://t.me/bilibili_API_collect_community)
注意:群内讨论同样需要遵守**公开交流**的原则,以及群内会定期清理不活跃成员

342
README.md
View File

@ -2,7 +2,7 @@
<img src="./assets/img/logo.png" width="250" height="200">
</p>
<h1 align="center">哔哩哔哩-API收集整理</h1>
<p align="center">
<p align="center" class="shields">
<a href="https://github.com/SocialSisterYi/bilibili-API-collect/issues" style="text-decoration:none">
<img src="https://img.shields.io/github/issues/SocialSisterYi/bilibili-API-collect.svg" alt="GitHub issues"/>
</a>
@ -19,6 +19,11 @@
<img src="https://img.shields.io/badge/License-CC%20BY--NC%204.0-lightgrey.svg" alt="GitHub license"/>
</a>
</p>
<p align="center" class="trendshift">
<a href="https://trendshift.io/repositories/3218" target="_blank">
<img src="https://trendshift.io/api/badge/repositories/3218" alt="SocialSisterYi%2Fbilibili-API-collect | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/>
</a>
</p>
<h3 align="center">野生API文档</h3>
<h3 align="center">不断更新中....</h3>
@ -56,117 +61,131 @@ B站 API 采用 C/S 结构,大多数接口为 REST API 和 gRPC少部分接
## 🍴目录
计划整理分类 & 目录:(文档已完结请选中 checkbox)
计划整理分类 & 目录:(文档已完结请选中 checkbox)
- [x] [API 签名](docs/other/API_sign.md)
- [x] [公共错误码](docs/other/errcode.md)
- [x] [图片格式化](docs/other/picture.md)
- [x] [bvid 说明](docs/other/bvid_desc.md)
- [ ] [接口签名与验证](docs/misc/sign)
- [x] [APP API 签名](docs/misc/sign/APP.md)`appkey`与`sign`
- [x] [已知的 APPKey](docs/misc/sign/APPKey.md)
- [x] [Wbi 签名](docs/misc/sign/wbi.md)`wts`与`w_rid`
- [x] [公共错误码](docs/misc/errcode.md)
- [x] [图片格式化](docs/misc/picture.md)
- [x] [bvid 说明](docs/misc/bvid_desc.md)
- [ ] [设备唯一标识BUVID](docs/misc/device_identity.md)
- [ ] [gRPC API 接口定义](grpc_api)
- [ ] [登录](docs/login)
- [x] [登录操作 (人机认证)](docs/login/login_action)
- [x] [短信登录](docs/login/login_action/SMS.md)
- [x] [密码登录](docs/login/login_action/password.md)
- [x] [二维码登录](docs/login/login_action/QR.md)
- [ ] SNS 登录 (QQ & 微信 & 微博)
- [x] [登录基本信息](docs/login/login_info.md)
- [ ] [个人中心](docs/login/member_center.md)
- [ ] [注销登录](docs/login/exit.md)
- [x] [登录记录](docs/login/login_notice.md)
- [x] [登录操作 (人机认证)](docs/login/login_action)
- [x] [短信登录](docs/login/login_action/SMS.md)
- [x] [密码登录](docs/login/login_action/password.md)
- [x] [二维码登录](docs/login/login_action/QR.md)
- [ ] SNS 登录 (QQ & 微信 & 微博)
- [x] [登录基本信息](docs/login/login_info.md)
- [ ] [个人中心](docs/login/member_center.md)
- [ ] [注销登录](docs/login/exit.md)
- [x] [登录记录](docs/login/login_notice.md)
- [x] [Web 端 Cookie 刷新](docs/login/cookie_refresh.md)
- [ ] [消息中心](docs/message)
- [ ] [通知类消息](docs/message/msg.md)
- [ ] [私信](docs/message/private_msg.md)
- [ ] 设置
- [ ] [通知类消息](docs/message/msg.md)
- [ ] [私信](docs/message/private_msg.md)
- [ ] 设置
- [ ] [用户](docs/user)
- [x] [基本信息](docs/user/info.md)
- [x] [状态数](docs/user/status_number.md)
- [x] [关系](docs/user/relation.md)
- [ ] [个人空间](docs/user/space.md)
- [x] [检查昵称是否可注册](docs/user/check_nickname.md)
- [x] [用户注册](docs/user/register.md)
- [x] [基本信息](docs/user/info.md)
- [x] [状态数](docs/user/status_number.md)
- [x] [关系](docs/user/relation.md)
- [ ] [个人空间](docs/user/space.md)
- [x] [检查昵称是否可注册](docs/user/check_nickname.md)
- [x] [用户注册](docs/user/register.md)
- [x] [用户认证类型一览](docs/user/official_role.md)
- [ ] [加入老粉计划](docs/user/contract.md)
- [ ] [大会员](docs/vip)
- [ ] [大会员基本信息](docs/vip/info.md)
- [ ] [大会员中心](docs/vip/center.md)
- [ ] [大会员签到](docs/vip/clockin.md)
- [ ] [大会员操作](docs/vip/action.md)
- [ ] [大会员基本信息](docs/vip/info.md)
- [ ] [大会员中心](docs/vip/center.md)
- [ ] [大会员签到](docs/vip/clockin.md)
- [ ] [大会员操作](docs/vip/action.md)
- [ ] [视频](docs/video)
- [x] [视频分区一览 (分区代码)](docs/video/video_zone.md)
- [x] [基本信息](docs/video/info.md)
- [x] [状态数](docs/video/status_number.md)
- [x] [快照](docs/video/snapshot.md)
- [x] [点赞 & 投币 & 收藏 & 分享](docs/video/action.md)
- [ ] [TAG](docs/video/tags.md)
- [x] [视频推荐](docs/video/recommend.md)
- [x] [播放&下载地址 (视频流)](docs/video/videostream_url.md)
- [ ] [互动视频](docs/video/interact_video.md)
- [x] [高能进度条](docs/video/pbp.md)
- [ ] [信息上报 (心跳及记录历史)](docs/video/report.md)
- [x] [视频属性数据](docs/video/attribute_data.md)
- [x] [视频在线人数](docs/video/online.md)
- [x] [视频分区一览 (分区代码)](docs/video/video_zone.md)
- [x] [基本信息](docs/video/info.md)
- [x] [状态数](docs/video/status_number.md)
- [x] [快照](docs/video/snapshot.md)
- [x] [点赞 & 投币 & 收藏 & 分享](docs/video/action.md)
- [ ] [TAG](docs/video/tags.md)
- [x] [视频推荐](docs/video/recommend.md)
- [x] [播放&下载地址 (视频流)](docs/video/videostream_url.md)
- [ ] [互动视频](docs/video/interact_video.md)
- [x] [高能进度条](docs/video/pbp.md)
- [ ] [信息上报 (心跳及记录历史)](docs/video/report.md)
- [x] [视频属性数据](docs/video/attribute_data.md)
- [x] [视频在线人数](docs/video/online.md)
- [x] [视频AI摘要](docs/video/summary.md)
- [ ] [稿件投诉](docs/video/appeal.md)
- [ ] [视频状态数](docs/video/status_number.md)
- [ ] [视频合集](docs/video/collection.md)
- [ ] [剧集 (番剧、影视)](docs/bangumi)
- [ ] [基本信息](docs/bangumi/info.md)
- [ ] [播放&下载地址(视频流)](docs/bangumi/videostream_url.md)
- [ ] [时间轴](docs/bangumi/timeline.md)
- [ ] 状态数
- [ ] 操作
- [ ] [基本信息](docs/bangumi/info.md)
- [ ] [播放&下载地址(视频流)](docs/bangumi/videostream_url.md)
- [ ] [时间轴](docs/bangumi/timeline.md)
- [ ] [追番相关](docs/bangumi/follow.md)
- [ ] 状态数
- [ ] 操作
- [ ] [视频弹幕](docs/danmaku)
- [x] [protobuf 实时弹幕](docs/danmaku/danmaku_proto.md)
- [x] [protobuf 弹幕元数据BAS 弹幕 / 互动弹幕)](docs/danmaku/danmaku_view_proto.md)
- [x] [xml 实时弹幕](docs/danmaku/danmaku_xml.md)
- [x] [历史弹幕](docs/danmaku/history.md)
- [x] [快照](docs/danmaku/snapshot.md)
- [ ] [弹幕操作](docs/danmaku/action.md)
- [ ] 高级弹幕
- [ ] 屏蔽管理
- [ ] 智能防挡弹幕
- [x] [弹幕个人配置修改](docs/danmaku/config.md)
- [x] [名词解释](docs/danmaku/buzzword.md)
- [x] [protobuf 实时弹幕](docs/danmaku/danmaku_proto.md)
- [x] [protobuf 弹幕元数据BAS 弹幕 / 互动弹幕)](docs/danmaku/danmaku_view_proto.md)
- [x] [xml 实时弹幕](docs/danmaku/danmaku_xml.md)
- [x] [历史弹幕](docs/danmaku/history.md)
- [x] [快照](docs/danmaku/snapshot.md)
- [ ] [弹幕操作](docs/danmaku/action.md)
- [ ] 高级弹幕
- [ ] 屏蔽管理
- [ ] 智能防挡弹幕
- [x] [弹幕个人配置修改](docs/danmaku/config.md)
- [x] [名词解释](docs/danmaku/buzzword.md)
- [x] [点赞查询](docs/danmaku/thumbup.md)
- [x] [视频笔记](docs/note)
- [x] [笔记列表](docs/note/list.md)
- [x] [笔记详细信息](docs/note/info.md)
- [x] [笔记操作](docs/note/action.md)
- [x] [笔记列表](docs/note/list.md)
- [x] [笔记详细信息](docs/note/info.md)
- [x] [笔记操作](docs/note/action.md)
- [ ] [专栏](docs/article)
- [ ] 分区
- [X] [基本信息](docs/article/info.md)
- [X] [点赞 & 投币 & 收藏 & 分享](docs/article/action.md)
- [X] [文集基本信息](docs/article/articles.md)
- [X] [获取用户专栏文章列表](docs/article/list.md)
- [ ] [专栏分类](docs/article/category.md)
- [X] [基本信息](docs/article/info.md)
- [X] [点赞 & 投币 & 收藏 & 分享](docs/article/action.md)
- [X] [文集基本信息](docs/article/articles.md)
- [X] [获取用户专栏文章列表](docs/article/list.md)
- [ ] [音频](docs/audio)
- [x] [歌曲基本信息](docs/audio/info.md)
- [ ] [歌单 & 音频收藏夹详细信息](docs/audio/music_list.md)
- [ ] [状态数](docs/audio/status_number.md)
- [ ] [投币 & 收藏](docs/audio/action.md)
- [x] [播放 & 下载地址(音频流)](docs/audio/musicstream_url.md)
- [ ] 音频榜单
- [x] [歌曲基本信息](docs/audio/info.md)
- [ ] [歌单 & 音频收藏夹详细信息](docs/audio/music_list.md)
- [ ] [状态数](docs/audio/status_number.md)
- [ ] [投币 & 收藏](docs/audio/action.md)
- [x] [播放 & 下载地址(音频流)](docs/audio/musicstream_url.md)
- [x] [音频榜单](docs/audio/rank.md)
- [ ] [排行榜 & 最新视频](docs/video_ranking)
- [ ] [排行榜](docs/video_ranking/ranking.md)
- [ ] [热门视频](docs/video_ranking/popular.md)
- [ ] [最新视频](docs/video_ranking/dynamic.md)
- [x] [入站必刷视频](docs/video_ranking/precious_videos.md)
- [ ] [排行榜](docs/video_ranking/ranking.md)
- [ ] [热门视频](docs/video_ranking/popular.md)
- [ ] [最新视频](docs/video_ranking/dynamic.md)
- [x] [入站必刷视频](docs/video_ranking/precious_videos.md)
- [ ] [搜索](docs/search)
- [x] [搜索请求](docs/search/search_request.md)
- [x] [搜索结果](docs/search/search_response.md)
- [x] [默认搜索 & 热搜](docs/search/hot.md)
- [x] [搜索建议](docs/search/suggest.md)
- [x] [搜索请求](docs/search/search_request.md)
- [x] [搜索结果](docs/search/search_response.md)
- [x] [默认搜索 & 热搜](docs/search/hot.md)
- [x] [搜索建议](docs/search/suggest.md)
- [ ] [小黑屋](docs/blackroom)
- [ ] 基本信息
- [x] [封禁公示](docs/blackroom/banlist.md)
- [x] [风纪委员及众裁案件相关](docs/blackroom/jury)
- [x] [风纪委员基本信息](docs/blackroom/jury/base_info.md)
- [x] [众裁案件基本信息](docs/blackroom/jury/judgement_info.md)
- [x] [裁决操作](docs/blackroom/jury/action.md)
- [ ] 基本信息
- [x] [封禁公示](docs/blackroom/banlist.md)
- [x] [风纪委员及众裁案件相关](docs/blackroom/jury)
- [x] [风纪委员基本信息](docs/blackroom/jury/base_info.md)
- [x] [众裁案件基本信息](docs/blackroom/jury/judgement_info.md)
- [x] [裁决操作](docs/blackroom/jury/action.md)
- [x] [评论区](docs/comment)
- [x] [评论区明细](docs/comment/list.md)
- [x] [操作](docs/comment/action.md)
- [x] [评论区明细](docs/comment/list.md)
- [x] [操作](docs/comment/action.md)
- [ ] [表情](docs/emoji)
- [x] [表情及表情包信息](docs/emoji/list.md)
- [x] [操作](docs/emoji/action.md)
- [x] [表情及表情包信息](docs/emoji/list.md)
- [x] [操作](docs/emoji/action.md)
- [ ] [创作中心](docs/creativecenter)
- [ ] [统计与数据](docs/creativecenter/statistics&data.md)
- [ ] 列表查询相关
- [x] [电磁力数据](docs/creativecenter/railgun.md)
- [ ] [统计与数据](docs/creativecenter/statistics&data.md)
- [ ] 列表查询相关
- [x] [电磁力数据](docs/creativecenter/railgun.md)
- [x] [实时广播(通讯协议)](docs/broadcast)
- [x] [视频内广播](docs/broadcast/video_room.md)
- [x] [视频内广播](docs/broadcast/video_room.md)
- [ ] [充电](docs/electric)
- [ ] [包月充电](docs/electric/monthly.md)
- [ ] 自定义充电
@ -175,73 +194,85 @@ B站 API 采用 C/S 结构,大多数接口为 REST API 和 gRPC少部分接
- [x] [充电留言](docs/electric/charge_msg.md)
- [x] [充电列表](docs/electric/charge_list.md)
- [ ] [动态](docs/dynamic)
- [ ] [动态基本信息](docs/dynamic/basicInfo.md)
- [ ] [发送 & 转载动态](docs/dynamic/publish.md)
- [ ] [根据关键字搜索用户at 别人时的填充列表)](docs/dynamic/atlist.md)
- [ ] [操作](docs/dynamic/action.md)
- [ ] 动态列表
- [x] [特定话题动态列表](docs/dynamic/tag_dynamics.md)
- [ ] [动态内容](docs/dynamic/get_dynamic_detail.md)
- [ ] [获取动态列表](docs/dynamic/all.md)
- [ ] [获取用户空间动态](docs/dynamic/space.md)
- [ ] [动态基本信息](docs/dynamic/basicInfo.md)
- [ ] [动态详细信息字段](docs/dynamic/card_info.md)
- [ ] [获取动态详情](docs/dynamic/detail.md)
- [ ] [动态类型](docs/dynamic/dynamic_enum.md)
- [ ] [动态信息](docs/dynamic/content.md)
- [ ] [发送 & 转载动态](docs/dynamic/publish.md)
- [ ] [根据关键字搜索用户at 别人时的填充列表)](docs/dynamic/atlist.md)
- [ ] [操作](docs/dynamic/action.md)
- [ ] 动态列表
- [x] [特定话题动态列表](docs/dynamic/tag_dynamics.md)
- [ ] [动态内容](docs/dynamic/get_dynamic_detail.md)
- [ ] [相簿](docs/album)
- [x] [基本信息](docs/album/info.md)
- [x] [相簿列表](docs/album/list.md)
- [x] [推荐作者](docs/album/recommend_author.md)
- [x] [活动列表](docs/album/activity_list.md)
- [x] [操作](docs/album/action.md)
- [ ] 投稿
- [x] [基本信息](docs/album/info.md)
- [x] [相簿列表](docs/album/list.md)
- [x] [推荐作者](docs/album/recommend_author.md)
- [x] [活动列表](docs/album/activity_list.md)
- [x] [操作](docs/album/action.md)
- [ ] 投稿
- [ ] [历史记录 & 稍后再看](docs/history&toview)
- [x] [历史记录](docs/history&toview/history.md)
- [x] [稍后再看](docs/history&toview/toview.md)
- [x] [历史记录](docs/history&toview/history.md)
- [x] [稍后再看](docs/history&toview/toview.md)
- [ ] [收藏夹](docs/fav)
- [x] [基本信息](docs/fav/info.md)
- [x] [收藏夹内容](docs/fav/list.md)
- [ ] [收藏夹操作](docs/fav/action.md)
- [x] [基本信息](docs/fav/info.md)
- [x] [收藏夹内容](docs/fav/list.md)
- [ ] [收藏夹操作](docs/fav/action.md)
- [ ] [课程](docs/cheese)
- [x] [课程基本信息](docs/cheese/info.md)
- [ ] 已购课程
- [ ] 分区推荐列表
- [ ] 操作
- [x] [播放 & 下载地址(视频流)](docs/cheese/videostream_url.md)
- [x] [课程基本信息](docs/cheese/info.md)
- [ ] 已购课程
- [ ] 分区推荐列表
- [ ] 操作
- [x] [播放 & 下载地址(视频流)](docs/cheese/videostream_url.md)
- [ ] [直播](docs/live)
- [ ] [直播间基本信息](docs/live/info.md)
- [ ] [直播分区](docs/live/live_area.md)
- [ ] [直播间管理](docs/live/manage.md)
- [ ] 直播间操作
- [ ] [直播视频流](docs/live/live_stream.md)
- [ ] [直播信息流](docs/live/message_stream.md)
- [ ] [直播红包](docs/live/redpocket.md)
- [ ] [直播间用户实用 API](docs/live/user.md)
- [ ] [直播间基本信息](docs/live/info.md)
- [ ] [直播分区](docs/live/live_area.md)
- [ ] [直播间管理](docs/live/manage.md)
- [ ] 直播间操作
- [ ] [直播视频流](docs/live/live_stream.md)
- [ ] [直播信息流](docs/live/message_stream.md)
- [ ] [直播红包](docs/live/redpocket.md)
- [ ] [直播间用户实用 API](docs/live/user.md)
- [x] [直播间禁言相关](docs/live/silent_user_manage.md)
- [ ] [转正答题](docs/newbie_exam)
- [x] [查询信息](docs/newbie_exam/info.md)
- [x] [拉取题目](docs/newbie_exam/fetch.md)
- [x] [操作](docs/newbie_exam/action.md)
- [x] [查询信息](docs/newbie_exam/info.md)
- [x] [拉取题目](docs/newbie_exam/fetch.md)
- [x] [操作](docs/newbie_exam/action.md)
- [ ] [青少年守护](docs/teenager/)
- [x] [青少年模式](docs/teenager/teenager_mode.md)
- [ ] 亲子平台
- [ ] 课堂模式
- [ ] B币钱包
- [ ] 基本信息
- [ ] B币充值
- [ ] 贝壳相关
- [ ] 基本信息
- [ ] B币充值
- [ ] 贝壳相关
- [ ] [哔哩哔哩漫画](docs/manga)
- [ ] [用户信息](docs/manga/user.md)
- [x] [签到](docs/manga/ClockIn.md)
- [x] [积分商城](docs/manga/point_shop.md)
- [x] [漫画操作](docs/manga/Comic.md)
- [x] [漫画赛季](docs/manga/Season.md)
- [x] [漫读券/已购相关](docs/manga/User.md)
- [x] [下载](docs/manga/Download.md)
- [x] [data.index解析](docs/manga/index_file.md)
- [ ] 用户信息
- [x] [签到](docs/manga/ClockIn.md)
- [x] [积分商城](docs/manga/point_shop.md)
- [x] [漫画操作](docs/manga/Comic.md)
- [ ] [漫画任务操作](docs/manga/Activity.md)
- [x] [漫画赛季](docs/manga/Season.md)
- [x] [漫读券/已购相关](docs/manga/User.md)
- [x] [下载](docs/manga/Download.md)
- [x] [data.index解析](docs/manga/index_file.md)
- [ ] [获取轻享卡信息](docs/manga/light_card.md)
- [ ] 哔哩哔哩游戏
- [ ] [终端网络查询](docs/clientinfo)
- [x] [基于ip的地理位置查询](docs/clientinfo/ip.md)
- [x] [终端信息查询](docs/clientinfo/client_info.md)
- [ ] [其他](docs/other)
- [x] [获取当前时间戳](docs/other/time_stamp.md)
- [x] [基于 ip 的地理位置查询](docs/clientinfo/ip.md)
- [ ] [其他](docs/misc)
- [x] [获取当前时间戳](docs/misc/time_stamp.md)
- [ ] [web端组件](docs/web_widget)
- [x] [分区当日投稿数](docs/web_widget/zone_upload.md)
- [x] [404 页漫画收集](docs/web_widget/404_manga.md)
- [x] [分区当日投稿数](docs/web_widget/zone_upload.md)
- [x] [404 页漫画收集](docs/web_widget/404_manga.md)
- [ ] [APP端组件](docs/APP_widget)
- [x] [开屏图片 + 恰饭珍贵录像](docs/APP_widget/splash.md)
- [x] [开屏图片 + 恰饭珍贵录像](docs/APP_widget/splash.md)
- [ ] [个性装扮](docs/garb)
- [x] [APP 主题](docs/garb/skin.md)
- [x] [主题色](docs/garb/color.md)
- [x] [APP 主题](docs/garb/skin.md)
- [x] [主题色](docs/garb/color.md)
## ✨鸣谢
@ -265,7 +296,7 @@ protobuf 序列格式:[传送门](https://www.jianshu.com/p/a24c88c0526a )
⚠注意:开源社群欢迎交流探讨,**拒绝**咨询、**不支持**合作,**黑产号**一经发现立即拉黑并举报相关 SRC
- QQ 交流群:[邀请链接](https://jq.qq.com/?_wv=1027&k=s1M0LCcu)
- QQ 交流群:[邀请链接](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=2rRJXK3zgU5yi3e_4rNLeJYUjMLzw_Jj&authKey=L%2FN3EfZXo3QFjEuHq4ifTgh%2F384UmrYpjl7dbYPhYHtznhfJWxkymxQKObQunmEQ&noverify=0&group_code=560304737)
- Telegram 交流群:[@bilibili_API_collect_community](https://t.me/bilibili_API_collect_community)
## 🧋发电
@ -313,14 +344,14 @@ OR Aifadian[https://afdian.net/@ShakaiAneE](https://afdian.net/@ShakaiAneE)
- [ironmanic/crawler_target_users_good](https://github.com/ironmanic/crawler_target_users_good):搜索bilibili特定视频为评论 点赞,关注,私信,一体化服务
- [dd-center/DDatElectron](https://github.com/dd-center/DDatElectron):DD@Home 分布式项目, 桌面客户端
- [dd-center/vtbs.moe](https://github.com/dd-center/vtbs.moe):B站VTB数据中心
- [JunzhouLiu/BILIBILI-HELPER](https://github.com/JunzhouLiu/BILIBILI-HELPER):利用Linux Crontab定时任务,云函数Docker等方式实现B站哔哩哔哩Bilibili每日自动投币签到银瓜子兑换硬币领取大会员福利大会员月底给自己充电等。每天轻松获取65经验值。
- [catlair/BiliOutils](https://github.com/catlair/BiliOutils):利用Docker青龙面板以及各种云函数等实现 B 站每日自动投币,会员大积分,漫画阅读和抢兑领取大会员福利大会员月底给自己充电等。每天轻松获取65经验值。
- [the1812/Bilibili-Evolved](https://github.com/the1812/Bilibili-Evolved):强大的哔哩哔哩增强脚本: 下载视频, 音乐, 封面, 弹幕 / 简化直播间, 评论区, 首页 / 自定义顶栏, 删除广告, 夜间模式 / 触屏设备支持
- [xlzy520/bili-short-url](https://github.com/xlzy520/bili-short-url): 哔哩哔哩短链生成器
- [zjkwdy/bili_app_splash](https://github.com/zjkwdy/bili_app_splash): B站壁纸娘和开屏图自动下载每天使用Actions自动同步
- [Jannchie/BiliOB](https://github.com/Jannchie/BiliOB): BiliOB观测者是一个观测B站UP主及视频数据变化并予以分析的Web应用程序
- [biliob233/biliob233.github.io](https://github.com/biliob233/biliob233.github.io): ~~无可奉告~~
- [biliup/biliup](https://github.com/biliup/biliup): 全自动录播、投稿工具也支持twitch、ytb频道搬运。提供分p上传b站接口腾讯云内网免流+大幅提速
- [ddiu8081/bilicli](https://github.com/ddiu8081/bilicli): Bilibili-live danmu dashboard in your terminal.
- [ddiu8081/bilicli](https://github.com/ddiu8081/bilicli): Bilibili-live danmu dashboard in your terminal.
- [MotooriKashin/Bilibili-Old](https://github.com/MotooriKashin/Bilibili-Old): 恢复旧版Bilibili页面为了那些念旧的人。
- [SocialSisterYi/bcut-asr](https://github.com/SocialSisterYi/bcut-asr): 使用必剪API的语音字幕识别
- [CzJam/Bili_Realtime_Data](https://github.com/CzJam/Bili_Realtime_Data): Bilibili粉丝与视频实时数据统计
@ -331,6 +362,13 @@ OR Aifadian[https://afdian.net/@ShakaiAneE](https://afdian.net/@ShakaiAneE)
- [uw-labs/bloomrpc](https://github.com/uw-labs/bloomrpc): GUI Client for GRPC Services
- [grpc/grpc](https://github.com/grpc/grpc): The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)
- [grpc/grpc](https://github.com/grpc/grpc): The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)
- [quicktype](https://github.com/quicktype/quicktype) quicktype generates strongly-typed models and serializers from JSON, JSON Schema, TypeScript, and GraphQL queries, making it a breeze to work with JSON type-safely in many programming languages.一键生成多种语言的json反序列化所需类,以便于快速反序列化, 有网页版
- [quicktype](https://github.com/quicktype/quicktype) quicktype generates strongly-typed models and serializers from JSON, JSON Schema, TypeScript, and GraphQL queries, making it a breeze to work with JSON type-safely in many programming languages.一键生成多种语言的json反序列化所需类,以便于快速反序列化,
有网页版
<style scoped>
.shields a {
margin: auto .5em;
}
</style>

1
assets/img/aiSummary.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -2,12 +2,16 @@
## 获取用户专栏文章列表
> https://api.bilibili.com/x/space/article
> https://api.bilibili.com/x/space/wbi/article
> ~~https://api.bilibili.com/x/space/article~~(旧链接)
*请求方式GET*
认证方式CookieSESSDATA
鉴权方式:[Wbi 签名](../misc/sign/wbi.md)
**url参数**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |

1160
docs/audio/rank.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -251,16 +251,27 @@ curl -G 'https://api.bilibili.com/pgc/review/user' \
`result`中的`payment`对象:
| 字段 | 类型 | 内容 | 备注 |
| ------------------- | ---- | ---- | ---- |
| discount | num | | |
| pay_type | obj | | |
| price | str | | |
| promotion | str | | |
| tip | str | | |
| vip_discount | num | | |
| vip_first_promotion | str | | |
| vip_promotion | str | | |
| 字段 | 类型 | 内容 | 备注 |
| ------------------- | ---- | ------------ | -------- |
| discount | num | 折扣 | 100为原价 |
| pay_type | obj | 支付相关 | |
| price | str | 售价 | |
| promotion | str | 推广信息 | |
| vip_discount | num | 大会员折扣 | |
| vip_first_promotion | str | | |
| vip_price | str | 大会员售价 | |
| vip_promotion | str | 大会员推广信息 | |
`payment`中的`pay_type`对象:
| 字段 | 类型 | 内容 | 备注 |
| ------------------- | ---- | ------------- | ------------------------- |
| allow_discount | num | 启用折扣 | 0<br />1<br />下同 |
| allow_pack | num | | |
| allow_ticket | num | 启用票券 | |
| allow_time_limit | num | 启用时间限制 | |
| allow_vip_discount | num | 启用大会员折扣 | |
| forbid_bb | num | 禁止使用B币券 | |
`result`中的`positive`对象:
@ -1019,4 +1030,4 @@ curl -L -X GET 'https://api.bilibili.com/pgc/web/season/section?season_id=42290'
}
```
</details>
</details>

View File

@ -58,7 +58,7 @@
## 查询投票过的单个案件
## 获取单个案件信息
> https://api.bilibili.com/x/credit/v2/jury/case/info
@ -82,51 +82,53 @@
| 字段 | 类型 | 内容 | 备注 |
| ------- | ------ | -------- | ------------ |
| code | num | 返回值 | 0成功<br />-101账号未登录<br />-400请求错误 |
| message | str | 信息 | 默认为0 |
| message | str | 信息 | 默认为 0 |
| ttl | num | 1 | |
| data | object | 数据本体 | |
`data` 对象:
| 字段 | 类型 | 内容 | 备注 |
| --------- | ------ | -------- | ------------ |
| case_id | str | 案件id | |
| case_type | num | 任务类型 | 1单条评论<br />2评论氛围<br />3单条弹幕<br />4弹幕氛围 |
| jury_state | num | `1` | 改版后未见过其它值 |
| participate | num | 是否投票 | 0未投票<br />1已投票 |
| vote_items | object | 投票选项 | 见开头「投票选项码总览」 |
| default_vote | num | 默认投票选项 | `4`或`14`即`无法判断` |
| status | num | 裁决状态(新版) | 0进行中<br />1已结束 |
| origin_start | num | 案件关联视频,播放进度条起始坐标 | 单位:`秒` |
| avid | num | 视频av号 | |
| cid | num | 弹幕 dmid | |
| vote_cd | num | `-1` | 暂不明确 |
| result | num | 众议结论 | 见开头「投票选项码总览」 |
| result_text | str | 众议结论文本 | |
| title | str | 视频标题 | |
| case_info | object | 案件信息 | |
| my_point | object | 我的观点 | |
| vote_info | object | 投票信息 | |
| 字段 | 类型 | 内容 | 备注 |
| ------------ | ------ | -------------------------------- | -------------------------------------------------------------- |
| case_id | str | 案件id | |
| case_type | num | 任务类型 | 1单条评论<br />2评论氛围<br />3单条弹幕<br />4弹幕氛围 |
| jury_state | num | `1` | 改版后未见过其它值 |
| participate | num | 是否投票 | 0未投票<br />1已投票 |
| vote_items | object | 投票选项 | 见开头「投票选项码总览」 |
| default_vote | num | 默认投票选项 | `4` `14` `无法判断` |
| status | num | 裁决状态(新版) | 0进行中<br />1已结束 |
| origin_start | num | 案件关联视频,播放进度条起始坐标 | 单位:`秒` |
| avid | num | 视频av号 | |
| cid | num | 弹幕 dmid | |
| vote_cd | num | `-1` | 暂不明确 |
| result | num | 众议结论 | 见开头「投票选项码总览」 |
| result_text | str | 众议结论文本 | 见开头「投票选项码总览」 |
| title | str | 视频标题 | |
| case_info | object | 案件信息 | |
| my_point | object | 我的观点 | 仅自己投过票才有该字段 |
| vote_info | object | 投票信息 | |
`data` 对象下的`case_info`对象
| 字段 | 类型 | 内容 | 备注 |
| ------------ | ------ | ------------ | ------------------------------------------------------------ |
| comment | object | 单条评论信息 | 仅当`case_type`为`1`有值。见「对象:评论信息」 |
| danmu_img | str | 弹幕截图 | 仅当`case_type`为`4`有值截图URL |
| comments | object | 若干条评论 | 仅当`case_type`为`2`有值。见「对象:评论信息」 |
| 字段 | 类型 | 内容 | 备注 |
| ------------ | ------ | ------------ | ----------------------------------------------- |
| comment | object | 单条评论信息 | 仅当`case_type`为`1`有值。见「对象:评论信息」 |
| danmu_img | str | 弹幕截图 | 仅当`case_type`为`4`有值截图URL |
| comments | object | 若干条评论 | 仅当`case_type`为`2`有值。见「对象:评论信息」 |
| single_danmu | str | 单条弹幕信息 | 仅当`case_type`为`3`有值。见「对象:评论信息)」 |
对象:评论信息
| 字段 | 类型 | 内容 | 备注 |
| ---- | ---- | ---- | ---- |
| mid | num | 用户uid | |
| uname | str | 用户名 | |
| face | str | 用户头像 | 头像URL |
| content | str | 评论内容 | |
| 字段 | 类型 | 内容 | 备注 |
| -------------- | ------ | ------------------------ | -------------------------------------------------------------- |
| mid | num | 用户uid | |
| uname | str | 用户名 | |
| face | str | 用户头像 | 头像URL |
| content | str | 评论内容 | |
| child_comments | object | 子评论(对该评论的回复) | 见「对象:评论信息」,单条评论和子评论下无`child_comments`字段 |
对象:弹幕信息
| 字段 | 类型 | 内容 | 备注 |
@ -137,7 +139,7 @@
`data` 对象下的`my_point`对象
记录了某个风纪委员的某个投票(观点)信息
记录了自己的投票(观点)信息,仅当自己投过票才有该字段。
| 字段 | 类型 | 内容 | 备注 |
| ----------- | ---- | ---------------- | ------------------------------------------------------------ |

View File

@ -1,91 +0,0 @@
# 终端信息查询
## 终端信息查询
> https://api.bilibili.com/client_info
*请求方式:任意*
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------- |
| code | num | 返回值 | 0成功 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
| data | obj | 信息本体 | |
`data`对象:
| 字段 | 类型 | 内容 | 备注 |
| -------- | -------- | ------------------- | ------------ |
| country | str | 国家/地区名 | |
| ip | str | 公网IP地址 | |
| province | str | 省/州 | 非必须存在项 |
| city | str | 城市 | 非必须存在项 |
| district | district | | |
| isp | str | 运营商名 | |
| dns | str | dns服务器ip | |
| dns_isp | str | dns服务器ip运营商名 | |
| headers | obj | 头部字段 | |
`data`中的`headers`对象:
| 字段 | 类型 | 内容 | 备注 |
| --------------------------------- | ---- | ----------------- | ---- |
| HTTP_ACCEPT_ENCODING | str | | |
| HTTP_X_CACHE_SERVER | str | CDN服务器名 | |
| HTTP_X_CACHE_SERVER_ADDR | str | CDN服务器ip | |
| HTTP_X_BACKEND_BILI_REAL_IP | str | 真实服务器ip | |
| HTTP_X_BACKEND_BILI_REAL_IPPORT | str | 真实服务器端口 | |
| HTTP_X_BACKEND_BILI_REAL_IP_CHAIN | str | 真实服务器ip+端口 | |
| HTTP_X_SCHEME | str | 访问协议 | |
| HTTP_HOST | str | 访问域名 | |
| HTTP_USER_AGENT | str | 客户端UA | |
| HTTP_ACCEPT | str | | |
| HTTP_CACHE_CONTROL | str | | |
**示例:**
```shell
curl 'https://api.bilibili.com/client_info'
```
<details>
<summary>查看响应示例:</summary>
```json
{
"code": 0,
"message": "ok",
"data": {
"country": "中国",
"ip": "36.40.120.140",
"province": "陕西",
"city": "渭南",
"district": null,
"isp": "电信",
"dns": null,
"dns_isp": null,
"headers": {
"HTTP_ACCEPT_ENCODING": "gzip",
"HTTP_X_CACHE_SERVER": "ks-bj-webcdn-07",
"HTTP_X_CACHE_SERVER_ADDR": "10.33.2.170",
"HTTP_X_BACKEND_BILI_REAL_IP": "36.40.120.140",
"HTTP_X_BACKEND_BILI_REAL_IPPORT": "22058",
"HTTP_X_BACKEND_BILI_REAL_IP_CHAIN": "36.40.120.140:22058",
"HTTP_X_SCHEME": "https",
"HTTP_HOST": "api.bilibili.com",
"HTTP_USER_AGENT": "PostmanRuntime/7.26.8",
"HTTP_ACCEPT": "*/*",
"HTTP_CACHE_CONTROL": "no-cache"
}
}
}
```
</details>

View File

@ -25,12 +25,12 @@
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------------------------------------------------------------ |
| code | num | 返回值 | 0成功<br />-101账号未登录<br />-102账号被封停<br />-111csrf校验失败<br />-400请求错误<br />-404无此项<br />-509请求过于频繁<br />12001已经存在评论主题<br />12002评论区已关闭<br />12003禁止回复<br />12006没有该评论<br />12009评论主体的type不合法<br />12015需要评论验证码<br />12016评论内容包含敏感信息<br />12025评论字数过多<br />12035该账号被UP主列入评论黑名单<br />12051重复评论请勿刷屏<br />12052评论区已关闭<br />**(其他错误码有待补充)** |
| message | str | 错误信息 | <br /> |
| ttl | num | 1 | |
| data | obj | 数据本体 | |
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| code | num | 返回值 | 0成功<br />-101账号未登录<br />-102账号被封停<br />-111csrf校验失败<br />-400请求错误<br />-404无此项<br />-509请求过于频繁<br />12001已经存在评论主题<br />12002评论区已关闭<br />12003禁止回复<br />12006没有该评论<br />12009评论主体的type不合法<br />12015需要评论验证码<br />12016评论内容包含敏感信息<br />12025评论字数过多<br />12035该账号被UP主列入评论黑名单<br />12051重复评论请勿刷屏<br />12052评论区已关闭<br />12045购买后即可发表评论<br/>**(其他错误码有待补充)** |
| message | str | 错误信息 | <br /> |
| ttl | num | 1 | |
| data | obj | 数据本体 | |
`data`对象:
@ -503,7 +503,7 @@ curl 'https://api.bilibili.com/x/v2/reply/top' \
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------------------------------------------------------------ |
| code | num | 返回值 | 0成功<br />-101账号未登录<br />-102账号被封停<br />-111csrf校验失败<br />-400请求错误<br />-403权限不足<br />-404无此项<br />-500服务器错误<br />-509请求过于频繁<br />12002评论区已关闭<br />12006没有该评论<br />12008已经举报过了<br />12009评论主体的type不合法<br />12019举报过于频繁<br />**(其他错误码有待补充)** |
| code | num | 返回值 | 0成功<br />-101账号未登录<br />-102账号被封停<br />-111csrf校验失败<br />-400请求错误<br />-403权限不足<br />-404无此项<br />-500服务器错误<br />-509请求过于频繁<br />12002评论区已关闭<br />12006没有该评论<br />12008已经举报过了<br />12009评论主体的type不合法<br />12019举报过于频繁<br />12077其他举报理由过长或过短<br />**(其他错误码有待补充)** |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |

View File

@ -17,7 +17,7 @@
| oid | num | 目标评论区 id | 必要 | |
| sort | num | 排序方式 | 非必要 | 默认为0<br />0按时间<br />1按点赞数<br />2按回复数 |
| nohot | num | 是否不显示热评 | 非必要 | 默认为0<br />1不显示<br />0显示 |
| ps | num | 每页项数 | 非必要 | 默认为20<br />定义域1-49 |
| ps | num | 每页项数 | 非必要 | 默认为20<br />定义域1-20 |
| pn | num | 页码 | 非必要 | 默认为1 |
**json回复**
@ -856,12 +856,16 @@ curl -G 'https://api.bilibili.com/x/v2/reply' \
## 获取评论区明细_懒加载
> https://api.bilibili.com/x/v2/reply/main
> https://api.bilibili.com/x/v2/reply/wbi/main
> ~~https://api.bilibili.com/x/v2/reply/main~~
*请求方式GET*
认证方式CookieSESSDATA或APP
鉴权方式:[Wbi 签名](../misc/sign/wbi.md)
**url参数**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |

View File

@ -228,6 +228,7 @@
| emote | obj | 需要渲染的表情转义 | 评论内容无表情则无此项 |
| jump_url | obj | 需要高亮的超链转义 | |
| max_line | num | 6 | 收起最大行数 |
| pictures | array | 评论图片数组 | |
`content`中的`members`数组:
@ -285,6 +286,15 @@
| appPackageName | str | (?) | |
| clickReport | str | 上报 id | |
`content`中的`pictures`数组中的对象:
| 字段 | 类型 | 内容 | 备注 |
| ---------- | ---- | -------- | -------- |
| img_src | str | 图片地址 | |
| img_width | num | 图片宽度 | |
| img_height | num | 图片高度 | |
| img_size | num | 图片大小 | 单位KB |
`评论条目`中的`replies`数组:
| 项 | 类型 | 内容 | 备注 |

View File

@ -4,7 +4,7 @@
## 获取电磁力等级web端
> https://member.bilibili.com/x/web/elec/user
> https://api.bilibili.com/studio/up-rating/v3/rating/info
*请求方式GET*
@ -26,8 +26,10 @@
| 字段 | 类型 | 内容 | 备注 |
| ------ | ---- | ----------- | ---------------- |
| mid | num | 当前用户mid | |
| state | num | 电磁力等级 | |
| reason | str | 空 | **作用尚不明确** |
| level | num | 电磁力等级 | |
| score | num | 电磁力分数 | |
| credit | num | 信用分 | |
| state | num | ? | 一直是2 |
**示例:**
@ -45,16 +47,19 @@ curl 'https://member.bilibili.com/x/web/elec/user' \
"message": "0",
"ttl": 1,
"data": {
"mid": 293793435,
"mid": ***,
"level": 4,
"score": 326,
"credit": 100,
"state": 2,
"reason": ""
"update_date": 1694966400
}
}
```
</details>
## 获取电磁力详细数值(双端)
## (失效)获取电磁力详细数值(双端)
> https://api.bilibili.com/studio/up-rating/rating/summary

View File

@ -156,7 +156,7 @@ curl 'https://member.bilibili.com/x/web/data/article' \
## 视频数据增量趋势
> https://member.bilibili.com/x/web/data/article/thirty
> https://member.bilibili.com/x/web/data/pandect
*请求方式GET*

View File

@ -14,21 +14,23 @@
**正文参数( application/x-www-form-urlencoded **
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ---------- | ---- | ------------------------ | -------------- | ------------------------------------------------------------ |
| access_key | str | APP登录Token | APP方式必要 | |
| type | num | 弹幕类选择 | 必要 | 1视频弹幕 |
| oid | num | 视频cid | 必要 | |
| msg | str | 弹幕内容 | 必要 | 长度小于100字符 |
| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 |
| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 |
| progress | num | 弹幕出现在视频内的时间 | 非必要 | 单位为毫秒<br />默认为0 |
| color | num | 弹幕颜色设置 | 非必要 | 十进制RGB888值<br />默认为16777215#FFFFFF白色 |
| fontsize | num | 弹幕字号设置 | 非必要 | 默认为25<br />极小12<br />超小16<br />18<br />标准25<br />36<br />超大45<br />极大64 |
| pool | num | 弹幕池选择 | 非必要 | 0普通池<br />1字幕池<br />2特殊池代码/BAS弹幕<br />默认为0 |
| mode | num | 弹幕类型选择 | 必要 | 1普通弹幕<br />4底部弹幕<br />5顶部弹幕<br />7高级弹幕<br />9BAS弹幕`pool`必须为2 |
| rnd | num | 当前时间戳*1000000 | 非必要 | **若无此项则发送弹幕冷却时间限制为90s**<br />若有此项则发送弹幕冷却时间限制为5s |
| csrf | str | CSRF Token位于cookie | Cookie方式必要 | |
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------------- | ---- | ------------------------- | --------------- | ------------------------------------------------------------ |
| access_key | str | APP 登录 Token | APP 方式必要 | |
| type | num | 弹幕类选择 | 必要 | 1视频弹幕<br />2漫画弹幕 |
| oid | num | 视频 cid | 必要 | |
| msg | str | 弹幕内容 | 必要 | 长度小于 100 字符 |
| bvid | str | 稿件 bvid | 必要(可选) | avid 与 bvid 任选一个 |
| aid | num | 稿件 avid | 必要(可选) | avid 与 bvid 任选一个 |
| progress | num | 弹幕出现在视频内的时间 | 非必要 | 单位为毫秒<br />默认为0 |
| color | num | 弹幕颜色设置 | 非必要 | 十进制 RGB888 值<br />如`16777215`为 #FFFFFF 即白色 |
| fontsize | num | 弹幕字号设置 | 非必要 | 默认为 25<br />极小12<br />超小16<br />18<br />标准25<br />36<br />超大45<br />极大64 |
| pool | num | 弹幕池选择 | 非必要 | 0普通池<br />1字幕池<br />2特殊池代码/BAS弹幕<br />默认为0 |
| mode | num | 弹幕类型选择 | 必要 | 1普通弹幕<br />4底部弹幕<br />5顶部弹幕<br />7高级弹幕<br />9BAS弹幕`pool`必须为2 |
| rnd | num | 当前时间戳*1000000 | 非必要 | **若无此项则发送弹幕冷却时间限制为90s**<br />若有此项则发送弹幕冷却时间限制为5s |
| colorful | num | 彩色弹幕 | 非必要 | 60001专属渐变彩色需要会员 |
| checkbox_type | num | 是否带 UP 身份标识 | 非必要 | 0普通<br />4带有标识 |
| csrf | str | CSRF Token位于 Cookie | Cookie 方式必要 | |
**json回复**
@ -36,38 +38,48 @@
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------------------------------------------------------------ |
| code | num | 返回值 | 0成功<br />-101账号未登录<br />-102账号被封停<br />-111csrf校验失败<br />-400请求错误<br />-404无此项<br />36700系统升级中<br />36701弹幕包含被禁止的内容<br />36702弹幕长度大于100<br />36703发送频率过快<br />36704禁止向未审核的视频发送弹幕<br />36705您的等级不足不能发送弹幕<br />36706您的等级不足不能发送顶端弹幕<br />36707您的等级不足不能发送底端弹幕<br />36708您的等级不足不能发送彩色弹幕<br />36709您的等级不足不能发送高级弹幕<br />36710您的权限不足不能发送这种样式的弹幕<br />36711该视频禁止发送弹幕<br />36712level 1用户发送弹幕的最大长度为20<br />36713稿件未付费<br />36714弹幕发送时间不合法<br />36715当日操作数量超过上限 |
| code | num | 返回值 | 0成功<br />-101账号未登录<br />-102账号被封停<br />-111csrf校验失败<br />-400请求错误<br />-404无此项<br />36700系统升级中<br />36701弹幕包含被禁止的内容<br />36702弹幕长度大于100<br />36703发送频率过快<br />36704禁止向未审核的视频发送弹幕<br />36705您的等级不足不能发送弹幕<br />36706您的等级不足不能发送顶端弹幕<br />36707您的等级不足不能发送底端弹幕<br />36708您的等级不足不能发送彩色弹幕<br />36709您的等级不足不能发送高级弹幕<br />36710您的权限不足不能发送这种样式的弹幕<br />36711该视频禁止发送弹幕<br />36712level 1用户发送弹幕的最大长度为20<br />36713稿件未付费<br />36714弹幕发送时间不合法<br />36715当日操作数量超过上限<br />36718目前您不是大会员无法使用会员权益 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
| data | obj | 信息本体 | |
`data`对象:
| 字段 | 类型 | 内容 | 备注 |
| -------- | ---- | -------- | ------------ |
| action | str | 空 | 作用尚不明确 |
| dmid | num | 弹幕dmid | |
| dmid_str | str | 弹幕dmid | 字串形式 |
| visible | bool | true | 作用尚不明确 |
| 字段 | 类型 | 内容 | 备注 |
| ------------ | ---------- | ------------------ | -------------------------------- |
| action | str | | |
| animation | str | 弹幕样式 Json | |
| colorful_src | str 或 obj | 渐变彩色样式信息? | 当请求参数`colorful=60001`时有效 |
| dm_content | str | | |
| dmid | num | 弹幕 dmid | |
| dmid_str | str | 弹幕 dmid | 字串形式 |
| visible | bool | | |
`data`中的`colorful_src`对象:
| 字段 | 类型 | 内容 | 备注 |
| ---- | ---- | ----------------- | ---- |
| type | num | 60001 | |
| src | str | 渐变色样式 Json | |
**示例:**
为视频`av2`/`BV1xx411c7mD`cid为`62131`的5000ms位置发送一条弹幕`前来考古`(颜色为#FFFFFF字号25普通弹幕游动弹幕
为视频`av2`/`BV1xx411c7mD`cid为`62131`)的 5000ms 位置发送一条弹幕`前来考古`(颜色为 #FFFFFF,字号 25普通弹幕游动弹幕
```shell
curl 'https://api.bilibili.com/x/v2/dm/post' \
--data-urlencode 'type=1' \
--data-urlencode 'oid=62131' \
--data-urlencode 'msg=前来考古' \
--data-urlencode 'aid=2' \
--data-urlencode 'progress=5000' \
--data-urlencode 'color=16777215' \
--data-urlencode 'fontsize=25' \
--data-urlencode 'pool=0' \
--data-urlencode 'mode=1' \
--data-urlencode 'rnd=3456789987654321' \
--data-urlencode 'csrf=xxx' \
-b 'SESSDATA=xxx'
--data-urlencode 'type=1' \
--data-urlencode 'oid=62131' \
--data-urlencode 'msg=前来考古' \
--data-urlencode 'aid=2' \
--data-urlencode 'progress=5000' \
--data-urlencode 'color=16777215' \
--data-urlencode 'fontsize=25' \
--data-urlencode 'pool=0' \
--data-urlencode 'mode=1' \
--data-urlencode 'rnd=3456789987654321' \
--data-urlencode 'csrf=xxx' \
-b 'SESSDATA=xxx'
```
<details>
@ -483,88 +495,6 @@ curl -G 'https://api.bilibili.com/x/dm/adv/state' \
</details>
## 查询弹幕点赞数
> https://api.bilibili.com/x/v2/dm/thumbup/stats
*请求方式GET*
认证方式CookieSESSDATA或APP
**url参数**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ---------- | ---- | ------------ | ----------- | ------------------- |
| access_key | str | APP登录Token | APP方式必要 | |
| oid | num | 视频cid | 必要 | |
| ids | nums | 弹幕dmid列表 | 必要 | 多个id之间用`,`分隔 |
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | --------------------------- |
| code | num | 返回值 | 0成功<br />-400请求错误 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
| data | obj | 信息本体 | |
`data`对象:
| 字段 | 类型 | 内容 | 备注 |
| -------- | ---- | ---------------- | --------------------------------- |
| {弹幕id} | obj | 弹幕id对应的信息 | id分别对应请求参数中的`ids`,下同 |
| …… | obj | 弹幕id对应的信息 | |
`{弹幕id}`对象:
| 字段 | 类型 | 内容 | 备注 |
| --------- | ---- | -------- | ------------------------------------------------------------ |
| likes | num | 点赞数 | |
| user_like | num | 是否点赞 | 0未点赞<br />1已点赞<br />需要登录(Cookie或APP) <br />未登录恒为0 |
| id_str | str | 弹幕dmid | |
**示例**
查询`cid=236871317`下的弹幕`35600074482384899`、`38880975220375559`、`39052528418553863`点赞数
```shell
curl -G 'https://api.bilibili.com/x/v2/dm/thumbup/stats' \
--data-urlencode 'oid=236871317' \
--data-urlencode 'ids=39019145405661191,38880975220375559,39052528418553863' \
-b 'SESSDATA=xxx'
```
<details>
<summary>查看响应示例:</summary>
```json
{
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"38880975220375559": {
"likes": 1,
"user_like": 1,
"id_str": "38880975220375559"
},
"39019145405661191": {
"likes": 3,
"user_like": 1,
"id_str": "39019145405661191"
},
"39052528418553863": {
"likes": 2,
"user_like": 0,
"id_str": "39052528418553863"
}
}
}
```
</details>
## 点赞弹幕
> https://api.bilibili.com/x/v2/dm/thumbup/add
@ -573,16 +503,18 @@ curl -G 'https://api.bilibili.com/x/v2/dm/thumbup/stats' \
认证方式CookieSESSDATA或APP
查询指定弹幕点赞状态参阅文档 [弹幕点赞查询](thumbup.md)
**正文参数( application/x-www-form-urlencoded **
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ---------- | ---- | ------------------------ | -------------- | ------------------------ |
| access_key | str | APP登录Token | APP方式必要 | |
| dmid | num | 弹幕dmid | 必要 | |
| oid | num | 视频cid | 必要 | |
| op | num | 操作 | 必要 | 1点赞<br />2取消点赞 |
| platform | str | 平台 | 非必要 | |
| csrf | str | CSRF Token位于cookie | Cookie方式必要 | |
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ---------- | ---- | ------------------------- | --------------- | ------------------------------------------- |
| access_key | str | APP 登录 Token | APP 方式必要 | |
| dmid | num | 目标弹幕 dmid | 必要 | |
| oid | num | 目标弹幕所在视频 cid | 必要 | |
| op | num | 操作 | 必要 | 1点赞<br />2取消点赞 |
| platform | str | 平台标识 | 非必要 | web_playerweb 播放器<br />android安卓端 |
| csrf | str | CSRF Token位于 Cookie | Cookie 方式必要 | |
**json回复**
@ -600,12 +532,12 @@ curl -G 'https://api.bilibili.com/x/v2/dm/thumbup/stats' \
```shell
curl 'https://api.bilibili.com/x/v2/dm/thumbup/add' \
--data-urlencode 'dmid=35600074482384899' \
--data-urlencode 'oid=145928946' \
--data-urlencode 'op=1' \
--data-urlencode 'platform=web_player' \
--data-urlencode 'csrf=xxx' \
-b 'SESSDATA=xxx'
--data-urlencode 'dmid=35600074482384899' \
--data-urlencode 'oid=145928946' \
--data-urlencode 'op=1' \
--data-urlencode 'platform=web_player' \
--data-urlencode 'csrf=xxx' \
-b 'SESSDATA=xxx'
```
<details>

View File

@ -1,43 +1,49 @@
# protobuf弹幕
2020年5月23日哔哩哔哩网页端及移动端启用了新的默认弹幕api,网页端弹幕显示的上限变为原弹幕池上限的两倍。
2020年5月23日哔哩哔哩网页端及移动端启用了新的默认弹幕 API,网页端弹幕显示的上限变为原弹幕池上限的两倍。
新的api是以6分钟为一个单位加载即每次加载6分钟内的弹幕
新的 API 是以 6min 为一个单位加载,即每次加载 6min 内的弹幕
## 获取实时弹幕
> https://api.bilibili.com/x/v2/dm/web/seg.so web端
>
> https://api.bilibili.com/x/v2/dm/wbi/web/seg.so web 端新接口,需要 wbi 认证)
>
> https://api.bilibili.com/x/v2/dm/list/seg.so APP端
>
> https://i0.hdslb.com/bfs/dm/{data}.bin BAS/代码弹幕专包)
*请求方式GET*
*认证方式:半匿名(部分视频在无 Cookie: SESSDATA 时只返回部分弹幕)*
此接口与漫画弹幕相同
只能返回普通弹幕(`pool=1` `mode=1-7`)和代码弹幕(`pool=2` `mode=8`BAS弹幕`pool=2` `mode=9`)请从[弹幕元数据](danmaku_view_proto.md)中获取
互动弹幕UP主头像弹幕、关联视频、内嵌关注按钮也不存在这个接口请从[弹幕元数据](danmaku_view_proto.md)中获取
互动弹幕UP 主头像弹幕、关联视频、内嵌关注按钮)也不存在这个接口,请从[弹幕元数据](danmaku_view_proto.md)中获取
**注仅获取6min的整数倍时间内的弹幕6min内最多弹幕数为6000条如第一包中弹幕`progress`值域为0-360000**
**注:仅获取 6min 的整数倍时间内的弹幕6min 内最多弹幕数为 6000 条(如第一包中弹幕`progress`值域为0-360000**
**url参数**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------------- | ---- | -------- | ------ | ----------- |
| type | num | 弹幕类 | 必要 | 1视频弹幕 |
| oid | num | 视频cid | 必要 | |
| pid | num | 稿件avid | 非必要 | |
| segment_index | num | 分包 | 必要 | 6分钟一包 |
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------------- | ---- | --------- | ------ | ---------------------------- |
| type | num | 弹幕类 | 必要 | 1视频弹幕<br />2漫画弹幕 |
| oid | num | 视频 cid | 必要 | |
| pid | num | 稿件 avid | 非必要 | |
| segment_index | num | 分包 | 必要 | 6min 一包 |
| pull_mode | num | | 非必要 | |
| ps | num | | 非必要 | |
| pe | num | | 非必要 | |
**proto回复**
proto定义见[bilibili.community.service.dm.v1.DmSegMobileReply](../grpc_api/bilibili/community/service/dm/v1/dm.proto)
proto定义见[bilibili.community.service.dm.v1.DmSegMobileReply](../../grpc_api/bilibili/community/service/dm/v1/dm.proto)
- [protogen.marcgravell](https://protogen.marcgravell.com/): 在线编译protogen工具, 无需再安装本地编译器(生成文件需加后缀_pb2.py才可使用)
- [protogen.marcgravell](https://protogen.marcgravell.com/): 在线编译 protogen 工具, 无需再安装本地编译器(生成文件需加后缀`_pb2.py`才可使用)
- [protobuf pip](https://pypi.org/project/protobuf/): 可一键安装的python的protogen解析库
- [protobuf pip](https://pypi.org/project/protobuf/): 可一键安装的 Python 的 protogen 解析库
消息`DmSegMobileReply`
@ -47,26 +53,28 @@ proto定义见[bilibili.community.service.dm.v1.DmSegMobileReply](../grpc_api
消息`DanmakuElem`
| 名称 | 类型 | 含义 | 备注 |
| -------- | ------ | ------------------ | ------------------------------------------------------------ |
| id | int64 | 弹幕dmid | 唯一 可用于操作参数 |
| progress | int32 | 视频内弹幕出现时间 | 毫秒 |
| mode | int32 | 弹幕类型 | 1 2 3普通弹幕<br />4底部弹幕<br />5顶部弹幕<br />6逆向弹幕<br />7高级弹幕<br />8代码弹幕<br />9BAS弹幕仅限于特殊弹幕专包 |
| fontsize | int32 | 弹幕字号 | 18<br />25标准<br />36大 |
| color | uint32 | 弹幕颜色 | 十进制RGB888值 |
| midHash | string | 发送者mid的HASH | 用于屏蔽用户和查看用户发送的所有弹幕 也可反查用户id |
| content | string | 弹幕内容 | utf-8编码 |
| ctime | int64 | 弹幕发送时间 | 时间戳 |
| weight | int32 | 权重 | 用于智能屏蔽根据弹幕语义及长度通过AI识别得出<br />范围:[0-10]<br />值越大权重越高 |
| action | string | 动作? | 作用尚不明确 |
| pool | int32 | 弹幕池 | 0普通池<br />1字幕池<br />2特殊池代码/BAS弹幕 |
| idStr | string | 弹幕dmid | 字串形式<br />唯一 可用于操作参数 |
| 名称 | 类型 | 含义 | 备注 |
| --------- | ------ | ------------------ | ------------------------------------------------------------ |
| id | int64 | 弹幕 dmid | 唯一 可用于操作参数 |
| progress | int32 | 视频内弹幕出现时间 | 毫秒 |
| mode | int32 | 弹幕类型 | 1 2 3普通弹幕<br />4底部弹幕<br />5顶部弹幕<br />6逆向弹幕<br />7高级弹幕<br />8代码弹幕<br />9BAS 弹幕(仅限于特殊弹幕专包) |
| fontsize | int32 | 弹幕字号 | 18<br />25标准<br />36大 |
| color | uint32 | 弹幕颜色 | 十进制 RGB888 值 |
| midHash | string | 发送者 mid 的 HASH | 用于屏蔽用户和查看用户发送的所有弹幕也可反查用户id |
| content | string | 弹幕内容 | utf-8编码 |
| ctime | int64 | 弹幕发送时间 | 时间戳 |
| weight | int32 | 权重 | 用于智能屏蔽根据弹幕语义及长度通过AI识别得出<br />范围:[0-10]<br />值越大权重越高 |
| action | string | 动作? | |
| pool | int32 | 弹幕池 | 0普通池<br />1字幕池<br />2特殊池代码/BAS弹幕 |
| idStr | string | 弹幕 dmid | 字串形式<br />唯一 可用于操作参数 |
| attr | int32 | 弹幕属性位 | bit0保护<br />bit1直播<br />bit2高赞 |
| animation | string | 动画? | |
**示例:**
获取视频`av810872(cid=1176840)`炮姐的实时弹幕分包1
获取视频`av810872(cid=1176840)`(炮姐)的实时弹幕分包 1
**注:[proto定义](../grpc_api/bilibili/community/service/dm/v1/dm.proto)需要编译,`bilibili.community.service.dm.v1.dm_pb2`并非通过pypi安装**
**注:以下[proto定义](../grpc_api/bilibili/community/service/dm/v1/dm.proto)需要编译,`bilibili.community.service.dm.v1.dm_pb2`并非通过 pypi 安装**
```python
import requests

View File

@ -127,19 +127,19 @@ curl 'https://comment.bilibili.com/144541892.xml'
弹幕的颜色属性使用**十进制RGB888**值
| 颜色 | HEXRGB888 | DECRGB888 |
| --------------------------------- | ----------------------------------- | ------------------------------------- |
| <font color="#FE0302">红色</font> | <font color="#FE0302">FE0302</font> | <font color="#FE0302">16646914</font> |
| <font color="#FF7204">橘红</font> | <font color="#FF7204">FF7204</font> | <font color="#FF7204">16740868</font> |
| <font color="#FFAA02">橘黄</font> | <font color="#FFAA02">FFAA02</font> | <font color="#FFAA02">16755202</font> |
| <font color="#FFD302">淡黄</font> | <font color="#FFD302">FFD302</font> | <font color="#FFD302">16765698</font> |
| <font color="#FFFF00">黄色</font> | <font color="#FFFF00">FFFF00</font> | <font color="#FFFF00">16776960</font> |
| <font color="#A0EE00">草绿</font> | <font color="#A0EE00">A0EE00</font> | <font color="#A0EE00">10546688</font> |
| <font color="#00CD00">绿色</font> | <font color="#00CD00">00CD00</font> | <font color="#00CD00">52480</font> |
| <font color="#019899">墨绿</font> | <font color="#019899">019899</font> | <font color="#019899">104601</font> |
| <font color="#4266BE">紫色</font> | <font color="#4266BE">4266BE</font> | <font color="#4266BE">4351678</font> |
| <font color="#89D5FF">青色</font> | <font color="#89D5FF">89D5FF</font> | <font color="#89D5FF">9022215</font> |
| <font color="#CC0273">品红</font> | <font color="#CC0273">CC0273</font> | <font color="#CC0273">13369971</font> |
| <font color="#222222">黑色</font> | <font color="#222222">222222</font> | <font color="#222222">2236962</font> |
| <font color="#9B9B9B">灰色</font> | <font color="#9B9B9B">9B9B9B</font> | <font color="#9B9B9B">10197915</font> |
| <font color="#FFFFFF">白色</font> | <font color="#FFFFFF">FFFFFF</font> | <font color="#FFFFFF">16777215</font> |
| 颜色 | HEXRGB888 | DECRGB888 |
| -------------------------------------- | ----------------------------------------- | ------------------------------------------- |
| <font v-pre color="#FE0302">红色</font> | <font v-pre color="#FE0302">FE0302</font> | <font v-pre color="#FE0302">16646914</font> |
| <font v-pre color="#FF7204">橘红</font> | <font v-pre color="#FF7204">FF7204</font> | <font v-pre color="#FF7204">16740868</font> |
| <font v-pre color="#FFAA02">橘黄</font> | <font v-pre color="#FFAA02">FFAA02</font> | <font v-pre color="#FFAA02">16755202</font> |
| <font v-pre color="#FFD302">淡黄</font> | <font v-pre color="#FFD302">FFD302</font> | <font v-pre color="#FFD302">16765698</font> |
| <font v-pre color="#FFFF00">黄色</font> | <font v-pre color="#FFFF00">FFFF00</font> | <font v-pre color="#FFFF00">16776960</font> |
| <font v-pre color="#A0EE00">草绿</font> | <font v-pre color="#A0EE00">A0EE00</font> | <font v-pre color="#A0EE00">10546688</font> |
| <font v-pre color="#00CD00">绿色</font> | <font v-pre color="#00CD00">00CD00</font> | <font v-pre color="#00CD00">52480</font> |
| <font v-pre color="#019899">墨绿</font> | <font v-pre color="#019899">019899</font> | <font v-pre color="#019899">104601</font> |
| <font v-pre color="#4266BE">紫色</font> | <font v-pre color="#4266BE">4266BE</font> | <font v-pre color="#4266BE">4351678</font> |
| <font v-pre color="#89D5FF">青色</font> | <font v-pre color="#89D5FF">89D5FF</font> | <font v-pre color="#89D5FF">9022215</font> |
| <font v-pre color="#CC0273">品红</font> | <font v-pre color="#CC0273">CC0273</font> | <font v-pre color="#CC0273">13369971</font> |
| <font v-pre color="#222222">黑色</font> | <font v-pre color="#222222">222222</font> | <font v-pre color="#222222">2236962</font> |
| <font v-pre color="#9B9B9B">灰色</font> | <font v-pre color="#9B9B9B">9B9B9B</font> | <font v-pre color="#9B9B9B">10197915</font> |
| <font v-pre color="#FFFFFF">白色</font> | <font v-pre color="#FFFFFF">FFFFFF</font> | <font v-pre color="#FFFFFF">16777215</font> |

View File

@ -119,7 +119,7 @@ curl -G 'https://api.bilibili.com/x/v2/dm/history/index' \
**proto回复**
porto定义见[bilibili.community.service.dm.v1.DmSegMobileReply](../grpc_api/bilibili/community/service/dm/v1.proto)
porto定义见[bilibili.community.service.dm.v1.DmSegMobileReply](https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/grpc_api/bilibili/community/service/dm/v1/dm.proto)
详细说明见[protobuf弹幕](danmaku_proto.md)
@ -237,4 +237,4 @@ curl -G 'https://api.bilibili.com/x/v2/dm/history' \
</details>
</details>
</details>

104
docs/danmaku/thumbup.md Normal file
View File

@ -0,0 +1,104 @@
# 弹幕点赞查询
## 查询指定dmid的点赞数
> https://api.bilibili.com/x/v2/dm/thumbup/stats
*请求方式GET*
**url参数**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------ | ---- | ----------------- | ------ | --------------------- |
| oid | num | 视频 cid | 必要 | |
| ids | nums | 欲查询的弹幕 dmid | 必要 | 多个 id 之间用`,`分隔 |
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------------------------- | --------------------------- |
| code | num | 返回值 | 0成功<br />-400请求错误 |
| message | str | 错误信息 | 默认为 0 |
| ttl | num | 1 | |
| data | obj | 弹幕 id 与之对应数据的 Map | |
`data`对象:
| 字段 | 类型 | 内容 | 备注 |
| ----------- | ---- | -------------------------- | ---- |
| {弹幕 dmid} | obj | {弹幕 dmid} 对应的点赞信息 | |
`{弹幕 dmid}`对象:
| 字段 | 类型 | 内容 | 备注 |
| -------------------- | ---- | ---------------------- | ------------------------------------------------------- |
| likes | num | 对应弹幕所获得的点赞数 | |
| user_like | num | 当前用户是否点赞 | 0未点赞<br />1已点赞<br />需要登录Cookie 或 APP |
| id_str | str | 弹幕 dmid 字符串形式 | |
| show_threshold | num | | |
| reply_count | num | | |
| gray_release_control | obj | | |
`gray_release_control`对象:
| 字段 | 类型 | 内容 | 备注 |
| ------------- | ---- | ------ | ---- |
| show_dm_reply | bool | | |
**示例:**
获取视频 BV1AP411d7Qa 1Pcid=1131648710下的几个弹幕 dmid`1318231376180646144,1318231518484950784,1318231736680887808`
```bash
curl -G 'https://api.bilibili.com/x/v2/dm/thumbup/stats' \
--data-urlencode 'oid=1131648710' \
--data-urlencode 'ids=1318231376180646144,1318231518484950784,1318231736680887808' \
-b 'SESSDATA=xxx'
```
<details>
<summary>查看响应示例:</summary>
```json
{
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"1318231376180646144": {
"likes": 0,
"user_like": 0,
"id_str": "1318231376180646144",
"show_threshold": 10,
"reply_count": 0,
"gray_release_control": {
"show_dm_reply": false
}
},
"1318231518484950784": {
"likes": 0,
"user_like": 0,
"id_str": "1318231518484950784",
"show_threshold": 10,
"reply_count": 0,
"gray_release_control": {
"show_dm_reply": false
}
},
"1318231736680887808": {
"likes": 0,
"user_like": 0,
"id_str": "1318231736680887808",
"show_threshold": 10,
"reply_count": 0,
"gray_release_control": {
"show_dm_reply": false
}
}
}
}
```
</details>

3811
docs/dynamic/all.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -13,12 +13,13 @@
需注意账号转发视频投稿其他用户的动态以及分享收藏夹等均为转发类内容并不属于type=4300的收藏类动态等。
在type=1的转发类动态中解析出的对象包含以下内容
| 字段 | 类型 | 内容 | 备注 |
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------- |
| user | obj | 转发者用户信息 | 包含用户名用户id和头像 |
| item | obj | 转发相关信息 | `content`字段为转发附言 | |
| origin | str | 被转发动态信息 | 即本文档所描述的动态详细信息字段。</br>动态类型为`item`对象的`orig_type`字段 |
| origin_extend_json | str | 被转发动态补充信息 | |
| user | obj | 转发者用户信息 | 包含用户名用户id和头像 |
| item | obj | 转发相关信息 | `content`字段为转发附言 | |
| origin | str | 被转发动态信息 | 即本文档所描述的动态详细信息字段。<br/>动态类型为`item`对象的`orig_type`字段 |
| origin_extend_json | str | 被转发动态补充信息 | |
| origin_user | obj | 被转发用户信息 | |
| activity_infos | obj | 被转发动态参与的活动 | |
@ -106,10 +107,11 @@
## 在图片动态中type=2
在type=2的图片动态中解析出的对象包含以下内容
| 字段 | 类型 | 内容 | 备注 |
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------- |
| item | obj | 图片动态内容 | `description`字段为文字内容</br>`pictures`字段图片 | |
| user | obj | 发布者用户信息 | 包含用户名用户id和头像 |
| item | obj | 图片动态内容 | `description`字段为文字内容<br/>`pictures`字段图片 | |
| user | obj | 发布者用户信息 | 包含用户名用户id和头像 |
<details>
@ -166,14 +168,14 @@
</details>
## 在文字动态中type=4
在type=4的文字动态中解析出的对象包含以下内容
| 字段 | 类型 | 内容 | 备注 |
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------- |
| item | obj | 文字动态内容 | `description`字段为文字内容 | |
| user | obj | 发布者用户信息 | 包含用户名用户id和头像 |
| item | obj | 文字动态内容 | `description`字段为文字内容 | |
| user | obj | 发布者用户信息 | 包含用户名用户id和头像 |
<details>
@ -204,9 +206,10 @@
## 在视频投稿动态中type=8
在type=8的视频投稿动态中解析出的对象包含以下内容
| 字段 | 类型 | 内容 | 备注 |
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------- |
| aid | num | 视频avid | |
| aid | num | 视频avid | |
| attribute | num | `0` | [可能已弃用](https://shakaianee.top/archives/9/) |
| cid | num | 视频cid | |
| copyright | num | 原创信息 | 1为原创2为转载 |
@ -215,7 +218,7 @@
| duration | num | 视频时长 | 单位秒 |
| dynamic | str | 动态文字内容 | |
| first_frame | str | 视频第一帧图片 | 图片链接 |
| jump_url | str | 视频跳转链接 | |
| jump_url | str | 视频跳转链接 | |
| mission_id | num | 稿件参与的活动id | |
| owner | obj | 动态作者信息 | 即up主 |
| pic | str | 视频封面 | |
@ -223,7 +226,7 @@
| pubdate | num | 发布时间 | 时间戳 |
| rights | obj | 联合投稿,是否付费等信息 | 可能用来代替原`attribute`字段 |
| stat | obj | 视频数据 | 点赞投币等 |
| state | num | 视频状态 | 详情见**属性数据文档** |
| state | num | 视频状态 | 详情见**属性数据文档** |
| tid | num | 视频分区编号 | |
| title | str | 视频标题 | |
| tname | str | 视频分区名称 | |
@ -302,7 +305,8 @@
## 在专栏投稿动态中type=64
在type=64的专栏投稿动态中解析出的对象包含以下内容
| 字段 | 类型 | 内容 | 备注 |
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------- |
| id | num | 专栏的id即cv号 | |
| category | obj | 分类号和分类名称 | |
@ -313,10 +317,10 @@
| template_id | num | 模板信息 | |
| state | num | 专栏状态 | |
| author | obj | 作者信息 | 包含了头像挂件和勋章等 |
| reprint | num | 可能是转载 | |
| reprint | num | 可能是转载 | |
| image_urls | obj | 图片链接 | |
| publish_time | num | 发布时间 | 时间戳,应该指专栏 |
| ctime | num | 发布时间 | 时间戳,应该指动态 |
| publish_time | num | 发布时间 | 时间戳,应该指专栏 |
| ctime | num | 发布时间 | 时间戳,应该指动态 |
| stats | obj | 专栏数据,点赞之类 | 有点踩字段,但并未实装此功能 |
| words | num | 字数 | |
| origin_image_urls | obj | 源图片地址 | |
@ -448,7 +452,8 @@
## 在音频投稿动态中type=256
在type=256的音频投稿动态中解析出的对象包含以下内容
| 字段 | 类型 | 内容 | 备注 |
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------- |
| id | num | 投稿编号 | 即au号 |
| upId | num | 音乐人id | 与用户uid不同 |
@ -456,7 +461,7 @@
| upper | str | 上传者名称 | |
| cover | str | 封面图链接 | |
| author | str | 作者名称 | |
| ctime | num | 上传时间 | 时间戳的后面加了三个0 |
| ctime | num | 上传时间 | 时间戳的后面加了三个0 |
| playCnt | num | 播放量 | |
| intro | str | 音频介绍 | |
| schema | str | 跳转链接 | 似乎并不只是url |

269
docs/dynamic/detail.md Normal file
View File

@ -0,0 +1,269 @@
# 获取动态详情
> https://api.bilibili.com/x/polymer/web-dynamic/v1/detail
请求方式:`GET`
是否需要登录:`否`
## URL参数
| 参数名 | 类型 | 必填 | 内容 | 备注 |
|-----------------|-----|-----|--------|-----|
| timezone_offset | num | | `-480` | |
| id | num | √ | 动态id | |
## Json回复
### 根对象
| 字段名 | 类型 | 内容 | 备注 |
|---------|-----|------|--------------------------|
| code | num | 响应码 | 0成功<br/>41011394101139 |
| message | str | | |
| ttl | num | 1 | |
| data | obj | 信息本体 | |
### `data`对象
| 字段名 | 类型 | 内容 | 备注 |
|------|-----|-----|-----|
| item | obj | | |
### `data`对象 -> `item`对象
参照 [获取动态列表](./all.md#获取动态列表)
## 请求示例
```shell
curl -L -X GET 'https://api.bilibili.com/x/polymer/web-dynamic/v1/detail?id=724328028268658744'
```
## 响应示例
<details>
<summary>点击查看</summary>
```json
{
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"item": {
"basic": {
"comment_id_str": "724328028268658744",
"comment_type": 17,
"like_icon": {
"action_url": "",
"end_url": "",
"id": 0,
"start_url": ""
},
"rid_str": "724328032624443401"
},
"id_str": "724328028268658744",
"modules": {
"module_author": {
"face": "https://i2.hdslb.com/bfs/face/876bf5dfa8c583acb5f8689fc923077f6a2aba23.jpg",
"face_nft": false,
"following": null,
"jump_url": "//space.bilibili.com/11357018/dynamic",
"label": "",
"mid": 11357018,
"name": "动画魂-Anitama",
"official_verify": {
"desc": "",
"type": 0
},
"pendant": {
"expire": 0,
"image": "",
"image_enhance": "",
"image_enhance_frame": "",
"name": "",
"pid": 0
},
"pub_action": "",
"pub_location_text": "",
"pub_time": "2022-11-03 22:02",
"pub_ts": 1667484162,
"type": "AUTHOR_TYPE_NORMAL",
"vip": {
"avatar_subscript": 1,
"avatar_subscript_url": "",
"due_date": 1685808000000,
"label": {
"bg_color": "#FB7299",
"bg_style": 1,
"border_color": "",
"img_label_uri_hans": "",
"img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/8d4f8bfc713826a5412a0a27eaaac4d6b9ede1d9.png",
"img_label_uri_hant": "",
"img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/VEW8fCC0hg.png",
"label_theme": "annual_vip",
"path": "",
"text": "年度大会员",
"text_color": "#FFFFFF",
"use_img_label": true
},
"nickname_color": "#FB7299",
"status": 1,
"theme_type": 0,
"type": 2
}
},
"module_dynamic": {
"additional": null,
"desc": {
"rich_text_nodes": [
{
"orig_text": "恭喜 @羽希plume @晕乎菌 中奖,已私信联系。——全天加码放水,红包力度很大,打开手淘搜“我爱你红包”,红包每天可以领,积少成多。 ——明天早上9点开另外一则抽奖有打扰请多保函。\n",
"text": "恭喜 @羽希plume @晕乎菌 中奖,已私信联系。——全天加码放水,红包力度很大,打开手淘搜“我爱你红包”,红包每天可以领,积少成多。 ——明天早上9点开另外一则抽奖有打扰请多保函。\n",
"type": "RICH_TEXT_NODE_TYPE_TEXT"
}
],
"text": "恭喜 @羽希plume @晕乎菌 中奖,已私信联系。——全天加码放水,红包力度很大,打开手淘搜“我爱你红包”,红包每天可以领,积少成多。 ——明天早上9点开另外一则抽奖有打扰请多保函。\n"
},
"major": null,
"topic": null
},
"module_more": {
"three_point_items": [
{
"label": "举报",
"type": "THREE_POINT_REPORT"
}
]
},
"module_stat": {
"comment": {
"count": 5,
"forbidden": false
},
"forward": {
"count": 1,
"forbidden": false
},
"like": {
"count": 170,
"forbidden": false,
"status": false
}
}
},
"orig": {
"basic": {
"comment_id_str": "",
"comment_type": 0,
"like_icon": {
"action_url": "",
"end_url": "",
"id": 0,
"start_url": ""
},
"rid_str": ""
},
"id_str": "720590749615259664",
"modules": {
"module_author": {
"face": "https://i2.hdslb.com/bfs/face/876bf5dfa8c583acb5f8689fc923077f6a2aba23.jpg",
"face_nft": false,
"following": null,
"jump_url": "//space.bilibili.com/11357018/dynamic",
"label": "",
"mid": 11357018,
"name": "动画魂-Anitama",
"official_verify": {
"desc": "",
"type": 0
},
"pendant": {
"expire": 0,
"image": "",
"image_enhance": "",
"image_enhance_frame": "",
"name": "",
"pid": 0
},
"pub_action": "",
"pub_time": "",
"pub_ts": 1666614008,
"type": "AUTHOR_TYPE_NORMAL",
"vip": {
"avatar_subscript": 1,
"avatar_subscript_url": "",
"due_date": 1685808000000,
"label": {
"bg_color": "#FB7299",
"bg_style": 1,
"border_color": "",
"img_label_uri_hans": "",
"img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/8d4f8bfc713826a5412a0a27eaaac4d6b9ede1d9.png",
"img_label_uri_hant": "",
"img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/VEW8fCC0hg.png",
"label_theme": "annual_vip",
"path": "",
"text": "年度大会员",
"text_color": "#FFFFFF",
"use_img_label": true
},
"nickname_color": "#FB7299",
"status": 1,
"theme_type": 0,
"type": 2
}
},
"module_dynamic": {
"additional": null,
"desc": {
"rich_text_nodes": [
{
"orig_text": "双11天猫红包超大力度提前发放\n活动很猛红包很大加额加量\n打开手淘搜“我爱你红包”\n打开手淘搜“我爱你红包”\n打开手淘搜“我爱你红包”\n最高可领取28888元\n\n一天可领3次今天红包额度最大\n越早领取得现金概率越大\n抽奖=转发+关注",
"text": "双11天猫红包超大力度提前发放\n活动很猛红包很大加额加量\n打开手淘搜“我爱你红包”\n打开手淘搜“我爱你红包”\n打开手淘搜“我爱你红包”\n最高可领取28888元\n\n一天可领3次今天红包额度最大\n越早领取得现金概率越大\n抽奖=转发+关注",
"type": "RICH_TEXT_NODE_TYPE_TEXT"
},
{
"jump_url": "//search.bilibili.com/all?keyword=%23%E4%BA%92%E5%8A%A8%E6%8A%BD%E5%A5%96%23",
"orig_text": "#互动抽奖#",
"text": "#互动抽奖#",
"type": "RICH_TEXT_NODE_TYPE_TOPIC"
},
{
"orig_text": "\n转+评,留言你领到多少红包\n评论区随机抽取2位每人补贴50零花钱 ",
"text": "\n转+评,留言你领到多少红包\n评论区随机抽取2位每人补贴50零花钱 ",
"type": "RICH_TEXT_NODE_TYPE_TEXT"
}
],
"text": "双11天猫红包超大力度提前发放\n活动很猛红包很大加额加量\n打开手淘搜“我爱你红包”\n打开手淘搜“我爱你红包”\n打开手淘搜“我爱你红包”\n最高可领取28888元\n\n一天可领3次今天红包额度最大\n越早领取得现金概率越大\n抽奖=转发+关注#互动抽奖#\n转+评,留言你领到多少红包\n评论区随机抽取2位每人补贴50零花钱 "
},
"major": {
"draw": {
"id": 210334026,
"items": [
{
"height": 672,
"size": 134.85938,
"src": "https://i0.hdslb.com/bfs/new_dyn/37c21f8864e47cbeeb7c3e3a66bb250b11357018.jpg",
"tags": [],
"width": 576
}
]
},
"type": "MAJOR_TYPE_DRAW"
},
"topic": null
}
},
"type": "DYNAMIC_TYPE_DRAW",
"visible": true
},
"type": "DYNAMIC_TYPE_FORWARD",
"visible": true
}
}
}
```
</details>

View File

@ -0,0 +1,222 @@
# 动态类型
| 类型 | 说明 | 示例 |
|-------------------------------|----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| DYNAMIC_TYPE_NONE | 无效动态 | [716510857084796964](https://t.bilibili.com/716510857084796964) |
| DYNAMIC_TYPE_FORWARD | 动态转发 | |
| DYNAMIC_TYPE_AV | 投稿视频 | |
| DYNAMIC_TYPE_PGC | 剧集(番剧、电影、纪录片) | |
| DYNAMIC_TYPE_COURSES | | |
| DYNAMIC_TYPE_WORD | 纯文字动态 | [718377531474968613](https://t.bilibili.com/718377531474968613) |
| DYNAMIC_TYPE_DRAW | 带图动态 | [718384798557536290](https://t.bilibili.com/718384798557536290) |
| DYNAMIC_TYPE_ARTICLE | 投稿专栏 | [718372214316990512](https://t.bilibili.com/718372214316990512) |
| DYNAMIC_TYPE_MUSIC | 音乐 | |
| DYNAMIC_TYPE_COMMON_SQUARE | 装扮<br/>剧集点评<br/>普通分享 | [551309621391003098](https://t.bilibili.com/551309621391003098)<br/>[716503778995470375](https://t.bilibili.com/716503778995470375)<br/>[716481612656672789](https://t.bilibili.com/716481612656672789) |
| DYNAMIC_TYPE_COMMON_VERTICAL | | |
| DYNAMIC_TYPE_LIVE | 直播间分享 | [216042859353895488](https://t.bilibili.com/216042859353895488) |
| DYNAMIC_TYPE_MEDIALIST | 收藏夹 | [534428265320147158](https://t.bilibili.com/534428265320147158) |
| DYNAMIC_TYPE_COURSES_SEASON | 课程 | [717906712866062340](https://t.bilibili.com/717906712866062340) |
| DYNAMIC_TYPE_COURSES_BATCH | | |
| DYNAMIC_TYPE_AD | | |
| DYNAMIC_TYPE_APPLET | | |
| DYNAMIC_TYPE_SUBSCRIPTION | | |
| DYNAMIC_TYPE_LIVE_RCMD | 直播开播 | [718371505648435205](https://t.bilibili.com/718371505648435205) |
| DYNAMIC_TYPE_BANNER | | |
| DYNAMIC_TYPE_UGC_SEASON | 合集更新 | [718390979031203873](https://t.bilibili.com/718390979031203873) |
| DYNAMIC_TYPE_SUBSCRIPTION_NEW | | |
# 富文本节点类型
| 类型 | 说明 | 示例 |
|---------------------------------|------|-----------------------------------------------------------------|
| RICH_TEXT_NODE_TYPE_NONE | | |
| RICH_TEXT_NODE_TYPE_TEXT | 文字节点 | [721295772787671059](https://t.bilibili.com/721295772787671059) |
| RICH_TEXT_NODE_TYPE_AT | @用户 | [721296515797090324](https://t.bilibili.com/721296515797090324) |
| RICH_TEXT_NODE_TYPE_LOTTERY | 互动抽奖 | [720907383182721040](https://t.bilibili.com/720907383182721040) |
| RICH_TEXT_NODE_TYPE_VOTE | 投票 | [721203899129659408](https://t.bilibili.com/721203899129659408) |
| RICH_TEXT_NODE_TYPE_TOPIC | 话题 | [721188862459641879](https://t.bilibili.com/721188862459641879) |
| RICH_TEXT_NODE_TYPE_GOODS | 商品链接 | [721282703208480790](https://t.bilibili.com/721282703208480790) |
| RICH_TEXT_NODE_TYPE_BV | 视频链接 | [716752002311258165](https://t.bilibili.com/716752002311258165) |
| RICH_TEXT_NODE_TYPE_AV | | |
| RICH_TEXT_NODE_TYPE_EMOJI | 表情 | [716751108968546393](https://t.bilibili.com/716751108968546393) |
| RICH_TEXT_NODE_TYPE_USER | | |
| RICH_TEXT_NODE_TYPE_CV | | |
| RICH_TEXT_NODE_TYPE_VC | | |
| RICH_TEXT_NODE_TYPE_WEB | 网页链接 | [716751027361022055](https://t.bilibili.com/716751027361022055) |
| RICH_TEXT_NODE_TYPE_TAOBAO | | |
| RICH_TEXT_NODE_TYPE_MAIL | 邮箱地址 | [721314095109767220](https://t.bilibili.com/721314095109767220) |
| RICH_TEXT_NODE_TYPE_OGV_SEASON | 剧集信息 | [721282046064853080](https://t.bilibili.com/721282046064853080) |
| RICH_TEXT_NODE_TYPE_OGV_EP | | |
| RICH_TEXT_NODE_TYPE_SEARCH_WORD | | |
# 作者类型
| 类型 | 说明 | 示例 |
|------------------------|------|-----|
| AUTHOR_TYPE_NONE | | |
| AUTHOR_TYPE_NORMAL | 普通更新 | |
| AUTHOR_TYPE_PGC | 剧集更新 | |
| AUTHOR_TYPE_UGC_SEASON | 合集更新 | |
| 类型 | 说明 | 示例 |
|-----------------|-----|-----|
| EMOJI_TYPE_NONE | | |
| EMOJI_TYPE_OLD | | |
| EMOJI_TYPE_NEW | | |
| EMOJI_TYPE_VIP | | |
# 相关内容卡片类型
| 类型 | 说明 | 示例 |
|-------------------------|------|--------------------------------------------------------------------------|
| ADDITIONAL_TYPE_NONE | | |
| ADDITIONAL_TYPE_PGC | | |
| ADDITIONAL_TYPE_GOODS | 商品信息 | |
| ADDITIONAL_TYPE_VOTE | 投票 | [716365292050055176](https://t.bilibili.com/716365292050055176) |
| ADDITIONAL_TYPE_COMMON | 一般类型 | 游戏<br/>[716357878942793745](https://t.bilibili.com/716357878942793745) |
| ADDITIONAL_TYPE_MATCH | | |
| ADDITIONAL_TYPE_UP_RCMD | | |
| ADDITIONAL_TYPE_UGC | 视频跳转 | [716489253410832401](https://t.bilibili.com/716489253410832401) |
| ADDITIONAL_TYPE_RESERVE | | 直播预约<br/>[716524987542929443](https://t.bilibili.com/716524987542929443) |
| 类型 | 说明 | 示例 |
|-------------------------------|-----|-----|
| ADDITIONAL_BUTTON_TYPE_NONE | | |
| ADDITIONAL_BUTTON_TYPE_JUMP | | |
| ADDITIONAL_BUTTON_TYPE_BUTTON | | |
| 类型 | 说明 | 示例 |
|----------------------------------|-----|-----|
| ADDITIONAL_BUTTON_STATUS_NONE | | |
| ADDITIONAL_BUTTON_STATUS_UNCHECK | | |
| ADDITIONAL_BUTTON_STATUS_CHECK | | |
| 类型 | 说明 | 示例 |
|-------------------------------|-----|-----|
| ADD_BUTTON_CLICK_TYPE_NONE | | |
| ADD_BUTTON_CLICK_TYPE_RESERVE | | |
| 类型 | 说明 | 示例 |
|-------------------------|-----|-----|
| DISABLE_STATE_HIGHLIGHT | | |
| DISABLE_STATE_GRAY | | |
| 类型 | 说明 | 示例 |
|----------------------------|-----|-----|
| ADD_BUTTON_BG_STYLE_FILL | | |
| ADD_BUTTON_BG_STYLE_STROKE | | |
| ADD_BUTTON_BG_STYLE_GRAY | | |
| 类型 | 说明 | 示例 |
|----------------------------------|-----|-----|
| HIGHLIGHT_TEXT_STYLE_TYPE_NONE | | |
| HIGHLIGHT_TEXT_STYLE_TYPE_ACTIVE | | |
# 动态主体类型
| 类型 | 说明 | 示例 |
|-----------------------------|-------|-----------------------------------------------------------------|
| MAJOR_TYPE_NONE | 动态失效 | [716510857084796964](https://t.bilibili.com/716510857084796964) |
| MAJOR_TYPE_NONE | 转发动态 | [866756840240709701](https://www.bilibili.com/opus/866756840240709701) |
| MAJOR_TYPE_OPUS | 图文动态 | [870176712256651305](https://www.bilibili.com/opus/870176712256651305) |
| MAJOR_TYPE_ARCHIVE | 视频 | [716526237365829703](https://t.bilibili.com/716526237365829703) |
| MAJOR_TYPE_PGC | 剧集更新 | [645981661420322824](https://t.bilibili.com/645981661420322824) |
| MAJOR_TYPE_COURSES | | |
| MAJOR_TYPE_DRAW | 带图动态 | [716358050743582725](https://t.bilibili.com/716358050743582725) |
| MAJOR_TYPE_ARTICLE | | |
| MAJOR_TYPE_MUSIC | 音频更新 | |
| MAJOR_TYPE_COMMON | 一般类型 | [716481612656672789](https://t.bilibili.com/716481612656672789) |
| MAJOR_TYPE_LIVE | 直播间分享 | [267505569812738175](https://t.bilibili.com/267505569812738175) |
| MAJOR_TYPE_MEDIALIST | | |
| MAJOR_TYPE_APPLET | | |
| MAJOR_TYPE_SUBSCRIPTION | | |
| MAJOR_TYPE_LIVE_RCMD | 直播状态 | |
| MAJOR_TYPE_UGC_SEASON | 合计更新 | [716509100448415814](https://t.bilibili.com/716509100448415814) |
| MAJOR_TYPE_SUBSCRIPTION_NEW | | |
| 类型 | 说明 | 示例 |
|-----------------|-----|-----|
| MEDIA_TYPE_NONE | | |
| MEDIA_TYPE_UGC | | |
| MEDIA_TYPE_PGC | | |
| MEDIA_TYPE_LIVE | | |
| 类型 | 说明 | 示例 |
|--------------------------|-----|-----|
| PGC_SUB_TYPE_NONE | | |
| PGC_SUB_TYPE_BANGUMI | | |
| PGC_SUB_TYPE_MOVIE | | |
| PGC_SUB_TYPE_DOCUMENTARY | | |
| PGC_SUB_TYPE_DOMESTIC | | |
| PGC_SUB_TYPE_TV | | |
| 类型 | 说明 | 示例 |
|----------------------|-----|-----|
| DRAW_TAG_TYPE_NONE | | |
| DRAW_TAG_TYPE_COMMON | | |
| DRAW_TAG_TYPE_GOODS | | |
| DRAW_TAG_TYPE_USER | | |
| DRAW_TAG_TYPE_TOPIC | | |
| DRAW_TAG_TYPE_LBS | | |
| 类型 | 说明 | 示例 |
|----------------------------------|-----|-----|
| MAJOR_COMMON_STYLE_TYPE_NONE | | |
| MAJOR_COMMON_STYLE_TYPE_SQUARE | | |
| MAJOR_COMMON_STYLE_TYPE_VERTICAL | | |
| 类型 | 说明 | 示例 |
|---------------------|-----|-----|
| RESERVE_TYPE_NONE | | |
| RESERVE_TYPE_RECALL | | |
| 类型 | 说明 | 示例 |
|--------------------------|-----|-----|
| LIVE_STATE_TYPE_NONE | | |
| LIVE_STATE_TYPE_LIVE | | |
| LIVE_STATE_TYPE_ROTATION | | |
| 类型 | 说明 | 示例 |
|----------------------------------|-----|-----|
| SUBSCRIPTION_NEW_STYLE_TYPE_NONE | | |
| SUBSCRIPTION_NEW_STYLE_TYPE_DRAW | | |
| SUBSCRIPTION_NEW_STYLE_TYPE_LIVE | | |
| 类型 | 说明 | 示例 |
|------------------------------|---------|-----|
| THREE_POINT_DELETE | 删除 | |
| THREE_POINT_REPORT | 举报 | |
| THREE_POINT_FOLLOWING | 关注/取消关注 | |
| THREE_POINT_TOP | 置顶/取消置顶 | |
| THREE_POINT_UNFAV | | |
| THREE_POINT_UNSUBS | | |
| THREE_POINT_TOPIC_REPORT | | |
| THREE_POINT_TOPIC_IRRELEVANT | | |
| THREE_POINT_RCMD_RESOURCE | | |
| THREE_POINT_RCMD_FEEDBACK | | |
| 类型 | 说明 | 示例 |
|--------------------|-----|-----|
| FOLD_TYPE_NONE | | |
| FOLD_TYPE_PUBLISH | | |
| FOLD_TYPE_FREQUENT | | |
| FOLD_TYPE_UNITE | | |
| FOLD_TYPE_LIMIT | | |
| 类型 | 说明 | 示例 |
|------------------------------|-----|-----|
| DYN_STATUS_TYPE_NONE | | |
| DYN_STATUS_TYPE_NORMAL | | |
| DYN_STATUS_TYPE_AUDITING | | |
| DYN_STATUS_TYPE_SELF_VISIBLE | | |
| DYN_STATUS_TYPE_DELETED | | |
| 类型 | 说明 | 示例 |
|---------------|-----|-----|
| SCENE_DETAIL | | |
| SCENE_HOT | | |
| SCENE_GENERAL | | |
| SCENE_SPACE | | |
| SCENE_TOPIC | | |

View File

@ -273,7 +273,7 @@ curl -G 'https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/get_dynamic_deta
| 字段 | 类型 | 内容 | 备注 |
| ----- | --- | ---- | ------------------------------------- |
| role | num | 认证类型 | 0<br />1 2 7个人认证<br />3 4 5 6机构认证 |
| role | num | 认证类型 | 见[用户认证类型一览](../user/official_role.md) |
| title | str | 认证信息 | 无为空 |
| desc | str | 认证备注 | 无为空 |
| type | num | 是否认证 | -1<br />0认证 |

1143
docs/dynamic/space.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -73,7 +73,7 @@ curl 'https://api.bilibili.com/x/ugcpay/trade/elec/pay/qr_code/create' \
"message": "0",
"ttl": 1,
"data": {
"qr_code_url": "http://api.bilibili.com/x/ugcpay/trade/elec/pay/qr_code/gateway?mid=293793435&token=c1cb1d95d2194ba58df6bb0f24ae1aaa",
"qr_code_url": "https://api.bilibili.com/x/ugcpay/trade/elec/pay/qr_code/gateway?mid=293793435&token=c1cb1d95d2194ba58df6bb0f24ae1aaa",
"qr_token": "c1cb1d95d2194ba58df6bb0f24ae1aaa",
"exp": 1
}

View File

@ -16,12 +16,12 @@
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | --------------------------- |
| code | num | 返回值 | 0成功<br />-400请求错误 |
| message | str | 错误信息 | |
| ttl | num | 0 | |
| data | obj | 数据本体 | |
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ---------------------------- |
| code | num | 返回值 | 0成功 <br />-400请求错误<br />88214up主未开通充电 |
| message | str | 错误信息 | |
| ttl | num | 0 | |
| data | obj | 数据本体 | |
`data`对象:

View File

@ -39,6 +39,8 @@
| ------ | ----- | ------------ | ---- |
| info | obj | 收藏夹元数据 | |
| medias | array | 收藏夹内容 | |
| has_more | bool | 收藏夹是否有下一页 | |
| ttl | num | 接口返回时间 | 时间戳 |
`data`中的`info`对象:
@ -103,7 +105,7 @@
| page | num | 视频分P数 | |
| duration | num | 音频/视频时长 | |
| upper | obj | UP主信息 | |
| attr | num | 属性位(?) | |
| attr | num | 失效 | 0: 正常9: up自己删除1: 其他原因删除 |
| cnt_info | obj | 状态数 | |
| link | str | 跳转uri | |
| ctime | num | 投稿时间 | 时间戳 |
@ -319,7 +321,8 @@ curl -G 'https://api.bilibili.com/x/v3/fav/resource/list' \
"season": null
}
],
"has_more": true
"has_more": true,
"ttl": 1703349018
}
}
```

View File

@ -389,15 +389,15 @@ curl -G 'https://api.bilibili.com/x/web-interface/history/cursor' \
| pubdate | num | 稿件发布时间 | 时间戳 |
| ctime | num | 用户提交稿件的时间 | 时间戳 |
| desc | str | 视频简介 | |
| state | num | 视频状态 | 略,见[获取视频详细信息web端](/video/info.md#获取视频详细信息web端)中的`state`备注 |
| ~~attribute~~(仅做历史性保留) | ~~num~~ | ~~稿件属性位配置~~ | 本字段已被删除<br />~~略,见[获取视频详细信息web端](/video/info.md#获取视频详细信息web端)中的`attribute`备注~~ |
| state | num | 视频状态 | 略,见[获取视频详细信息web端](../video/info.md#获取视频详细信息web端)中的`state`备注 |
| ~~attribute~~(仅做历史性保留) | ~~num~~ | ~~稿件属性位配置~~ | 本字段已被删除<br />~~略,见[获取视频详细信息web端](../video/info.md#获取视频详细信息web端)中的`attribute`备注~~ |
| duration | num | 视频总计持续时长所有分P | 单位为秒 |
| rights | obj | 视频属性标志 | 略,见[获取视频详细信息web端](/video/info.md#获取视频详细信息web端)中的`rights`对象 |
| owner | obj | 视频UP主信息 | 略,见[获取视频详细信息web端](/video/info.md#获取视频详细信息web端)中的`owner`对象 |
| stat | obj | 视频状态数 | 略,见[获取视频详细信息web端](/video/info.md#获取视频详细信息web端)中的`stat`对象 |
| rights | obj | 视频属性标志 | 略,见[获取视频详细信息web端](../video/info.md#获取视频详细信息web端)中的`rights`对象 |
| owner | obj | 视频UP主信息 | 略,见[获取视频详细信息web端](../video/info.md#获取视频详细信息web端)中的`owner`对象 |
| stat | obj | 视频状态数 | 略,见[获取视频详细信息web端](../video/info.md#获取视频详细信息web端)中的`stat`对象 |
| dynamic | str | 视频同步发布的的动态的文字内容 | 无为空 |
| cid | num | 视频1P cid | |
| dimension | obj | 视频1P分辨率 | 略,见[获取视频详细信息web端](/video/info.md#获取视频详细信息web端)中的`dimension`对象 |
| dimension | obj | 视频1P分辨率 | 略,见[获取视频详细信息web端](../video/info.md#获取视频详细信息web端)中的`dimension`对象 |
| bangumi | obj | 番剧/影视信息 | 非番剧/影视无此项 |
| cheese | obj | 课程信息 | 非课程无此项 |
| favorite | bool | 是否已收藏 | true已收藏<br />false未收藏 |

View File

@ -1,6 +1,6 @@
# 稍后再看
<img src="/imgs/toview.png" width="25" height="20"/>
<img src="../../assets/img/toview.png" width="25" height="20"/>
## 视频添加稍后再看
@ -170,14 +170,14 @@ curl 'https://space.bilibili.com/ajax/channel/addAllToView' \
| pubdate | num | 稿件发布时间 | 时间戳 |
| ctime | num | 用户提交稿件的时间 | 时间戳 |
| desc | str | 视频简介 | |
| state | num | 视频状态 | 略,见[获取视频详细信息web端](/video/info.md#获取视频详细信息web端)中的`state`备注 |
| ~~attribute~~(仅做历史性保留) | ~~num~~ | ~~稿件属性位配置~~ | 本字段已被删除~~略,见[获取视频详细信息web端](/video/info.md#获取视频详细信息web端)中的`attribute`备注~~ |
| state | num | 视频状态 | 略,见[获取视频详细信息web端](../video/info.md#获取视频详细信息web端)中的`state`备注 |
| ~~attribute~~(仅做历史性保留) | ~~num~~ | ~~稿件属性位配置~~ | 本字段已被删除~~略,见[获取视频详细信息web端](../video/info.md#获取视频详细信息web端)中的`attribute`备注~~ |
| duration | num | 稿件总时长所有分P | 单位为秒 |
| rights | obj | 稿件属性标志 | 略,见[获取视频详细信息web端](/video/info.md#获取视频详细信息web端)中的`rights`对象 |
| owner | obj | 稿件UP主信息 | 略,见[获取视频详细信息web端](/video/info.md#获取视频详细信息web端)中的`owner`对象 |
| stat | obj | 稿件状态数 | 略,见[获取视频详细信息web端](/video/info.md#获取视频详细信息web端)中的`stat`对象 |
| rights | obj | 稿件属性标志 | 略,见[获取视频详细信息web端](../video/info.md#获取视频详细信息web端)中的`rights`对象 |
| owner | obj | 稿件UP主信息 | 略,见[获取视频详细信息web端](../video/info.md#获取视频详细信息web端)中的`owner`对象 |
| stat | obj | 稿件状态数 | 略,见[获取视频详细信息web端](../video/info.md#获取视频详细信息web端)中的`stat`对象 |
| dynamic | str | 视频同步发布的的动态的文字内容 | 无为空 |
| dimension | obj | 稿件1P分辨率 | 略,见[获取视频详细信息web端](/video/info.md#获取视频详细信息web端)中的`dimension`对象 |
| dimension | obj | 稿件1P分辨率 | 略,见[获取视频详细信息web端](../video/info.md#获取视频详细信息web端)中的`dimension`对象 |
| count | num | 稿件分P数 | 非投稿视频无此项 |
| cid | num | 视频cid | |
| progress | num | 观看进度时间 | 单位为秒 |

View File

@ -15,8 +15,9 @@
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------- | ---- | ------------------------ | ------ | -------------------- |
| room_id | num | 直播间id | 必要 | 必须为自己的直播间id |
| title | str | 直播间标题 | 必要 | 最大20字符 |
| title | str | 直播间标题 | | 最大20字符 |
| csrf | str | CSRF Token位于cookie | 必要 | |
| csrf_token | str | CSRF Token位于 cookie | | |
**json回复**
@ -258,3 +259,174 @@ curl 'https://api.live.bilibili.com/room/v1/Room/stopLive' \
```
</details>
## 更新直播间公告
> https://api.live.bilibili.com/xlive/app-blink/v1/index/updateRoomNews
*请求方式POST*
认证方式CookieSESSDATA
鉴权方式Cookie中`bili_jct`的值正确并与`csrf`相同
**正文参数( application/x-www-form-urlencoded **
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------- | ---- | ------------------------ | ------ | --------------------- |
| room_id | num | 直播间id | 必要 | 必须为自己的直播间id |
| uid | num | 用户id | 必要 | |
| content | str | 公告内容 | 必要 | 最大60个字符,可以为空 |
| csrf | str | CSRF Token位于cookie | 必要 | |
| csrf_token | str | CSRF Token位于 cookie | | |
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | ----- | -------- | ------------------------------------------------------ |
| code | num | 返回值 | 0成功<br />65530token错误登录错误<br />1错误 |
| data | array | 空 | |
| message | str | 错误信息 | 默认为ok |
| ttl | num | 1 | 作用尚不明确 |
**示例:**
修改直播间`11996900`公告为`测试修改公告`
```shell
curl 'https://api.live.bilibili.com/xlive/app-blink/v1/index/updateRoomNews' \
--data-urlencode 'room_id=11996900' \
--data-urlencode 'uid=306903238' \
--data-urlencode 'content=测试修改公告' \
--data-urlencode 'csrf_token=xxx' \
--data-urlencode 'csrf=xxx' \
-b 'SESSDATA=xxx;bili_jct=xxx'
```
<details>
<summary>查看响应示例:</summary>
```json
{
"code": 0,
"message": "0",
"ttl": 1,
"data": {}
}
```
</details>
## 编辑直播间标签
> https://api.live.bilibili.com/room/v1/Room/update
*请求方式POST*
认证方式CookieSESSDATA
鉴权方式Cookie中`bili_jct`的值正确并与`csrf`相同
**正文参数( application/x-www-form-urlencoded **
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------- | ---- | ------------------------ | ------ | -------------------- |
| room_id | num | 直播间id | 必要 | 必须为自己的直播间id |
| add_tag | str | 要添加的标签 | 必要 | 最大10个字符 |
| del_tag | str | 要删除的标签 | 必要 | |
| csrf | str | CSRF Token位于cookie | 必要 | |
| csrf_token | str | CSRF Token位于 cookie | | |
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------------------------------------------------------ |
| code | num | 返回值 | 0成功<br />65530token错误登录错误<br />1错误 |
| data | obj | | |
| message | str | 错误信息 | 默认为ok |
| msg | str | 错误信息 | 默认为ok |
`data`对象:
| 字段 | 类型 | 内容 | 备注 |
| --------------- | ---- | ---- | ---- |
| audit_info | obj | | |
| sub_session_key | str | | |
`data`中的`audit_info`对象:
| 字段 | 类型 | 内容 | 备注 |
| ------------------ | ---- | ---- | ---- |
| audit_title_reason | str | | |
| audit_title_status | num | 0 | |
| update_title | str | | |
**示例:**
给直播间`11996900`添加一个标签为`测试标签`
```shell
curl 'https://api.live.bilibili.com/room/v1/Room/update' \
--data-urlencode 'room_id=11996900' \
--data-urlencode 'add_tag=测试标签' \
--data-urlencode 'csrf_token=xxx' \
--data-urlencode 'csrf=xxx' \
-b 'SESSDATA=xxx;bili_jct=xxx'
```
<details>
<summary>查看响应示例:</summary>
```json
{
"code": 0,
"msg": "ok",
"message": "ok",
"data": {
"sub_session_key": "",
"audit_info": {
"audit_title_reason": "",
"update_title": "",
"audit_title_status": 0
}
}
}
```
</details>
给直播间`11996900`删除内容为`测试标签`的标签
```shell
curl 'https://api.live.bilibili.com/room/v1/Room/update' \
--data-urlencode 'room_id=11996900' \
--data-urlencode 'del_tag=测试标签' \
--data-urlencode 'csrf_token=xxx' \
--data-urlencode 'csrf=xxx' \
-b 'SESSDATA=xxx;bili_jct=xxx'
```
<details>
<summary>查看响应示例:</summary>
```json
{
"code": 0,
"msg": "ok",
"message": "ok",
"data": {
"sub_session_key": "",
"audit_info": {
"audit_title_reason": "",
"update_title": "",
"audit_title_status": 0
}
}
}
```
</details>

View File

@ -44,6 +44,7 @@
| wss_port | num | wss端口 | |
| ws_port | num | ws端口 | |
**示例:**
获得直播间`22824550`的信息流认证秘钥
@ -94,6 +95,9 @@ curl -G 'https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo' \
</details>
**注:最终URI格式为 host+对应port+"/sub"**例如以上示例中一个可行的ws连接URI应当为`tx-sh-live-comet-02.chat.bilibili.com:2244/sub`
## 数据包格式
数据包为MQMessage Queue消息队列使用Websocket或TCP连接作为通道具体格式为头部数据+正文数据
@ -446,6 +450,73 @@ json格式
```
</details>
#### 连续弹幕消息
连续多条相同弹幕时触发
json格式
| 字段 | 类型 | 内容 | 备注 |
| ---- | ---- | ------ | --------- |
| cmd | str | "DM_INTERACTION" | 如果是进入直播间或关注消息,内容则是"INTERACT_WORD" |
| data | obj | 进入直播间的用户的信息 | |
data字段
| 字段 | 类型 | 内容 | 备注 |
| ---- | ---- | ------ | --------- |
| id | num | 事件ID | |
| status | num | 状态 | |
| type | num | 事件类型 | |
| data | str | 事件数据 | |
连续发送弹幕事件的data.data字段
| 字段 | 类型 | 内容 | 备注 |
| ---- | ---- | ------ | --------- |
| combo | array | 连续发送弹幕事件信息 | |
| merge_interval | num | 合并弹幕时间间隔 | |
| card_appear_interval | num | 弹窗出现时间间隔 | |
| send_interval | num | 发送时间间隔 | |
连续发送弹幕事件的data.data.combo字段
| 字段 | 类型 | 内容 | 备注 |
| ---- | ---- | ------ | --------- |
| id | num | 时间ID | |
| status | num | 状态 | |
| content | str | 重复的弹幕内容 | |
| cnt | num | 重复数量 | |
| guide | str | 标题词 | "他们都在说:" |
| left_duration | num | 左移时长 | |
| fade_duration | num | 淡化时长 | |
<details>
<summary>查看消息示例:</summary>
```json
{
'': 6785480089600,
'status': 4,
'type': 102,
'data': '{
"combo":[{
"id":6785480089600,
"status":4,
"content":"晚安",
"cnt":3,
"guide":"他们都在说:",
"left_duration":20000,
"fade_duration":60000}],
"merge_interval":1000,
"card_appear_interval":1000,
"send_interval":1000}'
}
```
</details>
#### 进场或关注消息
有用户进入直播间或关注主播时触发
@ -573,6 +644,85 @@ data字段
</details>
#### 用户庆祝消息
json格式
| 字段 | 类型 | 内容 | 备注 |
| ---- | ---- |------------------|----------------------------------|
| cmd | str | "USER_TOAST_MSG" | 用户购买舰长 / 提督 / 总督后的庆祝消息,内容包含用户陪伴天数 |
| data | obj | 上舰人uid & 昵称、上舰信息 | |
data字段
| 字段 | 类型 | 内容 | 备注 |
| ---- |-----|--------------------------|-----|
| anchor_show | bool | 是否显示 | |
| color | str | 颜色 | |
| dmscore | num | 待调查 | |
| effect_id | num | 待调查 | |
| face_effect_id | num | 待调查 | |
| gift_id | num | 礼物id | |
| group_name | str | 待调查 | |
| group_op_type | num | 待调查 | |
| group_role_name | str | 待调查 | |
| guard_level | num | 大航海等级 | 1: 总督 2: 提督 3:舰长 |
| is_group | num | 待调查 | |
| is_show | num | 待调查 | |
| num | num | 上舰个数 | |
| op_type | num | 待调查 | |
| payflow_id | str | 待调查 | |
| price | num | 价格 |
| role_name | str | 身份名称 | |
| room_effect_id | num | 待调查 | |
| room_group_effect_id | num | 待调查 | |
| start_time | num | 待调查 | |
| svga_block | num | 待调查 | |
| target_guard_count | str | 庆祝消息正文 | |
| toast_msg | num | 待调查 | |
| uid | num | 上舰人UID | |
| unit | str | 购买身份时间单位 | |
| user_show | bool | 待调查 | |
| username | str | 上舰人用户名 | |
<details>
<summary>查看消息示例:</summary>
```json
{
'anchor_show': True,
'color': '#00D1F1',
'dmscore': 90,
'effect_id': 397,
'end_time': 1702580687,
'face_effect_id': 44,
'gift_id': 10003,
'group_name': '',
'group_op_type': 0,
'group_role_name': '',
'guard_level': 3,
'is_group': 0,
'is_show': 0,
'num': 1,
'op_type': 1,
'payflow_id':'2312150304155852173446521',
'price': 138000,
'role_name': '舰长',
'room_effect_id': 590,
'room_group_effect_id': 1337,
'start_time': 1702580687,
'svga_block': 0,
'target_guard_count': 146,
'toast_msg': '<%无光之日%> 在主播Mia米娅-的直播间开通了舰长今天是TA陪伴主播的第1天',
'uid': 79667344,
'unit': '月',
'user_show': True,
'username': '无光之日'}
```
</details>
#### 醒目留言
json格式
@ -604,7 +754,7 @@ data字段
| medal_info | obj | SC发送用户佩戴的粉丝牌信息 | |
| message | str | sc内容 | |
| message_font_color | str | SC文本颜色 | |
| message_trans | str | 待调查 | |
| message_trans | str | 机翻sc内容 | |
| price | num | sc金额 | |
| rate | num | 待调查 | |
| start_time | num | 待调查 | |
@ -1085,12 +1235,6 @@ json格式
| ---- | ---- | ------ | --------- |
| cmd | str | "NOTICE_MSG" | 通知消息,内容则是"NOTICE_MSG" |
| id | num | 待调查 | |
| data | obj | 通知数据 | |
data字段
| 字段 | 类型 | 内容 | 备注 |
| ---- | ---- | ------ | --------- |
| full | obj | 待调查 | |
| half | obj | 待调查 | |
| side | obj | 待调查 | |
@ -1265,6 +1409,7 @@ data字段
"fans_club": 8
}
}
```
</details>
#### 直播间高能榜
@ -1409,6 +1554,44 @@ list数组中的对象
</details>
#### 直播间在人气榜的排名改变
json格式
| 字段 | 类型 | 内容 | 备注 |
| ---- | ---- | ------ | --------- |
| cmd | str | "POPULAR_RANK_CHANGED" | |
| data | obj | 直播间的人气榜排名信息 | |
data字段
| 字段 | 类型 | 内容 | 备注 |
| ---- | ---- | ------ | --------- |
| uid | num | 主播UID | |
| rank | num | 人气榜排名 | |
| countdown | num | 人气榜下轮结算剩余时长 | |
| timestamp | num | 触发时的Unix时间戳 | |
| timestamp | str | 待调查 | |
<details>
<summary>查看消息示例:</summary>
```json
{
'cmd': 'POPULAR_RANK_CHANGED',
'data': {
'uid': 780791,
'rank': 36,
'countdown': 1927,
'timestamp': 1702578474,
'cache_key': 'rank_change:91a4e81ba3034ae894d61e432aa13081'
}
}
```
</details>
#### 直播间用户点赞
json格式

View File

@ -0,0 +1,218 @@
# 直播间禁言相关 API
## 禁言观众
> https://api.live.bilibili.com/xlive/web-ucenter/v1/banned/AddSilentUser
*请求方式post*
认证方式CookieSESSDATA
鉴权方式Cookie中`bili_jct`的值正确并与`csrf`相同
**正文参数( application/x-www-form-urlencoded **
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ---------- | --- | ---------- | --- | ------------------ |
| room_id | str | 直播间Id | 必要 | |
| tuid | str | 要禁言的uid | 必要 | |
| msg | str | 要禁言的弹幕内容 | 非必要 | |
| mobile_app | str | web | 必要 | 定值"web"即可 |
| csrf_token | str | CSRF Token | 必要 | cookie中的bili_jct字段 |
| csrf | str | CSRF Token | 必要 | cookie中的bili_jct字段 |
| visit_id | str | 不明 | 非必要 | |
**json 回复:**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | --- | ---- | ------- |
| code | num | 返回值 | 0成功 |
| message | str | 错误信息 | 默认为 "0" |
| ttl | str | 1 | |
| data | obj | 信息本体 | 成功为空 |
**示例:**
```shell
curl -X POST 'https://api.live.bilibili.com/xlive/web-ucenter/v1/banned/AddSilentUser' \
--data-urlencode 'room_id=xxxxxx' \
--data-urlencode 'tuid=xxx' \
--data-urlencode 'msg=xxxx' \
--data-urlencode 'mobile_app=web' \
--data-urlencode 'csrf_token=xx' \
--data-urlencode 'csrf=xx' \
--data-urlencode 'visit_id=' \
-H 'Content-Type:application/x-www-form-urlencoded' \
-b 'SESSDATA=xxx; bili_jct=xx;'
```
<details>
<summary>查看响应示例:</summary>
```json
{"code":0,"message":"0","ttl":1,"data":{}}
```
</details>
## 查询直播间禁言列表
> https://api.live.bilibili.com/xlive/web-ucenter/v1/banned/GetSilentUserList
*请求方式post*
认证方式CookieSESSDATA
鉴权方式Cookie中`bili_jct`的值正确并与`csrf`相同
**正文参数( application/x-www-form-urlencoded **
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ---------- | --- | ---------- | --- | ------------------ |
| room_id | str | 直播间Id | 必要 | |
| ps1 | str | 列表页码 | 必要 | |
| csrf_token | str | CSRF Token | 必要 | cookie中的bili_jct字段 |
| csrf | str | CSRF Token | 必要 | cookie中的bili_jct字段 |
| visit_id | str | 不明 | 非必要 | |
**json 回复:**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | --- | ---- | ------- |
| code | num | 返回值 | 0成功 |
| message | str | 错误信息 | 默认为 "0" |
| ttl | str | 1 | |
| data | obj | 信息本体 | |
`data`对象:
| 字段 | 类型 | 内容 | 备注 |
| ---------- | ----- | ------ | ------- |
| data | array | 禁言列表 | 数组中为obj |
| total | int | 禁言观众数量 | |
| total_page | int | 页码总数量 | |
`data`对象中`data`数组的元素对象:
| 字段 | 类型 | 内容 | 备注 |
| ----------- | --- | ------ | --------- |
| tuid | num | 禁言者uid | |
| tname | str | 禁言者昵称 | |
| uid | num | 发起者uid | |
| name | str | 发起者昵称 | |
| ctime | str | 禁言时间 | |
| id | num | 禁言记录Id | 解除禁言时用到 |
| is_anchor | num | 不明 | |
| face | str | 禁言者头像 | |
| admin_level | num | 发起者权限 | 0:主播1:房管 |
**示例:**
```shell
curl -X POST 'https://api.live.bilibili.com/xlive/web-ucenter/v1/banned/GetSilentUserList' \
--data-urlencode 'room_id=xxxxxxx' \
--data-urlencode 'ps=1' \
--data-urlencode 'csrf_token=xxx' \
--data-urlencode 'csrf=xxx' \
--data-urlencode 'visit_id=' \
-H 'Content-Type:application/x-www-form-urlencoded' \
-b 'SESSDATA=xxxx; bili_jct=xxx;'
```
<details>
<summary>查看响应示例:</summary>
```json
{
"code":0,
"message":"0",
"ttl":1,
"data":{
"data":[
{
"tuid":123456,
"tname":"xxxxx",
"uid":123456,
"name":"xxxx",
"ctime":"2023-12-15 16:32:46",
"id":13493921,
"is_anchor":0,
"face":"https://i1.hdslb.com/bfs/face/xxxxx.jpg",
"admin_level":1
},
{
"tuid":123456,
"tname":"xx",
"uid":123456,
"name":"xxxx",
"ctime":"2021-08-23 22:26:06",
"id":8018136,
"is_anchor":1,
"face":"https://i1.hdslb.com/bfs/face/xxxxxx.jpg",
"admin_level":0
}
],
"total":2,
"total_page":1
}
}
```
</details>
## 解除禁言
> https://api.live.bilibili.com/banned_service/v1/Silent/del_room_block_user
*请求方式post*
认证方式CookieSESSDATA
鉴权方式Cookie中`bili_jct`的值正确并与`csrf`相同
**正文参数( application/x-www-form-urlencoded **
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ---------- | --- | ---------- | --- | ---------------------- |
| roomid | str | 直播间Id | 必要 | 注意该接口名称没有“_” |
| id | str | 禁言记录Id | 必要 | GetSilentUserList 接口获取 |
| csrf_token | str | CSRF Token | 必要 | cookie中的bili_jct字段 |
| csrf | str | CSRF Token | 必要 | cookie中的bili_jct字段 |
| visit_id | str | 不明 | 非必要 | |
**json 回复:**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | --- | ---- | ---- |
| code | num | 返回值 | 0成功 |
| message | str | 错误信息 | 成功为空 |
| ttl | str | 1 | |
| data | obj | 信息本体 | 成功为空 |
**示例:**
```shell
curl -X POST 'https://api.live.bilibili.com/banned_service/v1/Silent/del_room_block_user' \
--data-urlencode 'roomid=xxxxxxxxx' \
--data-urlencode 'id=xxxxx' \
--data-urlencode 'csrf_token=xxx' \
--data-urlencode 'csrf=xxx' \
--data-urlencode 'visit_id=' \
-H 'Content-Type:application/x-www-form-urlencoded' \
-b 'SESSDATA=xxxxxx; bili_jct=xxx;'
```
<details>
<summary>查看响应示例:</summary>
```json
{"code":0,"msg":"","message":"","data":[]}
```
</details>

View File

@ -24,7 +24,7 @@
| ------- | ---- | -------- | ------------------------------------------------- |
| code | num | 返回值 | 0成功<br>-1002002参数异常<br>-500服务器异常 |
| message | str | 错误信息 | 默认为 "0" |
| ttl | str | 1 | |
| ttl | num | 1 | |
| data | obj | 信息本体 | |
`data`对象:
@ -137,7 +137,7 @@ curl https://api.live.bilibili.com/xlive/app-ucenter/v1/user/GetMyMedals?page=1&
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | -------------- |
| code | num | 返回值 | 0成功 |
| ttl | str | 1 | |
| ttl | num | 1 | |
| message | str | 错误信息 | 默认为佩戴成功 |
| data | obj | 信息本体 | 默认为无 |
@ -196,7 +196,7 @@ _请求方式GET_
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ---------------------- |
| code | num | 返回值 | 0成功<br>1参数错误 |
| ttl | str | 1 | |
| ttl | num | 1 | |
| message | str | 错误信息 | 默认为当日签到奖励内容 |
| data | obj | 信息本体 | 默认为空 |
@ -215,7 +215,7 @@ _请求方式GET_
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ---------------------- |
| code | num | 返回值 | 0成功 |
| ttl | str | 1 | |
| ttl | num | 1 | |
| message | str | 错误信息 | 默认为0 |
| data | obj | 信息本体 | |
@ -294,7 +294,7 @@ _请求方式GET_
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ---------------------- |
| code | num | 返回值 | 0成功 |
| ttl | str | 1 | |
| ttl | num | 1 | |
| message | str | 错误信息 | 默认为0 |
| data | obj | 信息本体 | |

View File

@ -0,0 +1,511 @@
# Web端Cookie刷新
自从 2023 以来,社区反馈似乎 Web 端的 Cookie 会随着一些敏感接口的访问逐渐失效,而在 Web 页面上会判断 Cookie 是否需要刷新,如需刷新则会以动态加载 iframe 方式实现,同时登录(二维码 / 密码 / 短信验证码等)接口也会返回`refresh_token`字段,需要持久化保存,是一种官方的风控机制实现
感谢 [#524](https://github.com/SocialSisterYi/bilibili-API-collect/issues/524) 提供相关研究报告以及逆向工程结果
> cookie 不会主动刷新的,只要他没有调用下面的刷新接口就不会刷新。也就是说,你只要不再打开浏览器,或者直接把 localStorage 的 ac_time_value 字段删除了。那么 cookie 在真的失效前(登录过期、账号风控等强制下线)都是不变化的。
## 刷新步骤(伪代码)
```python
cookie, refresh_token = 进行登录操作() # can be 二维码 / 密码 / 短信验证码
while True:
if 每日第一次访问接口:
if 检查是否需要刷新(cookie):
CorrespondPath = 生成CorrespondPath(当前毫秒时间戳)
refresh_csrf = 获取refresh_csrf(CorrespondPath, cookie)
refresh_token_old = refresh_token # 这一步必须保存旧的 refresh_token 备用
cookie, refresh_token = 刷新Cookie(refresh_token, refresh_csrf, cookie)
确认更新(refresh_token_old, cookie) # 这一步需要新的 Cookie 以及旧的 refresh_token
SSO站点跨域登录(cookie)
do_somethings(cookie) # 其他业务逻辑处理
```
## 检查是否需要刷新
> https://passport.bilibili.com/x/passport-login/web/cookie/info
*请求方式GET*
鉴权方式Cookie
**url 参数:**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------ | ---- | ------------------------- | ------ | ---- |
| csrf | str | CSRF Token位于 Cookie | 非必要 | 位于 Cookie 中的bili_jct字段 |
**json 回复:**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ----------------------------- |
| code | num | 返回值 | 0成功<br />-101账号未登录 |
| message | str | 错误信息 | 默认为 0 |
| ttl | num | 1 | |
| data | obj | 信息本体 | |
`data`对象:
| 字段 | 类型 | 内容 | 备注 |
| --------- | ---- | ------------------- | ----------------------------------------------------- |
| refresh | bool | 是否应该刷新 Cookie | `true`:需要刷新 Cookie<br />`false`:无需刷新 Cookie |
| timestamp | num | 当前毫秒时间戳 | 用于获取 refresh_csrf |
**示例:**
```bash
curl -G 'https://passport.bilibili.com/x/passport-login/web/cookie/info' \
--data-urlencode 'csrf=xxx' \
-b 'SESSDATA=xxx'
```
<details>
<summary>查看响应示例:</summary>
```json
{
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"refresh": false,
"timestamp": 1684466082562
}
}
```
</details>
## 生成CorrespondPath算法
该算法逆向于以下 wasm 以及 JavaScript bind 接口,抓取于官方 Web 首页中,感谢 [#524](https://github.com/SocialSisterYi/bilibili-API-collect/issues/524) 提供
https://s1.hdslb.com/bfs/static/jinkela/long/wasm/wasm_rsa_encrypt_bg.wasm
https://s1.hdslb.com/bfs/static/jinkela/long/wasm/wasm_ras_umd.js
### 算法细节
将`refresh_${timestamp}`作为消息体(参数`timestamp`为当前毫秒时间戳),用下方 PubKey 进行 [RSA-OAEP](https://datatracker.ietf.org/doc/html/rfc3447#section-7.1) 算法加密,之后密文通过小写 Base16 编码为字符串
JWK 格式:
> {
> "kty": "RSA",
> "n": "y4HdjgJHBlbaBN04VERG4qNBIFHP6a3GozCl75AihQloSWCXC5HDNgyinEnhaQ_4-gaMud_GF50elYXLlCToR9se9Z8z433U3KjM-3Yx7ptKkmQNAMggQwAVKgq3zYAoidNEWuxpkY_mAitTSRLnsJW-NCTa0bqBFF6Wm1MxgfE",
> "e": "AQAB"
> }
PEM 格式:
> -----BEGIN PUBLIC KEY-----
> MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLgd2OAkcGVtoE3ThUREbio0Eg
> Uc/prcajMKXvkCKFCWhJYJcLkcM2DKKcSeFpD/j6Boy538YXnR6VhcuUJOhH2x71
> nzPjfdTcqMz7djHum0qSZA0AyCBDABUqCrfNgCiJ00Ra7GmRj+YCK1NJEuewlb40
> JNrRuoEUXpabUzGB8QIDAQAB
> -----END PUBLIC KEY-----
### 相关Demo
该 Demo 提供 [JavaScript](#JavaScript)、[Python](#Python) 以及 [Vercel 云函数](#vercel云函数),感谢 [#524](https://github.com/SocialSisterYi/bilibili-API-collect/issues/524) 提供
#### JavaScript
```javascript
const publicKey = await crypto.subtle.importKey(
"jwk",
{
kty: "RSA",
n: "y4HdjgJHBlbaBN04VERG4qNBIFHP6a3GozCl75AihQloSWCXC5HDNgyinEnhaQ_4-gaMud_GF50elYXLlCToR9se9Z8z433U3KjM-3Yx7ptKkmQNAMggQwAVKgq3zYAoidNEWuxpkY_mAitTSRLnsJW-NCTa0bqBFF6Wm1MxgfE",
e: "AQAB",
},
{ name: "RSA-OAEP", hash: "SHA-256" },
true,
["encrypt"],
)
async function getCorrespondPath(timestamp) {
const data = new TextEncoder().encode(`refresh_${timestamp}`);
const encrypted = new Uint8Array(await crypto.subtle.encrypt({ name: "RSA-OAEP" }, publicKey, data))
return encrypted.reduce((str, c) => str + c.toString(16).padStart(2, "0"), "")
}
const ts = Date.now()
console.log(await getCorrespondPath(ts))
```
```
b77f21ab5b7ce7879c410b2311dd6e7ea1a2cd1cd941073db067f4c3279fdabca3a06dfa744168ee14ad050b9f4889bd4edb8e76eb597fdd18c16804d82566b55c6dba8e225d838aa93d8e5b31cf7c56720db8244d92373f4944e0561f6ca5bf721a36ac079786060fc853605ccd1ddcb33f54617de6aedd44e3b9850d13b45f
```
#### Python
需要`pycryptodome`依赖
```python
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA256
import binascii
import time
key = RSA.importKey('''\
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLgd2OAkcGVtoE3ThUREbio0Eg
Uc/prcajMKXvkCKFCWhJYJcLkcM2DKKcSeFpD/j6Boy538YXnR6VhcuUJOhH2x71
nzPjfdTcqMz7djHum0qSZA0AyCBDABUqCrfNgCiJ00Ra7GmRj+YCK1NJEuewlb40
JNrRuoEUXpabUzGB8QIDAQAB
-----END PUBLIC KEY-----''')
def getCorrespondPath(ts):
cipher = PKCS1_OAEP.new(key, SHA256)
encrypted = cipher.encrypt(f'refresh_{ts}'.encode())
return binascii.b2a_hex(encrypted).decode()
ts = round(time.time() * 1000)
print(getCorrespondPath(ts))
```
```
47bbd615f333d6a2c597bbb46ad47a6e59752a305a2f545d3ba5d49ca055309347796f80d257613696d36170c57443a0e9dea2b47f83b0b4224d431e46124fadd9a24c8fa468147e8bf2d2501eaacae43310e19bf58fc4a728d80c90b9401afcfc1536ba9a2f6438ea53c0b2652f8b8d01c87355dd5a5da51de998b1a35d519a
```
### Kotlin
```kotlin
import java.security.KeyFactory
import java.security.spec.MGF1ParameterSpec
import java.security.spec.X509EncodedKeySpec
import java.util.*
import javax.crypto.Cipher
import javax.crypto.spec.OAEPParameterSpec
import javax.crypto.spec.PSource
fun main() {
println(getCorrespondPath(System.currentTimeMillis()))
}
fun getCorrespondPath(timestamp: Long): String {
val publicKeyPEM = """
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLgd2OAkcGVtoE3ThUREbio0Eg
Uc/prcajMKXvkCKFCWhJYJcLkcM2DKKcSeFpD/j6Boy538YXnR6VhcuUJOhH2x71
nzPjfdTcqMz7djHum0qSZA0AyCBDABUqCrfNgCiJ00Ra7GmRj+YCK1NJEuewlb40
JNrRuoEUXpabUzGB8QIDAQAB
-----END PUBLIC KEY-----
""".trimIndent()
val publicKey = KeyFactory.getInstance("RSA").generatePublic(
X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyPEM
.replace("-----BEGIN PUBLIC KEY-----", "")
.replace("-----END PUBLIC KEY-----", "")
.replace("\n", "")
.trim()))
)
val cipher = Cipher.getInstance("RSA/ECB/OAEPPadding").apply {
init(Cipher.ENCRYPT_MODE,
publicKey,
OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT)
)
}
return cipher.doFinal("refresh_$timestamp".toByteArray()).joinToString("") { "%02x".format(it) }
}
```
```
1428cbd14605ae42a0b42e22662cfe51d8e5034eeaffb36a46db46bd2f93216cbfd4d150cca2de44395add7c664b40acf44424ee8d634fc821b909423665a34d18bd7f4e77ea5388a2b612daf875e2fe8df62990e14b64a465898b0707bc1288586b68f9f4f2f20bea5cb1cada296beb8009e91bc8fb57a4b81b8923299b6eb7
```
### Go
```go
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/hex"
"encoding/pem"
"fmt"
"time"
)
func main() {
result, err := getCorrespondPath(time.Now().UnixMilli())
if err != nil {
panic(err)
}
fmt.Println(result)
}
func getCorrespondPath(ts int64) (string, error) {
const publicKeyPEM = `
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLgd2OAkcGVtoE3ThUREbio0Eg
Uc/prcajMKXvkCKFCWhJYJcLkcM2DKKcSeFpD/j6Boy538YXnR6VhcuUJOhH2x71
nzPjfdTcqMz7djHum0qSZA0AyCBDABUqCrfNgCiJ00Ra7GmRj+YCK1NJEuewlb40
JNrRuoEUXpabUzGB8QIDAQAB
-----END PUBLIC KEY-----
`
pubKeyBlock, _ := pem.Decode([]byte(publicKeyPEM))
hash := sha256.New()
random := rand.Reader
msg := []byte(fmt.Sprintf("refresh_%d", ts))
var pub *rsa.PublicKey
pubInterface, parseErr := x509.ParsePKIXPublicKey(pubKeyBlock.Bytes)
if parseErr != nil {
return "", parseErr
}
pub = pubInterface.(*rsa.PublicKey)
encryptedData, encryptErr := rsa.EncryptOAEP(hash, random, pub, msg, nil)
if encryptErr != nil {
return "", encryptErr
}
return hex.EncodeToString(encryptedData), nil
}
```
```
97759947aa357ed5d88cf9bf1172737570b7bba2d6788d39006f082b2b25ddf53b581f1f0c61ed8573317485ef525d2789faa25a277b4602a4b9cbf837681093a03e96cb9773a11df4bb1e20f1587180b3e958194de922d7dd94d0a2f0b9b0ef74e426e8041f99b99e7c02407ef4ab38040e61be81e4fdfbdb73461e3a2ad810
```
#### vercel云函数
```bash
curl -G 'https://wasm-rsa.vercel.app/api/rsa' \
--data-urlencode "t=$((`date '+%s'`*1000+`date '+%N'`/1000000))"
```
```json
{
"timestamp": "1684468084078",
"hash": "a768efe5114ef8610f9ed9ebc28c00827375f4a3448ec4ab17958cacc4fde9898e5b7aa27f649426bba1acae4aa222aafaff7d528669b15249de0b2b60d86618557d8dc90684db4ec68e8d98e41d94f1c97d1d431c288e595ceb522d033822442a9e1ee150b32771a83fbf65c13329e9fda080fbe3bc85c49c1de7ab148d228f",
"code": 0
}
```
## 获取refresh_csrf
> https://www.bilibili.com/correspond/1/{correspondPath}
*请求方式GET*
鉴权方式Cookie
**path 参数:**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| -------------- | ---- | ---------------------------- | ------ | ------------------------------------------------------------ |
| correspondPath | str | 使用当前毫秒时间戳生成的签名 | 必要 | 由 [生成CorrespondPath算法](#生成CorrespondPath算法) 加密获得 |
将参数`correspondPath`拼接在 https://www.bilibili.com/correspond/1/ 后进行请求,例如
> https://www.bilibili.com/correspond/1/0248397e5139a8b878894cae46f8d6742ef7c728e46403706452b5dda90fe248e58e73bd6c2da0dba515c53af107dc1ecda757ce843579bcf197fcd7800586126e9b896b646cc94c23183a5a067642e96f7b6e803880e1d3cceabc9f1dc52a121b5e3ba5619e008f6b6dcb65a09d7864084ac114f4ec9ccf6218776fe4f2fa95
请求该 url 会返回一个 html 页面,通常由 iframe 方式加载,它通过 SSR 方式返回一个实时刷新口令`refresh_csrf`存放于 html 标签中,并在 Client 端通过 js 请求 RestAPI 完成一些列的提交刷新、确认、SSO 站点登录等操作
若参数`correspondPath`错误或过期,则返回一个 404 Page
以下为返回的参数:
| 标签 id | 内容 | xpath | 备注 |
| ------- | ------------ | ------------------------- | --------------------------------- |
| 1-name | refresh_csrf | //div[id='1-name']/text() | 实时刷新口令<br />用于更新 Cookie |
**示例:**
```bash
correspondPath='0248397e5139a8b878894cae46f8d6742ef7c728e46403706452b5dda90fe248e58e73bd6c2da0dba515c53af107dc1ecda757ce843579bcf197fcd7800586126e9b896b646cc94c23183a5a067642e96f7b6e803880e1d3cceabc9f1dc52a121b5e3ba5619e008f6b6dcb65a09d7864084ac114f4ec9ccf6218776fe4f2fa95'
curl -G "https://www.bilibili.com/correspond/1/$correspondPath" \
-b 'SESSDATA=xxx'
```
```html
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
<meta name="spm_prefix" content="333.1193">
<link
href="//s1.hdslb.com/bfs/static/jinkela/token-iframe/css/token-iframe.1.a035e81c3bee5fa1a05633ad534ad1f44b05e54d.css"
rel="stylesheet">
</head>
<title>Correspond</title>
<script type="text/javascript"
src="//www.bilibili.com/gentleman/polyfill.js?features=Promise%2CObject.assign%2CString.prototype.includes%2CNumber.isNaN2%CglobalThis"></script>
<body>
<div id="1-name">b0cc8411ded2f9db2cff2edb3123acac</div>
<div id="token-iframe-app"></div>
<script type="text/javascript"
src="//s1.hdslb.com/bfs/static/jinkela/token-iframe/2.token-iframe.a035e81c3bee5fa1a05633ad534ad1f44b05e54d.js"></script>
<script type="text/javascript"
src="//s1.hdslb.com/bfs/static/jinkela/token-iframe/token-iframe.a035e81c3bee5fa1a05633ad534ad1f44b05e54d.js"></script>
</body>
<script type="text/javascript">window.reportMsgObj = {};
window.reportConfig = {
sample: 1,
scrollTracker: true,
msgObjects: 'reportMsgObj',
};
let reportScript = document.createElement('script');
reportScript.src = '//s1.hdslb.com/bfs/seed/log/report/log-reporter.js';
document.getElementsByTagName('body')[0].appendChild(reportScript);</script>
</html>
```
所以当前账号的实时刷新口令`refresh_csrf`为`b0cc8411ded2f9db2cff2edb3123acac`
## 刷新Cookie
> https://passport.bilibili.com/x/passport-login/web/cookie/refresh
*请求方式POST*
鉴权方式Cookie
刷新成功后会设置以下 Cookie 项:
`sid`、`DedeUserID`、`DedeUserID__ckMd5`、`SESSDATA`、`bili_jct`
**正文参数 (application/x-www-form-urlencoded)或 url 参数:**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------------- | ---- | -------------- | ------ | ------------------------------------------------------------ |
| csrf | str | CSRF Token | 必要 | 位于 Cookie 中的`bili_jct`字段 |
| refresh_csrf | str | 实时刷新口令 | 必要 | 通过 [获取refresh_csrf](#获取refresh_csrf) 获得 |
| source | str | 访问来源? | 必要 | 一般为`main_web` |
| refresh_token | str | 持久化刷新口令 | 必要 | localStorage 中的`ac_time_value`字段,在登录成功后返回并保存 |
**json 回复:**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------------------------------------------------------------ |
| code | num | 返回值 | 0成功<br />-101账号未登录<br />-111csrf 校验失败<br />86095refresh_csrf 错误或 refresh_token 与 cookie 不匹配 |
| message | str | 错误信息 | 默认为 0 |
| ttl | num | 1 | |
| data | obj | 信息本体 | |
`data`对象:
| 字段 | 类型 | 内容 | 备注 |
| ------------- | ---- | ------------------ | ----------------------------------------------------------- |
| status | num | 0 | |
| message | str | 空 | |
| refresh_token | str | 新的持久化刷新口令 | 将存储于 localStorage 中的`ac_time_value`字段,以便下次使用 |
**示例:**
```bash
curl -i 'https://passport.bilibili.com/x/passport-login/web/cookie/refresh' \
--data-urlencode 'csrf=f610640a37f51f6266f6b83cfc5eedbb' \
--data-urlencode 'refresh_csrf=b0cc8411ded2f9db2cff2edb3123acac' \
--data-urlencode 'source=main_web' \
--data-urlencode 'refresh_token=45240a041836905fe953e3b98b83d751' \
-b 'SESSDATA=xxx'
```
<details>
<summary>查看响应示例:</summary>
http 响应(关键信息已做脱敏处理):
```http
HTTP/2 200
date: Fri, 19 May 2023 07:34:11 GMT
content-type: application/json; charset=utf-8
content-length: 116
bili-status-code: 0
bili-trace-id: 17f4251365646726
set-cookie: SESSDATA=***; Path=/; Domain=bilibili.com; Expires=Wed, 15 Nov 2023 07:34:10 GMT; HttpOnly; Secure
set-cookie: bili_jct=***; Path=/; Domain=bilibili.com; Expires=Wed, 15 Nov 2023 07:34:10 GMT
set-cookie: DedeUserID=***; Path=/; Domain=bilibili.com; Expires=Wed, 15 Nov 2023 07:34:10 GMT
set-cookie: DedeUserID__ckMd5=***; Path=/; Domain=bilibili.com; Expires=Wed, 15 Nov 2023 07:34:10 GMT
set-cookie: sid=***; Path=/; Domain=bilibili.com; Expires=Wed, 15 Nov 2023 07:34:10 GMT
x-bili-trace-id: 3f6f6174aaa087b517f4251365646726
expires: Fri, 19 May 2023 07:34:10 GMT
cache-control: no-cache
x-cache-webcdn: BYPASS from blzone03
{"code":0,"message":"0","ttl":1,"data":{"status":0,"message":"","refresh_token":"ae1bd1149b56af9743ffe7bbbeff3e51"}}
```
JSON Payload
```json
{
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"status": 0,
"message": "",
"refresh_token": "ae1bd1149b56af9743ffe7bbbeff3e51"
}
}
```
</details>
## 确认更新
> https://passport.bilibili.com/x/passport-login/web/confirm/refresh
*请求方式POST*
鉴权方式Cookie
该步操作将让旧的`refresh_token`对应的 Cookie 失效
**正文参数 (application/x-www-form-urlencoded)或 url 参数:**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------------- | ---- | ------------------------- | ------ | ------------------------------------------------------------ |
| csrf | str | CSRF Token位于 cookie | 必要 | 从新的 cookie 中获取,位于 Cookie 中的`bili_jct`字段 |
| refresh_token | str | 旧的持久化刷新口令 | 必要 | 在刷新前 localStorage 中的`ac_time_value`获取,**并非刷新后返回的值** |
**json 回复:**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------------------------------------------------------------ |
| code | num | 返回值 | 0成功<br />-101账号未登录<br />-111csrf 校验失败<br />-400请求错误 |
| message | str | 错误信息 | 默认为 0 |
| ttl | num | 1 | |
**示例:**
```bash
curl 'https://passport.bilibili.com/x/passport-login/web/confirm/refresh' \
--data-urlencode 'csrf=1e9658858e6da76be64bd92cdc0fa324' \
--data-urlencode 'refresh_token=45240a041836905fe953e3b98b83d751' \
-b 'SESSDATA=xxx'
```
<details>
<summary>查看响应示例:</summary>
```json
{
"code": 0,
"message": "0",
"ttl": 1
}
```
</details>

View File

@ -83,18 +83,19 @@ curl 'https://passport.bilibili.com/x/passport-login/web/qrcode/generate'
*请求方式GET*
**url参数**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|------------|-----|--------|-----|-----|
| qrcode_key | str | 扫码登录秘钥 | 必要 | |
密钥超时为180秒
验证登录成功后会进行设置以下cookie项
`DedeUserID` `DedeUserID__ckMd5` `SESSDATA` `bili_jct`
**url参数**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|------------|-----|--------|-----|-----|
| qrcode_key | str | 扫码登录秘钥 | 非必要 | |
**json回复**
根对象:
@ -243,7 +244,7 @@ x-cache-webcdn: BYPASS from blzone02
## web端扫码登录-旧版
以下为旧版扫码登录 API可正常访问
以下为旧版扫码登录 API部分可正常访问
### 申请二维码(web端-旧版)
@ -298,10 +299,15 @@ curl 'https://passport.bilibili.com/qrcode/getLoginUrl'
### 扫码登录(web端-旧版)
> https://passport.bilibili.com/qrcode/getLoginInfo
**接口已失效,请求结果始终为 `{ code: 20000, message: '该版本已不支持当前功能,请升级新版本!' }`**
> ~~https://passport.bilibili.com/qrcode/getLoginInfo~~
*请求方式POST*
<details>
<summary>内容已过时:</summary>
密钥超时为180秒
验证登录成功后会进行设置以下cookie项
@ -321,7 +327,7 @@ curl 'https://passport.bilibili.com/qrcode/getLoginUrl'
| 字段 | 类型 | 内容 | 备注 |
|---------|----------------------|---------------------------|---------------------------------------------------------|
| code | num | 返回值 | 0成功 |
| code | num | 返回值 | 0成功<br />20000该版本已不支持当前功能请升级新版本 |
| message | str | | 正确无 |
| ts | num | 扫码时间 | 错误无 |
| status | bool | 扫码是否成功 | true成功<br />false未成功 |
@ -417,6 +423,8 @@ X-Cache-Webcdn: BYPASS from ks-sxhz-dx-w-01
</details>
</details>
## TV端扫码登录
### 申请二维码(TV端)
@ -437,8 +445,8 @@ X-Cache-Webcdn: BYPASS from ks-sxhz-dx-w-01
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| -------- | ---- | ---------- | ------------ | -------------------------- |
| appkey | str | APP 密钥 | APP 方式必要 | 仅可用`4409e2ce8ffd12b8` |
| local_id | str | TV 端 id | TV 端必要 | 可为`0` |
| appkey | str | APP 密钥 | APP 方式必要 | [可用](#appkey-可用列表) |
| local_id | num | TV 端 id | TV 端必要 | 可为`0` |
| ts | num | 当前时间戳 | APP 方式必要 | |
| sign | str | APP 签名 | APP 方式必要 | |
| mobi_app | str | 平台标识 | 非必要 | 会被拼接到返回的 url query |
@ -506,9 +514,9 @@ curl 'https://passport.snm0516.aisee.tv/x/passport-tv-login/qrcode/auth_code' \
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|-----------|-----|-------|---------|-----------------------|
| appkey | str | APP密钥 | APP方式必要 | 仅可用`4409e2ce8ffd12b8` |
| appkey | str | APP密钥 | APP方式必要 |[可用](#appkey-可用列表) |
| auth_code | str | 扫码秘钥 | 必要 | |
| local_id | str | TV端id | TV端必要 | 可为0 |
| local_id | num | TV端id | TV端必要 | 可为0 |
| ts | num | 当前时间戳 | APP方式必要 | |
| sign | str | APP签名 | APP方式必要 | |
@ -621,3 +629,24 @@ curl 'https://passport.snm0516.aisee.tv/x/passport-tv-login/qrcode/poll' \
```
</details>
### appkey 可用列表
**仅覆盖 [docs/misc/sign/APPKey](../../misc/sign/APPKey.md) 中包含的 appkey**
| APPKEY | APPSEC | platform | APP类型 | neuronAppId | mobi_app<sup>2</sup> | 备注 |
| :--------------: | :------------------------------: | :------------------: | :----------------: | :---------------------: | :------------------: | :----------------------------------------: |
| 783bbb7264451d82 | 2653583c8873dea268ab9386918b1d65 | `android` | 粉版 | `1` | `android` | 仅获取用户信息时使用(7.X及更新版本) |
| 8d23902c1688a798 | 710f0212e62bd499b8d3ac6e1db9302a | `android` | AndroidBiliThings | ? | ? | |
| bca7e84c2d947ac6 | 60698ba2f68e01ce44738920a0ffe768 | ? | login | - | ? | |
| 27eb53fc9058f8c3 | c2ed53a74eeefe3cf99fbd01d8c9c375 | `web`/`ios`? | - | - | - | 第三方授权使用 |
| 4409e2ce8ffd12b8 | 59b43e04ad6965f34319062b478f83dd | `android` | 云视听小电视(TV版) | `9`? | `android_tv_yst`? | |
| dfca71928277209b | b5475a8825547a4fc26c7d518eaaa02e | `android` | HD 版 | `5` | `android_hd` | |
**注意:**
通过某一组 APPKEY/APPSEC 获取到的 access_token当接口需要 `sign` 签名时也只能使用该组 APPKEY/APPSEC否则出现 `{ code: -663, message: '鉴权失败,请联系账号组', ttl: 1 }` 错误。
**例外:**
`783bbb7264451d82`/`2653583c8873dea268ab9386918b1d65` 获取到的 access_token 可配合 `1d8b6e7d45233436`/`560c52ccd288fed045859ed18bffd973` 使用。

View File

@ -89,6 +89,102 @@ curl 'https://passport.bilibili.com/web/generic/country/list'
</details>
## 发送短信验证码_app端
> https://passport.bilibili.com/x/passport-login/sms/send
*请求方式POST*
同手机号短信发送 CD 时间为 60s
短信验证码 timeout 为 5min
验证内容由第一次返回进行处理,解析recaptcha_url的params传到极验进行验证后取到验证结果入参后再次调用即可
**正文参数 (application/x-www-form-urlencoded)**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| --- | --- | --- | --- | --- |
| cid | num | 国际冠字码 | 必要 | 可以从[获取国际冠字码](#获取国际冠字码(web端))获取 |
| tel | num | 手机号码 | 必要 | |
| login_session_id | str | 登录标识 | 必要 | uuid去掉'-'后得到
| recaptcha_token | str | 登录 API token | 必要 | 在[申请 captcha 验证码](readme.md#申请captcha验证码)接口处获取 |
| gee_challenge | str | 极验 challenge | 必要 | 在[申请 captcha 验证码](readme.md#申请captcha验证码)接口处获取 |
| gee_validate | str | 极验 result | 必要 | 极验验证后得到 |
| gee_seccode | str | 极验 result +`\|jordan` | 必要 | 极验验证后得到 |
| channel | str | 通道? | 必要 | 一般固定值为"bili" |
| buvid | str | buvid | 必要 | 参考如下方法生成 |
| local_id | str | 同上 | 必要 | 同上 |
| statistics | str | ? | 必要 | 一般固定为{"appId":1,"platform":3,"version":"7.27.0","abtest":""},非key-value入参需要转URL编码 |
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------ | ---- | -------- | --------- |
| code | num | 返回值 | 0成功<br />-400请求错误<br />1002手机号格式错误<br />86203短信发送次数已达上限<br />1003验证码已经发送<br />1025该手机号在哔哩哔哩有过永久封禁记录无法再次注册或绑定新账号<br />2400登录秘钥错误<br />2406验证极验服务出错 |
| message | str | 错误信息 | 成功为0 |
| data | obj | 信息本体 | |
`data`对象:
| 字段 | 类型 | 内容 | 备注 |
| ----------- | ---- | -------------- | ------------------------ |
| captcha_key | str | 短信登录 token | 在下方传参时需要,请备用 |
**示例:**
例如手机号为`13888888888`国际id为`1 (中国大陆)`,登录秘钥为`aabbccdd`极验challenge为`2333`,极验结果为`666666`,进行发送短信验证码操作
```shell
curl 'https://passport.bilibili.com/x/passport-login/sms/send' \
--data-urlencode 'tel=13888888888' \
--data-urlencode 'cid=1' \
--data-urlencode 'login_session_id=669900' \
--data-urlencode 'recaptcha_token=aabbccdd' \
--data-urlencode 'gee_challenge=2333' \
--data-urlencode 'gee_validate=666666' \
--data-urlencode 'gee_seccode=666666|jordan' \
--data-urlencode 'channel=bili' \
--data-urlencode 'buvid=999999' \
--data-urlencode 'local_id=999999' \
--data-urlencode 'statistics=%7B%22appId%22%3A1%2C%22platform%22%3A3%2C%22version%22%3A%227.27.0%22%2C%22abtest%22%3A%22%22%7D'
```
生成buvid方法
``` javascript
static buvid() : string {
var mac = [];
for (let i = 0; i < 6; i++) {
var min = Math.min(0, 0xff)
var max = Math.max(0, 0xff)
var num = parseInt((Math.random() * (min - max + 1) + max).toString()).toString(16)
mac.push(num)
}
var md5 = this.md5(mac.join(':'));
var md5Arr = md5.split('');
return "XY${md5Arr[2]}${md5Arr[12]}${md5Arr[22]}${md5}"
}
```
<details>
<summary>查看响应示例:</summary>
```json
{"code":0,
"message":"0",
"ttl":1,
"data":{
"captcha_key":"7542f109c3318d74847626495c68c321",
"recaptcha_url":"...."
}
}
```
</details>
## 发送短信验证码_web端
> https://passport.bilibili.com/x/passport-login/web/sms/send
@ -157,6 +253,111 @@ curl 'https://passport.bilibili.com/x/passport-login/web/sms/send' \
</details>
## 使用短信验证码登录_app端
> https://passport.bilibili.com/x/passport-login/login/sms
*请求方式POST*
验证登录成功后会返回实体内容:
`mid` `expires_in` `access_token` `refresh_token`
**正文参数 (application/x-www-form-urlencoded)**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| --- | --- | --- | --- | --- |
| cid | num | 国际冠字码 | 必要 | 可以从[获取国际冠字码](#获取国际冠字码(web端))获取 |
| tel | num | 手机号码 | 必要 | |
| login_session_id | str | 登录标识 | 必要 | 必须与上述login_session_id保持一致
| code | num | 短信验证码 | 必要 | timeout 为 5min |
| captcha_key | str | 短信登录 token | 必要 | 从[上述API](#发送短信验证码(web端))请求成功后返回 |
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| --- | --- | --- | --- |
| code | num | 返回值 | 0成功<br />-400请求错误<br />1006请输入正确的短信验证码<br />1007短信验证码已过期 |
| message | str | 错误信息 | |
| data | obj | 信息本体 | |
`data`对象:
| 字段 | 类型 | 内容 | 备注 |
| --- | --- | --- | --- |
| mid | str | 用户uid | |
| expires_in | str | 过时时间 | |
| access_token | str | 登录 token | |
| refresh_token | str | 刷新 token | |
| cookie_info | Array | cookie集合 | |
**示例:**
使用手机号`13888888888`,短信验证码为`123456`,进行验证登录操作
```shell
curl 'https://passport.bilibili.com/x/passport-login/login/sms'
--data-urlencode 'cid=1' \
--data-urlencode 'tel=13888888888' \
--data-urlencode 'code=123456' \
--data-urlencode 'captcha_key=999999' \
--data-urlencode 'login_session_id=669900'
```
<details>
<summary>查看响应示例:</summary>
```json
{
"code": 0,
"data": {
"token_info": {
"mid": "...",
"expires_in": "114514",
"access_token": "",
"refresh_token": ""
//...
},
"cookie_info":[
//...
],
"message": "0"
}
}
```
</details>
**响应头部抓包信息:**
可明显看见设置了几个cookie填入浏览器即可成功登录
<details>
<summary>查看响应示例:</summary>
```http
HTTP/1.1 200 OK
Date: Mon, 13 Jul 2020 09:57:33 GMT
Content-Type: application/json;charset=UTF-8
Content-Length: 78
Connection: keep-alive
Server: Apache-Coyote/1.1
Set-Cookie: DedeUserID=***; Domain=.bilibili.com; Expires=Sat, 18-Jul-2020 09:57:57 GMT; Path=/
Set-Cookie: DedeUserID__ckMd5=***; Domain=.bilibili.com; Expires=Sat, 18-Jul-2020 09:57:57 GMT; Path=/
Set-Cookie: SESSDATA=***; Domain=.bilibili.com; Expires=Sat, 18-Jul-2020 09:57:57 GMT; Path=/; HttpOnly
Set-Cookie: bili_jct=***; Domain=.bilibili.com; Expires=Sat, 18-Jul-2020 09:57:57 GMT; Path=/
Set-Cookie: sid=***; Domain=.bilibili.com; Expires=Sat, 18-Jul-2020 09:57:57 GMT; Path=/
Expires: Mon, 13 Jul 2020 09:57:32 GMT
Cache-Control: no-cache
X-Cache-Webcdn: BYPASS from jd-sxhz-dx-w-01
```
</details>
## 使用短信验证码登录_web端
> https://passport.bilibili.com/x/passport-login/web/login/sms

View File

@ -227,7 +227,7 @@ curl 'https://passport.bilibili.com/login?act=getkey'
`sid` `DedeUserID` `DedeUserID__ckMd5` `SESSDATA` `bili_jct`
**正文参数 (application/x-www-form-urlencoded **
**正文参数 application/x-www-form-urlencoded**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
@ -241,8 +241,6 @@ curl 'https://passport.bilibili.com/login?act=getkey'
| validate | str | 极验 result | 必要 | 极验验证后得到 |
| seccode | str | 极验 result +`\|jordan` | 必要 | 极验验证后得到 |
</details>
**json回复**
根对象:

View File

@ -2,7 +2,7 @@
## 导航栏用户信息
> https://api.bilibili.com/nav带有转义
> ~~https://api.bilibili.com/nav带有转义~~ (已失效)
>
> https://api.bilibili.com/x/web-interface/nav原始数据
@ -27,30 +27,33 @@
| -------------------- | ---- | ---------------- | ------------------------------------------------- |
| isLogin | bool | 是否已登录 | false未登录<br />true已登录 |
| email_verified | num | 是否验证邮箱地址 | 0未验证<br />1已验证 |
| face | str | 用户头像url | |
| face | str | 用户头像 url | |
| level_info | obj | 等级信息 | |
| mid | num | 用户mid | |
| mid | num | 用户 mid | |
| mobile_verified | num | 是否验证手机号 | 0未验证<br />1已验证 |
| money | num | 拥有硬币数 | |
| moral | num | 当前节操值 | 上限为70 |
| official | obj | 认证信息 | |
| officialVerify | obj | 认证信息2 | |
| officialVerify | obj | 认证信息 2 | |
| pendant | obj | 头像框信息 | |
| scores | num | 0 | 作用尚不明确 |
| scores | num | | |
| uname | str | 用户昵称 | |
| vipDueDate | num | 会员到期时间 | 毫秒 时间戳 |
| vipStatus | num | 会员开通状态 | 0<br />1有 |
| vipType | num | 会员类型 | 0<br />1月度大会员<br />2年度及以上大会员 |
| vip_pay_type | num | 会员开通状态 | 0<br />1有 |
| vip_theme_type | num | 0 | 作用尚不明确 |
| vip_theme_type | num | | |
| vip_label | obj | 会员标签 | |
| vip_avatar_subscript | num | 是否显示会员图标 | 0不显示<br />1显示 |
| vip_nickname_color | str | 会员昵称颜色 | 颜色码 |
| wallet | obj | B币钱包信息 | |
| has_shop | bool | 是否拥有推广商品 | false<br />true有 |
| shop_url | str | 商品推广页面url | |
| allowance_count | num | 0 | 作用尚不明确 |
| answer_status | num | 0 | 作用尚不明确 |
| shop_url | str | 商品推广页面 url | |
| allowance_count | num | | |
| answer_status | num | | |
| is_senior_member | num | 是否硬核会员 | 0非硬核会员<br />1硬核会员 |
| wbi_img | obj | Wbi 签名实时口令 | 该字段即使用户未登录也存在 |
| is_jury | bool | 是否风纪委员 | true风纪委员<br />false非风纪委员 |
`data`中的`level_info`对象:
@ -65,7 +68,7 @@
| 字段 | 类型 | 内容 | 备注 |
| ----- | ---- | -------- | ------------------------------------------------- |
| role | num | 认证类型 | 0<br />1 2 7个人认证<br />3 4 5 6机构认证 |
| role | num | 认证类型 | 见[用户认证类型一览](../user/official_role.md) |
| title | str | 认证信息 | 无为空 |
| desc | str | 认证备注 | 无为空 |
| type | num | 是否认证 | -1<br />0认证 |
@ -79,35 +82,44 @@
`data`中的`pendant`对象:
| 字段 | 类型 | 内容 | 备注 |
| ------ | ---- | ----------- | ------------ |
| pid | num | 挂件id | |
| name | str | 挂件名称 | |
| image | str | 挂件图片url | |
| expire | num | 0 | 作用尚不明确 |
| 字段 | 类型 | 内容 | 备注 |
| ------ | ---- | ----------- | ---- |
| pid | num | 挂件id | |
| name | str | 挂件名称 | |
| image | str | 挂件图片url | |
| expire | num | | |
`data`中的`vip_label`对象:
| 字段 | 类型 | 内容 | 备注 |
| ----------- | ---- | -------- | ------------------------------------------------------------ |
| path | str | 空 | 作用尚不明确 |
| path | str | | |
| text | str | 会员名称 | |
| label_theme | str | 会员标签 | vip大会员<br />annual_vip年度大会员<br />ten_annual_vip十年大会员<br />hundred_annual_vip百年大会员 |
`data`中的`wallet`对象:
| 字段 | 类型 | 内容 | 备注 |
| --------------- | ---- | ------------- | ------------ |
| mid | num | 登录用户mid | |
| bcoin_balance | num | 拥有B币数 | |
| coupon_balance | num | 每月奖励B币数 | |
| coupon_due_time | num | 0 | 作用尚不明确 |
| 字段 | 类型 | 内容 | 备注 |
| --------------- | ---- | ------------- | ---- |
| mid | num | 登录用户mid | |
| bcoin_balance | num | 拥有B币数 | |
| coupon_balance | num | 每月奖励B币数 | |
| coupon_due_time | num | | |
`data`中的`wbi_img`对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | ------------------------------- | ---------------------------------------- |
| img_url | str | Wbi 签名参数 `imgKey`的伪装 url | 详见文档 [Wbi 签名](../misc/sign/wbi.md) |
| sub_url | str | Wbi 签名参数 `subKey`的伪装 url | 详见文档 [Wbi 签名](../misc/sign/wbi.md) |
**示例:**
**登录状态:**
```shell
curl 'https://api.bilibili.com/nav' \
-b 'SESSDATA=xxx'
curl 'https://api.bilibili.com/x/web-interface/nav' \
-b 'SESSDATA=xxx'
```
<details>
@ -115,64 +127,136 @@ curl 'https://api.bilibili.com/nav' \
```json
{
"code":0,
"message":"0",
"ttl":1,
"data":{
"isLogin":true,
"email_verified":1,
"face":"http://i1.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg",
"level_info":{
"current_level":5,
"current_min":10800,
"current_exp":17065,
"next_exp":28800
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"isLogin": true,
"email_verified": 1,
"face": "https://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg",
"face_nft": 0,
"face_nft_type": 0,
"level_info": {
"current_level": 6,
"current_min": 28800,
"current_exp": 52689,
"next_exp": "--"
},
"mid":293793435,
"mobile_verified":1,
"money":33.4,
"moral":70,
"official":{
"role":0,
"title":"",
"desc":"",
"type":-1
"mid": 293793435,
"mobile_verified": 1,
"money": 172.4,
"moral": 70,
"official": {
"role": 0,
"title": "",
"desc": "",
"type": -1
},
"officialVerify":{
"type":-1,
"desc":""
"officialVerify": {
"type": -1,
"desc": ""
},
"pendant":{
"pid":0,
"name":"",
"image":"",
"expire":0,
"image_enhance":""
"pendant": {
"pid": 2511,
"name": "初音未来13周年",
"image": "https://i0.hdslb.com/bfs/garb/item/4f8f3f1f2d47f0dad84f66aa57acd4409ea46361.png",
"expire": 0,
"image_enhance": "https://i0.hdslb.com/bfs/garb/item/fe0b83b53e2342b16646f6e7a9370d8a867decdb.webp",
"image_enhance_frame": "https://i0.hdslb.com/bfs/garb/item/127c507ec8448be30cf5f79500ecc6ef2fd32f2c.png"
},
"scores":0,
"uname":"社会易姐QwQ",
"vipDueDate":1612454400000,
"vipStatus":1,
"vipType":2,
"vip_pay_type":1,
"vip_theme_type":0,
"vip_label":{
"path":"",
"text":"年度大会员",
"label_theme":"annual_vip"
"scores": 0,
"uname": "社会易姐QwQ",
"vipDueDate": 1707494400000,
"vipStatus": 1,
"vipType": 2,
"vip_pay_type": 0,
"vip_theme_type": 0,
"vip_label": {
"path": "",
"text": "年度大会员",
"label_theme": "annual_vip",
"text_color": "#FFFFFF",
"bg_style": 1,
"bg_color": "#FB7299",
"border_color": "",
"use_img_label": true,
"img_label_uri_hans": "",
"img_label_uri_hant": "",
"img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/8d4f8bfc713826a5412a0a27eaaac4d6b9ede1d9.png",
"img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/VEW8fCC0hg.png"
},
"vip_avatar_subscript":1,
"vip_nickname_color":"#FB7299",
"wallet":{
"mid":293793435,
"bcoin_balance":8,
"coupon_balance":5,
"coupon_due_time":0
"vip_avatar_subscript": 1,
"vip_nickname_color": "#FB7299",
"vip": {
"type": 2,
"status": 1,
"due_date": 1707494400000,
"vip_pay_type": 0,
"theme_type": 0,
"label": {
"path": "",
"text": "年度大会员",
"label_theme": "annual_vip",
"text_color": "#FFFFFF",
"bg_style": 1,
"bg_color": "#FB7299",
"border_color": "",
"use_img_label": true,
"img_label_uri_hans": "",
"img_label_uri_hant": "",
"img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/8d4f8bfc713826a5412a0a27eaaac4d6b9ede1d9.png",
"img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/VEW8fCC0hg.png"
},
"avatar_subscript": 1,
"nickname_color": "#FB7299",
"role": 3,
"avatar_subscript_url": "",
"tv_vip_status": 0,
"tv_vip_pay_type": 0,
"tv_due_date": 1640793600
},
"wallet": {
"mid": 293793435,
"bcoin_balance": 5,
"coupon_balance": 5,
"coupon_due_time": 0
},
"has_shop": true,
"shop_url": "https://gf.bilibili.com?msource=main_station",
"allowance_count": 0,
"answer_status": 0,
"is_senior_member": 1,
"wbi_img": {
"img_url": "https://i0.hdslb.com/bfs/wbi/653657f524a547ac981ded72ea172057.png",
"sub_url": "https://i0.hdslb.com/bfs/wbi/6e4909c702f846728e64f6007736a338.png"
},
"is_jury": false
}
}
```
</details>
**未登录状态:**
```shell
curl 'https://api.bilibili.com/x/web-interface/nav'
```
<details>
<summary>查看响应示例:</summary>
```json
{
"code": -101,
"message": "账号未登录",
"ttl": 1,
"data": {
"isLogin": false,
"wbi_img": {
"img_url": "https://i0.hdslb.com/bfs/wbi/653657f524a547ac981ded72ea172057.png",
"sub_url": "https://i0.hdslb.com/bfs/wbi/6e4909c702f846728e64f6007736a338.png"
},
"has_shop":false,
"shop_url":"",
"allowance_count":0,
"answer_status":0
}
}
```
@ -558,4 +642,4 @@ curl 'https://account.bilibili.com/site/getCoin' \
}
```
</details>
</details>

View File

@ -101,9 +101,9 @@ curl 'https://api.bilibili.com/x/member/web/account' \
| watch | bool | 每日观看 | false未完成<br />true已完成<br />完成奖励5经验 |
| coins | num | 每日投币所奖励的经验 | 上限为50<br />注:该值更新存在延迟<br />[另外一个专门API](#查询每日投币获得经验数) |
| share | bool | 每日分享 | false未完成<br />true已完成<br />完成奖励5经验 |
| email | bool | 绑定邮箱 | false未完成<br />true已完成 |
| tel | bool | 绑定手机号 | false未完成<br />true已完成<br />首次完成完成奖励100经验 |
| safe_question | bool | 设置密保问题 | false未完成<br />true已完成 |
| email | bool | 绑定邮箱 | false未完成<br />true已完成<br />首次完成奖励20经验 |
| tel | bool | 绑定手机号 | false未完成<br />true已完成<br />首次完成奖励100经验 |
| safe_question | bool | 设置密保问题 | false未完成<br />true已完成<br />首次完成奖励30经验 |
| identify_card | bool | 实名认证 | false未完成<br />true已完成<br />首次完成奖励50经验 |
**示例:**
@ -283,7 +283,7 @@ curl 'https://api.bilibili.com/x/vip/web/user/info' \
| tel_verify | bool | 是否验证手机号 | false未验证<br />true已验证 |
| mail_verify | bool | 是否验证邮箱 | false未验证<br />true已验证 |
| unneeded_check | bool | 是否未设置密码 | false已设置<br />true未设置 |
| realname_certified | bool | 是否实名认证 | false已认证<br />true认证 |
| realname_certified | bool | 是否实名认证 | false未认证<br />true认证 |
`data`中的`account_safe`对象:

View File

@ -44,7 +44,7 @@
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------------------------------------------------------------ |
| path | str | .index 文件路径 | 解密详见[此处](./unlock_index_data.md) |
| path | str | .index 文件路径 | |
| images | array | 本话图片信息 | |
| last_modified | str | 本话信息最后修改时间 | |
| host | str | `https://manga.hdslb.com` | |

View File

@ -73,6 +73,7 @@ curl 'https://api.vc.bilibili.com/session_svr/v1/session_svr/single_unread' \
| msg[msg_status] | num | 0 | 非必要 | |
| msg[dev_id] | string | 372778FD-E359-461D-86A3-EA2BCC6FF52A | 必要 | **获取方式在下面** |
| msg[timestamp] | num | 时间戳(秒) | 必要 | |
| msg[new_face_version] | num | 表情包版本 | 非必要 | **详见下表** |
| msg[content] | 发送文字时str<br />撤回消息时num | 消息内容 | 必要 | **详见下表** |
| csrf | str | CSRF Token位于cookie | 必要 | |
@ -248,9 +249,11 @@ curl 'https://api.vc.bilibili.com/web_im/v1/web_im/send_msg' \
| sender_device_id | num | 发送者设备 | 可选 | 1 |
| talker_id | num | 聊天对象的UID | 必要 | -------------- |
| session_type | num | 聊天对象的类型 | 必要 | 1为用户2为粉丝团 |
| size | num | 列出消息条数 | 可选 | 默认是20 |
| size | num | 列出消息条数 | 可选 | 默认是20最大为200 |
| build | num | 未知 | 可选 | 默认是0 |
| mobi_app | str | 设备 | 可选 | web |
| begin_seqno | num | 开始的序列号 | 可选 | 默认0为全部 |
| end_seqno | num | 结束的序列号 | 可选 | 默认0为全部 |
**json回复**
@ -270,8 +273,8 @@ curl 'https://api.vc.bilibili.com/web_im/v1/web_im/send_msg' \
| ---- | ---- | ------------- | ---- |
| messages | array | 聊天记录列表 | |
| has_more | num | 0 | |
| min_seqno | num | 未知 | |
| max_seqno | num | 未知 | |
| min_seqno | num | 所有消息最小的序列号(最早) | |
| max_seqno | num | 所有消息最大的序列号(最晚) | |
| e_infos | array | 聊天表情列表 | |
`messages`数组:
@ -283,13 +286,13 @@ curl 'https://api.vc.bilibili.com/web_im/v1/web_im/send_msg' \
| receiver_id | num | 接收者uid | 注意名称是receiver_id |
| msg_type | num | 消息类型 | 1:文字消息<br>2:图片消息<br>5:撤回的消息<br>12、13:通知 |
| content | str | 消息内容 | 此处存在设计缺陷 |
| msg_seqno | num | 未知 | |
| msg_seqno | num | 消息序列号,保证按照时间顺序从小到大 | |
| timestamp | num | 消息发送时间戳 | |
| at_uids | array | 未知 | |
| msg_key | num | 未知 | |
| msg_status | num | 消息状态 | 0 |
| notify_code |str | 未知 | |
| new_face_version |num | 未知 | 疑似只在粉丝团消息中出现 |
| new_face_version |num | 表情包版本 | 0或者没有是旧版此时b站会自动转换成新版表情包例如`[doge]` -> `[tv_doge]`1是新版 |
`e_infos`数组:

657
docs/misc/bvid_desc.md Normal file
View File

@ -0,0 +1,657 @@
# bvid说明
2020-03-23 B站推出了全新的稿件视频id`bvid`来接替之前的`avid`,其意义与之相同
详见:
1. [【升级公告】AV号全面升级至BV号专栏](https://www.bilibili.com/read/cv5167957)
2. [【升级公告】AV号全面升级至BV号](https://www.bilibili.com/blackboard/activity-BV-PC.html)
## 概述
### 格式
“bvid”恒为长度为 12 的字符串前两个固定为“BV1”后 9 个为 base58 计算结果(不包含数字 `0` 和大写字母 `I``O` 以及小写字母 `l`
### 实质
“bvid"为“avid”的base58编码可通过算法进行相互转化
### avid发号方式的变化
从 2009-09-09 09:09:09 [av2](https://www.bilibili.com/video/av2) 的发布到 2020-03-28 19:45:02 [av99999999](https://www.bilibili.com/video/av99999999) 的发布B站结束了以投稿时间为顺序的avid发放改为随机发放avid
~~暗示B站东方要完泪目~~
## 算法概述
~~算法以及程序主要参考[知乎@mcfx的回答](https://www.zhihu.com/question/381784377/answer/1099438784)~~
~~实际上该算法并不完整,新的算法参考自[【揭秘】av号转bv号的过程](https://www.bilibili.com/video/BV1N741127Tj)~~
实际上上面的算法依然不完整,新的算法参考自 [SocialSisterYi#740](https://github.com/SocialSisterYi/bilibili-API-collect/issues/740)~~来自 B 站某个 JS 文件?~~
### av->bv算法
**说明**
1. 目前的 BV 格式为 BV1XXXXXXXXX以 BV1 开头,后面包含 9 位有效数据。
2. AV 最大值为 2⁵¹。
**算法**
- 定义一个包含初始值为 `['B', 'V', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0']` 的长度为 12 的数组`bytes`,用于存储转换后的字符。
- 定义变量 `bv_idx` 并初始化为数组 `bytes` 的最后一个索引。
- 将输入的 `aid` 与 avid 最大值2⁵¹进行按位或运算其结果与常量 `XOR_CODE`23442827791579进行异或运算得到变量 `tmp`
- 当 `tmp` 大于0时循环执行以下操作直到小于0
- 将 `tmp` 除以 58码表的长度 的余数作为索引,从 `FcwAPNKTMug3GV5Lj7EJnHpWsx4tb8haYeviqBz6rkCy12mUSDQX9RdoZf` 码表中取出对应的字符,并将其赋值给 `bytes[bv_idx]`
- 将 `tmp` 与 58 求模赋值给 `tmp`
- 将 `bv_idx` 减1。
- 将 `bytes` 数组中索引为 3 和 9 的元素进行交换。
- 将 `bytes` 数组中索引为 4 和 7 的元素进行交换。
- 将 `bytes` 数组转换为字符串,并返回结果。
### bv->av算法
#av->bv算法 的逆向
- 将 `bvid` 中索引为 3 和 9 的字符进行交换。
- 将 `bvid` 中索引为 4 和 7 的字符进行交换。
- 删除 `bvid` 前3个字符固定为 BV1
- 定义变量 `tmp` 并初始化为 0。
- 遍历 `bvid` 的每个字符,执行以下操作:
- 获取当前字符在 `FcwAPNKTMug3GV5Lj7EJnHpWsx4tb8haYeviqBz6rkCy12mUSDQX9RdoZf` 码表中的索引,并将其赋值给变量 `idx`
- 将 `tmp` 乘以常量 58并加上 `idx`,最后赋值给 `tmp`
- 将 `tmp` 与常量 2⁵¹ - 1 进行按位与运算,其结果与常量 `XOR_CODE`23442827791579 进行异或运算,得到最终结果。
## 编程实现
### JavaScript/TypeScript
<CodeGroup>
<CodeGroupItem title="JavaScript">
```javascript
const XOR_CODE = 23442827791579n;
const MASK_CODE = 2251799813685247n;
const MAX_AID = 1n << 51n;
const BASE = 58n;
const data = 'FcwAPNKTMug3GV5Lj7EJnHpWsx4tb8haYeviqBz6rkCy12mUSDQX9RdoZf';
function av2bv(aid) {
const bytes = ['B', 'V', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0'];
let bvIndex = bytes.length - 1;
let tmp = (MAX_AID | BigInt(aid)) ^ XOR_CODE;
while (tmp > 0) {
bytes[bvIndex] = data[Number(tmp % BigInt(BASE))];
tmp = tmp / BASE;
bvIndex -= 1;
}
[bytes[3], bytes[9]] = [bytes[9], bytes[3]];
[bytes[4], bytes[7]] = [bytes[7], bytes[4]];
return bytes.join('');
}
function bv2av(bvid) {
const bvidArr = Array.from(bvid);
[bvidArr[3], bvidArr[9]] = [bvidArr[9], bvidArr[3]];
[bvidArr[4], bvidArr[7]] = [bvidArr[7], bvidArr[4]];
bvidArr.splice(0, 3);
const tmp = bvidArr.reduce((pre, bvidChar) => pre * BASE + BigInt(data.indexOf(bvidChar)), 0n);
return Number((tmp & MASK_CODE) ^ XOR_CODE);
}
console.log(av2bv(111298867365120));
console.log(bv2av('BV1L9Uoa9EUx'));
```
</CodeGroupItem>
<CodeGroupItem title="TypeScript">
```typescript
const XOR_CODE = 23442827791579n;
const MASK_CODE = 2251799813685247n;
const MAX_AID = 1n << 51n;
const BASE = 58n;
const data = 'FcwAPNKTMug3GV5Lj7EJnHpWsx4tb8haYeviqBz6rkCy12mUSDQX9RdoZf';
function av2bv(aid: number) {
const bytes = ['B', 'V', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0'];
let bvIndex = bytes.length - 1;
let tmp = (MAX_AID | BigInt(aid)) ^ XOR_CODE;
while (tmp > 0) {
bytes[bvIndex] = data[Number(tmp % BigInt(BASE))];
tmp = tmp / BASE;
bvIndex -= 1;
}
[bytes[3], bytes[9]] = [bytes[9], bytes[3]];
[bytes[4], bytes[7]] = [bytes[7], bytes[4]];
return bytes.join('') as `BV1${string}`;
}
function bv2av(bvid: `BV1${string}`) {
const bvidArr = Array.from<string>(bvid);
[bvidArr[3], bvidArr[9]] = [bvidArr[9], bvidArr[3]];
[bvidArr[4], bvidArr[7]] = [bvidArr[7], bvidArr[4]];
bvidArr.splice(0, 3);
const tmp = bvidArr.reduce((pre, bvidChar) => pre * BASE + BigInt(data.indexOf(bvidChar)), 0n);
return Number((tmp & MASK_CODE) ^ XOR_CODE);
}
console.log(av2bv(111298867365120));
console.log(bv2av('BV1L9Uoa9EUx'));
```
</CodeGroupItem>
</CodeGroup>
### Python
来自:[#847](https://github.com/SocialSisterYi/bilibili-API-collect/issues/847#issuecomment-1807020675)
```python
XOR_CODE = 23442827791579
MASK_CODE = 2251799813685247
MAX_AID = 1 << 51
ALPHABET = "FcwAPNKTMug3GV5Lj7EJnHpWsx4tb8haYeviqBz6rkCy12mUSDQX9RdoZf"
ENCODE_MAP = 8, 7, 0, 5, 1, 3, 2, 4, 6
DECODE_MAP = tuple(reversed(ENCODE_MAP))
BASE = len(ALPHABET)
PREFIX = "BV1"
PREFIX_LEN = len(PREFIX)
CODE_LEN = len(ENCODE_MAP)
def av2bv(aid: int) -> str:
bvid = [""] * 9
tmp = (MAX_AID | aid) ^ XOR_CODE
for i in range(CODE_LEN):
bvid[ENCODE_MAP[i]] = ALPHABET[tmp % BASE]
tmp //= BASE
return PREFIX + "".join(bvid)
def bv2av(bvid: str) -> int:
assert bvid[:3] == PREFIX
bvid = bvid[3:]
tmp = 0
for i in range(CODE_LEN):
idx = ALPHABET.index(bvid[DECODE_MAP[i]])
tmp = tmp * BASE + idx
return (tmp & MASK_CODE) ^ XOR_CODE
assert av2bv(111298867365120) == "BV1L9Uoa9EUx"
assert bv2av("BV1L9Uoa9EUx") == 111298867365120
```
### Rust
参考 <https://github.com/Colerar/abv/blob/main/src/lib.rs>
### Swift
```swift
fileprivate let XOR_CODE: UInt64 = 23442827791579
fileprivate let MASK_CODE: UInt64 = 2251799813685247
fileprivate let MAX_AID: UInt64 = 1 << 51
fileprivate let data: [UInt8] = [70, 99, 119, 65, 80, 78, 75, 84, 77, 117, 103, 51, 71, 86, 53, 76, 106, 55, 69, 74, 110, 72, 112, 87, 115, 120, 52, 116, 98, 56, 104, 97, 89, 101, 118, 105, 113, 66, 122, 54, 114, 107, 67, 121, 49, 50, 109, 85, 83, 68, 81, 88, 57, 82, 100, 111, 90, 102]
fileprivate let BASE: UInt64 = 58
fileprivate let BV_LEN: Int = 12
fileprivate let PREFIX: String = "BV1"
func av2bv(avid: UInt64) -> String {
var bytes: [UInt8] = [66, 86, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48]
var bvIdx = BV_LEN - 1
var tmp = (MAX_AID | avid) ^ XOR_CODE
while tmp != 0 {
bytes[bvIdx] = data[Int(tmp % BASE)]
tmp /= BASE
bvIdx -= 1
}
bytes.swapAt(3, 9)
bytes.swapAt(4, 7)
return String(decoding: bytes, as: UTF8.self)
}
func bv2av(bvid: String) -> UInt64 {
let fixedBvid: String
if bvid.hasPrefix("BV") {
fixedBvid = bvid
} else {
fixedBvid = "BV" + bvid
}
var bvidArray = Array(fixedBvid.utf8)
bvidArray.swapAt(3, 9)
bvidArray.swapAt(4, 7)
let trimmedBvid = String(decoding: bvidArray[3...], as: UTF8.self)
var tmp: UInt64 = 0
for char in trimmedBvid {
if let idx = data.firstIndex(of: char.utf8.first!) {
tmp = tmp * BASE + UInt64(idx)
}
}
return (tmp & MASK_CODE) ^ XOR_CODE
}
print(av2bv(avid: 111298867365120))
print(bv2av(bvid: "BV1L9Uoa9EUx"))
```
## 老版算法存档
**以下算法已失效**,编解码函数值域有限,不推荐使用,在此仅作为存档
<details>
<summary>查看折叠内容:</summary>
算法参考自[【揭秘】av号转bv号的过程](https://www.bilibili.com/video/BV1N741127Tj)
### av->bv算法
注:本算法及示例程序仅能编解码`avid < 29460791296`且暂无法验证`avid >= 29460791296`的正确性
再注:本人不清楚新算法能否编解码`avid >= 29460791296`
1. a = (avid ⊕ 177451812) + 100618342136696320
2. 以 i 为循环变量循环 6 次 b[i] = (a / 58 ^ i) % 58
3. 将 b[i] 中各个数字转换为以下码表中的字符
码表:
> fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF
4. 初始化字符串 b[i]=` `
5. 按照以下字符顺序编码表编码并填充至 b[i]
字符顺序编码表:
> 0 -> 9
>
> 1 -> 8
>
> 2 -> 1
>
> 3 -> 6
>
> 4 -> 2
>
> 5 -> 4
>
> 6 -> 0
>
> 7 -> 7
>
> 8 -> 3
>
> 9 -> 5
### bv->av算法
为以上算法的逆运算
### 编程实现
使用 [Python](#Python) [C](#C) [TypeScript](#TypeScript) [Java](#Java) [Kotlin](#Kotlin) [Golang](#Golang) [Rust](#Rust) 等语言作为示例,欢迎社区提交更多例程
注: 新算法只提供了 [Python](#Python) 和 [Rust](#Rust) 版本
#### Python
```python
XOR = 177451812
ADD = 100618342136696320
TABLE = "fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF"
MAP = 9, 8, 1, 6, 2, 4, 0, 7, 3, 5
def av2bv(av: int) -> str:
av = (av ^ XOR) + ADD
bv = [""] * 10
for i in range(10):
bv[MAP[i]] = TABLE[(av // 58**i) % 58]
return "".join(bv)
def bv2av(bv: int) -> int:
av = [""] * 10
s = 0
for i in range(10):
s += TABLE.find(bv[MAP[i]]) * 58**i
av = (s - ADD) ^ XOR
return av
def main():
while 1:
mode = input("1. AV to BV\n2. BV to AV\n3. Exit\n你的选择")
if mode == "1":
print(f"BV号是BV {av2bv(int(input('AV号是')))}")
elif mode == "2":
print(f"AV号是AV {bv2av(input('BV号是'))}")
elif mode == "3":
break
else:
print("输入错误请重新输入")
if __name__ == "__main__":
main()
```
#### C
```c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
const char table[] = "fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF"; // 码表
char tr[124]; // 反查码表
const unsigned long long XOR = 177451812; // 固定异或值
const unsigned long long ADD = 8728348608; // 固定加法值
const int s[] = {11, 10, 3, 8, 4, 6}; // 位置编码表
// 初始化反查码表
void tr_init() {
for (int i = 0; i < 58; i++)
tr[table[i]] = i;
}
unsigned long long bv2av(char bv[]) {
unsigned long long r = 0;
unsigned long long av;
for (int i = 0; i < 6; i++)
r += tr[bv[s[i]]] * (unsigned long long)pow(58, i);
av = (r - ADD) ^ XOR;
return av;
}
char *av2bv(unsigned long long av) {
char *result = (char*)malloc(13);
strcpy(result,"BV1 4 1 7 ");
av = (av ^ XOR) + ADD;
for (int i = 0; i < 6; i++)
result[s[i]] = table[(unsigned long long)(av / (unsigned long long)pow(58, i)) % 58];
return result;
}
int main() {
tr_init();
printf("%s\n", av2bv(170001));
printf("%u\n", bv2av("BV17x411w7KC"));
return 0;
}
```
输出为:
```
BV17x411w7KC
170001
```
#### TypeScript
感谢[#417](https://github.com/SocialSisterYi/bilibili-API-collect/issues/417#issuecomment-1186475063)提供
```typescript
export default class BvCode {
private TABEL = 'fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF'; // 码表
private TR: Record<string, number> = {}; // 反查码表
private S = [11, 10, 3, 8, 4, 6]; // 位置编码表
private XOR = 177451812; // 固定异或值
private ADD = 8728348608; // 固定加法值
constructor() {
// 初始化反查码表
const len = this.TABEL.length;
for (let i = 0; i < len; i++) {
this.TR[this.TABEL[i]] = i;
}
}
av2bv(av: number): string {
const x_ = (av ^ this.XOR) + this.ADD;
const r = ['B', 'V', '1', , , '4', , '1', , '7'];
for (let i = 0; i < 6; i++) {
r[this.S[i]] = this.TABEL[Math.floor(x_ / 58 ** i) % 58];
}
return r.join('');
}
bv2av(bv: string): number {
let r = 0;
for (let i = 0; i < 6; i++) {
r += this.TR[bv[this.S[i]]] * 58 ** i;
}
return (r - this.ADD) ^ this.XOR;
}
}
const bvcode = new BvCode();
console.log(bvcode.av2bv(170001));
console.log(bvcode.bv2av('BV17x411w7KC'));
```
输出为:
```
BV17x411w7KC
170001
```
#### Java
```java
/**
* 算法来自https://www.zhihu.com/question/381784377/answer/1099438784
*/
public class Util {
private static final String TABLE = "fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF";
private static final int[] S = new int[]{11, 10, 3, 8, 4, 6};
private static final int XOR = 177451812;
private static final long ADD = 8728348608L;
private static final Map<Character, Integer> MAP = new HashMap<>();
static {
for (int i = 0; i < 58; i++) {
MAP.put(TABLE.charAt(i), i);
}
}
public static String aidToBvid(int aid) {
long x = (aid ^ XOR) + ADD;
char[] chars = new char[]{'B', 'V', '1', ' ', ' ', '4', ' ', '1', ' ', '7', ' ', ' '};
for (int i = 0; i < 6; i++) {
int pow = (int) Math.pow(58, i);
long i1 = x / pow;
int index = (int) (i1 % 58);
chars[S[i]] = TABLE.charAt(index);
}
return String.valueOf(chars);
}
public static int bvidToAid(String bvid) {
long r = 0;
for (int i = 0; i < 6; i++) {
r += MAP.get(bvid.charAt(S[i])) * Math.pow(58, i);
}
return (int) ((r - ADD) ^ XOR);
}
}
```
#### Kotlin
```kotlin
/**
* 此程序非完全原创改编自GH站内某大佬的Java程序修改了部分代码且转换为Kotlin
* 算法来源同上
*/
object VideoUtils {
//这里是由知乎大佬不知道用什么方法得出的转换用数字
var ss = intArrayOf(11, 10, 3, 8, 4, 6, 2, 9, 5, 7)
var xor: Long = 177451812 //二进制时加减数1
var add = 8728348608L //十进制时加减数2
//变量初始化工作,加载哈希表
private const val table = "fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF"
private val mp = HashMap<String, Int>()
private val mp2 = HashMap<Int, String>()
//现在定义av号和bv号互转的方法
//定义一个power乘方方法这是转换进制必要的
fun power(a: Int, b: Int): Long {
var power: Long = 1
for (c in 0 until b) power *= a.toLong()
return power
}
//bv转av方法
fun bv2av(s: String): String {
var r: Long = 0
//58进制转换
for (i in 0..57) {
val s1 = table.substring(i, i + 1)
mp[s1] = i
}
for (i in 0..5) {
r += mp[s.substring(ss[i], ss[i] + 1)]!! * power(58, i)
}
//转换完成后,需要处理,带上两个随机数
return (r - add xor xor).toString()
}
//av转bv方法
fun av2bv(st: String): String {
try {
var s = java.lang.Long.valueOf(st.split("av".toRegex()).dropLastWhile { it.isEmpty() }
.toTypedArray()[1])
val sb = StringBuffer("BV1 4 1 7 ")
//逆向思路,先将随机数还原
s = (s xor xor) + add
//58进制转回
for (i in 0..57) {
val s1 = table.substring(i, i + 1)
mp2[i] = s1
}
for (i in 0..5) {
val r = mp2[(s / power(58, i) % 58).toInt()]
sb.replace(ss[i], ss[i] + 1, r!!)
}
return sb.toString()
} catch (e: ArrayIndexOutOfBoundsException) {
return ""
}
}
}
```
#### Golang
```go
package main
import "math"
const TABLE = "fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF"
var S = [11]uint{11, 10, 3, 8, 4, 6}
const XOR = 177451812
const ADD = 8728348608
var TR = map[string]int64{}
// 初始化 TR
func init() {
for i := 0; i < 58; i++ {
TR[TABLE[i:i+1]] = int64(i)
}
}
func BV2AV(bv string) int64 {
r := int64(0)
for i := 0; i < 6; i++ {
r += TR[bv[S[i]:S[i]+1]] * int64(math.Pow(58, float64(i)))
}
return (r - ADD) ^ XOR
}
func AV2BV(av int64) string {
x := (av ^ XOR) + ADD
r := []rune("BV1 4 1 7 ")
for i := 0; i < 6; i++ {
r[S[i]] = rune(TABLE[x/int64(math.Pow(58, float64(i)))%58])
}
return string(r)
}
func main() {
println(AV2BV(170001))
println(BV2AV("BV17x411w7KC"))
}
```
输出为:
```
BV17x411w7KC
170001
```
#### Rust
crate: https://github.com/stackinspector/bvid
```rust
// Copyright (c) 2023 stackinspector. MIT license.
const XORN: u64 = 177451812;
const ADDN: u64 = 100618342136696320;
const TABLE: [u8; 58] = *b"fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF";
const MAP: [usize; 10] = [9, 8, 1, 6, 2, 4, 0, 7, 3, 5];
const REV_TABLE: [u8; 74] = [
13, 12, 46, 31, 43, 18, 40, 28, 5, 0, 0, 0, 0, 0, 0, 0, 54, 20, 15, 8,
39, 57, 45, 36, 0, 38, 51, 42, 49, 52, 0, 53, 7, 4, 9, 50, 10, 44, 34, 6,
25, 1, 0, 0, 0, 0, 0, 0, 26, 29, 56, 3, 24, 0, 47, 27, 22, 41, 16, 0,
11, 37, 2, 35, 21, 17, 33, 30, 48, 23, 55, 32, 14, 19,
];
const POW58: [u64; 10] = [
1, 58, 3364, 195112, 11316496, 656356768, 38068692544,
2207984167552, 128063081718016, 7427658739644928,
];
fn av2bv(avid: u64) -> [u8; 10] {
let a = (avid ^ XORN) + ADDN;
let mut bvid = [0; 10];
for i in 0..10 {
bvid[MAP[i]] = TABLE[(a / POW58[i]) as usize % 58];
}
bvid
}
fn bv2av(bvid: [u8; 10]) -> u64 {
let mut a = 0;
for i in 0..10 {
a += REV_TABLE[bvid[MAP[i]] as usize - 49] as u64 * POW58[i];
}
(a - ADDN) ^ XORN
}
// assert_eq!(*b"17x411w7KC", av2bv(170001));
// assert_eq!(170001, bv2av(*b"17x411w7KC"));
```
</details>

View File

@ -0,0 +1,104 @@
# 设备各类标识算法(APP 端)
## 设备唯一标识 BUVID
注意区分于 Web 端的 buvid3, buvid4.
BUVID 在 APP 首次安装于某设备, 且首次启动时生成.
APP 首次(即每次安装后)启动, 会向云端发送本机各类设备特征, 含 `AndroidId`, `DrmId` 等, 请求是否有匹配的 BUVID, 有就使用云端的, 否则使用本地生成的.
APP 请求是否有匹配的 BUVID 发送的本机各类设备特征包括(但不限于):
+ `AndroidID`
+ `DrmId`
+ `IMEI`
+ `OAID`
+ 手机网卡 `MAC`
+ 设备品牌
+ 设备 Model
+ 本地生成的 BUVID
### 生成方法
1. 选定设备特征码, 可以是 `AndroidID`, `DrmId`, 手机网卡 `MAC` 等. 记为 `ID`. 特别地, `MAC` 应当去掉 `:`, `GUID`(即 UUID) 应当去掉 `-`.
2. 计算 `ID` 的 MD5. 记为 `ID_MD5`.
3. 从 `ID_MD5` 抽取第 3, 13, 23 位, 失败就默认为 000, 记为 `ID_E`.
4. 根据选定的设备特征码类型确定 BUVID Prefix, 见附录. 记为 `BUVID_Prefix`.
5. 按 `{BUVID_Prefix}{ID_E}{ID_MD5}` 的顺序连接起来, 共37位(2+3+32). 结果应当为大写.
### Demo
#### Rust
代码及测试样例见 [Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=40b5906cf3838a60efa83fa368b15147).
## 设备指纹 fp (fp_local, fp_remote)
用于请求账户相关 REST API, 及 gRPC Metadata 生成.
在请求头中, `fp_local``fp_remote` 设置为同一值即可, 暂不清楚区别.
### 生成方法
1. 获取 BUVID. 此处一般使用 XU Prefix 的 BUVID.
2. 获取设备 Model(`Build.MODEL`), 如 `NOH-AN01`.
3. 获取手机无线电固件版本号(`Build.getRadioVersion()`), 失败则留空. 如 `21C20B686S000C000,21C20B686S000C000`.
4. 按前述顺序拼接字符串, 计算得 MD5.
5. 获取年月日, 格式 `yyyyMMddhhmmss`, 拼接到 4 得到的字符串后.
6. 生成 16 位随机字符串, CharSet 为 `0123456789abcdef`, 拼接到 5 得到的字符串后, 记为 `fp_raw`.
7. 计算得到一个特殊字符串, 拼接到 `fp_raw` 后, 即得到最终的 `fp`, 特殊字符串算法见下:
```rust
let mut veri_code = 0;
// 有点像 HEX 的操作
let fp_raw_sub_str = fp_raw
.as_bytes() // 将字符串 fp_raw 转换为字节数组
.chunks(2) // 按每两个字节一组进行切分
.map(|s| unsafe { ::std::str::from_utf8_unchecked(s) }) // 对每一组解析作为 UTF-8 字符串
.collect::<Vec<_>>(); // 将结果收集到 Vec 中
// 如果 fp_raw 的长度小于 62, 则向下取偶数减半作为循环终止条件, 否则终止条件为31
for i in 0..({
if fp_raw.len() < 62 {
fp_raw.len() - fp_raw.len() % 2 // 取偶数
} else {
62
}
} / 2)
{
// 将每组字符串转换为对应的 16 进制整数, 将转换得到的整数加到 veri_code 上.
veri_code += i32::from_str_radix(fp_raw_sub_str[i], 16).unwrap_or(0);
}
// 最后将 veri_code 对 256 取余, 格式化为两位的 16 进制字符串
let veri_code = format!("{:0>2x}", veri_code % 256);
```
### Demo
#### Rust
代码及测试样例见 [Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=40b5906cf3838a60efa83fa368b15147).
## 附录
### BUVID Prefix
|设备特征码|BUVID Prefix|备注|
|:-:|:-:|:-:|
|`AndroidID`|`XX`||
|`DrmId`|`XU`||
|`IMEI`|`XZ`|已弃用|
|`GUID`|`XW`|已弃用|
|`MAC`|`XY`||
|`GoogleId`|`XG`|东南亚版本|
|`FacebookId`|`XF`|东南亚版本|

View File

@ -57,4 +57,5 @@
| -688 | 地理区域限制 |
| -689 | 版权限制 |
| -701 | 扣节操失败 |
| -799 | 请求过于频繁,请稍后再试 |
|-8888|对不起,服务器开小差了~ (ಥ﹏ಥ)|

View File

@ -9,7 +9,7 @@
| width | 图片最大限制宽度 | |
| high | 图片最大限制高度 | |
| quality | 图片质量百分比 | 仅限webp |
| format | 图片格式 | 仅限png/jpg/webp |
| format | 图片格式 | 仅限png/jpg/webp/[avg_color](#avg_color格式说明) |
**示例:**
@ -41,4 +41,40 @@ https://i1.hdslb.com/bfs/archive/e5fff1472bad1c0c6bcb3004205f9be23b58ffc0.jpg@.w
https://i1.hdslb.com/bfs/archive/e5fff1472bad1c0c6bcb3004205f9be23b58ffc0.jpg@1q.webp
![](https://i1.hdslb.com/bfs/archive/e5fff1472bad1c0c6bcb3004205f9be23b58ffc0.jpg@1q.webp)
![](https://i1.hdslb.com/bfs/archive/e5fff1472bad1c0c6bcb3004205f9be23b58ffc0.jpg@1q.webp)
## avg_color格式说明
当图片格式化输出格式为`avg_color`时
> \*.hdslb.com/bfs/\*/\*.*@\*.avg_color
*请求方式GET*
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------ | ---- | ----------- | ------ |
| RGB | str | 平均颜色值 | HEX |
**示例:**
获取 https://i1.hdslb.com/bfs/archive/e5fff1472bad1c0c6bcb3004205f9be23b58ffc0.jpg 的平均颜色值
```shell
curl 'https://i1.hdslb.com/bfs/archive/e5fff1472bad1c0c6bcb3004205f9be23b58ffc0.jpg@.avg_color'
```
<details>
<summary>查看响应示例:</summary>
```json
{
"RGB": "#7d6f6c"
}
```
</details>

216
docs/misc/sign/APP.md Normal file
View File

@ -0,0 +1,216 @@
# APP API 签名与鉴权
## APP API 签名特性
部分客户端专用的 REST API 存在基于参数签名的鉴权,需要使用规定的`appkey`及其对应的`appsec`与原始请求参数进行签名计算,部分`AppKey`及与之对应的`AppSec`已经被公开:见该文档 [APPKey](APPKey.md)
- 不同 `appkey` 对应不同的 app (如客户端、概念版、必剪、漫画、bililink等)
- 不同平台同 app 也会存在不同的 `appkey` (如安卓端、ios端、TV端等)
- 同平台同 app 下不同功能也会存在不同的 `appkey`(如登录专用、取流专用等)
- 不同版本的客户端的 `appkey` 也可能不同
- **appkey与appsec一一对应**
## APP API 签名算法
1. 首先为参数中添加`appkey`字段
2. 然后按照参数的 Key 重新排序
3. 再对这个 Key-Value 进行 url query 序列化,并拼接与之对应的`appsec` (盐) 进行 **md5 Hash 运算**32-bit 字符小写),该 hash 便是 API 签名
4. 最后在参数尾部增添`sign`字段,它的 Value 为上一步计算所得的 hash一并作为表单或 Query 提交
## Demo
该 Demo 提供 [Python](#Python) 和 [Java](#Java) 和 [TS/JS](#TypeScript/JavaScript) 和 [Swift](#Swift) 语言例程
使用 appkey = `1d8b6e7d45233436`, appsec = `560c52ccd288fed045859ed18bffd973` 对如下 `params` 参数进行签名
上述示例`appkey`、`AppSec`均来自文档 [APPKey](APPKey.md)
### Python
```python
import hashlib
import urllib.parse
def appsign(params, appkey, appsec):
'为请求参数进行 APP 签名'
params.update({'appkey': appkey})
params = dict(sorted(params.items())) # 按照 key 重排参数
query = urllib.parse.urlencode(params) # 序列化参数
sign = hashlib.md5((query+appsec).encode()).hexdigest() # 计算 api 签名
params.update({'sign':sign})
return params
appkey = '1d8b6e7d45233436'
appsec = '560c52ccd288fed045859ed18bffd973'
params = {
'id':114514,
'str':'1919810',
'test':'いいよ,こいよ',
}
signed_params = appsign(params, appkey, appsec)
query = urllib.parse.urlencode(signed_params)
print(signed_params)
print(query)
```
输出内容分别是进行 APP 签名的后参数的 key-Value 以及 url query 形式
```
{'appkey': '1d8b6e7d45233436', 'id': 114514, 'str': '1919810', 'test': 'いいよ,こいよ', 'sign': '01479cf20504d865519ac50f33ba3a7d'}
appkey=1d8b6e7d45233436&id=114514&str=1919810&test=%E3%81%84%E3%81%84%E3%82%88%EF%BC%8C%E3%81%93%E3%81%84%E3%82%88&sign=01479cf20504d865519ac50f33ba3a7d
```
### Java
```java
package io.github.cctyl;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.net.URLEncoder;
import java.util.TreeMap;
/**
* @author cctyl
*/
public class AppSigner {
private static final String APP_KEY = "1d8b6e7d45233436";
private static final String APP_SEC = "560c52ccd288fed045859ed18bffd973";
public static String appSign(Map<String, String> params) {
// 为请求参数进行 APP 签名
params.put("appkey", APP_KEY);
// 按照 key 重排参数
Map<String, String> sortedParams = new TreeMap<>(params);
// 序列化参数
StringBuilder queryBuilder = new StringBuilder();
for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
if (queryBuilder.length() > 0) {
queryBuilder.append('&');
}
queryBuilder
.append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8))
.append('=')
.append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8));
}
return generateMD5(queryBuilder .append(APP_SEC).toString());
}
private static String generateMD5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(input.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(String.format("%02x", b));
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
Map<String, String> params = new HashMap<>();
params.put("id", "114514");
params.put("str", "1919810");
params.put("test", "いいよ,こいよ");
System.out.println(appSign(params));
}
}
```
输出结果为01479cf20504d865519ac50f33ba3a7d
### TypeScript/JavaScript
```typescript
import { createHash } from 'node:crypto'
type Params = Record<string, any>
const md5 = (str: string) => createHash('md5').update(str).digest('hex')
/**
* 为请求参数进行 APP 签名
*/
export function appSign(params: Params, appkey: string, appsec: string) {
params.appkey = appkey
const searchParams = new URLSearchParams(params)
searchParams.sort()
return md5(searchParams.toString() + appsec)
}
console.log(
appSign(
{
id: 114514,
str: '1919810',
test: 'いいよ,こいよ',
},
'1d8b6e7d45233436',
'560c52ccd288fed045859ed18bffd973',
),
'01479cf20504d865519ac50f33ba3a7d',
)
```
输出结果为01479cf20504d865519ac50f33ba3a7d
### Swift
```swift
import Foundation
import CommonCrypto
//Swift标准库没有MD5函数所以我们要自己实现一个
func MD5(string: String) -> String {
let length = Int(CC_MD5_DIGEST_LENGTH)
var digest = [UInt8](repeating: 0, count: length)
if let d = string.data(using: .utf8) {
_ = d.withUnsafeBytes { body -> String in
CC_MD5(body.baseAddress, CC_LONG(d.count), &digest)
return ""
}
}
return (0..<length).reduce("") {
$0 + String(format: "%02x", digest[$1])
}
}
func appSign(params: [String:String],appKey:String,appSec:String) -> String {
var signedParams = params
signedParams["appkey"] = appKey
let sortedParams = signedParams.sorted { $0.key < $1.key }
//在制作成query时需要显式addingPercentEncoding转换
let query = sortedParams.map { "\($0.key)=\($0.value.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)" }.joined(separator: "&")
let sign = MD5(string: query+appSec)
return sign
}
//testSign
let appKey = "1d8b6e7d45233436"
let appSec = "560c52ccd288fed045859ed18bffd973"
let signResult = appSign(params: [
"id": "114514",
"str": "1919810",
"test": "いいよ,こいよ",
],appKey:appKey,appSec:appSec)
print(signResult)
```
输出结果为01479cf20504d865519ac50f33ba3a7d

55
docs/misc/sign/APPKey.md Normal file
View File

@ -0,0 +1,55 @@
# APPKey
以下为已知的 APPkey / APPSec及部分使用场景参数信息均来自抓包与逆向工程
| APPKEY | APPSEC | platform<sup>2</sup> | APP类型 | neuronAppId<sup>1</sup> | mobi_app<sup>2</sup> | 备注 |
| :--------------: | :------------------------------: | :------------------: | :----------------: | :---------------------: | :------------------: | :----------------------------------------: |
| 9d5889cf67e615cd | 8fd9bb32efea8cef801fd895bef2713d | `android` | Ai4cCreatorAndroid | | | |
| 1d8b6e7d45233436 | 560c52ccd288fed045859ed18bffd973 | `android` | 粉版 | `1` | `android` | 获取资源通用 |
| 783bbb7264451d82 | 2653583c8873dea268ab9386918b1d65 | `android` | 粉版 | `1` | `android` | 仅获取用户信息时使用(7.X及更新版本) |
| 57263273bc6b67f6 | a0488e488d1567960d3a765e8d129f90 | `android` | 粉版 | `1` | `android` | 可能来自旧版 |
| 07da50c9a0bf829f | 25bdede4e1581c836cab73a48790ca6e | `android` | 概念版 | `3` | `android_b` | |
| 191c3b6b975af184 | 1673b15a09ef5e4427627f47b03a0578 | `android` | 概念版 | `3` | `android_b` | 仅获取用户信息时使用(7.X及更新版本) |
| 178cf125136ca8ea | 34381a26236dd1171185c0beb042e1c6 | `android` | 概念版 | `3` | `android_b` | 可能来自旧版 |
| 7d336ec01856996b | a1ce6983bc89e20a36c37f40c4f1a0dd | `android` | 概念版 | `3` | `android_b` | 可能来自旧版 |
| dfca71928277209b | b5475a8825547a4fc26c7d518eaaa02e | `android` | HD 版 | `5` | `android_hd` | |
| bb3101000e232e27 | 36efcfed79309338ced0380abd824ac1 | `android` | 白版 | `14` | `android_i` | |
| ae57252b0c09105d | c75875c596a69eb55bd119e74b07cfe3 | `android` | 白版 | `14` | `android_i` | 仅获取用户信息时使用(7.X及更新版本) |
| 8e16697a1b4f8121 | f5dd03b752426f2e623d7badb28d190a | `android` | 白版 | `14` | `android_i` | 可能来自旧版 |
| 7d089525d3611b1c | acd495b248ec528c2eed1e862d393126 | `android` | 蓝版 | `30` | `bstar_a` | |
| iVGUTjsxvpLeuDCf | aHRmhWMLkdeMuILqORnYZocwMBpMEOdt | `android` | - | - | - | 视频取流专用, 仅5.X旧版使用 |
| YvirImLGlLANCLvM | JNlZNgfNGKZEpaDTkCdPQVXntXhuiJEM | `ios` | - | - | - | 视频取流专用 |
| 27eb53fc9058f8c3 | c2ed53a74eeefe3cf99fbd01d8c9c375 | `web`/`ios`? | - | - | - | 第三方授权使用 |
| 84956560bc028eb7 | 94aba54af9065f71de72f5508f1cd42e | ? | UWP 版 | - | - | 部分API不接受此appkey, 返回-663错误 |
| 85eb6835b0a1034e | 2ad42749773c441109bdc0191257a664 | ? | UWP 版? | - | - | 部分API不接受此appkey, 返回-663错误 |
| 4ebafd7c4951b366 | 8cb98205e9b2ad3669aad0fce12a4c13 | `ios` | iPhone 客户端? | `iphone` | ? | |
| 8d23902c1688a798 | 710f0212e62bd499b8d3ac6e1db9302a | `android` | AndroidBiliThings | ? | ? | |
| 4c6e1021617d40d9 | e559a59044eb2701b7a8628c86aa12ae | `android` | AndroidMallTicket | ? | ? | |
| c034e8b74130a886 | e4e8966b1e71847dc4a3830f2d078523 | `android` | AndroidOttSdk | `7` | ? | |
| 4409e2ce8ffd12b8 | 59b43e04ad6965f34319062b478f83dd | `android` | 云视听小电视(TV版) | `9`? | `android_tv_yst`? | |
| 37207f2beaebf8d7 | e988e794d4d4b6dd43bc0e89d6e90c43 | `android` | BiliLink | ? | ? | |
| 9a75abf7de2d8947 | 35ca1c82be6c2c242ecc04d88c735f31 | `android` | BiliScan | ? | ? | |
| aae92bc66f3edfab | af125a0d5279fd576c1b4418a3e8276d | ? | PC 投稿工具 | - | ? | |
| bca7e84c2d947ac6 | 60698ba2f68e01ce44738920a0ffe768 | ? | login | - | ? | |
| h9Ejat5tFh81cq8V | BdiI92bjmZ9QRcjJBWv2EEssyjekAGKt | | | | | bilibili游戏 web端 游戏详情页API |
注释:
<sup>1</sup> `neuronAppId`,产品编号,由数据平台分配,详情如下:
- 粉(国内版)=1
- 白GooglePlay 版)=2
- 蓝(东南亚版)=3
- 直播姬=4
- HD=5
- 海外=6
- OTT=7
- 漫画=8
- TV野版=9
- 小视频=10
- 网易漫画=11
- 网易漫画lite=12
- 网易漫画HD=13,
- 国际版=14
<sup>2</sup> `platform`, `mobi_app` 仅供参考, 具体值需要抓包确定.

View File

@ -0,0 +1,62 @@
`bili_ticket` 目前没发现多少风控价值,但是暂且在这里提供一份示例。
由 [@aynuarance](https://github.com/aynuarance) 于 [#903](https://github.com/SocialSisterYi/bilibili-API-collect/issues/903) 提供的思路,根据时间戳使用 `hmac_sha256` 算法计算 `hexsign`
是 [JWT 令牌](https://jwt.io/),有效时长为 259260 秒,即 3 天。
例如 `eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MDI3NDI3NDYsImlhdCI6MTcwMjQ4MzQ4NiwicGx0IjotMX0.xQgtTAc41NA1gzvd9yKUPgucUy_DKcQj6OG1vj8V7ZA`
```json
{
"alg": "HS256",
"kid": "s03",
"typ": "JWT"
}
```
# Python 示例
```python
import hmac
import hashlib
import requests
import time
def hmac_sha256(key, message):
"""
使用HMAC-SHA256算法对给定的消息进行加密
:param key: 密钥
:param message: 要加密的消息
:return: 加密后的哈希值
"""
# 将密钥和消息转换为字节串
key = key.encode('utf-8')
message = message.encode('utf-8')
# 创建HMAC对象使用SHA256哈希算法
hmac_obj = hmac.new(key, message, hashlib.sha256)
# 计算哈希值
hash_value = hmac_obj.digest()
# 将哈希值转换为十六进制字符串
hash_hex = hash_value.hex()
return hash_hex
if __name__ == '__main__':
o = hmac_sha256("XgwSnGZ1p",f"ts{int(time.time())}")
url = "https://api.bilibili.com/bapis/bilibili.api.ticket.v1.Ticket/GenWebTicket"
params = {
"key_id":"ec02",
"hexsign":o,
"context[ts]":f"{int(time.time())}",
"csrf": ''
}
headers = {
'user-agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0"
}
resp = requests.post(url, params=params,headers=headers).json()
```

906
docs/misc/sign/wbi.md Normal file
View File

@ -0,0 +1,906 @@
# WBI 签名
自 2023 年 3 月起Bilibili Web 端部分接口开始采用 WBI 签名鉴权,表现在 REST API 请求时在 Query param 中添加了 `w_rid``wts` 字段。WBI 签名鉴权独立于 [APP 鉴权](APP.md) 与其他 Cookie 鉴权,目前被认为是一种 Web 端风控手段。
经持续观察,大部分查询性接口都已经或准备采用 WBI 签名鉴权,请求 WBI 签名鉴权接口时,若签名参数 `w_rid` 与时间戳 `wts` 缺失、错误,会返回 `v_voucher`(推测为内部记录错误请求的 ID 方便 Debug
```json
{"code":0,"message":"0","ttl":1,"data":{"v_voucher":"voucher_******"}}
```
感谢 [#631](https://github.com/SocialSisterYi/bilibili-API-collect/issues/631) 的研究与逆向工程。
细节更新:[#885](https://github.com/SocialSisterYi/bilibili-API-collect/issues/885)。
## WBI 签名算法
1. 获取实时口令 `img_key`、`sub_key`
从 [nav 接口](../../login/login_info.md#导航栏用户信息) 中获取 `img_url`、`sub_url` 两个字段的参数。
**注:`img_url`、`sub_url` 两个字段的值看似为存于 BFS 中的 png 图片 url实则只是经过伪装的实时 Token故无需且不能试图访问这两个 url**
```json
{"code":-101,"message":"账号未登录","ttl":1,"data":{"isLogin":false,"wbi_img":{"img_url":"https://i0.hdslb.com/bfs/wbi/7cd084941338484aae1ad9425b84077c.png","sub_url":"https://i0.hdslb.com/bfs/wbi/4932caff0ff746eab6f01bf08b70ac45.png"}}}
```
截取其文件名,分别记为 `img_key`、`sub_key`,如上述例子中的 `7cd084941338484aae1ad9425b84077c``4932caff0ff746eab6f01bf08b70ac45`
`img_key`、`sub_key` 全站统一使用,观测知应为**每日更替**,使用时建议做好**缓存和刷新**处理。
特别地,发现部分接口将 `img_key`、`sub_key` 硬编码进 JavaScript 文件内,如搜索接口 `https://s1.hdslb.com/bfs/static/laputa-search/client/assets/index.1ea39bea.js`,暂不清楚原因及影响。
2. 打乱重排实时口令获得 `mixin_key`
把上一步获取到的 `sub_key` 拼接在 `img_key` 后面(下例记为 `raw_wbi_key`),遍历重排映射表 `MIXIN_KEY_ENC_TAB`,取出 `raw_wbi_key` 中对应位置的字符拼接得到新的字符串,截取前 32 位,即为 `mixin_key`
重排映射表 `MIXIN_KEY_ENC_TAB` 长为 64内容如下
```rust
const MIXIN_KEY_ENC_TAB: [u8; 64] = [
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
36, 20, 34, 44, 52
]
```
重排操作如下例:
```rust
fn gen_mixin_key(raw_wbi_key: impl AsRef<[u8]>) -> String {
const MIXIN_KEY_ENC_TAB: [u8; 64] = [
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49, 33, 9, 42,
19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40, 61, 26, 17, 0, 1, 60,
51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11, 36, 20, 34, 44, 52,
];
let raw_wbi_key = raw_wbi_key.as_ref();
let mut mixin_key = {
let binding = MIXIN_KEY_ENC_TAB
.iter()
// 此步操作即遍历 MIXIN_KEY_ENC_TAB取出 raw_wbi_key 中对应位置的字符
.map(|n| raw_wbi_key[*n as usize])
// 并收集进数组内
.collect::<Vec<u8>>();
unsafe { String::from_utf8_unchecked(binding) }
};
let _ = mixin_key.split_off(32); // 截取前 32 位字符
mixin_key
}
```
`img_key` -> `7cd084941338484aae1ad9425b84077c`、`sub_key` -> `4932caff0ff746eab6f01bf08b70ac45` 经过上述操作后得到 `mixin_key` -> `ea1db124af3c7062474693fa704f4ff8`
3. 计算签名(即 `w_rid`
若下方内容为欲签名的**原始**请求参数(以 JavaScript Object 为例)
```javascript
{
foo: '114',
bar: '514',
zab: 1919810
}
```
`wts` 字段的值应为当前以秒为单位的 Unix 时间戳,如 `1702204169`
复制一份参数列表,添加 `wts` 参数,即:
```javascript
{
foo: '114',
bar: '514',
zab: 1919810,
wts: 1702204169
}
```
随后按键名升序排序后编码 URL Query拼接前面得到的 `mixin_key`,如 `bar=514&foo=114&wts=1702204169&zab=1919810ea1db124af3c7062474693fa704f4ff8`,计算其 MD5 即为 `w_rid`
需要注意的是:如果参数值含中文或特殊字符等,编码字符字母应当**大写** (部分库会编码为小写字母),空格应当编码为 `%20`(部分库按 `application/x-www-form-urlencoded` 约定编码为 `+`)。
例如:
```javascript
{
foo: 'one one four',
bar: '五一四',
baz: 1919810
}
```
应该被编码为 `bar=%E4%BA%94%E4%B8%80%E5%9B%9B&baz=1919810&foo=one%20one%20four`
4. 向原始请求参数中添加 `w_rid`、`wts` 字段
将上一步得到的 `w_rid` 以及前面的 `wts` 追加到**原始**请求参数编码得到的 URL Query 后即可,目前看来无需对原始请求参数排序。
如前例最终得到 `bar=514&foo=114&zab=1919810&w_rid=8f6f2b5b3d485fe1886cec6a0be8c5d4&wts=1702204169`
## Demo
含 [Python](#Python)、[JavaScript](#JavaScript)、[Golang](#Golang)、[C#](#CSharp)、[Java](#Java) 和 [Swift](#Swift) 语言编写的 Demo 。
### Python
需要`requests`依赖
```python
from functools import reduce
from hashlib import md5
import urllib.parse
import time
import requests
mixinKeyEncTab = [
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
36, 20, 34, 44, 52
]
def getMixinKey(orig: str):
'对 imgKey 和 subKey 进行字符顺序打乱编码'
return reduce(lambda s, i: s + orig[i], mixinKeyEncTab, '')[:32]
def encWbi(params: dict, img_key: str, sub_key: str):
'为请求参数进行 wbi 签名'
mixin_key = getMixinKey(img_key + sub_key)
curr_time = round(time.time())
params['wts'] = curr_time # 添加 wts 字段
params = dict(sorted(params.items())) # 按照 key 重排参数
# 过滤 value 中的 "!'()*" 字符
params = {
k : ''.join(filter(lambda chr: chr not in "!'()*", str(v)))
for k, v
in params.items()
}
query = urllib.parse.urlencode(params) # 序列化参数
wbi_sign = md5((query + mixin_key).encode()).hexdigest() # 计算 w_rid
params['w_rid'] = wbi_sign
return params
def getWbiKeys() -> tuple[str, str]:
'获取最新的 img_key 和 sub_key'
resp = requests.get('https://api.bilibili.com/x/web-interface/nav')
resp.raise_for_status()
json_content = resp.json()
img_url: str = json_content['data']['wbi_img']['img_url']
sub_url: str = json_content['data']['wbi_img']['sub_url']
img_key = img_url.rsplit('/', 1)[1].split('.')[0]
sub_key = sub_url.rsplit('/', 1)[1].split('.')[0]
return img_key, sub_key
img_key, sub_key = getWbiKeys()
signed_params = encWbi(
params={
'foo': '114',
'bar': '514',
'baz': 1919810
},
img_key=img_key,
sub_key=sub_key
)
query = urllib.parse.urlencode(signed_params)
print(signed_params)
print(query)
```
输出内容分别是进行 Wbi 签名的后参数的 key-Value 以及 url query 形式
```
{'bar': '514', 'baz': '1919810', 'foo': '114', 'wts': '1702204169', 'w_rid': 'd3cbd2a2316089117134038bf4caf442'}
bar=514&baz=1919810&foo=114&wts=1702204169&w_rid=d3cbd2a2316089117134038bf4caf442
```
### JavaScript
需要 `axios`、`md5` 依赖
```javascript
import md5 from 'md5'
const mixinKeyEncTab = [
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
36, 20, 34, 44, 52
]
// 对 imgKey 和 subKey 进行字符顺序打乱编码
const getMixinKey = (orig) => mixinKeyEncTab.map(n => orig[n]).join('').slice(0, 32)
// 为请求参数进行 wbi 签名
function encWbi(params, img_key, sub_key) {
const mixin_key = getMixinKey(img_key + sub_key),
curr_time = Math.round(Date.now() / 1000),
chr_filter = /[!'()*]/g
Object.assign(params, { wts: curr_time }) // 添加 wts 字段
// 按照 key 重排参数
const query = Object
.keys(params)
.sort()
.map(key => {
// 过滤 value 中的 "!'()*" 字符
const value = params[key].toString().replace(chr_filter, '')
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
})
.join('&')
const wbi_sign = md5(query + mixin_key) // 计算 w_rid
return query + '&w_rid=' + wbi_sign
}
// 获取最新的 img_key 和 sub_key
async function getWbiKeys() {
const res = await fetch('https://api.bilibili.com/x/web-interface/nav', {
headers: {
// SESSDATA 字段
Cookie: "SESSDATA=xxxxxx"
}
})
const { data: { wbi_img: { img_url, sub_url } } } = await res.json()
return {
img_key: img_url.slice(
img_url.lastIndexOf('/') + 1,
img_url.lastIndexOf('.')
),
sub_key: sub_url.slice(
sub_url.lastIndexOf('/') + 1,
sub_url.lastIndexOf('.')
)
}
}
async function main() {
const web_keys = await getWbiKeys()
const params = { foo: '114', bar: '514', baz: 1919810 },
img_key = web_keys.img_key,
sub_key = web_keys.sub_key
const query = encWbi(params, img_key, sub_key)
console.log(query)
}
main()
```
输出内容为进行 Wbi 签名的后参数的 url query 形式
```
bar=514&baz=1919810&foo=114&wts=1684805578&w_rid=bb97e15f28edf445a0e4420d36f0157e
```
### Golang
需要 `github.com/tidwall/gjson` 作为依赖
```golang
package main
import (
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
"sync"
"time"
"github.com/tidwall/gjson"
)
var (
mixinKeyEncTab = []int{
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
36, 20, 34, 44, 52,
}
cache sync.Map
lastUpdateTime time.Time
)
func main() {
urlStr := "https://api.bilibili.com/x/space/wbi/acc/info?mid=1850091"
newUrlStr, err := signAndGenerateURL(urlStr)
if err != nil {
fmt.Printf("Error: %s", err)
return
}
req, err := http.NewRequest("GET", newUrlStr, nil)
if err != nil {
fmt.Printf("Error: %s", err)
return
}
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
response, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Printf("Request failed: %s", err)
return
}
defer response.Body.Close()
body, err := io.ReadAll(response.Body)
if err != nil {
fmt.Printf("Failed to read response: %s", err)
return
}
fmt.Println(string(body))
}
func signAndGenerateURL(urlStr string) (string, error) {
urlObj, err := url.Parse(urlStr)
if err != nil {
return "", err
}
imgKey, subKey := getWbiKeysCached()
query := urlObj.Query()
params := map[string]string{}
for k, v := range query {
params[k] = v[0]
}
newParams := encWbi(params, imgKey, subKey)
for k, v := range newParams {
query.Set(k, v)
}
urlObj.RawQuery = query.Encode()
newUrlStr := urlObj.String()
return newUrlStr, nil
}
func encWbi(params map[string]string, imgKey, subKey string) map[string]string {
mixinKey := getMixinKey(imgKey + subKey)
currTime := strconv.FormatInt(time.Now().Unix(), 10)
params["wts"] = currTime
// Sort keys
keys := make([]string, 0, len(params))
for k := range params {
keys = append(keys, k)
}
sort.Strings(keys)
// Remove unwanted characters
for k, v := range params {
v = sanitizeString(v)
params[k] = v
}
// Build URL parameters
query := url.Values{}
for _, k := range keys {
query.Set(k, params[k])
}
queryStr := query.Encode()
// Calculate w_rid
hash := md5.Sum([]byte(queryStr + mixinKey))
params["w_rid"] = hex.EncodeToString(hash[:])
return params
}
func getMixinKey(orig string) string {
var str strings.Builder
for _, v := range mixinKeyEncTab {
if v < len(orig) {
str.WriteByte(orig[v])
}
}
return str.String()[:32]
}
func sanitizeString(s string) string {
unwantedChars := []string{"!", "'", "(", ")", "*"}
for _, char := range unwantedChars {
s = strings.ReplaceAll(s, char, "")
}
return s
}
func updateCache() {
if time.Since(lastUpdateTime).Minutes() < 10 {
return
}
imgKey, subKey := getWbiKeys()
cache.Store("imgKey", imgKey)
cache.Store("subKey", subKey)
lastUpdateTime = time.Now()
}
func getWbiKeysCached() (string, string) {
updateCache()
imgKeyI, _ := cache.Load("imgKey")
subKeyI, _ := cache.Load("subKey")
return imgKeyI.(string), subKeyI.(string)
}
func getWbiKeys() (string, string) {
resp, err := http.Get("https://api.bilibili.com/x/web-interface/nav")
if err != nil {
fmt.Printf("Error: %s", err)
return "", ""
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Printf("Error: %s", err)
return "", ""
}
json := string(body)
imgURL := gjson.Get(json, "data.wbi_img.img_url").String()
subURL := gjson.Get(json, "data.wbi_img.sub_url").String()
imgKey := strings.Split(strings.Split(imgURL, "/")[len(strings.Split(imgURL, "/"))-1], ".")[0]
subKey := strings.Split(strings.Split(subURL, "/")[len(strings.Split(subURL, "/"))-1], ".")[0]
return imgKey, subKey
}
```
### CSharp
无需依赖外部库
```cs
using System.Security.Cryptography;
using System.Text;
using System.Text.Json.Nodes;
class Program
{
private static HttpClient _httpClient = new();
private static readonly int[] MixinKeyEncTab =
{
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49, 33, 9, 42, 19, 29, 28, 14, 39,
12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40, 61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63,
57, 62, 11, 36, 20, 34, 44, 52
};
//对 imgKey 和 subKey 进行字符顺序打乱编码
private static string GetMixinKey(string orig)
{
return MixinKeyEncTab.Aggregate("", (s, i) => s + orig[i])[..32];
}
private static Dictionary<string, string> EncWbi(Dictionary<string, string> parameters, string imgKey,
string subKey)
{
string mixinKey = GetMixinKey(imgKey + subKey);
string currTime = DateTimeOffset.Now.ToUnixTimeSeconds().ToString();
//添加 wts 字段
parameters["wts"] = currTime;
// 按照 key 重排参数
parameters = parameters.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
//过滤 value 中的 "!'()*" 字符
parameters = parameters.ToDictionary(
kvp => kvp.Key,
kvp => new string(kvp.Value.Where(chr => !"!'()*".Contains(chr)).ToArray())
);
// 序列化参数
string query = new FormUrlEncodedContent(parameters).ReadAsStringAsync().Result;
//计算 w_rid
using MD5 md5 = MD5.Create();
byte[] hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(query + mixinKey));
string wbiSign = BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
parameters["w_rid"] = wbiSign;
return parameters;
}
// 获取最新的 img_key 和 sub_key
private static async Task<(string, string)> GetWbiKeys()
{
HttpResponseMessage responseMessage = await _httpClient.SendAsync(new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://api.bilibili.com/x/web-interface/nav"),
});
JsonNode response = JsonNode.Parse(await responseMessage.Content.ReadAsStringAsync())!;
string imgUrl = (string)response["data"]!["wbi_img"]!["img_url"]!;
imgUrl = imgUrl.Split("/")[^1].Split(".")[0];
string subUrl = (string)response["data"]!["wbi_img"]!["sub_url"]!;
subUrl = subUrl.Split("/")[^1].Split(".")[0];
return (imgUrl, subUrl);
}
public static async Task Main()
{
var (imgKey, subKey) = await GetWbiKeys();
Dictionary<string, string> signedParams = EncWbi(
parameters: new Dictionary<string, string>
{
{ "foo", "114" },
{ "bar", "514" },
{ "baz", "1919810" }
},
imgKey: imgKey,
subKey: subKey
);
string query = await new FormUrlEncodedContent(signedParams).ReadAsStringAsync();
Console.WriteLine(query);
}
}
```
输出内容为进行 Wbi 签名的后参数的 url query 形式
```
bar=514&baz=1919810&foo=114&wts=1687541921&w_rid=26e82b1b9b3a11dbb1807a9228a40d3b
```
### Java
需要 `hutool` 依赖
```java
package com.example.demo;
import cn.hutool.crypto.SecureUtil;
import java.util.*;
public class WbiTest {
private static final int[] mixinKeyEncTab = new int[]{
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
36, 20, 34, 44, 52
};
public static String getMixinKey(String imgKey, String subKey) {
String s = imgKey + subKey;
StringBuilder key = new StringBuilder();
for (int i = 0; i < 32; i++) {
key.append(s.charAt(mixinKeyEncTab[i]));
}
return key.toString();
}
public static void main(String[] args) {
String imgKey = "653657f524a547ac981ded72ea172057";
String subKey = "6e4909c702f846728e64f6007736a338";
String mixinKey = getMixinKey(imgKey, subKey);
System.out.println(mixinKey);
//72136226c6a73669787ee4fd02a74c27
//{
// foo: 'one one four',
// bar: '五一四',
// baz: 1919810
//}
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
map.put("foo", "one one four");
map.put("bar", "五一四");
map.put("baz", 1919810);
map.put("wts", System.currentTimeMillis() / 1000);
StringJoiner param = new StringJoiner("&");
//排序 + 拼接字符串
map.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.forEach(entry -> param.add(entry.getKey() + "=" + URLUtil.encode(entry.getValue().toString())));
String s = param + mixinKey;
String wbiSign = SecureUtil.md5(s);
System.out.println(wbiSign);
String finalParam = param + "&w_rid=" + wbiSign;
System.out.println(finalParam);
}
}
```
### PHP
来自[SocialSisterYi/bilibili-API-collect#813](https://github.com/SocialSisterYi/bilibili-API-collect/issues/813)
```php
<?php
/**
* B站 Wbi 测试
* @author Prk
*/
class Bilibili {
private $mixinKeyEncTab = [
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
36, 20, 34, 44, 52
];
function __construct() {
}
public function reQuery(array $query) {
$wbi_keys = $this->getWbiKeys();
return $this->encWbi($query, $wbi_keys['img_key'], $wbi_keys['sub_key']);
}
private function getMixinKey($orig) {
$t = '';
foreach ($this->mixinKeyEncTab as $n) $t .= $orig[$n];
return substr($t, 0, 32);
}
private function encWbi($params, $img_key, $sub_key) {
$mixin_key = $this->getMixinKey($img_key . $sub_key);
$curr_time = time();
$chr_filter = "/[!'()*]/";
$query = [];
$params['wts'] = $curr_time;
ksort($params);
foreach ($params as $key => $value) {
$value = preg_replace($chr_filter, '', $value);
$query[] = urlencode($key) . '=' . urlencode($value);
}
$query = implode('&', $query);
$wbi_sign = md5($query . $mixin_key);
return $query . '&w_rid=' . $wbi_sign;
}
private function getWbiKeys() {
$resp = @json_decode(
$this->curl_get(
'https://api.bilibili.com/x/web-interface/nav',
null,
'https://www.bilibili.com/'
), true
);
if (!$resp) throw new Exception('请求失败');
$img_url = $resp['data']['wbi_img']['img_url'];
$sub_url = $resp['data']['wbi_img']['sub_url'];
return [
'img_key' => substr(basename($img_url), 0, strpos(basename($img_url), '.')),
'sub_key' => substr(basename($sub_url), 0, strpos(basename($sub_url), '.'))
];
}
private function curl_get($url, $cookies = null, $referer = 'https://www.bilibili.com/', $ua = null, $proxy = null, $header = []) {
$ch = curl_init();
$header[] = "Accept: */*";
$header[] = "Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7";
$header[] = "Connection: close";
$header[] = "Cache-Control: max-age=0";
curl_setopt_array($ch, [
CURLOPT_HTTPGET => 1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HTTPHEADER => $header,
CURLOPT_ENCODING => '',
CURLOPT_URL => $url,
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36 Edg/102.0.1245.39',
CURLOPT_TIMEOUT => 15
]);
if ($cookies) curl_setopt(
$ch,
CURLOPT_COOKIE,
$cookies
);
if ($referer) curl_setopt_array($ch, [
CURLOPT_AUTOREFERER => $referer,
CURLOPT_REFERER => $referer
]);
$content = curl_exec($ch);
curl_close($ch);
return $content;
}
}
$c = new Bilibili();
echo $c->reQuery(['foo' => '114', 'bar' => '514', 'baz' => 1919810]);
// bar=514&baz=1919810&foo=114&wts=1700384803&w_rid=4614cb98d60a43e50c3a3033fe3d116b
```
### Rust
需要 serde、serde_json、reqwest、tokio 以及 md5
```rust
use reqwest::header::USER_AGENT;
use serde::Deserialize;
use std::time::{SystemTime, UNIX_EPOCH};
const MIXIN_KEY_ENC_TAB: [usize; 64] = [
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49, 33, 9, 42, 19, 29,
28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40, 61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25,
54, 21, 56, 59, 6, 63, 57, 62, 11, 36, 20, 34, 44, 52,
];
#[derive(Deserialize)]
struct WbiImg {
img_url: String,
sub_url: String,
}
#[derive(Deserialize)]
struct Data {
wbi_img: WbiImg,
}
#[derive(Deserialize)]
struct ResWbi {
data: Data,
}
// 对 imgKey 和 subKey 进行字符顺序打乱编码
fn get_mixin_key(orig: &[u8]) -> String {
MIXIN_KEY_ENC_TAB
.iter()
.map(|&i| orig[i] as char)
.collect::<String>()
}
fn get_url_encoded(s: &str) -> String {
s.chars()
.filter_map(|c| match c.is_ascii_alphanumeric() || "-_.~".contains(c) {
true => Some(c.to_string()),
false => {
// 过滤 value 中的 "!'()*" 字符
if "!'()*".contains(c) {
return None;
}
let encoded = c
.encode_utf8(&mut [0; 4])
.bytes()
.fold("".to_string(), |acc, b| acc + &format!("%{:02X}", b));
Some(encoded)
}
})
.collect::<String>()
}
// 为请求参数进行 wbi 签名
fn encode_wbi(params: &mut Vec<(&str, String)>, (img_key, sub_key): (String, String)) -> String {
let mixin_key = get_mixin_key((img_key + &sub_key).as_bytes());
let cur_time = match SystemTime::now().duration_since(UNIX_EPOCH) {
Ok(t) => t.as_secs(),
Err(_) => panic!("SystemTime before UNIX EPOCH!"),
};
// 添加当前时间戳
params.push(("wts", cur_time.to_string()));
// 重新排序
params.sort_by(|a, b| a.0.cmp(b.0));
let query = params.iter().fold(String::from(""), |acc, (k, v)| {
acc + format!("{}={}&", get_url_encoded(k), get_url_encoded(v)).as_str()
});
let web_sign = format!("{:?}", md5::compute(query.clone() + &mixin_key));
query + &format!("w_rid={}", web_sign)
}
async fn get_wbi_keys() -> Result<(String, String), reqwest::Error> {
let client = reqwest::Client::new();
let ResWbi { data:Data{wbi_img} } = client
.get("https://api.bilibili.com/x/web-interface/nav")
.header(USER_AGENT,"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36")
// SESSDATA=xxxxx
.header("Cookie", "SESSDATA=xxxxx")
.send()
.await?
.json::<ResWbi>()
.await?;
Ok((wbi_img.img_url, wbi_img.sub_url))
}
#[tokio::main]
async fn main() {
let urls = get_wbi_keys().await.unwrap();
let mut params = vec![
("foo", String::from("114")),
("bar", String::from("514")),
("baz", String::from("1919810")),
];
let query = encode_wbi(&mut params, urls);
println!("{}", query);
}
```
### Swift
需要 [Alamofire](https://github.com/Alamofire/Alamofire) 和 [SwiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON) 库
```swift
import Foundation
import CommonCrypto
import Alamofire
import SwiftyJSON
func biliWbiSign(param: String, completion: @escaping (String?) -> Void) {
func getMixinKey(orig: String) -> String {
return String(mixinKeyEncTab.map { orig[orig.index(orig.startIndex, offsetBy: $0)] }.prefix(32))
}
func encWbi(params: [String: Any], imgKey: String, subKey: String) -> [String: Any] {
var params = params
let mixinKey = getMixinKey(orig: imgKey + subKey)
let currTime = round(Date().timeIntervalSince1970)
params["wts"] = currTime
params = params.sorted { $0.key < $1.key }.reduce(into: [:]) { $0[$1.key] = $1.value }
params = params.mapValues { String(describing: $0).filter { !"!'()*".contains($0) } }
let query = params.map { "\($0.key)=\($0.value)" }.joined(separator: "&")
let wbiSign = calculateMD5(string: query + mixinKey)
params["w_rid"] = wbiSign
return params
}
func getWbiKeys(completion: @escaping (Result<(imgKey: String, subKey: String), Error>) -> Void) {
AF.request("https://api.bilibili.com/x/web-interface/nav").responseJSON { response in
switch response.result {
case .success(let value):
let json = JSON(value)
let imgURL = json["data"]["wbi_img"]["img_url"].string ?? ""
let subURL = json["data"]["wbi_img"]["sub_url"].string ?? ""
let imgKey = imgURL.components(separatedBy: "/").last?.components(separatedBy: ".").first ?? ""
let subKey = subURL.components(separatedBy: "/").last?.components(separatedBy: ".").first ?? ""
completion(.success((imgKey, subKey)))
case .failure(let error):
completion(.failure(error))
}
}
}
func calculateMD5(string: String) -> String {
let data = Data(string.utf8)
var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
_ = data.withUnsafeBytes {
CC_MD5($0.baseAddress, CC_LONG(data.count), &digest)
}
return digest.map { String(format: "%02hhx", $0) }.joined()
}
let mixinKeyEncTab = [
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
36, 20, 34, 44, 52
]
getWbiKeys { result in
switch result {
case .success(let keys):
let spdParam = param.components(separatedBy: "&")
var spdDicParam = [String: String]()
spdParam.forEach { pair in
let components = pair.components(separatedBy: "=")
if components.count == 2 {
spdDicParam[components[0]] = components[1]
}
}
let signedParams = encWbi(params: spdDicParam, imgKey: keys.imgKey, subKey: keys.subKey)
let query = signedParams.map { "\($0.key)=\($0.value)" }.joined(separator: "&")
completion(query)
case .failure(let error):
print("Error getting keys: \(error)")
completion(nil)
}
}
}
```

View File

@ -119,6 +119,7 @@ curl 'https://api.bilibili.com/x/note/del' \
<details>
<summary>查看响应示例:</summary>
```json
{
"code": 0,

View File

@ -1,79 +0,0 @@
# API 签名与鉴权
部分客户端专用的 rest api 存在基于 sign 的鉴权,需要使用规定的`appkey`及其对应的`appsec`与原始请求参数进行签名计算
不同`appkey`对应不同的 app (如客户端、概念版、必剪、漫画、bililink等)
不同平台同 app 也会存在不同的 `appkey`(如安卓端、ios端、TV端等)
同平台同 app 下不同功能也会存在不同的 `appkey`(如登录专用、取流专用等)
**appkey与appsec一一对应**
## API签名的计算方式
首先为参数中添加`appkey`字段,然后按照参数的 key 重新排序,再将重排序后的参数使用 url query 格式序列化拼接与该 appkey 相对应的 appsec (盐值) 进行**md5 hash计算**32位小写该 hash 便是 API 签名
为参数尾部增添`sign`字段,它的值为上一步计算所得的 hash一并作为表单提交
**实例:**
使用 appkey = `1d8b6e7d45233436`, appsec = `560c52ccd288fed045859ed18bffd973` 对如下 `params` 参数进行签名
```python
import hashlib
import urllib.parse
def appsign(params, appkey, appsec):
'为请求参数进行 api 签名'
params.update({'appkey': appkey})
params = dict(sorted(params.items())) # 重排序参数 key
query = urllib.parse.urlencode(params) # 序列化参数
sign = hashlib.md5((query+appsec).encode()).hexdigest() # 计算 api 签名
params.update({'sign':sign})
return params
appkey = '1d8b6e7d45233436'
appsec = '560c52ccd288fed045859ed18bffd973'
params = {
'id':114514,
'str':'1919810',
'test':'いいよ,こいよ',
}
signed_params = appsign(params, appkey, appsec)
query = urllib.parse.urlencode(signed_params)
print(signed_params)
print(query)
```
输出以下内容,分别是进行 api 签名后参数的 dict 以及 url query 格式
```
{'appkey': '1d8b6e7d45233436', 'id': 114514, 'str': '1919810', 'test': 'いいよ,こいよ', 'sign': '01479cf20504d865519ac50f33ba3a7d'}
appkey=1d8b6e7d45233436&id=114514&str=1919810&test=%E3%81%84%E3%81%84%E3%82%88%EF%BC%8C%E3%81%93%E3%81%84%E3%82%88&sign=01479cf20504d865519ac50f33ba3a7d
```
## 已知的APPKey
| appkey | appsecsign盐值 | 平台 | 应用 | 备注 |
|------------------|----------------------------------|-----|----------|------|
| 07da50c9a0bf829f | 25bdede4e1581c836cab73a48790ca6e | 安卓 | 概念版 | |
| 1d8b6e7d45233436 | 560c52ccd288fed045859ed18bffd973 | 安卓 | 客户端 | 一般用途 |
| 178cf125136ca8ea | 34381a26236dd1171185c0beb042e1c6 | 安卓 | 概念版 | |
| 27eb53fc9058f8c3 | c2ed53a74eeefe3cf99fbd01d8c9c375 | ios | 客户端 | 一般用途 |
| 37207f2beaebf8d7 | e988e794d4d4b6dd43bc0e89d6e90c43 | 安卓 | biliLink | |
| 4409e2ce8ffd12b8 | 59b43e04ad6965f34319062b478f83dd | TV | 客户端 | |
| 57263273bc6b67f6 | a0488e488d1567960d3a765e8d129f90 | 安卓 | 客户端 | |
| 8d23902c1688a798 | 710f0212e62bd499b8d3ac6e1db9302a | 安卓 | 车机版 | |
| 5dce947fe22167f9 | | 安卓 | 必剪 | |
| 7d336ec01856996b | a1ce6983bc89e20a36c37f40c4f1a0dd | 安卓 | 概念版 | |
| 85eb6835b0a1034e | 2ad42749773c441109bdc0191257a664 | | | |
| 8e16697a1b4f8121 | f5dd03b752426f2e623d7badb28d190a | 安卓 | 国际版 | |
| aae92bc66f3edfab | af125a0d5279fd576c1b4418a3e8276d | PC | 投稿工具 | |
| ae57252b0c09105d | c75875c596a69eb55bd119e74b07cfe3 | 安卓 | 国际版 | |
| bb3101000e232e27 | 36efcfed79309338ced0380abd824ac1 | 安卓 | 国际版 | |
| bca7e84c2d947ac6 | 60698ba2f68e01ce44738920a0ffe768 | 安卓 | 客户端 | 登录专用 |
| cc578d267072c94d | ffb6bb4c4edae2566584dbcacfc6a6ad | 安卓 | 轻视频 | |
| cc8617fd6961e070 | 3131924b941aac971e45189f265262be | 安卓 | 漫画 | |
| iVGUTjsxvpLeuDCf | aHRmhWMLkdeMuILqORnYZocwMBpMEOdt | 安卓 | 客户端 | 取流专用 |
| YvirImLGlLANCLvM | JNlZNgfNGKZEpaDTkCdPQVXntXhuiJEM | ios | 客户端 | 取流专用 |

View File

@ -1,362 +0,0 @@
# bvid说明
2020-03-23 B站推出了全新的稿件视频id`bvid`来接替之前的`avid`,其意义与之相同
详见:
1. [【升级公告】AV号全面升级至BV号专栏](https://www.bilibili.com/read/cv5167957)
2. [【升级公告】AV号全面升级至BV号](https://www.bilibili.com/blackboard/activity-BV-PC.html)
## 概述
### 格式
“bvid”恒为长度为 12 的字符串前两个字母为大写“BV”后 10 个为 base58 计算结果
### 实质
“bvid"为“avid”的base58编码可通过算法进行相互转化
### avid发号方式的变化
从 2009-09-09 09:09:09 [av2](https://www.bilibili.com/video/av2) 的发布到 2020-03-28 19:45:02 [av99999999](https://www.bilibili.com/video/av99999999) 的发布B站结束了以投稿时间为顺序的avid发放改为随机发放avid
~~暗示B站东方要完泪目~~
## 算法概述
算法以及程序主要参考[知乎@mcfx的回答](https://www.zhihu.com/question/381784377/answer/1099438784)
### av->bv算法
注:本算法及示例程序仅能编解码`avid < 29460791296`且暂无法验证`avid >= 29460791296`的正确性
1. a = (avid ⊕ 177451812) + 8728348608
2. 以 i 为循环变量循环 6 次 b[i] = (a / 58 ^ i) % 58
3. 将 b[i] 中各个数字转换为以下码表中的字符
码表:
> fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF
4. 初始化字符串 b[i]=`BV1 4 1 7 `
5. 按照以下字符顺序编码表编码并填充至 b[i]
字符顺序编码表:
> 0 -> 11
>
> 1 -> 10
>
> 2 -> 3
>
> 3 -> 8
>
> 4 -> 4
>
> 5 -> 6
### bv->av算法
为以上算法的逆运算
## 编程实现
使用 Python、C、TypeScript、Java、Kotlin 以及 Golang 等语言作为示例,欢迎社区提交更多例程
### Python
```python
table = 'fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF' # 码表
tr = {} # 反查码表
# 初始化反查码表
for i in range(58):
tr[table[i]] = i
s = [11, 10, 3, 8, 4, 6] # 位置编码表
XOR = 177451812 # 固定异或值
ADD = 8728348608 # 固定加法值
def bv2av(x):
r = 0
for i in range(6):
r += tr[x[s[i]]] * 58 ** i
return (r - ADD) ^ XOR
def av2bv(x):
x = (x ^ XOR) + ADD
r = list('BV1 4 1 7 ')
for i in range(6):
r[s[i]] = table[x // 58 ** i % 58]
return ''. join(r)
print(av2bv(170001))
print(bv2av('BV17x411w7KC'))
```
输出为:
```
BV17x411w7KC
170001
```
### C
```c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
const char table[] = "fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF"; // 码表
char tr[124]; // 反查码表
const unsigned long long XOR = 177451812; // 固定异或值
const unsigned long long ADD = 8728348608; // 固定加法值
const int s[] = {11, 10, 3, 8, 4, 6}; // 位置编码表
// 初始化反查码表
void tr_init() {
for (int i = 0; i < 58; i++)
tr[table[i]] = i;
}
unsigned long long bv2av(char bv[]) {
unsigned long long r = 0;
unsigned long long av;
for (int i = 0; i < 6; i++)
r += tr[bv[s[i]]] * (unsigned long long)pow(58, i);
av = (r - ADD) ^ XOR;
return av;
}
char *av2bv(unsigned long long av) {
char *result = (char*)malloc(13);
strcpy(result,"BV1 4 1 7 ");
av = (av ^ XOR) + ADD;
for (int i = 0; i < 6; i++)
result[s[i]] = table[(unsigned long long)(av / (unsigned long long)pow(58, i)) % 58];
return result;
}
int main() {
tr_init();
printf("%s\n", av2bv(170001));
printf("%u\n", bv2av("BV17x411w7KC"));
return 0;
}
```
输出为:
```
BV17x411w7KC
170001
```
### TypeScript
感谢[#417](https://github.com/SocialSisterYi/bilibili-API-collect/issues/417#issuecomment-1186475063)提供
```typescript
export default class BvCode {
private TABEL = 'fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF'; // 码表
private TR: Record<string, number> = {}; // 反查码表
private S = [11, 10, 3, 8, 4, 6]; // 位置编码表
private XOR = 177451812; // 固定异或值
private ADD = 8728348608; // 固定加法值
constructor() {
// 初始化反查码表
const len = this.TABEL.length;
for (let i = 0; i < len; i++) {
this.TR[this.TABEL[i]] = i;
}
}
av2bv(av: number): string {
const x_ = (av ^ this.XOR) + this.ADD;
const r = ['B', 'V', '1', , , '4', , '1', , '7'];
for (let i = 0; i < 6; i++) {
r[this.S[i]] = this.TABEL[Math.floor(x_ / 58 ** i) % 58];
}
return r.join('');
}
bv2av(bv: string): number {
let r = 0;
for (let i = 0; i < 6; i++) {
r += this.TR[bv[this.S[i]]] * 58 ** i;
}
return (r - this.ADD) ^ this.XOR;
}
}
const bvcode = new BvCode();
console.log(bvcode.av2bv(170001));
console.log(bvcode.bv2av('BV17x411w7KC'));
```
输出为:
```
BV17x411w7KC
170001
```
### Java
```java
/**
* 算法来自https://www.zhihu.com/question/381784377/answer/1099438784
*/
public class Util {
private static final String TABLE = "fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF";
private static final int[] S = new int[]{11, 10, 3, 8, 4, 6};
private static final int XOR = 177451812;
private static final long ADD = 8728348608L;
private static final Map<Character, Integer> MAP = new HashMap<>();
static {
for (int i = 0; i < 58; i++) {
MAP.put(TABLE.charAt(i), i);
}
}
public static String aidToBvid(int aid) {
long x = (aid ^ XOR) + ADD;
char[] chars = new char[]{'B', 'V', '1', ' ', ' ', '4', ' ', '1', ' ', '7', ' ', ' '};
for (int i = 0; i < 6; i++) {
int pow = (int) Math.pow(58, i);
long i1 = x / pow;
int index = (int) (i1 % 58);
chars[S[i]] = TABLE.charAt(index);
}
return String.valueOf(chars);
}
public static int bvidToAid(String bvid) {
long r = 0;
for (int i = 0; i < 6; i++) {
r += MAP.get(bvid.charAt(S[i])) * Math.pow(58, i);
}
return (int) ((r - ADD) ^ XOR);
}
}
```
### Kotlin
```kotlin
/**
* 此程序非完全原创改编自GH站内某大佬的Java程序修改了部分代码且转换为Kotlin
* 算法来源同上
*/
object VideoUtils {
//这里是由知乎大佬不知道用什么方法得出的转换用数字
var ss = intArrayOf(11, 10, 3, 8, 4, 6, 2, 9, 5, 7)
var xor: Long = 177451812 //二进制时加减数1
var add = 8728348608L //十进制时加减数2
//变量初始化工作,加载哈希表
private const val table = "fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF"
private val mp = HashMap<String, Int>()
private val mp2 = HashMap<Int, String>()
//现在定义av号和bv号互转的方法
//定义一个power乘方方法这是转换进制必要的
fun power(a: Int, b: Int): Long {
var power: Long = 1
for (c in 0 until b) power *= a.toLong()
return power
}
//bv转av方法
fun bv2av(s: String): String {
var r: Long = 0
//58进制转换
for (i in 0..57) {
val s1 = table.substring(i, i + 1)
mp[s1] = i
}
for (i in 0..5) {
r += mp[s.substring(ss[i], ss[i] + 1)]!! * power(58, i)
}
//转换完成后,需要处理,带上两个随机数
return (r - add xor xor).toString()
}
//av转bv方法
fun av2bv(st: String): String {
try {
var s = java.lang.Long.valueOf(st.split("av".toRegex()).dropLastWhile { it.isEmpty() }
.toTypedArray()[1])
val sb = StringBuffer("BV1 4 1 7 ")
//逆向思路,先将随机数还原
s = (s xor xor) + add
//58进制转回
for (i in 0..57) {
val s1 = table.substring(i, i + 1)
mp2[i] = s1
}
for (i in 0..5) {
val r = mp2[(s / power(58, i) % 58).toInt()]
sb.replace(ss[i], ss[i] + 1, r!!)
}
return sb.toString()
} catch (e: ArrayIndexOutOfBoundsException) {
return ""
}
}
}
```
### Golang
```go
package main
import "math"
const TABLE = "fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF"
var S = [11]uint{11, 10, 3, 8, 4, 6}
const XOR = 177451812
const ADD = 8728348608
var TR = map[string]int64{}
// 初始化 TR
func init() {
for i := 0; i < 58; i++ {
TR[TABLE[i:i+1]] = int64(i)
}
}
func BV2AV(bv string) int64 {
r := int64(0)
for i := 0; i < 6; i++ {
r += TR[bv[S[i]:S[i]+1]] * int64(math.Pow(58, float64(i)))
}
return (r - ADD) ^ XOR
}
func AV2BV(av int64) string {
x := (av ^ XOR) + ADD
r := []rune("BV1 4 1 7 ")
for i := 0; i < 6; i++ {
r[S[i]] = rune(TABLE[x/int64(math.Pow(58, float64(i)))%58])
}
return string(r)
}
func main() {
println(AV2BV(170001))
println(BV2AV("BV17x411w7KC"))
}
```
输出为:
```
BV17x411w7KC
170001
```

View File

@ -2,10 +2,14 @@
## 获取默认搜索内容web端
> https://api.bilibili.com/x/web-interface/search/default
> https://api.bilibili.com/x/web-interface/wbi/search/default
> ~~https://api.bilibili.com/x/web-interface/search/default~~ (旧链接)
*请求方式GET*
鉴权方式:[Wbi 签名](../misc/sign/wbi.md)
默认搜索为搜索框中默认填充内容,用于官方推荐内容,若不输入点击搜索按钮跳转为`url`中的链接
**json回复**
@ -353,6 +357,12 @@ curl 'https://s.search.bilibili.com/main/hotword'
带有转义
**url参数**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------- | ---- | ---------------- | ------ | ---- |
| limit | num | 热搜数量 | 非必要 | 1~100 |
**json回复**
根对象:
@ -376,16 +386,16 @@ curl 'https://s.search.bilibili.com/main/hotword'
| ---- | ---- | --------------- | ------------ |
| 0 | obj | 榜单第1名 | |
| n | obj | 榜单第n+1名 | 按照名次顺序 |
| 20 | obj | 榜单第20名 | 最后一项 |
| 20/limit | obj | 榜单第20名 | 最后一项 |
`list`数组中的对象:
| 字段 | 类型 | 内容 | 备注 |
| ---------- | ---- | -------- | ------- |
| position | num | 名次 | 1-20 |
| position | num | 名次 | 1-20/limit |
| keyword | str | 关键词 | |
| show_name | str | 完整关键词| |
| word_type | num | 条目属性 | 均返回8 |
| word_type | num | 条目属性 | 4<br />5<br />6<br />8默认 |
| icon | str | 图标url | |
| hot_id | num | 热词id | 大概是吧? |
@ -400,163 +410,165 @@ curl 'https://app.bilibili.com/x/v2/search/trending/ranking'
```json
{
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"trackid": "12666380188451258075",
"list": [
{
"position": 1,
"keyword": "流浪地球2刘德华",
"show_name": "流浪地球2刘德华造型",
"word_type": 8,
"icon": "http://i0.hdslb.com/bfs/feed-admin/4d579fb61f9655316582db193118bba3a721eec0.png",
"hot_id": 11003
},
{
"position": 2,
"keyword": "QQ飞车手游飞跃黄河",
"show_name": "QQ飞车手游飞跃黄河",
"word_type": 8,
"icon": "http://i0.hdslb.com/bfs/feed-admin/4d579fb61f9655316582db193118bba3a721eec0.png",
"hot_id": 11012
},
{
"position": 3,
"keyword": "西工大遭网络攻击最新调查",
"show_name": "西工大遭网络攻击最新调查",
"word_type": 8,
"icon": "http://i0.hdslb.com/bfs/feed-admin/e9e7a2d8497d4063421b685e72680bf1cfb99a0d.png",
"hot_id": 10996
},
{
"position": 4,
"keyword": "EDG 起诉",
"show_name": "EDGJieJie已起诉多家企业",
"word_type": 8,
"icon": "http://i0.hdslb.com/bfs/feed-admin/4d579fb61f9655316582db193118bba3a721eec0.png",
"hot_id": 11004
},
{
"position": 5,
"keyword": "隐入尘烟",
"show_name": "隐入尘烟全平台下架",
"word_type": 8,
"icon": "http://i0.hdslb.com/bfs/feed-admin/e9e7a2d8497d4063421b685e72680bf1cfb99a0d.png",
"hot_id": 10992
},
{
"position": 6,
"keyword": "原神半年内最良心封神池",
"show_name": "原神半年内最良心封神池",
"word_type": 8,
"hot_id": 10987
},
{
"position": 7,
"keyword": "高校回应设国内首个元宇宙院系",
"show_name": "高校回应设国内首个元宇宙院系",
"word_type": 8,
"hot_id": 10988
},
{
"position": 8,
"keyword": "美宇宙飞船成功撞击小行星",
"show_name": "美宇宙飞船成功撞击小行星",
"word_type": 8,
"hot_id": 10994
},
{
"position": 9,
"keyword": "你薅的羊毛可能已违法",
"show_name": "你薅的羊毛可能已违法",
"word_type": 8,
"hot_id": 10991
},
{
"position": 10,
"keyword": "火锅店剩锅底重新给顾客",
"show_name": "火锅店剩锅底重新给顾客",
"word_type": 1,
"hot_id": 11014
},
{
"position": 11,
"keyword": "海月",
"show_name": "王者海月逆天",
"word_type": 8,
"hot_id": 10999
},
{
"position": 12,
"keyword": "周琦重返NBL",
"show_name": "徐静雨评周琦重返NBL",
"word_type": 8,
"icon": "http://i0.hdslb.com/bfs/feed-admin/4d579fb61f9655316582db193118bba3a721eec0.png",
"hot_id": 11007
},
{
"position": 13,
"keyword": "小超梦剑魔连招",
"show_name": "小超梦剑魔QA连招",
"word_type": 8,
"hot_id": 11006
},
{
"position": 14,
"keyword": "东八区的先生们已下架",
"show_name": "东八区的先生们已下架",
"word_type": 8,
"hot_id": 10955
},
{
"position": 15,
"keyword": "三国杀新武将全惠解",
"show_name": "三国杀新武将全惠解",
"word_type": 8,
"icon": "http://i0.hdslb.com/bfs/feed-admin/4d579fb61f9655316582db193118bba3a721eec0.png",
"hot_id": 11009
},
{
"position": 16,
"keyword": "ALGS训练赛",
"show_name": "ALGS训练赛",
"word_type": 8,
"icon": "http://i0.hdslb.com/bfs/feed-admin/4d579fb61f9655316582db193118bba3a721eec0.png",
"hot_id": 11011
},
{
"position": 17,
"keyword": "王者青白蛇皮肤优化",
"show_name": "王者青白蛇皮肤优化",
"word_type": 8,
"hot_id": 11000
},
{
"position": 18,
"keyword": "普京授予斯诺登俄公民身份",
"show_name": "普京授予斯诺登俄公民身份",
"word_type": 1,
"hot_id": 10977
},
{
"position": 19,
"keyword": "赛诺角色演示",
"show_name": "原神赛诺角色演示",
"word_type": 8,
"hot_id": 10998
},
{
"position": 20,
"keyword": "COD19被玩坏了",
"show_name": "COD19被玩坏了",
"word_type": 8,
"hot_id": 10971
}
],
"exp_str": "8000#5509#6605#7708"
}
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"trackid": "2578006123492681222",
"list": [{
"position": 1,
"keyword": "列车延误乘务员哽咽安抚乘客",
"show_name": "列车延误乘务员哽咽安抚乘客",
"word_type": 5,
"icon": "http://i0.hdslb.com/bfs/activity-plat/static/20221213/eaf2dd702d7cc14d8d9511190245d057/lrx9rnKo24.png",
"hot_id": 107814,
"is_commercial": "0"
}, {
"position": 2,
"keyword": "黑神话悟空首次线下试玩",
"show_name": "黑神话悟空首次线下试玩",
"word_type": 5,
"icon": "http://i0.hdslb.com/bfs/activity-plat/static/20221213/eaf2dd702d7cc14d8d9511190245d057/lrx9rnKo24.png",
"hot_id": 107781,
"is_commercial": "0"
}, {
"position": 3,
"keyword": "22万人打出9.9分的动画",
"show_name": "22万人打出9.9分的动画",
"word_type": 6,
"icon": "https://i0.hdslb.com/bfs/legacy/463fa23613670218608e68247a137dd071c0e9c8.png",
"hot_id": 107818,
"is_commercial": "0"
}, {
"position": 4,
"keyword": "冰冻近五万年线虫被复活",
"show_name": "冰冻近五万年线虫被复活",
"word_type": 5,
"icon": "http://i0.hdslb.com/bfs/activity-plat/static/20221213/eaf2dd702d7cc14d8d9511190245d057/lrx9rnKo24.png",
"hot_id": 107774,
"is_commercial": "0"
}, {
"position": 5,
"keyword": "LNG前任和现任的较量",
"show_name": "LNG前任和现任的较量",
"word_type": 4,
"icon": "http://i0.hdslb.com/bfs/activity-plat/static/20221118/eaf2dd702d7cc14d8d9511190245d057/UF7B1wVKT2.png",
"hot_id": 107853,
"is_commercial": "0"
}, {
"position": 6,
"keyword": "LOL手游剑姬女警新皮",
"show_name": "LOL手游剑姬女警新皮",
"word_type": 8,
"hot_id": 107841,
"is_commercial": "0"
}, {
"position": 7,
"keyword": "抽奖中金条却因过号被取消",
"show_name": "抽奖中金条却因过号被取消",
"word_type": 8,
"hot_id": 107817,
"is_commercial": "0"
}, {
"position": 8,
"keyword": "雪王到长城开蜜雪冰城",
"show_name": "雪王到长城开蜜雪冰城",
"word_type": 4,
"icon": "http://i0.hdslb.com/bfs/activity-plat/static/20221118/eaf2dd702d7cc14d8d9511190245d057/UF7B1wVKT2.png",
"hot_id": 107849,
"is_commercial": "0"
}, {
"position": 9,
"keyword": "堡垒之夜联动终结者",
"show_name": "堡垒之夜联动终结者",
"word_type": 8,
"hot_id": 107846,
"is_commercial": "0"
}, {
"position": 10,
"keyword": "王者新英雄海诺动画",
"show_name": "王者新英雄海诺动画",
"word_type": 4,
"icon": "http://i0.hdslb.com/bfs/activity-plat/static/20221118/eaf2dd702d7cc14d8d9511190245d057/UF7B1wVKT2.png",
"hot_id": 107870,
"is_commercial": "0"
}, {
"position": 11,
"keyword": "周星驰功夫10万字拆解",
"show_name": "周星驰功夫10万字拆解",
"word_type": 4,
"icon": "http://i0.hdslb.com/bfs/activity-plat/static/20221118/eaf2dd702d7cc14d8d9511190245d057/UF7B1wVKT2.png",
"hot_id": 107848,
"is_commercial": "0"
}, {
"position": 12,
"keyword": "张杰铁粉彭奶奶去世",
"show_name": "张杰铁粉彭奶奶去世",
"word_type": 4,
"icon": "http://i0.hdslb.com/bfs/activity-plat/static/20221118/eaf2dd702d7cc14d8d9511190245d057/UF7B1wVKT2.png",
"hot_id": 107840,
"is_commercial": "0"
}, {
"position": 13,
"keyword": "李玟二姐回应礼服争议",
"show_name": "李玟二姐回应礼服争议",
"word_type": 8,
"hot_id": 107833,
"is_commercial": "0"
}, {
"position": 14,
"keyword": "洪水中飘来冰箱市民取走饮料",
"show_name": "洪水中飘来冰箱市民取走饮料",
"word_type": 8,
"hot_id": 107802,
"is_commercial": "0"
}, {
"position": 15,
"keyword": "LOL斗魂觉醒佛耶戈语音",
"show_name": "LOL斗魂觉醒佛耶戈语音",
"word_type": 8,
"hot_id": 107790,
"is_commercial": "0"
}, {
"position": 16,
"keyword": "全面落实带薪休假制度",
"show_name": "全面落实带薪休假制度",
"word_type": 4,
"icon": "http://i0.hdslb.com/bfs/activity-plat/static/20221118/eaf2dd702d7cc14d8d9511190245d057/UF7B1wVKT2.png",
"hot_id": 107839,
"is_commercial": "0"
}, {
"position": 17,
"keyword": "花少北 把病娇治好了",
"show_name": "花少北 把病娇治好了",
"word_type": 8,
"hot_id": 107782,
"is_commercial": "0"
}, {
"position": 18,
"keyword": "2.28米高的村超娃",
"show_name": "2.28米高的村超娃",
"word_type": 8,
"hot_id": 107805,
"is_commercial": "0"
}, {
"position": 19,
"keyword": "当在动漫中不小心撞到",
"show_name": "当在动漫中不小心撞到",
"word_type": 8,
"hot_id": 107832,
"is_commercial": "0"
}, {
"position": 20,
"keyword": "台风卡努路径趋向日本",
"show_name": "台风卡努路径趋向日本",
"word_type": 8,
"hot_id": 107800,
"is_commercial": "0"
}],
"exp_str": "8000#5508#6604#7703",
"hotword_egg_info": "0"
}
}
```

View File

@ -4,12 +4,16 @@
## 综合搜索web端
> https://api.bilibili.com/x/web-interface/search/all/v2
> https://api.bilibili.com/x/web-interface/wbi/search/all/v2
> ~~https://api.bilibili.com/x/web-interface/search/all/v2~~ (旧链接)
*方式GET*
认证方式CookieSESSDATA
鉴权方式:[Wbi 签名](../misc/sign/wbi.md)
返回和关键字相关的20条信息
综合搜索为默认搜索方式主要用于优先搜索用户、影视、番剧、游戏、话题等并加载第一页的20项相关视频还用于展示各个类型的结果数目便于进一步分类搜索
@ -37,7 +41,7 @@
| ---------------- | ----- | ---------------- | ---------------- |
| seid | str | 搜索id | |
| page | num | 页数 | 固定为1 |
| pagesize | num | 每页条数 | 固定为20 |
| page_size | num | 每页条数 | 固定为20 |
| numResults | num | 总条数 | 最大值为1000 |
| numPages | num | 分页数 | 最大值为50 |
| suggest_keyword | str | 空 | **作用尚不明确** |
@ -579,12 +583,16 @@ curl -G 'https://api.bilibili.com/x/web-interface/search/all/v2' \
## 分类搜索web端
> https://api.bilibili.com/x/web-interface/search/type
> https://api.bilibili.com/x/web-interface/wbi/search/type
> ~~https://api.bilibili.com/x/web-interface/search/type~~ (旧链接)
*请求方式GET*
认证方式CookieSESSDATA
鉴权方式:[Wbi 签名](../misc/sign/wbi.md)
根据关键词进行搜索返回结果每页20项
**url参数**

View File

@ -0,0 +1,84 @@
# 青少年模式
## 开启/关闭
> https://app.bilibili.com/x/v2/account/teenagers/update
*请求方式POST*
认证方式APP详见[设备各类标识算法](../misc/device_identity.md)
**POST参数**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|--------|-----|-------|---------|-----|
| appkey | str | APP密钥 | APP必要 | |
| ts | num | 当前时间戳 | APP必要 | |
| sign | str | APP签名 | APP必要 | |
| access_key | str | APP登录Token | APP必要 | |
| device_model | str | 设备 Model | APP必要 | |
| channel | str | APP下载渠道 | APP必要 | 比如yingyongbao |
| mobi_app | str |APP 包类型 | APP必要 | |
| platform | str |平台类型| APP必要 | android |
| c_locale | str |语言| 非必要 | zh_CN |
| s_locale | str |语言| 非必要 | zh_CN |
| statistics | str | ? | 必要 | 一般固定为{"appId":1,"platform":3,"version":"7.27.0","abtest":""},非key-value入参需要转URL编码 |
| pwd | num |密码| 必要 | 开启时为4位关闭时必须为空 |
| teenagers_mode | num |开启/关闭模式| 必要 | 0为开启1为关闭 |
| teenagers_status | num |当前模式状态| 必要 | 0为已经开启1为目前关闭 |
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | ------ | -------- | ---------------------------- |
| code | num | 返回值 | 0成功 <br />-400请求错误 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
**示例:**
关闭本账号的青少年模式pwd=&teenagers_mode=1&teenagers_status=0
```shell
curl --location 'https://app.bilibili.com/x/v2/account/teenagers/update' \
--header 'Device-Id: 你的设备id' \
--header 'Fp_local: 你的本地设备指纹' \
--header 'Fp_remote: 你的远程设备指纹' \
--header 'Session_id: 会话id' \
--header 'App-Key: android' \
--header 'Content-Type: application/x-www-form-urlencoded; charset=utf-8' \
--data-urlencode 'access_key=你的access_key' \
--data-urlencode 'appkey=1d8b6e7d45233436' \
--data-urlencode 'build=6270200' \
--data-urlencode 'c_locale=zh_CN' \
--data-urlencode 'channel=yingyongbao' \
--data-urlencode 'device_model=samsung%257CSM-G955N' \
--data-urlencode 'mobi_app=android' \
--data-urlencode 'platform=android' \
--data-urlencode 's_locale=zh_CN' \
--data-urlencode 'statistics=%257B%2522appId%2522%253A1%252C%2522platform%2522%253A3%252C%2522version%2522%253A%25226.27.0%2522%252C%2522abtest%2522%253A%2522%2522%257D' \
--data-urlencode 'pwd=' \
--data-urlencode 'teenagers_mode=1' \
--data-urlencode 'teenagers_status=0' \
--data-urlencode 'ts=1699301298' \
--data-urlencode 'sign=0666c38cb79691c4a0d9570a0669ec96' \
```
<details>
<summary>查看响应示例:</summary>
```json
{
"code": 0,
"message": "0",
"ttl": 1
}
```
pwd有数值时
```json
{
"code": -400,
"message": "关闭时密码必须为空",
"ttl": 1
}
```
</details>

View File

@ -4,70 +4,76 @@
## 用户空间详细信息
> https://api.bilibili.com/x/space/acc/info
> https://api.bilibili.com/x/space/wbi/acc/info
*请求方式GET*
认证方式Cookie(SESSDATA)
认证方式CookieSESSDATA
鉴权方式:[Wbi 签名](../misc/sign/wbi.md), Cookie (对于某些 IP 地址,需要在 Cookie 中提供任意非空的 `buvid3` 字段)
~~该接口的旧版 API https://api.bilibili.com/x/space/acc/info~~(已废弃,不建议使用)
**url参数**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|-----|-----|---------|-----|-----|
| mid | num | 目标用户mid | 必要 | |
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------ | ---- | ----------- | ------ | ------------------------------------ |
| mid | num | 目标用户mid | 必要 | |
| w_rid | str | Wbi 签名 | 必要 | 详见 [Wbi 签名](../misc/sign/wbi.md) |
| wts | num | 当前时间戳 | 必要 | 详见 [Wbi 签名](../misc/sign/wbi.md) |
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
|---------|-----|------|---------------------|
| code | num | 返回值 | 0成功<br />-400请求错误 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
| data | obj | 信息本体 | |
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------------------------------------------------------------ |
| code | num | 返回值 | 0成功<br />-400请求错误<br />-403访问权限不足<br />-404用户不存在如注销账号 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
| data | obj | 信息本体 | |
`data`对象:
| 字段 | 类型 | 内容 | 备注 |
|------------------|------|------------|--------------------------------------------------------------------------------------------------|
| mid | num | mid | |
| name | str | 昵称 | |
| sex | str | 性别 | 男/女/保密 |
| face | str | 头像链接 | |
| face_nft | num | 是否为 nft 头像 | `0`不是nft头像<br />`1`是 nft 头像 |
| face_nft_type | num | | 0,1 |
| sign | str | 签名 | |
| 字段 | 类型 | 内容 | 备注 |
| ---------------- | ---- | ---------------- | ------------------------------------------------------------ |
| mid | num | mid | |
| name | str | 昵称 | |
| sex | str | 性别 | 男/女/保密 |
| face | str | 头像链接 | |
| face_nft | num | 是否为 NFT 头像 | 0不是 NFT 头像<br />1是 NFT 头像 |
| face_nft_type | num | NFT 头像类型? | |
| sign | str | 签名 | |
| rank | num | 用户权限等级 | 目前应该无任何作用<br/>50000级未答题<br/>10000普通会员<br/>20000字幕君<br/>25000VIP<br/>30000真·职人<br/>32000管理员 |
| level | num | 当前等级 | 0-6级 |
| jointime | num | 注册时间 | 此接口返回恒为`0` |
| moral | num | 节操值 | 此接口返回恒为`0` |
| silence | num | 封禁状态 | 0正常<br />1被封 |
| coins | num | 硬币数 | 需要登录(Cookie) <br />只能查看自己的<br />默认为0 |
| fans_badge | bool | 是否具有粉丝勋章 | false<br />true |
| fans_medal | obj | 粉丝勋章信息 | |
| official | obj | 认证信息 | |
| vip | obj | 会员信息 | |
| pendant | obj | 头像框信息 | |
| nameplate | obj | 勋章信息 | |
| user_honour_info | obj | | |
| is_followed | bool | 是否关注此用户 | true已关注<br />false未关注<br />需要登录(Cookie) <br />未登录恒为false |
| top_photo | str | 主页头图链接 | |
| theme | obj | 空 | **作用尚不明确** |
| sys_notice | obj | 系统通知 | 无内容则为空对象<br />主要用于展示如用户争议、纪念账号等等 |
| live_room | obj | 直播间信息 | |
| birthday | str | 生日 | MM-DD<br />如设置隐私为空 |
| school | obj | 学校 | |
| profession | obj | 专业资质信息 | |
| tags | null | 个人标签 | |
| series | obj | | |
| is_senior_member | num | 是否为硬核会员 | 0<br />1 |
| mcn_info | null | | |
| gaia_res_type | num | | |
| gaia_data | null | | |
| is_risk | bool | | |
| elec | obj | 充电信息 | |
| contract | obj | 是否显示老粉计划 | |
| level | num | 当前等级 | 0-6 级 |
| jointime | num | 注册时间 | 此接口返回恒为`0` |
| moral | num | 节操值 | 此接口返回恒为`0` |
| silence | num | 封禁状态 | 0正常<br />1被封 |
| coins | num | 硬币数 | 需要登录Cookie <br />只能查看自己的<br />默认为`0` |
| fans_badge | bool | 是否具有粉丝勋章 | false<br />true有 |
| fans_medal | obj | 粉丝勋章信息 | |
| official | obj | 认证信息 | |
| vip | obj | 会员信息 | |
| pendant | obj | 头像框信息 | |
| nameplate | obj | 勋章信息 | |
| user_honour_info | obj | | |
| is_followed | bool | 是否关注此用户 | true已关注<br />false未关注<br />需要登录Cookie <br />未登录恒为`false` |
| top_photo | str | 主页头图链接 | |
| theme | obj | | |
| sys_notice | obj | 系统通知 | 无内容则为空对象<br />主要用于展示如用户争议、纪念账号等等的小黄条 |
| live_room | obj | 直播间信息 | |
| birthday | str | 生日 | MM-DD<br />如设置隐私为空 |
| school | obj | 学校 | |
| profession | obj | 专业资质信息 | |
| tags | null | 个人标签 | |
| series | obj | | |
| is_senior_member | num | 是否为硬核会员 | 0<br />1是 |
| mcn_info | null | | |
| gaia_res_type | num | | |
| gaia_data | null | | |
| is_risk | bool | | |
| elec | obj | 充电信息 | |
| contract | obj | 是否显示老粉计划 | |
`rank`示例
@ -108,29 +114,29 @@
`data`中的`official`对象:
| 字段 | 类型 | 内容 | 备注 |
|-------|-----|------|-----------------------------------------|
| role | num | 认证类型 | 0<br />1 2 7 9个人认证<br />3 4 5 6机构认证 |
| title | str | 认证信息 | 无为空 |
| desc | str | 认证备注 | 无为空 |
| type | num | 是否认证 | -1<br />0个人认证<br />1机构认证 |
| 字段 | 类型 | 内容 | 备注 |
| ----- | ---- | -------- | ---------------------------------------- |
| role | num | 认证类型 | 见 [用户认证类型一览](official_role.md) |
| title | str | 认证信息 | 无为空 |
| desc | str | 认证备注 | 无为空 |
| type | num | 是否认证 | -1<br />0个人认证<br />1机构认证 |
`data`中的`vip`对象:
| 字段 | 类型 | 内容 | 备注 |
|----------------------|-----|-----------|----------------------------------------------|
| type | num | 会员类型 | 0<br />1月大会员<br />2年度及以上大会员 |
| status | num | 会员状态 | 0<br />1有 |
| due_date | num | 会员过期时间 | Unix时间戳(毫秒) |
| vip_pay_type | num | 支付类型 | 0未支付常见于官方账号<br />1已支付以正常渠道获取的大会员均为此值 |
| theme_type | num | 0 | 作用尚不明确 |
| label | obj | 会员标签 | |
| avatar_subscript | num | 是否显示会员图标 | 0不显示<br />1显示 |
| nickname_color | str | 会员昵称颜色 | 颜色码,一般为`#FB7299`,曾用于愚人节改变大会员配色 |
| role | num | 大角色类型 | 1月度大会员<br/>3年度大会员<br/>7十年大会员<br/>15百年大会员 |
| avatar_subscript_url | str | 大会员角标地址 | |
| tv_vip_status | num | 电视大会员状态 | 0未开通 |
| tv_vip_pay_type | num | 电视大会员支付类型 | |
| 字段 | 类型 | 内容 | 备注 |
| -------------------- | ---- | ------------------ | ------------------------------------------------------------ |
| type | num | 会员类型 | 0<br />1月大会员<br />2年度及以上大会员 |
| status | num | 会员状态 | 0<br />1 |
| due_date | num | 会员过期时间 | 毫秒时间戳 |
| vip_pay_type | num | 支付类型 | 0未支付常见于官方账号<br />1已支付以正常渠道获取的大会员均为此值 |
| theme_type | num | 0 | 作用尚不明确 |
| label | obj | 会员标签 | |
| avatar_subscript | num | 是否显示会员图标 | 0不显示<br />1显示 |
| nickname_color | str | 会员昵称颜色 | 颜色码,一般为`#FB7299`,曾用于愚人节改变大会员配色 |
| role | num | 大角色类型 | 1月度大会员<br/>3年度大会员<br/>7十年大会员<br/>15百年大会员 |
| avatar_subscript_url | str | 大会员角标地址 | |
| tv_vip_status | num | 电视大会员状态 | 0未开通 |
| tv_vip_pay_type | num | 电视大会员支付类型 | |
`vip`中的`label`对象:
@ -219,19 +225,19 @@
`sys_notice`示例
| id | content | url | notice_type | 示例用户 |
|-----|-------------------------------------------------|-----|-------------|-------------------------------------------------------------------------------------------------|
| 5 | 该用户存在争议行为,已冻结其帐号功能的使用 | | 1 | [82385070](https://space.bilibili.com/82385070) |
| 8 | 该用户存在较大争议,请谨慎甄别其内容 | | 1 | [28062215](https://space.bilibili.com/28062215) |
| 11 | 该账号涉及合约争议,暂冻结其账号功能使用。详见公告-> | | 1 |
| 16 | 该UP主内容存在争议请注意甄别视频内信息 | | 1 | [382534165](https://space.bilibili.com/382534165) |
| 20 | 请允许我们在此献上最后的告别,以此纪念其在哔哩哔哩留下的回忆与足迹。请点此查看纪念账号相关说明 | | 2 |
| 22 | 该账号涉及合约诉讼,封禁其账号使用。 | |
| 24 | 该账号涉及合约争议,暂冻结其账号功能使用 | | 1 | [291229008](https://space.bilibili.com/291229008) |
| 25 | 该用户涉及严重指控,暂冻结其账号功能使用 | | 1 | [81447581](https://space.bilibili.com/81447581) |
| 31 | 该用户涉及严重指控,暂冻结其账号功能使用 | | 1 | [22439273](https://space.bilibili.com/22439273) |
| 34 | 该用户涉及严重指控,暂冻结其账号功能使用 | | 1 | [1640486775](https://space.bilibili.com/1640486775) |
| 36 | 该账户存在争议,请谨慎甄别 | | 1 | [198297](https://space.bilibili.com/198297)<br/>[18149131](https://space.bilibili.com/18149131) |
| id | content | notice_type | 示例用户 |
|-----|-------------------------------------------------|-------------|-------------------------------------------------------------------------------------------------|
| 5 | 该用户存在争议行为,已冻结其帐号功能的使用 | 1 | [82385070](https://space.bilibili.com/82385070) |
| 8 | 该用户存在较大争议,请谨慎甄别其内容 | 1 | [28062215](https://space.bilibili.com/28062215) |
| 11 | 该账号涉及合约争议,暂冻结其账号功能使用。详见公告-> | 1 ||
| 16 | 该UP主内容存在争议请注意甄别视频内信息 | 1 | [382534165](https://space.bilibili.com/382534165) |
| 20 | 请允许我们在此献上最后的告别,以此纪念其在哔哩哔哩留下的回忆与足迹。请点此查看纪念账号相关说明 | 2 |[212535360](https://space.bilibili.com/212535360)|
|22| 该账号涉及合约诉讼,封禁其账号使用 | ||
| 24 | 该账号涉及合约争议,暂冻结其账号功能使用 | 1 | [291229008](https://space.bilibili.com/291229008) |
| 25 | 该用户涉及严重指控,暂冻结其账号功能使用 | 1 | [81447581](https://space.bilibili.com/81447581) |
| 31 | 该用户涉及严重指控,暂冻结其账号功能使用 | 1 | [22439273](https://space.bilibili.com/22439273) |
| 34 | 该用户涉及严重指控,暂冻结其账号功能使用 | 1 | [1640486775](https://space.bilibili.com/1640486775) |
| 36 | 该账户存在争议,请谨慎甄别 | 1 | [198297](https://space.bilibili.com/198297)<br/>[18149131](https://space.bilibili.com/18149131) |
`data`中的`live_room`对象:
@ -314,12 +320,14 @@
**示例:**
查询用户`mid=2`的详细信息
查询用户`mid=2`的详细信息Wbi 签名的 `wts`、`w_rid`生成方式详见 [Wbi 签名](../misc/sign/wbi.md) 文档
```shell
curl -G 'https://api.bilibili.com/x/space/acc/info' \
--data-urlencode 'mid=2' \
-b 'SESSDATA=xxx'
curl -G 'https://api.bilibili.com/x/space/wbi/acc/info' \
--data-urlencode 'mid=2' \
--data-urlencode 'wts=1685070149' \
--data-urlencode 'w_rid=f7b376124782ae8cb42c56fdd69144ed' \
-b 'SESSDATA=xxx'
```
<details>
@ -327,204 +335,163 @@ curl -G 'https://api.bilibili.com/x/space/acc/info' \
```json
{
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"mid": 2,
"name": "碧诗",
"sex": "男",
"face": "https://i2.hdslb.com/bfs/face/ef0457addb24141e15dfac6fbf45293ccf1e32ab.jpg",
"face_nft": 0,
"face_nft_type": 0,
"sign": "https://kami.im 直男过气网红 # We Are Star Dust",
"rank": 20000,
"level": 6,
"jointime": 0,
"moral": 0,
"silence": 0,
"coins": 0,
"fans_badge": true,
"fans_medal": {
"show": true,
"wear": true,
"medal": {
"uid": 2,
"target_id": 335115,
"medal_id": 45408,
"level": 21,
"medal_name": "伍千万",
"medal_color": 1725515,
"intimacy": 1980,
"next_intimacy": 2000,
"day_limit": 250000,
"medal_color_start": 1725515,
"medal_color_end": 5414290,
"medal_color_border": 1725515,
"is_lighted": 1,
"light_status": 1,
"wearing_status": 1,
"score": 50001980
}
},
"official": {
"role": 2,
"title": "bilibili创始人站长",
"desc": "",
"type": 0
},
"vip": {
"type": 2,
"status": 1,
"due_date": 3909916800000,
"vip_pay_type": 0,
"theme_type": 0,
"label": {
"path": "",
"text": "十年大会员",
"label_theme": "ten_annual_vip",
"text_color": "#FFFFFF",
"bg_style": 1,
"bg_color": "#FB7299",
"border_color": "",
"use_img_label": true,
"img_label_uri_hans": "",
"img_label_uri_hant": "",
"img_label_uri_hans_static": "https://i0.hdslb.com/bfs/activity-plat/static/20221008/0597543265563f522fad443825cff578/O9l2i8GdaZ.png",
"img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/8u7iRTPE7N.png"
},
"avatar_subscript": 1,
"nickname_color": "#FB7299",
"role": 7,
"avatar_subscript_url": "",
"tv_vip_status": 1,
"tv_vip_pay_type": 0
},
"pendant": {
"pid": 32257,
"name": "EveOneCat2",
"image": "https://i2.hdslb.com/bfs/garb/item/488870931b1bba66da36d22848f0720480d3d79a.png",
"expire": 0,
"image_enhance": "https://i2.hdslb.com/bfs/garb/item/5974f17f9d96a88bafba2f6d18d647a486e88312.webp",
"image_enhance_frame": "https://i2.hdslb.com/bfs/garb/item/4316a3910bb0bd6f2f1c267a3e9187f0b9fe5bd0.png"
},
"nameplate": {
"nid": 10,
"name": "见习偶像",
"image": "https://i1.hdslb.com/bfs/face/e93dd9edfa7b9e18bf46fd8d71862327a2350923.png",
"image_small": "https://i1.hdslb.com/bfs/face/275b468b043ec246737ab8580a2075bee0b1263b.png",
"level": "普通勋章",
"condition": "所有自制视频总播放数>=10万"
},
"user_honour_info": {
"mid": 0,
"colour": null,
"tags": []
},
"is_followed": false,
"top_photo": "http://i0.hdslb.com/bfs/space/cb1c3ef50e22b6096fde67febe863494caefebad.png",
"theme": {},
"sys_notice": {},
"live_room": {
"roomStatus": 1,
"liveStatus": 0,
"url": "https://live.bilibili.com/1024?broadcast_type=0&is_room_feed=0",
"title": "试图恰鸡",
"cover": "http://i0.hdslb.com/bfs/live/new_room_cover/96ee5bfd0279a0f18b190340334f43f473038288.jpg",
"roomid": 1024,
"roundStatus": 0,
"broadcast_type": 0,
"watched_show": {
"switch": true,
"num": 14,
"text_small": "14",
"text_large": "14人看过",
"icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png",
"icon_location": "",
"icon_web": "https://i0.hdslb.com/bfs/live/8d9d0f33ef8bf6f308742752d13dd0df731df19c.png"
}
},
"birthday": "09-19",
"school": {
"name": ""
},
"profession": {
"name": "",
"department": "",
"title": "",
"is_show": 0
},
"tags": null,
"series": {
"user_upgrade_status": 3,
"show_upgrade_window": false
},
"is_senior_member": 1,
"mcn_info": null,
"gaia_res_type": 0,
"gaia_data": null,
"is_risk": false,
"elec": {
"show_info": {
"show": true,
"state": 1,
"title": "",
"icon": "",
"jump_url": ""
}
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"mid": 2,
"name": "碧诗",
"sex": "男",
"face": "https://i2.hdslb.com/bfs/face/ef0457addb24141e15dfac6fbf45293ccf1e32ab.jpg",
"face_nft": 0,
"face_nft_type": 0,
"sign": "https://kami.im 直男过气网红 # We Are Star Dust",
"rank": 20000,
"level": 6,
"jointime": 0,
"moral": 0,
"silence": 0,
"coins": 0,
"fans_badge": true,
"fans_medal": {
"show": true,
"wear": true,
"medal": {
"uid": 2,
"target_id": 335115,
"medal_id": 45408,
"level": 21,
"medal_name": "伍千万",
"medal_color": 1725515,
"intimacy": 1980,
"next_intimacy": 2000,
"day_limit": 250000,
"medal_color_start": 1725515,
"medal_color_end": 5414290,
"medal_color_border": 1725515,
"is_lighted": 1,
"light_status": 1,
"wearing_status": 1,
"score": 50001980
}
},
"official": {
"role": 2,
"title": "bilibili创始人站长",
"desc": "",
"type": 0
},
"vip": {
"type": 2,
"status": 1,
"due_date": 3931344000000,
"vip_pay_type": 0,
"theme_type": 0,
"label": {
"path": "",
"text": "十年大会员",
"label_theme": "ten_annual_vip",
"text_color": "#FFFFFF",
"bg_style": 1,
"bg_color": "#FB7299",
"border_color": "",
"use_img_label": true,
"img_label_uri_hans": "https://i0.hdslb.com/bfs/activity-plat/static/20220608/e369244d0b14644f5e1a06431e22a4d5/wltavwHAkL.gif",
"img_label_uri_hant": "",
"img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/802418ff03911645648b63aa193ba67997b5a0bc.png",
"img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/8u7iRTPE7N.png"
},
"avatar_subscript": 1,
"nickname_color": "#FB7299",
"role": 7,
"avatar_subscript_url": "",
"tv_vip_status": 1,
"tv_vip_pay_type": 0,
"tv_due_date": 2000822400
},
"pendant": {
"pid": 32257,
"name": "EveOneCat2",
"image": "https://i2.hdslb.com/bfs/garb/item/488870931b1bba66da36d22848f0720480d3d79a.png",
"expire": 0,
"image_enhance": "https://i2.hdslb.com/bfs/garb/item/5974f17f9d96a88bafba2f6d18d647a486e88312.webp",
"image_enhance_frame": "https://i2.hdslb.com/bfs/garb/item/4316a3910bb0bd6f2f1c267a3e9187f0b9fe5bd0.png"
},
"nameplate": {
"nid": 10,
"name": "见习偶像",
"image": "https://i2.hdslb.com/bfs/face/e93dd9edfa7b9e18bf46fd8d71862327a2350923.png",
"image_small": "https://i2.hdslb.com/bfs/face/275b468b043ec246737ab8580a2075bee0b1263b.png",
"level": "普通勋章",
"condition": "所有自制视频总播放数>=10万"
},
"user_honour_info": {
"mid": 0,
"colour": null,
"tags": []
},
"is_followed": true,
"top_photo": "http://i2.hdslb.com/bfs/space/cb1c3ef50e22b6096fde67febe863494caefebad.png",
"theme": {},
"sys_notice": {},
"live_room": {
"roomStatus": 1,
"liveStatus": 0,
"url": "https://live.bilibili.com/1024?broadcast_type=0&is_room_feed=0",
"title": "试图恰鸡",
"cover": "http://i0.hdslb.com/bfs/live/new_room_cover/96ee5bfd0279a0f18b190340334f43f473038288.jpg",
"roomid": 1024,
"roundStatus": 0,
"broadcast_type": 0,
"watched_show": {
"switch": true,
"num": 19,
"text_small": "19",
"text_large": "19人看过",
"icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png",
"icon_location": "",
"icon_web": "https://i0.hdslb.com/bfs/live/8d9d0f33ef8bf6f308742752d13dd0df731df19c.png"
}
},
"birthday": "09-19",
"school": {
"name": ""
},
"profession": {
"name": "",
"department": "",
"title": "",
"is_show": 0
},
"tags": null,
"series": {
"user_upgrade_status": 3,
"show_upgrade_window": false
},
"is_senior_member": 0,
"mcn_info": null,
"gaia_res_type": 0,
"gaia_data": null,
"is_risk": false,
"elec": {
"show_info": {
"show": true,
"state": 1,
"title": "",
"icon": "",
"jump_url": "?oid=2"
}
},
"contract": {
"is_display": false,
"is_follow_display": false
}
}
}
}
```
</details>
**查询到的信息解析如下:**
**用户昵称为**:碧诗
**性别**:男
**用户的头像为**
https://i2.hdslb.com/bfs/face/ef0457addb24141e15dfac6fbf45293ccf1e32ab.jpg
<img src="https://i2.hdslb.com/bfs/face/ef0457addb24141e15dfac6fbf45293ccf1e32ab.jpg" width="100" height="100" />
**等级**6级
**生日**09-19
**粉丝勋章状态**:拥有
**认证**:个人认证
**认证名称** bilibili创始人(站长)
**大会员类型**:年度
**大会员状态**:已开通
**电视大会员状态**:已开通
**头像框**EveOneCat2
https://i2.hdslb.com/bfs/garb/item/5974f17f9d96a88bafba2f6d18d647a486e88312.webp
<img src="https://i2.hdslb.com/bfs/garb/item/5974f17f9d96a88bafba2f6d18d647a486e88312.webp" width="100" height="100" />
**粉丝勋章** 见习偶像
https://i1.hdslb.com/bfs/face/e93dd9edfa7b9e18bf46fd8d71862327a2350923.png
<img src="https://i1.hdslb.com/bfs/face/e93dd9edfa7b9e18bf46fd8d71862327a2350923.png" width="100" height="100" />
**空间头图**
https://i0.hdslb.com/bfs/space/cb1c3ef50e22b6096fde67febe863494caefebad.png
![](https://i0.hdslb.com/bfs/space/cb1c3ef50e22b6096fde67febe863494caefebad.png)
## 用户名片信息
> https://api.bilibili.com/x/web-interface/card
@ -582,6 +549,7 @@ https://i0.hdslb.com/bfs/space/cb1c3ef50e22b6096fde67febe863494caefebad.png
| fans | num | 粉丝数 | |
| friend | num | 关注数 | |
| attention | num | 关注数 | |
| sign | str | 签名 | |
| level_info | obj | 等级 | |
| pendant | obj | 挂件 | |
| nameplate | obj | 勋章 | |
@ -623,7 +591,7 @@ https://i0.hdslb.com/bfs/space/cb1c3ef50e22b6096fde67febe863494caefebad.png
| 字段 | 类型 | 内容 | 备注 |
| ----- | ---- | -------- | ------------------------------------------------- |
| role | num | 认证类型 | 0<br />1 2 7个人认证<br />3 4 5 6机构认证 |
| role | num | 认证类型 | 见[用户认证类型一览](official_role.md) |
| title | str | 认证信息 | 无为空 |
| desc | str | 认证备注 | 无为空 |
| type | num | 是否认证 | -1<br />0认证 |
@ -653,10 +621,10 @@ https://i0.hdslb.com/bfs/space/cb1c3ef50e22b6096fde67febe863494caefebad.png
| s_img | str | 主页头图url 小图 | |
| l_img | str | 主页头图url 正常 | |
**示**
**示**
```shell
curl -G 'api.bilibili.com/x/web-interface/card' \
curl -G 'https://api.bilibili.com/x/web-interface/card' \
--data-urlencode 'mid=2' \
--data-urlencode 'photo=true' \
-b 'SESSDATA=xxx'
@ -850,7 +818,7 @@ curl -G 'api.bilibili.com/x/web-interface/card' \
| 字段 | 类型 | 内容 | 备注 |
| ----- | ---- | -------- | ------------------------------------------------- |
| role | num | 认证类型 | 0<br />1 2 7个人认证<br />3 4 5 6机构认证 |
| role | num | 认证类型 | 见[用户认证类型一览](official_role.md) |
| title | str | 认证信息 | 无为空 |
| desc | str | 认证备注 | 无为空 |
| type | num | 是否认证 | -1<br />0认证 |
@ -867,7 +835,7 @@ curl -G 'api.bilibili.com/x/web-interface/card' \
**示例:**
```shell
curl -G 'api.bilibili.com/x/space/myinfo' \
curl -G 'https://api.bilibili.com/x/space/myinfo' \
-b 'SESSDATA=xxx'
```

View File

@ -0,0 +1,12 @@
# 用户认证类型一览
| ID | 认证类型 | 详细类型 |
| -- | ------- | ------- |
| 0 | 无 | |
| 1 | 个人认证 | 知名UP主 |
| 2 | 个人认证 | 大V达人 |
| 3 | 机构认证 | 企业 |
| 4 | 机构认证 | 组织 |
| 5 | 机构认证 | 媒体 |
| 6 | 机构认证 | 政府 |
| 7 | 个人认证 | 高能主播 |
| 9 | 个人认证 | 社会知名人士 |

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
# 视频点赞&投币&收藏&分享
# 稿件观众操作
## 点赞
@ -12,24 +12,26 @@
认证方式仅可CookieSESSDATA
需验证 Cookie 中`buvid3`字段存在且正常, 否则将导致触发风控
**正文参数( application/x-www-form-urlencoded **
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------ | ---- | ------------------------ | ------------ | ---------------------- |
| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 |
| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 |
| like | num | 操作方式 | 必要 | 1点赞<br />2取消赞 |
| csrf | str | CSRF Token位于cookie | 必要 | |
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------ | ---- | ------------------------- | ------------ | ---------------------- |
| aid | num | 稿件 avid | 必要(可选) | avid bvid 任选一个 |
| bvid | str | 稿件 bvid | 必要(可选) | avid bvid 任选一个 |
| like | num | 操作方式 | 必要 | 1点赞<br />2取消赞 |
| csrf | str | CSRF Token位于 Cookie | 必要 | |
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| code | num | 返回值 | 0成功 <br />-101账号未登录<br />-111csrf校验失败<br />-400请求错误<br />10003不存在该稿件<br />65004取消点赞失败<br />65006重复点赞 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------------------------------------------------------------ |
| code | num | 返回值 | 0成功 <br />-101账号未登录<br />-111csrf校验失败<br />-400请求错误<br />-403: 账号异常<br/> 10003不存在该稿件<br />65004取消点赞失败<br />65006重复点赞 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
**示例:**
@ -78,22 +80,22 @@ curl 'https://api.bilibili.com/x/web-interface/archive/like' \
**正文参数( application/x-www-form-urlencoded **
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ---------- | ---- | ------------ | ----------- | ---------------------- |
| access_key | str | APP登录Token | APP方式必要 | |
| aid | num | 稿件avid | 必要 | |
| like | num | 操作方式 | 必要 | 0点赞<br />1取消赞 |
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ---------- | ---- | -------------- | ------------ | ---------------------- |
| access_key | str | APP 登录 Token | APP 方式必要 | |
| aid | num | 稿件 avid | 必要 | |
| like | num | 操作方式 | 必要 | 0点赞<br />1取消赞 |
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | --------------------------------------------------------------------------- |
| code | num | 返回值 | 0成功 <br />-101账号未登录<br />-400请求错误<br />10003不存在该稿件 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
| data | obj | 数据本体 | |
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------------------------------------------------------------ |
| code | num | 返回值 | 0成功 <br />-101账号未登录<br />-400请求错误<br />-403: 账号异常<br />10003不存在该稿件 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
| data | obj | 数据本体 | |
`data`对象:
@ -138,11 +140,11 @@ curl 'https://app.bilibili.com/x/v2/view/like' \
**url参数**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ---------- | ---- | ------------ | ------------ | ------------------ |
| access_key | str | APP登录Token | APP方式必要 | |
| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 |
| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 |
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ---------- | ---- | -------------- | ------------ | --------------------- |
| access_key | str | APP 登录 Token | APP 方式必要 | |
| aid | num | 稿件 avid | 必要(可选) | avid bvid 任选一个 |
| bvid | str | 稿件 bvid | 必要(可选) | avid bvid 任选一个 |
**json回复**
@ -170,7 +172,7 @@ curl -G 'https://api.bilibili.com/x/web-interface/archive/has/like' \
bvid方式
```shell
curl -G 'api.bilibili.com/x/web-interface/archive/has/like' \
curl -G 'https://api.bilibili.com/x/web-interface/archive/has/like' \
--data-urlencode 'bvid=BV1Bt411z799' \
-b 'SESSDATA=xxx'
```
@ -201,11 +203,11 @@ curl -G 'api.bilibili.com/x/web-interface/archive/has/like' \
**正文参数( application/x-www-form-urlencoded **
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|------------|-----|-----------|-----|-----------------|
| access_key | str | APP Token | 必要 | |
| aid | num | 视频aid | 必要 | |
| dislike | num | 操作类型 | 必要 | 0点踩<br/>1取消点踩 |
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ---------- | ---- | -------------- | ------ | ----------------------- |
| access_key | str | APP 登录 Token | 必要 | |
| aid | num | 视频 aid | 必要 | |
| dislike | num | 操作类型 | 必要 | 0点踩<br/>1取消点踩 |
**json回复**
@ -250,26 +252,28 @@ curl -L -X POST 'https://app.biliapi.net/x/v2/view/dislike' \
认证方式仅可CookieSESSDATA
需验证 Cookie 中`buvid3`字段存在且正常, 否则将导致触发风控
**正文参数( application/x-www-form-urlencoded **
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ----------- | ---- | ------------------------ | ------------ | --------------------------------------- |
| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 |
| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 |
| multiply | num | 投币数量 | 必要 | 上限为2 |
| select_like | num | 是否附加点赞 | 非必要 | 0不点赞<br />1同时点赞<br />默认为0 |
| csrf | str | CSRF Token位于cookie | 必要 | |
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ----------- | ---- | ------------------------- | ------------ | --------------------------------------- |
| aid | num | 稿件 avid | 必要(可选) | avid bvid 任选一个 |
| bvid | str | 稿件 bvid | 必要(可选) | avid bvid 任选一个 |
| multiply | num | 投币数量 | 必要 | 上限为2 |
| select_like | num | 是否附加点赞 | 非必要 | 0不点赞<br />1同时点赞<br />默认为0 |
| csrf | str | CSRF Token位于 Cookie | 必要 | |
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| code | num | 返回值 | 0成功<br />-101账号未登录<br />-102账号被封停<br />-104硬币不足<br />-111csrf校验失败<br />-400请求错误<br />10003不存在该稿件<br />34002不能给自己投币<br />34003非法的投币数量<br />34004投币间隔太短<br />34005超过投币上限 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
| data | obj | 信息本体 | |
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | ------------------------------------------------------------ |
| code | num | 返回值 | 0成功<br />-101账号未登录<br />-102账号被封停<br />-104硬币不足<br />-111csrf校验失败<br />-400请求错误<br />-403: 账号异常<br />10003不存在该稿件<br />34002不能给自己投币<br />34003非法的投币数量<br />34004投币间隔太短<br />34005超过投币上限 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
| data | obj | 信息本体 | |
data 对象:
@ -329,12 +333,12 @@ curl 'https://api.bilibili.com/x/web-interface/coin/add' \
**正文参数( application/x-www-form-urlencoded **
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ----------- | ---- | ------------ | ----------- | --------------------------------------- |
| access_key | str | APP登录Token | APP方式必要 | |
| aid | num | 稿件avid | 必要 | |
| multiply | num | 投币数量 | 必要 | 上限为2 |
| select_like | num | 附加点赞 | 非必要 | 0不点赞<br />1同时点赞<br />默认为0 |
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ----------- | ---- | -------------- | ------------ | --------------------------------------- |
| access_key | str | APP 登录 Token | APP 方式必要 | |
| aid | num | 稿件 avid | 必要 | |
| multiply | num | 投币数量 | 必要 | 上限为2 |
| select_like | num | 附加点赞 | 非必要 | 0不点赞<br />1同时点赞<br />默认为0 |
**json回复**
@ -389,11 +393,11 @@ curl 'https://app.bilibili.com/x/v2/view/coin/add' \
**url参数**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ---------- | ---- | ------------ | ------------ | ------------------ |
| access_key | str | APP登录Token | APP方式必要 | |
| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 |
| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 |
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ---------- | ---- | -------------- | ------------ | --------------------- |
| access_key | str | APP 登录 Token | APP方式必要 | |
| aid | num | 稿件 avid | 必要(可选) | avid bvid 任选一个 |
| bvid | str | 稿件 bvid | 必要(可选) | avid bvid 任选一个 |
**json回复**
@ -419,7 +423,7 @@ curl 'https://app.bilibili.com/x/v2/view/coin/add' \
avid方式
```shell
curl -G 'api.bilibili.com/x/web-interface/archive/coins' \
curl -G 'https://api.bilibili.com/x/web-interface/archive/coins' \
--data-urlencode 'aid=37896701' \
-b 'SESSDATA=xxx'
```
@ -427,7 +431,7 @@ curl -G 'api.bilibili.com/x/web-interface/archive/coins' \
bvid方式
```shell
curl -G 'api.bilibili.com/x/web-interface/archive/coins' \
curl -G 'https://api.bilibili.com/x/web-interface/archive/coins' \
--data-urlencode 'bvid=BV18t411q7zz' \
-b 'SESSDATA=xxx'
```
@ -468,12 +472,12 @@ curl -G 'api.bilibili.com/x/web-interface/archive/coins' \
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------------- | ---- | ------------------------ | -------------- | ------------------------------ |
| access_key | str | APP登录Token | APP方式必要 | |
| rid | num | 稿件avid | 必要 | |
| access_key | str | APP 登录 Token | APP 方式必要 | |
| rid | num | 稿件 avid | 必要 | |
| type | num | 必须为2 | 必要 | |
| add_media_ids | nums | 需要加入的收藏夹mlid | 非必要 | 同时添加多个,用`,`%2C分隔 |
| del_media_ids | nums | 需要取消的收藏夹mlid | 非必要 | 同时取消多个,用`,`%2C分隔 |
| csrf | str | CSRF Token位于cookie | Cookie方式必要 | |
| add_media_ids | nums | 需要加入的收藏夹 mlid | 非必要 | 同时添加多个,用`,`%2C分隔 |
| del_media_ids | nums | 需要取消的收藏夹 mlid | 非必要 | 同时取消多个,用`,`%2C分隔 |
| csrf | str | CSRF Token位于 Cookie | Cookie 方式必要 | |
**json回复**
@ -544,10 +548,10 @@ curl 'https://api.bilibili.com/medialist/gateway/coll/resource/deal' \
**url参数**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ---------- | -------- | ------------------ | ----------- | ---- |
| access_key | str | APP登录Token | APP方式必要 | |
| aid | num或str | 稿件avid或稿件bvid | 必要 | |
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ---------- | ---------- | --------------------- | ------------ | ---- |
| access_key | str | APP 登录 Token | APP 方式必要 | |
| aid | num str | 稿件 avid 或稿件 bvid | 必要 | |
**json回复**
@ -618,24 +622,26 @@ curl -G 'https://api.bilibili.com/x/v2/fav/video/favoured' \
同时点赞投币收藏视频,收藏于默认收藏夹中
需验证 Cookie 中`buvid3`字段存在且正常, 否则将导致触发风控
**正文参数( application/x-www-form-urlencoded **
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------ | ---- | ------------------------ | ------------ | ------------------ |
| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 |
| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 |
| csrf | str | CSRF Token位于cookie | 必要 | |
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------ | ---- | ------------------------- | ------------ | --------------------- |
| aid | num | 稿件 avid | 必要(可选) | avid bvid 任选一个 |
| bvid | str | 稿件 bvid | 必要(可选) | avid bvid 任选一个 |
| csrf | str | CSRF Token位于 Cookie | 必要 | |
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- | -------------------------------------------------------------------------------------------------- |
| code | num | 返回值 | 0成功<br />-101账号未登录<br />-111csrf校验失败<br />-400请求错误<br />10003不存在该稿件 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
| data | obj | 信息本体 | |
| 字段 | 类型 | 内容 | 备注 |
| ------- | ---- | -------- |------------------------------------------------------------------------------------------|
| code | num | 返回值 | 0成功<br />-101账号未登录<br />-111csrf校验失败<br />-400请求错误<br />10003不存在该稿件<br />-403: 账号异常 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
| data | obj | 信息本体 | |
`data`对象:
@ -699,10 +705,10 @@ curl 'https://api.bilibili.com/x/web-interface/archive/like/triple' \
**正文参数( application/x-www-form-urlencoded **
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ---------- | ---- | ------------ | ----------- | ---- |
| access_key | str | APP登录Token | APP方式必要 | |
| aid | num | 稿件avid | 必要 | |
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ---------- | ---- | -------------- | ------------ | ---- |
| access_key | str | APP 登录 Token | APP 方式必要 | |
| aid | num | 稿件 avid | 必要 | |
**json回复**
@ -761,15 +767,13 @@ curl 'https://app.bilibili.com/x/v2/view/like/triple' \
*请求方式POST*
认证方式 csrf token
**正文参数( application/x-www-form-urlencoded **
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------ | ---- | ------------------------ | ------------ | ------------------ |
| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 |
| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 |
| csrf | str | CSRF Token位于cookie | 必要 | |
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------ | ---- | ------------------------- | ------------ | --------------------- |
| aid | num | 稿件 avid | 必要(可选) | avid bvid 任选一个 |
| bvid | str | 稿件 bvid | 必要(可选) | avid bvid任 选一个 |
| csrf | str | CSRF Token位于 Cookie | 必要 | |
**json回复**

View File

@ -17,7 +17,7 @@
| code | num | | 成功为0 |
| message | str | | 成功为0 |
| ttl | num | 1 | |
| data | List\<object> | | |
| data | array | | |
`data`数组:
@ -40,9 +40,9 @@
| remark | str | 类型备注 | |
| ctime | str | | 意义不明 |
| mtime | str | | 意义不明 |
| controls | 拥有时:object<br>没有时null | 详细信息填写提示 | |
| controls | 拥有时:array<br>没有时null | 详细信息填写提示 | |
`data`数组中的对象中的`controls`对象:
`controls`数组中的对象:
| 项 | 类型 | 内容 | 备注 |
| ----------- | ---- | -------------- | -------- |
@ -61,7 +61,8 @@ curl --location --request GET 'https://api.bilibili.com/x/web-interface/archive/
```
<details>
<summary>查看响应示例</summary>
<summary>查看响应示例</summary>
```json
{
"code": 0,
@ -74,12 +75,34 @@ curl --location --request GET 'https://api.bilibili.com/x/web-interface/archive/
"weight": 1,
"round": 2,
"state": 1,
"name": "其他问题",
"name": "其他",
"remark": "为帮助审核人员更快处理,请补充问题类型和出现位置等详细信息",
"ctime": "2018-08-13T15:41:20+08:00",
"mtime": "2018-08-13T15:41:20+08:00",
"mtime": "2023-09-21T18:40:20+08:00",
"controls": null
},
{
"tid": 8,
"business": 1,
"weight": 40,
"round": 2,
"state": 1,
"name": "与站内其他视频撞车",
"remark": "为帮助审核人员更快处理, 请描述撞车信息",
"ctime": "2018-08-13T15:41:20+08:00",
"mtime": "2023-03-06T16:36:02+08:00",
"controls": [
{
"tid": 8,
"bid": 1,
"name": "撞车对象",
"title": "撞车对象",
"component": "input",
"placeholder": "BVID",
"required": 1
}
]
},
{
"tid": 9,
"business": 1,
@ -110,10 +133,10 @@ curl --location --request GET 'https://api.bilibili.com/x/web-interface/archive/
"weight": 35,
"round": 2,
"state": 1,
"name": "转载/自制类型错误",
"name": "转载/自制错误",
"remark": "为帮助审核人员更快处理, 请补充原创作品出处",
"ctime": "2018-08-13T15:41:20+08:00",
"mtime": "2018-08-13T15:41:20+08:00",
"mtime": "2023-09-20T16:23:39+08:00",
"controls": [
{
"tid": 52,
@ -126,6 +149,78 @@ curl --location --request GET 'https://api.bilibili.com/x/web-interface/archive/
}
]
},
{
"tid": 10018,
"business": 1,
"weight": 36,
"round": 2,
"state": 1,
"name": "违规推广",
"remark": "",
"ctime": "2023-09-21T17:56:21+08:00",
"mtime": "2023-09-22T14:36:41+08:00",
"controls": null
},
{
"tid": 10019,
"business": 1,
"weight": 34,
"round": 2,
"state": 1,
"name": "其他不规范行为",
"remark": "",
"ctime": "2023-09-21T18:05:33+08:00",
"mtime": "2023-09-22T14:37:03+08:00",
"controls": null
},
{
"tid": 10020,
"business": 1,
"weight": 89,
"round": 2,
"state": 1,
"name": "危险行为",
"remark": "",
"ctime": "2023-09-21T18:05:51+08:00",
"mtime": "2023-09-22T14:38:08+08:00",
"controls": null
},
{
"tid": 10022,
"business": 1,
"weight": 1,
"round": 2,
"state": 1,
"name": "其他",
"remark": "",
"ctime": "2023-09-21T19:07:01+08:00",
"mtime": "2023-09-22T14:38:59+08:00",
"controls": null
},
{
"tid": 10023,
"business": 1,
"weight": 59,
"round": 2,
"state": 1,
"name": "企业商誉侵权",
"remark": "",
"ctime": "2023-12-01T14:06:58+08:00",
"mtime": "2023-12-01T15:33:26+08:00",
"controls": null
},
{
"tid": 10024,
"business": 1,
"weight": 58,
"round": 2,
"state": 1,
"name": "侵权申诉",
"remark": "",
"ctime": "2023-12-01T14:07:18+08:00",
"mtime": "2023-12-01T15:33:37+08:00",
"controls": null
},
{
"tid": 2,
"business": 1,
@ -144,10 +239,10 @@ curl --location --request GET 'https://api.bilibili.com/x/web-interface/archive/
"weight": 90,
"round": 1,
"state": 1,
"name": "色情",
"name": "色情低俗",
"remark": "为帮助审核人员更快处理,补充违规内容出现位置",
"ctime": "2018-08-13T15:41:20+08:00",
"mtime": "2018-08-13T15:41:20+08:00",
"mtime": "2023-09-21T19:07:10+08:00",
"controls": null
},
{
@ -198,28 +293,6 @@ curl --location --request GET 'https://api.bilibili.com/x/web-interface/archive/
"mtime": "2018-08-13T15:41:20+08:00",
"controls": null
},
{
"tid": 8,
"business": 1,
"weight": 40,
"round": 1,
"state": 1,
"name": "与站内其他视频撞车",
"remark": "为帮助审核人员更快处理, 请描述撞车信息",
"ctime": "2018-08-13T15:41:20+08:00",
"mtime": "2018-08-23T00:30:04+08:00",
"controls": [
{
"tid": 8,
"bid": 1,
"name": "撞车对象",
"title": "撞车对象",
"component": "input",
"placeholder": "BVID",
"required": 1
}
]
},
{
"tid": 10000,
"business": 1,
@ -243,16 +316,64 @@ curl --location --request GET 'https://api.bilibili.com/x/web-interface/archive/
"ctime": "2019-04-17T19:18:09+08:00",
"mtime": "2019-04-17T20:42:25+08:00",
"controls": null
},
{
"tid": 10014,
"business": 1,
"weight": 8,
"round": 1,
"state": 1,
"name": "涉政谣言",
"remark": "为帮助审核人员更快处理,请补充谣言内容出现位置",
"ctime": "2022-09-15T17:23:44+08:00",
"mtime": "2022-09-16T09:56:07+08:00",
"controls": null
},
{
"tid": 10015,
"business": 1,
"weight": 7,
"round": 1,
"state": 1,
"name": "涉社会事件谣言",
"remark": "为帮助审核人员更快处理,请补充谣言内容出现位置",
"ctime": "2022-09-15T17:25:56+08:00",
"mtime": "2022-09-16T09:56:07+08:00",
"controls": null
},
{
"tid": 10017,
"business": 1,
"weight": 5,
"round": 1,
"state": 1,
"name": "虚假不实信息",
"remark": "为帮助审核人员更快处理,请补充不实内容出现位置",
"ctime": "2022-09-15T17:28:16+08:00",
"mtime": "2022-09-16T09:56:08+08:00",
"controls": null
},
{
"tid": 10021,
"business": 1,
"weight": 88,
"round": 1,
"state": 1,
"name": "观感不适",
"remark": "",
"ctime": "2023-09-21T18:06:15+08:00",
"mtime": "2023-09-21T18:06:15+08:00",
"controls": null
}
]
}
```
</details>
## 投诉稿件
> https://api.bilibili.com/x/web-interface/archive/appeal
> https://api.bilibili.com/x/web-interface/appeal/v2/submit
*请求方式POST*
认证方式CookieSESSDATA)
@ -261,12 +382,15 @@ curl --location --request GET 'https://api.bilibili.com/x/web-interface/archive/
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------ | ---- | ------------------------ | ------ | ------------------------ |
| csrf | str | csrf token(位于cookie) | 必要 | 在url params中 |
| jsonp | str | jsonp | 必要? | 意义不明位于url params |
| csrf | str | csrf token(位于cookie bili_jct) | 必要 | 位于request body |
| aid | num | 稿件aid | 必要 | 位于request body |
| tid | num | 投诉理由tid | 必要 | 位于request body |
| desc | str | 投诉理由详细描述 | 必要 | 位于request body |
| attach | str | 附件(多个附件用逗号隔开 | 非必要 | 位于request body |
| buid | str | 风控代码 | 必要 | 位于request header |
| Buid | str | 风控代码 | 必要 | 位于request cookies |
上下两个buid值必须相同可随机
**json回复**
@ -279,7 +403,8 @@ curl --location --request GET 'https://api.bilibili.com/x/web-interface/archive/
**示例举报av号为61080066的视频理由为人身攻击描述为“xxxxx”并附带了一个图片附件
```bash
curl --location --request POST 'https://api.bilibili.com/x/web-interface/archive/appeal?jsonp=jsonp&csrf=xxxx' \
curl --location --request POST 'https://api.bilibili.com/x/web-interface/appeal/v2/submit' \
--form 'csrf="xxxx"'\
--form 'aid="61080066"' \
--form 'tid="7"' \
--form 'desc="xxxxx"' \
@ -288,6 +413,7 @@ curl --location --request POST 'https://api.bilibili.com/x/web-interface/archive
<details>
<summary>查看响应示例</summary>
```json
{
"code":0,
@ -295,4 +421,5 @@ curl --location --request POST 'https://api.bilibili.com/x/web-interface/archive
"ttl":1
}
```
</details>

View File

@ -29,7 +29,7 @@
| 18 | 是否付费 | |
| 19 | 推送动态 | |
| 20 | 家长模式 | |
| 21 | 是否限制游客和外链 | 分为两种情况默认全部网页限制referer跳转但第二种未登录无法访问可以通过未登陆b站访问http://api.bilibili.com/x/web-interface/view 返回的code为-403来判断 |
| 21 | 是否限制游客和外链 | 分为两种情况默认全部网页限制referer跳转但第二种未登录无法访问可以通过未登陆b站访问https://api.bilibili.com/x/web-interface/view 返回的code为-403来判断 |
| 22 | | |
| 23 | | |
| 24 | 是否为联合投稿 | |

92
docs/video/collection.md Normal file
View File

@ -0,0 +1,92 @@
# 视频合集信息
## 获取视频合集信息
> https://api.bilibili.com/x/polymer/web-space/seasons_archives_list
*请求方式GET*
**url参数**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|--------|-----|------|--------|-----|
| mid | num | UP 主 ID | 必要 | |
| season_id | num | 视频合集 ID | 必要 | |
| sort_reverse | bool | 未知 | 可选 | |
| page_num | num | 页码索引 | 可选 | |
| page_size | num | 单页内容数量 | 可选 | |
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
|---------|-----|------|------------------------------------------------------------------------------------|
| code | num | 返回值 | 0成功 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
| data | obj | 信息本体 | |
`data`对象:
| 字段 | 类型 | 内容 | 备注 |
| ----------------------- | ------- | ------------------------------ | ----------------------------------------------------------- |
| aids | array | 稿件avid | 对应下方数组中内容 aid |
| archives | array | 合集中的视频 | |
| meta | obj | 合集元数据 | |
| page | obj | 分页信息 | |
`data`中的`archives`数组:
| 项 | 类型 | 内容 | 备注 |
|-----|-----|----------|---------|
| 0 | obj | 合集内容 | |
| n | obj | (n+1)P内容 | |
| …… | obj | …… | …… |
`archives`数组中的对象:
| 字段 | 类型 | 内容 | 备注 |
|----------|-----|------|-----|
| aid | num | 稿件avid ||
| bvid | str | 稿件bvid ||
| ctime | num | 创建时间 | Unix 时间戳 |
| duration | num | 视频时长 | 单位为秒 |
| enable_vt | bool | false ||
| interactive_video | bool | false ||
| pic | str | 封面 URL ||
| playback_position | num || 会随着播放时间增长,播放完成后为 -1 。单位未知 |
| pubdate | num | 发布日期 | Unix 时间戳 |
| stat | obj | 稿件信息 ||
| state | num | 0 ||
| title | str | 稿件标题||
| ugc_pay | num | 0 ||
| vt_display | str |||
`archives`中的`stat`对象:
| 字段 | 类型 | 内容 | 备注 |
|----------|-----|------|-----|
| view | num | 稿件播放量 ||
| vt | num | 0 ||
`data`中的`meta`对象:
| 字段 | 类型 | 内容 | 备注 |
|-----------------|-----|--------------|--------|
| category | num | 0 | |
| covr | str | 合集封面 URL | |
| description | str | 合集描述 | |
| mid | num | UP 主 ID | |
| name | num | 合集标题 | |
| ptime | num | 发布时间 | Unix 时间戳 |
| season_id | num | 合集 ID | |
| total | num | 合集内视频数量 | |
`data`中的`page`对象:
| 字段 | 类型 | 内容 | 备注 |
|-----------------|-----|--------------|--------|
| page_num | num | 分页页码 | |
| page_size | num | 单页个数 | |
| total | num | 合集内视频数量 | |

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,10 @@
# 视频推荐
- [获取单视频推荐列表web端](#获取单视频推荐列表web端)
- [获取首页视频推荐列表web端](#获取首页视频推荐列表web端)
- [获取短视频模式视频列表](#获取短视频模式视频列表)
---
## 获取单视频推荐列表web端
> https://api.bilibili.com/x/web-interface/archive/related
@ -288,3 +293,615 @@ curl -G 'https://api.bilibili.com/x/web-interface/archive/related' \
```
</details>
## 获取首页视频推荐列表web端
> https://api.bilibili.com/x/web-interface/index/top/rcmd
*请求方式GET*
认证方式CookieSESSDATA
最多获取14条推荐视频
**url参数**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|--------------|-----|---------------------------|-----|------------------------------|
| fresh_type | num | 相关性 | 非必要 | 默认为3 <br /> 值越大推荐内容越相关 |
| version | num | web端新旧版本:0为旧版本1为新版本 | 非必要 | 默认为0 <br /> 1,0分别为新旧web端 |
| ps | num | pagesize 单页返回的记录条数默认为10或8 | 非必要 | 默认为10 <br /> 当version为1时默认为8 |
| fresh_idx | num | 翻页相关 | 非必要 | 默认为1 <br /> 与翻页相关 |
| fresh_idx_1h | num | 翻页相关 | 非必要 | 默认为1 <br /> 与翻页相关 |
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
|-------------|-------|------|----------------------|
| code | num | 返回值 | 0成功 <br />-400请求错误 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
| data | array | 推荐列表 | |
| userfeature | str | 用户功能 | |
| abtest | obj | 用户分组 | |
`data`数组:
| 项 | 类型 | 内容 | 备注 |
|-----| ---- |-----------| ---- |
| 0 | obj | 推荐视频1 | |
| n | obj | 推荐视频(n+1) | |
| …… | obj | …… | …… |
| 13 | obj | 推荐视频13 | |
`data`数组中的对象:
基本同「[获取视频详细信息web端](info.md#获取视频详细信息web端)」中的data对象
`abtest`对象:
| 字段 | 类型 | 内容 | 备注 |
|-------|-----|------|-----|
| group | str | 用户分组 | |
**示例:**
获取新版web端首页推荐视频列表
```shell
curl -G 'https://api.bilibili.com/x/web-interface/index/top/rcmd' \
--data-urlencode 'fresh_type=3' \
--data-urlencode 'version=1' \
--data-urlencode 'ps=10' \
--data-urlencode 'fresh_idx=1' \
--data-urlencode 'fresh_idx_1h=1'
```
<details>
<summary>查看响应示例:</summary>
```json
{
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"item": [
{
"id": 511495739,
"bvid": "BV1Cu411z7mG",
"cid": 717978243,
"goto": "av",
"uri": "http://www.bilibili.com/video/BV1Cu411z7mG",
"pic": "http://i2.hdslb.com/bfs/archive/e05f487bc9f26baa568f10fe69a0e1ea5e0fbc23.jpg",
"title": "请大家助力我的梦想为凑够10万赞在街头唱《Be Crazy For Me》",
"duration": 199,
"pubdate": 1652605500,
"owner": {
"mid": 1723817,
"name": "樱萍Apple",
"face": "http://i2.hdslb.com/bfs/face/6e0fa1bdbbf7e0dd929d968df3b57ca99d187e25.jpg"
},
"stat": {
"view": 263169,
"like": 39871,
"danmaku": 543
},
"avfeature": "{\"ctr\":0.192554,\"wdur\":2.323159,\"duration\":213.318313,\"wdlks\":0.685926,\"multi_score_0\":0.452564,\"multi_score_1\":0.112414,\"multi_score_2\":0.03976,\"rankscore\":13.906487,\"av_play\":258890,\"av_like\":39224,\"av_coin\":7165,\"reason_type\":3,\"av_feature\":\"|real_matchtype -1 |s_e online_av2av_v2 |source_len 1 |m_k_w 0 \"}",
"isfollowed": 0,
"rcmdreason": {
"content": "3万点赞",
"reasontype": 3
},
"showinfo": 1,
"trackid": "web_pegasus_0.shylf-ai-recsys-1355.165525355529.398"
}
......
],
"userfeature": "{\"enter_rank\":1500,\"is_fallback\":0,\"s_fresh_idx\":41,\"s_fresh_idx_session\":31,\"s_session_idx\":1,\"fresh_idx\":1,\"fresh_idx_1h\":1}",
"abtest": {
"group": "b"
}
}
}
```
</details>
## 获取短视频模式视频列表
> https://app.bilibili.com/x/v2/feed/index
*请求方式GET*
认证方式CookieSESSDATA
**url参数**
有大量不明意义的参数 备注仅供参考
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|--------------|-----|---------------------------|-----|------------------------------|
| fnval | num | 视频流格式标识 | 非必要 | 默认为272 |
| fnver | num | 视频流版本标识 | 非必要 | 恒为1 |
| force_host | num | 源url类型 | 非必要 | 0:无限制 1:使用http 2:使用https |
| fourk | num | 是否允许 4K 视频 | 非必要 | 画质最高 1080P0默认<br />画质最高 4K1 |
| guidance | num | 0 | 非必要 | |
| https_url_req | num | 0 | 非必要 | |
| inline_danmu | num | 2 | 非必要 | |
| inline_sound | num | 1 | 非必要 | |
| interest_id | num | 0 | 非必要 | |
| login_event | num | 登录状态 | 非必要 | 0为登录 1为未登录 |
| mobi_app | num | android | 非必要 | 设备类型 |
| network | num | wifi | 非必要 | 网络类型 |
| open_event | num | | 非必要 | |
| platform | num | android | 非必要 | 设备类型 |
| pull | boll | false | 非必要 | |
| qn | num | 32 | 非必要 | 似乎是画质 |
| recsys_mode | num | 0 | 非必要 | |
| s_locale | str | zh_CN | 非必要 | 语言 |
| video_mode | num | 1 | 非必要 | |
| voice_balance | num | 音量均衡? | 非必要 | 默认为1 |
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
|-------------|-------|------|----------------------|
| code | num | 返回值 | 0成功 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
| data | obj | | |
`data`对象:
| 字段 | 类型 | 内容 | 备注 |
|-------------|-------|------|----------------------|
| config | obj | 一些界面相关的内容 | 此处省略 |
| items | array | 视频列表 | |
`data`中的`items`数组的对象:
以下为视频类型
| 字段 | 类型 | 内容 | 备注 |
|-------------|-------|------|----------------------|
| can_play | num | 1 | 字面意思 |
| card_goto | str | av | |
| card_type | str | 卡片类型 | 视频为small_cover_v2 |
| cover | str | 封面url | |
| cover_left_1_content_description | str | 播放量 | 8.9万观看 |
| cover_left_2_content_description | str | 弹幕数 | 250弹幕 |
| cover_left_text_1 | str | 播放量 | 8.9万 |
| cover_left_text_2 | str | 弹幕数 | 250 |
| cover_right_content_description | str | 视频长度 | 1分钟20秒 |
| cover_right_text | str | 视频长度 | 1:20 |
| desc_button | obj | up主信息 | |
| param | str | 视频aid | |
| player_args | obj | 视频信息 | |
| talk_back | str | | |
| title | str | 标题 | |
| uri | str | 跳转链接 | |
`desc_button`对象:
| 字段 | 类型 | 内容 | 备注 |
|-------------|-------|------|----------------------|
| event | str | | |
| text | str | up名称 | |
| type | num | 1 | |
| uri | str | 跳转链接 | |
`player_args`对象:
| 字段 | 类型 | 内容 | 备注 |
|-------------|-------|------|----------------------|
| aid | num | 视频aid | |
| cid | num | 视频cid | |
| duration | num | 视频长度 | 秒数 |
| type | str | | |
**示例:**
获取短视频模式视频列表
```shell
curl -G 'https://app.bilibili.com/x/v2/feed/index'
```
<details>
<summary>查看响应示例:</summary>
```json
{
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"items": [
{
"card_type": "small_cover_v2",
"card_goto": "av",
"goto": "av",
"param": "411978753",
"cover": "http://i2.hdslb.com/bfs/archive/a1bda1e57e6812ca8822a8839fc4a1d3539255a8.jpg",
"title": "帕 鲁 现 状",
"uri": "bilibili://video/411978753?cid=1423365216\u0026player_height=1920\u0026player_preload=%7B%22cid%22%3A1423365216%2C%22expire_time%22%3A1706633200%2C%22file_info%22%3A%7B%2216%22%3A%5B%7B%22timelength%22%3A79970%2C%22filesize%22%3A3782665%7D%5D%2C%2264%22%3A%5B%7B%22timelength%22%3A79900%2C%22filesize%22%3A9552030%7D%5D%7D%2C%22support_quality%22%3Anull%2C%22support_formats%22%3Anull%2C%22support_description%22%3Anull%2C%22quality%22%3A16%2C%22url%22%3A%22http%3A%2F%2Fcn-gdst-cm-01-12.bilivideo.com%2Fupgcxcode%2F16%2F52%2F1423365216%2F1423365216-1-16.mp4%3Fe%3Dig8euxZM2rNcNbRVhwdVhwdlhWdVhwdVhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8gNEVE5XREto8z5JZC2X2gkX5L5F1eTX1jkXlsTXHeux_f2o859IB_%5Cu0026uipk%3D5%5Cu0026nbs%3D1%5Cu0026deadline%3D1706636800%5Cu0026gen%3Dplayurlv2%5Cu0026os%3Dbcache%5Cu0026oi%3D0%5Cu0026trid%3D00000ccc07d4b7a34140a25493d51003bd95U%5Cu0026mid%3D0%5Cu0026platform%3D%5Cu0026upsig%3D2bf8e99202a181300981ab6ba9d2305d%5Cu0026uparams%3De%2Cuipk%2Cnbs%2Cdeadline%2Cgen%2Cos%2Coi%2Ctrid%2Cmid%2Cplatform%5Cu0026cdnid%3D6876%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026orderid%3D0%2C3%5Cu0026buvid%3D%5Cu0026build%3D0%5Cu0026f%3DU_0_0%5Cu0026bw%3D47881%5Cu0026logo%3D80000000%22%2C%22video_codecid%22%3A7%2C%22video_project%22%3Atrue%2C%22fnver%22%3A0%2C%22fnval%22%3A0%7D\u0026player_rotate=0\u0026player_width=1080\u0026report_flow_data=%7B%22flow_card_type%22%3A%22av%22%7D",
"three_point": {
"dislike_reasons": [
{
"id": 4,
"name": "UP主:锤子game",
"toast": "将减少相似内容推荐"
},
{
"id": 2,
"name": "分区:网络游戏",
"toast": "将减少相似内容推荐"
},
{
"id": 3,
"name": "频道:搞笑",
"toast": "将减少相似内容推荐"
},
{
"id": 12,
"name": "此类内容过多",
"toast": "将减少相似内容推荐"
},
{
"id": 13,
"name": "推荐过",
"toast": "将减少相似内容推荐"
},
{
"id": 1,
"name": "不感兴趣",
"toast": "将减少相似内容推荐"
}
],
"feedbacks": [
{
"id": 1,
"name": "恐怖血腥",
"toast": "将优化首页此类内容"
},
{
"id": 2,
"name": "色情低俗",
"toast": "将优化首页此类内容"
},
{
"id": 3,
"name": "封面恶心",
"toast": "将优化首页此类内容"
},
{
"id": 4,
"name": "标题党/封面党",
"toast": "将优化首页此类内容"
}
],
"watch_later": 1
},
"args": {
"up_id": 495695169,
"up_name": "锤子game",
"rid": 65,
"rname": "网络游戏",
"tid": 1833,
"tname": "搞笑",
"aid": 411978753
},
"player_args": {
"aid": 411978753,
"cid": 1423365216,
"type": "av",
"duration": 80
},
"idx": 1706629610,
"three_point_v2": [
{
"title": "添加至稍后再看",
"type": "watch_later",
"icon": "https://i0.hdslb.com/bfs/activity-plat/static/ce06d65bc0a8d8aa2a463747ce2a4752/NyPAqcn0QF.png"
},
{
"title": "反馈",
"subtitle": "(选择后将优化首页此类内容)",
"reasons": [
{
"id": 1,
"name": "恐怖血腥",
"toast": "将优化首页此类内容"
},
{
"id": 2,
"name": "色情低俗",
"toast": "将优化首页此类内容"
},
{
"id": 3,
"name": "封面恶心",
"toast": "将优化首页此类内容"
},
{
"id": 4,
"name": "标题党/封面党",
"toast": "将优化首页此类内容"
}
],
"type": "feedback"
},
{
"title": "不感兴趣",
"subtitle": "(选择后将减少相似内容推荐)",
"reasons": [
{
"id": 4,
"name": "UP主:锤子game",
"toast": "将减少相似内容推荐"
},
{
"id": 2,
"name": "分区:网络游戏",
"toast": "将减少相似内容推荐"
},
{
"id": 3,
"name": "频道:搞笑",
"toast": "将减少相似内容推荐"
},
{
"id": 12,
"name": "此类内容过多",
"toast": "将减少相似内容推荐"
},
{
"id": 13,
"name": "推荐过",
"toast": "将减少相似内容推荐"
},
{
"id": 1,
"name": "不感兴趣",
"toast": "将减少相似内容推荐"
}
],
"type": "dislike"
}
],
"talk_back": "视频,帕 鲁 现 状,32.5万观看,257弹幕,时长1分钟20秒,UP主锤子game,",
"report_flow_data": "{\"flow_card_type\":\"av\"}",
"cover_left_text_1": "32.5万",
"cover_left_icon_1": 1,
"cover_left_1_content_description": "32.5万观看",
"cover_left_text_2": "257",
"cover_left_icon_2": 3,
"cover_left_2_content_description": "257弹幕",
"cover_right_text": "1:20",
"cover_right_content_description": "1分钟20秒",
"desc_button": {
"text": "锤子game",
"uri": "bilibili://space/495695169",
"event": "nickname",
"type": 1
},
"official_icon": 16,
"can_play": 1,
"goto_icon": {
"icon_url": "https://i0.hdslb.com/bfs/activity-plat/static/20230227/0977767b2e79d8ad0a36a731068a83d7/077GOeHOfO.png",
"icon_night_url": "https://i0.hdslb.com/bfs/activity-plat/static/20230227/0977767b2e79d8ad0a36a731068a83d7/ldbCXtkoK2.png",
"icon_width": 16,
"icon_height": 16
}
},
{
"card_type": "small_cover_v2",
"card_goto": "av",
"goto": "av",
"param": "836990443",
"cover": "http://i1.hdslb.com/bfs/archive/d16a125d6ec1c68cc9e0815bc28dcb62a1df9932.jpg",
"title": "【Phigros自制/崩坏:星穹铁道】欢迎来到匹诺康尼! 不眠之夜 IN Lv.13",
"uri": "bilibili://video/836990443?cid=1422516399\u0026player_height=1080\u0026player_preload=%7B%22cid%22%3A1422516399%2C%22expire_time%22%3A1706633200%2C%22file_info%22%3A%7B%2216%22%3A%5B%7B%22timelength%22%3A102818%2C%22filesize%22%3A4441802%7D%5D%2C%2264%22%3A%5B%7B%22timelength%22%3A102748%2C%22filesize%22%3A12468618%7D%5D%7D%2C%22support_quality%22%3Anull%2C%22support_formats%22%3Anull%2C%22support_description%22%3Anull%2C%22quality%22%3A16%2C%22url%22%3A%22http%3A%2F%2Fupos-sz-mirrorali.bilivideo.com%2Fupgcxcode%2F99%2F63%2F1422516399%2F1422516399-1-16.mp4%3Fe%3Dig8euxZM2rNcNbRVhwdVhwdlhWdVhwdVhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8gNEVE5XREto8z5JZC2X2gkX5L5F1eTX1jkXlsTXHeux_f2o859IB_%5Cu0026uipk%3D5%5Cu0026nbs%3D1%5Cu0026deadline%3D1706636800%5Cu0026gen%3Dplayurlv2%5Cu0026os%3Dalibv%5Cu0026oi%3D0%5Cu0026trid%3D0ccc07d4b7a34140a25493d51003bd95U%5Cu0026mid%3D0%5Cu0026platform%3D%5Cu0026upsig%3D06ea793aa573018646c0096adf0dcb9e%5Cu0026uparams%3De%2Cuipk%2Cnbs%2Cdeadline%2Cgen%2Cos%2Coi%2Ctrid%2Cmid%2Cplatform%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026orderid%3D0%2C3%5Cu0026buvid%3D%5Cu0026build%3D0%5Cu0026f%3DU_0_0%5Cu0026bw%3D43547%5Cu0026logo%3D80000000%22%2C%22video_codecid%22%3A7%2C%22video_project%22%3Atrue%2C%22fnver%22%3A0%2C%22fnval%22%3A0%7D\u0026player_rotate=0\u0026player_width=1920\u0026report_flow_data=%7B%22flow_card_type%22%3A%22av%22%7D",
"three_point": {
"dislike_reasons": [
{
"id": 4,
"name": "UP主:早期陈总",
"toast": "将减少相似内容推荐"
},
{
"id": 2,
"name": "分区:音游",
"toast": "将减少相似内容推荐"
},
{
"id": 3,
"name": "频道:音乐游戏",
"toast": "将减少相似内容推荐"
},
{
"id": 12,
"name": "此类内容过多",
"toast": "将减少相似内容推荐"
},
{
"id": 13,
"name": "推荐过",
"toast": "将减少相似内容推荐"
},
{
"id": 1,
"name": "不感兴趣",
"toast": "将减少相似内容推荐"
}
],
"feedbacks": [
{
"id": 1,
"name": "恐怖血腥",
"toast": "将优化首页此类内容"
},
{
"id": 2,
"name": "色情低俗",
"toast": "将优化首页此类内容"
},
{
"id": 3,
"name": "封面恶心",
"toast": "将优化首页此类内容"
},
{
"id": 4,
"name": "标题党/封面党",
"toast": "将优化首页此类内容"
}
],
"watch_later": 1
},
"args": {
"up_id": 1515475415,
"up_name": "早期陈总",
"rid": 136,
"rname": "音游",
"tid": 10174,
"tname": "音乐游戏",
"aid": 836990443
},
"player_args": {
"aid": 836990443,
"cid": 1422516399,
"type": "av",
"duration": 103
},
"idx": 1706629609,
"three_point_v2": [
{
"title": "添加至稍后再看",
"type": "watch_later",
"icon": "https://i0.hdslb.com/bfs/activity-plat/static/ce06d65bc0a8d8aa2a463747ce2a4752/NyPAqcn0QF.png"
},
{
"title": "反馈",
"subtitle": "(选择后将优化首页此类内容)",
"reasons": [
{
"id": 1,
"name": "恐怖血腥",
"toast": "将优化首页此类内容"
},
{
"id": 2,
"name": "色情低俗",
"toast": "将优化首页此类内容"
},
{
"id": 3,
"name": "封面恶心",
"toast": "将优化首页此类内容"
},
{
"id": 4,
"name": "标题党/封面党",
"toast": "将优化首页此类内容"
}
],
"type": "feedback"
},
{
"title": "不感兴趣",
"subtitle": "(选择后将减少相似内容推荐)",
"reasons": [
{
"id": 4,
"name": "UP主:早期陈总",
"toast": "将减少相似内容推荐"
},
{
"id": 2,
"name": "分区:音游",
"toast": "将减少相似内容推荐"
},
{
"id": 3,
"name": "频道:音乐游戏",
"toast": "将减少相似内容推荐"
},
{
"id": 12,
"name": "此类内容过多",
"toast": "将减少相似内容推荐"
},
{
"id": 13,
"name": "推荐过",
"toast": "将减少相似内容推荐"
},
{
"id": 1,
"name": "不感兴趣",
"toast": "将减少相似内容推荐"
}
],
"type": "dislike"
}
],
"talk_back": "视频,【Phigros自制/崩坏:星穹铁道】欢迎来到匹诺康尼! 不眠之夜 IN Lv.13,22.8万观看,797弹幕,时长1分钟43秒,UP主早期陈总,",
"report_flow_data": "{\"flow_card_type\":\"av\"}",
"cover_left_text_1": "22.8万",
"cover_left_icon_1": 1,
"cover_left_1_content_description": "22.8万观看",
"cover_left_text_2": "797",
"cover_left_icon_2": 3,
"cover_left_2_content_description": "797弹幕",
"cover_right_text": "1:43",
"cover_right_content_description": "1分钟43秒",
"desc_button": {
"text": "早期陈总",
"uri": "bilibili://space/1515475415",
"event": "nickname",
"type": 1
},
"can_play": 1,
"goto_icon": {
"icon_url": "https://i0.hdslb.com/bfs/activity-plat/static/20230227/0977767b2e79d8ad0a36a731068a83d7/077GOeHOfO.png",
"icon_night_url": "https://i0.hdslb.com/bfs/activity-plat/static/20230227/0977767b2e79d8ad0a36a731068a83d7/ldbCXtkoK2.png",
"icon_width": 16,
"icon_height": 16
}
}
],
"config": {
"column": 2,
"autoplay_card": 2,
"feed_clean_abtest": 0,
"home_transfer_test": 0,
"auto_refresh_time": 1200,
"show_inline_danmaku": 1,
"toast": {},
"is_back_to_homepage": true,
"enable_rcmd_guide": true,
"inline_sound": 2,
"auto_refresh_time_by_appear": 1200,
"auto_refresh_time_by_active": 1200,
"visible_area": 80,
"card_density_exp": 1,
"story_mode_v2_guide_exp": 6
},
"interest_choose": null
}
}
```
</details>

View File

@ -116,7 +116,7 @@ curl 'https://api.bilibili.com/x/v2/history/report' \
上报一次视频`av2`/`BV1xx411c7mD`的心跳数据
```shell
curl 'api.bilibili.com/x/click-interface/web/heartbeat' \
curl 'https://api.bilibili.com/x/click-interface/web/heartbeat' \
--data-urlencode 'aid=2' \
--data-urlencode 'bvid=BV1xx411c7mD' \
--data-urlencode 'cid=62131' \

225
docs/video/summary.md Normal file
View File

@ -0,0 +1,225 @@
# 视频AI总结
<img src="../../assets/img/aiSummary.svg" width="100" height="100"/>
## 获取AI总结内容
> https://api.bilibili.com/x/web-interface/view/conclusion/get
*请求方式: GET*
鉴权方式:[Wbi 签名](../misc/sign/wbi.md)
**url参数**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|--------|-----|--------|-----|----------------------------------|
| aid | num | 稿件 avid | 必要(可选) | avid与bvid任选一个 |
| bvid | str | 稿件 bvid | 必要(可选) | avid与bvid任选一个 |
| cid | num | 视频 cid | 必要 | |
| up_mid | num | UP主 mid | 必要 | |
| w_rid | str | Wbi 签名 | 必要 | 详见 [Wbi 签名](../misc/sign/wbi.md) |
| wts | num | 当前时间戳 | 必要 | 详见 [Wbi 签名](../misc/sign/wbi.md) |
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
|---------|-----|------|--------------------------|
| code | num | 返回值 | 0: 成功<br />-400请求错误<br /> -403: 访问权限不足 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
| data | obj | 数据本体 | |
`data`对象:
| 字段 | 类型 | 内容 | 备注 |
|--------------|-----|------|----------------------|
| code | num | 返回值 | -1: 不支持AI摘要敏感内容等或其他因素导致请求异常<br />0: 有摘要<br />1无摘要未识别到语音 |
| model_result | obj | 摘要内容 | |
| stid | str | 摘要 id | 如`code=1`且该字段为`0`时,则未进行 AI 总结,即添加总结队列<br />如`code=1`且该字段为空时未识别到语音 |
| status | num | (?) | |
| like_num | num | 点赞数 | 默认为`0` |
| dislike_num | num | 点踩数 | 默认为`0` |
`data`中的`model_result`对象:
| 字段 | 类型 | 内容 | 备注 |
|-------------|-----|----------|------------------------------------------|
| result_type | num | 数据类型 | 0: 没有摘要<br />1仅存着摘要总结<br />2存着摘要以及提纲 |
| summary | str | 视频摘要 | 通常为一段概括整个视频内容的文本 |
| outline | 有数据时array<br />无数据时null | 分段提纲 | 通常为视频中叙述的各部分及其要点 |
`model_result`对象中的`outline`数组:
| 项 | 类型 | 内容 | 备注 |
|-----|-----|---------|-----|
| 0 | obj | 总结分段1 | |
| n | obj | 总结分段(n+1) | |
| …… | obj | …… | …… |
`outline`数组中的对象:
| 字段 | 类型 | 内容 | 备注 |
|--------------|-----|------|----|
| title | str | 分段标题 | 段落内容的概括 |
| part_outline | array | 分段要点 | 当前分段中多个提到的细节 |
| timestamp | num | 分段起始时间 | 单位为秒 |
`outline`数组中的对象中的`part_outline`数组:
| 项 | 类型 | 内容 | 备注 |
|-----|-----|---------|-----|
| 0 | obj | 分段要点1 | |
| n | obj | 分段要点(n+1) | |
| …… | obj | …… | …… |
`part_outline`数组中的对象:
| 字段 | 类型 | 内容 | 备注 |
|-----------|-----|-------|----|
| timestamp | num | 要点起始时间 | 单位为秒 |
| content | str | 小结内容 | 其中一个分段的要点 |
**示例:**
得到视频`BV1L94y1H7CV``cid=1335073288`)的摘要
```bash
curl -G 'https://api.bilibili.com/x/web-interface/view/conclusion/get' \
--data-urlencode 'bvid=BV1L94y1H7CV' \
--data-urlencode 'cid=1335073288' \
--data-urlencode 'up_mid=297242063' \
--data-urlencode 'wts=1701546363' \
--data-urlencode 'w_rid=1073871926b3ccd99bd790f0162af634'
```
<details>
<summary>查看响应示例:</summary>
```json
{
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"code": 0,
"model_result": {
"result_type": 2,
"summary": "在网上阅读时遇到错别字和语言梗的烦恼,以及正确使用语言的重要性。作者认为,我们每个人都应该有包容心,不掉渣,不纠正别人的错误,同时也需要明辨是非,规范使用语言。视频还提到了一些常见的语言梗和错误用法,呼吁大家不要过分使用网络词汇,而应该注重语言的艺术性和深度。最后,作者欢迎大家关注他的微信公众号。",
"outline": [
{
"title": "现代人使用中文时面临的困境,包括错别字、用法不正确等问题,并呼吁大家规范使用中文。",
"part_outline": [
{
"timestamp": 1,
"content": "网友评论有错别字,勉强能看懂,但难受。"
},
{
"timestamp": 39,
"content": "重来一次,明辨是非。"
},
{
"timestamp": 167,
"content": "粉墨登场是贬义词,形容坏人打扮好老登场。"
}
],
"timestamp": 1
},
{
"title": "网络词汇的过度使用导致语言生硬,以及对流行语言梗的短暂使用感到厌倦。",
"part_outline": [
{
"timestamp": 241,
"content": "网络词汇过分使用会误导别人,使规范词汇生硬"
},
{
"timestamp": 270,
"content": "以前的语言梗有深度,现在的流行梗很短命"
},
{
"timestamp": 338,
"content": "巨星之间需要化学反应的过程,前几场发挥欠佳"
}
],
"timestamp": 241
}
]
},
"stid": "5117037934391059183",
"status": 0,
"like_num": 6,
"dislike_num": 2
}
}
```
</details>
## 点赞&点踩摘要
> https://api.bilibili.com/x/web-interface/view/conclusion/set
*请求方式POST*
认证方式Cookie(SESSDATA)
鉴权方式:[Wbi 签名](../misc/sign/wbi.md)
**url参数:**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|-------|-----|--------|-----|----------------------------------|
| w_rid | str | Wbi 签名 | 必要 | 详见 [Wbi 签名](../misc/sign/wbi.md) |
| wts | num | 当前时间戳 | 必要 | 详见 [Wbi 签名](../misc/sign/wbi.md) |
**正文参数( application/x-www-form-urlencoded ):**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|------------|-----|----------------------|-----|-----------------------------|
| aid | num | 稿件 avid | 必要(可选) | avid与bvid任选一个 |
| bvid | str | 稿件 bvid | 必要(可选) | avid与bvid任选一个 |
| cid | num | 稿件 cid | 必要 | |
| up_mid | num | UP主 mid | 非必要 | |
| stid | num | 摘要 id | 必要 | |
| like_state | num | 执行操作 | 必要 | 1: 点赞<br />2: 取消点赞<br />3: 点踩<br />4: 取消点踩 |
| csrf | str | CSRF Token位于cookie | 必要 | |
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
|---------|-----|------|------------------------------------------|
| code | num | 返回值 | 0: 成功 <br />-400: 请求错误<br />65002origin id 错误<br />65004取消赞失败 未点赞过<br />65005取消踩失败 未点踩过<br />65006: 已赞过<br /> 65007已踩过 |
| message | str | 错误信息 | 默认为0 |
| ttl | num | 1 | |
**示例:**
为视频`BV1L94y1H7CV``cid=1335073288`)的摘要点赞
```shell
curl 'https://api.bilibili.com/x/web-interface/view/conclusion/set?w_rid=edb471fc926646ef3889a80488166b66&wts=1700358953' \
--data-urlencode 'bvid=BV1L94y1H7CV' \
--data-urlencode 'cid=1335073288' \
--data-urlencode 'up_mid=297242063' \
--data-urlencode 'stid=5117037934391059183' \
--data-urlencode '&like_state=1' \
--data-urlencode 'csrf=xxx' \
-b 'SESSDATA=xxx'
```
<details>
<summary>查看响应示例:</summary>
```json
{
"code": 0,
"message": "0",
"ttl": 1
}
```
</details>

View File

@ -175,6 +175,7 @@
| 手工 | handmake | 161 | 手工制品的制作过程或成品展示、教程、测评类视频 | [/v/life/handmake](https://www.bilibili.com/v/life/handmake) |
| 绘画 | painting | 162 | 绘画过程或绘画教程,以及绘画相关的所有视频 | [/v/life/painting](https://www.bilibili.com/v/life/painting) |
| 日常 | daily | 21 | 记录日常生活,分享生活故事 | [/v/life/daily](https://www.bilibili.com/v/life/daily) |
| 亲子 |parenting | 254 | 分享亲子、萌娃、母婴、育儿相关的视频 | [/v/life/parenting](https://www.bilibili.com/v/life/parenting)|
| ~~美食圈~~(重定向) | ~~food~~ | ~~76~~ | ~~美食鉴赏&料理制作教程~~ | ~~/v/life/food~~ |
| ~~动物圈~~(重定向) | ~~animal~~ | ~~75~~ | ~~萌萌的动物都在这里哦~~ | ~~/v/life/animal~~ |
| ~~运动~~(重定向) | ~~sports~~ | ~~163~~ | ~~运动相关的记录、教程、装备评测和精彩瞬间剪辑视频~~ | ~~/v/life/sports~~ |

View File

@ -69,12 +69,16 @@
## 获取视频流地址_web端
> https://api.bilibili.com/x/player/playurl
> https://api.bilibili.com/x/player/wbi/playurl
> ~~https://api.bilibili.com/x/player/playurl~~ (旧链接)
*请求方式GET*
认证方式CookieSESSDATA
鉴权方式:[Wbi 签名](../misc/sign/wbi.md)
---
关于视频流会员鉴权:
@ -109,7 +113,8 @@
| session | str | | 非必要 | 从视频播放页的 HTML 中获取 |
| otype | str | | 非必要 | 固定为`json` |
| type | str | | 非必要 | 目前为空 |
| platform | str | | 非必要 | pcweb播放默认值视频流存在 referer鉴权<br />html5移动端 HTML5 播放(仅支持 MP4 格式,清晰度最高 360P无 referer 鉴权可以直接使用`video`标签播放) |
| platform | str | | 非必要 | pcweb播放默认值视频流存在 referer鉴权<br />html5移动端 HTML5 播放(仅支持 MP4 格式,无 referer 鉴权可以直接使用`video`标签播放) |
| high_quality | num | 是否高画质 | 非必要 | platform=html5时此值为1可使画质为1080p |
**json回复**
@ -452,9 +457,9 @@ curl -G 'https://api.bilibili.com/x/player/playurl' \
| minBufferTime | num | 1.5 | |
| min_buffer_time | num | 1.5 | |
| video | array | 视频流信息 | |
| audio | array | 伴音流信息 | |
| audio | array | 伴音流信息 | 当视频没有音轨时,此项为 null |
| dolby | obj | 杜比全景声伴音信息 | |
| flac | obj | 无损音轨伴音信息 | |
| flac | obj | 无损音轨伴音信息 | 当视频没有无损音轨时,此项为 null |
`dash`中的`video`数组:
@ -494,7 +499,7 @@ curl -G 'https://api.bilibili.com/x/player/playurl' \
| start_with_sap | num | **同上** | |
| SegmentBase | obj | 见下表 | url 对应 m4s 文件中,头部的位置<br />音频流该值恒为空 |
| segment_base | obj | **同上** | |
| codecid | num | 码流编码标识代码 | 含义见 [上表](视频编码代码)<br />音频流该值恒为`0` |
| codecid | num | 码流编码标识代码 | 含义见 [上表](#视频编码代码)<br />音频流该值恒为`0` |
`video`数组中的对象中的`backup_url`数组:

View File

@ -46,7 +46,7 @@
`data`中的`archives`数组中的对象:
基本同[获取视频详细信息web端](/video/info.md#获取视频详细信息web端)中的data对象
基本同[获取视频详细信息web端](../video/info.md#获取视频详细信息web端)中的data对象
`data`中的`page`对象:

View File

@ -45,7 +45,7 @@ _请求方式GET_
`data`中的`list`数组中的对象:
基本同[获取视频详细信息web端](/video/info.md#获取视频详细信息web端)中的data对象
基本同[获取视频详细信息web端](../video/info.md#获取视频详细信息web端)中的data对象
**示例:**

View File

@ -6,7 +6,7 @@
**url参数**
| 字段 | 类型 | 内容 | 必要性 备注 |
| 字段 | 类型 | 内容 | 必要性 | 备注 |
| --------- | ---- | -------- | ----- | ----- |
| page | num | 页码 | 非必要 | 默认为`1` |
| page_size | num | 每页数量 | 非必要 | 默认为`85` |

View File

@ -2,8 +2,7 @@
<img src="../../assets/img/ranking.svg" width="100" height="100"/>
- [视频排行榜](#视频排行榜)
- [获取分区视频排行榜列表](#获取分区视频排行榜列表)
- [获取分区视频排行榜列表](#获取分区视频排行榜列表)
---
@ -19,7 +18,7 @@
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------ | ---- | ----------- | ------ | ------------------------------------- |
| rid | num | 目标分区tid | 非必要 | |
| rid | num | 目标分区tid | 非必要 | 可参考[视频分区一览](../video/video_zone.md#视频分区一览),只支持主分区 |
| type | str | 未知 | 非必要 | 默认为all且为目前唯一已知值。怀疑为稿件类型但没有找到其他值佐证。 |
**json回复**
@ -51,7 +50,7 @@
`data`列表中的对象:
可参考[获取视频详细信息web端](/video/info.md#获取视频详细信息web端)中的data对象。本API对象中所有字段均可在链接对象中找到。
可参考[获取视频详细信息web端](../video/info.md#获取视频详细信息web端)中的data对象。本API对象中所有字段均可在链接对象中找到。
**示例:**

View File

@ -10,10 +10,10 @@
**正文参数 (application/x-www-form-urlencoded)**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
| ------ | ---- | ----------------------- | --------------- | ------------------------------------------------------------ |
| type | num | 兑换类型 | 必要 | 1B币券<br />2会员购优惠券<br />3漫画福利券<br />4会员购包邮券<br/>5漫画商城优惠券 |
| csrf | str | CSRF Token (位于cookie) | Cookie 方式必要 | |
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|------|-----|-----------------------|-------------|--------------------------------------------------------------------------------------|
| type | num | 兑换类型 | 必要 | 1B币券<br />2会员购优惠券<br />3漫画福利券<br />4会员购包邮券<br/>5漫画商城优惠券<br/>6装扮体验卡<br/>7课堂优惠券 |
| csrf | str | CSRF Token (位于cookie) | Cookie 方式必要 | |
**json回复**
@ -46,3 +46,60 @@ curl 'https://api.bilibili.com/x/vip/privilege/receive' \
```
</details>
## 大会员每日经验
> https://api.bilibili.com/x/vip/experience/add
*请求方式POST*
认证方式Cookie (SESSDATA)
**正文参数 (application/x-www-form-urlencoded)**
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|------|-----|-----------------------|-------------|--------------------------------------------------------------------------------------|
| csrf | str | CSRF Token (位于cookie) | Cookie 方式必要 | |
**json回复**
根对象:
| 字段 | 类型 | 内容 | 备注 |
|---------|-----|------|---------------------------------------------------------------------------------------------------|
| code | num | 返回值 | -101账号未登录<br />-111csrf 校验失败<br />69198用户经验已经领取<br />6034007请求频繁,请稍后再试<br />0成功 |
| message | str | 错误信息 | ` |
| ttl | num | 1 | |
| data | obj | | 信息本体 |
**`data`对象:**
| 字段名 | 类型 | 内容 | 备注 |
| ------------------ | ------------------------------- | -------------------- | ---------------------------------------------- |
| type | num | 0 | |
| is_grant | bool | | 暂时发现 code 为 0 时为 `true` |
**示例:**
```shell
curl 'https://api.bilibili.com/x/vip/experience/add' \
-b 'SESSDATA=xxx' \
--data-urlencode 'csrf=xxx'
```
<details>
<summary>查看响应示例:</summary>
```json
{
"code": 69198,
"message": "用户经验已经领取",
"ttl": 1,
"data": {
"type": 0,
"is_grant": false
}
}
```
</details>

View File

@ -21,32 +21,47 @@
`data`对象:
| 字段 | 类型 | 内容 | 备注 |
| --------------- | ----- | ------------ | ---- |
| list | array | 卡券信息列表 | |
| is_short_vip | bool | (?) | |
| is_freight_open | bool | (?) | |
| 字段 | 类型 | 内容 | 备注 |
| ---------------- | ----- | -------------- | ----------- |
| list | array | 卡券信息列表 | |
| is_short_vip | bool | (?) | |
| is_freight_open | bool | (?) | |
| level | num | 当前等级 | |
| cur_exp | num | 当前拥有经验值 | |
| next_exp | num | 升级所需经验值 | 满级时为 -1 |
| is_vip | bool | 是否为大会员 | |
| is_senior_member | num | (?) | |
| format060102 | num | (?) | |
`list`数组:
| 字段 | 类型 | 内容 | 备注 |
| ---- | ---- | ---------------------- | ---- |
| 0 | obj | B币兑换状态 | |
| 1 | obj | 会员购优惠券兑换状态 | |
| 2 | obj | 漫画福利券兑换状态 | |
| 3 | obj | 会员购包邮券兑换状态 | |
| 4 | obj | 漫画商城优惠券兑换状态 | |
| 索引 | 类型 | 内容 | type | 备注 |
| ---- | ---- | -------------------------------- | ---- | ------------------------------- |
| 0 | obj | B币兑换状态 | 1 | |
| 1 | obj | 会员购优惠券兑换状态 | 2 | |
| 2 | obj | 漫画福利券兑换状态 | 3 | |
| 3 | obj | 会员购包邮券兑换状态 | 4 | |
| 4 | obj | 漫画商城优惠券兑换状态 | 5 | |
| 5 | obj | 装扮体验卡兑换状态 | 6 | |
| 6 | obj | 课堂优惠券兑换状态 | 7 | |
| 7 | obj | ~~王者荣耀~~)游戏礼盒兑换状态 | 8 | 每日可领取,目前 state 固定为 1 |
| 8 | obj | 每日 10 经验领取状态 | 9 | 每日可领取,未完成时 state 为 2 |
`list`中的对象:
| 字段 | 类型 | 内容 | 备注 |
| ----------------- | ---- | -------------------- | ------------------------------------------------------------ |
| type | num | 卡券类型 | 1B币券<br />2会员购优惠券<br />3漫画福利券<br />4会员购包邮券<br/>5漫画商城优惠券 |
| state | num | 兑换状态 | 0当月未兑换<br />1已兑换 |
| expire_time | num | 本轮卡券过期时间戳 | 当月月底 |
| vip_type | num | | 2年度大会员可兑换 |
| next_receive_days | num | 距下一轮兑换剩余天数 | |
| period_end_unix | num | 下一轮兑换开始时间戳 | 秒级时间戳 |
| 字段 | 类型 | 内容 | 备注 |
| ----------------- | ---- | -------------------- | ----------------------------------------------------- |
| type | num | 卡券类型 | 详见 `list` 数组表格中的 `type` 项 |
| state | num | 兑换状态 | 0未兑换<br />1已兑换<br />2未完成若需要完成 |
| expire_time | num | 本轮卡券过期时间戳 | 当月月底/当日24点 |
| vip_type | num | 当前用户的大会员状态 | 2年度大会员 |
| next_receive_days | num | 距下一轮兑换剩余天数 | 无权限时,每月任务固定为 0每日固定为 1 |
| period_end_unix | num | 下一轮兑换开始时间戳 | 秒级时间戳 |
**注意:**
卡券除每日可领取(`type` 为 `8``9`)的,其他可通过 [https://api.bilibili.com/x/vip/privilege/receive](./action.md#兑换卡券) 领取
每日 10 经验领取(`type` 为 `9`)需要完成视频观看,未完成的 `state` 为 2。
**示例:**
@ -113,4 +128,4 @@ curl 'https://api.bilibili.com/x/vip/privilege/my' \
}
```
</details>
</details>

View File

@ -30,6 +30,8 @@
## dynamic类型
以下内容爬取自接口`https://api.bilibili.com/x/activity/operation/list?source_id=630edcfddbd0b39ca7371ad2&pn=1&ps=5`且进行去重
[https://i0.hdslb.com/bfs/activity-plat/cover/20171215/o6y3r7or6z.png](https://i0.hdslb.com/bfs/activity-plat/cover/20171215/o6y3r7or6z.png)
[https://i0.hdslb.com/bfs/activity-plat/cover/20171215/2978n4wwpj.png](https://i0.hdslb.com/bfs/activity-plat/cover/20171215/2978n4wwpj.png)
@ -187,3 +189,133 @@
[https://i0.hdslb.com/bfs/activity-plat/cover/20170511/122k3z3lp3.png](https://i0.hdslb.com/bfs/activity-plat/cover/20170511/122k3z3lp3.png)
[https://i0.hdslb.com/bfs/activity-plat/cover/20170511/w44xw6r98w.png](https://i0.hdslb.com/bfs/activity-plat/cover/20170511/w44xw6r98w.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/moCBusxHG2.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/moCBusxHG2.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/LJjOhuzi2l.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/LJjOhuzi2l.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/fzjTcKtbOA.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/fzjTcKtbOA.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/PEXod21DmE.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/PEXod21DmE.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/5NYt7b0jWy.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/5NYt7b0jWy.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/I6DotAbsU0.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/I6DotAbsU0.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/VZkCQV3H8N.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/VZkCQV3H8N.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/pMst3j1Wh2.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/pMst3j1Wh2.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/FFBsId9kkU.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/FFBsId9kkU.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/j8PQollWgb.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/j8PQollWgb.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/CvPAnLwfLB.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/CvPAnLwfLB.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/86Og1GMuE6.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/86Og1GMuE6.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/4gKxYMNEd7.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/4gKxYMNEd7.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/VUahg7oVIp.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/VUahg7oVIp.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/0Wp3GSTqa2.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/0Wp3GSTqa2.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/GI167h1ubu.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/GI167h1ubu.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/abiv2iRJiN.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/abiv2iRJiN.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/vocgKB4Bjl.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/vocgKB4Bjl.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/6cLRxO9RkR.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/6cLRxO9RkR.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/aoqhUIvZ3x.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/aoqhUIvZ3x.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/zRespfCkmo.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/zRespfCkmo.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/3wdVaSoWjI.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/3wdVaSoWjI.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/XywNN8KlpA.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/XywNN8KlpA.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/Yg8QV17GKZ.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/Yg8QV17GKZ.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/h4ytfrWZID.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/h4ytfrWZID.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/J8BB0k7uKM.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/J8BB0k7uKM.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/i8sLpoa4Wn.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/i8sLpoa4Wn.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/XHhqvtddUA.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/XHhqvtddUA.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/hr97jf0KpZ.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/hr97jf0KpZ.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/DUmMBOlW5E.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/DUmMBOlW5E.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/dKua3o3HRw.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/dKua3o3HRw.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/f1BYK2oCwp.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/f1BYK2oCwp.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/els4Nwd0F6.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/els4Nwd0F6.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/PSI3OAv9Hs.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/PSI3OAv9Hs.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/JGrXDA8RKH.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/JGrXDA8RKH.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/wT6pn2O18p.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/wT6pn2O18p.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/Okx4iJ1PLv.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/Okx4iJ1PLv.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/8Ri6Xlk826.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/8Ri6Xlk826.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/nNEBpbZlI0.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/nNEBpbZlI0.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/HtPXYfpuXU.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/HtPXYfpuXU.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/Wwzw0XTwUl.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/Wwzw0XTwUl.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/E738vcDvd3.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/E738vcDvd3.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/dFQfkypPWA.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/dFQfkypPWA.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/hinEAw6Abq.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/hinEAw6Abq.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/KNH7Hz104m.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/KNH7Hz104m.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/2ETVB2F8Pq.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/2ETVB2F8Pq.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/Bk5vekQZoa.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/Bk5vekQZoa.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/IcRizWqXCq.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/IcRizWqXCq.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/jvNq7sSxAT.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/jvNq7sSxAT.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/laYMWQCnnY.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/laYMWQCnnY.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/I2ep6rPv8i.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/I2ep6rPv8i.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/HKynZO2AxL.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/HKynZO2AxL.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/dtYHFq8LIq.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/dtYHFq8LIq.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/egQQvfxwvY.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/egQQvfxwvY.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/duwQurWqyy.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/duwQurWqyy.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/wqP0BMH8vp.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/wqP0BMH8vp.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/00FlTw9i50.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/00FlTw9i50.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/V8wFvnEm3T.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/V8wFvnEm3T.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/VrYZXfmehY.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/VrYZXfmehY.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/QBchCuhVFr.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/QBchCuhVFr.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/hJo8sPKDkj.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/hJo8sPKDkj.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/JnqnvZTKxf.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/JnqnvZTKxf.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/0gu9qonH7t.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/0gu9qonH7t.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/aA5e4coXVQ.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/aA5e4coXVQ.png)
[https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/UM9bnucVhq.png](https://i0.hdslb.com/bfs/activity-plat/static/2cf2b9af5d3c5781d611d6e36f405144/UM9bnucVhq.png)

View File

@ -1,62 +1,64 @@
syntax = "proto3";
package bilibili.account.fission.v1;
// Fission裂变
service Fission {
//
rpc Entrance (EntranceReq) returns (EntranceReply);
//
rpc Window (WindowReq) returns (WindowReply);
//
rpc Privacy(PrivacyReq) returns (PrivacyReply);
}
//
message AnimateIcon {
// icon文件
string icon = 1;
// json文件
string json = 2;
}
// -
message EntranceReply {
//
string icon = 1;
//
string name = 2;
//
string url = 3;
//
AnimateIcon animate_icon = 4;
}
// -
message EntranceReq {}
//
message PrivacyReply {
//
string message = 1;
}
//
message PrivacyReq {
//
string activity_uid = 1;
}
//-
message WindowReply {
//
// 0: 1:
int32 type = 1;
//
string url = 2;
//
string report_data = 3;
}
// -
message WindowReq {}
syntax = "proto3";
package bilibili.account.fission.v1;
// Fission裂变
service Fission {
//
rpc Entrance (EntranceReq) returns (EntranceReply);
//
rpc Window (WindowReq) returns (WindowReply);
//
rpc Privacy (PrivacyReq) returns (PrivacyReply);
}
//
message AnimateIcon {
// icon文件
string icon = 1;
// json文件
string json = 2;
}
// -
message EntranceReply {
//
string icon = 1;
//
string name = 2;
//
string url = 3;
//
AnimateIcon animate_icon = 4;
}
// -
message EntranceReq {}
//
message PrivacyReply {
//
string message = 1;
}
//
message PrivacyReq {
//
string activity_uid = 1;
}
//-
message WindowReply {
//
// 0: 1:
int32 type = 1;
//
string url = 2;
//
string report_data = 3;
}
// -
message WindowReq {
}

View File

@ -1,138 +1,192 @@
syntax = "proto3";
package bilibili.api.probe.v1;
//
service Probe {
//
rpc TestCode (CodeReq) returns (CodeReply);
//
rpc TestReq (ProbeReq) returns (ProbeReply);
//
rpc TestStream (ProbeStreamReq) returns (ProbeStreamReply);
//
rpc TestSub (ProbeSubReq) returns (ProbeSubReply);
}
//
enum Category {
CATEGORY_UNSPECIFIED = 0; //
CATEGORY_ONE = 1; //
CATEGORY_TWO = 2; //
CATEGORY_THREE = 3; //
}
//
message CodeReply {}
//
message CodeReq {
//
int64 code = 1;
}
//
message DynamicMessageUpdate {
//
SimpleMessage body = 1;
}
//
message Embedded {
//
bool bool_val = 1;
//
int32 int32_val = 2;
//
int64 int64_val = 3;
//
float float_val = 4;
//
double double_val = 5;
//
string string_val = 6;
//
repeated int32 repeated_int32_val = 8;
//
repeated string repeated_string_val = 12;
//
map<string, string> map_string_val = 13;
//
map<string, ErrorMessage> map_error_val = 14;
}
//
message ErrorMessage {
//
int64 code = 1;
//
string reason = 2;
//
string message = 3;
}
//
enum ErrorReason {
PROBE_UNSPECIFIED = 0; //
PROBE_CATEGORY_NOTFOUND = 1; //
}
//
message ProbeReply {
//
string content = 1;
//
int64 timestamp = 2;
}
//
message ProbeReq {
//
int64 mid = 1;
//
string buvid = 2;
}
//
message ProbeStreamReply {
//
int64 sequence = 1;
//
int64 timestamp = 2;
//
string content = 3;
}
//
message ProbeStreamReq {
//
int64 mid = 1;
//
int64 sequence = 2;
}
//
message ProbeSubReply {
//
int64 message_id = 1;
}
//
message ProbeSubReq {
//
int64 buvid = 1;
}
//
message SimpleMessage {
//
int32 id = 1;
//
int64 num = 2;
//
string lang = 3;
//
int32 cate = 4;
//
Embedded embedded = 5;
}
syntax = "proto3";
package bilibili.api.probe.v1;
//
service Probe {
//
rpc TestCode (CodeReq) returns (CodeReply);
//
rpc TestReq (ProbeReq) returns (ProbeReply);
//
rpc TestStream (ProbeStreamReq) returns (ProbeStreamReply);
//
rpc TestSub (ProbeSubReq) returns (ProbeSubReply);
}
//
service ProbeService {
//
rpc Echo(SimpleMessage) returns (SimpleMessage);
//
rpc EchoBody(SimpleMessage) returns (SimpleMessage);
//
rpc EchoDelete(SimpleMessage) returns (SimpleMessage);
//
rpc EchoError(ErrorMessage) returns (ErrorMessage);
//
rpc EchoPatch(DynamicMessageUpdate) returns (DynamicMessageUpdate);
}
//
enum Category {
CATEGORY_UNSPECIFIED = 0; //
CATEGORY_ONE = 1; //
CATEGORY_TWO = 2; //
CATEGORY_THREE = 3; //
CATEGORY_FOUR = 4; //
}
//
message CodeReply {
//
string id = 1;
//
string id1 = 2;
//
int64 code = 3;
//
string message_s = 4;
}
//
message CodeReq {
//
int64 code = 1;
}
//
message CreateTopic {
//
int64 id = 1;
}
//
message CreatTask {
//
string name = 1;
}
//
message DynamicMessageUpdate {
//
SimpleMessage body = 1;
}
//
message Embedded {
//
bool bool_val = 1;
//
int32 int32_val = 2;
//
int64 int64_val = 3;
//
float float_val = 4;
//
double double_val = 5;
//
string string_val = 6;
//
repeated bool repeated_bool_val = 7;
//
repeated int32 repeated_int32_val = 8;
//
repeated int64 repeated_int64_val = 9;
//
repeated float repeated_float_val = 10;
//
repeated double repeated_double_val = 11;
//
repeated string repeated_string_val = 12;
//
map<string, string> map_string_val = 13;
//
map<string, ErrorMessage> map_error_val = 14;
}
//
message ErrorMessage {
//
int64 code = 1;
//
string reason = 2;
//
string message = 3;
}
// Deprecated
enum ErrorReason {
PROBE_UNSPECIFIED = 0; //
PROBE_CATEGORY_NOTFOUND = 1; //
}
//
message ProbeReply {
//
string content = 1;
//
int64 timestamp = 2;
}
//
message ProbeReq {
//
int64 mid = 1;
//
string buvid = 2;
}
//
message ProbeStreamReply {
//
int64 sequence = 1;
//
int64 timestamp = 2;
//
string content = 3;
}
//
message ProbeStreamReq {
//
int64 mid = 1;
//
int64 sequence = 2;
}
//
message ProbeSubReply {
//
int64 message_id = 1;
}
//
message ProbeSubReq {
//
string buvid = 1;
}
//
message SimpleMessage {
//
int32 id = 1;
//
int64 num = 2;
//
string lang = 3;
//
int32 cate = 4;
//
Embedded embedded = 5;
}
//
message Task {
//
string name = 1;
//
string author = 2;
//
bool cache = 3;
}

View File

@ -0,0 +1,79 @@
syntax = "proto3";
package bilibili.api.ticket.v1;
service Ticket {
// Ticket
rpc GetTicket (GetTicketRequest) returns (GetTicketResponse);
// Webview 使 Ticket
rpc GenWebTicket (GenWebTicketRequest) returns (GenWebTicketResponse);
}
//
message GenWebTicketRequest {
//
map<string, string> context = 1;
//
string key_id = 2;
//
string hexsign = 3;
//
string token = 4;
}
//
message GenWebTicketResponse {
//
message Context {
//
string v_voucher = 1;
}
//
message Nav {
//
string img = 1;
//
string sub = 2;
}
//
string ticket = 1;
//
int64 created_at = 2;
//
int64 ttl = 3;
//
Context context = 4;
//
Nav nav = 5;
}
//
message GetTicketRequest {
// :
// + x-fingerprint(, 使 datacenter.hakase.protobuf.AndroidDeviceInfo )
// + x-exbadbasket(?)
map<string, bytes> context = 1;
// ec01
string key_id = 2;
//
bytes sign = 3;
//
string token = 4;
}
//
message GetTicketResponse {
//
message Context {
//
string v_voucher = 1;
}
// x-bili-ticket
string ticket = 1;
//
int64 created_at = 2;
//
int64 ttl = 3;
//
Context context = 4;
}

View File

@ -0,0 +1,122 @@
syntax = "proto3";
package bilibili.app.click.v1;
service Click {
//
rpc HeartBeat (HeartBeatReq) returns (HeartBeatReply);
}
//
message AccountInfo {
//
uint64 mid = 1;
}
//
message AppInfo {
//
string top_page_class = 1;
//
int64 ftime = 2;
//
string did = 3;
}
//
message Extra {
//
string session = 1;
//
string refer = 2;
}
message HeartBeatReply {}
//
message HeartBeatReq {
//
string session_v2 = 1;
//
Stage stage = 2;
// timeout
uint64 stream_timeout = 3;
//
uint64 batch_frequency = 4;
//
float frequency = 5;
//
VideoMeta video_meta = 6;
//
AppInfo app_info = 7;
//
AccountInfo account_info = 8;
//
PreProcessResult pre_process_result = 9;
//
repeated PlayerStatus player_status = 10;
//
VideoInfo video_info = 11;
}
//
message PlayerStatus {
//
float playback_rate = 1;
//
uint64 progress = 2;
//
PlayState play_state = 3;
//
bool is_buffering = 4;
}
//
enum PlayState {
//
STATE_UNKNOWN = 0;
//
PREPARING = 1;
//
PREPARED = 2;
//
PLAYING = 3;
//
PAUSED = 4;
//
STOPPED = 5;
//
FAILED = 6;
}
//
message PreProcessResult {
//
int64 vt = 1;
}
//
enum Stage {
//
STAGE_UNKNOWN = 0;
//
START = 1;
//
END = 2;
//
SAMPLE = 3;
}
//
message VideoInfo {
//
uint64 cid_duration = 1;
}
//
message VideoMeta {
//
uint64 aid = 1;
//
uint64 cid = 2;
}

View File

@ -0,0 +1,11 @@
syntax = "proto3";
package bilibili.app.distribution.setting.download;
import "bilibili/app/distribution/v1/distribution.proto";
//
message DownloadSettingsConfig {
//
bilibili.app.distribution.v1.BoolValue enable_download_auto_start = 1;
}

View File

@ -0,0 +1,17 @@
syntax = "proto3";
package bilibili.app.distribution.setting.dynamic;
import "bilibili/app/distribution/v1/distribution.proto";
//
message DynamicAutoPlay {
//
bilibili.app.distribution.v1.Int64Value value = 1;
}
//
message DynamicDeviceConfig {
//
DynamicAutoPlay auto_play = 1;
}

View File

@ -0,0 +1,65 @@
syntax = "proto3";
package bilibili.app.distribution.setting.experimental;
import "bilibili/app/distribution/v1/distribution.proto";
//
message DynamicSelect {
//
bilibili.app.distribution.v1.BoolValue fold = 1;
}
//
message Exp {
//
bilibili.app.distribution.v1.Int64Value id = 1;
//
bilibili.app.distribution.v1.Int32Value bucket = 2;
}
//
message ExperimentalConfig {
//
bilibili.app.distribution.v1.StringValue flag = 1;
//
repeated Exp exps = 2;
}
//
message MultipleTusConfig {
//
TopLeft top_left = 1;
//
DynamicSelect dynamic_select = 2;
}
// APP首页头像跳转信息
message TopLeft {
//
bilibili.app.distribution.v1.StringValue url = 1;
//
bilibili.app.distribution.v1.StringValue story_foreground_image = 2;
//
bilibili.app.distribution.v1.StringValue story_background_image = 3;
//
bilibili.app.distribution.v1.StringValue listen_foreground_image = 4;
//
bilibili.app.distribution.v1.StringValue listen_background_image = 5;
//
bilibili.app.distribution.v1.StringValue ios_story_foreground_image = 6;
//
bilibili.app.distribution.v1.StringValue ios_story_background_image = 7;
//
bilibili.app.distribution.v1.StringValue ios_listen_foreground_image = 8;
//
bilibili.app.distribution.v1.StringValue ios_listen_background_image = 9;
//
bilibili.app.distribution.v1.StringValue goto = 10;
//
bilibili.app.distribution.v1.StringValue url_v2 = 11;
//
bilibili.app.distribution.v1.Int64Value goto_v2 = 12;
//
bilibili.app.distribution.v1.StringValue badge = 13;
}

View File

@ -0,0 +1,11 @@
syntax = "proto3";
package bilibili.app.distribution.setting.internaldevice;
import "bilibili/app/distribution/v1/distribution.proto";
//
message InternalDeviceConfig {
//
bilibili.app.distribution.v1.Int64Value fts = 1;
}

View File

@ -0,0 +1,11 @@
syntax = "proto3";
package bilibili.app.distribution.setting.night;
import "bilibili/app/distribution/v1/distribution.proto";
//
message NightSettingsConfig {
//
bilibili.app.distribution.v1.BoolValue is_night_follow_system = 1;
}

View File

@ -0,0 +1,25 @@
syntax = "proto3";
package bilibili.app.distribution.setting.other;
import "bilibili/app/distribution/v1/distribution.proto";
//
message OtherSettingsConfig {
//
bilibili.app.distribution.v1.Int64Value watermark_type = 1;
//
bilibili.app.distribution.v1.Int64Value web_image_quality_type = 2;
//
bilibili.app.distribution.v1.BoolValue enable_read_pasteboard = 3;
//
bilibili.app.distribution.v1.BoolValue paste_auto_jump = 4;
//
bilibili.app.distribution.v1.BoolValue mini_screen_play_when_back = 5;
//
bilibili.app.distribution.v1.BoolValue enable_resume_playing = 6;
//
bilibili.app.distribution.v1.BoolValue enable_wifi_auto_update = 7;
//
bilibili.app.distribution.v1.BoolValue enable_guide_screenshot_share = 8;
}

View File

@ -0,0 +1,41 @@
syntax = "proto3";
package bilibili.app.distribution.setting.pegasus;
import "bilibili/app/distribution/v1/distribution.proto";
//
message FeedModeValue {
//
bilibili.app.distribution.v1.Int64Value value = 1;
}
//
message PegasusAutoPlay {
//
bilibili.app.distribution.v1.Int64Value single = 1;
//
bilibili.app.distribution.v1.Int64Value double = 2;
//
bilibili.app.distribution.v1.BoolValue single_affected_by_server_side = 3;
//
bilibili.app.distribution.v1.BoolValue double_affected_by_server_side = 4;
}
//
message PegasusColumnValue {
//
bilibili.app.distribution.v1.Int64Value value = 1;
//
bilibili.app.distribution.v1.BoolValue affected_by_server_side = 2;
}
//
message PegasusDeviceConfig {
//
PegasusColumnValue column = 1;
//
FeedModeValue mode = 2;
//
PegasusAutoPlay auto_play = 3;
}

View File

@ -0,0 +1,58 @@
syntax = "proto3";
package bilibili.app.distribution.setting.play;
import "bilibili/app/distribution/v1/distribution.proto";
//
message CloudPlayConfig {
//
bilibili.app.distribution.v1.BoolValue enable_panorama = 1;
//
bilibili.app.distribution.v1.BoolValue enable_dolby = 2;
//
bilibili.app.distribution.v1.BoolValue enable_shake = 3;
//
bilibili.app.distribution.v1.BoolValue enable_background = 4;
// HIRES
bilibili.app.distribution.v1.BoolValue enable_loss_less = 5;
}
//
message PlayConfig {
//
bilibili.app.distribution.v1.BoolValue should_auto_play = 1;
//
bilibili.app.distribution.v1.BoolValue should_auto_fullscreen = 2;
//
bilibili.app.distribution.v1.BoolValue enable_playurl_https = 3;
//
bilibili.app.distribution.v1.BoolValue enable_danmaku_interaction = 4;
//
bilibili.app.distribution.v1.Int64Value small_screen_status = 5;
//
bilibili.app.distribution.v1.Int64Value player_codec_mode_key = 6;
//
bilibili.app.distribution.v1.BoolValue enable_gravity_rotate_screen = 7;
//
bilibili.app.distribution.v1.BoolValue enable_danmaku_monospaced = 8;
//
bilibili.app.distribution.v1.BoolValue enable_edit_subtitle = 9;
//
bilibili.app.distribution.v1.BoolValue enable_subtitle = 10;
//
bilibili.app.distribution.v1.Int64Value color_filter = 11;
//
bilibili.app.distribution.v1.BoolValue should_auto_story = 12;
//
bilibili.app.distribution.v1.BoolValue landscape_auto_story = 13;
//
bilibili.app.distribution.v1.BoolValue volume_balance = 14;
}
//
message SpecificPlayConfig {
//
bilibili.app.distribution.v1.BoolValue enable_segmented_section = 1;
}

View File

@ -0,0 +1,20 @@
syntax = "proto3";
package bilibili.app.distribution.setting.privacy;
import "bilibili/app/distribution/v1/distribution.proto";
//
message MidPrivacySettingsConfig {
//
bilibili.app.distribution.v1.BoolValue recommend_to_known = 1;
}
//
message PrivacySettingsConfig {
//
bilibili.app.distribution.v1.BoolValue ad_recommand_store = 1;
//
bilibili.app.distribution.v1.BoolValue sensor_access = 2;
}

View File

@ -0,0 +1,19 @@
syntax = "proto3";
package bilibili.app.distribution.setting.search;
import "bilibili/app/distribution/v1/distribution.proto";
//
message SearchAutoPlay {
//
bilibili.app.distribution.v1.Int64Value value = 1;
//
bilibili.app.distribution.v1.BoolValue affected_by_server_side = 2;
}
//
message SearchDeviceConfig {
//
SearchAutoPlay auto_play = 1;
}

View File

@ -0,0 +1,158 @@
syntax = "proto3";
package bilibili.app.distribution.v1;
import "google/protobuf/any.proto";
// APP配置
service Distribution {
//
rpc GetUserPreference (GetUserPreferenceReq) returns (GetUserPreferenceReply);
//
rpc SetUserPreference (SetUserPreferenceReq) returns (SetUserPreferenceReply);
//
rpc UserPreference (UserPreferenceReq) returns (UserPreferenceReply);
}
//
message GetUserPreferenceReq {
//
repeated string type_url = 1;
//
map<string, string> extra_context = 2;
}
//
message GetUserPreferenceReply {
// GetUserPreferenceReq
repeated google.protobuf.Any value = 1;
}
//
message SetUserPreferenceReq {
//
repeated google.protobuf.Any preference = 1;
//
map<string, string> extra_context = 2;
}
//
message SetUserPreferenceReply {}
//
message UserPreferenceReq {}
//
message UserPreferenceReply {
// type_url
repeated google.protobuf.Any preference = 1;
}
//
message BoolValue {
//
bool value = 1;
//
int64 last_modified = 2;
//
bool default_value = 3;
//
string exp = 4;
}
//
message BytesValue {
//
bytes value = 1;
//
int64 last_modified = 2;
//
bytes default_value = 3;
//
string exp = 4;
}
//
message DoubleValue {
//
double value = 1;
//
int64 last_modified = 2;
//
double default_value = 3;
//
string exp = 4;
}
//
message FloatValue {
//
float value = 1;
//
int64 last_modified = 2;
//
float default_value = 3;
//
string exp = 4;
}
//
message Int32Value {
//
int32 value = 1;
//
int64 last_modified = 2;
//
int32 default_value = 3;
//
string exp = 4;
}
//
message Int64Value {
//
int64 value = 1;
//
int64 last_modified = 2;
//
int64 default_value = 3;
//
string exp = 4;
}
//
message StringValue {
//
string value = 1;
//
int64 last_modified = 2;
//
string default_value = 3;
//
string exp = 4;
}
//
message UInt32Value {
//
uint32 value = 1;
//
int64 last_modified = 2;
//
uint32 default_value = 3;
//
string exp = 4;
}
//
message UInt64Value {
//
uint64 value = 1;
//
int64 last_modified = 2;
//
uint64 default_value = 3;
//
string exp = 4;
}

View File

@ -0,0 +1,22 @@
syntax = "proto3";
package bilibili.app.dynamic.common;
//
message ItemWHRatio {
//
int32 ratio = 1;
//
int32 width = 2;
//
int32 height = 3;
}
//
enum WHRatio {
W_H_RATIO_1_1 = 0;
W_H_RATIO_16_9 = 1;
W_H_RATIO_3_4 = 2;
W_H_RATIO_CUSTOM = 3;
}

View File

@ -0,0 +1,66 @@
syntax = "proto3";
package bilibili.app.dynamic.v2;
import "bilibili/app/archive/middleware/v1/preload.proto";
import "bilibili/pagination/pagination.proto";
import "bilibili/app/dynamic/common/dynamic.proto";
import "bilibili/app/dynamic/v2/dynamic.proto";
service Campus {
//
rpc WaterFlowRcmd (WaterFlowRcmdReq) returns (WaterFlowRcmdResp);
}
//
message CampusWaterFlowItem {
//
int32 item_type = 1;
//
bilibili.app.dynamic.common.ItemWHRatio wh_ratio = 2;
//
oneof item {
WFItemDefault item_default = 3;
}
}
//
message WaterFlowRcmdReq {
//
int64 campus_id = 1;
//
int32 page = 2;
//
bilibili.app.archive.middleware.v1.PlayerArgs player_args = 3;
//
CampusRcmdReqFrom from = 4;
}
//
message WaterFlowRcmdResp {
//
repeated CampusWaterFlowItem items = 1;
//
bilibili.pagination.FeedPaginationReply offset = 2;
}
//
message WFItemDefault {
//
string title = 1;
//
string cover = 2;
//
CoverIconWithText bottom_left_1 = 3;
//
CoverIconWithText bottom_left_2 = 4;
//
CoverIconWithText bottom_right_1 = 5;
//
string uri = 6;
//
RcmdReason rcmd_reason = 7;
//
map<string, string> annotations = 8;
}

Some files were not shown because too many files have changed in this diff Show More