diff --git a/.github/update.log b/.github/update.log index 0db367f611..1cb28174e5 100644 --- a/.github/update.log +++ b/.github/update.log @@ -1256,3 +1256,4 @@ Update On Mon Jan 26 19:49:29 CET 2026 Update On Tue Jan 27 19:51:58 CET 2026 Update On Wed Jan 28 19:49:27 CET 2026 Update On Thu Jan 29 20:05:52 CET 2026 +Update On Fri Jan 30 16:38:46 CET 2026 diff --git a/bb-api-collect/.github/FUNDING.yml b/bb-api-collect/.github/FUNDING.yml new file mode 100644 index 0000000000..b5cfe717ca --- /dev/null +++ b/bb-api-collect/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: [SocialSisterYi] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: https://afdian.com/@ShakaiAneE diff --git a/bb-api-collect/.github/ISSUE_TEMPLATE/1-add-request.yml b/bb-api-collect/.github/ISSUE_TEMPLATE/1-add-request.yml new file mode 100644 index 0000000000..d632a1a15a --- /dev/null +++ b/bb-api-collect/.github/ISSUE_TEMPLATE/1-add-request.yml @@ -0,0 +1,56 @@ +name: "新增请求" +description: "请求添加文档中未收录的 API 定义" +title: "[新增请求] " +labels: ["新增/Add"] +body: + - type: checkboxes + id: reminders + attributes: + label: "提交前请确认" + options: + - label: "我已阅读贡献指南, 已检索仓库中文档,确认不包含所提及内容,且 Issues、Pull Requests 中无相关提交" + required: true + - type: dropdown + id: source + attributes: + label: "API 来源" + description: "该 API 在何平台中使用" + multiple: true + options: + - "Web 端(含 H5)" + - "PC 客户端(Electron)" + - "Android 客户端(含粉版、平板版、蓝版、概念版、国际版等)" + - "TV 客户端(含云视听小电视、车机、物联网版等)" + - "iOS 客户端(含粉版、平板版、概念版等)" + - "必剪客户端" + - "漫画客户端" + - "其他(请在详情中备注)" + validations: + required: true + - type: dropdown + id: type + attributes: + label: "API 类型" + description: "API 所使用的协议标准及调用方式" + options: + - "REST" + - "gRPC" + - "长连接数据帧(含 WS、TCP)" + - "其他类型(请在详情中备注)" + validations: + required: true + - type: input + id: address + attributes: + label: "API 地址" + description: "REST 的 URL,或 gRPC 的包名+服务名" + placeholder: "eg: https://api.bilibili.com/2333333" + validations: + required: true + - type: textarea + id: details + attributes: + label: "详情描述" + description: "请描述该 API 的使用场景、请求及响应字段等,可附上原始抓包记录" + validations: + required: true diff --git a/bb-api-collect/.github/ISSUE_TEMPLATE/2-update-request.yml b/bb-api-collect/.github/ISSUE_TEMPLATE/2-update-request.yml new file mode 100644 index 0000000000..cc2a1fc118 --- /dev/null +++ b/bb-api-collect/.github/ISSUE_TEMPLATE/2-update-request.yml @@ -0,0 +1,29 @@ +name: "更新请求" +description: "请求补充或更新文档中已有的 API 定义" +title: "[更新请求] <title>" +labels: ["更新/Update"] +body: + - type: checkboxes + id: reminders + attributes: + label: "提交前请确认" + options: + - label: "我已阅读贡献指南, 已确认文档中相关内容存在错误或不足,且 Issues、Pull Requests 中无相关提交" + required: true + - type: input + id: document_link + attributes: + label: "原文档链接" + description: | + 需要更新的文档链接,指定到具体 API<br> + eg: https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/bangumi/info.md#获取剧集明细web端ssidepid方式<br> + https://socialsisteryi.github.io/bilibili-API-collect/docs/bangumi/info.html#获取剧集明细-web端-ssid-epid方式 + validations: + required: true + - type: textarea + id: details + attributes: + label: "更新内容" + description: "请指出原文档中与最新 API 行为不符之处,并附上已知的最新改动和验证信息" + validations: + required: true diff --git a/bb-api-collect/.github/ISSUE_TEMPLATE/3-mistake-report.yml b/bb-api-collect/.github/ISSUE_TEMPLATE/3-mistake-report.yml new file mode 100644 index 0000000000..22df22c06c --- /dev/null +++ b/bb-api-collect/.github/ISSUE_TEMPLATE/3-mistake-report.yml @@ -0,0 +1,64 @@ +name: "错误修正" +description: "发现文档内容有误并提交修正请求" +title: "[错误修正] <title>" +labels: ["错误/Mistakes"] +body: + - type: checkboxes + id: confirmations + attributes: + label: "提交前请确认" + options: + - label: "我已阅读贡献指南, 已确认文档中有错误存在,且 Issues、Pull Requests 中无相同修正" + required: true + - label: "我已验证修正内容的正确性" + required: false + + - type: input + id: document_link + attributes: + label: "错误所在文档链接" + description: | + 需要修正的文档链接,指定到具体 API<br> + eg: https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/bangumi/info.md#获取剧集明细web端ssidepid方式<br> + https://socialsisteryi.github.io/bilibili-API-collect/docs/bangumi/info.html#获取剧集明细-web端-ssid-epid方式 + validations: + required: true + + - type: dropdown + id: error_type + attributes: + label: "错误类型" + multiple: true + options: + - "API 地址/鉴权方式错误" + - "参数错误" + - "响应数据结构或响应示例错误" + - "描述性内容错误(如拼写/流程说明)" + - "接口已弃用或下线" + - "其他(请在下文说明)" + validations: + required: true + + - type: textarea + id: error_description + attributes: + label: "错误描述" + description: "请详细说明具体错误所在,如有多个错误请编号列出" + validations: + required: true + + - type: textarea + id: evidence + attributes: + label: "纠错依据" + description: "如果有,请提供抓包记录等佐证,方便确认。如果有多个错误,请将依据对应错误描述的编号列出" + validations: + required: false + + - type: textarea + id: correction + attributes: + label: "修正方案" + description: "如果可以,请提供修正后的内容,如有多个修正点请编号列出" + validations: + required: false diff --git a/bb-api-collect/.github/ISSUE_TEMPLATE/config.yml b/bb-api-collect/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..e65606e913 --- /dev/null +++ b/bb-api-collect/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: 参与讨论 + url: https://github.com/SocialSisterYi/bilibili-API-collect/discussions + about: 代码用例、情报分享等内容请使用 Discussions diff --git a/bb-api-collect/.github/workflows/vuepress-deploy.yml b/bb-api-collect/.github/workflows/vuepress-deploy.yml new file mode 100644 index 0000000000..46c3e95888 --- /dev/null +++ b/bb-api-collect/.github/workflows/vuepress-deploy.yml @@ -0,0 +1,37 @@ +name: deploy and publish + +on: + workflow_dispatch: + push: + branches: + - master + +permissions: + contents: write + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + # if: github.repository == 'SocialSisterYi/bilibili-API-collect' + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup Node.js environment + uses: actions/setup-node@v4.0.3 + with: + node-version: 22 + cache: yarn + - name: Build with yarn + run: yarn && yarn build + - name: Commit & Push + run: | + cd .vuepress/dist/ + git init -b gh_pages + git config user.name "github-actions" + git config user.email "github-actions@github.com" + git remote add origin https://user:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }} + git add -A . + git commit -m "generated" + git push -fu origin gh_pages diff --git a/bb-api-collect/.gitignore b/bb-api-collect/.gitignore new file mode 100644 index 0000000000..7307447f38 --- /dev/null +++ b/bb-api-collect/.gitignore @@ -0,0 +1,11 @@ +/.vuepress/.cache/ +/.vuepress/.temp/ +/.vuepress/dist/ +/node_modules/ +.idea/ +.vscode/ +.DS_Store +*.swp +/*.*js +/*.json +/*.sh diff --git a/bb-api-collect/.vuepress/client.js b/bb-api-collect/.vuepress/client.js new file mode 100644 index 0000000000..0509372b0c --- /dev/null +++ b/bb-api-collect/.vuepress/client.js @@ -0,0 +1,8 @@ +import { defineClientConfig } from '@vuepress/client' +import Layout from './theme/layouts/Layout.vue' + +export default defineClientConfig({ + layouts: { + Layout, + }, +}) diff --git a/bb-api-collect/.vuepress/config.js b/bb-api-collect/.vuepress/config.js new file mode 100644 index 0000000000..dbe9307400 --- /dev/null +++ b/bb-api-collect/.vuepress/config.js @@ -0,0 +1,64 @@ +import { defineUserConfig } from "vuepress"; +import { viteBundler } from '@vuepress/bundler-vite' +import { defaultTheme } from "@vuepress/theme-default"; +import markdownItTaskLists from "markdown-it-task-lists"; +import { searchPlugin } from "@vuepress/plugin-search"; +import { shikiPlugin } from '@vuepress/plugin-shiki' + +const base = "/bilibili-API-collect/"; + +export default defineUserConfig({ + bundler: viteBundler(), + base: base, + lang: "zh-CN", + title: "BAC Document", + description: "社区开源的第三方哔哩哔哩 API 文档", + head: [["link", { rel: "icon", href: base + "logo2.jpg" }]], + locales: { + "/": { + lang: "zh-CN", + }, + }, + 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=ympvb3LAPT-Ulu3ezhGqbkJ8zXMKImOX&authKey=z1KdkOdKO3wytN43m9K6On9nBtnDL4pAoD6VQHCipFBb9TasNDKuDHCmOE6TF3uc&noverify=0&group_code=191187164", + }, + { + text: "Telegram交流群(Github Bot推送)", + link: "https://t.me/bilibili_API_collect_community", + }, + ], + }, + ], + repo: "https://github.com/SocialSisterYi/bilibili-API-collect", + docsBranch: "master", + editLinkText: "在 GitHub 上编辑此页", + colorMode: "auto", + themePlugins: { + prismjs: false + } + }), + plugins: [ + searchPlugin({}), + shikiPlugin({ + theme: 'dark-plus', + langs: [ + 'javascript', 'typescript', 'markdown', 'protobuf', 'json', 'jsonc', + 'shell', 'go', 'html', 'http', 'java', 'kotlin', 'python', 'rust', 'c', + 'c++', 'cs', 'php', 'swift', 'text' + ] + }) + ], + extendsMarkdown: (md) => { + md.use(markdownItTaskLists); + } +}); diff --git a/bb-api-collect/.vuepress/public/logo2.jpg b/bb-api-collect/.vuepress/public/logo2.jpg new file mode 100644 index 0000000000..199eefc2de Binary files /dev/null and b/bb-api-collect/.vuepress/public/logo2.jpg differ diff --git a/bb-api-collect/.vuepress/theme/layouts/Layout.vue b/bb-api-collect/.vuepress/theme/layouts/Layout.vue new file mode 100644 index 0000000000..75d2f211ac --- /dev/null +++ b/bb-api-collect/.vuepress/theme/layouts/Layout.vue @@ -0,0 +1,28 @@ +<template> + <ParentLayout> + <template #page-bottom> + <footer style="text-align: center"> + Copyright © 2020-2025 + <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> + +<style> + /* README.md */ + .shields a { + margin: auto .25em; + } + .shields a::after { + display: none !important; + } +</style> + +<script setup> +import ParentLayout from '@vuepress/theme-default/layouts/Layout.vue'; +</script> diff --git a/bb-api-collect/CONTRIBUTING.md b/bb-api-collect/CONTRIBUTING.md new file mode 100644 index 0000000000..8856cabdc4 --- /dev/null +++ b/bb-api-collect/CONTRIBUTING.md @@ -0,0 +1,285 @@ +# 贡献指南 + +欢迎来到 bilibili-API-collect 社区贡献指南,本文主要面向想要对本项目参与贡献的用户, 请务必认真阅读本文正文与潜在的注释 + +## 总则 + +[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) 语法进行文档书写,按照业务类型及功能以**路径**+**文件**形式索引,任何用户都可通过 Issue、Pull Request 与 Discussion 提供自己分析出的接口地址与使用说明。 + +本项目收集的接口类型包括但不限于 REST API、gRPC、WebSocket,文档内统一优先使用安全套接字协议,如 `https`、`securityRpc`、`wss`。 + +## Issue、Discussion 与社群讨论 + +对文档内容存在**不理解**之处、以及发现文档内容有所**缺失**或**错误**,可直接提出,强烈建议以提交 **Issue** 的形式 添加 / 补充 / 更新 文档中的说明,以发起 **Discussion** 的形式提出问题、代码用例、情报分享,并希望关于本项目的各种交流都是**公开进行**的,因为这样才可以保证关键信息的一致性。 + +提交 Issue 请遵守以下原则: + +1. 标题需要点明 API 的用处, `<title>` 要替换为标题主要内容而不是保留不动,切勿仅填写 `补充`、`修复`,形式良好的标题可以是 `[新增请求] 新增 xx 接口`、`[更新请求] xx 接口地址已失效`、`[更新请求] xx 接口的参数有变化` +2. 正文请按照 Issue 模板进行填写,标明 API 来源(Web、Android、iOS、TV 等)、API 类型(REST、gRPC、WebSocket 等)、API 地址 +3. 详情描述需要提供该 API 的使用场景、请求及响应字段等,可附上原始抓包记录 (文本格式优先);在更新时还需指出原文档中与最新 API 行为不符之处,并附上已知的最新改动。例如:“在前端页面某地址 / APP 某界面访问某 API(标明地址),它的某参数与文档中不符(标明文档地址)” + +发起 Discussion 请遵守以下原则: + +1. 标题言简意骇,说明欲提出的问题要点,如 `如何通过 xx 接口获取 yy`、`关于 xx 字段意义的探讨`、`建议将 xx 加入 yy 分类` 等标题;切勿使用表意含糊不清或索取性的标题,如 `怎么解决风控`、`搜索的接口是什么`、`好兄弟有没有投稿的接口` 等标题 +2. Discussion 正文应对遇到的问题进行尽可能详细的描述,展开并聚焦有关的信息,例如: “按照文档中某位置的说明进行了某操作,为什么无法获得预期结果”、“请问某 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://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=ympvb3LAPT-Ulu3ezhGqbkJ8zXMKImOX&authKey=z1KdkOdKO3wytN43m9K6On9nBtnDL4pAoD6VQHCipFBb9TasNDKuDHCmOE6TF3uc&noverify=0&group_code=191187164) +- 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 及其相关社群中**禁止**询问讨论 风控解除、爬虫(采集)、破解、漏洞利用、买卖代码和账号 相关内容,抵制基于本项目进行的一切黑产行为! + +::: + +## 目录与路径结构 + +### 目录 + +文档目录以 **Markdown 无序列表**语法写在 [README.md](README.md) 中,使用缩进标识文档的层级,如 `视频` 下存在 `基本信息`、`快照`、`视频推荐`、`TAG` 等子分类,使用 **Markdown 复选框**语法该标注文档是否编写完成, 新文档写完后记得在目录添加入口 + +```markdown +- [ ] 视频 + - [x] 基本信息 + - [x] 快照 + - [x] 视频推荐 + - [ ] TAG +``` + +### 路径 + +路径层级应当与文档目录一致,以文件夹的形式存放在项目中的 `/docs` 路径下,命名统一使用英文小写,如 `video`、`danmaku`、`comment`, 不建议出现 `&` 等特殊字符 + +二级、三级路径应当存在二级三级目录,可选添加 `README.md` 以描述该子目录 + +### 文件 + +各个子接口集整理为 Markdown (.md) 文件,命名统一使用英文小写,如 `info.md`、`action.md`、`list.md` + +文档文件中用于存放相关的接口的说明,如 `video/` 下的 `info.md`,存在 `查询视频基本信息`、`查询视频简介`、`查询视频分P列表` 等内容 + +## Markdown 文档内容格式 + +文档使用 [VuePress](https://vuepress.vuejs.org/) 生成,可以使用 [VuePress Markdown 扩展语法](https://vuepress.vuejs.org/guide/markdown.html)编写 + +注:以下文档范式主要针对接口类文档, 可根据**实际情况**进行调整, 你也可以使用 [`json-apidoc-gen`](https://github.com/SessionHu/json-apidoc-gen) 工具直接生成模板自行填充内容. 非接口类文档, 如算法等, 可以参考已有的内容 + +### 头部 + +文档首行为**一级标签**格式标题,如 `# 用户基本信息` + +**文档头部不需要手写索引**,索引由 VuePress 自动生成 + +### 接口说明 + +文档中可存在多个接口说明,应当遵守同一范式,依次排列在文档中 + +接口说明分为 `标题`、`地址`、`说明`、`请求参数`、`响应正文`、`示例` 这些部分 + +接口标题为**二级以下**的标签<!--别顶着一级标题就开写-->,接口地址使用**块引用**语法,地址只保留 REST API 路径,不应携带 query 等内容 + +接口地址下方需要注明接口的请求方法,如 `GET`、`POST`、`PUT` 等,使用*斜体*语法 + +若接口存在认证或鉴权,需要在说明中注明,如 `Cookie (SESSDATA)`、`APP`(认证是针对用户的,鉴权是针对接口使用的) + +其他使用说明也可写在这里,如 `限制游客访问的视频需要登录` + +e.g.: + +```markdown +## 获取视频详细信息_web端 + +> https://api.bilibili.com/x/web-interface/view + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +限制游客访问的视频需要登录 +``` + +**请求参数**应在**接口说明**的下方,应注明参数类型 URL 参数或正文参数(正文参数应注明 `Content-Type`,如 `application/x-www-form-urlencoded` 或 `multipart/form-data`),使用**加粗**语法 + +对象的字段及其含义使用**表格**进行整理,表头统一依次为 `参数名`、`类型`、`内容`、`必要性`、`备注`,使用 `object`、`number`、`string`、`boolean`、`number[]`、`string[]`、`file` 等这种类似 TypeScript 的类型系统,必要性为 `必要`、`非必要`、`必要 (可选)` 等,表格内每个字段为一行 + +e.g.: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | --------- | ----------- | ----------------- | +| aid | num | 稿件 avid | 必要 (可选) | avid 与 bvid 任选 | +| bvid | str | 稿件 bvid | 必要 (可选) | avid 与 bvid 任选 | + +**响应正文**应在**请求参数**的下方,接口响应的数据格式应标注,如 `JSON 回复`、`XML 回复`、`ProtoBuf 回复`,使用**加粗**语法 + +JSON Object 或 ProtoBuf Message 应以对象的**表格**形式书写,表头为 `根对象` 或 `xx 中的 yy 对象` 或 `xx.yy.zz 对象`,若对象位于数组中则为 `xx 数组中的对象` 或 `xx[] 中的对象` + +表头统一依次为 `字段`、`类型`、`内容`、`备注`,类型为 JSON / Protobuf 的标准类型,具体同请求参数一致 + +不明确定义的字段说明在内容的末尾添加问号,如 `播放数?`;定义尚未明确的字段使用 `(?)` 在内容中占位,并在备注中填写 `作用尚不明确` + +多个对象及数组,使用**遍历树**的顺序进行排列, 若数组中的每一项结构均相同也可以直接省略为像 `xxx 数组中的对象` 这样的格式 + +e.g.: + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ----------- | ------------ | +| bvid | str | 稿件 bvid | | +| aid | num | 稿件 avid | | +| videos | num | 稿件分P总数 | 默认为 1 | +| tid | num | 分区 tid | | +| no_cache | bool | (?) | 作用尚不明确 | + +Json Array 或 ProtoBuf Repeated 类型使用数组的**表格**形式书写,表头统一依次为 `项`、`类型`、`内容`、`备注`,无限长度数组表尾需要添加**省略号** + +数组每项内容若与实际数据有关联,`内容` 字段则可标为 `(n+1)P 视频内容` 这样的形式 + +e.g.: + +`data` 中的 `pages` 数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ------------- | +| 0 | obj | 1P 视频内容 | 无分 P 仅有此项 | +| n | obj | (n+1)P 视频内容 | | +| …… | obj | …… | …… | + +**示例**部分位于所有**响应正文**部分下方,需要**加粗**格式,分为请求命令示例与响应体示例两部分 + +请求命令示例为一段可测试该接口的 cURL 命令或某种编程语言的代码,使用**代码块**语法书写,命令应当尽可能简短、便于使人阅读, 代码缩进为 **2** 个 **空格 (U+0020)** + +示例命令中的认证信息应做**脱敏处理**,如 Cookie、Token、access_key 等,可替换为 `xxx` 占位 + +示例命令前后可以适当添加一些文字说明 + +响应体示例为一段格式化后的 JSON 或 ProtoBuf Message,使用**代码块**语法书写, 代码块语言填写清楚, 注意 `json` `jsonc` 区别. 并使用 `<details>` 标签进行折叠, 仍一律使用 **2** 个 **空格** 进行缩进 + +e.g.: + +````markdown +**示例:** + +获取视频 `av85440373` 的基本信息 + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/view' \ + --data-urlencode 'aid=85440373' +``` + +<details> +<summary>查看响应示例:</summary> + +```jsonc +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "bvid": "BV117411r7R1", + "aid": 85440373, + "videos": 1, + "tid": 28, + "tname": "原创音乐", + "copyright": 1, + // ... + } +} +``` + +</details> +```` + +### 枚举值与属性位 + +接口返回或请求中若存在一些 enum 类型或二进制属性位,应当单独进行探讨,如视频的属性位 `attribute` 或视频清晰度 `qn` + +这些值及其说明使用**表格**进行整理,表头统一为 `位` / `代码` / `值`、`含义`、`备注` + +这些枚举值或属性位的用法应附加文字说明 + +e.g.: + +| 值 | 含义 | 备注 | +| ---- | ------------- | ------------------------------------------------------------ | +| 6 | 240P 极速 | 仅 MP4 格式支持<br />仅 `platform=html5` 时有效 | +| 16 | 360P 流畅 | | +| 32 | 480P 清晰 | | +| 64 | 720P 高清 | WEB 端默认值<br />B 站前端需要登录才能选择,但是直接发送请求可以不登录就拿到 720P 的取流地址<br />**无 720P 时则为 720P60** | +| 74 | 720P60 高帧率 | 需要登录认证 | +| 80 | 1080P 高清 | TV 端与 APP 端默认值<br />需要登录认证 | + +## Proto 定义格式 + +proto 文件为 [Protocol Buffers](https://protobuf.dev/) 以及 [gRPC](https://grpc.io/docs/) 的数据结构体定义,多用于客户端的接口,本文档也做相关的收集 + +存放于项目的 `/grpc_api` 路径下,使用包名进行路径层级的组织,如: + +``` +/grpc_api/bilibili/main/community/reply/v1/reply.proto +/grpc_api/bilibili/app/archive/v1/archive.proto +/grpc_api/bilibili/app/view/v1/view.proto +``` + +proto 文件内使用**单行注释**标注字段或对象的含义,如: + +```protobuf +// UP主信息 +message Author { + // UP主mid + int64 mid = 1; + // UP主昵称 + string name = 2; + // UP主头像url + string face = 3; +} +``` + +## 文档提交 + +### 拉取 (Pull) 与 提交 (Commit) + +本项目仓库仅托管于 GitHub, 使用 Git 作为版本控制系统, 你需要对两者有基础的了解 + +请先 fork, 然后在自己的 fork 上进行修改<!--废话--> + +提交的标题不要使用默认的 `Update xxx`, 请遵循 [Conventional Commits (约定式提交) 规范](https://www.conventionalcommits.org/zh-hans/v1.0.0/), 标题语言可根据个人习惯 + +<!--下面这两段属于常识, 但好像还有人不知道--> +当发现远程与本地仓库不一致时, 若你操作的 fork 的 branch 无打开的 PR, 建议使用变基拉取, 而不是生成一个额外的合并提交的合并拉取, 反之则相反 + +移动文件请使用 `git mv`, 而不是删除并添加同一个文件于不同位置 (该问题在 VSCode 的 GUI 版 Git 中存在<!--某个易姓owner干过-->), 以便后续 blame 操作 + +### 拉取请求 (Pull Request) + +使用 拉取请求 (Pull Request, PR) 将修改后的文档提交到 `master` 分支,标题需写明修改或新增的内容, 同样也需要遵循约定式提交规范, `gh_pages` 分支将在 PR 合并后自动更新 + +如果你还没有完成计划的全部修改, 请创建 Draft Pull Request 表示你还没有做好被合并的准备 ~~(抢占先机, 精神可嘉, 值得鼓励)~~ + +PR 正文使用 **无序列表** 写明更改的每一项内容, 可以使用复选框表明进度, 需要关闭的 Issue 请使用 `close #xxxx` 这样的格式一并包含在内 + +如果内容包含代码等, 请一并提供测试的输入与输出的文本或截图, 最好可以附上完整的测试环境及相关可执行文件等 + +<!--这也是常识喵--> +PR 合并后, 请及时删除或更新分支. 特别是在使用压缩合并或变基合并后, 请 `Discard changes` 或直接删除分支, 以免在下一次 PR 后出现重复相同提交的问题 diff --git a/bb-api-collect/LICENSE b/bb-api-collect/LICENSE new file mode 100644 index 0000000000..973f6ce469 --- /dev/null +++ b/bb-api-collect/LICENSE @@ -0,0 +1,352 @@ +Creative Commons Attribution-NonCommercial 4.0 International + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright and +certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + +- Considerations for licensors: Our public licenses are intended for + use by those authorized to give the public permission to use + material in ways otherwise restricted by copyright and certain other + rights. Our licenses are irrevocable. Licensors should read and + understand the terms and conditions of the license they choose + before applying it. Licensors should also secure all rights + necessary before applying our licenses so that the public can reuse + the material as expected. Licensors should clearly mark any material + not subject to the license. This includes other CC-licensed + material, or material used under an exception or limitation to + copyright. More considerations for licensors : + wiki.creativecommons.org/Considerations_for_licensors + +- Considerations for the public: By using one of our public licenses, + a licensor grants the public permission to use the licensed material + under specified terms and conditions. If the licensor's permission + is not necessary for any reason–for example, because of any + applicable exception or limitation to copyright–then that use is not + regulated by the license. Our licenses grant only permissions under + copyright and certain other rights that a licensor has authority to + grant. Use of the licensed material may still be restricted for + other reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, such + as asking that all changes be marked or described. Although not + required by our licenses, you are encouraged to respect those + requests where reasonable. More considerations for the public : + wiki.creativecommons.org/Considerations_for_licensees + +Creative Commons Attribution-NonCommercial 4.0 International Public +License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-NonCommercial 4.0 International Public License ("Public +License"). To the extent this Public License may be interpreted as a +contract, You are granted the Licensed Rights in consideration of Your +acceptance of these terms and conditions, and the Licensor grants You +such rights in consideration of benefits the Licensor receives from +making the Licensed Material available under these terms and conditions. + +- Section 1 – Definitions. + + - a. Adapted Material means material subject to Copyright and + Similar Rights that is derived from or based upon the Licensed + Material and in which the Licensed Material is translated, + altered, arranged, transformed, or otherwise modified in a + manner requiring permission under the Copyright and Similar + Rights held by the Licensor. For purposes of this Public + License, where the Licensed Material is a musical work, + performance, or sound recording, Adapted Material is always + produced where the Licensed Material is synched in timed + relation with a moving image. + - b. Adapter's License means the license You apply to Your + Copyright and Similar Rights in Your contributions to Adapted + Material in accordance with the terms and conditions of this + Public License. + - c. Copyright and Similar Rights means copyright and/or similar + rights closely related to copyright including, without + limitation, performance, broadcast, sound recording, and Sui + Generis Database Rights, without regard to how the rights are + labeled or categorized. For purposes of this Public License, the + rights specified in Section 2(b)(1)-(2) are not Copyright and + Similar Rights. + - d. Effective Technological Measures means those measures that, + in the absence of proper authority, may not be circumvented + under laws fulfilling obligations under Article 11 of the WIPO + Copyright Treaty adopted on December 20, 1996, and/or similar + international agreements. + - e. Exceptions and Limitations means fair use, fair dealing, + and/or any other exception or limitation to Copyright and + Similar Rights that applies to Your use of the Licensed + Material. + - f. Licensed Material means the artistic or literary work, + database, or other material to which the Licensor applied this + Public License. + - g. Licensed Rights means the rights granted to You subject to + the terms and conditions of this Public License, which are + limited to all Copyright and Similar Rights that apply to Your + use of the Licensed Material and that the Licensor has authority + to license. + - h. Licensor means the individual(s) or entity(ies) granting + rights under this Public License. + - i. NonCommercial means not primarily intended for or directed + towards commercial advantage or monetary compensation. For + purposes of this Public License, the exchange of the Licensed + Material for other material subject to Copyright and Similar + Rights by digital file-sharing or similar means is NonCommercial + provided there is no payment of monetary compensation in + connection with the exchange. + - j. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, + distribution, dissemination, communication, or importation, and + to make material available to the public including in ways that + members of the public may access the material from a place and + at a time individually chosen by them. + - k. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and + of the Council of 11 March 1996 on the legal protection of + databases, as amended and/or succeeded, as well as other + essentially equivalent rights anywhere in the world. + - l. You means the individual or entity exercising the Licensed + Rights under this Public License. Your has a corresponding + meaning. + +- Section 2 – Scope. + + - a. License grant. + - 1. Subject to the terms and conditions of this Public + License, the Licensor hereby grants You a worldwide, + royalty-free, non-sublicensable, non-exclusive, irrevocable + license to exercise the Licensed Rights in the Licensed + Material to: + - A. reproduce and Share the Licensed Material, in whole + or in part, for NonCommercial purposes only; and + - B. produce, reproduce, and Share Adapted Material for + NonCommercial purposes only. + - 2. Exceptions and Limitations. For the avoidance of doubt, + where Exceptions and Limitations apply to Your use, this + Public License does not apply, and You do not need to comply + with its terms and conditions. + - 3. Term. The term of this Public License is specified in + Section 6(a). + - 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter + created, and to make technical modifications necessary to do + so. The Licensor waives and/or agrees not to assert any + right or authority to forbid You from making technical + modifications necessary to exercise the Licensed Rights, + including technical modifications necessary to circumvent + Effective Technological Measures. For purposes of this + Public License, simply making modifications authorized by + this Section 2(a)(4) never produces Adapted Material. + - 5. Downstream recipients. + - A. Offer from the Licensor – Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + - B. No downstream restrictions. You may not offer or + impose any additional or different terms or conditions + on, or apply any Effective Technological Measures to, + the Licensed Material if doing so restricts exercise of + the Licensed Rights by any recipient of the Licensed + Material. + - 6. No endorsement. Nothing in this Public License + constitutes or may be construed as permission to assert or + imply that You are, or that Your use of the Licensed + Material is, connected with, or sponsored, endorsed, or + granted official status by, the Licensor or others + designated to receive attribution as provided in Section + 3(a)(1)(A)(i). + - b. Other rights. + - 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, + to the extent possible, the Licensor waives and/or agrees + not to assert any such rights held by the Licensor to the + limited extent necessary to allow You to exercise the + Licensed Rights, but not otherwise. + - 2. Patent and trademark rights are not licensed under this + Public License. + - 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties, including when + the Licensed Material is used other than for NonCommercial + purposes. + +- Section 3 – License Conditions. + + Your exercise of the Licensed Rights is expressly made subject to + the following conditions. + + - a. Attribution. + - 1. If You Share the Licensed Material (including in modified + form), You must: + - A. retain the following if it is supplied by the + Licensor with the Licensed Material: + - i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if designated); + - ii. a copyright notice; + - iii. a notice that refers to this Public License; + - iv. a notice that refers to the disclaimer of + warranties; + - v. a URI or hyperlink to the Licensed Material to + the extent reasonably practicable; + - B. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + - C. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + - 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may + be reasonable to satisfy the conditions by providing a URI + or hyperlink to a resource that includes the required + information. + - 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + - 4. If You Share Adapted Material You produce, the Adapter's + License You apply must not prevent recipients of the Adapted + Material from complying with this Public License. + +- Section 4 – Sui Generis Database Rights. + + Where the Licensed Rights include Sui Generis Database Rights that + apply to Your use of the Licensed Material: + + - a. for the avoidance of doubt, Section 2(a)(1) grants You the + right to extract, reuse, reproduce, and Share all or a + substantial portion of the contents of the database for + NonCommercial purposes only; + - b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; + and + - c. You must comply with the conditions in Section 3(a) if You + Share all or a substantial portion of the contents of the + database. + + For the avoidance of doubt, this Section 4 supplements and does not + replace Your obligations under this Public License where the + Licensed Rights include other Copyright and Similar Rights. + +- Section 5 – Disclaimer of Warranties and Limitation of Liability. + + - a. Unless otherwise separately undertaken by the Licensor, to + the extent possible, the Licensor offers the Licensed Material + as-is and as-available, and makes no representations or + warranties of any kind concerning the Licensed Material, whether + express, implied, statutory, or other. This includes, without + limitation, warranties of title, merchantability, fitness for a + particular purpose, non-infringement, absence of latent or other + defects, accuracy, or the presence or absence of errors, whether + or not known or discoverable. Where disclaimers of warranties + are not allowed in full or in part, this disclaimer may not + apply to You. + - b. To the extent possible, in no event will the Licensor be + liable to You on any legal theory (including, without + limitation, negligence) or otherwise for any direct, special, + indirect, incidental, consequential, punitive, exemplary, or + other losses, costs, expenses, or damages arising out of this + Public License or use of the Licensed Material, even if the + Licensor has been advised of the possibility of such losses, + costs, expenses, or damages. Where a limitation of liability is + not allowed in full or in part, this limitation may not apply to + You. + - c. The disclaimer of warranties and limitation of liability + provided above shall be interpreted in a manner that, to the + extent possible, most closely approximates an absolute + disclaimer and waiver of all liability. + +- Section 6 – Term and Termination. + + - a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply + with this Public License, then Your rights under this Public + License terminate automatically. + - b. Where Your right to use the Licensed Material has terminated + under Section 6(a), it reinstates: + + - 1. automatically as of the date the violation is cured, + provided it is cured within 30 days of Your discovery of the + violation; or + - 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect + any right the Licensor may have to seek remedies for Your + violations of this Public License. + + - c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing + so will not terminate this Public License. + - d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + +- Section 7 – Other Terms and Conditions. + + - a. The Licensor shall not be bound by any additional or + different terms or conditions communicated by You unless + expressly agreed. + - b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + +- Section 8 – Interpretation. + + - a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could + lawfully be made without permission under this Public License. + - b. To the extent possible, if any provision of this Public + License is deemed unenforceable, it shall be automatically + reformed to the minimum extent necessary to make it enforceable. + If the provision cannot be reformed, it shall be severed from + this Public License without affecting the enforceability of the + remaining terms and conditions. + - c. No term or condition of this Public License will be waived + and no failure to comply consented to unless expressly agreed to + by the Licensor. + - d. Nothing in this Public License constitutes or may be + interpreted as a limitation upon, or waiver of, any privileges + and immunities that apply to the Licensor or You, including from + the legal processes of any jurisdiction or authority. + +Creative Commons is not a party to its public licenses. Notwithstanding, +Creative Commons may elect to apply one of its public licenses to +material it publishes and in those instances will be considered the +"Licensor." The text of the Creative Commons public licenses is +dedicated to the public domain under the CC0 Public Domain Dedication. +Except for the limited purpose of indicating that material is shared +under a Creative Commons public license or as otherwise permitted by the +Creative Commons policies published at creativecommons.org/policies, +Creative Commons does not authorize the use of the trademark "Creative +Commons" or any other trademark or logo of Creative Commons without its +prior written consent including, without limitation, in connection with +any unauthorized modifications to any of its public licenses or any +other arrangements, understandings, or agreements concerning use of +licensed material. For the avoidance of doubt, this paragraph does not +form part of the public licenses. + +Creative Commons may be contacted at creativecommons.org. \ No newline at end of file diff --git a/bb-api-collect/README.md b/bb-api-collect/README.md new file mode 100644 index 0000000000..26886b71c6 --- /dev/null +++ b/bb-api-collect/README.md @@ -0,0 +1,414 @@ +> 上游仓库[SocialSisterYi/bilibili-API-collect](https://github.com/SocialSisterYi/bilibili-API-collect)由于某些原因已存档,本仓库也将同样归档并转为私有记录。 +> +> 主归档分支为: `master` 在2026年01月24~25日之间从上游同步未进行修改。 +> +> 附归档分支为: `main` 额外存档部分图片资源。 + +<p align="center"> + <img src="./assets/img/logo.png" width="250" height="200" /> +</p> +<h1 align="center">哔哩哔哩 - API 收集整理</h1> +<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?style=flat&color=red" alt="GitHub issues"/> + </a> + <a href="https://github.com/SocialSisterYi/bilibili-API-collect/stargazers" style="text-decoration: none;"> + <img src="https://img.shields.io/github/stars/SocialSisterYi/bilibili-API-collect.svg?style=flat&color=yellow" alt="GitHub stars"/> + </a> + <a href="https://github.com/SocialSisterYi/bilibili-API-collect/network" style="text-decoration: none;"> + <img src="https://img.shields.io/github/forks/SocialSisterYi/bilibili-API-collect.svg?style=flat&color=blue" alt="GitHub forks"/> + </a> + <a href="https://github.com/SocialSisterYi/bilibili-API-collect/actions" style="text-decoration: none;"> + <img src="https://img.shields.io/github/actions/workflow/status/SocialSisterYi/bilibili-API-collect/vuepress-deploy.yml?style=flat" alt="Build status"/> + </a> + <a href="https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/LICENSE" style="text-decoration: none;"> + <img src="https://img.shields.io/badge/License-CC%20BY--NC%204.0-lightgrey.svg?style=flat" alt="GitHub license"/> + </a> +</p> +<p align="center" class="trendshift"> + <a href="https://trendshift.io/repositories/3218" target="_blank"> + <img src="./assets/img/trendshift_6RepoOfTheDay.svg" alt="Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/> + </a> +</p> +<h3 align="center">野生 API 文档</h3> +<h3 align="center">不断更新中....</h3> + +本项目旨在对 B 站 WEB、APP、TV 等客户端中,散落在世界各地的野生 API 进行收集整理,研究使用方法并对其进行说明,运用了黑箱法、控制变量法、代码逆向分析、拆包及反编译法、网络抓包法等研究办法 + +本文档探讨的对象是主站业务接口,[官方开放平台](https://openhome.bilibili.com/doc) 和 [直播开放平台](https://open-live.bilibili.com/document/) 均不属于本项目范畴,请移步 + +B站 API 采用 C/S 结构,大多数接口为 REST API 和 gRPC,少部分接口为 WebSocket;REST API 接口请求数据大多为 url query 表单或 JSON,返回数据大多为 JSON 或 Protobuf,强制使用 https 协议 + +📖阅读地址:[Github Pages](https://socialsisteryi.github.io/bilibili-API-collect/) + +小小的 Demo:~~av583785685~~ [视频失效原因](https://shakaianee.top/archives/56/) ([Youtube 备链](https://www.youtube.com/watch?v=nfF91Z6fqGk)) + +::: warning 声明 + +1. 本项目遵守 CC-BY-NC 4.0 协议,禁止一切商业使用,如需转载请注明作者 ID +2. **请勿滥用,本项目仅用于学习和测试!请勿滥用,本项目仅用于学习和测试!请勿滥用,本项目仅用于学习和测试!** +3. 利用本项目提供的接口、文档等造成不良影响及后果与本人无关 +4. 由于本项目的特殊性,可能随时停止开发或删档 +5. 本项目为开源项目,不接受任何形式的催单和索取行为,更不容许存在付费内容 +6. **上传任何信息时请注意脱敏,删去账户密码、敏感 cookies 等可能泄漏个人信息的数据(例如 `SESSDATA`、`bili_jct` 之类的 cookies)** + +::: + +## 🌱参与贡献 + +欢迎各位 dalao 对本项目做出贡献,也希望每个使用者都能提出宝贵的意见 + +目前本项目存在的问题包括但不限于: + +1. 文档二级目录尚未完成 +2. 部分文档较旧,修改与更新没有跟进 +3. 目前文档使用 Markdown 语法编写,不易生成编程语言的 SDK,详见 [#604](https://github.com/SocialSisterYi/bilibili-API-collect/issues/604) + +更多信息请浏览 [贡献指南](CONTRIBUTING.md) + +## 🍴目录 + +计划整理分类 & 目录:(文档已完结请选中 checkbox) + +- [ ] [接口签名与验证](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`) + - [ ] [bili_ticket](docs/misc/sign/bili_ticket.md) + - [ ] [v_voucher 验证](docs/misc/sign/v_voucher.md) +- [ ] [杂项](docs/misc) + - [x] [获取当前时间戳](docs/misc/time_stamp.md) + - [x] [公共错误码](docs/misc/errcode.md) + - [x] [图片格式化](docs/misc/picture.md) + - [x] [表达式渲染](docs/misc/mathjax.md) + - [x] [bvid 说明](docs/misc/bvid_desc.md) + - [ ] [设备唯一标识 BUVID](docs/misc/device_identity.md) + - [ ] [获取 buvid3 / buvid4 / b_nut](docs/misc/buvid3_4.md) + - [ ] [b23.tv 短链](docs/misc/b23tv.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] [Web 端 Cookie 刷新](docs/login/cookie_refresh.md) +- [ ] [消息中心](docs/message) + - [ ] [通知类消息](docs/message/msg.md) + - [x] [私信](docs/message/private_msg.md) + - [x] [私信消息类型、内容说明](docs/message/private_msg_content.md) + - [x] [设置](docs/message/settings.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/official_role.md) + - [ ] [加入老粉计划](docs/user/contract.md) + - [x] [所有粉丝勋章](docs/user/medals.md) + - [ ] [批量查询](docs/user/batch.md) +- [ ] [大会员](docs/vip) + - [ ] [大会员基本信息](docs/vip/info.md) + - [ ] [大会员中心](docs/vip/center.md) + - [ ] [大会员签到](docs/vip/clockin.md) + - [ ] [大会员操作](docs/vip/action.md) +- [ ] [视频](docs/video) + - [x] [视频分区一览 (分区代码)](docs/video/video_zone.md) + - [ ] [视频分区一览 (分区代码) (v2)](docs/video/video_zone_v2.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/collection.md) + - [ ] [播放器](docs/video/player.md) +- [ ] [剧集 (番剧、影视)](docs/bangumi) + - [ ] [基本信息](docs/bangumi/info.md) + - [ ] [播放 & 下载地址(视频流)](docs/bangumi/videostream_url.md) + - [ ] [时间轴](docs/bangumi/timeline.md) + - [ ] [索引](docs/bangumi/season_index.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) + - [ ] 高级弹幕 + - [ ] 屏蔽管理 + - [ ] [智能防挡弹幕](docs/danmaku/webmask.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) +- [ ] [图文](docs/opus) + - [x] [图文详细](docs/opus/detail.md) + - [x] [空间图文](docs/opus/space.md) + - [ ] [功能模块](docs/opus/features.md) + - [ ] [富文本节点](docs/opus/rich_text_nodes.md) +- [ ] [专栏](docs/article) + - [ ] [专栏内容](docs/article/view.md) + - [ ] [专栏分类](docs/article/category.md) + - [x] [卡片信息](docs/article/card.md) + - [X] [基本信息](docs/article/info.md) + - [X] [点赞 & 投币 & 收藏 & 分享](docs/article/action.md) + - [X] [文集基本信息](docs/article/articles.md) +- [ ] [动态](docs/dynamic) + - [ ] [获取动态列表](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) + - [ ] [话题](docs/dynamic/topic.md) + - [ ] [动态内容](docs/dynamic/get_dynamic_detail.md) + - [ ] [导航栏动态](docs/dynamic/nav.md) + - [x] [首页公告栏](docs/dynamic/banner.md) +- [ ] [创作中心](docs/creativecenter) + - [ ] [投稿](docs/creativecenter/upload.md) + - [ ] [统计与数据](docs/creativecenter/statistics&data.md) + - [ ] 列表查询相关 + - [x] [电磁力数据](docs/creativecenter/railgun.md) + - [ ] [合集管理](docs/creativecenter/season.md) + - [ ] [视频相关杂项](docs/creativecenter/videos.md) + - [ ] [图文操作](docs/creativecenter/opus.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/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/search) + - [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/comment) + - [x] [评论区明细](docs/comment/list.md) + - [x] [操作](docs/comment/action.md) +- [ ] [表情](docs/emoji) + - [x] [表情及表情包信息](docs/emoji/list.md) + - [x] [操作](docs/emoji/action.md) +- [x] [实时广播(通讯协议)](docs/broadcast) + - [x] [视频内广播](docs/broadcast/video_room.md) +- [ ] [充电](docs/electric) + - [ ] [包月充电](docs/electric/monthly.md) + - [ ] 自定义充电 + - [x] [B 币方式充电](docs/electric/Bcoin.md) + - [x] [微信 & 支付宝方式充电](docs/electric/WeChat&Alipay.md) + - [x] [充电留言](docs/electric/charge_msg.md) + - [x] [充电列表](docs/electric/charge_list.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)~~ + - [ ] ~~投稿~~ +- [ ] [历史记录 & 稍后再看](docs/historytoview) + - [x] [历史记录](docs/historytoview/history.md) + - [x] [稍后再看](docs/historytoview/toview.md) +- [ ] [收藏夹](docs/fav) + - [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) +- [ ] [直播](docs/live) + - [ ] [直播间基本信息](docs/live/info.md) + - [ ] [直播推荐](docs/live/recommend.md) + - [ ] [直播分区](docs/live/live_area.md) + - [ ] [直播间管理](docs/live/manage.md) + - [ ] 直播间操作 + - [ ] [直播视频流](docs/live/live_stream.md) + - [ ] [直播信息流](docs/live/message_stream.md) + - [ ] [直播红包](docs/live/redpocket.md) + - [ ] [直播间表情包](docs/live/emoticons.md) + - [ ] [直播间用户实用 API](docs/live/user.md) + - [x] [直播间禁言相关](docs/live/silent_user_manage.md) + - [ ] [关注UP直播情况](docs/live/follow_up_live.md) + - [ ] [直播心跳上报](docs/live/report.md) + - [ ] [直播间弹幕](docs/live/danmaku.md) + - [ ] [直播流水](docs/live/live_bill.md) + - [ ] [礼物相关](docs/live/gift.md) + - [ ] [大航海/粉丝团](docs/live/guard.md) + - [ ] [直播回放](docs/live/live_replay.md) + - [ ] [直播数据](docs/live/live_data.md) + - [ ] [直播投票](docs/live/live_vote.md) +- [ ] [活动](docs/activity) + - [ ] [活动列表](docs/activity/list.md) + - [ ] [活动主题信息](docs/activity/info.md) +- [ ] [转正答题](docs/newbie_exam) + - [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 币钱包](docs/wallet/) + - [ ] [基本信息](docs/wallet/info.md) + - [ ] B 币充值 + - [ ] 贝壳相关 +- [ ] [哔哩哔哩漫画](docs/manga) + - [ ] 用户信息 + - [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) +- [ ] [客服中心](docs/customerservice) + - [ ] [客服消息](docs/customerservice/msg.md) +- [ ] [web 端组件](docs/web_widget) + - [x] [分区当日投稿数](docs/web_widget/zone_upload.md) + - [x] [404 页漫画收集](docs/web_widget/404_manga.md) + - [ ] [首页横幅头图](docs/web_widget/header.md) + - [ ] [分区横幅轮播图](docs/web_widget/banner.md) +- [ ] [APP 端组件](docs/APP_widget) + - [x] [开屏图片 + 恰饭珍贵录像](docs/APP_widget/splash.md) + - [ ] [获取最新 APP 版本](docs/APP_widget/ver.md) +- [ ] [个性装扮](docs/garb) + - [x] [APP 主题](docs/garb/skin.md) + - [x] [主题色](docs/garb/color.md) + - [ ] [装扮/收藏集](docs/garb/lottery.md) + +## ✨鸣谢 + +你们的存在,让社区更美好 + +[![contributors](./assets/img/contributors.svg)](https://github.com/SocialSisterYi/bilibili-API-collect/graphs/contributors) + +## 📖相关协议基础 + +HTTP 协议:[传送门](https://www.cnblogs.com/an-wen/p/11180076.html) + +JSON 序列格式:[传送门](https://www.sojson.com/json/json_index.html) + +XML 序列格式:[传送门](https://www.w3school.com.cn/xml/xml_intro.asp) + +ProtoBuf 序列格式:[传送门](https://www.jianshu.com/p/a24c88c0526a) + +## 💦交流 + +<img src="./assets/img/45892418_SocialSisterYi.jpg" width="100" height="100" /> + +⚠注意:开源社群欢迎交流探讨,**拒绝**咨询、**不支持**合作,**黑产号**一经发现立即拉黑并举报相关 SRC + +- QQ 交流群:[邀请链接](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=ympvb3LAPT-Ulu3ezhGqbkJ8zXMKImOX&authKey=z1KdkOdKO3wytN43m9K6On9nBtnDL4pAoD6VQHCipFBb9TasNDKuDHCmOE6TF3uc&noverify=0&group_code=191187164) +- Telegram 交流群:[@bilibili_API_collect_community](https://t.me/bilibili_API_collect_community) + +## 🧋发电 + +欢迎来~~交♂易~~,大家的支持就是我继续开发的动力! + +~~请可爱的易姐喝杯奶茶~~ + +WeChat & Alipay: + +<img src="./assets/img/sponsorQR.jpg" width="300" height="300" /> + +OR Aifadian:[https://afdian.com/@ShakaiAneE](https://afdian.com/@ShakaiAneE) + +## 🔗相关项目推荐 + +### 库及文档 + +- [jingyuexing/bilibiliAPI](https://github.com/jingyuexing/bilibiliAPI) +- [fython/BilibiliAPIDocs](https://github.com/fython/BilibiliAPIDocs) +- [czp3009/bilibili-api](https://github.com/czp3009/bilibili-api) +- [Vespa314/bilibili-api](https://github.com/Vespa314/bilibili-api) +- [Pengfei00/bili-utils](https://github.com/Pengfei00/bili-utils): bilibili 工具箱 +- [lovelyyoshino/Bilibili-Live-API](https://github.com/lovelyyoshino/Bilibili-Live-API): Bilibili 直播/番剧 API 文档 +- [flaribbit/bilibili-manga-spider](https://github.com/flaribbit/bilibili-manga-spider): Bilibili 漫画爬虫 +- [simon300000/bili-api](https://github.com/simon300000/bili-api): Bilibili Node.js API +- [iyear/biligo](https://github.com/iyear/biligo): Bilibili API SDK in Golang +- [bilibili-openplatform/demo](https://github.com/bilibili-openplatform/demo): 哔哩哔哩开放平台示例代码库 +- [ddiu8081/blive-message-listener](https://github.com/ddiu8081/blive-message-listener): Bilibili-live danmu listener with type. Bilibili 直播间弹幕监听库,支持类型输出。 +- [Nemo2011/bilibili-api](https://github.com/Nemo2011/bilibili-api): 哔哩哔哩常用API调用。支持视频、番剧、用户、频道、音频等功能。工具齐全。 +- [CuteReimu/bilibili](https://github.com/CuteReimu/bilibili): 哔哩哔哩API的Go版本SDK + +### 成品 + +- [NullPointerException/AnimePipe](https://codeberg.org/NullPointerException/AnimePipe): 功能完善的Android流媒体综合客户端,支持Bilibili, Youtube, NicoNico +- [3Shain/Comen](https://github.com/3Shain/Comen): 基于h5的B站直播弹幕姬 +- [AncientLysine/BiliLocal](https://github.com/AncientLysine/BiliLocal): 本地弹幕播放器 +- [zyzsdy/biliroku](https://github.com/zyzsdy/biliroku): bilibili 生放送(直播)录制 +- [otakustay/danmaku-to-ass](https://github.com/otakustay/danmaku-to-ass): A站B站弹幕转字幕文件 +- [bilibili-helper/bilibili-helper-o](https://github.com/bilibili-helper/bilibili-helper-o): 哔哩哔哩 (bilibili.com) 辅助工具,可以下载视频,查询弹幕发送人以及一些十分实用的直播区功能。 +- [apachecn/CDNDrive](https://github.com/apachecn/CDNDrive): 基于B站相簿上传的文件分块索引存储器 +- [Hsury/BiliDrive](https://github.com/Hsury/BiliDrive): 基于B站相簿上传的文件分块索引存储器 +- [Tsuk1ko/bilibili-live-chat](https://github.com/Tsuk1ko/bilibili-live-chat): 无后端的仿 YouTube Live Chat 风格的简易 Bilibili 弹幕姬 +- [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数据中心 +- [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): 全自动录播、投稿工具,支持录制直播弹幕,也支持Youtube、twitch直播回放列表自动搬运到B站 +- [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粉丝与视频实时数据统计 +- [kingwingfly/fav](https://github.com/kingwingfly/fav): 自动同步bili收藏夹、合集视频到本地的CLI工具(Rust实现,并提供一个文档测试完善的Rust风格的用于构建有状态爬虫的核心库) +- [linyuye/Bilibili_crawler](https://github.com/linyuye/Bilibili_crawler): 基于bilibili懒加载api爬取b站动态,视频等评论区 +- [ouzexi/bilibili-hot-tags](https://github.com/ouzexi/bilibili-hot-tags): 一个B站热门视频标签检索统计小工具 +- [SpenserCai/rust-video-downloader](https://github.com/SpenserCai/rust-video-downloader): Rust实现的高性能跨平台视频下载器(目前支持Bilibili),基本覆盖了BBDown的所有功能。 + +### 其他 + +- [kuresaru/geetest-validator](https://github.com/kuresaru/geetest-validator): GeeTest 调试器 +- [bloomrpc/bloomrpc](https://github.com/bloomrpc/bloomrpc): GUI Client for GRPC Services +- [grpc/grpc](https://github.com/grpc/grpc): The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#) +- [glideapps/quicktype](https://github.com/glideapps/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反序列化所需类,以便于快速反序列化,有网页版 +- [SessionHu/json-apidoc-gen](https://github.com/SessionHu/json-apidoc-gen): Simple CLI tool for generating BAC document template diff --git a/bb-api-collect/assets/img/2233login.png b/bb-api-collect/assets/img/2233login.png new file mode 100644 index 0000000000..3d9ff56226 Binary files /dev/null and b/bb-api-collect/assets/img/2233login.png differ diff --git a/bb-api-collect/assets/img/45892418_SocialSisterYi.jpg b/bb-api-collect/assets/img/45892418_SocialSisterYi.jpg new file mode 100644 index 0000000000..1b3a9a2fd5 Binary files /dev/null and b/bb-api-collect/assets/img/45892418_SocialSisterYi.jpg differ diff --git a/bb-api-collect/assets/img/activit.svg b/bb-api-collect/assets/img/activit.svg new file mode 100644 index 0000000000..b210f77f14 --- /dev/null +++ b/bb-api-collect/assets/img/activit.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> +<path d="M518.656 475.904a223.488 223.488 0 0 1-23.296-75.52 366.08 366.08 0 0 1 81.408 14.592 623.104 623.104 0 0 1-58.112 60.928m-69.888-119.04c-11.52-58.112-8.704-55.296-25.6-156.928a265.984 265.984 0 0 0-78.336 46.592c51.2 104.448 60.928 165.376 92.928 290.304 51.2-5.632 211.968-40.704 226.56-130.56 8.704-64-142.336-64-215.04-49.408M486.4 624.128a263.424 263.424 0 0 0-107.52 69.632l43.52 153.6a47.872 47.872 0 0 1-92.928 23.296L216.576 473.088l-72.704-204.8c2.816-5.632 5.888-8.704 8.704-14.336l-14.592-51.2a46.08 46.08 0 0 1 32-57.856A47.616 47.616 0 0 1 228.096 179.2v2.816a334.848 334.848 0 0 1 98.816-43.52c177.152-46.592 203.264 55.04 429.824 23.296L890.368 588.8c-171.52 90.112-232.448-11.52-403.712 35.072" fill="#F39800"> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/img/add.svg b/bb-api-collect/assets/img/add.svg new file mode 100644 index 0000000000..ecdea954c7 --- /dev/null +++ b/bb-api-collect/assets/img/add.svg @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 24.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 838 838" enable-background="new 0 0 838 838" xml:space="preserve"> +<path fill="#1497C7" d="M419,838c-118.67-3.33-217.33-44.33-296-123S3.33,537.67,0,419c3.33-118.67,44.33-217.33,123-296 + S300.33,3.33,419,0c118.67,3.33,217.33,44.33,296,123s119.67,177.33,123,296c-3.33,118.67-44.33,217.33-123,296 + S537.67,834.67,419,838z M372,372H233v94h139v139h94V466h139v-94H466V233h-94V372z"/> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +</svg> diff --git a/bb-api-collect/assets/img/aiSummary.svg b/bb-api-collect/assets/img/aiSummary.svg new file mode 100644 index 0000000000..efa4420da5 --- /dev/null +++ b/bb-api-collect/assets/img/aiSummary.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="1024" height="1024" viewBox="0 0 1024 1024"><defs><clipPath id="master_svg0_1_5"><rect x="0" y="0" width="1024" height="1024" rx="0"/></clipPath><linearGradient x1="-0.03559274226427078" y1="0.14154286682605743" x2="0.3670809864997864" y2="1.0495315790176392" id="master_svg1_1_92"><stop offset="0%" stop-color="#393946" stop-opacity="1"/><stop offset="40.115898847579956%" stop-color="#23232E" stop-opacity="1"/><stop offset="100%" stop-color="#191924" stop-opacity="1"/></linearGradient><linearGradient x1="1.0356004238128662" y1="0.14154286682605743" x2="0.6329137682914734" y2="1.0495315790176392" id="master_svg2_1_93"><stop offset="0%" stop-color="#393946" stop-opacity="1"/><stop offset="40.115898847579956%" stop-color="#23232E" stop-opacity="1"/><stop offset="100%" stop-color="#191924" stop-opacity="1"/></linearGradient><filter id="master_svg3_1_05" filterUnits="objectBoundingBox" color-interpolation-filters="sRGB" x="-5" y="-5" width="831.2000732421875" height="728.800048828125"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="1" dx="1"/><feGaussianBlur stdDeviation="1.5"/><feColorMatrix type="matrix" values="0 0 0 0 0.03954499959945679 0 0 0 0 0.08450230211019516 0 0 0 0 0.20010699331760406 0 0 0 0.8500000238418579 0"/><feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/><feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/></filter><filter id="master_svg4_1_12" filterUnits="objectBoundingBox" color-interpolation-filters="sRGB" x="0" y="0" width="887.4667358398438" height="750.933349609375"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feColorMatrix in="SourceAlpha" type="matrix" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="3.714289903640747" dx="2.785710096359253"/><feGaussianBlur stdDeviation="1.3928600549697876"/><feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/><feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"/><feBlend mode="normal" in2="shape" result="effect1_innerShadow"/><feColorMatrix in="SourceAlpha" type="matrix" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="-1.8571399450302124" dx="-2"/><feGaussianBlur stdDeviation="1.8571399450302124"/><feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/><feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0.15444999933242798 0 0 0 0 0.45426398515701294 0 0 0 0.10999999940395355 0"/><feBlend mode="normal" in2="effect1_innerShadow" result="effect2_innerShadow"/></filter><linearGradient x1="0.21811191737651825" y1="0.21849091351032257" x2="0.6896499991416931" y2="1.0494545698165894" id="master_svg5_1_95"><stop offset="0%" stop-color="#F4FCFF" stop-opacity="1"/><stop offset="100%" stop-color="#EAF5F9" stop-opacity="1"/></linearGradient></defs><g clip-path="url(#master_svg0_1_5)"><g><g><path d="M257.357049609375,80.1351999267578C279.080249609375,62.032609926757814,311.364849609375,64.96772992675781,329.467549609375,86.69049992675781L414.802349609375,189.09079992675782C432.902349609375,210.8137999267578,429.967349609375,243.0987999267578,408.245349609375,261.2007999267578C386.522349609375,279.30379992675785,354.239349609375,276.3687999267578,336.135049609375,254.6457999267578L250.801749609375,152.2452999267578C232.699149609375,130.5224999267578,235.634279609375,98.2374999267578,257.357049609375,80.1351999267578Z" fill-rule="evenodd" fill="url(#master_svg1_1_92)" fill-opacity="1"/></g><g><path d="M749.5745874023437,80.1351999267578C727.8525874023437,62.032609926757814,695.5695874023438,64.96772992675781,677.4648874023437,86.69049992675781L592.1314874023437,189.09079992675782C574.0306074023438,210.8137999267578,576.9660174023437,243.0987999267578,598.6884874023438,261.2007999267578C620.4109874023437,279.30379992675785,652.6942874023438,276.3687999267578,670.7985874023437,254.6457999267578L756.1315874023437,152.2452999267578C774.2325874023437,130.5224999267578,771.3005874023438,98.2374999267578,749.5745874023437,80.1351999267578Z" fill-rule="evenodd" fill="url(#master_svg2_1_93)" fill-opacity="1"/></g><g style="opacity:0.20000000298023224;" filter="url(#master_svg3_1_05)"><g><path d="M921.6000244140625,623.0460183105469C921.6000244140625,854.0370183105468,738.2150244140626,921.6000183105468,512.0000244140625,921.6000183105468C285.7840244140625,921.6000183105468,102.4000244140625,854.0370183105468,102.4000244140625,623.0460183105469C102.4000244140625,392.05501831054687,133.9078244140625,204.80001831054688,512.0000244140625,204.80001831054688C905.8480244140625,204.80001831054688,921.6000244140625,392.05501831054687,921.6000244140625,623.0460183105469Z" fill="#D9D9D9" fill-opacity="1"/></g></g><g filter="url(#master_svg4_1_12)"><g><path d="M955.7336625976562,646.7890183105469C955.7336625976562,909.8580183105469,757.0666625976562,955.7330183105469,511.99966259765625,955.7330183105469C266.93266259765625,955.7330183105469,68.26666259765625,909.8580183105469,68.26666259765625,646.7890183105469C68.26666259765625,341.3330183105469,102.39996259765624,204.80001831054688,511.99966259765625,204.80001831054688C938.6666625976562,204.80001831054688,955.7336625976562,341.3330183105469,955.7336625976562,646.7890183105469Z" fill="url(#master_svg5_1_95)" fill-opacity="1"/></g></g><g><path d="M163.36666870117188,485.00368701171874C163.36666870117188,407.0843870117187,219.98396870117188,340.03798701171877,297.34866870117185,330.76228701171874C450.79566870117185,312.36440701171875,572.3406687011718,311.68546701171874,727.4906687011719,330.44178701171876C804.5126687011718,339.7532870117187,860.6616687011718,406.65778701171877,860.6616687011718,484.2426870117188L860.6616687011718,655.0866870117188C860.6616687011718,728.1596870117187,810.8406687011719,792.7736870117187,738.8226687011719,805.1506870117187C576.9556687011718,832.9626870117188,449.55266870117185,827.6006870117187,292.1596687011719,802.6006870117187C217.16826870117188,790.6886870117187,163.36666870117188,724.7296870117187,163.36666870117188,648.7996870117188L163.36666870117188,485.00368701171874Z" fill="#191924" fill-opacity="1"/></g><g><path d="M639.7466748046875,522.6667022705078L639.7466748046875,617.7519022705078Q639.7466748046875,618.5060022705078,639.7836748046875,619.2593022705078Q639.8206748046875,620.0125022705079,639.8945748046875,620.7630022705079Q639.9684748046875,621.5135022705078,640.0791748046875,622.2595022705078Q640.1898748046875,623.0057022705078,640.3369748046875,623.7447022705078Q640.4840748046875,624.4847022705078,640.6672748046875,625.2167022705078Q640.8505748046875,625.9477022705078,641.0694748046875,626.6697022705079Q641.2883748046875,627.3907022705079,641.5424748046875,628.1007022705078Q641.7964748046875,628.8117022705078,642.0850748046875,629.5077022705078Q642.3736748046875,630.2047022705078,642.6961748046875,630.8867022705078Q643.0185748046875,631.5677022705078,643.3740748046876,632.2337022705078Q643.7295748046874,632.8987022705078,644.1172748046876,633.5447022705079Q644.5049748046875,634.1917022705078,644.9239748046875,634.8187022705079Q645.3428748046875,635.4457022705078,645.7921748046875,636.0517022705078Q646.2413748046876,636.6577022705078,646.7197748046875,637.2407022705078Q647.1981748046875,637.8237022705079,647.7046748046876,638.3827022705078Q648.2110748046875,638.9407022705078,648.7443748046875,639.4747022705078Q649.2775748046874,640.0077022705078,649.8363748046875,640.5137022705078Q650.3951748046875,641.0207022705079,650.9780748046875,641.4987022705078Q651.5610748046875,641.9777022705078,652.1667748046875,642.4267022705078Q652.7724748046875,642.8757022705079,653.3995748046875,643.2947022705079Q654.0265748046875,643.7137022705078,654.6734748046875,644.1017022705078Q655.3202748046875,644.4887022705078,655.9853748046875,644.8447022705078Q656.6504748046875,645.1997022705078,657.3321748046875,645.5227022705078Q658.0138748046875,645.8447022705078,658.7106748046875,646.1337022705078Q659.4073748046875,646.4217022705078,660.1173748046875,646.6757022705078Q660.8274748046875,646.9307022705078,661.5491348046875,647.1487022705078Q662.2707948046875,647.3677022705078,663.0023248046875,647.5517022705078Q663.7338548046876,647.7347022705078,664.4735048046875,647.8817022705078Q665.2131448046875,648.0287022705078,665.9591148046875,648.1397022705078Q666.7050848046875,648.2497022705078,667.4555848046875,648.3237022705079Q668.2060948046875,648.3977022705078,668.9593148046876,648.4347022705078Q669.7125408046875,648.4717022705079,670.4666748046875,648.4717022705079Q671.2208088046875,648.4717022705079,671.9740348046874,648.4347022705078Q672.7272548046875,648.3977022705078,673.4777648046875,648.3237022705079Q674.2282648046875,648.2497022705078,674.9742348046875,648.1397022705078Q675.7202048046875,648.0287022705078,676.4598448046875,647.8817022705078Q677.1994948046874,647.7347022705078,677.9310248046875,647.5517022705078Q678.6625548046875,647.3677022705078,679.3842148046875,647.1487022705078Q680.1058748046875,646.9307022705078,680.8159748046875,646.6757022705078Q681.5259748046875,646.4217022705078,682.2226748046875,646.1337022705078Q682.9194748046875,645.8447022705078,683.6011748046875,645.5227022705078Q684.2828748046875,645.1997022705078,684.9479748046875,644.8447022705078Q685.6130748046875,644.4887022705078,686.2598748046875,644.1017022705078Q686.9067748046875,643.7137022705078,687.5337748046875,643.2947022705079Q688.1608748046875,642.8757022705079,688.7665748046875,642.4267022705078Q689.3722748046875,641.9777022705078,689.9552748046875,641.4987022705078Q690.5381748046875,641.0207022705079,691.0969748046875,640.5137022705078Q691.6557748046876,640.0077022705078,692.1889748046875,639.4747022705078Q692.7222748046875,638.9407022705078,693.2286748046874,638.3827022705078Q693.7351748046875,637.8237022705079,694.2135748046875,637.2407022705078Q694.6919748046874,636.6577022705078,695.1411748046875,636.0517022705078Q695.5904748046875,635.4457022705078,696.0093748046875,634.8187022705079Q696.4283748046875,634.1917022705078,696.8160748046874,633.5447022705079Q697.2037748046876,632.8987022705078,697.5592748046874,632.2337022705078Q697.9147748046875,631.5677022705078,698.2371748046875,630.8867022705078Q698.5596748046875,630.2047022705078,698.8482748046875,629.5077022705078Q699.1368748046875,628.8117022705078,699.3908748046875,628.1007022705078Q699.6449748046875,627.3907022705079,699.8638748046875,626.6697022705079Q700.0827748046875,625.9477022705078,700.2660748046875,625.2167022705078Q700.4492748046875,624.4847022705078,700.5963748046875,623.7447022705078Q700.7434748046875,623.0057022705078,700.8541748046875,622.2595022705078Q700.9648748046875,621.5135022705078,701.0387748046875,620.7630022705079Q701.1126748046875,620.0125022705079,701.1496748046875,619.2593022705078Q701.1866748046875,618.5060022705078,701.1866748046875,617.7519022705078L701.1866748046875,522.6667022705078Q701.1866748046875,521.9125682705078,701.1496748046875,521.1593422705079Q701.1126748046875,520.4061222705078,701.0387748046875,519.6556122705078Q700.9648748046875,518.9051122705079,700.8541748046875,518.1591422705078Q700.7434748046875,517.4131722705079,700.5963748046875,516.6735322705078Q700.4492748046875,515.9338822705079,700.2660748046875,515.2023522705078Q700.0827748046875,514.4708222705078,699.8638748046875,513.7491622705078Q699.6449748046875,513.0275022705079,699.3908748046875,512.3174022705078Q699.1368748046875,511.6074022705078,698.8482748046875,510.91070227050784Q698.5596748046875,510.2139022705078,698.2371748046875,509.5322022705078Q697.9147748046875,508.85050227050783,697.5592748046874,508.18540227050784Q697.2037748046876,507.52030227050784,696.8160748046874,506.8735022705078Q696.4283748046875,506.2266022705078,696.0093748046875,505.59960227050783Q695.5904748046875,504.9725022705078,695.1411748046875,504.36680227050783Q694.6919748046874,503.7611022705078,694.2135748046875,503.1781022705078Q693.7351748046875,502.5952022705078,693.2286748046874,502.03640227050784Q692.7222748046875,501.4776022705078,692.1889748046875,500.9444022705078Q691.6557748046876,500.4111022705078,691.0969748046875,499.9047022705078Q690.5381748046875,499.3982022705078,689.9552748046875,498.91980227050783Q689.3722748046875,498.4414022705078,688.7665748046875,497.9922022705078Q688.1608748046875,497.5429022705078,687.5337748046875,497.1240022705078Q686.9067748046875,496.7050022705078,686.2598748046875,496.3173022705078Q685.6130748046875,495.9296022705078,684.9479748046875,495.5741022705078Q684.2828748046875,495.2186022705078,683.6011748046875,494.89620227050784Q682.9194748046875,494.5737022705078,682.2226748046875,494.2851022705078Q681.5259748046875,493.9965022705078,680.8159748046875,493.7425022705078Q680.1058748046875,493.48840227050783,679.3842148046875,493.2695022705078Q678.6625548046875,493.0506022705078,677.9310248046875,492.8673022705078Q677.1994948046874,492.6841022705078,676.4598448046875,492.5370022705078Q675.7202048046875,492.38990227050783,674.9742348046875,492.2792022705078Q674.2282648046875,492.1685022705078,673.4777648046875,492.09460227050783Q672.7272548046875,492.0207022705078,671.9740348046874,491.9837022705078Q671.2208088046875,491.9467022705078,670.4666748046875,491.9467022705078Q669.7125408046875,491.9467022705078,668.9593148046876,491.9837022705078Q668.2060948046875,492.0207022705078,667.4555848046875,492.09460227050783Q666.7050848046875,492.1685022705078,665.9591148046875,492.2792022705078Q665.2131448046875,492.38990227050783,664.4735048046875,492.5370022705078Q663.7338548046876,492.6841022705078,663.0023248046875,492.8673022705078Q662.2707948046875,493.0506022705078,661.5491348046875,493.2695022705078Q660.8274748046875,493.48840227050783,660.1173748046875,493.7425022705078Q659.4073748046875,493.9965022705078,658.7106748046875,494.2851022705078Q658.0138748046875,494.5737022705078,657.3321748046875,494.89620227050784Q656.6504748046875,495.2186022705078,655.9853748046875,495.5741022705078Q655.3202748046875,495.9296022705078,654.6734748046875,496.3173022705078Q654.0265748046875,496.7050022705078,653.3995748046875,497.1240022705078Q652.7724748046875,497.5429022705078,652.1667748046875,497.9922022705078Q651.5610748046875,498.4414022705078,650.9780748046875,498.91980227050783Q650.3951748046875,499.3982022705078,649.8363748046875,499.9047022705078Q649.2775748046874,500.4111022705078,648.7443748046875,500.9444022705078Q648.2110748046875,501.4776022705078,647.7046748046876,502.03640227050784Q647.1981748046875,502.5952022705078,646.7197748046875,503.1781022705078Q646.2413748046876,503.7611022705078,645.7921748046875,504.36680227050783Q645.3428748046875,504.9725022705078,644.9239748046875,505.59960227050783Q644.5049748046875,506.2266022705078,644.1172748046876,506.8735022705078Q643.7295748046874,507.52030227050784,643.3740748046876,508.18540227050784Q643.0185748046875,508.85050227050783,642.6961748046875,509.5322022705078Q642.3736748046875,510.2139022705078,642.0850748046875,510.91070227050784Q641.7964748046875,511.6074022705078,641.5424748046875,512.3174022705078Q641.2883748046875,513.0275022705079,641.0694748046875,513.7491622705078Q640.8505748046875,514.4708222705078,640.6672748046875,515.2023522705078Q640.4840748046875,515.9338822705079,640.3369748046875,516.6735322705078Q640.1898748046875,517.4131722705079,640.0791748046875,518.1591422705078Q639.9684748046875,518.9051122705079,639.8945748046875,519.6556122705078Q639.8206748046875,520.4061222705078,639.7836748046875,521.1593422705079Q639.7466748046875,521.9125682705078,639.7466748046875,522.6667022705078Z" fill-rule="evenodd" fill="#2CFFFF" fill-opacity="1"/></g><g><path d="M375.2577557128906,485.21440764160155L375.2550557128906,485.2118076416016Q375.24655571289065,485.20330764160155,375.2380557128906,485.1948076416016Q375.1149557128906,485.07190764160157,374.99045571289065,484.95040764160154Q374.9815557128906,484.94170764160157,374.9726557128906,484.93300764160153Q374.4414557128906,484.4154076416016,373.8859557128906,483.9240076416016Q373.33035571289065,483.4326076416016,372.7517557128906,482.9686076416016Q372.17305571289063,482.5046076416016,371.5727557128906,482.0691076416016Q370.97235571289065,481.63350764160157,370.35165571289065,481.22750764160156Q369.7310557128906,480.8214076416016,369.09145571289065,480.44580764160156Q368.45195571289065,480.07010764160157,367.79505571289064,479.7258076416016Q367.1380557128906,479.38150764160156,366.4652557128906,479.06930764160154Q365.79255571289065,478.75700764160155,365.1054557128906,478.47760764160154Q364.4183557128906,478.1982076416016,363.7186557128906,477.9523076416016Q363.0189057128906,477.7064076416016,362.3081057128906,477.49460764160153Q361.5973057128906,477.2827076416016,360.8771057128906,477.1054076416016Q360.1569157128906,476.92810764160157,359.42899571289064,476.78570764160156Q358.70108571289063,476.6434076416016,357.96715571289064,476.53640764160156Q357.2332157128906,476.42930764160155,356.4949757128906,476.35780764160154Q355.7567257128906,476.2863076416016,355.0158957128906,476.2505076416016Q354.2750557128906,476.21470764160154,353.5333557128906,476.21470764160154L353.5325367328906,476.21470764160154Q352.1499857128906,476.21470764160154,350.7730257128906,476.33900764160154Q349.44232571289064,476.45900764160154,348.12707571289064,476.69420764160157Q346.81182571289065,476.92930764160155,345.52195571289064,477.2777076416016Q344.23208571289064,477.6262076416016,342.97735571289064,478.08530764160156Q341.72255571289065,478.54440764160154,340.51245571289064,479.11070764160155Q339.3022557128906,479.67700764160156,338.14585571289064,480.3463076416016Q336.9894557128906,481.0155076416016,335.89555571289065,481.78260764160154Q334.8015557128906,482.54980764160155,333.77835571289063,483.40900764160153Q332.75515571289066,484.2682076416016,331.81045571289064,485.21300764160156Q331.8019557128906,485.22150764160153,331.79345571289065,485.23000764160156Q331.67055571289063,485.3531076416016,331.5490557128906,485.47760764160154Q331.54035571289063,485.4865076416016,331.5316557128906,485.49540764160156Q331.01405571289064,486.0266076416016,330.52265571289064,486.58210764160157Q330.03125571289064,487.13770764160154,329.56725571289064,487.7163076416016Q329.10325571289064,488.29500764160156,328.66775571289065,488.89530764160156Q328.23215571289063,489.49570764160154,327.8261557128906,490.11640764160154Q327.42005571289064,490.73700764160156,327.0444557128906,491.37660764160154Q326.66875571289063,492.01610764160154,326.32445571289065,492.67300764160154Q325.9801557128906,493.3300076416016,325.6679557128906,494.0028076416016Q325.3556557128906,494.67550764160154,325.0762557128906,495.3626076416016Q324.79685571289065,496.0497076416016,324.55095571289064,496.7494076416016Q324.30505571289063,497.4491576416016,324.0932557128906,498.15996764160155Q323.88135571289064,498.8707576416016,323.70405571289064,499.59095764160156Q323.52675571289063,500.31114764160156,323.3843557128906,501.03906764160155Q323.24205571289065,501.76697764160156,323.13495571289064,502.50090764160154Q323.0279557128906,503.23484764160156,322.9564557128906,503.9730876416016Q322.88495571289064,504.7113376416016,322.84915571289065,505.4521676416016Q322.8133557128906,506.1930076416016,322.8133557128906,506.93470764160156L322.8133557128906,506.9355266216016Q322.8133557128906,508.3180776416016,322.9376557128906,509.6950376416016Q323.0576557128906,511.02573764160155,323.2928557128906,512.3409876416016Q323.5279557128906,513.6562376416016,323.87635571289064,514.9461076416015Q324.22485571289064,516.2359776416016,324.6839557128906,517.4907076416016Q325.1430557128906,518.7455076416015,325.7093557128906,519.9556076416015Q326.2756557128906,521.1658076416015,326.94495571289065,522.3222076416016Q327.61415571289064,523.4786076416016,328.3812557128906,524.5725076416015Q329.1484557128906,525.6665076416016,330.0076557128906,526.6897076416016Q330.86685571289064,527.7129076416015,331.8116557128906,528.6576076416015L331.8142557128906,528.6602076416016L373.4799557128906,570.3237076416016L331.8116557128906,611.9897076416016Q331.27835571289063,612.5227076416015,330.7718557128906,613.0817076416016Q330.2654557128906,613.6407076416016,329.78695571289063,614.2237076416015Q329.3085557128906,614.8067076416015,328.85935571289065,615.4117076416015Q328.41005571289065,616.0177076416015,327.9910557128906,616.6447076416016Q327.57205571289063,617.2717076416016,327.18435571289064,617.9187076416016Q326.79665571289064,618.5657076416015,326.44115571289063,619.2307076416016Q326.0856557128906,619.8957076416016,325.76315571289064,620.5777076416016Q325.4407557128906,621.2587076416015,325.1520557128906,621.9557076416015Q324.86345571289064,622.6527076416015,324.60935571289065,623.3627076416016Q324.3553557128906,624.0727076416016,324.13635571289063,624.7947076416016Q323.9174557128906,625.5157076416016,323.73415571289064,626.2477076416016Q323.55095571289064,626.9787076416015,323.40375571289064,627.7187076416016Q323.2566557128906,628.4587076416016,323.1459557128906,629.2047076416015Q323.0352557128906,629.9507076416015,322.9613557128906,630.7007076416015Q322.88745571289064,631.4517076416016,322.85035571289063,632.2047076416015Q322.8133557128906,632.9577076416016,322.8133557128906,633.7117076416016L322.8133557128906,633.7127076416016Q322.8133557128906,634.4507076416015,322.84875571289064,635.1877076416015Q322.8827557128906,635.8947076416016,322.94925571289065,636.5997076416015Q323.01585571289064,637.3047076416016,323.1147557128906,638.0057076416016Q323.2136557128906,638.7067076416015,323.34485571289065,639.4017076416015Q323.4759557128906,640.0977076416016,323.6389557128906,640.7867076416015Q323.8019557128906,641.4757076416015,323.99655571289065,642.1567076416015Q324.19115571289063,642.8377076416016,324.4169557128906,643.5087076416016Q324.64265571289064,644.1797076416016,324.89905571289063,644.8387076416016Q325.15555571289065,645.4987076416015,325.44205571289064,646.1467076416016Q325.7286557128906,646.7937076416016,326.04465571289063,647.4277076416015Q326.36075571289064,648.0607076416015,326.70565571289063,648.6787076416016Q327.0505557128906,649.2977076416016,327.42365571289065,649.8987076416015Q327.79665571289064,650.5007076416016,328.19705571289063,651.0847076416015Q328.59735571289065,651.6687076416016,329.02425571289064,652.2337076416015Q329.45105571289065,652.7987076416016,329.9034557128906,653.3427076416016Q330.3558557128906,653.8877076416015,330.83285571289065,654.4107076416016Q331.3098557128906,654.9337076416016,331.81045571289064,655.4347076416016Q332.3436557128906,655.9677076416016,332.9024557128906,656.4747076416015Q333.46125571289065,656.9807076416016,334.0442557128906,657.4587076416016Q334.6271557128906,657.9377076416015,335.2329557128906,658.3867076416016Q335.8386557128906,658.8357076416016,336.46575571289065,659.2547076416015Q337.0927557128906,659.6737076416016,337.7396557128906,660.0617076416015Q338.3864557128906,660.4497076416015,339.0515557128906,660.8047076416016Q339.7166557128906,661.1607076416016,340.3984557128906,661.4827076416016Q341.08015571289064,661.8057076416015,341.77695571289064,662.0937076416016Q342.4736557128906,662.3827076416015,343.1837557128906,662.6367076416016Q343.89382571289065,662.8907076416016,344.6155157128906,663.1097076416015Q345.3371957128906,663.3287076416016,346.0687557128906,663.5117076416016Q346.80030571289063,663.6957076416015,347.5399757128906,663.8427076416016Q348.2796457128906,663.9897076416016,349.0256357128906,664.1007076416015Q349.7716357128906,664.2107076416016,350.5221657128906,664.2847076416016Q351.27269571289065,664.3587076416015,352.02594571289063,664.3957076416016Q352.7791957128906,664.4327076416016,353.5333557128906,664.4327076416016Q354.32820271289063,664.4327076416016,355.1220457128906,664.3917076416016Q355.8255057128906,664.3547076416015,356.5265657128906,664.2867076416015Q357.22762571289064,664.2177076416016,357.92480571289065,664.1177076416016Q358.62198571289065,664.0167076416016,359.3138057128906,663.8837076416016Q360.00563571289064,663.7517076416016,360.6906657128906,663.5877076416016Q361.3756957128906,663.4237076416016,362.0524757128906,663.2277076416016Q362.7292557128906,663.0327076416015,363.39637571289063,662.8067076416016Q364.06345571289063,662.5807076416015,364.7195557128906,662.3237076416016Q365.3755557128906,662.0667076416016,366.0191557128906,661.7807076416016Q366.6627557128906,661.4947076416015,367.2926557128906,661.1787076416016Q367.9224557128906,660.8637076416015,368.5370557128906,660.5197076416016Q369.15175571289063,660.1757076416015,369.7500557128906,659.8037076416016Q370.3483557128906,659.4317076416016,370.9289557128906,659.0327076416015Q371.5094557128906,658.6337076416016,372.07115571289063,658.2087076416016Q372.6328557128906,657.7837076416015,373.17455571289065,657.3337076416016Q373.7161557128906,656.8827076416015,374.2365557128906,656.4087076416015Q374.7569557128906,655.9337076416016,375.2550557128906,655.4357076416015L438.6475557128906,592.0466076416016Q439.18075571289063,591.5134076416016,439.68725571289065,590.9546076416016Q440.19365571289063,590.3959076416015,440.6721557128906,589.8129076416016Q441.15055571289065,589.2300076416016,441.59985571289064,588.6243076416016Q442.0490557128906,588.0186076416015,442.46805571289065,587.3915076416016Q442.88705571289063,586.7645076416015,443.2747557128906,586.1177076416016Q443.6624557128906,585.4708076416016,444.0179557128906,584.8058076416015Q444.3735557128906,584.1407076416016,444.6959557128906,583.4590076416016Q445.0184557128906,582.7773076416015,445.30705571289064,582.0805076416016Q445.5956557128906,581.3838076416016,445.8497557128906,580.6738076416016Q446.10375571289063,579.9637076416016,446.3227557128906,579.2421076416016Q446.54165571289064,578.5204076416015,446.7249557128906,577.7889076416016Q446.9081557128906,577.0573076416016,447.0553557128906,576.3177076416016Q447.20245571289064,575.5781076416016,447.31315571289065,574.8321076416016Q447.4238557128906,574.0861076416015,447.49775571289064,573.3356076416015Q447.5716557128906,572.5851076416016,447.6087557128906,571.8319076416016Q447.6457557128906,571.0787076416016,447.6457557128906,570.3246076416016Q447.6457557128906,569.5704076416016,447.6087557128906,568.8172076416016Q447.5718557128906,568.0640076416016,447.49795571289064,567.3135076416015Q447.4240557128906,566.5630076416015,447.3133557128906,565.8170076416015Q447.2027557128906,565.0710076416016,447.0556557128906,564.3314076416016Q446.90855571289063,563.5917076416016,446.72535571289063,562.8602076416016Q446.54215571289063,562.1286076416015,446.3232557128906,561.4070076416016Q446.10435571289065,560.6853076416015,445.85025571289066,559.9753076416016Q445.59625571289064,559.2652076416016,445.3076557128906,558.5685076416015Q445.01905571289063,557.8717076416016,444.6966557128906,557.1900076416016Q444.37425571289066,556.5082076416015,444.01875571289065,555.8432076416016Q443.6633557128906,555.1781076416015,443.2756557128906,554.5312076416016Q442.88795571289063,553.8844076416016,442.46895571289065,553.2573076416015Q442.05005571289064,552.6303076416016,441.6008557128906,552.0245076416015Q441.1515557128906,551.4188076416016,440.6731557128906,550.8358076416016Q440.19475571289064,550.2528076416015,439.6883557128906,549.6941076416016Q439.1819557128906,549.1353076416016,438.6486557128906,548.6020076416015L375.2577557128906,485.21440764160155Z" fill-rule="evenodd" fill="#2CFFFF" fill-opacity="1"/></g></g></g></svg> \ No newline at end of file diff --git a/bb-api-collect/assets/img/akari.jpg b/bb-api-collect/assets/img/akari.jpg new file mode 100644 index 0000000000..5e5ea0bc91 Binary files /dev/null and b/bb-api-collect/assets/img/akari.jpg differ diff --git a/bb-api-collect/assets/img/ban.png b/bb-api-collect/assets/img/ban.png new file mode 100644 index 0000000000..a51f5b95d5 Binary files /dev/null and b/bb-api-collect/assets/img/ban.png differ diff --git a/bb-api-collect/assets/img/battery-100.png b/bb-api-collect/assets/img/battery-100.png new file mode 100644 index 0000000000..4336d56f48 Binary files /dev/null and b/bb-api-collect/assets/img/battery-100.png differ diff --git a/bb-api-collect/assets/img/bilibili.svg b/bb-api-collect/assets/img/bilibili.svg new file mode 100644 index 0000000000..e5cd8eed57 --- /dev/null +++ b/bb-api-collect/assets/img/bilibili.svg @@ -0,0 +1,44 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2250 1024"> +<path d="M2079.44,914.36c-10,0-19-0.33-27-1c-17.33-1.33-34.33-2-51-2c-10.67,0-10.67-0.33-12-11l-16-182l-16-151 + l-11-93l-10-81l-18-126c-6-44.67-13.33-89.33-22-134c-1.33-6.67-1-7.67,7-9c31.33-6,63-9,95-9h11c5.33,0.67,8.33,4,9,10 + c1.33,23.33,2.67,46.33,4,69l28,373l14,171l9,98L2079.44,914.36z M853.44,115.36c4.67,0,10.67,0,18,0c9.33,0,11,2.67,11,12l8,121 + l18,251l11,131l8,101l16,174c0,8-1,9-9,9c-24-1.33-48-2.33-72-3c-5.33,0.67-8-1.67-8-7c-1.33-11.33-2.33-23-3-35 + c-3.33-30-6-60.33-8-91l-16-158l-17-143l-12-101l-13-92c-6-41.33-12.67-82.67-20-124l-5-28c-1.33-4.67,0.33-7.33,5-8 + C793.44,119.03,820.11,114.03,853.44,115.36z M1859.44,518.36c25.33,0,28,1,32,25c4.67,30,8.67,60,12,90l11,97l21,206 + c1.33,4.67-0.33,7-5,7l-78,9c-8,1.33-9.67,0-11-8l-45-230l-28-153l-4-21c-0.67-4,1-6.67,5-8 + C1800.11,525.03,1830.11,520.36,1859.44,518.36z M722.44,518.36c26.67-1.33,30.33,1.67,33,27c6.67,40.67,12,81.33,16,122l13,120 + l8,81l7,65c0,9.33-1,10.67-9,12l-74,7c-8,1.33-9.67,0-11-8l-61-314l-16-89c-1.33-4.67,0.67-7.67,6-9 + C665.11,525.03,694.44,520.36,722.44,518.36z M1104.44,828.36v124v4c0.67,6-2,8.67-8,8c-8,0-16,0-24,0c-17.33,0-34.33,0.67-51,2 + c-9.33,1.33-9.67,0.67-11-10l-16-180l-8-89l-12-136c-1.33-10.67,0.67-12.67,10-14c28-2.67,56-3.33,84-2c6.67,0.67,13.67,1.67,21,3 + c8,2.67,9,4,9,12c1.33,18,2.33,36,3,54l1,60C1103.78,719.03,1104.44,773.7,1104.44,828.36z M2239.44,834.36v117v6 + c0,5.33-2.33,7.67-7,7h-36c-14,0-27.67,0.67-41,2c-8,1.33-8.67,0.33-10-9l-21-234l-11-116l-4-59c-1.33-8,1-10,9-10 + c33.33-4,66.67-5,100-1c13.33,1.33,14.67,4.67,16,18c1.33,44.67,2.33,89,3,133C2238.78,735.03,2238.11,782.36,2239.44,834.36z + M1830.44,305.36c10,0,18.67,0.67,26,2c4.67,0.67,7.33,3.33,8,8l13,139c2.67,12,1,14-11,14l-34,2c-6.67,1.33-10,1.67-10-9 + c-4.67-37.33-9.33-75-14-113l-4-32c-1.33-6,1-9.33,7-10L1830.44,305.36z M697.44,305.36c8,0,15.67,0.67,23,2c4,0.67,6.33,3.33,7,8 + l4,35l10,109c1.33,8,1,9-7,9c-12.67,0.67-25.67,1.33-39,2c-8,1.33-8.67,0-10-8l-9-80c-2.67-22.67-5.33-45-8-67 + c-1.33-5.33,0.67-8,6-8C681.78,306.03,689.44,305.36,697.44,305.36z M1096.44,405.36c0,23.33,0,46.33,0,69c1.33,10.67-0.67,11-10,11 + c-12.67,0-25-0.67-37-2c-8-1.33-9.33-1-8-9l-3-85c0-18.67-0.33-37.67-1-57c-1.33-9.33-0.33-10,9-10c14,0,28,1,42,3c8,0,8,2,8,10 + V405.36z M2232.44,406.36c0,22.67,0,45.67,0,69c0,9.33-0.67,10-10,10c-12.67-0.67-25.33-1.33-38-2c-6-0.67-8.67-3.67-8-9l-3-143 + c0-8,1-9,9-9c12.67,0,25,0.67,37,2c14.67,1.33,13,4.33,13,15V406.36z M666.44,460.36c1.33,12,0,13.67-12,15l-24,6 + c-8,2.67-8.67,0.67-10-6l-25-141c-2.67-9.33-1.33-10.67,8-12l35-6c8-1.33,10-1,10,7c3.33,17.33,6,34.33,8,51l10,80V460.36z + M1730.44,323.36c15.33-2.67,31-5,47-7c4.67-0.67,7.33,1.67,8,7c2.67,18.67,5.33,37,8,55c4,26.67,6.67,53.67,8,81v8 + c0.67,4-1,6.67-5,8l-32,7c-4.67,0.67-7.33-1.33-8-6l-26-149V323.36z M1020.44,431.36c0,16-0.67,31-2,45c0,4.67-2.33,7.33-7,8l-31,3 + c-4.67,0.67-7-1.67-7-7c-2-14.67-3.33-29.33-4-44c-2-27.33-3.67-55-5-83l-2-20c-0.67-4,1-6,5-6c13.33-1.33,27-2.33,41-3 + c6.67,0,9,1,9,9L1020.44,431.36z M2154.44,415.36c0.67,19.33,0.67,38.67,0,58c1.33,9.33-0.67,11-10,11l-28,3c-5.33,0.67-8-1.67-8-7 + c-1.33-25.33-3-50.67-5-76l-4-70c-0.67-4.67,1-7,5-7c13.33-1.33,26.67-2.33,40-3c6.67,0,8,1,8,9 + C2154.44,360.7,2155.11,388.03,2154.44,415.36z M627.44,756.36c16,18.67,18.67,40.33,12,63c-6,22-17,41-33,57 + c-26,27.33-55.67,49.33-89,66c-56.67,30-116.33,50.67-179,62c-44.67,9.33-89.67,15.33-135,18c-14,0.67-28,1-42,1h-30 + c-8,0-9.67-2-11-10l-7-97l-19-191l-21-182l-12-97l-13-93c-7.33-51.33-15.67-102.33-25-153c-6.67-41.33-14.33-82.33-23-123 + c-1.33-5.33,0.33-8.67,5-10l139-58c8.67-4,17.33-7,26-9c6-1.33,8.67,1,8,7c0,16-0.33,32.33-1,49l-1,13c-1.33,58-1.33,116.33,0,175 + c1.33,51.33,3.67,102.67,7,154c5.33,80,13,160.33,21,239c0,8,0.67,8.33,10,7c16.67-2.67,33.33-4,50-4c53.33,0,105.67,6.33,157,19 + c44.67,10.67,88.33,25.67,131,45c20.67,10,40,22,58,36C617.11,745.03,622.78,750.36,627.44,756.36z M1754.44,747.36 + c20.67,17.33,28,39.67,22,67c-5.33,22-15.33,41.33-30,58c-24,26.67-51.67,48.33-83,65c-60,33.33-124,56-192,68 + c-36.67,7.33-73.67,12.67-111,16c-21.33,2-43.67,2.67-67,2h-27c-6,0.67-9-2-9-8c-2-28-4.33-56-7-84l-16-171l-17-149l-21-168 + c-3.33-29.33-7.33-58.67-12-88l-18-112c-8-53.33-17.67-106.33-29-159l-1-7c-2-5.33-0.33-8.67,5-10c49.33-20,96.67-42.33,146-61 + c13.33-5.33,29.33-11,28,1c-4,37.33-2.67,74-4,110c-1.33,30-1,59.67,1,89c0,8,0,15.67,0,23c0,36,1.33,71.67,4,107 + c2,47.33,5,94.67,9,142c2.67,34,5.67,67.67,9,101c1.33,18.67,3.33,37.33,6,56c0,10.67,1.67,10.33,11,9c18-2.67,36-4,54-4 + c62.67,1.33,124,10.67,184,28c40.67,10.67,80,26,118,46C1724.11,723.7,1739.78,734.7,1754.44,747.36z M308.44,923.36 + c15.33-8.67,41-27.17,77-55.5s58.33-47.5,67-57.5c-54-24-110-45.33-168-64L308.44,923.36z M1585.44,815.36c2.67-2.67,2.33-5-1-7 + l-24-10c-42-18-84.33-34-127-48l-6-2c-2-0.67-4.33-0.33-7,1l24,173c2.67,0,4.67-0.67,6-2c39.33-28,78.33-57.33,117-88 + C1573.44,827.03,1579.44,821.36,1585.44,815.36z" fill="#FB7299"/> +</svg> diff --git a/bb-api-collect/assets/img/blackroom.svg b/bb-api-collect/assets/img/blackroom.svg new file mode 100644 index 0000000000..10c801dfb2 --- /dev/null +++ b/bb-api-collect/assets/img/blackroom.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"><path d="M139.264 529.152a27.136 27.136 0 0 1-14.592-2.816A32 32 0 0 1 113.152 486.4l130.816-236.032a28.416 28.416 0 1 1 49.152 28.928l-130.56 235.52a25.6 25.6 0 0 1-23.296 14.336" fill="#F99E4A"></path><path d="M380.416 529.152a34.56 34.56 0 0 1-25.6-14.592l-131.328-235.264a30.208 30.208 0 0 1 11.52-37.632 25.6 25.6 0 0 1 37.888 11.52l130.816 235.264a25.6 25.6 0 0 1-11.776 37.888c-2.816 0-8.704 2.816-11.52 2.816m261.376 0a25.6 25.6 0 0 1-14.336-2.816 29.44 29.44 0 0 1-11.776-37.888l130.816-235.264a28.928 28.928 0 0 1 37.632-11.52 29.44 29.44 0 0 1 11.776 37.632L665.6 514.56a25.6 25.6 0 0 1-23.296 14.592" fill="#F99E4A"></path><path d="M883.968 529.152a34.56 34.56 0 0 1-25.6-14.336l-130.56-235.52a27.392 27.392 0 0 1 11.52-37.632 25.6 25.6 0 0 1 37.888 11.52l130.56 235.52a25.6 25.6 0 0 1-11.776 37.632c-2.816 0-8.704 2.816-11.776 2.816" fill="#F99E4A"></path><path d="M801.536 241.664l-130.56-51.2A129.536 129.536 0 0 0 640 183.552H380.416a153.6 153.6 0 0 0-32 5.632L217.6 241.664A21.248 21.248 0 0 0 226.304 281.6h569.6a21.248 21.248 0 0 0 5.632-40.704M458.752 281.6v520.704a51.2 51.2 0 0 0 104.704 0V281.6z" fill="#FFD043"></path><path d="M561.152 183.296A51.2 51.2 0 0 0 512 139.776a52.992 52.992 0 0 0-51.2 46.336h102.4z" fill="#FFD043"></path><path d="M755.2 877.824H267.008A41.472 41.472 0 0 1 230.4 816.896l55.04-122.112a44.8 44.8 0 0 1 37.888-25.6h373.76a37.12 37.12 0 0 1 37.632 25.6L790.016 819.2a37.888 37.888 0 0 1-34.816 58.112" fill="#F99E4A"></path><path d="M900.352 494.336a9.216 9.216 0 0 1 8.704 8.704 148.48 148.48 0 0 1-296.192 0 7.68 7.68 0 0 1 8.704-8.704z m-502.528 0a9.216 9.216 0 0 1 8.704 8.704 151.808 151.808 0 0 1-148.224 142.336 150.016 150.016 0 0 1-148.224-142.336 7.68 7.68 0 0 1 8.704-8.704z" fill="#FFD043"></path></svg> \ No newline at end of file diff --git a/bb-api-collect/assets/img/channel.svg b/bb-api-collect/assets/img/channel.svg new file mode 100644 index 0000000000..308e4df03a --- /dev/null +++ b/bb-api-collect/assets/img/channel.svg @@ -0,0 +1,6 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> +<path fill="#23c9ed" d="M837,192c1.3-8,10-14,18-10c46.7,24,75,70.7,75,124v299c-1.3,78.7-60.3,137.7-139,139H352 + c-53.3,0-100-28-124-76c-4-6.7,2-15.7,10-17h506c53.3-1.3,91.7-39.7,93-93V192z M93,0h605c50.7,0,91.7,41,93,93v419 + c-1.3,50.7-42.3,91.7-93,93H93c-52-1.3-93-42.3-93-93V93C0,41,41,0,93,0z M508,321c12-9.3,12-28.7,0-38L339,165 + c-16-10.7-35.7,0.3-37,19v236c1.3,18.7,21,29.7,37,19L508,321z"/> +</svg> diff --git a/bb-api-collect/assets/img/class.svg b/bb-api-collect/assets/img/class.svg new file mode 100644 index 0000000000..51797d1d1e --- /dev/null +++ b/bb-api-collect/assets/img/class.svg @@ -0,0 +1,7 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> +<path fill="#0BA395" d="M107.7,3.2C45,16.5,1,68.8-0.3,134.2v582c1.3,65.3,45.3,117.7,108,131V3.2z M625.7,0.2h-452v850h452 + c76-2.7,132.7-58,134-134v-582C758.4,58.2,701.7,2.8,625.7,0.2z M385.7,117.2c0-18.7,14.3-33,33-33h213c18.7,0,31.7,14.3,33,33v237 + c-0.7,13.3-6.7,23.3-18,30c-10.7,4-23.3,4.7-34-2l-92-63l-82,62c-22.7,14.7-51.7-0.3-53-27V117.2z M670.7,704.2 + c0,18.7-14.3,33-33,33h-354c-42.1,0-41.2-63.1,0-66h354C656.4,672.5,670.7,685.5,670.7,704.2z M670.7,555.2c0,18.7-14.3,33-33,33 + h-354c-42.1,0-41.2-63.1,0-66h354C656.4,523.5,670.7,536.5,670.7,555.2z"/> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/img/coin.svg b/bb-api-collect/assets/img/coin.svg new file mode 100644 index 0000000000..d58a86ebf4 --- /dev/null +++ b/bb-api-collect/assets/img/coin.svg @@ -0,0 +1,7 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> +<path d="M472,244h119c47.06,0,47.06-65,0-65H281c-45.49,0-45.49,65,0,65h125v60c-112,8-192,93-196,205v44 + c3.12,40.52,62.97,42.37,66,0v-44c1.33-74.67,55.33-133.33,130-140v305c2.98,41.69,63.02,41.69,66,0V369 + c74.67,6.67,128.67,65.33,130,140v44c0,41.73,65,41.73,65,0v-44c-2.67-112-82.67-197-196-205v-60H472z M439,878 + c-124-3.33-227.33-46.33-310-129S3.33,563,0,439c3.33-124,46.33-227.33,129-310S315,3.33,439,0c124,3.33,227.33,46.33,310,129 + s125.67,186,129,310c-3.33,124-46.33,227.33-129,310S563,874.67,439,878z" fill="#FB7299"/> +</svg> diff --git a/bb-api-collect/assets/img/collect.svg b/bb-api-collect/assets/img/collect.svg new file mode 100644 index 0000000000..b382480659 --- /dev/null +++ b/bb-api-collect/assets/img/collect.svg @@ -0,0 +1,9 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> + <path fill="#F3A034" d="M646.6,837.1c-50.8,0-119.6-23.4-204.4-69.5l-0.2-0.1l-0.2,0.1c-84.7,45.8-153.4,69.1-204.2,69.1 + c-36,0-63.8-11.7-82.8-34.6c-17.8-21.5-28.2-53.6-31.1-95.4c-2.9-41.8,1.7-94.5,13.8-156.5l0.1-0.3l-0.2-0.2 + c-53.4-49.2-91.6-94.1-113.6-133.2c-21.9-39.1-28.3-73.6-19-102.7c9.4-29.2,35-53.7,76.1-72.8c41.2-19.1,99.1-33.4,172.1-42.4 + l0.3,0l0.1-0.2c31.3-65.6,63.1-115.6,94.4-148.4C379,17.1,410.7,0.5,441.9,0.5c31.2,0,62.9,16.6,94.1,49.3 + c31.3,32.8,63.1,82.7,94.4,148.4l0.1,0.2l0.3,0c73.2,9,131.2,23.3,172.5,42.4c41.2,19.1,66.9,43.6,76.2,72.9 + c9.3,29,2.9,63.6-19.1,102.6c-22.1,39.2-60.4,84-113.9,133.2l-0.2,0.2l0.1,0.3c12,62.2,16.7,115,13.8,156.9 + c-2.9,41.8-13.4,74-31.2,95.5C710.1,825.4,682.4,837.1,646.6,837.1z"/> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/img/comment.svg b/bb-api-collect/assets/img/comment.svg new file mode 100644 index 0000000000..f5cf6b1c0a --- /dev/null +++ b/bb-api-collect/assets/img/comment.svg @@ -0,0 +1,7 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 823"> +<path fill="#1497C7" d="M892,329c-2-74-28.8-135.8-80.5-185.5C759.8,93.8,695,68,617,66H343c-78,2-142.8,27.8-194.5,77.5 + S70.3,255,69,329c1.3,74.7,27.8,136.8,79.5,186.5S265,591,343,593h79l32,107l117-107h46c78-2,142.8-27.8,194.5-77.5 + C863.2,465.8,890,403.7,892,329z M343,0h274c96.7,2.7,177.3,35,242,97s98.3,139.3,101,232c-2.7,93.3-36.3,171-101,233 + s-145.3,94.3-242,97h-19L419,823l-49-164h-27c-96.7-2.7-177.3-35-242-97S2.7,422.3,0,329c2.7-92.7,36.3-170,101-232S246.3,2.7,343,0 + z"/> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/img/contributors.svg b/bb-api-collect/assets/img/contributors.svg new file mode 100644 index 0000000000..269f5700d9 --- /dev/null +++ b/bb-api-collect/assets/img/contributors.svg @@ -0,0 +1,218 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="860" height="184"> + <style>.opencollective-svg { cursor: pointer; }</style> + <a xlink:href="https://github.com/188102836" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="188102836"><image x="2" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/863056768" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="863056768"><image x="28" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/1299172402" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="1299172402"><image x="54" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/2513502304" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="2513502304"><image x="80" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/SocialSisterYi" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="SocialSisterYi"><image x="106" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/wuziqian211" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="wuziqian211"><image x="132" y="2" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAW9klEQVRogb2aZ2yj65Xf9SHefM8F1nac5Esc7wb7IcAGAbL5tEGyiw3i2Nf24jZf761zp/em6WojadSlkTSSqDLSSKPRqDeKRb1QVJeoRlKkCkWKnWKvL+cXkJprr2N7kfXe9QEO8b4A+b7//ynPc55zmJLyDQhHru9gPv4Is6sUm1uKL7gTd/tceANRBCEKuAiFdnB7pTiOS7E6PxQObd/5Jt79+4N2ut/B7LmEzbuA3QvHfnD6wOWDYx+4/eANQCgE4TB4Et/xgO0YrC6wOODINo/FfpEj6zt/MOBxo+PfCHumElyeADYfOP0n4H3BE8AJ8MdviSQJhCESgWAQ/AFwesGeIOIGm+tErQ4/ZlsxVsf3/tmAA99C4LJgcvqEfdNbKwfAHzoBHwiBJ0Dc4cGxto5tToFvd4vQkR7BZyfmOCJsMRG3u8HhA9vfI2E/BpszcR3A5krDYv+X3yx4gT8BVhEgbrAjmKwnVk9oIITPaEIrl7NQK2K84AnzlSWsNVTh39sgbNIQOzYRs+qJWXUI4RBRlxshaXkXWJ3gOAbH12RccOxdweP9wTcDHn4G+EhIHIRdK4LJnvTAG5cPw9QMS6IaFqsrmSsvRdVQg2lCwmZLLTH9GoLDABEvCGEQBOJBL8RjCOEIYZMFzM6TfPiaSCJPAgmPBr04j3/yTwIfDUc/fRN/E0sAR0h8gKC3IBxakqFwOD7GSr2ImbIS5irKmKssY6+jBd+6EufKJMQTYKwIFi2C3ZD8fdIOfhfEIsQFgcDhEcKBFSwucHnB64dgCPxBcLoF7Mdnfl/Ln+b/lVgcQWcmtmvEta5iraGeyScFzJQkQkbEbEUpS6IK1htr8G4qCR/vARGIJoAdgSNxfyIR6z4IoSSJ4KEJErkRiSa9lEx6XwAsCa+4Ezly8fcJG+E3CISixHZMBLY0GGRijmXD+BXT7Ha3syiqTHpgpa4Kg6yHmNNA+HCLuBA6edSbCFh04DCeeCEaIaSZh2iAWCRM1Ot56574CfiEN77OC4tDiJps7/7/gv8+8PZpf08SdPwhojtGjpcXMEgG2WxsZL+nA33Pa1aaRKzUV6NqrMEg7sQ8I8Nv1BGyGoh7TRC2g1NHWCkl6jkCopgXFei7m4n67IQclpMlN7GauX0n4BO55vElNaI3+2Jz+j/9h8EL/BFxVn8N+JtE6Lwl4AkQWFdjGpOh7+rkYKgP16oS4/AgK40idge7ME5I0PW84kDajXN1hgNJJ0ejvQguAzHLNtaRXhRVBQhBJ0LIx1RxNvvi18RjYSJ2O/j8J6BdHnB6TvIhHCG0sUd0RLUcm9V/63cTCMdT8YUg8jZ6EnmbKAQS95EYgtnFgTgBsIPN+joiOxvETFpcq7NM5j9B19eBtvc1i9VlqBqr0fa8ZKb0CevN1ZgVclRNVayIntJ79yqC34ZjbZbxkmxUz58h+GwErEeJxD0hkFiNEmQSK1KCRCiEp3WUYNPojd8O3hP6Hga7P7lLBqMQikEgenIdjIA/jH1OxUpDPfapMdZqa1l/0ZhcheYry5GkPWKyKJ+5yhKmS/NZqC5jvaWW0exHjOamsfa8iqXacsbzM+m9c43lpir0fa+YrshntiwPfW8rxkkx3h0tuD0npUeCQIJIIqTCYXySeVz5bT7/0Nx3f5PAka+EXRc4g+CJnIA/TuyuIQiEwRtkulLEXHUVR8MyZp9WMFFczGzFU6ZKihh8+JDBR/cZzXuMNDstSWK+pozJnAy6b15itjSf6ZIniB/eYiQnncGMO+x0v2StWcTgo1Q2XjUgWNXo+tvB64NQYi9I7PSBk1oqEuG4bQx7cTtRu6vw18GbA+9wFAjgjYE1AEc+sPrBlijQAuAOcqBcoiv1AZttbXhVa+z19TGS+4SJwkLkudkMPHhI05nTdKbeYDD9PuMF2Qw/yWQyJ5OVwlxkafeYLsxlIPUaM/nZdN25QtCwzaGkm4GHt5mtKMQ5P8xcdRHBPf3b/SB4kthvNWJzISTCKxz2E4v9qgDEHLyEPWHtKOwdk/TEnhNMHjAd49UcMP60moP2PmyyYXStrex19TKQnoUkK5uhrCxeXb2O+PpV2m9eo+feLeTZ6bTfuIQiPxdLxysGbl5hqayE/tTrjKfdZbnsCXGvDfPMCNLMh8geP2S5rgJldUky3KKJhHZ7T6rZaOxkeQ1HTjQWS+j5XxE49C9gDYLZD3su0NpBa4NdB0HNIUtNr/Cp93GLR9mqe85U6VP6H2XSffchHal36bn3gIZTZ1CXFDP04B6yjHSkGY9ou3yOqexM/IoJHEP9zD3OYCYnG/Hls2w/zcOzsUjEqqcj9VqS8MzTQuaelTBXks9hbxuC230SPrG3BKLRk/sEiUh07gT83M532TK+4cgLh8ew/ysCgRU9e+IxgtojInoru9XPkWY/QfI4j+67j+i4eY+mc5fpuJFKy5dfYu/vZbm4iMmsHEYzMpjIzECZ8xjvvIKIXoO5s43t8qcM37yK7PY1NhtEqNuaKP/4PUafZCXDTlFRyOjjNIxdrQQ2VokdH5+sRF/vEYnrRF6EQm+IRr+dwqbxI/T2pLXZscGOnbjGTGB5B9+SlpjWSlRvxTq5zKtzV5Dm5DGQ9pjO1Ie0XrpJ05mLtJ69zEJ+HuH1VY7Hx5nJyEGZk8dqcRnq0nKcMjEmxSTzDTUsF2Qzl5GO8tE9NmtrWKuvJvd//w/GnmQhz05D8bSA7ttXML5uxD08iHd+Gv/B7gnoREglNFH0JfYJt+f9FLbNpWybQWMFtRV0dtDZkirobcR2rETUZsZK62i+eIu+BPi7abReuUXntTu8PnuZl1+cxjzYR0SzhXNmlq2aOnT1jWir6jhsfIX+ZQt9eSVc+Iu/4ct//R0y/uovkdy6znZdLWt1VRT/5H8hfngHaeZ9RvOzkGQ+QHb/BgfD/VhmFSw+F2FfXz3Ji8TZIVG9JkoMh7s4BZVRyuYRbCVImEFrJUEovm1G2LESVZsxDs8zlJ6PvlXCq5v36Xv0mOYLN+hPTaPzi7OMXb/FWPpD1l88xzExgXdpAatUhkepYL+pFbdyhunqeqp+8KeU/ODPkOTkoGpoYbuujpXqZyifFtJ9+xpD6fcQZ9yj6841Xl49z+Dje3g127g1Wra62nGsLOOcmyOs3T0h4XCLU1g90LNhAIMVNCZQW+DQiaC1ENWYcS9qEWcWYJfOcdQ/Rcu1+7RcuUXzhZt0XrvH+I37NJ8+z6k//2v+7t/+O7QyCVHjAYLFiGdpnui+Ds/yAvujYyz87F1UZz5l+Px59lra2BLVsVzxFPf4MCP5OUnLd6Re5cWl00zm59B86yKbrxqJWWyEDUY0XZ2Edg/wa3dwr6vwaDQ7KSxsO5nbgtltWN6DXRvxAzuxHQvHG3pk+RWYRuYIK7SYB2YQfXUZ0akLPD99BemDHNrPXGGk+iUZ//7PKP+P/wn5xYsIFhO4neCyEbceET3QE93R4Oh8yXF7I/aZGY46elA9q2KptBjr+Ah9924jzrhPzalPeHn1HDNFeQznZyLPScMwPETMZEFwuND19xM8NCZzQTh221OYWI0wpYKFXVAZQW8jumlib2iK8VIRxuE51LkNhKbUrIpe03rrETWnLtFw+gqvL91mJa8S7YsOxtPyWP/iU3ZyHhHb14PDCk4rHBkQ1JvEFuaITI4TmZ4irNFg7B1kpbySlaclyWW0794txJkPKHj/J/TcvY5tepzFqjJGC3PZ7mhl/VVzEnjc5WZfIiHksENMCKfEhxcjKPdg/oDYmgGjZJal+tdoOqSEtozsjijo+c/voiqtZyu/grrzt5IE6s9c5dXlVHTNPZgqawhNKdh/VkF4cozYhorY7g4c7sG+jrh6E2FtGWF5gejKEmGjAW1TK6vP2hgvbOLpxx8iz0pP7uAVn3xA580rBFQr6FobUUvEzJcVYl2cZ7O5EfPUBBGXE8fcMtFdRzhlr1Pu3G7uZ7WhneXGNnSdUvYHp5B+cI35sxn0PcjixZ//NU2nLjKVXULJR19S+9Vl6s9e4+XlVCSPcpm+/Qhv8wvCr9uIyiQIqyu80W6DXgO7WtAnVIOws010V4tHq0VV3cRsWScDOS+o/uIrJvJy6bh1lYbzX7BaXkBEp2a/4xWDmfeZLc0jcqBDcHtxqtY5kIjxzK4Qm9HZU/qzS3U9WcV0ZxbRlVFAe1oenen51H56nua//Cni//kxdf/1hzTfeED/4yKartyh+stLtFy/x4vLqTSduUbbpdtM3XtIVDxIdGoSYWWZ+PYGwaEBwj2dRNZXQKdOEoiZDewPSZkvraD10m3qz16g4fRnLJSV0HLpNI3nT7HX+hzfghJFWT5NF75E09WBprUR6/wsQbM5ual5tXr8A0s7KcqiWqkwvkJ8y5CsOBPHxuiBk/CWGdfSDp13M8j5ix/Te/UC+92v6X6UR9WpK3Tcy6Th3E3ab2dQ+8k5qt77BHt/H1GlkujSIsL6GpHpCWKKKQTtFuyceMSzqWK5SkTP7VREn39C+c/fp+HUpyjLCnl55RyNF75iJDsN9YsGlmue0n3vBgapNFkIGieG0fV0YZ5VEA9HiEej4pSD5v7SwaxSnBMr4ArgXdnFJF9g+lkj0oIKOtLy6Tr9OWsFd1muqaI3rYCaU9foy8yn7sw1Xt3OoPKjryj64YdU/O3PUYlEROaUSS+wqQL1Jmi2YUeNe3wMzbMqpvOLqPnsE+pOfUbFxx8wkn6H9tSrdN25QdPF0wxnZ6Btb2WjroL2GxfxaTfQS6UcTY+x3dZKyGLFPDFOxGorTolNrX/ols8jzi1HXiJirbkHadEz5MVV9GUVI36Qz7qomYn8Mio+OctQVhkNZ28ymF2E6NQlxJnFlH/4Bbl/8x75P3yP/P/zHlW/+JyZ4hLsMinx9VWCcwqcLS85ftHMSrWIlgsXqPq7j6j69CNqv/wMeW4Gz8+fYqG1hb77qUwWPGHkSWbyqGqeV+JQjGOcGsc4JmdnsJ/557XE/AGc8wvvpThG5r990C17o27tQ5L3lM7MIl7czuLZ55d4+aPPaD13k77sYsYKa6g/f4PhnGdIcirozW5gMvc58xXNVP3iDIXv/oKin35Myd9+TNGP3qfsxx/S8PEnOGvr8DU8J9TRgVE8wHRhEc8/+Iyqn31A3alP6b13m94HqbTeuEz3g7t03LrCZGEe2631zNUn3pXO4YiMrfYWDKMyQtYjdkfkBHXaN8Kx59vJivSgdWB+q7mT1fp2DlqH0NV04FCscdgzgnV8gf3J5aTlR3NKWRT1MP96ia48OYtdS8hzq6n9/DJlH5yi+P3PKP/5F9S/f4e2H99C9F/ex1JeTUwmJbS0wEptHUa5BEvvIM//6jQ1//1DZI8f05v2AFlRPtLcbEays5ivKCSwvUrH3RvMV5SyUF7GVFE+WskAAeMBxAXci/OzvzwPLFU1XrQNjBMdXyc6oyai1GPvmsQ9vIS2fwxZ7jMkD/LZfDHIRu8i0rIJenKHGC5LhFY1jadu03wunZfX8unLbWP22TBTmS+RXy5m4N1LRBUKDDIJRrmM+O4OwuY6weUllm6kIbvwCHFWMdL0dOSPs1BWlBBQq5iuLEU7MoyyVsRy9TOmyoqRZj3CuKBMHi99ev25XxLYauh4x/Ja5o/Kl4nOaQkpd7BMLqGseclYfjXLz1qxyRSYusaRlbQykNNK0+V0Kj8+x0JZDbbXPWxU9zNXMcyyaIKNxmm0rUp0ncvsPB9kIaOAPYkYDHvgchDa38U5q8Dc14/yyj1WyppZbxxkvqIWy+IcSlEVTee+pP3+Lbx7BvofZ7De3kb/nVuM5D4msL/nxxf89ZmCpqm7+LBTjqq5i8nKeiQFVcxVNmMcVHA8p2alvo35upe8uJ5G+/18Gk5dYzunlPmcEvZaOwkrlJj6pjBK1jFINjAMbXK8sIemRcJ0WjHe2VnwHBM6MhE2HiJYzUT39tjNKWKvsYfgkoajkRUWqkX03E2l4/Z1Xlw6iyw/G9O0AnH6Iwbu3ERRXoK2o6PgN7oSIwVV3xsurfVLCqoZLa5B1y4lsm4guLDLYuNrpisakT+tpe1mJi2XH3HQ2kVwTIGrS8xuQyuGtm5cUjlHsmXciwcE1UeYJtexKFQc9Y5jFzURtxwRNyd6P3YEnR7BYsEnlXJYWoNzWIl/Q09QtcFunYjxJ0/oy3iIvLSInf4+Nnt7GMnKZKlW5F1qaPjt4yl1Q9dtTbsY99gK0UU9wc0Dlpo7GcorpzujgKmKBrrvPGE6o4jI7BKRtQ3CS2sEJmbxjE4SmJnDOTZLSGPGv2nCu75HSGvGv3XEYWMfXvkIHJmSYYTLlRyMCLu7GLIL2H0hJrhrJmx2EhkfwyKT0Xb9KvqeQaYqytGIh5gsKWG9ueV6yu+Subq2b8mKqpcnyhsZKa1DUljBROULJmtaWHnRzdDDAqYyKjE29mJ9Lcc1OExkY5uIVo9gTswMvIQ2tPjWD4no7ET0doJqE5FdO56JBQ4rm4glPODzvj3bhsHlxlLTiK5xAM/aAcZhFceyKWIry0zkFbA3JEdRW8fss2qOlAtLK43Nv7u1mBCXWPH9lbrXHm2nBNeUisWmTmarW5lIq2ct7xWOaS0HTRIs4nkMHdM4xWPEEhObRPMrFCGu3cc5vkpkx05U7yCss+LfMuJdM6B61sfO0wZIHNT9iblaIFnXR2bn2M0pwzMxj2l0E13TEML4OGPvnWXl7F02G1tZffXat9be+Sf/IPhfkpAqf7LVIRGGC6sZflLFVEUTSzXDHA3vYB7fwzFrIGb341Fu4ZvdxDY2nwyHuNFCbHYRz+hCkkBCwzo7zuV9POuJnNBhbhNjbe0majKBJ9H7txFXbxMan8DY3IOuaRB1bSf65/1s5DVjn9lkd2RC2Ozp+1HKP0YmSuq/2u6QsS9X0pHxlO3OVcyjekJ6J7EDN0Ki7RgF++QaW896iS6rECYVCCPjhKcXCKqtBLatBNRW3Otmjmb0eLeOiOjMWIdm2avvwjM6hW9sEqdsmJh6G22piN3WUTZKW7EpdrGMrOPe2H8TObR+mfL7yHxd16ftDwpjS00jOGcPOJ4zEjF4EOyJnmUUwRNBJxKzXC7H1dxJTD5BfGyawMgM/nUzgS0rHpUFj9pBxBkk5vAS8wXxaQ6IWLz4ltTon73A2daNub6ZydM3WH5UxnbFS94kmsuxuBALhE6n/FNkXCR/90Cs8ZqHdQTWLET33cTMPrwqC0cjOlZKxCyVydnPeEp0cpaobAJfjxS3QkdYYyOaaJgl2vQRgbg7mOzau1XrBNY2Ca6r8cyuoS2p57D+NWu30tA09BHYthAyuz0I/OPC5nfJXu/2f7DK9cuRNSuRTRuRDRsWqRZ9p4r15woUOb3sZVUSkYwS7pbgbO7H0KfCPrWHf9tG3Bkk7gr+clD4a4OfcITQoQ1T+yjbOZVsFDYQ0TuWwhb391O+SXEP7/2L6IrlcnjO5HWP7mLsWERVN8NcsZzpBy0sXn9CRDZOaGAYY90AO22ruBeNySROhlzsN8F/LfFwjNCODUPzQGC3uj0tqDb9Uco/l/jHD76rblQWbVbJ/YpiGaOZ3fSfr+T5e+n4XvVied7JevUYO50buJdMhNS2kyV130U8MWv4LV4gGPNH912FR20Df7g/gChLht+RZXRfyP1pqvLef7vxpvfGC+Zz2xjL6GCtTonmtYq9ATXHCS9o3pLQOYnuORHMXuKe8Bv8sVmCsfNxi+9f/cGA/zYRfV7xx7L03vclad3F04XSoaVqhVr9ctW507kZ0fdrItYpgzO4ZVVHtPahiM5RHN6xvx9QW//4m3j5/wXdryTHn05SLgAAAABJRU5ErkJggg=="/></a> +<a xlink:href="https://github.com/SessionHu" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="SessionHu"><image x="158" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/z0z0r4" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="z0z0r4"><image x="184" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/7rikka" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="7rikka"><image x="210" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/catlair" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="catlair"><image x="236" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/MineCreeper86" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="MineCreeper86"><image x="262" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/cxw620" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="cxw620"><image x="288" y="2" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAXcUlEQVRogcWaV3Bc95Xm8bCefV9Xjcfl3TfPemte5mHTeGTLkogciUQEkiBFBUpUGkm2TFlWskQFixJNyxIl0RIjSIAJJHLqnHNCB3QCOueARiORIH5bfenV1NTYW+MZj/dUfXUbt7qqv+//nXP+5/4vqqr+BNFS2/NXLdU9/e31e092N+yfaa/t97VX9+Y7avputz3Qfbuzui/fWd3n2/3gnpnehoGTrzz9Zt+ti9N/VfX/Mxrr93yzrXXfs011vYb2xn3saTlIV9MALQ92U3dfG7urexlof4z26l56GgfobzpIV91emn/YQeMP2+mo6WNf2yH9R29+8oxm2vTNPxvxw/ue/s/9nY/8qqmhZ+1H9zfT0XqAptp+Gh7cQ2vtXrqaDtLZeIC22r20PtQroL1mL911A3Q3HGBP/QE66/bTUbtPuN/X8nBFYPnlI6+dmB0Sf+ffjbhmXPsNl873nEnpXL1yaYKXfvwLmhp6qKvuoaG6l5b6fXRUiNfto7m6T7juaTkkiNldt4+Wyr1dfffENBygt/kQ/a2P0nh/B511ewVHOnb1rv3kkZffGD07+R//pORNYtv3TFK7VTVvQiExo1bakUvNTE8qefml93l44Hkaavuo/lEnjTV97G46QHvzQTqbDrK7fj/tDQOCuPb6/bTW9NP0UA8ND3QLONhzhOYHugQh/S0P01nbT9N9uy0vPfryf/2TkNeKzJ0aqXVVLbehlFsF8jqNE43KIYiQS6yc/fImP3nhGL3dT9BUv1dwRXCmtk9AxZ22xgFBSMWZiiMVZ3paH6HmB22011dSb0Com4ob/a2H2L2rp3Tf3+5q/7etvGrhoMXkvaPWLiBTWJArrShUNlQqGzrNAka9B5VyAZMxiFazyIXz4zx15OdU7+oWsKf7MO27D9HSPCAIqXmgi133d1D3oy6advUKNdPX8SitdX201PYKjaCzcT8ND3QKQh7vf3a7vabviX8VeYPCflincyLT2plVGJlTmlAZXWiNbkGITGJEpbCiUTqRyxwo5AuCiNk5Ex//5hIHDr7AfT9opa6+X0Bjw15amwbobD0koOJGS00/DTV7aGnoF0Q0Ve8RhHQ2D9BW30/N/buFv+se6Hjmj1t5maVTITVsKzRW5jUmxAYbUoMNkdqESGlErjKjUphRyMzoNR6mxlXotB4UcjtKtZNZkZGbY3Jeevk9vv+DJtraD9LV+Qj1NXuor+6mrWmfQLKjab8goLm+j9bGvcK1sbZHuFa+094yINxvaejfbq7v2/0vW/kZ3Xd1MvOKWm1lWqJhRqlnTmtmXmcRxFQEKNQWNCorKpkFp20ZhcyCVuViekqFSGJGprKhtwYZmZAxODRFV++j/O/v19PT/Qh93Y9T+6M2Ifdba3qFla6Q3N28/2u0NO6lqb6PuupudldENO2rCFpta9r33/6f5HWjyr9walxWncKCxbLIjFTLnNqIWGcRMK8yIpYbkClNKGRGZGIdGoVNgF7rYn5ei0xhRaq0oDV7kersTIl0TM9reO2ND6nZtZv66k727B6go66X7srq1vYKqfO1E037BDQ39FNf10Nz014a6nsFQbtbBswdrQe+8QcFBE2Bo26jF49zmWAwyYInhNkZwOwOYlrwo7N60JtcGAxONBobcqmB+Uk5aqkRjdKCTGZApbUJIiviZ+Q61CYnIpleEH3uzBUGeh+lubqd/e0H6KjZQ3t9H801PTTu6hbSp0JUQGM/rS37aWzoo652j+BGY11vxaEf/17yuUD6O8VIsRx0hSiv3CaVLFIsbpJIr5DIloimCoSiGZbCKZaXk3i9YRYcPuxGF1atA6lIjVikQibTIVMbmVfoUBntzMo0qA02FAoDOrUFlUjLL46+ReMPGuiq7RZc2F3XL6BSE5V0Emrld6vf0rxPuFbI1+3qouGhrtWW6p5v/zMBbPGrQqJEKpSF25CI5iitbFEobAhC8vl1MplVstmygHg8z1IwTjaWw+8MoJHr0OssKJQ6NHoLEqUWiUYvYEYsR60xolUZkc3K0Yu13Dp3jaf2H6Gr0kIf7KbpoW4qM1WlBipk/6+AigNtrQO0tx4QupXQqap7Pvwn5Je90W9mYoU1v2uZYrrMWmGLVCRHPlP+Gpl0SXClcq0gEsng84bJxfO4TU70Cj1BfwiT0YbdtYjWZEWi0aExWtCbbcyLZExPzmFRmbCqTGimZBjmtLzx/Nsc3vucsJlVWmnb7/K/QrySQrU13YILFQEVcRWR3c0HynsaB/5xAGSTZy06B3qlmY2VO2RiBUqFTdZKdyjmNilkN8imSqTiBdKJPKlEluVgiEWHk7Tfj1ksQTUzR9QXxGa0E4mmiKWLLMXz6M1u9KYFjMYFwSXZpBj1lBjLvBzjdEWEmtMnTnPkwDPsaaqkU++9wq7tp6XxAE2V8aPpIK0NB2iu3vu7gbEyGO5/6msBmUDe8PG7nxBajFIurFMqrLO+dpd4vMjWFoRCOdLJVZKxLNlkimRkCZNShNcoI6aXsCSbwTxxk0WVGqNETXw5TTy5QTy1jdObI5bcutelxmVYpBossxIsU1MsyiTYpWKschnS8Ul+9dZxar/fKAx6LQ/so7/tOZoffIS2msN0NDxBe/1jtNUdEES01PbqBPIrwZVvT1+e2fnyxFeUkivkU0XWyreFnM8V7pDKbJIrbJPNbhKPpMklEiy7rRjlk6Q8WqKaKTI6EXmbjpBRR8DsYMkdZnmpgN2ZJJHaIRzZwKjzYlCY8RltLIilmMZvYp+bwKWaQzJ6hUIoiGRsionL4xzsPEzbg3up/l89HGj/CW27DlP3wwO0VD9MZ+tjdLQ8TGtj305z/Z5vVS3rl/qPvXCMiYvjbOU2CPkj3N1GKNR8cZtkdpN88S5+f1JwYGt1FbdZg3L2BkGzmKRZRnFBy2ZoEbdKxqLJgtPsJJteE8SHo6uYTT5UchMWrQWfyYRXq2bJoCTvt5MJOgl7LNwcPIdiZhaL0ohWZBDq4uCeZ6m5bw+dDY/S1fQ4DQ/em6famvrpaN1HY11HT9XY6Vsnf/bYUawSCyuxAl6HD3buCYgny+RLO8STa9hsAbKpIvlkEqNiHo9RSsKrJ+bQUAwusBEPErAYWdDr0MqV+L1L5HOrrJW3WfQEcdnc2LQGdOJ5zJJZPBopUZeJTMiDZPomyvkZ9DI5epkavcKAaELOR8c+FYpbGMUb9wm10VDTRWNtFy0NPbQ27TlRdfLoRzPvPX+MJVOAXCV3lxKUVzZJJAok0+uCAxUBy8tZwQG7To9BPkcp7iXq0RNZtJIOeVly2VhyL2DWqdGplFiNBsqlVRw2OwqJFLNWi1Epx6ZREfEssGhUY9fIkE5PMD81ztnTn3H53DnmJ6dRyeRI52ToVUYGzwzz5OPPseuBJtqae+jb8zBNdd3UPrSbzrb9k1XHn30n8PFPPyRqWiK1GGU1VSL2u81qZRVCsRVBQCq1xnIgik2rY9GsZUE9x6kPXqelvobDjz3OKz89yuToLRasFsJBH0aNkmWfm+iSD7fdTMTnwWU24LGaWNBr+eyj4/zshX/gpRde5M3Xf8GLz/0D3Z1dDJ47z+itEexmExqVGovJypWh6xx96RW62nupr9n9Owd6K/BVnXz+/dyJF94j64jjVFgIe0Ikwimhz2dyW4TjJSKxErFIkYBnCV9lRSdv8pu3Xua1559EIVNz4dIIR468wCOHDvPFZ5+jVyqx6dT4FszYdXIBySUvAaediG8Rp8XC6U8+4benTt9b3Yca2d//MONj0/T37uXkyRMY9Fpu3RpBLpdisVgQzct459gH7O19hPaWfcJTX2PN3kzVx8+9v/XLI2+yGSgivjKJakZBKVemkF/HF0gRS60JAiKhPIsLPsxKFcdff5nnBrowSWdRK2389swo+wae4aGHmjl/dpCAe5G434tNLceqkuCz6tnKp0kvB0kEl3DbHMxOzAmbZja5wdNHjtLa3McXn5/j5sg4XV1dvPvuMdxuJ0qlHIlEgkFvwWb1MHjuJgf6n2XX/d20Nz22WfXZ88e3jj/5JnlzhLEvrzB26SbF1ArexRCpzAbL0SLL4QLx6ApOqxujXEFP/S6mBk+zlojidSeZmLLS0fkEA3uf5oNjJyjEM6wmEoQcVlwaOQGzjtxSkNv5PC6TlVw8x84mvHb0Hd79xafUPdTLk4+9xIfvnxLS9MyX5+no6MDpdOLz+dDrjaiUevRaJ1qVh7ERNW/8/BT1ux7erDrx2Ju5L144TlLj58qvz/LZex8T98dIxvJEYiv4gxmhjVZSSCXVoBdLeeXpw6jGhuHOJiePn+WNV7/g6Sde51fvn+bTDz6nlMgRtFrZSMZIe1xEbBaCZjPZwDJ+m5tyepWtlW3efuU4X/z6Mm8cPcHp31ziy1ODsA0SkZzLg0N4PF4KhRX8vmXMRrfwPC4TO5CJXIyPmPji1GSm6uShN/xfvfgRlmtybn06yFvPv4pyViGMDdF4iURqXShmuzXA7MQ8SX8Qr6HSx+WwUsCmdvP2K58yNixj8IurOFR2tnNlVkJhWF1hKxGjGPQTMJmIud3EXD7KiSLr6TKXvhjiwmfDTF2VcObUJXQyM7dLd0nHsoT8YcLLMWFsiYaShJayuBdiaNU+tOogek0YicTnqzrz9Acznxx+i+vvfoX22hzvvPAan310Co8zKLRRrz9FYWWHZHwVk9qMU2dgIxkh67FALs1aZIWPfv5r5q7M8+WHXxA0uSlHE9xOJlkNBbidCkMhSWnZT3F5mVwgSGEpzEY8y6LOgXJcgl1pY+j0IIVolmw4zUoyR2I5QSqaJhKMEo9kyWXWiYSLGA0BJNIFRCInY+PGyarB506c/PjQ63z+/PssTKj46Gfv8PqLr6LXWFkK5YQCjsZXyaTWsRscXD1zTiBT2Xk3Qz5I5Aio7IQNTtaCcVJON6yvcTcboxRaZCsZhHKanVyM7VSE24kI5YqweIztZIrNWIK4y03Y7qAcj7OeThNZ9JIORUmEYhQzK8L+Ew6lsNl8zIsNzIlNyFULiBSOE1VfPfFe3+kj7/LZs++gOD/GyVfeEwQYtDYMpkVhD1hwRQgv5wi4glw7e55yOMidqJ+YXsGm18tOMMSWLwD5HJvLftbDPjbjfnwGMdvZABRD3E76BVCIQjbETiwImQhkwmzGgmxEA2wmlom77azGoqSXl0gEQ6QiCdxOL8bKwYJCi6hSh2Y3C74IVvfSnqrfPnbsW2ee+eXOp0fe4vI7p/j1z9/nnZffwqR3CGdBEpkZk8VPOrlGIVlk9NIQHrWc4qKNDZ+VVaueskXHHY+d0oIeNnOsLdlhO8tqxMGdvI/bGQ9bSRdbcSfkK0KDEHNBwsNa0AgZDymHiu2UD59eyu1MlJjXRcjtwqrXo5DJkcuVaAxGbE4XS7EYy6nkjt3n/ZYwkX525G39B4++zKmX3ufTNz7k2NFfYFY70KjsKORWtGoHcoleGMZmro+wqFGRdllYDy5QdhnYCTnYXrZD2isQXFm2CuTv5io14BZAIchOysPd+AIkXdyNVL7vgYKXu0kHpYCR0pKV7UyIgFlDMrCIw6AVdnSZVIxKpcK+4CAYDpEtFkjm05qvnwfOvXrimQ+OvMrbh1/mt8c+4f2fvotkTIbXsoRBYUUt1mGQ6dGJlRilctTTU0IhZwILrEQXKETtlLOLbJdDrOd9ZMI21pIe2EhBKgAJPyQCkKqkTQByQXZyAe5m/bAa407MzXrESTnsoRT1wWqOtUxKIK+USpBKRDgcDmKxGMl0gtW1ErlC9sjXAl5/9MVv/uroe+VfvvgWT/Yc5si+p5i+Os+iOYheYkInMwoTokasQCOWIBobJR8JsZGNs5bysZH1spJyUUy4YDUCWylWfFasY1exXLuE88Ywi9ev4Lo+zMLoMAHZJHmPgbtpP+vLDu4mvJALcycdZi2+xFo6TtS/iEIyj1qlwGjUE4lEKBaLFAqFioByMpn8p+8Unuh97MTBrkPs+rt6dv2wiffe/pjlYEY4OtFprahVBmQSJXKxhLGRG/hcDigX2Qp7IbMM6SV2Il5IVj6HSclFzH30AfpTn7J47jzxK9eIDF3BM3ge/8gVijo5hDxshyt1ERIKeysREPJ/M5ciGw0JQ6HL6SAUClEqlSmvbVAolsiXVo7/s1MJucjwncbarvL3vvffeXDXbl559Zek87cRy02o9Q6kKgNimRqpTMH169eRiOfJR8MQD0Ns6R6iQYgE2HHaSExNYDt9mtTVG2xOzoJIzp0ZEbmRm2THx7ijV8Oy915aFULciXmFznU3nyAbChBadJFPp8ik0pRW11hb3yRTKJHMFkrJXPH3v576+4dafvo/flDH/fVdHPnxG8SLt5HqF5DqHcwpdYjVOiRKDdfHxrg4NCzM9yRjEF6CJT+EghCPQniZ21od0WsjFEfGWLs5weq1m2QuDRO/dJn8+BhYTZAMQ3QR0n7BQfJRiiEvypkJpkau43bYhZVf37hDYXWdeKZAIlt8seoPxd/83a5v3NfQZf7e/3yArkPPEC3dRb0QYN5gZ1ZlQGqwMCtXMT4v5osz57lx5So+tYqd5SDks5CIQKySDgkI+llTqchNTFIcn6Q0PiFgdW6WbZ0avM576Rb3QWZJSKG1yCJ2xTzXz3/F3NgtktEYuewKxdVNsitrJAtrptTKxh8+WqzEf/nb+777N39ft9L75IvE1sESiDOnszOvtiAz2hmblSJSaTk7OMyFi0Ncu3ieBZ2KUmWHTUVYjQeFYiQZgmUftx1mcNrvEQ4uQtgHMf894nEf5EJsRz3kPSYc0hmmrw4im5ogtrTE3Ts7pNIF8iubJAsbq8mVze9V/Uvi/ta97T9q6d0OZNZxR3NIdA7hoFahX+DG6BwqvZWrNya4ePka5y9eYPDSOaZnJ/AFnZRKSdZW4qxlQtzNhIS0EHbceAAqRR7xcCfm4U7KJ+zSWzEvKYcWm2icycGvGKsUud3GZqlMMp4hl1ujsLq9nSxstVb9MVHXvv/xWOEO0ewGMo0Dg8WLRGZiclKKXG5kbEzElevjXBy+xpmhQX57+QJDY1fR2dRk8hHWywlKST/lsIvt+OI/rnh2iZ38EoW4m/CiHvP8KB6lCLtkhtPH38UgFVNKpSmk8xTyZVbX7+4kMuVHq/41sRwvHUyk1u+YLD7kcjNSsQG91oF4XiNgeHiMi8MjXLh6nbNXhvly6CKXb1xGqpgm6LewWtnE1lJQTgp9fjvkEvp/1K7EYxRjUUxhk06zoJjHpZQzNTwkDHLlfEk4ASwUNrZjyZXDVf+WSMRKuwPeeEk8pxbGCYfVx8SoSHi5MTOl5PzZqwwOXmdo+AaDl4Y4d/Yrhi58iWz8Gl61iNsBJzuBBbbdZvI6KUviCdzzt1gQj2GTTOCQibDKJXiNRtwmM1vFVcqFNaKRzEruj02bPxSxSPavVXKTWauyolaYuTUyy8SYVHjEG7k6y9DFUS5duMH1oRtcuzTE8JkvuXX2c8SDX+GbHSM8N058bpzw7CjBqZv450YJymYIqKWYJfPCM0bI5SUZjrO5ukUuvWIKh7PfrfpThkFr+w9mk/O5mSl5SSTScOrUOaamFCgkViZHZFy7NM71y7e4fnmYGxfOMXnhS5TD5/HPjBGaHiU+M0ZifoK4aIpl8QQ+0QRO8TQmiYSQJ0AylCSbyK8lY/k34vHiX1T9e8XUrOzbSo31o/c//LR88pOzTE/pmJs2IJrTMTcrZ3x0gtErQ8xcGUQ9cpmIfI6IeJKYaIKEZEr47J4ZwTpxDe3ECHaNgUw8V05Gch9mkit/vn8AOX919JsnPj//9OUbYu34nGlHrHYI79Am58SMT95iauwK8zcv4paNsyi6hX/+Fj7RKM7ZEczTVzHP39yxKec1PufiU6l48T/92Yj/vhiXWP/yxrym59LYzInhiYmpCdGERyQay4knh7ccsrEtl+RmblEy6vGIb01ZZ6+fMM5e63Hq5v7yT/Hj/wfur5llOZ59lwAAAABJRU5ErkJggg=="/></a> +<a xlink:href="https://github.com/ProgramRipper" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="ProgramRipper"><image x="314" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/lb-chc" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="lb-chc"><image x="340" y="2" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE7klEQVRogdWa224bVRSGc0HLPZVaonJZKE+DWlUCtVdcIIoKhQuQgOZgxzmCGpK8ALQcWsQDgPIEhVaESNSJA3Fru8SJE9sz41NiO8qH1ngmnYxnxh577CaWljxxZu31//vw77X2zMBAAB/gVeAasAAsAv8C+VKpVBOTa+O3ReOeq+Iz8CI/wBngY+CRqqp0YsBD4Ka01U/grwHz1Wq13Clwu9VqtRIwB5zvJfBTwCe1eq0oQRVFCQS8amlLOgUIAy8HDf7ifX5avh37mifZJxTVYuAENFVjM7/Jwj/z3OPHv4A3ggJ/ZSIRKQ5HbzG2EmJ9Z52iWgqcQEEtkM6lmV6dZOjxl0wmIwXgcrfg342shesCPBQdYWIlQnwn3rMRSOfSfBWbYTQ6rHdWJBbeBz7oFPz18MoopgmB8ZUx4voI9IJAwSAwzUh06DCumCiVX/BXhP1xITAWC8lIXGoX/IWJZESzNtCKgHkt3+2YXcWUFgTEJhPjReDNVuBP/8y9ZacGWo2A+bcsRi9zkmClDQIS/3vuLImcexH4wquBdkZApFCAuFleyXc0AiEjPvCZG/jz2p5W6pSAVcenVid1IFabWZ1C30d2mvcRxQeBrd1NmUqDTgTm22nAjYBdx0UKR6NDhg0z4rGPKD4ISHxg1g7+TL1WL3dDwEnH7f5u+4jik8BB/aB0JAGUrNJPA90CCMIf+NBK4NEJJPCHCX5QVdWDdhtozOGiriamrsv18ynUW/+44S+YgXNC4JpbD4iTmFzLvJYGJBstaxU9oPg0TNMX5lZ+q+f+ccsIAu8IgQUrgRmHBsSkgchKmGgmynZ+m3Ru44i+S3CRSJHLXvmPNxOYEwKL5nyUoUxlkySyiSZLZVOsbceYW5tlenWqSedNrX+c+ZtnuWcksk8D9U9kEySzSXJK7nDdAL8Kgbh1ZxR2TlbRKmTymSM6Lz1lNwm+q+3q+0KQ/kXDrFjloEAI5FolY+Yi28ht6D3lpPOmSc9JcKdF2qm/4pIMAjsD5XK56qdiagBwVgkxGWqvnboTf9XFKpXK3skngI8plLZMAXcATz10vjN/xWsKAeut8nkJXtKaddoJgKiNLFjxCcq/4FJPmIt4sXU+v2HodFyXOq8ejG3H2M5n9AUbnH/asZ4wZXShnXze1GkzmBsAN43v1n/GoZ4wN7Kr7eXzjW8zuBWE9dp6b7D+t5rqCeBtIXCukcx55/P23nLrQTefbv1DtnriMJkzMtKHrbLRF22h5nT6gbUeuHkCCdw4UlLu1/dLrfLxfoIN+ykpDRJzbgSsC68fFnYgYSvqb/s6VjlOBDJ7WwXXx1PA561KuuWtZf5zyde7sVQ2pW9i1oLGKT7wqSN4g8CpX7i/5NxAoyKSYF75eqdW1sp6pebVgT9w90/Po8V2DndlIym0SLb8Wt6W7Hkc7l70BG8hcfkYHq+/1RZ4C4n3jwmBA+A9X+Dtj5ieE4j0hcCokcoYPX+9I/AWEpemkhMF81ik1wRmVqeQB4rTqQnN97TxIPH6Xb5bkky1lw/5NnObesp8h29FbS4EAt5C4iV50F3drxasVVFQBFRVZa+6Zz7oPh0oeBuRQeAbeT0g4FcNZvv6AojxssdHwO+Sm3cAXNTlgRyTA6/0DbgLmbNy0Gq8sPEbEJPTDjmyEZNr4zf5n9wj954NIvj/Grim/OotgoEAAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/zjkwdy" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="zjkwdy"><image x="366" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/pskdje" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="pskdje"><image x="392" y="2" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEQklEQVRogdWaXW8bRRSGcwHlnkotUbkslF+DWlUCtVdcIIqAwAVIfDSlAakBIUrSPwPKXdI0CW1FASeBSk2AIjXE9dfs2g61186Dzu4mHtu7m5n1NmQtHe3InvG+z5zZMzNndmwsgw/wAnARuAHMAQ+AaqPRaItJOfxuLqxzQdqM/Z8f4DjwPnC3Vquhm1Jq/6qXB+sBd4AJ+a/DFP4iMNtue02lXIatX/wghFJOWG/v6uJ5nQYwA5x6msKfBT5oPXHrlfIWcVarVRM9UCn/E9v236ZqAlPAc1mLPwP8Ijf//fYsa0vXWF/+mvWlr4as/PghyqlHALiYtgd+Bl7OSvx5z/PqgYAt1m5d49f5TyksTFJYuNyz+cBKxb8SAMzbdzqeC5wbVfwb9Xrd0wVIL8nNV29eZfXm50NWPgDApr3ruh3g7bTiL8ULuDx048LCFd/MAOzaAxO24s8L/VEBcANPnDUVf7rb7TrDIdBMQKn4ZyigqsV8iUwOldIjbQiZAyilkOcQeOUg8cck2kTHcMMefPw3jrvTF+el7DgNqpXtVB5QvaF0T8J5EsAng41sAYpb96lWin5v78f40iNffGl7k/Wl6VQeUD2Ij+LEn2q3241RAURgVHwPbHq/bloALxhK41EAs1ENTAB0Qb34rsd5/bsrkRAFQ4DQC9cHxR9vtVrNtAC6gKjYHlU3rQeUUshI6VsAyqoyrrIpwKhWsAAIvfCuDnA3hwC398SPK6V28waglNoFTgrAxQMqHlUAgNcF4EaOAWYEYC7HAN8LwGaOAR4IQCXHAKWxZrPZyivAzs7Ok/wDkGoIDa8ms4Io2w4hYMMOYJrC/Gf7PZadTfqW5iG2CqO/rXzjb8jXFr9kdfGLzK1cfGgdRg0nMrlWKW3/QWl7w9+cBNdsrVat9N3TZCK7cFDFvj906v72MLhmY0ovG4oPAV4TgJNmi7nh5OzTMmUGESzmwhXpHRPio2TAir4fmMghwDt9W8q4Db2J2Q4xwyGC8ZYyhJgZpUeS8v96fmhU8Sro/W+t0io2HkjK/8tvUecHysI6nY4bezwFfJwewOnl/28N5P+Xg5yQTIIyj5hOVCq69z+MFK+dwtxLB5CU/5/0lx8yg8tkJfNIGgDgp8TUYlxy19wDW37PD+f/r/rrHVl+yAyexgNekJE7kyhegzinp9dtPJCU+JK1TuABOwA3SK+/aiReg3jriADsAm9aiR88YrICWI4+QuoNoQ3jIeQGPX8plXgN4qyErtH3C5OsLk4Ze6Db7TrWwyYB4qWk6KSH0aj9QlCe8iOUyUNMEG1OZyJeg3hGDrqjvGG+X9ikVi33tVGaSYY8POg+lqn4AZBx4LvBWTtpv6C0a5T4drC2uX6oL4CEL3u8B/y4t5+wWcyF0WVF0uTA84cmPAbmhCRawxc2fgDuS7ZDUjZiUg6/k9+kjtQ9kcXN/wN11iQCR5YLiAAAAABJRU5ErkJggg=="/></a> +<a xlink:href="https://github.com/sheep-realms" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="sheep-realms"><image x="418" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Jannchie" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Jannchie"><image x="444" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Kataick" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Kataick"><image x="470" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/SpaceXC" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="SpaceXC"><image x="496" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/XiaoMiku01" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="XiaoMiku01"><image x="522" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/kuresaru" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="kuresaru"><image x="548" y="2" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAYCklEQVRogcWad3Cj95nf+Ud8+T+eOZ/HyUz+cOIkN+PEl7m7OMnlLNuST7bKSitptVptk3a12qLVFq12pS3UNmk7eydIAiBIAiAJAiQBgiAJgui9EJUAe+8N7OWTIXSjm5uzM+c7nfPMPPMCf+H7ecrvfd7nRVrat2Bj+s4/mTYa31k0m7JGmpu1oyplfEbdNDcsl22OyRWbo7KGuT5JbTxcJtUGy+qzwmL1Qb+g8U/S/n/arM/13WmP4/yM2+kcNRhYsDsYb+9gXKtlqkXDcmc7/VIp0QoxCbGUeKWMUIWM7rJ6/BWNeMsasRcpHMb8uo86c+Xf/YMJn7Ka/+20y54563OtzPrdzHhcTLscrHQHGOvUM2XQM2foYKmrk3ClmEBZBdHKGnqq6wlXKvALFbiFKpxlKmyljXQVNtCR35DU5cgzNFk1P/gXEz7e3vGdUX3Hx2NGw/KUzcKM18lcwMNcwM9iKMiC38uSz8Os1cSizcSwuhF/pZB+hYK+ugZ65EpC1Uq84gacIhW2ciVdpUo6ipvQFTWhLWigOa9uRZUt/aI+q/pff6vi503GH00Z9L5RfRvDnW2MmvRMOswpiCGblXG3i159O1uJGNM2E0suO6HaGhINdcx0dDDQ1Ey3tA6PpA5PlRJHVRPmCiXtpQp0Ag0tJRrURc0oC1Qo8hqoza33ynLq/uO3Ij5ps+1ftFmWZ01djOvbGW5vZUivS0GM28xEdK0kOvX4VCpWuv0pgAW7iahCzryxkwVjJ/2NKjyVVThFNXiqFDirGzGJGugoV6Irb0EtaKWppAVlsZrawkZkBY1I81VL1QWq1/5Z4hftlmPLDtvWssPGos3CtNHAmEHHcGcro11tjFsM9HXoGTaaGNi7trcxbzUz0aZlTNvEht3MoqGd4ca98pHir5YTkCpTEDaRAqOoEW15C00VbajKWlGUtiAvUVNTtOctVBVptkUFzR/+08S77KeSe83pcrDqdqaue7U9Y+5k0tTBlFmfqvek28O6z89Od4iwTMqa1cyAQsaSXsemWc+qoZ0pTRODinr665XEZA14K+U4hXLskkZahRqaha00lreiEGi+BijRIClupbKkFUG+htICzUe/n3iPc/+y27W97Haxsife7WTJbmbGqGe6q4M5a2fK9z6vWK2s22ysW6zgsuMrysebnwERPzsGLes6NVMKOf6CPAblUhI1MhLSeiwFAoK1zbQLG2gVa9CKW1IginIt0tKWlHhhsQ6hoIOK0vbt0hLdvn+c+IDvh4te9+KS103S42bF62LG1JUSu5eBFZeFBauBObOeJauB+TYdW8YusFkgGmROUUO8JBv0aiarBAwIckkUZdF19wbRknzCpcV0CwTYcvNxlgkxiWvprFTRVtmEVqSmUaihtqwFSamWihLdnnhKSzsoKWlfLixp+0//T/HJaOiPlkPdvqVuP8t+L8s+DwsOKyNtrYy1a1n32iHkZcVhYtGiZ9NpZtPYyVaHjil5FQsN1fTkP8acfpnBosf0ZN9jrCyTyco8fE/SGRUVMSgqIVZWSFwowFVSQEAmx1lTj0lSR1tFPc1lDdSVNVJTpkVS1k6Z4GuAIkEnhYJ2T0Fp23d+J8BqT+zaajRMMhxkqdvHotedOjZH9FpmTR1s+p0pgA2PlRWHkW2niV2jjkVlDc4H6VjuXMV04zy6S8cJP77GhOAB63XF7DQJmRBmsNYkZrlJwmSdiNU2Jb3SMgaUcnqUdQTr6rFUydGWy1CW1lFX3oKsspOKcj2CCgMl5V0UlRvIL+/85LeKX+vp+cF6Ip7ciMfYg1gMeJl3O0lom5m1daXEb/gcbHpt7PgcbHn26r49JWZUnIf70ecEnt6kv/AePdk3GBfcY0ORS1KWxaI0k5mqp6w1C1jTVrKoEYNDw5xawmhDBRMaKZOtKvrUTbhqlbSKFKiETchF7VSJu6gQmxCIzRQJzeRXGJdzy/Xf/wcA64l45kZvgs1EIgUw73Mz7TAz2NHK6l7kY4FUCa05TCmAbbeZZX0TI9IixiQ5DJY9ZqLyKcn6POZrnjAvecC6IoNNZRZj5emsqPLY0ApYb6sgqatgx1rHvFbIWG0+06py5ltrmW5roletwVGrplnUjLRUTY3EhEhioazSRpHYQq7QSFaF4enfj35v33fX470rKYC+3hTArMeZOueXfS62wj62Q55UBvYiv+crlg5mtfXMN4mYayhiUVnIXF0Ws7KnLNY+ZkH2gOW6h6ArIF5wCYwVYBSybRKz1iVivk3AbEsRsw25TNRkkBBmEJMUE5RLcclV6CqbkAvUVIs6/zYDVgpFFnKEJrKEXcmM8s6/GwC3E/3nNxN9bPX2s9nbTzIaYcrlYMjYCQMJtkM+1jw2tv0OCDrZcnUx19nIuLqaWbWQ2cYS1vWVLLcKmFVls6YrYlNXyIY2jyXVM4x3j4KxjN2uMnbMIrYtIqbV+Sxoi1nXFDFYdhfL/Y/puHsFa94zXJUSTFUqGiuakJRrKRN2UigykysykyM2ky3agzCe/QaAaMJJvJ/dvkEYGWMpFKHfYGSzJw7RGDvBAAS9ELCxYW9n1aph0aRkXCtirk3CuqmWJaOUpFXGvKmSqfZS1iwSFttKWdQWYvzqJBgqWNcWstMhAKuEZFsR6+0CpmueEnp6heCTT1F9dBj52eOob98kIFXQWFRFXaUWYbWBwmoL2VVWssRWskWpUrJ/LT4Q/T6JgV36htjpHWBneIwhm5Nxhwf6h1IAJOKp0ydpamFB38CaVcmqQ8m8oZp1Uz2rXbWsWhQsW2uZMogJ1T6DuI6kUULHV6fZbK9gq7Us1QdYpEzWPGBZk8d07VPGKx8Rzfwc952PaLtwjKL9v6Li/SO0PnmGUaKgrrIZYbWeghoLmdVWsiQOcsRW8sstu0Vlpu+lbfgD79A/AINDrO31wOgI3lYti7EYjAxDXwJG+sBnY7hRwphaxJq1gW23km2HAswKNttrwNnImnmvESuwFd2EQBOTjQWYH35MNP8G89JMxsruMyl+yIz0CUuNucRL0lON35OTTueV99Bdep/MX/+MjNdfpezCZSw1KuolakQ1nRRKrWTV2L4BKKiwUlBuOpCW9PmyGOhnd2iQ5b44W5OjWJuVbI0Nsz3cB6N90B9h3tBEXFbEZHMF62YZOw45eBrY0UmgrRoczax3VDHVVIy3KJ2o6Eu8+ddTzR3K+pyh4nv05X9B9+PLxPJvMFB2j3jJHYbKnxDMSEd74TiNp9+l5M2Xydy/j5yTH9KUL0Ip0aYAimQ2sqV2squcZFfayBNaKRCaM9IWAx7tZm+M9YEES/0xNqdHcLWrYWaU1d4wTA6w4tTTpyhnoLaARa2Idb2IzS4h2KSs1+VDWw3o5czX5dEvfshA9RMUVw5j+nIv+l9AVz2O2+fxffUJgYefIjj4S5ouHsF092Os969gun2RzmtnqDn6FqLDb/Hk1VfIfv80JTcfpgAqawzfAGRVu8iR2MkT28gXW9Rpy0F/71I4wGp/jOWBHpZHeok6DDA7zGpfEIZjDDbXEBZnM6koYamphFVNIdvtxaArZb78AbRUsVFbyIjgK1zPrjBRm03jZ8exPr6M4YtzDJU9xpp+IeXmLy6gvvI+0jMHqb94FNm5wygvnqTr1mXEh9+k+M193HnhBfJOnCHzwk1UVa1IpF0Uy+3kyBxk17hTWciT2MkXW+Npa5HA7HzAxXp/lJXBHiYiXka6nWxP9MNIjM2gnZCkgIQ4myWlgJmqJyTrMqCthPW6pww9vQb1xcxWPGG49Es6vjhNuPQeicqnGB5eol+UQctnp3A8uIb57mVaPj9LqPgRVeeO0HzzPHWXTyH96D2aL52m+v13yHjpBR698golZy6QfSmdpmodVTIjJbUOcuVOsqTuVBZyqxx7ENNpO5HgxoLXwe5gPAXR7zQxFXazNRRPlc+iVUewLJux6kJWFQKGC9JZrX4IHeWsVH5JMP0Mq5UZjJd+xUTVM9Q3TtD24AK7rkYabp1KlV1MmInk3CFqLhyn+tIJ7r/xPKd/+qdIPzuLMeMO0osnKD/+FrIzx3j2m+cpe+84lZevUnD1Dk3VWmpkRkrltm8AMmtc5HwNsZ5G0L+xE/SxGelmoyfEak+YZCzAZm8EhuMMNcpZ0TUwLs5nVphF7+NPSZbdh7pstiSP0H90gPHiL/E9ucqYLJvaz4/TcO80RDvYDGipunkKggZG1FUIPz1J3tlD3H33N5z82X/jyE//My2PrmN4ms5XLz+H7Nxxnr70AtKPzpF17H3Kbn5Ji0xHdbWewmpTCiC33p/yHKlnD2I9Db9vloCX7WAgBZGMdLMcDrAZD8NggsVOHau6RhL5TxjOe0j0zmU2Rc9YKr7DUul97NdP0nT2bRxPrrBra0CefoLCKwfZSnTCmIuBTikRjYjduI3dXgeyx59x6tf/gwtv/pK3fvoj7rz7Iqa8u9RePUXh4Vd5/PLPKTx8gMxjx8g4f4U2uQ6ZvJNSmZm8WldKfFZdgCypl4xq53Qa3kACr4/dQDebwW6WgwEWgz7WY2HoT7DtsoHbjvHWVcIPb+O7dYnBxzeYzE4n/vATjNdOUnPydYyPP6Er9waXXv3vnN//F8QtUpj2wXKUuWgnTARgOoKrWcw7z/8ZJ177GY8+OYpDlsNMlwxrbjrFx19Bc+MchUf2k3H0ECXXbqCTaqiTd1JWayW/zk12fTfZ9SFyaoNk1/riaXgCWjw+8Hez2R1MAcx3+1iJhFI3sR2/Dwb7ab5yGfOta1g+u0jDsTcZzrpL1+UTdH52CsWFI1ReOMTZX/wXDvz033H8pf+KUnSftUkXc30m2ByEtUFWht3szES5fu4A77z8P3l68wPGnA3Qo2dEXUq34D64Wmi9c5mn7x4g5+IlmsUKamV6KurtFNR7yFEEyVVFyVfFyG2IqNPw+LP2APYysBEKpZZU091+5iMh9qbT7WgUIjECxSWoP/0E5fkPKX7jJazpl2n+6CiWu5cRfvAGGUd/w4c//1PO7vtzzhz8KyqLrrO5GIT1PrYXwpDsZXnEzcZUCJ2iCIdeitdQTWPxdTbCajY89cy27s1J9XQ+vEL+B+9SfuNzmiqk1Ms7qFS5KGrwfQ2gjKU8WxHJSMPpOYjbx5a/m/VwhLlwmLGAn4lgiPmeWGpCHdN3seX2orl9m/ITx2j45BzSM8dRfHwS1aUPkJx5F9XtCzw+9RoH/uqHHNv3FzTLnrGxFIKNPmaHbbCcgJ0xdhbjmFpEtKtKKXl6Cbsqk7WIkhW3lBWTmP7qJ4jPHeDZkX1I7txCWVZJQ10HUo2f0uZgCiCzIUZWfZSnsuBbaTsWx/e2HO7dvdVIMhxmKhxiwOej3+9nJBhiJhxj0GhmN9JDsEZK6ZnTuApykH96gfIPDlN0aB+qT8/S+vBzKm+d5cy+n3Lx+N+gqnrCWL+R1ZnulM/129iZi8DOBGvTIVanQ5CMMdfTzFJIzopHwoZdTFBwi5zDv+Dem89z4+B+qnMLkUs1SFu8CNShvbIhWxUnqyGx+0Qe/l5qIl2xOxxJn4+lcCgV+V6vl6jbT68/RMzmYTkxxJDRxrI/gPj6dbziCoz5WTx8+zXyD+2n6txxHr31Iq2ZX+BtKEVekE7ps08IuxqZHfWwuRRndsjD2sxeKfWzNtHN6rgP5gIs97aQjChYtknofHyaonf/mkcv/TlV549yfd+LlD18QLVQTk2zhTK1j/zGEAWaAQrUI9a/W6U4bR9NOW2MOh0MeXz0eYP0eCNEXWH6u3sJW3wMe0IM2d3EdDqasjOZdZhwlBeRd+QQ2Qf2U/LBESounaQ9/z4doqesjXphpZ+N5CAww8JsguR8gt3FPpiPwnKcpWg7CxEtC24FgYqvuP/LHyN86zkqDzxP/el3yDr0KoVXL1BfKaa6QUNZs5niliDZTTHy1MNnvgGYtHd9d9xhSY663Qz7ggz4o8S9MSLuKEF7hIAlQMIVpsfqZtjhJqJrSS13Gx7eI/fIu+hu30R66SzXXvhf2EuesOLrgLk4C/1ulmd6mJ6IMT4SYnttBHamWB60w2wAZvZOOx2D7WLyjrzIved+TOXrv6T4b/43bZdOobhyhtLPL6KsElGjakLQbKBQ7SNTFUrma4b+/juFSbcjY8LnYzQQZjAQo8fTQ9gZo9sZxWfxE3F0E7G46Lc7SXQZcCnkVKZ/Rsfjr4hXFJN9cB+f/PVPyD6+D4Z9MB2FpUHYmIStWXZXxpgbCrAzF2dlD2DGz0q0lSl3HeNdEm79+s8oevuXNJ46iGDfC5hvX0v1Wcmtz1HWSKlq1FGqNlPQ7CVTGXzyD7YS892+H0x0B5Ij/hD9vr3yiRJwRIh4E3hMXkI2f6offG0dWOrr0ZQUY6woZbSxFvHpIxS++xof/vjf8+j152h/dBX6PTDXS7LHyc5UAlYnWBz0w/oIrPZBMsKEU06io5QVvwLhx28gOPYyjeePUvXeQfz52dTcuE7xvS+pr1UiUXdSpnVRog0t5ShDv/311LDbe7XfFSDmChF2Rb6Ovi2Cy+QnZO+m2+TErm7FomrEXFdHT4uaxtvXePjyz8na/wJf/OIn5L39POUnXsdb/IhgVQGM7M1UUUiOw0wcFuIkE13MBpoZs1fTry8i6ZFiKfiMR/v/D2Xvv0nFyaMERWJMQgnFT3OpU7YhabEi6ggi7EhcTvtd1udwfidm83jC9sDXAO4YDlMAvzOS+m7UGLBoOggazHTrDTRkZ3L9N8/R+eU1bv3sJxQe/BWlh17E++wGRYdeoujEW1x/6ecIr18g1CxjzNHGlF/HasLIkF1GXF/MnEfCvF3EeGsJFRcO0ph+CcmVixhLy3E2tSEskVKvsSHWehDqY25J1+DvXi3uWY8z8MOwI7jY7QwTcEXxOaIEXD34HGE61QZcBjsevYlAl5mb77/Hs/cOEhXnkHvwRR68+JdY7l7ClP4xNR+8zYOXnuPOy8+Tc+oIjz84zLVDL5N+4lXCbWL6zFUMWIQs+atYC9Sw5q0lUpfHqE6Bp6YafaUcXV0r0lo9Dfow5Rrfcnlbz4/S/jEWcYdfCzgi2y57kKCvD5spgN3cjd3opccXo0ujp9vi5up7x6l/kI5fmMOjN59H9vHR1ENLw0eHqTt7lIx9v0J1/VMqr3xM5pnjyB7dpE34DBbCTAebmQrUMmEtZSdez5KrhjmHip24l9WeGAGDk0ZFBwqNhwZT77ZAHXwl7fexbnfsg25vLzZLEL+3l65ODx5HNAXh6HJj19u4euoMlmoR8UYpRWePUHftDMpPP6T43dcoPvQ6TZ9dpin9OpVXL6F6ep+eNiUxfX3qHsB6jOlQPQt+CVs9ClaCSmY8aqa8JpYHBxnpGcXh7KVO272r9UyfSPunmMcVO2a1BLc87jidejcuRxSzwYu5y43T7OXBzbsE9t6Zmdr47I2XEFz8kIcHXqHm4hkk50/TXSGg+Nw5wg11zHrsbA3H2B4Pw8YgzPthI8zWQDObvY0kIxrmI3rmEj6WxsaYmVxicGxjOzCweSrtn2M2a2ifzRFbatd7sDt76DJ4/xYmglhQjafLQq/dRsntL7j21hsUXjyH7PZNbOUCrOXlbO9t9xbmYWMVFqcYChhZnwzCagJmXTBhZD2hYSbUzLBfx2jMzWAixvDw9OLgxPrvVza/y8y2yH/Qd/k8dlccgymErsOdglE3GzF0WPFZPNy+dJVP3zvB3dNncNY3MOfvhrlFWN+C5ApsbcHmKtODEbYX+1NZmE60w6IXJq1sjNmYiJmYG4szNTnuXlje/GHat2lGS+Rf2b39HxttPUs6g58uW5S2rgCdljCt7S4eP8ylILOQksx8OpUt9LiDsLUX9EXYAXZhfW0ZWCU518dErx2WoqyNWNiZcMJChLG4dWV9cfyLza3VP0r7lzKTs/f7HebIszZjKNlujqIxxtC7+rG4+yktr0cu1yCsqEHd3I5K1crY1DLJLdhgz/dINpmfHWBi0MPSmIf5PhMbE54kq4NPh2P2P9wfQFq7Qt/VmnvOKTp7bHrf1G55vZlHedWcvnSbQlEtgmolda1GaluNNBkdJKYXmFpdZWsvLSSB2d3BcJd1Zy5ydme+59/8wYT/Nnsm1v/xw5LGA7cyxBnpT0o1x85fj37+OG9W1mbZeFYh22i2+2Y1Nm9UIK/V9I4NZmxsLRxgd+6Pv40f/7+rvQLLFVKCMwAAAABJRU5ErkJggg=="/></a> +<a xlink:href="https://github.com/mckuhei" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="mckuhei"><image x="574" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/thefatwhale" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="thefatwhale"><image x="600" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/LightQuanta" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="LightQuanta"><image x="626" y="2" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAADv0lEQVRogdVayW4TQRB9TrzEzjKOnbAoHIHwNSgREghOHBBBQMIBJDjyASzhZ4LyBWwKcEQKfAEiUkKQWKI0eqMuq9LuWWyPx+OWnma6u7r7VXVN9WID2aQzAG4AeAVgG8AugD0Afy32bNm2lblu24w0tQFsAPgAwPSJ9wDWbV+5pXMANgH8GoC4i0MALwEsDZN4BcADAD8zJG4c0ChPAdSyJr8M4PMQiRsHnwBczIr8lSFb3UTgAMDqoORvAvg3AvLG4gjAnX7Jr42QuHHASNWz2xwVgLhRM7GSlvx5APsFIG0c8Du8lES+mnO0MT3iow3nkelJAUiaBDyKIr9kV8RREzQpXOmsT4HNApAzKfHcJd/OeG8zbBy6G8CNApAyPeKeVmCQLfGo8E7I84M4dgVKpVKIqA4mJia6ZCQf107LlJSsfvrqPSDn07AnKe9Ak5OTkR2wvFwuh4qIQswLopTWMmULMYavjohR4hrsEa+rkuQXFhbM7Oxsl5WIqampsL5arYb5er0e5jVmZmY6ChLT09Oduna73XmyXPpbXFwMIXWtVstUKpWu8S14CArPqV5rzc/Ph6Aybh3JsXOtQBAEoSzBcirP9iIjs8r2fNbrddNsNjszLeUELc/+Go3GCSM42KIC36IUmJubC0lwIN0JCbGOg7sKaL9lG9ZTzrUe80EQdFlX2tdqNa/xHPCiAD/iFGAHfOoBSIgDyFMUYN73wYpiuox9NhoNLzGOKbOZEIm+U4E/cQrIYEJULCou5irgi0oko2eQ/u6bFSgDsb+4aGbxO5UC7Eze+cHRcnzX/h03A5qs9Cvt4CCl65xQINaF5J0fLC0niogCegYoo63GdlRY+mEdP34xACLGlO8iBUIX+pqkAAfjoBJWpcznQuIqJME828i6QAMwNEokKqnFinmJOj0sZruxYVTISp4D6KnXUUimnjIsp/JUSi+GLNMyQRCE4CwRrNPlghh32opcyMTKcXnXitrvk9pGbSGQznVOLGS8aDXDRhK5Un8KXIXdEHVt5sYAx7KZg70lNmOGN/o8sF4AQqZH3HWPlONwoDdRR0rYL9qMCZ6N87XKQdzPU48LQNAk4CFiUsVe35mCYifparHol7vLSJlWC3i9fhk9ptsFIG7sinsLY/wT0xoGTCs2dOVNfr8ft4lKF3KOTjs2mGSayvaH7oMcfuiuYoiJd6kvMl61D+2df65/AOFm6j6At32eJ9iGW2Jek7fyJO5Lp+xFKzeErwF8sbcdvLIh+M4y1lGGsmwzcPoPnxAjIe6ItGMAAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/mzhsy1" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="mzhsy1"><image x="652" y="2" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE6UlEQVRogdVaTW8bRRjOgZY7lVqicgyUX4NaVQK1px4QRUDgABIcOUMTx5WSigt/ogIUIWInDgpNROCABKjOB03An7s7+2GTtZ086F3Pltnx7Leb2pEe7crZd+Z5ZnfeeebdnZkZwx+AlwHcBlAEsArgMQDdcZwegc75b6v8mlsUM/M8/wBcAvAhgB3DMMAYAx2TwL8WwDaAeWrrPIm/AmDJdd0OEfHhE2PMjIF4LfPQ6/UcAAUAV58l8QsAPur3+7bYuUiIjm29jrZe48dRGIauFMEYAw0KgM8BvDhu8tcA/Cp3GBRgegS3Dr9GZX8Zm/sPAqjsr+DHg69Q1/6CyWylAMYB4BcAr42L/E3VqKsF1DzyP1S/QKm6gLXqPQ/+eXlvCbX2QawAxhgGg4EF4EZe8nds2+5HdSTfARptIkxky3uFpyhVF7G+dx/1hAIYY7AsawDg3azk78Z1ECZgONoFpYCkd4AFH6n5tORvkvpJEWAN78T1pOTnTk9PzaQ5fQjKLCZa3hxIIsDyYowUfdA8BPB6HPmLlG2ogzQg8jSqmt6IvQOUhSyzw2OsVACwS+k8SsBn9BjQSFJGaaVAW2+g3j700uVwEqsEFHHc+hOa0UzZdo0f6yTikzDyV/91bYfy+AbP40QmOYbX+2RVAuhYydD2prCOOCdtepRmVQKW/Dy+Vv3SG8VsWBwRIf6Wtd01YR0BsCCTv9Tr9TtReTwNou5AnjbX+Toy6J85AQNIrjIuDT5vlKQ0DOB9UcDOFAp45JOfZYydjVqB9I9I0sckS3xJEkCcAVwhAbfFlVRciPxGZcgk5PM4pI0vh6zkAN4iAcWggJWJE1Di2YvWEUlAgQSs/r8h0dHUjtDQnoygqR3jn/ZjL82GLVSEo9bvaGp/jz2+4eEIuqGJW9JvScCeuEMaLtu2BMtb/jW9GTpHfALUuW12pXbyxttPIXKlQgEJ0OI35aJZC7cKBBqpUbOWN94IKwq0ZjqdjpvELlOjyQkE7XLeeBaCbrd7Mv0CMO2PEICqODFUPp1+s5jjWeZK7CQ8HvH7eeNNoR3VJF6V6zqq/UASv0+gVEnZpjXG+LawHxDrSn4aDSxk4fuBeL9PCPf72eM3Q+pK/kJ2S67rRO8H4lbS7PuFckS8qq4E4E0ScEVt5pYm0szVZTPHHen2FNrpLXE/MD+FAt4LbCn7/YETV5hK09mziF/nAka2lFxEIUxAcFOe3S5njS9LAgDcU5ZVuq7lTLoAx21Zoa+nAHwaXVkr4knztwi/X40tbOWLv0+j/7GSPBdwwcL3u1GlQepM6fdZB5rRii0t5oln+ObnyNIiFzG33Vg2o7OAyqyxHMVdPTb+UW2ZUs+1SPKCiBsbB8VBVBqT7XKe8roRE09cALyRiLwg4p0JEXAG4O1U5AURdyqHxX5aAlGTME38xnDk72YiL4i4vl1fsVRlDRUBvyyTpCzCIuJ3Gg/M1I9NhIhXDTzcJadKnj6KAFleMoI02kEUkTTewEPKNnNjIS+IeMF70T3oWcEdnPiiW/f8Oo0yucaaBCIv1nWYFO+6J/6L7otjJS8JmQWwSJ8HjL7oY8paTlhdhwU/NVg41w9A+MceHwD4abifSPexB/fzW1QmB/DSuREPEXOZCq38g43vAPxB1Q4q2RDonP9G/6Nr6NrL4+j8Pwe6VQrqtzNaAAAAAElFTkSuQmCC"/></a> +<a xlink:href="https://github.com/jiudays" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="jiudays"><image x="678" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/MoshiCoCo" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="MoshiCoCo"><image x="704" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/HankTheSniper" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="HankTheSniper"><image x="730" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Miuzarte" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Miuzarte"><image x="756" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Nemo2011" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Nemo2011"><image x="782" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/stmtc233" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="stmtc233"><image x="808" y="2" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE3ElEQVRogdVaXY/TRhTdh5a+Fwm6oo9b6K+pQEit4ImHqlSlwAOV6GPfIdlNEHFIgzYIif4DqvSxAkFBfKhSJWBpHGeXkk3WH7GTiNjZPdUdO4md9cc46yS7ka4cOZ6Zc2bu3Dn3OgsLCXwAfAbgLIAMgDKANQBKu902yei7c6/sPHOG2izM8wPgMIBLAJ5qmoZJDMATABepr1kC/xzASq/X60wKfNxM02wDWAZwbJrAPwZw2TJNgwZVVTUR8JqrL5oUAL8A+CRp8CfwoPyyercAuSZB043kCbRaUDbrkH5bBR6UXwA4nhT405ulm0ZFSEEsZCBLIjRjSgTqdVRXc6jkrqFRyukATu0V/LlaMWuJhRVUbi1DvH0DslSd6gpU7+RRyafZZEnFbB/A95OCP0/AB8YIFImAOAMCqeG4ZBSp4oI/Tez3CwHJXomTvOCXmndyLXcH8yYgFlawWcoZAL6MAn8ID/946dfBvAlUbi0Df95/TuE8jMDPYR3Mm4BYvEH74acg8Md6ht7e7wQ+bDXIlRb9CKzwdDBvArIk0iqkxsEfNi2rc1AIWNs7bY8AJFUZp4N5E9B08iJccBN4egAJ/DUAv6hp2s7uozysAx2qorCBkzKNaaH3nOMbRHwHwFEicNY7A8JwBqgRa+jugNRou2PPXquVnBkGlMamZwV2j5/1eACAb4hAxqMGSwJs5TnqgBnNSjGL5tprqM0mmy0inIjV3zPwNDnVUi50/DECy0SgPPBnVVUgv9uAvFGDvLHuXGuQ12vs/lblLaR7t9kgNFOJWymH5ptXUP57Z485GH+IZR2qIg/3DYD7RODf4UYit9B128c8pjO3UZsNR69fZzNCS52Mpe2rkGLgW51uAA7m+0OsVCggAvJoBQI2maJEbrKkTF6vRQYJ1wo0FzqdTo8vzOk2AdojUyBQcXydXIU3THe73Q8HnwAAmZ9A8DmxK2Zz3BN9nqGNykuAuRCAt7FXQEh5Q9yYjQN23wu1fDrWCgw2cTnWUX+3APHXDEvw6WDzWjZ6BeiZYkDbYjbuCrAwmuEiQFdFYYcNHSZUnbCvjtUkbK29tsNsoBTIovHP33ZMd7eVRuaO8xwE2EF2hltwsXPCYMe+/znRjBZjGzW0unxxXosm8DUROMrEHM8KhJ0TmuacEyMtNakY1PhI2GLOUaRPeBhz7ZEZyXEAj9z5wMUDSOAHb0ppmu2JXcij56fvQqZdjve+U6AdzbWJY+h5XwJR+YQW7f8ArvuWVYJWwT0rtn4P0/NCaBjdCssn6nUm6cNI9Pt9PfD1FICrPPV7ivVeLS84el6IPMhGbYXdfZQElncwFwsgAOCKL3jXW5jnoVJi9WZIPpCOlhJB7fJ2PhAmJQA8Cy0tOiSWtre3W/MQcyLlAwFSwrIsKkWcCAXvInFK1/X+fpHTuq5Tef0rLvAuEt/tEwI7AL6NBd5F4pxhGFZcF9oLCdnlQs7Mn58IvIvESQpdcfKBiS0/ygdoH8Z2mxASX1B0is4H9mLZYT7gRJulRMC7SHxEL7pNRdZ984EErNuoD150H0oU/BiRRQBpKnH76vkJzLLL5amZ/gHE+bPHjwAeU6SIXcy1o8sjKpMD+HRmwAPIHKFCq/OHjd8BvKJqB5VsyOi7c49+o2fo2SNJDP4/IQPHqXIXA3QAAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/Jackwu945" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Jackwu945"><image x="834" y="2" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/GalaxySnail" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="GalaxySnail"><image x="2" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/pooneyy" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="pooneyy"><image x="28" y="28" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEtUlEQVRogdVabW/bVBjNBza+M2mjGh8H49cgxkubeO00sbVDg/IugXiR+AGMbb8BVgh7KeIDqD8ADZrOzcTSjnWdKppsbdIkTmK3iZP2oOM4cOPemy6p7aSWjuw4fu495/r63vNcOxLxYQPwPAANwFUAMwCWABRM07QJHrvnZtxrYoyJ9HMDcATAewASxWIRvQDALIBJlhUm8RcAXGnYdatslOAHtusNE8BlAMeDJH4IwPuFqlVZzWcRBPKbFQvA1wCe9Zv8yS+37yXH528iDHyF1DyAl/wi/7qWull5M3ENYUJbuFUGcGpf5AvA2dPzP9Vjcz+gH9D0eOMh8HZP5B8BF/pFPObBXWCy+26jxxv9Jh4T7gSAV5+W/InTi9MlrUOB0cSU7ySjiSllueQymrpVAfDyXuQPf7H9V/KN2e+dwkYkaFXip4ioUJaqzuHENXy0ndQ5nHcS8NnF5LSj+MydOMYkCPoOjM3trpNcRud+xFv6dc7en6jIH6/aNfN+No2F9VUsZFebexd/ZzOYe/II5/TrTmsEJeD3zBIeZDNICXW3sJhNY8uusSsNyQRcMQwDZqkMywOeq5ZNrBU2nIkmSAErG2uwyxZMo7SLB0GOAC55yR+p1WoWDVZBgnyxgJJh4J+NdYzrNwIV8CCbQcUoOXXKuJCjbdtmmwGkq6QyFRjEQldDELCUe+y0NMl24gTgHVFA4gAK+LNFfsgwjJ0WURlYGG1vWF3IdAWo+LgidgAcowCtRZ57mV9n/2erZPI5jOvBPsTLuSfYKlWcOmVcRK4ARijgausE92nHm6+3+XS2/ON8Dhxizwd8B5JrK85oxzq9+QK55QWuTIIoYIY/qI4XfHj3F2fCmBA9ut7ck7wW8ER2Tr/RrNutk5hw6+Yky0ZsdTEAv1LAcksAW57kX5v9zmllr0fnuaCtxLCiXtobNh4ntNZDzoUCCsj/LyDrqGXAoJm5aGLKsRR0CIKAXMSyrJoogLeMqv0muF+M0CdRgHAHNjc3qwdfAHroQmFDE7tQ+zOQo4CHogA+7Z3ygX4g6uYDtNSyh7htGN0rH+gHzgj5AC215RlG/5vIOEmo8oFBwGI2jVwhv2sii4nTsywfGCQY7VZimAKOiWauMOAoes2c60hnO1nXQQSA22I+MHkABVxsSymZpj3tur7YD8XjsOJtb0rpirisygdUftybtYUVD+Ab6bJKzbZNWT6g8uOyFgw63m7Uy8rXUwA+leUDKj8uEuiUT/gZD+BjKXlXwKHPcU/35gMqP+4loMon/Ir/YCd5p+PSompxV+XHdxOQm0E/4kdT01yRO9mRvCDilHd5XWZnZQRUdnw/8Vpzef2VSDfbCjAxIAJ20sD5SC9bHjirzcfrKj/eUxfqIl7T441l4EJkPxvfjIwtTJdlflxGQJZPqPy80SF+bPHnUtfdpoOIF/lywevHZcOgLJ9Q+XlDEe+ONid8IS+IeIYvuqt1u6yaiPbKJ7x+3vDEb9WqrRfdh30l7xEyBOBb+hGZFdgrn5BZCbvpbS6F+gGI+7HHuwD+6Caf8Pj521wmB/BcaMQVYo5yodX9YOM3APe52sElG4LH7jn+x2t47VE/Kv8XDYIM9nCNqBoAAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/Glyceryl6" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Glyceryl6"><image x="54" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/iyear" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="iyear"><image x="80" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Colerar" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Colerar"><image x="106" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/zly2006" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="zly2006"><image x="132" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/zxc135781" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="zxc135781"><image x="158" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/ywmoyue" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="ywmoyue"><image x="184" y="28" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEyklEQVRogdWaW28TVxSF89DS9yJBI/qYlv6aCoTUCl6KmzQOtCFERSrqU9VHVAr8jpJLHQWaH1DRgoBKxLEpCUlL7r7M2B7nZjtftefijIe52ZlxGktL48ucs9c6c2affda4pyeCF/ABcAm4B8wAr4Cipml7AnlvfjdjnnNR2vQc5Qs4CVwDniiKQicAHgPD0lc3iX8I3K3t1asltUwUqNcaGnAHOBMn8XeBka1dpbJZWCYOaNvFKvAD8F7U5M/Oc+uvqcx1uoEFbj0HPo6K/IXp14OV+7Nf0k1MLybLwPnDkr/8azZZG09/xVFgMjNYh92hDsnXkkdFfNwBKAy3O/IXRP1REx9vuRKcC0u+78FSsuTsZGx2IHRAt3MP2356cagCfBJE/oRkG7mJ3DqUo4F+HxycG1X7cf1zPy/58Zmkcz8BNyWNOQXYO5xIDzGZvuKKifSVwCvQeft+/Rzghhf5M9UdRfMTIMFfrf3Oan6e5VyG5Vy2iZXc3yxtPCc1dy2m9v26AHX7jUylXjcBd2U19BZgdCDBtdIuJbVCWdV0lFSNSmmbfHGDqcwo92cTsbVfzmXlKtx2kj8ptU0YATJyEryoFFCUYhOqWmKz8KYL7bM0amgtBaBUlVJUhROQ1UfNCKrqkMqy2+2Br+0CnhxDAX9a5HtVVd0/bgJUVdkHTouAS293kGjJ290XkAgVH/hcBNwL6sBafCQNHoWAMY/4sgkSATPSgdFRkbX8az3VreUXWrBqHotKvhk0SgFqB/GBByJgwd6JlZu94CQfhQC1w/hiFIiAwsEIWBvuog+UGK+A0lZ8INdTrVZ37SPRCaK4AmoH2Nra2jn+AnCdQv6IfwopoeLrUwiYt3cS5OHEfROX2ohv3cS2NKqwWVjx9W6swHFdgc024ltptLmQ5Qor/Pbye1Jzw3pZa/dqUnMjTGdu6HV7XAtZrs341kJ20U5ANhS/vPhCD2h5NMZ7WR2Tsa/EqTbiA5+JgNOtxdyoSWDQRmBQX84n01dZib2UGA0Vv1nMmRXp4+NWjQKP7PuB4WMo4GrLllIsbv8OBpodyB7WWtatpd/YEoYjcNj2DeeW0hRxJ0w9LllANuAS8CA3l/RRyRVXAwmEa5/w3Q8AP3nYKkUtqB4X60PcA9mA2/OzBBdyU5kRTwHi+wS1T82N+MYv7SyXPR9PAd+51ePyeT2/yL+bL3iYvamnOmeeNjDSDOw2BeXo3fa6Tn5x4ynrhSUXDsYR+NaVvO0pzDNnDS42iOHbrDfztJevH2QtGuclXNomdAh5p29kAXjqay2aIvoajXrJWYfbfRu5nK152n20g74bd4GMvJBXHL5RrbYnjtxZX/I2EefL5XK9nTR3WIyZc12miTPNChfg01DkbSIG/ycC9oGBtsjbRFyuVCo1p4CgKXQYEWs2AebIJzsibxNxrl6vlw+KLSPNBfv8nWHVFCD3YdvTxkfER5KdRICUtFIVSmHl5fN3ion0kJUqJdv0RULeJuIdedBd3lktG37+gbcfFYrVf6wH3SciJe8Q0gv8LPVIkIcTFg2jtrnd1T+AmH/2+Ab4Q2pzfy/nbZj1/COxyYH3u0bcQ8wpMVrNP2w8BKTiKohlI5D35nfym5wj556KIvh/qu6CrQ928hUAAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/shitianshiwa" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="shitianshiwa"><image x="210" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/kingwingfly" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="kingwingfly"><image x="236" y="28" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAYgElEQVRogcWaCXCb53nn2W2TbJvtdBM3SVM3jpM4cQ5nvZ24mek6iR13a3tTx0nsWo4sK/ElyZatm7osWiIlkuJ9k+ANggBB3BcB4gaIiwABHiB436fEU9RBShQpkb8dIRtnM006mzbN/meemW8w8833+7/P+77f87wfEhJ+D7oDf3V7e/uV67duFW6DdWubkY2NOyvA5r3Y2tpa2dy8PQJb1rtbtwvvbt3eCZt/lfD/U9xZvy/gcx0Mt7dF7gD3Yv3OXbaBu1uwtcWvaXPzNrDF5p1bcV93t9Zxu83hRnH5gQZh8X1/MPCb62t/s7V1pwC2bvb399JsN7OyepW798AhbmDzzi/oNzbu2fql7v22BdvxpHDt6iKKxlpUshqkdSVrFqMs32nX3P8fBp5RnP2RnNKCQ+2x6OovR3ty9hJGq4nxmQlubW58aGBj894V3Pk/Rn5l4N6dm2xt3WRkpAdxnQCNQohRU4/P3YRJ33DTaGhIjnb7PvZ7hT+Xm/xwRmlONEtQQGldNf2TE6wDvWOjtAQ8DI8OsLi8wDZbvzBw594o/0Lb29usr6//ysDWbZbmp2j1OeIZaNJKMGnF2JoVuO3aeNxam+vaWF/4yu8Fvlxc9GJJXdHqmcwkCmtLKBFVUqMQ0z89Tmykn0g0zNTMOLOXJrl1+2bcwJ2tX2Tgl9rY+KWBTW7fXGF8uBuHRYvVpMDa1IhCUo5eKaQ74qa308vtG5eZGOq4EQlYf/Lvgm8Nm19r1FTf0VllFFbnUFxbQJ2yhmJhMY1NjYRiQdq7WlldW2ZxYZb5hVm2t38dPu4oPve32Lh1nYXZcQaiIcz6BlwWFSZ1PeqGSgJOAwNdfsb7I0wOduC36e7FXbdB9va/CT7abt3XE3XSHrEilhYTiliQqSvIKvoARVMtIkUpGpOYtjYncIvVawuMjw1ye/3m/7Xz3OXOxibbW3dg+w6Xp8bo7wrSGXCgbazEpK6Lw9ubZFwai9EbbmG8N0y3345L1xgPh7yeprqKA78TvLa25EVdveCupr4EvUyA362ks60Jv1dOS4sUt7cBg6mc6tp0FI3lcOda3ESsK8T6rRvxUTebraSlXeRiWjrzc5dYX71GyOfEa9fjalail1Xgscix6xsIuYz0tLnpC7lpd5nwGRRxcEtDLeqyApQleXcVhTk//n+Cl5cUP6QSlFyXl+XTUJKFsjYPjSgPV1MN/V1NzE54mBi10xPVEgkqkAhzuHl1hsWZIdi+zeToEAp5I9/4xjf4xCfu49N/+Sm+993HCflaaA+4CXss+G0aPKYG3E1ignYtHS1moj5bHN6jk2Gqr0IpKKCxIAt5QTaKwhzUhbmr6sLcr/6r8JlHkz5aejY1WpuRhSQ/B3lpHqrKPBQVmVjkJfSHdVy9HOTGcpgrcz7mp71cGgvTUFPAzZVZNm4u43FZeeftvTzyyCM89NBXePSb/40/+eM/Iuh1EfE7cJuUeEyNjEXdTMS8jHX56Q+5CTuacKkbMAjL48+V5F5EnJWGLD/rHjy6kgK0xfmdyvzsj/xWA6f2HTl1dv8x0o+cQJBygcaifKRFmRiEhdjkArz6GgbDOm7MtbF1o5eby11MD/hYXRwh6DYyM9pLd3uI/e/s4/Ofe4BHH/1bHvril/gv//lj+Fw22gNOOnxmBsI2bsxEuXW5n+WRboZCLfGR11aXIi3KpiEvIw6uLc7HUFaEqaIUc5Ugfq0qyEn8jfBVJdX3517IXktJPEPSgcOkJh6nOOUcgtSzSEuy0AuLMTcICJobmRnwsHV9BDZnYXWau9cmWZ4dwG3R0OpxolLK+fpXv8aXv/wwX/7SQ+x86Z9x25oJuS2Mx1q5PtvD5kIfrE0z19dGzG3BLhOhqSxGXpSDNDcDRV4W+pICjIJimitK4yb0pYUoi3JXlSV5n/0XBkxWW4FOZ0BSJ6IsN4+C1FSK01KpzM6gPP089YVZmKW1+JvktLuauDQQhluXYWuZqzM9XLs8TMhjpiPkR6dVo5Qr+Na3/o7jxxJp9Xro7+6gO+RmPObn9vwgdxf74dYlJts9RJ3NBPQKvMoGHOLa+EirC3LQFOYiy76IPCcDeW5mPCvKkjyahOW5v75wLfr7LAHXTWerB1eLE6vFiFGrQidtQF5bTXlWJsUXLlBfXIBOVItZLqXNbmEqFuHyUBsbyyOszg0x1hdmpD+KzWriye89wWOPfZsfP/8jCnNzcFoMTA50Mtvfxu2FfjbmulkZDTEedtPbYiVqbaLLYiCkVWCrraTp3tQpL/nQgKogB0NFCTapkJBJs9brs/+qAFRZDQebPXasXme8NGiLhIiEW2n1uFA31FNVmE/6qeMkHz1EafoFmiQi/AYdAaOKheEga5eibK6MMzPUwfKlMfa8tps//9M/4xN/8Uk+/tE/40uf+xwZyR8QC7np9jVzZTQMi31c7nYxHrLT4zDSblLTZtLgUUsxCivRVZVhrq+hqbYCY11FHNxvkBHzmJmMBVgcj777oYHK8pqIw+ZmaGiEjo4u/H4/gYCPzo4QAa8di74RnbQaXb0AvbAUm7QKj1yITVyMW1PC/LCb1blu5kfbGesJ85Nnnuarn/8if/7HH+dPEz7GV+7/As88/l2cGiVTXQEuxXysDPmZbjcz2mKgx6ImoJfi0Iix62U4mzW4rE202E20us1MDXbF3xVdrWYujUe4sdJHuE3dFof3WzyflVSItm06C806I8FAK8FggLawH6vNQDjkwGxsoE6QQZO0FHlZGuqyVKTZ72OtzSTmEjPQpmKm18n8SIR2t5m3d+/i5X/6EY984WG+8OkHOHPwOM8/8RRhSzNzvR30+0xMtpnptkhoa6zCL6nApxTiM8hoVkvQKOux2Qy0t/vxtVgZiLYyPdzB9FAIm7GaSEjO0JB5e3LS9pmE2qKyV8rz8vFYrJgNWkYGe+I3BgJWdHoxNmsjGnkp50++SW3++yhKkwnrq3CKcuh3NDAa0jHd42C2z0t/yI62vhJxeQkFqek88MlP89W/eRCnvglpuYCTe14nYtXikFchzT9HkyCTHqUIxfn3qT5zFHOtgHZ7E5EWG20tVoIuMwPtrQxFvPT6zQSbJYiKzqCVpOO3VxJurXs5oSI7q7A4IxVJVRnVpbnYzSp8HiOhVjOxbic2ixiPXUzhxYOcPfgSOad+jrr0DIq8E9hFWXQ7lIy3u4i2NOFvVqKuFdAT8KKsqebBT93HY197mLqiQswyMe/89Ceoqwoxicpoqsqn6960yc+k4Oe7SN31MjVJJ6lNS6Yk5QyVmecRF2XjkImYCLUwGjAzETBybdjHcKsSReVpJGXH8hOqctKsEkEeFTkXyE45TmFmEl6nAp9LQTRiwm0V0RVS4TSUkXPm5xSffZ2sIy9See4N9IJkbJIKIhYDXp2KdqcFg7gWm7qRuuJcTr/3Fs9//+/RispRVRUjK8vh/b278aglrPS3464V0JKbRd6Ol0h78QWEJxIRp5xDlJZyb79HU5qHraaUAauWPpOMmL6OlS4b00EVUXM548GG5oTGspyxqNdMu0uPUlhI0rE3MGmqaNZVxuG1sjwaq1JoEmciKT6JR5VP9YU9qAoT8TYWMR/tpNvhQVpcirWxkV6vi+me9jh0XvIx3n7lhzRLBXQ6NMgF2Zx4YyfFSYnxPd1dXU6HQIBg126yXtyB9NQpjHnZeEXVeOprkGYko8xMRpZ6Cr8wnx5NNZPORqZ9jSx36Rly144kzMZCVy73RRgOO9GKSjj+9k8pzz2DrCYTi1pAaeYx0k++RmXGYSQFJ9GVJ5Nx8CXyj+1CeOE42rJKWnVOhgOdTHfEGAr446VBh1NHt0ePuCSFrNP76PMbaChKpSE/lXdeeI4Tu3dyu7eXrvIqXCnptJeWMyiT4a+uJCKrp0cvw1yaTVBUhiw5EVVaIqb8JAaaqlgIqtgcc3MpolhK4Or8hkspQVtbgr6uDGH+eUrST5N6ch+n39vF8T0vkf3+26gq01GUnOPc3hd445nHOL37WQRnDpNx8AzHXj2MrFDEzck52LgNq8tcm+hiebiVxUEvPn0Vl3rctCiquXhkL8KM88y0hQjL5JS9sZfcF3YgPZpIQCCgSybmSsTL1S4/zqp8yhP30pB8GEXqEZryT3O738lyp4EhVx39buHtBNZWNqa72giZtOiE5Xj1cvR15VRlJXNy3ytcPLmfpP0/I+3oW0yHXaz0hEh9+1UqPjiC4Mwpit7P4tDLh3j1H1/myKt7sEmkrM+Msr00CnfmYXWEG+OtrE93wfwwC91BVvq6qUu/yM8ef4ID33mSk0/+IyeefpozLzyP5PxpDCWZ1KWeIO3tn1J77l0iyjJmPWqmvUomfEr6nCJCTWWELILbCTenx6/M93XjVskImfRoayqwyespuZDExROHUJYXoii7V5Vm45TWcX2wG+YmiejkNOYWUHW+lP0v7Cdx9yHef+MQJ19/k8yj79Hr0tHrVDLgUbA1F2U6ZOZSZwsxq4E9zz1LwYmTvPfcj0j76W4u7tjJ/ie/z+kdPybn8B4stfk4GorpMNbF11lQWcqgVcKAvYGAupSAvpyIXYTbWLaU0O12jo63hxls9aMX1lCfl4ukMJeGojxKUj6gJiMNo7AaYdZFXFIJXoWMjYlxuLKMSyxDVSxDlCkiN/Eiye8cQ5yVy+GXX6A8ORFFQQo6wQUmWg2ENXXUX0yi9kISzZUVOOrFOIUifJW1+Kur6daocNaV0+/W41JWErGK6bCKcEjz4uuu2ypiocdBj0dJzKeiL2KgWS8YSZjv77GuTY+zPDyIXFCMRSKm1aAnZGyi+NxZMhOP4VWrqM3MwKNSEnM6COl0rPT3w/INlmKXkBdJkRXUIc0RUHMhnaTXdiNIOsaFfbtIe2cX7//sxzhFpSjz0qlOTmIq4EecmcWk18+QycydwX5u9HTC3BijbTYu93nocssY7zQRczVgk+QS0JYz4FUTsckIu9X0dthoCxqbE2QVJYXLY/2sX5qiz+8k+/TxePkszMlAW11OY0kBH+zfi666Cr9Oi1ejplWvo9ftYirSyfrUCoYqJfoKKfnHz/L28z/h0IsvcPrVHZScOEjMqCDrvdepOHOEt//pH3jtfz7JiVd2knsskawDh2hMS6dDKWdrcpi5bj/rl3uJ+TR0umXYlUVEHRJiLimjQSOLA60sDIVpa9FjUNWh19bnJ1gUop3+ZjU9XhvjHQEiNgNWWR3a6jKaxTUYRVV4NAqCRh2WBhHLQ33cWzMxl5OA3oCitJaqtCIKT55nx+NPset7T3H4hRd4/tFvUpx4CH1BJudff4Xzb/6MpJ/v5IPXXsVRV8NSdxRHnRBvnZBegw6bsByXrAptbQ49fjV9QTXLoz5uTrVxYyzEVLud4aCVya4A3UEXkaCLmcmhHQlOvfgzFlXt9mDYScxvZiYWwtJYg1sjjYeupgyPRoampiy+SxnF1bRoZQwFfVRnZZBz8iyn3zpAxbkMDr/0Kvt+8DwnfvoKu7/7PZ77+tc49+orPP/Nr/LOD54h78gB9j77NBUfvI+hXMCN/j6MRYUoMtLRl+RhFZUy3eViosvCyniAjflOLket8ap1LtrC0kA7c/2djETDxDratrvCoc/EK9L1xeHw8kQXS+OdDLQ54vV2p0sf777cGkm8DBDmpZOfciq+O7m0CqSCIixyKQahiMn2TmY6olSdT8NUVc3Fd/fzz3/3LZ548HN8/8H7efLzf83pV16i8OgBFLkX0RRmx3tcS3U5yrwMKpJOUHH2JGGjnPn+MJNRD1GXjsnOFhb7I0Qdegb9TobbvDh1CixaBWaDJvhhP3BraezAxpUJbi6McGtxmJXpWLzTutd8KKrzERamIynLZSDsZSrWQczvobfVF+/O9PU1+JtU8ay4VQ0Em1TknjiIJPM8u5/6e3Y98RjPfv1BRBdOk3d4D15JBR1aCZNeMyFVHWpBJp12NbrqYuyyeoIWEx1OFy6tkagnRMjixWN0ErR5cOhNyMR1OG0mQgHH/g8N+C2q+4J27VrQrqYnaGWky8NYt4+wS0dtUSqjUT+LY73oJdXMDffGDbh0WuxqRfw45Nb8CLO9QTxaMeqKPErPHWUiaCfn6B5+9K2HefaRByhM3EvWgd30NEvps8gYcWkY8xno9eiYjLYw199O2N6MRliPsqqBdlcHVpWTLn8fNq0blUSPokFJs6GJYKtnTaeT/vo3hazkE/nleakoRQK0DRVYtWIsmnqCTj2SyjxWZocJt5gpz71IRV4WQYcNl17J3FAnAZMUt1qIXliIqiIbQcoxmqrzyDz0Gju/+yinf/ZDmsovUv7BfjoMQkLqSlqV5fEX3UjYRotOjLQ8P55dr9FIzHfveLGT/nA/IWcEp6EFdYMOuUSBucl4r+fO+RenEnte2XH/+ZNH1gS5qeSlnqG6KAN9Yw1GRR1eiwaLpgGrRoZeWk9JZhrnTx5nItYOm1dRVGbT6VSjqshCXpxGTfopsg6/zrjfRGdTPSF1NQ5RHukHduIQ5zMTbqa/RY6pLpfKjCTa7AZ0okraXXZaLRbmR8fpC0cZiQ7iMNjwWb3YmmwYlAaMOv0NWWPDb/48deydfSezUpLITT1HnaAArbQGg7wOd7M2HtNDvXitRtymJux6HRqxkJXJHuzKKvoDJvKTDlBy7iDZiW/xvYc+Rc7RN2nMTUJVlIJdVEB12jHKUt6jWZRDm1mEVVZG0KqjtiAXUXEBdrUKNjcYbG9nvLeH3nAEi9aA3+7C62jBabZjaTIfS/htevf1Nz5y7viJTkFuNoq6WsSVpajEtbhMOjyWJnojrUwN9NEbDjEc7UJZV03IpiVsU+JS1iBIPYG8KJWU/a/y5Y8n8IWPJbDjO4/y5Fc+w+6nv01h0ruUnj+CtDQFh7oSj1ES31XMcjlTPTEiLS7aXA7CHkf8Q8jliSH0cilBt5ORvj76uro7jFrTbz9avKfzp88+VJSZdV1SVY1QUIpZq8Jnt+A2Gwm1OBntjdER8OFuNuMxm6gvzkFZWYCk4CJFZ4+T+u5bvPmDf+Cphx/kiYc+x7fv/0u++amP89QjXyD96D5SjrwVL9XNyhq4u8qtxUUibg/e5mZGuruw6VV0tbrZvD7P0uwwPoeRaCTA8tzs6qWJqYf/VfgPF3RK+k+qi8vu6hpldLb6Geru5NLYCCuXZ3GbTQxFu9E0SDEq5LRaTCgqijBL6ihLOcuZN18n7d39PPffH+WB//RHPPJf/4LH/vqz/I8vPsDFxINU5aRRmJpEcWYyA51tjEZjDLRHCTpdqMWieKajbW62by+zsTrH0twog72RuxPD/c8n/C4SFBbvrS0vZ7i3l/7uTi5PTjI+OMjM2BgzYxME3B5ibe20t7TQLGuksaQMpaCC8+8coOLsBQTvn2PPsz/kxW8/znN/+20OvrQTcX4hisoqMj/4AIOsEZepmeWpOZam5wi6PPjsVjpaXfS0e1m/fgm4Dqxu37o+91bCv0XRcPtr3ZGOO7Pj4yzMzHBlboGrC0vMjk8zPjgajw5/kL62DqKeVkZCnTQLG5FklVJyKpWyU6ns+u7/4uXHn2HHd56hNrOI3LNpVBcKUEvkuEw2ZoYnmBufoTPQGs92T7uf7nALVxbG4M7Vu6tXZ/Yl/HvUFWn/8ZWFxRuTo2Mszy1x48p1ZsZnWZhdZCA2SE9HN9fnr7AwOsN4Rx8+jZna9GLO701EmJyPLLMcdaEQfVkDZ/YcJTXxHFX5FQx2DtCsbWZxdp6V+UUmh4eZnRhhemyA3miAmYne6+ur87/btPlt2ry5/uX5mbnOpcvLrN+4zY0rayxdvkJfdICJsUluXr/B4tRlvCYH2ioJklwBOYfPUnTsfNxEfXoJBoE03vyL8qsQC0T4bQGmhqdYv77K2rWr9xYpVxcvs3hpgt5osCPWGXgo4fepleWrfzI2MnloavzSjcW5awz0jjEyOMHS0hKTU6Ncv7JMT1uYZqkcW4MCXZmQquRMCo+doyAxGU2JiIjJg0wgQl7dQMTdxubabTZu3uDqygJL8zMsXJ64OTc7kdwX6/hown+UYtGhzw71T+V1tQ+sXV1ZY/HqAr42N5sba6xdXSLidOBSKLEIxdSlZeGXarDXNNBr9VKTnkdtbikakYyJ3mFG+ga4u7HG6urC2vXri7nLy7N/uD+ATIwt3Le1xXvLq0shd8i8vXn3KtevzhALegia9DgkEkQXM3DWSWjMykNTXE6X1YGmqgZ/czPNCtV2Z6s/uHpt7t3V1cuf/IOB/ybFhkOf3thaeXl4MJI/2NVqnh+KDY74PFeaq6s21PmFG5UfnLvSIpUPWiVSs0OhyPeZjC9HXK5P/z4e/r8Bkzgy3mLv8rYAAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/aaa1115910" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="aaa1115910"><image x="262" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/stydxm" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="stydxm"><image x="288" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/emptyBud" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="emptyBud"><image x="314" y="28" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEhElEQVRogdVaXW/TSBTtwy77vkhAxT6ywK9BIKRF8MQDghVQeACJfeQF2l1a2iAhLftDdtVfUL6SlIRQpLKlwO6msZN47DgfjZOe1Z1MEsexHX+MUxrpKk489845nvHxnTuemZHwAXAMwCUAKQCrADYBVE3TbJPRsfhvVbS5SD4z+/kBcBjALQCvGGOIYgBeApijWNME/gOAld3d3XpU4E5rt9smgGUAx5ME/i2A25Zl1WQBZw6jiwLgPoDvZIM/BWA9KeBsfGplAZyUBf58kledeVin0zEAnIsL/nKtVrOmDZ4JMwyjA+DnqOCv7RdwNj6l5sKCP0/s9xs4Gx2Js0HBn+h2u7qmaYhq1Gn/234cJ6ZlWTUApyeBP8TVxmCIbA7wThJMjx4bQIbk3I/AL5WdCirF6KZV/UcgbnwAd73AH28ZLTP/xwbWV95i/UkhvKUKUL+UoddcCOiMg88/ixg/VcCbp+/QUJs0lWbdCKwQQwr++uEbpBdy4W0+B/WTBwGDIVb8+Rwyj/JQtlQahSUn+MNtq13nHTwpcAdqnPktnKV/zUH9PIFAP36E2Nmlt1A+qujsWeZIAkhZJR/ifgfz0TpInkCej4Be02kUbtgJvDqABF70wc8yxvakEfikcrCkRgMdJ2XS5RJgjO0BOEoELg1UQgYBUqG63tN7m1GnlVJVGgFN02gULhCBlEwCpU0FVaU6ruGlKr8BSQ4lElgmAqsyCRBAPy3vt5VE4E8i8HdcAnZAfc12NTon2oYlkXYnsEkEKjJHICzhTDwC6ky9Xt+VQSBpS7sQaDQarYNPAAGnUJhhd2srwz/rNoUAfJhEwH7jBTEniLj+mQk3cSAZHQRczPNAbkbnJo5ADP+sh4wGepDxoIt5/Lte5OmCsqXwYAPbVrHzvuT5oJLhn/V4kF0MSoACUOdG0+D5DgXqGePpAz2Bk/ZXRgn8RASOBknmhgEU92SNMZT/m4a/OprMiYz0ZXACwyswtmScoj+ANft6YO4AErg+sqS0OpYZPIBjCjgBLCTr33EuKQWJZScBpy7zANtqL99nPvl+kv5bfFG/6FpWaRot0y0AN7oqi3kUN0pcLeiGG8v3t0W+n6B/Q2kanttTAO7Rioqkjta2A6PfX8p8sZL7fcM7508VUHy3g/I/jhhx/T8PDcAdV/C2XZgM12Wbcc3u6zTVdR6Iuo49zxfH1LnR0IXOy/HXhQFI+5YWPYu7YlE+0GmfupHfoj6yvzYo7p7yBW8jcc5eXg9SFolbVkn7+Ivy+plA4G0krn4lBPYAXAkF3rnFFLQwFbewlXb4iyt/LRJ4G4mztOE2ACBkzjWXXwhAIKB/t9vVQ08bHxI/kjoRACpx0w1IhVa3fH4SgSD+6KnNCSngbSS+oY3uZrll8Pz9oy2Xt5lW8dngqGr8YeXlXyua/Y3uQ1LBO4jMAnhM+chIPi+OJ20xDdsOfTq93GZpqi+AiJc9bgJ4TkoRdpNPqMsalckBfD814B5kjlChVbyw8ReA91TtoJINGR2L/+gctaG2R2R0/j9Mv4djNgytwAAAAABJRU5ErkJggg=="/></a> +<a xlink:href="https://github.com/setupdata" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="setupdata"><image x="340" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/renmu123" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="renmu123"><image x="366" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/chesha1" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="chesha1"><image x="392" y="28" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFBklEQVRogdVaz28bRRTOAcqdSi1ROQbKX4NaVQK1px4QRUDgQKVy5A+gtLmRNgk0ASHUEqduG5o7aqAVpUe6tgMk8Y/Y8Xp2bUe11+6H3uzanrV3ZmfX2zSJ9LQrZ35838y8b+a92YmJBP4AvAHgHIAZAGsAMgDMRqPRJqN377c1r8xZqjPxMv8AHAXwGYBHtVoNjDHQU8d6ZQE8BDBNbe0n8DcBXG21Wk0C0rMeMGZZahPLMtfa7XYDwBUAJ14k8FcBfO602/VhEOKomjsVmDtlqdXMQVk2VJ8GBcBXAF5LGvxJrGee5H68h92tPJhtjwKwLA5+4+f7yN5II7t0x2+Ld6BbHw8yfwF4OynwZ/KL9+rG7C1k5pax+9+2AkCZgze+vQnj2i2/RaxfWFq1AZweF/z5jYXbDnVsXP8Fme9WsLupGsEyH20CTHVEi1M/t7DSAfBRXPAXRgAsrISPoIpAzPoApqOCP0PsDwqBnDsTp3TBTxWXVi01AIurybC2myVdAor6i8H1yQ8BvBMG/gjWs0+UALYKsBp1MGtI8+s2zHLFBTB7k5f3GbW5kAqvvyQfAPz29DHJuYrAl+oRTKGS/RdmZRdmaYePWN/KFe6guR/uIjO/zB2WCA8shez3t0PrZyUz0BtAABdl4E+06s2GksDc8kDjFwPsRhrlpzlUtwt8qfhsq8DB535aVbSR9vUVROBZldFSmgwicFXmRL0G3aXgLgeZVQslWM0GX+fkrK5ZfNnQyA/2CUk71wd9yXwIwOVh8EfbjtMMVZGh34LK0Oi7TmoOnJSODxY56Y7XvrotQzEDRMDpdhu+AyCdKsNkUAe8S6Aol0mFymQ02hdlGMAnIoFHh5DAHz3wk4yx51EIyKbYv4SGdD6EgOHV1yVAmAEcJwLnfDuh0MGIlgudBDkZJ5AvuTovxgb0Lu4TEpHISPoMIuAFRO8TgZkRArPxCVQ2Nj2dF+IAn86nIxMwPPXjG6GfwBUisCYGJNV8kS8DWssDK3B5JHBcBhVLgAD2NV6IBXrPsCVYNv5BtVgKxrBd5OomhKSrRCDni5D62m0H67hin+Dvij0iTOcNWoLFoH1EMAErJQqIQDU0KO/reHwnHFcEasFJgcpEs9lsiQF2kCUhg+PIMJPY3t7es8NPAEBVm0B/n9BbKnFIVCMQ4EsIQDbaDKS5zErlbhy71vMBbQLcideizAClRoLP+0lYKuoMcBmd0SJAT7PG8zr8fL/pPRO2mqDzGgT4RnY2rGD4PpGgMT3wHoH3iMBxfpjTmQHN5O24xvRIuIc570T6UIfxQTIA62I8MH0ICXzsDynb7UbcxuLeD7CY/XnpeP+dAnn0OCMyzv0Aiz76XwemVeLOwrj3AyyCdTodW3o9BeBSbAJj3A+waKP/RSB44RbmcXwC8e4HmD74P5WpRY/EVLfbtWITiHE/wDTMcRzKyJ1UghdInLZtu5M4AUl6nYUYYQHwrhZ4gcSHB4TAcwAfRAIvkDhfr9edl0XAdkf+QizwAolTJF3aBLy0TOD9wLw/LcIUbZIfRl42ChJvqdRpJF6YC4gX5lNcoXScGK7aTCUCXiDxCl10B82GdrywmUetKj/vtwYX3UcSBT9EZBLAN8O7tna8IP/U4PK+fgDifezxKYDfe/FElMOcpy7rlCYH8Pq+AZeQOUaJVu+DjV8B/E3ZDkrZkNG79xv9j8pQ2WNJdP4/j5UQ7P19hTkAAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/CreeperKong" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="CreeperKong"><image x="418" y="28" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAZnUlEQVRogcWaeVTP69r/7+rbPM+zJErGRAiJRGQoISWkokIDDWhWaR41SQqVobBFiWSe52mb52FvbNvGJmzbxuu3ap/fOetZzzm/9ZznOc/5vde6/vmse63P+31/3td1X/d9f4T4F+DzNwzew4yXX1n5+it72/74dvfT299ff/31t8+8/fj50Y3rry+fO3X3wunDew9uq1u5s6jA+0R+sYH4/4mHv/2ufe9NW9gPr96de/7rB27/9JLLT37k0cs3vPn1A1/efIIP3+BlGz9cvsalE8c4dbiVxtq11KSnsi1xOY0rMs42rFwdum1Vpfa/jfix67dNojKyCm8+f/7h1rPnvPz4iRs/PqXl/Dlaz57l9oMnvPvpV3j+AV5/gdd/8ObyLb4/dIQTrS3sqq9lx7pyjm2o4fK27Ryq2cx3RavfVyQkF6QHBhr/rxHfue+E7NELV8OPnL/cNm2WL5evXef1r2948eIl+w4dJrukmNyyUvYeOMjDG3f5eOcnePIrn75/zJ3WExxr2s2h5l20NGzh4LY6rjQ1ca+llYf7j3K1qYWTtfWEj5/4oTgkdHlN7FL5fyn5DZtbrBpbjl/esn0PO3Y2M2fmLHZtqefjs2c8O3eZneWVLA4KJjw8lJoNtZw5dZo7F67xw/d3OLR1F82bttK6s5EThw9wunUv53Y2cm3zdi5VbuRidR1Xt+zgbG0dswcNY0dWLmXhEZdKQ8Mt/yXkC/Nrp2RlVbaVldayqXYbVUVlJIaFE+0zg/3l5RzLL6Fm8VKipnsTPi+AvIJsVq+tICcnh4S4RJLjl7M8MZnCwkI21VTTvHETZ7c08LB+Nw9rG7hWXcfl2joaM3OZM8iB45UbqI5PpTIm6d3O/JLJ/yPyFaVb5yycn/jH0qgM4qJTKUjJITV0EUune+FsbEiK63jyR7mywmE0/naDmTR0EBMnjcVx3Eg6W1uipK1BXzs7etnaMmDIEJydRuEzfhIZ/gtoXpbBseQCbtfUcaZ8DatDFpPsNZuduSUUR8SRtTCa0qXJX3YUrQ3+b5GvLNwU1FR/hIgFSSREpREdFMXcidMIdh6Lp6Ulo5UVSbYfQmqvAcT1ssXN1ISuqvJoa8ijrKWEkJNGSAmERBYhpBHSMshISaMpLc9AfVP8+wwlYqATSWMnsnySGwuGOVIVFUtVbDL5YTGkBEeSsmApm/MqaFpVG/pPkS+IL5hSkbn2S2ZMPinRGSSGJjDXdToOBp0ZIC3LRFVVAo0NCDE2IKpzZ3y0dTAXgl46SjgO7I2LswOG6mooCIGqkKAto4qckEYiBMpCgr5EDlttQ3zt7Ikc6YSzpgaz+vZjTcQSisKjiZg6k4R5EaxKzqcgJp3qrLIv69Py3f9L5JPnL+maEZ70Nik4npDpC/BzncmQTr3oIVFnhLoubuoauEkJgtSUyLfpQ9nwYcw1NWSklhK2RmqMGWaLkbYqSkKgLqQ7QkPIoSQkyAnRIaJdmJYQ9FVVIXhQf4ZKpBgkK8GzR0/mDBtBuLsnmWEx5C1NJWNxAitj0qlMyWtbm5TR/f9JfpiFtdzcsVMvezuMx6P/KMb3Goatlhk2CprYK6gxWduAefr6LNRQJ0pFkXhtDfKsrUns3YOAPpb01pKni5E60tKig2w7URUh0zHrqtIKKMvK//V5J0UFbNVVmdbZhMFCMEAIXHR1mGjRDW87e/ycxuI51JmEgBAivAJIDgynJDrhYllkrOw/FGClor2sv64Z/TSMGahhyjAdMwYq6zCtizXzuvdmjp4+QaqqxGhrEqeowAIhiJCSIbW7FX6WnRlgoIJESiCvKoWMrEBOIouqRBH5v9inPdoFaEmkGGphjnt3SyZqqTFECOyFYIyKEo7Kqjhq6jClhw0Bw0ezyM2TGfZOBLt4kBEYTnlUYtTfJW+moGFsLqf63lJWDUf9zkzp1pfZvewIH+yAf1crZmhp46+iTIiCHBHSgjghWCGRJVbIEKGshoemMsM76yKRFQg5gZAVyGuooqik0pHEEokEeRmBvBB0VlPCtbc1vn1746aswGQZKTwUZJmsrIyTtDRDhTRjNfXw7GbNJPPujO9sTYD9aFK951EentC2I6PU8D8JMJJVK7RW1mWIjhmhjuPI9/FnQ0g4xVOmEmrZFS95CSFqKqQZ6pOlqUGmnBw5cookyigQIKRw01bGvH3W5f8moL0KSf1l9mWlpJGTFihICQxVJPQz0sFJXxMPZUUW6uowX1ebabISxgmBq0SOUVIy2ArBDHMrohxdKJy9gPWLEtkan09DSlnefyCvp6CrbaFq9MHddjhhzu5ULohk57JEzuXkkjliJPG9rYkw1CVOV5Mic1NqulmwWlOb5e0WkpPDQ0owVFmgKQQyUgI5RYGJvk5HImsKCYbSSqj/JYml2kur9J/j9IVgiooCIWpqzJKWYrQQHeEpkcNPSxdffSPcVLQJ6TuIpQ7jiR/jSY7XQlI8gt/HjJ/3twbQQs0kzNHKjrzwOLam5rI3u5Ad0Us5GBtDXK/uLDM1IEZLlWQNJXK11CnSUKNUXY08TU2itDRxEIIu7aEgUBMCS0MN7EyNcTLrRtCw0cwfPpYxFj0wkZFD+f+KkBGYyAmmyMoSLqvIIgXFDnsGyEkxtV2YEPjrGTBD25hgywHMNrMlsJcTOdNCSfcMIWFy4MK/+V8onyuMiOfSzr00l63hcv0W1s0PomKKG4kWnUgz0CRZTpAhIyhVV6FEQ4UMeTnilZRYZKDPdG0NLIXAVAh8hvYhfsYkGjOWsyN2GR9b9nG3fB2tcStYNmo8hu3jFJXQ01SjkxDMU9AiUkgRKQSLJQJfIVigJnAXgkAjIyYrGeAsY4ybVj+8u4wkxzuCqsUp7MopPtNB3lwIw/SZgd8ubWvi4LoN1KZncqSqqkNA6YQx5Pe2pKq7OdWd9Fivr0mVnhaF6kpkqauQY26Or5IqnlraDBICNzNd6hMieHuilfIAH15s2ciPFWt4tqqKKvcZrJ8ZxNTOvZjUe0CHvXopqrNIx4xCA3OWSQuWSAniVQVRyoLZQjBTTpaQzr0JshxOSP8pBA2cSnFQIq1FVTxs2fvtQUujvugnqzRjU/xy1iyNo3BRJFtzctmYkED2FHcqJ08gtYsxBSa6lOtrUmOqx6ZuZlSYGVFi3omqgYPYOGU6bkqq9BCCfJ/pvNy/m2sbq3hQX8tPdZuocJvCzcx86rwCaA6NIWfKbGrjVmAkq4Jeu2hFZbJ7WpNmqE6RkQo7+nRipboUaSoyLJKTI1jLFF8zGzwth+FiPpAoD38a8kvbBXB/967pYrmHx8qtySl497cl1tOTfeVlZPh4keIyii2zprNEW5UEFQkpcoJ8dQXKTfVY1dWMzUPtOeLnT5N/MI2hER0V4/6Wet4fP0xDUhzPdn7Hp9Z9VE3zZqffAk4vS+NKVinbIhJJ9fLHRsuoQ0C79eaaaLDBsT+nJjjwYIIjjUbq1BtoU6CtzTxFNSao6tFfWY/uasZMHTKKkqXxnFpfy7W6+gKxPSlm747UBDzbK834MZSGBDOzpxVLBtmSNXgACUY6pOqokigvSJAIEpRkSdbToGKwHYcCg7mUks1qT1/cdY151rgLLl+GK1f4euYc1yvWcjGzkCdlNXD8Cm/r93CuYA1LXCZjr2fakQ/tYSct2Oo2ggezJ/Ns1BBO6mvRpKxAmYIcC+XlcZLI0klIY6Sshk1nC+ZNcKcuKY3723bsFpVhfvejRg9llIE6c+1tCR0xhBHKsszrYoKfhgrxxrrEaSgRKS1YJi9IMdQmzkiHYHVlfNU1KBk/lT7tydvFmt1pWdTFJbItZQVcvwWXrsPJS3DxNi+qG6j0CqImMIIc77m4dLLEWkkBnfaFTQiybbtyaJgtZ81NOK6ixCYhyBWCUCVZRshKdZRcHRVF1KQl2BiakTR1NtfWbr0rktwdXg1UEAyQE8zoaY5/vx6MVVPCr5MBPiryBChKEaYiQ4SSFPG6KuT16kaSZWemSf7sX9rJOytoMdPahjvfNfK49QC3m/dwfXsT3LgP95/z275T3Fy9ifP5a7ixtp4Ni2NxMbGgh5wcBu09kKES8V0MWW9mRLO6OvsVFFnXnlMyguXmxkzQVcNMQRpzQz00JAp0U9ZjZm9HNi5Mfilm9NT/3VoInHRkGakpj4OyBEdZKaZpqXQsKhOFIMpIk6ye5qRamZDQzZilXU2IsDInsm8v7IRglJoewUNHMKFbD/xGOrMhLZtnp87Dg6fw42t+bD7Egy27KfGdT2D/YUwx74G7RXcs2iuRjKDYy52SgQOotuhKk6ExO1Q1WC0joczIgPR+vZhorIORtKCrgQGdlHTpoWyKvXxn/LqO+iTcLdR+t5ERjNSWMM5QnSEKUoxQlOAkIxgmBJMlghRbK6K76FAwrA9JNhaMEoKqqRPJHjcaZzU1QhydOFS+hszghVRnZHO6sZlXN+7Bizf8cvEGn28/4fbOVm5s3cW6iBia0vNozStinL4RFTN9qZ3iycYRztTbDqTOwpJ9dgOp79uH5sluzO9q1mGx9i9lKKeCrlDGRKhjL9ONtHGhn8Q4E4VXdvKCsUaquBprM1RFjuHK8gyR+bNDDLAwJG3kAGbpyhHZw5DoXqb4aEpIG2rLqfTlBNj0JicggPt798LPL3hx9TrvH/8An+Hbm/f89uwXfnvygq9PXsDjn+D5L/DgCVWLIkkcPZ7ts+aybsRYVvWxo3WiB2t69GGxvCL+EgnBpkaMUlHEUV+/IweMpVQwFur0V+pOX2GGp4nzSzFcW+beIGWBayddxhjrYq+qhL2KIv0kUthJBO4m6oTadSXSvhuZLv2ZpimI6mWKv64ykX2siBhhT0NmKu8unYMfHvHpxx/g40e+tf3Gl7ZP3P3+Jm3PXsGbNvj4B7x4BTfucHvrdm6WVRJrasXR6X60Tvbi/Pww9vkFkDvMAV9jI1w01ZnWqweD9fTRFQJdIcHVygELoUdXoY+dVPe7YpSe6t5hmgqMNTNmlJEBgzU0sdfSxlZFETsNBYYbKjK1pz7hjt1JcrHBVVFQ7GpP1pDexPXrTswoe3LmeMPPT/h0+xp8bIPPf/DyyVPaXr/jpx9e8OXjZz48e8mXZy/g9Vu494gzqyrIHDWGDSPHcNJ7Nge9Z3FlaQzNgfOJ7N8fJ3U1vPvakB8SymDDThgJGcylNFg2bT7u1s70EGaYCI3dwsPSYuVQLTWcTUxxNDalv4YOA/QM6Kerha2RBrYG8ozva4izmSw+1hoE99CmcLQt68YNY3egDzWBPszo0YnfLxyHD2/g3Ru+/fwSPn3pIH7h9EWeP3reYanfHj2D95/hziNKfPxoCFrAlYgwjs3y4nDAbLb5eJE7Zgy5k6cQP8mdA2WryZi/kCn2wxhg2BlzOXVMhSoZwbH4OU7Hvc+YAuFrN9C7v7IKwwxMcDDtgoWsKhZKaljqaNFNX43OmgI7cwXsjdttJoW3sTSJ/UzZ6uFEuZMdW4NmUOI7mdNlOfDLU3j6Ax8fPIBPf/Bru9+/wrOHz3j//DW8fg9Pf+FoQRnl3n6cSohnX8A0Xhcv5/ukxeQMH8jmwLkczc4hdZoX93fvo3XNeqJ9ZuM3fhLdNfUxklGmOruEwmXp7Rt/T7HIZby+rbLGNyczS1x79sdIKKMlZDHT0cJUTwVzI3nMtQUDjAX2Gn/W/eW2JpwNnckaR1tWTXLk+5I09iRGcn/bRmh7C2/b+PT0Bfe/v8WNSze5deUWv//8Fj7CsYoaQgY4cDajkBdr1/CgKJaPW3M4GTeXyqlj2L8smup5QbjqGrMuKo7GolWsSUnjwdlz1BQVkRAexpLgYLJjE7411tTpd3SkjrqGZ71s7PEbOQEzeR3UhSJdjbrQpZMpJgbqmGrKYK4s6KsssJcShFlqkGFjSunw3uxc4EVd6CyKZrqT6zOV369c4tuDx3x9/vOfM/7mA7T91hEnN9WT5+tPrNNoGsIXcSIllt/2reNq+RKOpQazI3wWhZNdOV24khv1O9hXvo4NOStZOjeQxPAQKguyONrcwLmDLeyuqzv11/1A4oTxof52Qxhn2RtdoYhd14HoqXbGVK87Rjpd6GfZh566+gzW16Bve59urU9Ub33WeY/gu8hZzOqhT/E8T3ICfHi4v5VfLl7k092H8OIl/PIzPL7P45ZGXh7aTUNCBOVzp1MfHUyRnwdPWzfzsLmKxsRASme7UhHozdcrFzsq1v3Ld1iRmEl58WoO7Gpgjsc4dlaVwO/v4N37BX8VsCkqUnvfyuL3w4y70FPbgqG9RqIoDJASunTS64PrcA9G9BrEggmTcNLXwLeHETM6yZE9aQCh9uYMVRMkT3ehKMyfB4daeXnhHI8OH+HHo0d4c/Iovxzew5dzB3jaWM3e9Ei2xgXxXWIIpSEz2FW8Au6d51T5CqrDfODJNb7dvsq3n9u4d+NHJkzyITk5i4O7GrlxbD8f7lyFX356z6u2/3incHff4QI7465oCTW8J8xGXuhhoG3NqKHuhPpH4NRnENPsB+Ogo4Z3d0Pm9tQn3rknPtZqeFiqkuPvTv6CmZzdtoHP92/z65VL/HzmOK9PHIIb53i0o4arNSs5W5HO9qSFPG3ZSG3MfHIXzOb+nm1c31DK6rmefDq2j6cHDnCm6TChftHY2Y4mcVk6adHLuHvsCC/Onubc1m25/+lU4kxji7HLwOHvTdSMmeMVhIKUJlJChZC5kWTGpzPMujdWygqM6axPqKMNieMH42OljoeFPNHj+lAS5k3MtNGsXR7Nh1uX+Xz3Bm2Xz8Ljm3D/MidXpXWQv7l5JadWp/DqaAPrY4JZ7uNB2aIg9mcmUDh9AiWzZnBt8zZKY3NwtpvAve9/5qe7rzhc30Tb1Vtc2LzlXXNuyd+/nnJ1dFk6fJAjc7wC8PKYibqCBrnJWawrLMahuxU22qpM729F0rTRLBplg4O6YHJXefL8nPkuM4ySKF+25CXQdvMcH29d5NON83D7LFfrVnF100ourMvkSm0uz1trqY0NpHC+F+l+3lQvi2BjWBBrA3xY4zeHw/mrSJ8Xy7byJrZUNFMQX0RjcQ23duxl3aJlkeIfoWl7o2xpYcnFrRvr2by2mt7m5hxqaGBf3QZc+ljhYKbDSFNVZg/uxsQu6szoo0uEixV1Sb6cr8/jdN1K7h7cxh+PLvHH3Yvw812ubV/DwZJEzq5N41pdAcfKkji8Kpkkb2cy506lcmk493dt51BWEruWLaI2cB7JE6aSFRBL85oWAj3CSJqXyIHVmzlcVHmhJnTpPz5abEf9huquJw+0vD17YA/ZMYt5fuUktw81kh06iym2ZnjZmjHBQh2P7los93RguZcde4vDudFUzMnNOTw6vp13N4/y65UDfLh+mIasCI5XJLM7O5yza1Npzoskw8+V7KApZAVP51j1Kt6dPcoP29dzozyPCh/PjtPAwvnxLPGKIGpGNOtTV3O8YlNb0/IMK/FfwZ6t6yZfOtDw5di2Cn48s5vnp5t4c3436XPG0ZwXxXxHSyLH2ZDsNYSYyb05sS6Wx4cq2b0qlhv71vP25kGen9nJmfpCquP9qE+Zx9HVcTRlh3VYbYXfeGJ9XEgPmsbzU638eGA7zxvX8+1IAyfSE9gaGUVlZDKFi9JIDUokbOKcL+ULoiaJfwaX91QHXm2p4nbrWn45s5VHeyu4v6uME5WJxLnZMmeAPumzHFg0rgtNhcEcqFrKxsxgbh1Yz72jmzm/vYjNmQvJCXZlU9KcDpsdXBVLmKsNqQGTyF/sS31+Ary7zx83j3B1XQZc2cvFlUmcL83nXtM+CsITGW09+Nvs4ePmiv8OrjWXzzmzKf2PptyF3GksgLt7OboqmsrFbqT7DGVKTwUWOJtSGTOZdUnelMVMZ+/a5ZxrLGZ96jxSApwpXjyJ77KCaC2OoCTcAz9HS45tKGR1Qji3Dn4HHx/Cg6PcrM/k6fZCTuUt5euZ/ezMzqE2reCL55AxQeJ/gh15oe48OPCOe3v59fRGbjbkUhY2Hj97PSqj3AkaaURm0HBWxXpQlTyTLYXhXGgupnqFPzUr5rC/IpraJB8WunTDZ7AR8TNHs2yWKztW58D7H6DtFry9BDd38mzXSs6WLOPjiV00FuS8PVCz+Z+zzT8Cj491e3lq88WnR6rh2UluNBYS7zWQkLFdiXTvTqq/PbVpvpTGeZIb4cbmgoWUxU6jpSKKA2uiqUnyZomHDbHeQ4j2HElNZgxbSrLgzWP4+phPj1p51FrMg+2ZPPqukAvr8y7c2tPYVfwr8fHWQcnLC43hv93a/+5ITRqrY2eRPMeR+BkDWORuRVWSNysWjCZt4VgqUmazvSiU63tWcq+1hB15QWxI8WWxW38WTxtB/LzpvL57Db68gfe3efdgL5e2pfPT/lUfnu1Zs7w+MURO/G+BNzcNv29Zl18QPfP9hoz55CwczfxxXcgLH0dm2DjWZ86lZX0sN1pLeXi0goa8IFpKwymJcGNXaQwhk4eTu2QhvH3F1zfPeHbvGJ9+Ovn+7r7SvG9Xd/77fgBZm7lYO3vRtJDqVN/TsbPsvqUvGMWa5JlsyA2msSKK5tVRlCx1o7k4lKzAEexauZiQif3wdxnIvRMH4POnb++ePjz16unlhbfObNH6txH/e0iZ56CXGuQ0vbE8sqA2J3DPtpKwWxWJ3q/mje38+/bcwN+97NRfzbQ3vLXE02FPdvjsgtd3rkx/fv263r/i5f8H4ORfeM8FbCoAAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/GWDx" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="GWDx"><image x="444" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/stackinspector" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="stackinspector"><image x="470" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/watermelon1024" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="watermelon1024"><image x="496" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/welcomeworld" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="welcomeworld"><image x="522" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/xCipHanD" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="xCipHanD"><image x="548" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/YangchenYe323" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="YangchenYe323"><image x="574" y="28" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAY+0lEQVRogcWaZ3Bc6XWm+WPt/b9TZVkrl/9YDuWVd9dea600I8mjlTQz5AyHCSABEBmNbnRudDc6IOcMEATBDJIg0pBEBgECRM6x0bnRCWgkAiRBEiQ4TDN8tghXactlactay9q36qv769Z93nvOPXW+8919+34HMnfd/uO+S1dOrA+Pl98bHLvjbL/tacgufLRjc71+6PS+Dljsj5wmiyfg8d1x2ezlAZ//uGPO8sf7/n9qcnzmPY/dIX22ujoz3dlG6+kzNJWUsz09z/rwOINX69BHRBOYX+DBUoBVt4cV/xJe1yLrgRVcFhv33IHpdZNXsrngf+/3Br65tPYndpO1bM239nzN48cxM8WW28lA4w2GG2/SUXUB/9AYtp4+8pSJ3G5oYMPrYdnjwumw4bBb2VgJ4LJYWPcucX9tk1W3b9dntZWu2+3f+ncDXzI5/+BRYFO26Vl5dn9pnRXnEl6znQ2vG7/VhHVogFtnq5i41cRQfQOWnh4u5uZwKiODgMPGituJy2rC47Bwf2UJv9XMmtuF12nD67QScCywZZ9//nB6MG2jrf4//k7hl82Ov5y43b/QUFXNus3LlmuZFfMia3Y3G55FbFMj2EcGaL98gfvzc/gHB5m6dZPhhnoypUICC1OsuxZYc5rY9Fh5tuLhodPCw0Ura445tr0Wdhbn2BjsxHy2mHG9xDQnCf+L3wl8R+0Xh2d7h54NNHVwqaCM6+VVLI7O8GVgk6f+ZZ74FnlzbxnfaB/91efpPlXKzLUrVMkkdJ0qQv7ZL5lorMbU0cjyWA+rE3d5ODvE07lRdmaGeW4eY72vFcvVCkaykxhSxjIjDMUbF/x0K+7I5/8mePvUXER5dv6b5iu1tF6p44HLS7ZMydqMiU2ThY3pKTYnBlnqbcbaUE1bup57TfW8uHubtyN97HQ3k/SP36M7V0dfUQqu+rNYq8uxXypjreES6zVVeMqzmDZI6Y0NZjjqCF55NC+SpZAiA23sV2/FR+P/n+BXFr2CZacb5+wCNaerGLjZxJWCIizdd2g7U8kTs4lHUyOMnsrFXJVPqyIWS1EG41o596pKeHixAmtmErXH92PO0zGToWL9YiGWbDVjmlgWMxOx60RYhSEsy6PY1onYNYp5nhTHC2UkXyvDQRUO2nBeyw5Lfit4v9tz2O/2fLW06Nkrf1O9vdSdKmd5fIx8kYBAfw+9p0tpS9PiPZ3DtFbAaEIYZkU0TkUsLmkk9oSTmGKDcCmj8Rvi95YzMRyvOoqtNAmP02Q81MbxSh0HhgQwxPNcHsYz2Qm+1kSALpo3qhBeyoMhPfYrb+RPDv6r4D0ez7c9Hs+O1+3B715k2WHn6eoyW+Y56vMy2R4fYPZSJa3JSkYzNJiT4rGKQwioYnikT2BLFsU9YQiP5FHsaOLwxx5hRRLCpiqc++pInmij+NIo4I1RyFfaGJ7FHeJr2XHQRvA2KZxX2jBe6U7yWh/O66STkBbHl5oQRn7xX57NB//or/6v8Ise3x8uenwLbq8Hj8fDktvJhsvOhnmW9YkBnkz2U6uIY+5UFv2GBAakYawbhQREx9gSn+C1RsDXagFfK6J4KQ7jUexRtkXBbIuD2FGF8WVSFF+qw3kqPc6u5DivFCGQmQDJUbzWh/HCGMaO/gSbqkOsiD8lINqPM+SnrMbuZzHox9iPfDB/X3LsD36jAbfHl+T2+Pbg3739FZeDh4t2tueneGudxnb5FLN5BnokYZh08eyUJfMqX80D6QnuCw7z6l3eauNAK+CNNIzN0E/20uKx9PiegZf6GJ6pT3Iv7iCbMZ/tGfGe+AnWYz9gMepnPDaG8Tw3jlX1EWZO/IDBj7+D/fj7uILfxx/8Y5yf/QM7CYcSfz282/ctj8e36/H48Ls9BBadbDht3J+bAq+DydIcPJX5mHQi1rNUdO7/B6gp5mmKgC3FcR7JQnmRGMVLeQRv1bGgF/EmKY57omMEREfYUp/kZY6UF1myvXTakJzgkTqCXUMcHsGnTAW9z1jwDxk//iMmQ36ET/QJz1NOshz9Ie7g77EV9TP8R7/L2skfPrMf/M43/4UBr9tX5nX78C/6CLg8rDudPLRZeGGeZ7Akl7tJEmzpKhbEofgkx/FE7mc17iBPjNGsyINZFR9jSxrKtjSMl5o43qSIeaqLwysOZlF2nLUUAS8qjLyqTOFhjpwVXQzrSTHcS4zivjaGx6kJPE4V4pMexhT6U1yRH/JYeQjvie9h/+w7bEW/TyD0b3Gd+GvcEX9T/M/gl1xL7y25lp4vuZYIuHysOzxs2R3sWBZYamumL12HKV3NlDCEJ6kStkRB7AqP8EBwkMepApa0JwkkhrGhiWIrMYpHOgEPDUJ8ypO41BFYNOE4UuJZKdSydTqVe2VGVgo03MtRsySJYl0czaY8ik15BIH4o/ijPmYzbj8vlIfZTfgF9gN/xvz+bzF/+D/jFv01XDux++Lywf/TAK47fNJVxxIrTh8rTg8bDifbVgsvFmYYzk9jXCdjKVXBamI0nohPeSYN4Y0qjNfGWJyKE/gzEtg9k8yzCgPLxth/KpUZMh4XaHAmRjInDWVSEsKsNhpnvprA2Wzu1ZTwpKacV5U5PMvWcN8g4rFRxIs0Mbv6aDbjD+AO+j4vlJ/xQPQTthK+jy3szxk68h5vzhzky/MHEn5l4JHVO/PAubzX9i6aTSwtTLFtHiPQchVLjgazNIQ1WRhr0QcJRHzCK72AFylCVtQReDJljCdF4T+lh7l2JvQRODOFjIsO87zMyJM0JcvSaO4lSXBphARK03nwxVmqZSEs3TrN264LWFMi8abH4NWHMx/3CS7RZ1gjf4455MdMHfkfbMj3Ywv7LivCDxg/8KeM7/8m1qA/m9qD35ld/OYzq/+tf8aMe8HMus/Nin2Wx6ZBbBcLcWcr8EhPsKMM56Uqgi/VUTzRxmCKOURv6MfMG6Usn83HfS6bm9Ig8j75b+T85C+YM0RjU0eyphGwKo3hgU5GQCfn2ZVTPOuooTlDgqm2COd5Az3yAwzLPmcw9pdMRH/CdmYCO5liAorjmKN+zsihv2f0s//K5IHv4A39PlMf/imBo3/7diP4776xz9o+eMIzMMN4Vz/9nd3YTLNM3e1gc7KPu7laxlXRrOqEvEyWsBZ7BE/kIZbk4dgTY/BkJ2HKMLJ29QKDWTpKg37OpbjPyfr473jSWIEpOR6XNo6VJBFeeQxj4YdZK0phu+40nmslPOq+wrAxikHZEbxZUgLpCdgkoayqY3igF/FQJ8AS/jE+4SEoVvFcF86u6hhLwT9kPfgHPAr7IGjfXGtfubV/AtvEPKO9/Qx236ap+jyP58cYzDUypYnHmyjgoSaeLUU0Dwwy/PoExuWRLBZl8KihgdmiYkqCDnFdKaBaHkFl1AEYa4Y7NbSF/HLPrE8rZE4cytNz+excP8VuezXbzed53nSeAUUYzcc/ZjT+OA6FAG+ikBWthE2jnC8LDaxpYlmSh7KuDMMXvZ8d+Qlsn36X5eAPSvf5JufvWIYmWFv0MT82TnPtdeoqSnlpnWG6LJsBSRQzcSfY0Ip5mqVlSS+lO+IIPcoYGLvL1wPDzFec405uDiudzTRmqGjOUvBmsp23gzdojzuEWS/AlRSPXR3LV7WneHPrHPTWstVwei+d5otSGEqSEajI59X1ar6quQR1V6Hh3brEq0tlUFcJNaewS0MYC/6Qlvf/Cr/g89v7thbdPvvEBAGng+nBAboa6+ivvcqr+QnW6y4xLI3BpUngQZoGqySSnsjD3JGEM1mQzG7fbd5OTPO4ZxA8HvDa8XU28ni0HRxDTBSoseQmYk2TMiWPYF4dy5NLhbxqOseLzmoC9RWUhX9OZ7aB+XPl+Gsu4b1Qhbm4AGtxIVNZqey21POs+ToMtPC4rpK3LRfZuZiHwxBP8+EPPPue+N3bD7xO1pxmhtpuMd56k9mmOpx11by6fYuNU7k4tUIWxGFMxgezVJzKi47rDBenkn745+yODoLNDC4zj4a7eNDXBJYhmL5NlyqCcW0csxoBjjQFD84V8uT6aR7eOIf9cgGm6+WsTd7lud/B1vwED2fGeWVd4I3NxGvrPIGedtqKsxi/dobZ+iq6SoyYr5WwdOMMuz11OM5mPtjnnx1+9Xx1Ee/0INfLcmmrKqExU0/BkY/xVRWyXprBzc8+oPngBziSE9ipq2Cn4xpT5/P4IlPJ6MUyvrZP8WyqF9zTYOrn9cAtls4X0CePYE4vxpaiYO1UDo+uVzFflsnshSLGq0t4aBnBY55gc9WH1zrPptvJE7+XNfMc224HWy4zD/12ZvvbqTuTy5p5kKeuCdZGWvB0XsPTduXlvvvOyVcP7BOszg0wUHuWa2ka7hRncFUQQr9GwExSHAvqKCzaKCaUYcznKpgpT2bjznXMt6rYnGzla88wb6w9vJnphPE2fOdy6JdFMJsYj1Unx2JQwt1OmBygM8dI9/lStn3z+F2zuH0O7G4HHs8ia8tLrPp8+Gx23Dbb3iTD47IS8NvxumZZ880x3FlLf8N57l45heN2/ct9z7zT24+cY9xfGGK+tYamAiMtGSpuKKLp1wuwZEmxpMRhTo7mSU0+Lzovsd1VTaCjmvGaYlYmvmB3sZcXli6+mmuH+Ts8bTyLySjFpJUwrUhg+/wZcNhg0cFwzWW+uHCG4eEeZiwzON8BB9ZYdPmYnzXjMDvZCKyzvryG1WzB5XKwtr7M4qKZzYCT0a4m5nuamW2tY3Ws98G+jdle72P7KF+v2njumsbSdIWmTBV30pXckAQzmyNhSBtKS9xHrF/J5N6NclaazmCqLWWyoZzx1tOsL7SyPd9GoPMii9WFTGdrmEyS4SvIYS7ZyIvWdphbYGt4jJGWNhrq6mnp7cOxdg//0hq+dz2Ye4UHS1usu1ZwzdjxW7w82XiE02zFY7djnhhjy+tgzTTNrtOKrekGw+cqPfscA613emoquZqrpzbXSEtJFrXJCvpKUkj76O8ZzBLREL8f/Q//hPxP/zvlIT/lsjSInvJUHF013LMPsGq9y1zbJXoqMxkqy6A/S8cNURzVJ0O5d+MW2739mBtbqSutojizCHliMrGKZPQ5pygurmKkd5wVxwqLMy788x6erz/l6fpjnLM2nj/cYdnhZLS7m97Gemw9d3g8N8PT8Ql8zc23910vyy0faa7DOdjN+vQI3r5uRq+dY2OolZvpUuz1pUxW6bim+Jzc4B9QEPozJB/+DeL/9T+J/PB7HPrp9xGGHsEQH4kuIgRt8GGMx46SFhxM9slIwt7/CUd/9I8c+ulHfP6LQ3zyURC//CSUnx+I4GcfhXIyVEjosQiSpDra6trwL/hYd64RsPn3hmfOeSuueRObbjfjba0sjQzj6b7N69l5ngwOlu4baWs6fveLOmpKS+i6Vr3n0N3fw+pYD9UpEq5nCGkrVnIzV0R9hoD5hnLaS4xUG2RoThxDGh5DxLFwjn96jIjDJ5BHxpEklCI6GcWxTz7j0IHP+eUvDnAkKILQcCmffhbN/v0xHDss57MDsXy8P5ijR8M4cjiEY4dDSdVm0N81wIpvjY3APbbu3d/bHfodNuqqTtN95TJdlRU8GB5kd3z82L7F6elvOCYn3w61dbJisfN0KcAj9yKrs6MM37jE9UI1HefTqc4SUpMtYbKxkvG6KvouVnCr4gxGWTpKSRYaRS4aVQ4isQ6hXI8yNRdtfjEhcjVHxUpCJDpChTqOBkk5+ImQkANyQg9LESoNHImK5kDwCQ6eCOVQUAgRsULOXL6K3beExethYdGGxT5Pb3czfS0NdF05z9C1S2/7L1R+Y68jNU9MTjfV1GMem8JvsrBms7FinuZZwI4h7ij15Uau5CrouVrMYF0VTRUF5MkSSBeryEk+hUZVgk5XTlr2OTSpZQh1OcQas4gwZBCZkkVcZiEx+lwE2lwSdaUkCDKIOapBFGHgaFg8R+JEhIkVhCVI+TQ0nI+OBBMWL0KXnc2kxYx71c+i34nTaaK7uY6emzX01l+e+NV+YNXjkjRcucyp/AJmhgYxjQ6z7jDzyGPj5uk8Kg1STmlETNy8Ssu5CgZv3uBCQRk6iRatKgNjSjEaXR7xUiPREh3hCVpCJWqi1EZiNGlEqZKJ12QSr8ggLEpNRKQasSCFhPhkYgRJxCtTEGkyiFUaCBMpCY5NICgiliOh4Wi0Otpb2/aGwM+27uGzzTFw+xZnijJFvzKws7Xxnsu6sDsxPMDmsh/7zBRLC3OsW2YZv3GNodrzNJXnM1h7mdqyUkbabzM7MMmNmiYK808jVxkRiFSo9BnoMgqRJqUjNWSRUniaxLQiVMn5JKWXkZRailiZQYI0FaksHaHISGy8AZEsA4kmlwRtNgJ1GtHyJEJjxQSdCCdJY6Ast4BzxaX0t7Wx6rLxeHN51+2Y++dnCsseV6ndZGJ7bR2f1cID7yK7AQ/Ou+3cLMvmjE7BwPVLDHzRyGhHF44pC0N3RpkenaeluYvK0xfRJ2chlutQ6tLRpOYhSkxGacxBmpSxZ0KdXIBYlYlQlopAnEpEtIYogYE4SSoiVRZSfR6K1AKkxmyixGqOhURi1KWRoUshWaHmdF4e3bduMDs2UPQvphLLbve3rHNzuxs+P16LeW+k8i4CS6O9nNHLOGdMZPJWHbaBu8z03mX8zjDD3UMM3u5n5O4I3e13KCkqRyiSIVPqMKTmIUlM2YuIwpBNYkoB6tRCZEm5yHV5KHWFCOWZxAiTiRYlEyNORajJITGjFHVmCfFKA8fD4kgxZJCXkkN+cjpFaRlkJGmfJquVv/54aqRvQOux2PHb7DzweNiwzjFUd4kSpYC2M4XcvnCa5vNV9Dc1c+tKI231zXTfaGO86y72SRMT/SOcLq1EkiBHpTKQX3wGQ0YRMl0m0qQsErSZxCpSEaqzkemLkKjzSFDkEifOIEqUSowiA3lyMZqs8r17ogVKNOpk9CoD2fo0SjNz0Uqkql8L/08Ghv7gTnPnfGt9A0OtrQw1fYF/5C71hWlMN9WwNjWIe2yQe04nc4MTuOdseKfmuGe17117b7ZSkVdEQqyQmMh4jMYstIYsEhKTEaqSiZEbCYlPIkxiJFadTYwiC5WuHLGygOiEDCIkacQn5ZGYXr4XMXliGpIEDYliLbnGLCpyiud0UuVvHi2+U09L97d7Wzp2XJNTBOan2Zwbp7kij2s5hj0D9sFeLMPDmEYm8JisOAZHWOjq4VxmDkkxcRTok8nRpyCJkyATq9AZs1Hps9CmF5KYUYzwXbXS5yFJK0VsKCHRUIlMU0a0JIcwYSqR8kwSDIUoU4pQG/KRinUYVGnkGXOelaQX/OW+f41G7wx8vjg1+9Xi+DCB8QEst29wSpNA96XTFKjlVOVlM9U3wMzdIQKTM7RUVBL/6eckRcUweKuVtpoGjAotqfp0xOJERAoDmrQCknLKkSQXITQWkJBeitBYjFxfgVRdTrQkj2BBCsdFKcQkZiEzFO4Z0CRmoFOkfKURaT7d99vIMzMf55+ewtbdwUuvmZpcI+WaBEr0Ki6XFtHT1ELPjSaGGm4wWFPLYF0j67Mmvqg8T5JAQu3ZanJSczldcQG1LovIBDWxqhQSkgv3DAhSilBkVaJNv4hQXkSsopBwaTaHY5I4KU1BnJRHbIKOZGPB26yUgpjfCv5XJsbHIx6YZt6sTfbRf+0MF9LUWPq7MA/34ZyZYaC9k9qiUkxttzF13KHtYjUXcgrJ0yZTlJpHdeVl0pLzSNRkEC83EKNMJvZdrU8uID61GFFqGerU84gUxXsGohR5BMUbORqrJlqWijwp+6uU5ELBvn+LtuanD3ZdKHvadqaA2sIUVk3j9DU1Up6ThUEmQxUeyfXCUjZMdvobW7iQV0LrtUauVVZz/XwtCqkOlTodhTYTgSqVmMRMRMmFv0ohmaECheEM8YklnJRkcVKWyYkEA8fjNDtRIu1vlza/MRIDHX9uaq+fP5+mIl0Sg0EciyQqAmW8gJgjQRTr01hbWGRhYIL2azeZ6R2jo6GDhiu3MGiz0etyUely90qpWJ+LJLV4z4A4tQxxUhmG7MuINCUcExiIUucQp82dOxql/Pa+36WSI4/+B134IZkhLvSpVhiBJkGAWpJAZUEZvU1dDHX00dnQynDnALe/uM21qlr6OkepLK8mLbUYRWImSn3uXnURG/P3oqDIOIVM/y6NzhKtzH/3AT+PUGWlhUmT/3Dfv5dSRRHflEYElVyrqtjt6+hkdmyWqaFZ2hs7uNPcQ0dj1x58a2M3PR3D3Ki/TX7eGWTKdGTaLBTv0keXs1dKFenlKJMriJXn7IaJ04ujE3N+fz+ALNvN7w3fvSueGJqabLnV/bava4SZMTO1l25SX93E5JCZ+istdLQMUXW6liRd4V4jJ9FkIzHkIUkueCtLLZmQ6ooTwoQp/+n3Bv7r1N7a/0fD/bNBHS39pfVXWrpaGu+42m/e3b5+6darzpbhV9eqW7Yzs864EhTpXUJleqkitSgoMbPsj34XD//f8GrjONMZumoAAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/CuteReimu" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="CuteReimu"><image x="600" y="28" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAYnUlEQVRogcWad3SU5br2n+kz77zTW6YkmSSTTHpPJoWEJBAgIQQCSCCEFnoVASkCoqj0qlhRVJCiWLYNQRAV2aggiG5722LbCIh0pcjvrAzf8nxnnb3P+vY5nv3da93rWWv+ea/rfe7nfu7rekeIPyC2blgT07u2qKV7ecbq8nTfjvJUz+e9yzNO1uUnXqoMey/VF4ZP1uaEPk9xyDvsQqy2CDHArlTFiP+fMXfebMc77+ydtHv7kwcevmchDVX51HXIpCzdR3Gyi9r8JKozYimMs1EW8lCZnkBpSjypbjtOtRpJCPRC7HdKYqLXrnT8y4DLdnvAGeNZdeOMKedf2b2NrZsfZOkdM+hUnk1thywKU32kx5ooSHKSn+ggzWMkZNeTHeuiIjtMYUoSbqOhHTwWnZqgz0zQJ59L9FpXpvpd/v814C6PWyOUyuuFUpxVGTRc19KHtevuZvXqhUyZPIKighRKi9JIDboI2LXEOnSEYmQSnEZceoFXVhMOuEkJ+HDKEnaDRGyMi2DQTZzPQtBhItluPp/ptN+S6TLr/lDwKfHesMNhOayT9ch2M8FwkG69apk8fQKjJrTR0LMLwQQvycl+HA4DFlmFWRL4HAZ8DiN2owqTVmDSqzEbtJglAw6LGZ/XgyvGgtOmx6fXEtRqCBv1pNq176a4NCl/CHinWvSx6sRZvV6QEIolIzeNko4RauorGDSyP0Udiwlnh5FsEhanCZVWIJm06PQCu13CZjZgt0jIRi0atUClFOh0GmTJiMGoRyOpMehVeNUqEpUqQjoVKWYlaR7FmTyvaPofga9MsAz1qsTlZK+RwtxkSspyMNp0GB1afMkeqhsqcQVjsPpdKE061BYDQiUw2o2o9EokiwGDUYtsNmCySFHAWr0GtVaFRqNCqVMh1ALZqCNsspJnspBpMZDlUJPnV9ExqL4yIts95r8Fvq0yZXT3DDcFXj1hjw6fU4vDoYsCjE2OwZfswuK3IHmsyDFOtHYzGpsJoVViirEjDGrUkjaaGkmLwSwh20wYTRJqrSKaBrMeoVHgspmJ+OKojo0l4rNHn1kW1NGQrGdWaZBDC2+Y+E+BH1ed0Wdq9/wrTVkuhtbmUhp2YDcI0lO9ePwmbF4Jq9+IO9GN2e9E7bAiZAPCqEcY21cdQtIi9BosMY4oSKERv++ITlIhGTXojeprv2sUVIdT6ZGRTn1WMh0SrDQV+Okdkljbt5LDd0y6smPO6F7/T+A7xRlDY6rCp2c3lTCuNoP+ZYkkWwU2rSCUYCc+yUlscjtwCZ1Lj9omIWQJYdBdS1lCZZJRW4xozMbojikNSoxWCY1egVCI6Plwu+VoWmQNMRaJThlpNORk0C03RJHPQH3YRkuqhU2Du/FEWwOX9mw9yy9fp/6X4CN+i7Y2aDo8qCjAjMZ8bu7XgT4FPhL0grSAkeR4C8FEJ4GQC6PHgMqmjta+0vR/vXVJi0LS/Z7RM2GVsNklDAaBw6YhLdlHVthPnNuIU1IQY1CS7XNQHgrQNS9EoVdPdYya1mQru2cMZ8OQbhzd9hBXvtp3iKsnNP+QQLHfOrMmXqZHsszo8iAzmwrpm+8lL0ZJn855ZIU9eLzG6CEWRoHBZUBIyt9rXalXo9BpoqtSr42eB4VKoNUJ2ruY264lI9lDQbqfjEQbYZ9EvFHg1wgcKkGCQ0vHrHg6BO10iTEwMtPPppFNzOoQ5oeXH+X4e9v57uO90/4ueJNS+HN9lnNV8TJd4jQMyLIyviZEc4GXhnw/kwZ1pyQvgfgEJ7JTF61drb39EAq0elU0VRqBSq9GJ2uRZAManRKDQYHx/4AvyAxQXZRMbpKdkjQnwxvL6Rhvp8hrwqEX2GRBakCmMuShX4qPOVVF3NatmNt6lvLT289w+du3+eztF892joS9/4mAUSFWZXmtVCdaqU800D/TQlupn4GRWEY1FDG+pRuVkTClpVmk5iYjZCVaqw6L3YjdJmM26dHqlOgNaswWCaOsi/b8+IADr0OH16YmkuGnR2UGldkeGssSWTSxP61FKVxXmEyCX4NeEph1IkpgZG468zqVMrMqjzvH9GbXowv44LXNHNrxGDlx5uX/AbxSIzvMWvX5DK+FqgQLPVLNtOY6GFzkoW+ei+ktNfSpyiErxR0lkF+SjdqqxeiS8XmdBDw2HFYDskEdvbhiPHacDjOSTpAUsJMadBBnV5Ps0tAxy0t1lotuuTFMaCxmTGkarZFkgnEatOZruzCgsoAbyiIMTQjQN8nFyOoMnrpvLrufuouBtbnkBYzncuKs/z4AqjXSJLukJ81toSzWREOqnZb8GPoXuOmUoGV6ayeKk23YjYL4oJ34sA+hE1i81ihwt0mLTSewagVxTomcZG80k7wmkr0mencpoWdNPoUhJyWpNioy7dTk2GipSmZIWZjGHD9+Z3uZCYoTJZaPuo7bulZQIQQRnWD+sEZe37qGrffO47ryEKumtdIz4h//OwGb3nTAodGQYNbTIcFNQ04sXcNW+hT56VsWT3lYJj2gxGoUyBaBM1ZG41Cjs2kxKAVevQKfXlAaslGeZGRsz2Luu2UUdQUBBnQpYurwviyZcz2FqTGU5/roXB5HapwgM0FBa48yukWSyXAL0g2CpnjBtlktrBtYTYNZUGkWDIyk8ey9S2irK6JDrIJVE2tZNiz37Sj4BLPd61aqrlqEIFYtyHdLdAm76F0QR+9CH/0rkyhO1JESI4ixC0wWgdAKtE4NtT1qMGsEQZOWgEbQUhVmRksZA8q9zB5UzvgeeWQ6BL3K0+lTXUCn4hSq8gKUpFvo3SmRIb3z6RhJxKYUZJkFzWEVw4KCLYMjbB5Uxi0ViVRLggHZcTTnhegaspKjFfSIEzw2Ie/qrlsrPCLdaGhJUivwCUGmThCxK6kJGBhekUJDqpXmSBwVSTIpToFHFlhMAqEUSE6ZEWPbyA3HYWsnrxdUp5nYunoSq6b1pChGkGoUJOkEOU4VpfF26nISKYjR0FQUz/N3z+LiV6+zfvUM0pyC5gIba0dXsaCTl62DC3lmSBlre+YwMlEfbaP1TsGwbBsDkwWNbsHTkyPsu6O2WQyJ5Kxui2QzKC+FCdV5TOiYyahIEquGNzC6IpnGVBv1GW6y3GpMQuA0KrFaJKwuGz0a65g1YThTh/akPGwmxSK45+b+bFw2gg2LR3Dr6C5k2QXZFsGcgQ1Mbqik3KliWHESD9/QwpGXH+LbfVvoU+xkxegq9q4cybKusTzcK5lnWwt4uD6ZJREPq2uSuLnIxewiG3NLLMwq0rK0i4V7m9wrxZTqgh1TawqYVp3LnLpiZnTKZniOlzuH1jG2PER9UKJPdoCIT46+aa+kId7jwm130CFSQIxeUBjUc//toxnXr4Bls5rYvn4Wu7fM48jbG6nPtNKvIJYXV8xl7eShjMxL4ta6Mu4b1J07W2u4f2ojQzrYefOByXyyfjpzS2UWl5t4dVQZuwcXsrGzj81dAjzRI5GVxRIL8tUsKZWYnSNY1FHeJkYWJn85INXDoHQPLWF7FHwPr4ppNRkMzo6hT4qDnqkeKgNWErSCBFlHrNlIwGqlsbqc6kw/HUIS88bU8eKjc9i/YwV7XljIleOvwc9v8pcd93Hk1cc49vpTHHhwGTfVFDC/cxErGjrQSScYmKtlXnMKP7y0mHfvH8+MQgNzs1W8OiLCruY0nu8aw84eAXb2DPJy3xCP1XpYEZG5u0ss6/pkfC4mdir4qXeahwHZsfRJdTGtaz6Dc/xcX5PFuIpUWvPiqE+yUx1rId+uI8OqI9msJ91lpbmqhB0PLaKtcyqrZzXzwWtrOfP9Dn47s5dzP+7i52+2c/zj5+C7fZw/vI2L+7exoLGCNQPqmFORSaVGMKLEyOO3NPD+Y1N5cHQ5E7NVTEsT7BhayEu9Q+zpHWRXnYPXGrwcHJLN9n5prK8PsaFvEXd2yzgueheFL+bYlZTHmSnx6hhXV0JTtp/GNHc0WyMh6kLtBEwU2FXk2zWUBWyUxtrpnhHH/k0r2H7vTD7atRYuHObCsdf46ceXgff47cJ+Lh3fA8f2wQ/74ft3mNgxlXuG96IpINESlpnbJ4kD6yewe00bs+r8TMiXuLnUymcLB3H6zhEcu7kHbzTFcqg1nT39wuwYkMf+G/vxWGtn5pSFfhUlGYkX42x6jEJgba9xnSBWJ6Jtsb1kGvPi6VuUQGWsxLi6Yqb26kCJS0F1nJGBkQRube4IR/Zy5pOX4NQ7XDpzgLNn9vHTyT2cOf0G50+8ztnvXoErn/D+82u4f0YrTyyYRNckE8U2wYZ5PXlmSR+2zG9iZo8gIwuN7FkwDA4/Dq+s4cLdY9jdnM6BEaV8NrOJLxaO4c+z21jb2p03l8/7VeQX5vzk9TlRqwUapbgmvjUCi+rahFhfFGLpDUNZN38icwfX0ZBuo9guKLQIJnTOoDnLyTevrIdjB7l84iA/H3+Li5c/4Ovvd3Hh4iHOntwLv/2FKz++zisbb2Xn+tt44/EVdMl20zlD5u4ZtSwZW8DS0UVMa4xn+dAIV/Y9At/sgo+fhW2r+PmBG/nk9qG8Me06tk1u5ttNd8GRD+CL94+LcEHeF9aAD6FXR/Vpu05Va66RMagESR4DN40dwCub1rBoUjODq1IYUROmxCWY2ljA4mHduHNSPzj1Cae/P8DlS1+w561NfPDZtiiRK78chMvv8e6uNXyw+352blnI8+tv57nNS+mQJXPH+DKmNweZMzCVm1vSWTu5lqPbV/Hd00vgnSfYv3wS22cPZvf8MexfPZcrb2+Hc9/B8a+58vGhz4U7JWWH1u1C6HQIrRZh0EdneYVWoGmXeypBSWaQ26a0MaOtJ8umDGTRuF4M7pDAAzMHcdf1zeRYBbfdMJAT373LyVOfcYkfOH3hEy5c+IBjR15mzfwWGiNmmkodpNgFGQHBkxsXU1Xkolu+ggk93NwyJI37p1WxfmY3ti0ewlPzBnLqjcfgyFvw/WHOvvsq/HIMjn4G337Mr18cplPYt02YvN7VaqsVYTAg9AYURhmlUUJo1VExohACk0HQo1Mpbb1rWbd4JvPG9mXeiJ48f++tbF42g1SHIM6hoKpjFlufWcfXf/uQXy5+y9OPL2PuuHq655mZ1b+IulQNA6sSqc6yU5huIyekpUuu4OW1bby79Xre3TyBXatbeG7BdRzcNA++fwsuHYVzP8KFU/DbBS6c+Ibdf9rAHVOG0do1f6WwOOwDJKsZjdGIymBAYTAi9BJCpUUolJitFtTtslCrxCNrGX5dPXPGDWb31gc59uFe9j2/nofvvDUqWtrlo9ltpL5XZzLSfLil9tnewLLR9WxbOp6GBAUT6rIY3aOQTL+ORIegMaLh9F/u5vKH97BtSXeWD0li8eA0vtixEn75nC8/2sddd69izoKF/PXHo2zY9DBZ6X6GXVfB2P4d+okYh8XjsMhXjZIerVaLSq1FodEjVDqEQoNQqBFCGd0JSaMkxiyT4ncRa73WuVJ8MjlpXkwWJUIvcMZ7UOgFWqXAoxX0yfXxzkO38eT0FsYXeemZYIiO0M1VuQSNgvFNcXy5czbfvHwjd40IsrzVy5JBiby1+SaOHH6Ookg69sQEhM2FcLrROE2o9YJ4t7jatdTtiU6kDqtxv9xuOKkUKIUCtVqLRiuh0kmoNQaUKk2UhFk2oRaC5Fg/XpMJj7ldxAgUSoHDYyAlOwG9SYvJrCXWJRHQChaO6MXO5dNZ1LuEu4fUMiDNTr9MNxG3ioZsO/OH5rJqXAbL2+IYWSxYOyGV6Q1Wmoq05IXU6GWBPsaDsDgQdjfCImH3GojkON/8dzlplScaDDp0WjU6lYimVqmIElIoRNQKaXfThBCohMBtsmLTGPDbrHh9crR7tVuK4VQ3hdlxUec5xaVh86qbGdEtn7WzhrJu+iAWDa4lSyHom2qiPk7FiFIP8/uFmd8cZHC+YGpXifktAaY1eemUIagqsOG0CWxuC+5gPEKnR21QEQrFUJzrG/c7AbPH6TCapHN6nSZaJiaNMmo26dvbqfYauPb6jt4XQhCMcUf9fb9VRqcRmMwCq0Ug6QXpSVZyEi28tHE198wdy86Hl7D59klcX5dPxCQYWuhnYnUK/dJkJlUHGVfhZFJnJwNyBXOaE7l/Zg2T+iZQmaGgvmM8NosgEOcgISWI2qBBaxAkJDrPpSZZ/uM3BYNRv1KjVqJXKpHbV9U1I1bRfjfoBRqjICHZjSwJEvymqMbtWppJJC0On1WLXRK0DujGogU3sO6++Tz50CJ+++4wqye00FYY4ubuZawb35+Z3fK5Z0Jf7pzUl8Hl8bSWxDCo1EVLqZUFYyvYtGIobT1D1BRb6d0jB50kCKUHSC/MiJoIalkQFzIv+0+uhMGo9+u06nNGjQZZq0WvVqBsLx2dQC0JPHEysq3dcRa4bIIuFUFuGFZPcaybLtnpjB3Ymz27nuTrvx7g4IEX4OpRPnv9KQbmxvPI+IE8M20UHz+4gt1Lb2LtlMGMaSiksThAzwI/XVLNNBa4mDwgwk1jaijL1lNWaKegwIOyXRCVhCmuLsAUo0djFmfiwvLf/zxltZhmOEwm7LIc9fB1elXUjbbE6PAkGKLdxekSBHyChlo/g7tn0CXk59W1azn/1Sf8dvpbTp38lFMnP+Tyzx+z9PoBbF88g1PPbWTvLTfy7PXDee/BZYyqyqJztoeKLDfdi8JUpweoK4ynuUsmXcpjSQwIOlYm4vII9CZBeec8KrsW44yV0JjEVPGPwmWXNQ6T6ZBVNkX9e0nSo5M12H1GFMZ221zgjxWUlxhpqLFRmyPRKznAwYcf5fKXH8KvP3Lp58+5+PNHPLRsCgeeuotLbz7Hpw8u4fN7l3Dk4dXM6RqJzlE12W4yY/X0LM2mtVMHuhWFqcqLIyMokeBXUFUZRjIIvH4tdfUldOqcT3yCfFA2i39sLbaHSa8JGTTa0waDAaNJRiWprjlxWoHdI8jI0FBX42b0gHTGNIRZ0L87n21+jCsf7OfyF/v54fAO7rl1FGtmtfLI3GH8bfs6Tm57mMuvP8Xn61fSENBTn2IlqBe01OYytFM5K26YSE16kDhZ4DcLArb2Vq2PdrP8dA/N3cvp1iHzbH7YFf4vwf9+HjTKJlmWr1idDiwuG7LTgMOnj1oqZUUuyrP0LJ3enUfmtTK7oYyjL2zm8ju7+GHnFk6+/Qxfv/Iot7Z25MSfN3H2rS2cePURfj3wNFNrM+jsU7B0VPfoLPXCmnmsGt/Ge09voW9xJn61ICNGR1qMlnizINEq6JIXx7CuxVd6FaY0in8mbHbTKKNVxhVwoZWVxARMFObHEmcXRBJVPLZgBK8/MIsXF0zgzO5N7F0xnf1rbmJJ3zLubqtl86z+nD/4BBc/fZ7v317P8fefoMAjuH9GX/j4Jdbf2I/PnriLqwdf5YunNtBanEZpTLviE+R6VJQHjRR7lIyqzr7aJz1mhPjvhMNlGqqWxOWU9AAVldnYjII0jyBVEtw7uQ/bl47jpTva4O2NHN26jFPP3MXS+myGp0gcfGA2Fw4/ybmvXuTIB1s4+uWfmDmugrMfPQ0/7mXL5J5ML43l9roI94+6jmldC+mT46UuzUn3LBfDqlOp9Ioro0qCo8X/JEKpnl5xCfKZ1CQTQbsgoBTcPbkPH2y4gy823c7O2wfy5yWDYf9GPl4xidl5bpbV53Lm1fVw6l1+O32AUz+/wdFjO3ly4ww4/hpn31jLwcWjmJpqYMPwerbdPJo7mjtyQ10OG28bw4z+5QyvCp4eVGT/58rmH0VhkSvZ5xKHChMFvXIllg8phxNvcnnXXeya08i8cpnbSmxRI2pVlyxW9Ihw8eALnPpoJ8d/2MepC4c5d/k9vj/yAhe/ep73103nw8UjWVTi4csH5vHVlmW8uHAiC4Z15v6bBvLCfVMPbrtnYkj8kVFbKamrMsT1S0fln3l1WTPPTK7gizuH8UC9lw1NiWzpl8umAeXc07cDm6YM4tKn++CXbzh34StOnP+EU+f+wpUzh/jmtbUcuucG9kzpwcqOATaPqePXNx/n+N7NHHpm1fk9Ty685dEVw7Xifyve3dzmvfja3BW3dxTnHm/28+exxbw8KI9Xx9Xy0sRenNm+/prk+/U4/Haaq5zl5PlvOXb0PX75YT/vbFzA4TVTeH54JU+0RLjOJxge8Z17dP7w5d++88S/7g8gd9ULx1uT0ybsa019640BeVef7J3LhWfXwNm/wt8+5crZE1zlMn878QPHT3zHb6e/h19+4MJbf+Kvj9zKY/3yr97XmPFmS0g/vneOw/4vA/734pdFbW4Obm3mradWcurLl7j80ycXzp786TJc/Pn8+Yvnzp7+iVM/fsIvx17i2IcrTzy1ovmRphz3H/HwfwMg7FwOb1b57gAAAABJRU5ErkJggg=="/></a> +<a xlink:href="https://github.com/xiaoyv404" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="xiaoyv404"><image x="626" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/MukjepScarlet" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="MukjepScarlet"><image x="652" y="28" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAATzElEQVRogcWa+ZNcV3XH54dAfo+rWIr8SEL+mhQUCS5IUuGHVEgFMASFxQkEk4KAV9lItlZbu0azaPaZ7p7e9+7X+77vy+vX+zKLZkbSJ3WvLMUQWzFgyK06dd+87uk5n3u+59xzX8/c3EcwTkaTT52MJl85GU3eOBlNDCejSeFkNBmejCbHwo6H4+HxcFw4GowMR4PRG8eD8ZePh+NPzf1/jiNt8Mz9wfi54+E4cDwc80F2Mpp84GvHo4ly3O9/k8nkmT+Y4wdq909P+qPXH46m+4edHkeD0VPtaXDHwzFMJhz1env3ut3TTKef+b05Pqm1PsZ49q2j7mB2T+vzcDRFzP8XwNMgjgYjCbCvqgKCh+PxfikSeSHp8/3xR+p8JhD6XC2eijKeIWy/rXHcG3J/8MiJp9lhb8C9/vBXQMS1uHfYG3B/OJQAB50Os1aLiN1OwGqN7Gvan38kzh/0Bl9MeP2zmMPNuNbkwXDCgdqVJq6FI0+zfa3HQbf/BOSx4+LevtbjXrfLoabRK5UoRSJ49HrCDgcH3e50f9D7wu/k/EzrfnVf650Uo3H8u2bSXoVZU5WrLwBO+iP2Ne2pNlNV9jod4RCHvZ40cS3uzVRVAhz3+xRCIdw6Ha6dHfLhMMfDIdNu5/5U6/3Tb+v812aa+ENd2vkiHt0ujs0dOrniE/0LCOHE02zSaslZwAjHhT0Gm7RaUvsng4GUztbt2xKilctxfzxmpLaYdHrMhtNv/kbOTzvaF6cd7f60o8lw9yo1QhY727cX8BlMMgocHMkIDOt19jSVo2Gfw36XUbNOt1KiVy3LazHvdzvcG/Tk6wc9jUG9Sr9W4WQ8lKsfMJtZv3ED/eKivNZKJQkw0VRm3QHTweR+UIl8/kOuvPbZaUebCOeFzVRNRqESTbC7tMLWrTuIfBhW6lK7nWJROjRuNaSz9UyKQjRMPhKiFI+S8HmoJON0SgWmaosH07GEEJDdSolqPE7QYsG8uop1fZ2kxyMjIyTUrVeZan0BQFCJzPz+6F88feW17sdnWjf62Hlhk5YqK4dwWDFaJIBtfYt8IIxWKMhwa+WidF4t5iknYmRDATJBhVw4KEGqqYS838xlZLREJAS0Vi5K6QinFZNJJrAAEs6fjEYM200JMOmPCfjD+HzRsD+U/tjTAH4gdP9eABEBIaNpo00pHJNSEpby+MkFAnJ1G9m0dF6YcFJEQcziZ7HKQkrCWfE+MYv74vfKiRgJt1t+jgDw7e6i5nLc6/cfJf1oIHNg3Buh+EJ4vRF8wdS/vr/z3d5nplp379cBpu2OlJDQvUhgsfIJl1da2ueTq1yKh6lnErTyAiSLVs4zqJeZtOs0cylmnSaH/Q7jVk2+J+Ky4dBt4jXtUgyHSXm9MnlFNIbVqpRQv1rlYNhnrHYZdYdPALyB5MyuxD/9PtrvvT7Vuvw6gJCQiILYvHrFilx5UZFEFETdFnovJyISoF3I0Cnl6NdK0lnheLcitN+Q18NGRcIK580bK8Q8DprptFyImNNJK5ORSS1KrACYdjuM2poE8HuDeDxhAYDNH3/1151/Ztbt7b8fgHBeREGUzEm9RSEYwas3EjTbKEejUgbVVIxGNilXVwD0qkVGzaqMwH63LX8WrwtA8V6f2YBiNcr3CqfzwSC1RIJJoyF35MclV1QhATDUBvg8AdzuEB4lgdUX21tYt/xPAzjr9p6bdXu8H4DQ/7jZlhIStX9QrpH1B2UlEtothkOUImEqsSj1ZIxWJkknn6FfLjCslhhUipQiQXIBn7yeNmtkFT8Ruw01l5WLID5HgHSLRRkRUZpl4Wi16bc7EsDrCeL0PAHgzobp6+/RfycgwiVspnWYdlQmaptxuyVXQ2jycb8i5rDNJsMuqkdeCdDNF2inMxSDQVqpFONqlVG1RK+Yo1/KM21UyXi9DEolOtnsu+8NUYvFaSSSpNxu+Tm9QlEWi0elu8+gqTHSBvS7I1xuBatLweGPYfZGubWx65fOTzT109Nu5+GHBdhrt58AJJwuMi4f7USGRjROwafQSae5125yoqnStEyKYTFP0uGQr7UTKeqRGHlvgEowTCuRkACFQJBBqcxeU5X59gSgM5IATpdfAtj8Ucy+sAB4aFSin5ybdNSvPHb+gwCm7bYEEM6LjlEAiMoRtdkp+IKo8QyVQIiU3UktFGaYzzEuFpiU82jpOP1cipTdRjueQE2kqIUiFL3BJwBZj4tyMMiwLABaTwCGDY2JOmLQGeJy+rE6/Nh9jwBuruswesPPCoA3PgyAcH7abEoT5U4AhMwWyoEI7XiSok8hbrFS8HpoxkLUIwFqYQU1GaWTipG0WakGA6iJJCV/QAKUlSCtWFwCVEIBxuUy+40G+622hBg2VMZqn746wOnwYrF7sHlDmD0hbq3tYPSFTwsJGZ4GIJqu6bsrP67XZaWIOhxSQkGTmbTDRcUfJOf0kLLaqQUDdFNx1HiEdixII+ynHvIRMxnIOOw0QhGSFhsZu4uM00U7LuTkpBryMxLthiif9QZ7rQ7jptg7NAZqD6fdg9Xmxu5RMLsUbq1tYfQGdgRA6WkAQv/jZlM6PqhUJETc5SLj9xMwmkhY7eRdHtJmG0mrhWZQQUtGUCMBmhFFzrWgl5TZSNJqoh0OE901kbO5JPBjgErQxyCflvkyfldKYg8aNTuyEjlsTqw2F3aXH5PLy62VTYwepSAABk8DGDUa0oTj4tAhZlF9ROkTAAW3l4rHT0YAmEw0/L5Hzge8NENeevGQnHM2k4TQIlGiej0FEQGrlU4iSs5jo6R4ZL70MmkGhQKzRvNJFAZNFZfVidXifAJw8+4GJrfSEwBHTwMY1GqyLo9qNVmnBYDQv9h8Qrsm6v4gDb9CzmojazGjhhVG6RjDVJRJNoEWDVD3u8hYdonpt2gHAwQ3NkmbrMR3d58AFP3uR/mSTNDL5Z4AjBqqBHBaHE8AjE6PBDC6/Pfmhu3m0Z7o04d9ufNJ3WuPQEatppRPM5uVhw4hIZHEon8RW3/C5sC9vEraYCRrNJPU6yg7rHSCPvrRIIfFFONUmKx5h5rbzua5s5ivXeXif/yIyz/+CTdfepmi10XO4yDvccskHxaLMg/q8YTczN4rIYvVic39CODG8joGl+/e3KynDUTX916AxxEYNOoyB0TPL05OYvVFsyW2fZkHbjff/Zu/5fSp7/DdZ5/l1LN/xbWfvkDRvks/4qfutVGy7cq57Xdz5vun+NHf/x3f+dJfM//ii5iu36AZCVNUfNTDIWqRCJrYkfMFavEU03b3XYAuDpsbi9WF1eXD4PBy/e46OrevJwCKIgKycVJbctWF82Lu1aqyCgkZPd4DOvm8bHlFG1zw+1k/d57w2hq/PPUvvPrtb7Bz7izDWIBDIZ+gi0kiwFExyb1cEuM7F1l65UXmX/w5FauNst1JMxqRG5nYDwqBAGmPl2IoKgE6pRrDVpduq4fN6sZoccsKZHD4ubK8wbbLX5ibdTXDrKfx2A76PWmPJSQAhIxEDgiAejJJv1yWAKVAgMjGFpN4lN1L5/HM3ySj30QLOBnF/BwVElDLsZcOM02EUX1OVJ+b5PYGg3CQnNlEJRAk5nSg5fIyqrLTtbtpZot0Ky16zR5qUwB4MZg9mJwBdHaFd+5usekK7Mz1m7U3+s26PP2MO225+sNmg261QqdcknuAqEJC/wKiEovJa5HIAkBZucsoFCSn26bjcTGOKMziAY6yMVDLHKZDTGM+eU/12CmbdlHu3Cav15E1GeVnxD0eRtUGfrMV8/o2HqMdtVinX++iNXu0WwMsFh86i49dZ5Atu8Kl5S3WXYHTc3v97pfFyu8PejIP9rqaXHkBIWAEgJCQcF4cIR9HQJTRkl/Bv7REdmeLktFAenuNptPEOOJhGHLR8Vrk9VE2wsNSmprNQNW6S91mkQAtv4+cx0fKH6BfrWNa38ayacBjclHPVqkXGrQbfZrNIUazn22zD70jyKY9yIWlbdbswS/NdarlT7bLxYdqpYSwZj5HPZuREZBSUlV6lYrshUTLKyDEfiDa4KLPT85owPb2JTpuJ6XdHQ4SISinoJTkMBVgGvUwibh5UIjTtBs5SEQ4Ssfx3bpBy+sl6XKTUsK0CxW2F9eIugNkQikaxSb5ZJlWY0itMcJg9rFp9rLjCLNmC3F+cefhiiP0SdmRzl8+ryxevsTS5Qssnj/P8sWLGJeWUKxmpl2Vdq3MbNijmEnSqzfoFMvUE1nZz6hKkNv/9XM0xSclRDHNNORmHHBwPxuEeoa9iEdCjcNuTvIpWh4n1/7zx3TCIfmwLBNL0Sw12V7T0aiq9LUp/d6MQqFFozGg1hygs3jYMnvYdgRYswc4t7TjfXIeuHX2lW8uvP4KK2+8yurLL7P22qu4l+9Qjij0OjWqaoVqr0GinEXtdAm6gxy2JlR9KTI2H47lVcw3bhPf2mIUVLifCkMyBGmF47ATmlmOk34mEQ91p4Xty+cwXLtCXpwpwlE6ap9dswu7O0yhNiCWa1LpTCg1+3QGM7KlGia7my2TlV13gNs6KxeW9f/8BGD5/OlndOfP7FkvvIX57C8xnjmD7cYVfIYNUukwnnSA0lTDm09TaKnEI3naKZW8M0UzWsC5tsPymXNsvHkOZf4WZd0GY5eRB2EXD6NOyAYY+0wcxHzQKnGvkmdSzMgTWSGTJVessaazsmpwEsi1sYQLlPuHFLUJ7dEemUodk93Fxq6ZXbefBb1179Lq7q9+p2C4/NZpy6Vz2M6fx3rhPPorl1i7dYXr81e5Y1inejjBkU0TLtSIJaoUo006mS4FJYmiM2K/s4xv6S7x1bsEb72D/c1XMLz0AsWVa8y8uzxIeKGSgHoO+g04GDKtFqkXi4TCcRbW9CxuWbBGiuiVLKXRA/LdQ1rTEzL1jty8VvVm9E4/CzrbK//rqcSZ7337M2dPPbd34dR3uPT8Dzj7w3/jZz/8Pj/5xU+Y392ienyIu1LFlshjcieJh0WfdEg2kMKnM2O6vYDt9jzK0h2iS7eI3Hyb0LW3yN29yr7fBFoJ9jUelOKcVJJwNOJYrcrCoShB5sXGZPWj82WxJltk+g/I9U+oTSDdHKF3h1gxWNmy+6d3dqzv//XUyumXvr/x+mtsvXWWpXNvcfncWc4LKRXzZGZ7eBoapmSVm5sezM4SAW+VZk4l7lSwLK2iv34T5/xtwqvL5LdXqerXaJk3KW0v0HHoeJAL0QvYGMQ8MGqy38jJR5LxaIzrt5bRO8IsGkMo1X2iGuSmUBhDqnOAMZhmxeRmw+Y/NfdBw3LtwsfMVy6HhXxWr77NnZs3cImnDtMZrloLa0nFVuhzQxdhUZ9i/q6XTKJOwh8nYPGiGKyEDEZCm1t4F+ZxXrtCYm0R3ZuvsPHGL/AtXsV+6yLB9Tsc1TLc1+o8GPWp5HLcnl9mft3M1Q0PSv2YkAbFe5AaQmb4EHemxZY7EtpyBD740aIYxiuXPrt56dxk6/YtDPod8u02hfEMa7HJTrqBrThhwVnkrQU/V+4q2F0ZrGYFw44d05YVt8FJzOYjbRcnNAfe1VVM16+hv3oZ1/Idtt++wO6tq4xLGTiewWwod/yd7V3OXp5n2RLHUz0i1IP0AcSHUNiDaGM6s0aKn5v7MGPt7XNfsG5t3E8mYjQGQ7K9EWFtiiHdRJ/UuOMo8cI5HTe3E+zYU+itEfSWMGZrGI8rTsibIuyKoFh8+E1u/LtWnFsG+UBMt7CAbuEOtUScfbUJ04F8fur3Krxy5m0ciRae8gHRIdJiA6gecT/XP/nLud9kKFbzPx5MJ1RbHfpH4Mo2WPdl8VYPWHQU+dlFA9e3E2x5ysSq+2y7cuhcGZS4itWVxauUiMWbGHa8rCzqMercbCzvsDy/gn7TIE9Y/Yb4ykrjZNAln0zz0mvniJaG2JJ9UiMoHkDpgIe5If8w99uMVqXy1X5/eKKND/AmS7x8aZEVW5Jr2yHemnfywtlVLPEexSl4CzMcyT5KfoZJaWINNPDEVNyhOgtrTrYMQSz2OPpdPytrJrb1djrtnswBJn3UcoUbN5YIpVvYow1S6gm5IfejtdnX5n6XoVYbn+93R9NYssSrZ67wizeuc2PFxsJ2gH9/+TqWZI/a8SOdhtsPCdUfYI4PMIQ6mEIavuyURX2cZX1Uym3TGObOqp2VHSelUotZq8nDfkc2jh6Xn3i6RqLQoTl+OOns8ZvJ5oNGM1f6s0woFTbr7Dz3jee5en2du5tO3lkwsuHKkh5B8wHkJhDtgCN/gD4yZCvQxRgdsGTNc3M7wpVVD9fuOrm15mDDGMQfTNEvl7inVuXXULVCiXSqQK2mhfqje5+d+yhHwub6o6w38q3nn/ve9NWfvc7SnU2c7jgLOhdKqU/rGGoHkOqBr3qMPtpnU9EkxJKtxI2tKPO6KIs7QQmwovNhtHgZ12sctascdFriCLufCcdeKGVzH5/7fY35X5779E9PPf/a3avzewFfhKUtM7uBFKXBfcojiLaO8RT32PQ1WPHU0QU15k05GQFnoosr2ub6XSs3lo3s7NgYViscNsp7h53Gq5NG9Q/3DyDzb775jE2n/8bS6obv9rruoTteQMm2sEQqGAIVbupj3DamWbYVuL4T49q6gjup4Ym1uLqwy/VF3cO1Nb23Go99fVRM/8kfzPH3G69fvPyJFZ3l2U2b//SSUdHdMQaz5xcdg3c2Akfnl71H1zaCg4uLjuyaKa5bM4ZOvzO/8+zCqvkTH8Uf/2+mz26E3z2iYAAAAABJRU5ErkJggg=="/></a> +<a xlink:href="https://github.com/NingmengLemon" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="NingmengLemon"><image x="678" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/HiGraygoo" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="HiGraygoo"><image x="704" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/TyraelDLee" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="TyraelDLee"><image x="730" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/TZFC" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="TZFC"><image x="756" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/hexadecimal233" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="hexadecimal233"><image x="782" y="28" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAIEUlEQVRogcWabWwcxRnH70N9KB8LFdQCoRalTa02KkKq8gGJUoNUoaZ1KGmiWFUKFEEgL0SkKVaSS9FFqpSmiR2ntLAlBAdfMHJiGxJ85MUXYuOXs+98yZnYvj2/BG9vbZMLJWd7L5QoT/Uf36zn9nb31uZIRvpLs7uPn/n/ZmZn5u7schWgSDH1u5KslktyYr8UU09KshqXZPVzSVb/lxHq8dlnLGYN/sZ1K4skq3dIsrpJktUeSVYJOq4kKZRM5Qj3eYxB3ZKsbkSum2c8pt4jyWqVJKszRkMwa1Zw3wKAMpqWZLVSkhN3f2PGiaiIiF4koikzQ2Jxe3y6xGIHEZqFnyGiV4jotoKa9wYuLPEGoue9gSgzkpi5ljNNUD4amSDELK1t0YVr3OcjYaXEzDUWg3hvIBrxBqI/LIh5t8f3hNvjmzLrUWNB44hZGbqoC9cc3Elxz41eyr3D9/jXMr+8sePJamXyq2plkrjE6WE1VXBdcqiTft36GYPASJjFuE0ktlWtTF5f3tS5bqE9/9zypk6W6GBigt4av0y1k/+ltc1h+t3xbsIzGCuuek/vZS6Yf7BpMAdAnE64Lq56jz1DLuREbrSBttAm2sYzt8e3cV7miQjTBvQsybsT49SY/Jyav5hhQiO4L5oTBeNcxhg+nVBfWtvCniMXcvL8aAttCgDXiWiFI/OhZGoxEV1FA04A5isOI96rzg9AmdXvR7bmpZjqDl1Onec9ZAaAhvZcGqctA6MLAnj4w6De8yszQi7k5BAWABRKXu2VZLXIGkBWK/iSaAWA64Wat9OWgVGW2x6A7T9/sjCfuBs7orib8mVRXBnsTKyNDNO6vgQT6sbnu//zBW0aHLPNUW1Y8cQlOAMwJclqsVnvV4nnGREAvcOFRtaEY8ygUX+88KkOgDq//2zfKDMOgO0jk6xu9vdrI8OsjYqYQp74eBaA4Uy11+xglnW2sdqYjD3tRBXxz5h5UVaxK4X8IoDJ2WnuAJg5VZITALExGFnfdyVr2bSTMb68e9wW3AYAWi8C5ByJRQBxiJ/Zf4g2NX/MenWrVEubm7scQyDu992X9esnOiYYhCgYL2u5SMvq2rM2vhyAmBrk5oslWb1hdiTmAGKvPLViDTOO3hTrTkchn9b1JZh5BydZeL4LAOVmZ3okuFdqo2X+MZZ49e4aZthKiOP6uhDlmZHIM4Wg1Vg+9zsB+K2vXYdY9fx2Wr7rYFb9/veHdT3o/5QePZPQDf3y7ASVnlEtJXX26BKnlgOASlfmM2xeAC6YhmHcF+slx2JZAgT/G5gUR8io8dAxXWJb+QESzZhCw04ArEygx2F40b/DVFzbpwPgvhkYF579pf4Udb5VTWpX/ZzaG+n1tpBDADUOgCtmAPjDFUe7GYQIIE4V6CeNcR3g24fO6xC4z+HMhGfb65qp480qih57lWT/mzR27ghdOlVD/wy0OwW4DIAvrT6Y81VIBLAyBAAuqxijXvYdp/aD++hs9SsUObKfRk8dJrnpAB04GXAKcC0HwGwjszOBHhfNzwegJCP/zufp3J4NFHptc9b0tDgL5QBkTSGzjQwv5APCdPh+XT8zDi17J0Sr6tuZfvp2UH8XEMMB82nzqzW09Y3DtO1wbdb0xPTFNBbPQ2ZTaMjJFAKEWa/DeO3pABPq/D5/F4yjY6YSmxcdEIbjtOEltllGuYyrDVcqldIlbmp2Zj0do3r8z7YesIXJD8CWUeuN7PY9J1gCvMBLm4b0nn+kPkw7z/RaAuAZYrgpHg/z/qEJPf5XT/+ZQYjx8xwBtpGtcbIP/LghrhtCg9MjEUsAPEPMQuJL5jcCq/AO3GV2mLPaiUVDYlEbR3ThmZmcxC8S3p88q9DsYS5zIu3ON4VwnrmVAKGcb7kTneLngY35XmJA3EoAKXevesH4kXLaahkFwPfeHWDJrcwVSouEFcnxR8oMRKXVRgbz3zkc1Xv/ZHh2BJjivTQdC9PUJz00NRBidVuTFvEnw71ZL34egL9bfq1idpQwrtV8CjHBwMUemurppKnzQVa3BbCI32kwbwOQsvx5SpLVl+cNUCDtdA6wxdR8BqBIktVeI8Bt1a1Z+sXbbbTjRFvBzO840cZyGtvJWYXGkmHbrxYzEIslWb0qAhT97UNTFQqgyCK/YR/Al7tLXE4KET1ORNfzARj10JGPqKI1SO/II1mSPonR3shF9gwxTvMVQbsa+Nfrv3HNp3gD0WcfPXg6F2BXQ5aWvHaKHjvaQS+dPkrbzrWQtytCbcpZaoiHmHHU6wa7GUD9wAe0L9jEYgFy3z/8c7n+etwK4Ibb43vGtZDi9viedHt8XxmHVdRjR1qYudFkDTUPn85b58Jo/PyQX8/DIHIBrhftanhuQeYFiBXsBzfB9P1/2EblpWXMRGVvH5smMIgeN04f8T7izVReWsZyGjoHP7LMb9pYFW8g+gNvS7QX7wQa2uDZTXVvvE7+oX5qHYtT78QlOqcMUVdihNVF4f6xuMwgMIW4YPxfkQjLgVzIidyzv7NdCHsD0cWuQhYi+hZ+6C4vLUuhQS2tOBYgzKaQf6hfj0HO8tIy/kO32/VNFS2tFGtpZZ+WVqadAsAoDO8zTCf/HABy7dXSys37BxAtrdyhpZUNWlrp0tLKDScAeJnPXGphK1NFa/CGf6i/U0uPrdc05fabZtyszGjKnVpaWa2llUotrfi1tDKopZUrWlr5EvIP9V+paA0OjiZr/KPJmsqRZM3qitbgnYVo/P9jxYMCABi+zwAAAABJRU5ErkJggg=="/></a> +<a xlink:href="https://github.com/fred913" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="fred913"><image x="808" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/icyux" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="icyux"><image x="834" y="28" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/michael-eddy" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="michael-eddy"><image x="2" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/HIM049" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="HIM049"><image x="28" y="54" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAATqElEQVRogcWaV3Cc13XH+RA779GMyziPTpzM5D2ZzGTy4nHGTsaWLVmK3CRLsiRTLKIoFpESCUoiJVIkwQICIAgSHbsoi7IAtvdeUFnAAoIEQbCh99392i9z7y4oypJFF9k5M2ewZb69//85555z7rlYt+5LEDT1G+j8TNc5rqo4sxojis6sCkpBZ7M6I1kdZ07nuGLoz2mG9o11/5+ikntCR9lk6Lk0qgKaDgZSxB+toEurKlntk/e6AYqmYhjinZLSUTZqKE/81YDrKH+vohzTUVYMFNAVUHP5v8YnJISomkFOMSRo8XH+Kx35HKpU8dowtGVd14p1XfvWXwy4gfIVA2WzgbIkFxUgjAIBqSpoOdDUTzzxCHBVVVGUbP4ZCV5BUzNgaNIbBV0xDK3IMLS//XLBG+p3MLRBsdinVAAXoNcIqFlkOKE/DKX5xQUyuSyqrqGqOQw995CArmULv2P8rg4YhvGPXwp4DO0pDG3pE9BrKhYSwZ0DQ1hdxxAkCsCXszkmJidJDQ5yd3paQpZRr+XIqVkM+YmOIdwkf6uwQQpqGMaiYRg//nPBv4BuqJ+yjramnyyoGTqKqheiGjLA0LWbNPc46btynXuLy/KzLLCCwSoGwg8Khf1hFLaP8RnVdIPX/lTwr36ue9fSiSSQB7wCLCj5v0IfZKHVG2XLBx8zqcOC+B6YESElvFPQqdWs3M6fjaDfUZ2NfxR4w9CeMgxDE+5VsirZVREmMDs9Ry4jQgkyiyIMYEGDxUcAXptX8Q2PUdLu4o3DZYRuPKA5NsSpTg+lnS7MwQSeS9cYfDDL7VVNeiVXsEtOA/URGykG5HSDxdWMltPVJ/8g8Lqufdsw1AUBXsZnQWZm5vL7U+TxnCHD/87kvAQ+ugKt8UEO1FrYWVrDrgoT75xrZmelmc0na1h/tELqmyXn2FFew7bSs1LfKa/Ekx6U3pNEgKbObg6XlDEvDFfwcEbVyGrqkgr/9MWWR/mqYWiDIqWJbC10NZMjmxP5GlYzmixMwjqTM4ss6hAaGac6mKKoppk3TlSy4VglG05UsaGkmvUl1Wwqb2TLGRPbq1vZXWdhR5WJt87Usq2yjj1V9RSdqqC6vRtf33kaumy8sGkLL216g+YeO0Mj1yUpQSKna2R1rV81lK98EYGdazlZgBewBdip+aWHG1RYanIhw0fFp3j/RBknO2zsrTWztbya7ZUN7K5pZXtNM9uqWthR18abNS15PWdi85l6NpZXsbmimrdrzbzf1MqeirPsLTvNlgMH+cXmrbxTfJKTDSYOVVTQ5Qswubwi11wjoRnqW58LHl35Foay/GkChQeB8elZ+UMD126w+6OjPPPSb3lx29scbrKwr97Mu7Vmikyt7G20sK26kW3VJnab29jd3ME7LZ3saemQureljb0trew1N/NuQwPv1TdwrK2DJzdsZsNHB6lxuilpaqbW1sNZi4X+a9eYV3L5ymHogsCSouW++XkEjokqmQevFUoNPFhYksBFGnQne9n63of8eusO9h4/hbN/iBMdVo739FDqdHPK7eGozcH7rW3sabZQZBGg23i32cLupibebTLzQUc7h23dHOq2st/Syj6ziV/u28fT23fwQV0DR1paOGpuwuz1carJTHcoxIOVJWnEHLrEpii5I58Gb+SewFBWPo9AppAaRdo7VHmOLR98xLnOHkpbOrBE4zQnYjQmw1SFfJQ4uim2dVHicXMmGuFcKslxr4dit4tDdgG6g+NuO1WJEPV9cWrTUY47Hfz7iy/yk7d3UlRfz7GOdkzhCI0+Hw1uJ01OBxNL89KIq5qsHCLxLucyS580gBjKpjXwj4aPICAevLe0hKe3lw9Pn+GD8tPsKj5GtcNFd/8A9UE/TYkw5niI2oCPmqCPxliYmnCIcpeTElsPZU4HpS4bJ2xWSfK0z06518ZxRxfFdjs/f38///L002w9c4bGVIoyuw1zNEyDz02j0y4JCA8sZVbXCJDLZV7/ZPMaWjoPPp86ZQYy8vG/oOQkCVskwo+ef54nX36JY431NIdCmIIBWqIxegYGaQmE6YjGqOrqpjUQpMXrxxqJUd3dQ3Fdff47u50at4uO/n6OtbVx1h+k1BFkS2kV//zks2w4VUZtb5r6dILaqB9TxI81GiRxcTC/H0XPVRADkgXwxjeNvDwkIEkUCKxq+WJTY7Hw89fX86OXfk2t206j30NnMklbOEaDw0N7MEqFuQWTtZtgug+7P0iP1099axvltXWE+wepam/Hnu6lweuloruHkx3dnPMlZc3411/9hl8eOCQJVEQC1CdDNCcCkkD8wgAi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"/></a> +<a xlink:href="https://github.com/Nek0Neko" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Nek0Neko"><image x="54" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/mnixry" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="mnixry"><image x="80" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Mz1z" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Mz1z"><image x="106" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Roberta001" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Roberta001"><image x="132" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/diylxy" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="diylxy"><image x="158" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/TES286" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="TES286"><image x="184" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Pcrab" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Pcrab"><image x="210" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/YuHuanTin" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="YuHuanTin"><image x="236" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/ag2s20150909" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="ag2s20150909"><image x="262" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/caojen" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="caojen"><image x="288" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/nailvcoronation" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="nailvcoronation"><image x="314" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/cctyl" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="cctyl"><image x="340" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/hd80606b" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="hd80606b"><image x="366" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/fwqaaq" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="fwqaaq"><image x="392" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/cqrect" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="cqrect"><image x="418" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/114514ns" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="114514ns"><image x="444" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/imba97" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="imba97"><image x="470" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/lanyeeee" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="lanyeeee"><image x="496" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/leejoker" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="leejoker"><image x="522" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/linyuansup" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="linyuansup"><image x="548" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/littlefish12345" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="littlefish12345"><image x="574" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/loph3xertoi" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="loph3xertoi"><image x="600" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/lxb007981" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="lxb007981"><image x="626" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/lytDARK" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="lytDARK"><image x="652" y="54" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAADlklEQVRogc2aW0hUURiF10PW40BhJQa+2OWtxxDMeQ5MtLCLFQaVdjOhez6kEERgpkJgI9FFuprgQ6UIhfUQZaZFGDSYjPjkXUqFLuKKf9pDg52Z5ux9ZuYsWODMnDN86/i7z//vI+CASK4kWUSynmQHyX6SkyR/Kk+q9zrUMTvlHCRTJJeRPEaym/p6S7JMviuR4KtI1pGcpXOaIVlLMj2e4Ckky0lOM36aJVlFconT8GtJfmDi9J7kGqfgt8b5qkfSN5IFpvB7Sf5i8jRH8qAufCldoOLiYgIo0ymbOZfAE8AcgPxY4TNJfk0m+NTUFL1ebwg+5GkA6/4HvzjBq42lLOBD7gWQEi3AWbqnbBjBJyPBp6s7opvhqUopzSqAtAduqnlGcY1VY+ZYb9PX18fm5mYWVjcFXdl4L/g6krz24MUzAP42gKqrNFZnVw+9dY+Jmm6iafgfeypbWXm/I3jFbZYNLXwkPIBJSxwEKrz2lGjwW4IvdEZtJzvffTSBF3eF4NNIzpvAr7/6IibwcOe2fmLujl0mAeYBrICapLR16Fa7ffjnw/T5R/kwMMHU1FSTENuhRjwtBQKBiPUeyVltf+BDPlffYBKgFmpO1VLx9TYjeJ9/lHcHxpmRkaEboE0CDOgG8JxvtV02Vt5StFs3QL8EmNCBHxoaIi6+NIb3+Ud5/FKNboAxCfBDJ4DcmHTLZqEvtzzRDfA9rgFigfc5EECrhEZGRogLz7TLJtwlpyuMSugLNZVa1WoM7/OPcue+EqM/YkeX0VjLxslltN6pG5ldeJ9DNzLZaNVW+e12rbIRN30M0OPxmATYJgFWmDRzoj01N2zD3xkY54bsjebNnOpIZZdYS9ISy1WsbLzNm/1jsQV49YEbsnNM4MWvw+eBMl348C/N2pjD6kdP2DI4YQn+oG+QB05VmJYNlQ8vHClnnJphBVA+l/VdvGlzns7YyJhHShVC9udjksMw1PBl7W0VwzHQCX8DYP14iuQZl8MTwAlL+LCnML12az6B7om6tRhpc9cl8NMA1kaFDwtRENped0nZzAHIiwk+LESJS+DnAeyHpvYC+JXkK18KQ+WrpSvR8F9tl00UrVYPFxK52mTCYS0CUB7n38YsgCoAixFHycOFK6ofcQp8Ru35J/QfQKSZOgrgjVop7ELLOdISyzb50kSCW2l5cKNVRjygHcBnABMAfijLz/KefCbHyLFyjrF+A2gHgV5LC3MQAAAAAElFTkSuQmCC"/></a> +<a xlink:href="https://github.com/M1saka10010" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="M1saka10010"><image x="678" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/maimierjiafude" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="maimierjiafude"><image x="704" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/mizuhokaga" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="mizuhokaga"><image x="730" y="54" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAWG0lEQVRogcWaV5Bc93Xm8WDZ78sqyyrto3a97/u2teuy9WB5q2zTNFSUKFEUFZhEAQQzBJAASREkMggiEAARiDgJgzCDyamnu6enc845Tud8O9y+3f3bundUVLksuVZeWnurbvVDz3Sf73/O+b7vnNs7dnwFF/HiX4ihzA/q3thpEuUF0RIOYYpV3OfGe6LK1Ys9UFUM92ZD1qX1Be30wmnN2NRTkRn1X+z4/3mJ8cpjbLV2k6iaiBeREgXlJlYgu2Kiu+4mPbZCelIF/iy0gUaXXrEG5RbESoiGgFFUuXZhiDz2RwtcqLb+cyvf/KQbr7VIC5BtQ6kDNRHKbcjU2FLbqSxZSYyvIelDEMxDoYmQrdCvtqHZh1wb7HE6KhdofULhgfpUdWbzm/9hgXfzta81io1XWrVOs10Q6MvBF3tQEqE1hFafYb2rgKi7YsSmtZgv3kXQBxCccYbyqbcl6APVjpKBtjGEqHHBppfuio3i1HqrvWJ9b6D3/9lXGjxbjb+k0bf3mj06DZFWvkk/04IqUB/Qr4u0Ki36rT5URXLWEOabM9huzJJaNNORS0gEsSFCFzrZOsQq1De8SBseMAYYaJyk7y5Qm9PR07lsbbXtv34lwdf1/p2kak1aMBT6dOsiQq6BmJQzICkBtYpNKqU6DGDYlAiqbaguTlDV+pCcaaJrVvx6J/p1PelgEt+mg4o1ogBA5wFrEGFeS/CLu1Rm1xE3HAgqc4PA1hP/T8F7JpafrWo9ErEy1CUGTQlJ6NMptmjH6nTjNWgOkeQMNLvbAOo9tqwhVj8bI7dkQzCE2RyZRT+3jmndQCVVxLKgJbFsobJqhU0PmLxErk9gPH2J2vw6fYMTUWcDR6jf2nS8+O8KXvJlXvCMzdPQ+SBaUmp70OhBBwa1Hu1ohaY/TzNRVrIgCRJCWaCXb0KqjurcKGsnb2K6/AD/Qw2NcA7LyiaOdROrd6YpaTz0NwOw6QC9HdPJc6x9dJzG0jqY3QyMDkSjk5bOCp7Yrj8oeIrCzqbR3w9NLCinJJgCSuD9sgBCn0G5CxmBkj1GO1qEWg+p0oEekGtRMgYpLzswnZ2guuSga4lDdQC1PllHhPSGm64hgqhykLw9SfXhLJtHT2E7ewFJrQerE2zy39gQjXZwBft44//0fxd8U/oWuXpd0HuITcxTnNXRNvoYJIv0i03oDKEiA2jS8qSpe1JI6Qr9XHObHks9eo4E9UUH8dtLYExCsAQliWG6SlrvJbJkoDRvpTmrp7+yAap13Oc/w3f5KoMNHVhsYHUgmqz0zDZwB8AXa0oW33/7t4Ovd/6UettOuoCgtRMfnSE+MsvAEiBvtNPPlqAz2Ob7dA3Rl6Fhj9IJbIMgK4uUpAhXZdqAOG8FQxxCJeQ+qrojZA0etlQWGkt2ULvA6QeDgej1L4jdvMlgQwsWM1isDGwOJIsdPEHwR+mZXNbqiv5rvx9AVdhLVa7hvMIEubvzWE9/Ac4oKZWOXiIDtRaUGpCqIHoSdN1x2p4oUjxPJ5yCnADeFLnxNdAGQOUBd5qOK0bO4qbhjtJxhMEchcAWODywvkbq5nVSI3fob6jBatoG4XLRtzvA41cAiHoruZnVN35n8J1o8pv9rZxAtgihOOK6meLdORZ+9TEYPWRVG7T8YaRMFopVyNWRPHEGviQdbwQxlKIupzqaY2gPkZtYAVMYadWuHIDgClNweOhG0gwjaXAnIZSBTT2d2Sny47fJTY7R06yC3Qw2E3ic4HKD2weeEC2tkcTd2WZtXvONfwWgG4p90o3GEEMRWiYb5YdLJK6MMvPqARqzKgoqLSWrnVYoDNkCFBoQTNHzROj5IrT8EWouHz1flK7RTW12Awx+mgt6RKObhitAJRiim8xAKgvBNHhjDFdXEaYnac9NUX10j/baIrgt2yCcNvB6wOUBu5v66gaR2w/orBhO/MvSiaQfk8KJlhSNI4XCdE1WGjMrFG7dw/jhKaLXxyisqNjSbdLw+OiGIpAsQCSD6AjQD8doBsIKuI47SG3DjKSx01s1Ul/QUdWalPfb6STNVIpBJgPRLbB5aM8+oj09AeplmrMPqS08Ao8VnFaGDiv4fAztTvomG6UFFYHrdxlq7UJ/zfpbAzjwRHZ3AiGGiRRksxBPgMMHm1biV0dxnrtCcXGV3JoGweGhLtOcPw7hNG2XD1KZ34CSa91HVW0Ag5vS1CqS3oFgstFPJqCcpxWP0IuGIBBCVG9Su/eA1v2HoNNTn5khPz0NHrlv3AydDggEwGqjpzNSmlnCd20U9G7ENcvLvwXgDZm6wTByCbUiIeo+L223Bzw+QqP3FXUcbFiRdHa6Bgd9R5CBO4zg8FF1uunFYwpo0emhvWmhb7Aj6azUVrQMHV5IJOjHQpCMQiLM0ONQmrQ2NUfpxkOEsRVQOUmPLzC0hhGtfmqbNkjnwOGmv6Gn+mgW52efk5x4CN4IHYPLoARf11i+MXCHh8QzdCJRKgEvtZAfIRhA9HkpralpyQy0qqO7pgeLByIpCEYpmswUHXZqPhdtp5uO0UJf/mKzEwxOOloDfaebYSiA4LLSD3gg7AeHhdbSIo5PLrD25nGuf/9Njv39C+z/22cZP3CO1c/G8U4u0TK6lM8qPnhEZmScjY+Pkrs/Q2/TKgMYNg2ur++IP1z9gWgJQjyHGIxR9fmULEixMD2fh8LyMtKmATaNNJdWqS6tIFrMDP0eOn4X7YAHweOkbbUxkEXH6ga7F6wesMgU6INgkLbdQsdmoW3QUV1eInF7hKnX3+H1//4PfPi/X+Lj777OgSd289GP93HyxYNMH73MyqnLeK+O4L34BeWJ+5iOnEBcUtHXGMEZoqt3fW9H4q7qdEPtBE+CQTCusFAvGmGg1KmXyINJhiY9RELgcdAzbNAx6+h5LIh+G8SCSH73b+jOsy1McuCyBTDbGcpC5PMjueReMLA1O0v63j1SdyaY2/8xi4eu8/krn3Ly+SMsnJ9Dd1PDF+9c4NKewxz67guc++FLaN4/RmNyivjnX8C6Hkwu8MTpaiyndpRmzAvFWSN1jax4MYhtQSSqpJ1wkLZBy8C8iaTX0lAtUFqZo6RdpmJWU7NuIHntDNzy/3rA5wW7S2lISaNTMtfUaOiYjErW5NfS4hLCior2goqlQ2d47q9+xN6nPuCZb/+Cp/7Xc+x7+gNWLq4QuGfmxqsfc+bJF5l/431cx8+Suz4CKr1i9jB56KnNszsklTdSfLhJ9pEG0eRVuB1/GLyyCw0rVDawGMBqVMRF0G+QWV0gtjxPSrVMzaBFspnB597mbIfcoBYwmxhYTPStVrpmEy2zkYHDiWS0KAzXXtFy7ZWDnNj9CR/88hLv/+ICl967z3vPnuLVv3+b0X1XkXRJvBcmMRw6y/ye/WSu3gKdBQyyDbeCyR3agcZfrj7Skb23RmVRR19uHLkMvAGQRSscxTs6zrVX3+DXT/6QfY8/yeFnX2T29EWyagMFtYqWWcfQZWHokOXfBkEPBN0M3FaIBuh7XYguOwOPh7ZZ5ng/+flVDv1gF5+8dYVjb49z5p0H3D+j4/rBKc68dJHzz58kMW4EY4Ly+BLGI6eJXrkJVjsYzMohSHpLcQdql9hZNJK/v8LWvQXqyzqwecEXAW+YqkrP2P5D7P7247z810/w7s4X+OiZt7j46jEeHLlMZllFVa+hYdigql+nYzdAzAcxL4LLSD/kVpq9Ize9x82WWkvT7CCzrOboc29z6o0rnHx7gpOvj3LlnYfc/XCBpROrXHruFJqjE6BPKDNz7dEy3qvXwW6jpzdAOEZqdqG7A51TRGOjs7RB4vZ9PJdvU5xeBosPrAG0529y9Eev8vEP30B1bprDz3zIC//zBT743iFu7L1MQW2CSJDCpgbiAZo+M1nzOinTGjm7li2rlpRRQzPooR30UbTaaXqDhJbVfLb3KJcO3OHknhucfOkax39+kbG991k9usTDfTeY+tVFeho/yEOS00Ns6r5Sjl2bhaHPj+/+tAzAVsbgQL7LD+bxXbxFenSKzOQ82k+uML7/BFOHv8B0Q82e77zC3n88wMmffc7Z529x7qVLrJ0fhVAIElHaITdSJgjlBM2Um3rCiZgPU4u6EWJBqkEfBbcX8iU6ySy6e8s4ptx89tpVLu2+xq3XbnPhp2e58dJ5Rvec4/buYxAsgrztSKcpbKyBLIiREB2XB+/0XHFHe20j3N8wgdVLd0mt+J785BzBG5NcfXkfB//5eVJLXiYPj/PG4/s59vOL3N6/yIP3N5k8MMOtvacpbpqgVqMZ8kE9D/0anVocSUhDM4tUTkK9oFiJXi4H7Q5ioYxtScf0qQkO/+AgHz2xnxPfPcipf36HG88fZ+7AVSwX72+ffqUOlTwVux6ySYhGyGn1+KYXQzskvXWhvW4As0x/VioPF2jNqUmMPeLmq+8y9t6nDIINPt1zmuO/PMeVvXc5+/IIN16f4+6+GSbevYTu6hhkK1AsgNhEbGYR6kkY1pDqGWjk5Z0KiB0QBOiIVLfyWJa1THx0AcNnU6iO3OHe62cwn3qA9+I8hjPj29Ser0A6AdUcZadhO9NON+GHi2TmtLM7CGVOd3Wy8LjBEQSNic6imvCtScb3/5r0qoG0xs385WneemovF391gzMvX+PSrlGuv3KLsbc+49qeD2k5ItDuQ6dNV86CVANRHvgr0C5DswyVMtTqIEoMhA7VeIbNG+OIm/IMHKO7Jr+mGGh9RO/OI8lsWMwxTIWhmlEASH7Z3uiIjs4jrjpP7cCfeqq5Yae1bgFLAGxBpLVNAjdGmDtynJrZTsboQDOxwN0zo4wdHePzt69w881bXPj5p5z/0Xuc/8l+0otWKIv0S1XoCMjL0HohDt0adOpQr0C5BLUGtEVlSzeoVkmureAbH0HcMCjU2FrRU1nS0papMpOCfJxBNgj5MEWrjpbFSmxslvTNBVjxP7mjYQh8vaZ1DfNzGoRlAzjDYHGRe/gI18gdul43tAQCG5vkXGHun73NmVePcu6l4xx98h3GXv6EjaOjJGfMsNWCchPabeh3aJdSUMtDqwaNOtSaIHSgLtDMVRDSaSjESC/epaVdoW/QkX4wRX5hgZ7DBskQ3YSLXtZPI2glr1+nu2ki+sV9Wnc0QxZDX1ccac8aMcpKnJqY386CN4Kg3iC3vELdZoFMEsQuSzfucO39Y9x69xRX9nzMyGvH8V6do6+PUpT9VLULPYm+UKdbL8KwzVB+bf2mEUs1qLehItAqVBiUy5DyQ8gMsrfSacBkBbeXlkGP4DDRClnpb/kpOHXkjGr6VgfJW9PwyLr55TzQ1rl3dbUOth6sEhl5xEBW4+gWDb0ZyReAdAaENjW7h0fHzqA7f4PgrSkIyr4pRjfgpRHy0Ckk6XfLiFKNjlihI5fPUARJLhl5CdyFZpdho41UE+hXynTjXvo+K5LVhKQ1MFgzwroZ9A5lK9FwGBVaLrg3GSQDdJ0OmqpNandXf/ElgOa65TGMfgFLiNKshuS9RaoqIy2jPBFFt09OvpMZcgvrBEfusTU5S1Oe0GwGyh4DzYRHYZyBWKbTKSK0i3Q6VYRqCbFagUYDWu3tu96gWyjQTMfoxP30AnYkmzwwmWHdCjL7bLqUBZdsQxoeC+QjiGE3A5+bwOhdAb37Xz5TwOg/hTeNsGoieOshwZEHpKeWSM4s03d66cnrj1gCEllqK2pEtZ783CI1vY6m28YgHduu90YBsZJDqpWgJVNnd7snqvIhFKFSgKq8zctDNY2Y8NAN2xHd26ZP0ssTnRXMDnDIlRBACtghE4atON7xMcwXLh//V1uJgdH3zb7OLfTW7XRXzeTuLeK4eIvFQyeI3H1Ac0O/vWRKZenLdSqPjxt6BvIcICuxwhg5hvkt5aZSAqEJhRzI4pXPQSkPZXktE4eMn07cTi/lQow56QRstD1WOg47osNB3+li6HFBJADJGAR9iIZNpg++31g9dOx3P54SVba30fvAlQS1jfSdae699g6281cUipMHa2VGNZvpGo1K2vH6IRjZXgSk0ttLgXwBSmUoFCGzBXYrWzMPcd26imfsKnntFGScIKbpZzyIKQ/tuBMh6qAZcSqWpBeSrb0PIhEIhsEVQPPRCZYOfPT67wxeKSND8GsYg1Z0XlA5YMPJ3OvvsX7wiCJwso3taDbo6nVU1GuKx2+aLYovGYYj2wBKBahUtkHEE7iuf0Ho9k3Sk+MUZiaprD5AMC0g+dWQskDWj5QL0sn6aW55qWd8CGkfvUQQYvJnZsEWoHl/ldldByyPdh38/avF7V4IfktcMNQHs/IAH8J75CIzL+/FffIC6C3KpNXZ0NIy6KiZNqhaDQg+B1I8AFsxKOWgWoZ8HmJRHNeukpgYo7m8gKRbpWdeo+deh5geci7IRxkWEnRLUYRyhEYpjFCIImXjyjaDYJbU1Yeo3zjZVO069pf/ZvBfglh3PsG8sY/azXBylcWX9nLv2V2KV5JBdLQaZe1XNqlpBW1KCchqKWX8kI1AOQ3lnGK8ZJUtLc1tT3Q+O3iNdN1a2sENxJgVCikobNGrJGnX4jRrMdqVBINcavv0tV4uP/FKf2zn2/+44w+5OlPa51m2wqKV1Rf2Yd57GO/hc2D1gd7E0G5X2EHactHJOWgX3PTKQQblCMOSTL1JKKXJaVZomfX07RZlH9QPOpSZoR40M8zJYEvbvVLLMxRyiM2UkoGmvIoxuvn86beHp/7mxZ//QcF/mQld6FlW3JL/4Dnsbx9D/cr7tCYXwOZTFsDyQN9J2mhsmWmXXEjNMIhb0M1BKwe1HFI4QMNmoWYxKWsaeTIrO03UI26QVXpLztS21W4mfNQTbsUAJtUa3n386f6Rv3vxhX9X8F+CWPP+U+nTiYbt9eOs/OwdAkevwbodAhnI5BSVpBKkW/TTKgeVOaDXyDCs56CypXC+vGMaRGUeT0MihhgP0c8lIJ/ZFsh0HmQdaeYVa7F48ROO/Pgn9bM/3v2Hlc3vu1pXFv6LZfdxq+GXR9DuPoLv+E1yI0vb+/1oBPKJ7UGmXfmt+xQqDCp5BrksUiIOyST9SAhRpsZcGipZejLHKwCykIqSX5lCc+Ew8ft3LNHR0W/t+Covx2tn/8S2+/Qrc08fbEw9c5AHz/0a15kJ5eGF/FMDsg3IlOml8vSyRYbyM4RyVXGeFEqwlQF5wZuMQDENcoaKGYjH6W1q8V09h+fzE63u0th73YXxP93xH3WtPH3oG8s/PXzy5s63hCs73+Da9/eyduAqyQk9PUsaUvLPDoDaQHkIopTHVmFb4CpysxYgaKdvVoHPzNbDCcLXPxc6MyMnmL/zx/sByP3vf/DY2b95+Ze3H39Pf+0fDgyPfnsPb/yPn/Lm3z7P0Z8d4Oq7n3DnozPMfnqZ9IqK8toa+dkpuup5Ko9G8V87OUyOXdiM3/n85eb0yH/6owX+u67rf/fBn5//zoHvHfnOm6c+3rlv7vhPDvh//eze8ps7fyb+auczouXmSNl8+ZL/xq7n5jaOHDhVunfte+V7l//8q/jy/wMXuUVLv4MqEgAAAABJRU5ErkJggg=="/></a> +<a xlink:href="https://github.com/ours1505" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="ours1505"><image x="756" y="54" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAESElEQVRogdWaXW/bZBTHe8HGPZM2qnFZGJ8GbZoE2q64QAwB2y5Agks+AKMrHRQ1RbvgO4AqJrHGXTvapewKAUk6ttI0b06c2ImapOoPHcdundSO45cka6QjRcnj5/x/9uNzznPsqakYPsDrwHVgDlgG0kDFMIy2mHy3flu2xlyTY6Ym+QHOAbeAzWq1ShgDNoCbMtc4hb8B3G23Ow1NqxGHdToHBjALXByl8DPA7f22oZcreUZhjf16A/gKeDVu8Zd0Hj5dyy4xDjN4+AfwVlzir27mFvVkep5x2pO9xTpwJar499eeLXSUzHdMwh5tLxwAH4UVf2NSwpU+k0gVVPxVoZ+0cKX3SlweVvxMKr9UGzRhMn0vdpHJ9L2B8z7JJXTgbT/xZ3V+e7qS/vZoQjeLGyLpmMvb7zx1ft2ScD4I4MvH2/dRMt+zmvmB1czCCRv1FVh18WlreZRdlPvhcy/xF9vtllEovyBf/veEFdQX7Jb+YS2bMM/GqAB2in9SUHdcNeTLz2l3WrKUpt0A7mqaRk2rU9P0PqtTrzVQKyUz0YwSoKTm0GtNDx06ohG40y/+XKvVangXXhWzZilV9kYOUFB3TPHi00tPu902egpAqSqFzMvkIAGQemU8ALrl01sT8IkTYPMUAvxui5/WNO0wKoBfHO8fGxVA07RD4IIAXPcZ6AswXBwfnEeSwQHkKrwnAHOnGGBWAJajAjgF/Ff82wyFIsRpRXWXXCnrmUeS4QB+FoBsnADucdw/jyTDAaQFQI0TwD2O++eRZDiA0lSj0WjFD9ArIOrxmoc1m8390w8AqPZgv1KiHHIJRF+C1R6z5zSXEJA5dqJ59m5ElFopjhygqO6aN7x3H+lYq30TLzupypWCS89mzxQv5WyYMBgEIFfKmtFKbni33lF3NRxdATOMzh07KLDx7Cdz4+Des0mEKgWCAKxlE56+17fvUyg/t5ZY9SiRXet1kGAlPTegZxM8kwbL5POuJttc2SnKxsaeH3hXAC50iznbwY++1eYor4AywKdsLW2Ao2LOqkg3opbLUQGUIeaXfbENAKw79wM3TyHAxz1bSmlxxwdwMo775RElAMBB57B3S2lBzMYB0I3jxomcImdNolwcAMDXrm2VZks3ogLYcVzOtjN+++URZUgAo1Wuez6eAr6ICuAdxwfnEWVIAOAzV/EWwJkmK1tBAYaJ4355RBnCh8GD1MDWogUxk8onamGvQFBgZUizmruXBop3QFx5Cdvr7wwl3gHx4aSFK12TjPtBIPEv2SOmG6HEOyAup/aW6sO0S+K0VH6pFnjZDIB4U+fBlnvvPn4zutFmJhbxDohX5EG3JBL33n10qzUL9oPus7GK7wOZBr6ResStfx/GDrq1zZ2xvgBivezxKfBYavOgL3pY9fy6tMmB18Ym3APmvDRarRc2fgH+km6HtGzE5Lv1m/wnY2Ts+Tic/w+KWxyiCTe05gAAAABJRU5ErkJggg=="/></a> +<a xlink:href="https://github.com/Pillow0-0" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Pillow0-0"><image x="782" y="54" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFgUlEQVRogdVaW28bRRjNA5R3KrVE5TFQ/giXpklIqGhwJFBVQYtKAw8gwSPPkNhx1SSqVPVPVKJEQrwgUdrS0NhOmpBbc1Muztp7sVPfkoPOXuLxZr3eXW9CYunIK3tn55xvZs73zdgtLSG8ALwBoA9AHMAYgFkAmVwuVyJ4bX42Zt4TYZuW//MF4DSArwE8yWazkGUZfPcC614AjwH081lHSfxNAEPFYjFPIhYsYorqDvFe2USpVMoBiAE4d5jEXwXwTalY1uwk9qOayWJjRcL6soQNJ6xIyEjVEZBt7YuFYh7AjwBeC5v8+V9v4tmdzyaxNJWGljfIigQYXRK8d20Kw5eTGO1LYTRioi+FkU9S8Nr+wQ38A+DtcMgv4NLtjllt4P0JDHUmsJjcgpZXHAkw8iT/07vPMHhhAgMfGNCvfbYf7pxTsYqe5sj/jSvxrslyrDOB6MUJ3PooicVUui4BThNGm4RJNtZhImD7eGeqgt/wZTDyv+P6PoGOBKLtE7jVk8BiasudQCSlR11s22x73Ee/P/ILuET1x0VAnCMhodsbeaBtuHNeiTlNgZ5kYwLmFAi7/XDXnAbgnUbkT9FtuODYIaOm46KxEOMfNo4g3eaw2t+/inHauZuAH2h1XEBccBxyA0m9czrEi0mXRbgi4bDbA/iuHvlzxUIpR5+m1dEtGC0R7FxK109ETFKH3b7wssSp1OokYIgPYZJhhOrBqRQQPzuK9gAG7eRPs7bRi61MAwjF2IFS4ojal4zaqVoAsqq0R+S4A8BXooAnJ1DAI4t8qyzLe808LOh+QG5OxB6AsxTQF0ZEmtkPyMFHoZcC4mGRD7ofkIMLiFHAWBgCmtkPyMEF/EIB82EJCLofkIMLmKUAKbQRCLgfkIMLSLfk8/liqAIClNNyQOzs7BROvgAAkl8ftyOTyUJRZKwvedgPJLeg5ozCLRuwP4urPoUAzFkf8F3RZKg+wehrOwo21zLu+4HuBJaep5EvKnob1W8/WnXExUU8dsDHlwwv94wlCZurEl5MpXHn00kMdTnU890J3P44iZlHG9haz/jvY9nIJWIesWw0XuPjX1R9fCTiD8O9KUz+sY7laaumN5Hc0iNP8nevTun3jfp47mjEOY9YiSxS4+O9KfxMH283ht0zTM9fW9jGTlnV57lVw/Oa04aR15//npEnBn1AzyNdtSYA4DIFnGVh5OrjHsG5zujvL1Kzhue1HiAu8ojDIu9ogJpDASOPyFmzmDMr0seNbNALeV3AjPOel4uQIzxiCfD7/PZaGwbwUNwP9J9AATdqtpSV3XLOEsD57DbEJOomwO7zep4wp1A9AVGzvRcBeyjXbilNETH7CFgPtcNJhPXd6tw28gUFsiLsAxQzT6wKa6BOQKL1+hMEABhwPFZRtws5KxEFFTA3vom06fPWPkDPE2sZPU/w+X4FRIVEmF58qdb9eQrA9yuz2/o0qMF0Wo/s7NNN3QbdpsAIPV7cC9j2BJaj1Gv//M8N3YrZp53Hyr/bjP63juSFX2HGDf929vFGU0DcB9jBtdVoBNcc8ojFBcBT16NFU0TbbmVXEc9iRB8Pugg9m8D0wTxClEtlnsiddyUviOhRVbUSpg02Y8OqqlYAdHkiL4i4dkwE7AH43Bd5QcQVTdPKooBApYAPEcsz1WLNjPz1QOQFEd2VckXdHwGnej8kDF6ojgDXoe9p4yLiLboTPV0/v2e93yPW++Eg3p2wrJJu0xYKeUHEK/yhW1ouqEadf/D8vllszOesH7pPhUreJqQVQJT1iNs5vh/sGbXN4JH+AcT8s8dNAH+xNm94rm+DWc8/5DE5gNePjHgdMWd40Gr+YeMBgGmedvDIhuC1+Rm/4z2890wYnf8H6mnQeStuVN4AAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/topkie" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="topkie"><image x="808" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Warma10032" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Warma10032"><image x="834" y="54" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/YumeMuzi" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="YumeMuzi"><image x="2" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Z-fly" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Z-fly"><image x="28" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Zerek-Cheng" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Zerek-Cheng"><image x="54" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/wryx166" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="wryx166"><image x="80" y="80" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAD10lEQVRogdWaTU/UQBjHOYjeJVEJHvHl0xiNiQZPHIwYFT1ookePKiy7Bowc/BB6wfAJ8CUiAiYm7LJED6K4MPuGbLvwM8/SlW7pO7MFmjxps9un8/9NpzP/mbajQ8MGnAKuAc+BSWABWK1UKoaEHFu/TVrn9ElOx35uQBdwF/i4traGPZRS//f2Y+d5wAdgUK6VpPDTQMY0jGpRKZzhFO+EcMupm2YFSAM97RTeCdyr1Izyz8IqXrEacAeWfXKLfzeqwGPgmG7x54AZKfzV1yVG5xZ54RJjc4v8+FOg7AIgNR02H/gMnNUl/rJpmuWSUo1aGp1d5OnnLEMzWZ5ZYT/+vlKgXNwNEDW/Xq+XgEt7Fd9fLpdNuwCpKSlw5EuOlEsEAUTJL5VKdeBmXPEDfgKcBQ/PZBsRFiBKPjAYVfxloT8oAKXtO3ExrPjezc3NorMLDBLQFBEXIOWTLyHPIXA+SPxR6W3c+vCmAOkp5GEbdomhEABx8tVOU5qW7twP4JEzySng5Xy+8QBmZnNkZG87Tn/J8SMAIE6+aoV44CW+xzCMiheA7GWQWlopkP/9xzMKPgNZ3Hy1uyl1uwFk3BKcImSQkhryiiArETdftd6FlFN8V61WqwaJd5oxrwhr5tZC5jtDWkqLARRX6Ud8EAO4bQf4eAgB3jfFdyultvZyMd1NRIWLLeCkAFzTUSN+fj/MfEHFuwtXBeC5LvFBfn/ZY76g4gOkBWBSB0CL35919/rj8/nGOFDWBzAhADldAE2//8TD78sILIOV30irogEsCEBBJ4CX3xevI5ZBM8BKR7VarekGkNp2c5rid3QCrK+vbxx+ANrUhFJJNSEgqxPAy+8LVLpND/Gkzm503MPvi3jpoTQDTGgdyHT4fRVjIOvb64V0+30VHuCKAJw81GZONlkl1lEjSQYw1RBvAQweQoBbdoAumaYl3ARiN8FdU0oLIp20n1cuEGHKB4ZbxNuXVZL088rlDgSVb26vWru/ngIeJunnVYz5BHDfVbwF0DkB00n5eRVxPvEaPvkuLVoQvaPZX8Uk/LyKMJ8YXfgpK3LnfMXbIC6l5/L1dtthFdKOixbgQijxNogbBwRgC7geSbwNoj89v2TuRxNK7dT8QCzxNoiLY9nlUjv8vPKZT4zlfhUjNxsfiDNvYFq3n1cu3ah0lVZv06tFvA3iiLzorpn1UrNQnQBKKTZqteaL7qNaxTtAuoERr5chccLY9japRD8AsT72uAO8izmfkN5lSpbJgeOJCfeAOSELrdYHG2+Bb7LaIUs2EnJs/Sb/yTly7gkdhf8DLO0vV4ipOKMAAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/songzy12" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="songzy12"><image x="106" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/aliyome" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="aliyome"><image x="132" y="80" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEpUlEQVRogdVaW0tjVxTeMV4fvEt0vD3oRAUFNW+iaF68g46pt6qggtRSa420aAXB8QaCVseHQJ7Fo/ggXoLm6y+YdoaZ9nHAzi8YLMyMAzOtuMo+HOV4TjQn8RyPDXwk5Kx18n37rL322muHMR1eADIA9ABY9/v9vwI4AfA3gH8k8M8n0rV1AF9zH2bmC0AqgB8AvARAYeIFgFF+r/skng3gGYBPdyCuxBmANQBZRhKPAjAG4KOOxEkBPihPAcToTb4QwJ8GEicF/gBQoBf5rwwedboBHwC03ZX8AIB/TSBPEs4BfBsu+WETiZMCo+GEzfkDIE6yJ/FEK/nHAN4/ANKkAJ+HRcHIR99ztqEQ8Zqn89sE/PwASFIQ/HQT+SxpRTSbIGkIpUeBBDx7AORII34JVJjpWdsYjbNrBaBUVdL/DCNyAXcpie+MmZkZGhgYuMLw8DBtbGwE8/v9kvwjABdmCigqKiLG2DWkpaUF8+Oc05m0kzI1HJKTk1UCCgsLtfh2MWmLZ6qA6OholYDFxUUtvmtM2qeaKsBisVwjHxERQaurq1p8j/kTeGsm+cPDQ9Xox8TEkNfr1eJ/wgWcminA6/WqBMTHx9Pm5mZQ3729vXdcwBczBSwvL6sE2Gw2Oj4+pv39ffJ4PDQ/P08TExPkdrvJ5XJRRUUFlZWVUXZ29mfDBfCRbGlpocbGRhH19fVUW1t7hfLycpWAy3kQ6HsFPhseQnxh0kCEwoQYQn8ZKWBubs5IASeGp1Eew4HyvE44NnwhOzg4EMuCUIhFRUWJEzkjI4OysrIoLy+PiouLqbq6mnp6eqi/v1+sl6amptaY1GglI1FXVydOWP7OJ3JTUxO1t7dTd3c3lZaWqgQ0NDSIWUh5n97eXvEePBvNzs7S1tZWJxeQbmYx53K5VAL6+voC2ubm5srtLiwWS/plRfrCLAFOp1MlgIeI0m57e5sSEhLkds/l+4FRswRUVVWpBHR2dtL09DQNDg5STU0NORwOstvtyprpO+WW0pQNvcPhCCf7nDHGrp8pSP35eyV/dHREJSUl4QhYMb2tIgiCGD5WqzVU8h8YY4GPpwBMGk3c7/eLKVAxISkE/BiQvOwU5rWRITM0NBR0ZY6Li6Pm5mYaGRmhlZUVGh8fv7z2ijF2c2vR6OZuR0eHppCx2+3X/Pjqyxj7yBgrvJW8TESbnu11HjZ85LWGSWZm5pWvz+ejgoKCc8ZYiybyMhHf6CVgYWEhYNhERkaKpYHy+6SkJNrZ2RF9PR7PhdVqHQqJvJ5HTLu7u5STk6MiyQWNjY2JNsrNCw+z9fV1fu28tbV1OCzyMhFPpAO3sATw1VRJnq+ok5OTVzYpKSkqG7fb/V4QhNDC5hYR9nCyE68oU1NTVeT4FlNuV1lZqbR55XQ6H+tCXiYiUjro1vw0lpaWVOQTExPFRUxu19XVdXn9E2PsKWMsWlfyCiG8l7qqZdXmRZlSQFtbWyChZxaLhff87+8PIFIB+D2A327aTwQq1GQdN+7znLfJBUFIuTfiN4ix8UarVBD6Abzx+Xyn+fn5XxhjHKeMsTexsbF+QRC4Dbe16fHj/wEqD8zp/KGkrgAAAABJRU5ErkJggg=="/></a> +<a xlink:href="https://github.com/david082321" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="david082321"><image x="158" y="80" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFFklEQVRogdWa30/bVhTHeVi791Vqh7pHtu6vmVpV2tQ+9WFqaWiAaYVOe+rboDRAqLSH/RV9asVf0K2otNKmyUn4GRJ+xs618wMSB77Tudd2nGA7sX1hgHSEFfvG34/P8bnnnpuBAQl/AL4EcB9AGsAigBwArVqtNsno2Pps0brmHo0Z+D//AFwDMApgqVwuI4oBeA8gSd91nsK/AjDfNFs1phuQYWbruApgDsDNsxR+BcBYs6JXtJ0izsIOda0G4DmAz2WLvwXgk7ZbxMofz5FNP0Xu1TNkpdoksguTULfWKbQ+AvhGlvi7pmlWmGFA2ylw8cpvD6FMP4YyJcmm7eNhlPKrYJUqWi3TAHAnrvgHlUrFpBdOABT501KmE8i8TCIz80S6lfJrHIDuaRhGC8BwVPGPGGMgawMUuKvpickWrrwY4eYGsO9PmSqs+LtEf1EADOGJ2/2KHzo+Ptbtwf0C2AL6FRsGgDEGeg8BfNtL/FXKNu6B/QC4BQkhiQAb8YRQegBYobRM6TwI4JfuQaE9kBpDZnbc2+hcRA+wNsRTP/E3m81mNS7A3t9LKG2uorSWQWndMjreWMG+8kmkYcpiEQFMEUqDXgDzXgPCAqjFPPR6A8yocCHcjAr02iG0/T0rDT+ODMCEF1Ld4q81Go2aDAB6+iS4rKkolzVhmgam61C3t3qPz/cGoEjpKACpqvS7ODSAh4C445m3F0bcAEuXEOAvW/wgY+xEGoATQlq79uchZECVCMAYOwFwgwDu97gw3Eu8tQG9Vucx3675dbBKDdrejkwAAPiBANIyAQ5y//BsQ0+7XesXuPjSRg7ZhQmZAHMEsCgTgAQ69b271qf/C5OxJzLWCfCGAFbjAnSUEkHrBDoXo5RgpwFyBKDK9MBZFXPMG+BgoFarNWQAxDUlAkC9Xj+6/AAAVPti3x5OH3lcGsCmxzzSZbZWHkIAVpynTGSUt40uo8+qwXlcFoBaoHnkUMwd3TrIXFrtl3jRTUWtE5637fy9UxA5nfL4etY3j8sCOLDnkW1x704tRRENbQ/wNJrmALoBbXfb6fu087fLFiZ8s4gsgGzHPDLpmkMmkPv9Vz4Z2u+IPZHdcwCobeL0fRIib3ebTx6PKz5jH3vdk7RMDfNWDi2OBAD1i/E9AdzgxZwFQB03HiIBfZ+z9EDG83xSnJsd52HMF0msLIo5qyJ973iAAKbkx3h8wIQFIDwA4J17PZC8hACJjiUltbjjAMQtJTIhAMwTdC4pLYi5qACn+0LBFgVCcQEAeOnZVjkyytWLDnB0UDR8t6cAPIsbQvv/LkMtboreUH5N2OYqn2Fpkoo6ESoWAICfPcVbAFfw5tVyHAASr9ePQveFMn0A4PXMh8DWogUxVJwf06MC+C/qqS8UvRjcmh+njtytQPEuiDu51GgrEkDEtkomwHKpJLXXv+tLvAvi4QUBOAHwYyjxLogHK6lRMwxEMIBri2om2e+TfxRJvAvidiE9bvTq+fP/0wlnk87XA5SFpoZ77iMUF37SQ4dNAMTXeP1i2bfv7+r/9/IAlcS8UAz4HohsMyRFvAviM9roponE6ft7WFlVO1ZN7mPKRlTPi72D7Kmxtd28vdF9Var4LpBBALNUjzh53m1d4rshvMaYorZJnesPQKwfezwB8CfV5s5egGt5esoDzsJcs+v5d9QmB/DFuQn3gblOjVbrBxtvASjU7aCWDRkdW5/RObqGrr0u4+b/AT7ws/xddM28AAAAAElFTkSuQmCC"/></a> +<a xlink:href="https://github.com/Koril33" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Koril33"><image x="184" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/eya46" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="eya46"><image x="210" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/gwy15" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="gwy15"><image x="236" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/hanfangyuan4396" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="hanfangyuan4396"><image x="262" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/holll" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="holll"><image x="288" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/huanli233" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="huanli233"><image x="314" y="80" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAY+0lEQVRogcWad1CbWZru+ePO3j9u1a17t2tCT9jZ6fa4HbrboW0c2jlnt3OcNu2cbRzadjsbYxzAYMBgckaInJPIQRICCSEySAIhkQQi5/S7hebO3Nrama2d3d65T9Vb5z1vnSo9zznnO+f93k8WFj8CwPQLMB1l0vgOOtPGRpvrx0abu8A0Bp1jYJr268GUBh3TY44wZfyFxf9PTMBHpt6eqzBYDL0MD7YwPmpk2jfbVDdMdjEy1MrEWIfZn5ow/TH+pzH0yvoHmq5MTPV89HcjDkO/npwYcertGxhMS8/A+e0bqsqKYWqEqdF+ejqaYWLI3Gds4I/tn2xsgLHBbrNNDPcyPjItZoDxyb4BY3urY0pS6q/+64gPt/1kpEd/bXzA2D/YY0QqKSQtJR2dRktGcirl8lJaGpvQaxoQ5+SRnSYiV5Rpbqf705aWkER4cCiB3r4EePng5+WJj/cHfP08SYhLJDEudbBF2/GkRdv+339U8oGedp/FBb9TRge9I8jDgYykCOxfPadRrUFTpUXgHU50UByxIQlUFFWjLddRWqAiJjieYA8BkQExxIUmEi9IQhSbRaWshkHjCIzDQN8wTMFg3zjJ8TlML0p361Cpj4v3zB+FPJMt+5gy9DNlgMkWjJoSRrobiRb4MDYwgL6mBT8XAaKYfIqzy9GqWkgOzyIxLIOakkaaqoz0GEYY74aRTmiuNSHNUCLwiuGtrRs+HgKc3nrxxs6Nns5J6lXNpMbk0Nlk6osJFe75T5FXyGKsKooixqulAspy/enTF9BQlkKXvpSsFAFpcdF063spy6+jUqLF+20IhSkKGsraaK3twajup795gvb6PnNs2v4U62ocRlfZgUquw8czitoKI4qiBrKTi3l+3968Yr7vPSc0larz/yHyEqnwnLwolNb6BFprYqgr8mXUmE99SQSGmix62yuIFwbS1zJAW10/fYZJInySqZe3MGLE3DeqB9Eq21EVaCjOrKJKqqNDM0S3boxKSSNJwlzSEuQU5NSSn1lNbEQeEQFplIprcbJ1oba0GlluHsUFGVf+JvI5BUH7JFL/CWWJH7rqUHQV/oy2p2JSx9JnyKSiSEh3eymCgPf0tPQyaoKBtiniQkToq030GMYw6YYpTCululhnnmmjdsAc62gYpE3dR2OFkWp5C/GRUpJiFQT7puP7IR5HWx+CvaIJ94vB29mLakUZtaqSiehw32/+XeSzCwNmZBd49RZJPVGVfKBTF0GPLpzxjhSaK4Npro6lp1VMTro/4aGeRIXEwhhmEZFBqWaS9apWsuKlGHVDtGv66WgapqtpxNyfFtDe+EcRuuoe0hNUhPjnMNQNFYo2OpvGaGvoIzlChL9bAJFBYaTGRpObmdj/3vXZrH+TfJ408B9yCr2VeYVuFBe5UVHqTmOVF6PGOCa7UmiuDqOhPAplUSTBgW9QFOcR5CPAoOmmUz9EtbLJvPwFmaVoKlrp65g0nyoDJjAZhmnW9tCq7aXDMGQe39owRFVpD8mxKtRVfQx0Q11ZC0ZdH56OfkQGRnH97DUKM3JpbtTg7/tOodPJfvJXBeTLAu7mSb0plHqgkLtTqfyAWuXOQHMkJk04huoI9HVp+Hg8ISs7hk5TG/rGDtxdgukzQkN9J8HecfSapmjW9NHfDcPdmE+Xdt0QOk2XOd7ePESHfgRDwxBtesjP0pISJ6exvpcWTQ/RoUnI85SoyxooTJdSW1rDQFcPnu5OJCcH3vqL5AukIb/KlwQO5Ip9KJB8oETmTrnCnW5DNO3qMBrKgqlXRCAXRxIb7Udjk4ZWYzcd7cMUiWuJCc+hosyArLAefWM/vZ2YW2PzOK3Ts984hE7bS4tumPaWUXOrrZvuQ5NmkszU0v8rrI/o0AT6WgfpaOzC2NBNS307Pm6+lBZLKZKk9mflBn/8r2e/INgptzCQnEIf8sUeFEncUEjd6G1OoKUunF59BvXKRHzc7dBqamhq7UDd1EOzfoT66i6S4qSUl7agbxiiVT9GTUUHhumjUjNgjk37zboR2gzjGFsmzb6mtg+deozOVsjLLKdMriYtLgt1RQN9bf106XvR17QTGRDPsx/sKCoUExsdiLw0xeFfks8XfFRQEDaYLwmlUBKIWOKHTOKJXPwBbXkoDWXhGDWZ1CrS8f7giEHfhmb6/K82oVIZqa/tJTuzktbmSQxNY8ikjWjq+6mt7qZBM4heN2qONzWOmP1m/bi5bVBPr8wUJVI95YomwoLjqSippqe913xLt2k6cLf3IdAtnPcO3pQrKpDL8snJixwQ5fr8vwRQVhB5VVkopFIcQo3Yl2rxByqkbiiL3qNS+FFU6EdyrBuFuUkUS6RUVTXSZoLM/FpK5A0kJ+XToh+gtERDuVKPtr4HoSCTFsMYWu0QOv0YjU3jqNVDqGuHzLPeopmgWT1OdxvUV/dQItGg03Riah1kpAeK88rxdgomLiSTqIA00mJzcXf6QGZ6AvKSFNIyPS/9WUBFQVSxPisAVcA9Kn0uogo8TWuJHZKcB+SXvCcx35MCeTphUUK02hbqattpNU6SLynHNzCAUKE/r17acOPqFR7fe4jt41dkZ8rQNw+g1g9SXt+FpnmCOu0oddVDGGomMFZOUZysobcFNNW9qOQGWptGiRFkE+aXTqlYT2PlIOqyftztw8lJlPHw5gNqK0soksSSnu5WZCZfXJD0cZ00fqo23B594F0aXI/RJjhFWYQVdSW2iEvdSCkKIk2SijAhkeraFkxGqFC1IkqX0tysp6pKQVxkGExMkh6ThMsrV9KS8qmsMFCtMVGt7aW8tpsmwyTVym6GWsFUMU65qIFycRP1VSZ09YO4vg2jSm6kuwVKC9voMkCbGjwdY8hLVvD+jSvi7BRyRCEo5ZFTipKgn1vIxYlHq3IjqYmwRxtwG73PSdrDTlPwfjcdKieKC9+RkR+AWJGLV1Ao+qY+WnQjqCs6UYq1tNZ3UymrR+gdi1RUymDr9I2cSXxYDtoqE/VVnZQrmzG1TaGt6qBTP4KqoB5ZqgIv+yAK0lV0tYNeO4goWc5oD6jLezDUTaCtGKahfJiEMCmlhRoSIpIJ9fOgIDuCBnUm8bGvDlmolTnvJAleGPMDKfe7TmvoZXT+Vqi8jmLMf0ld4QcURRHEJ4Xj7O5Fk64fdVUPbfWjNCi7cbYJZvea71i/+CCWc7ezfvkR7t9wxOW1gKbaAYyNo3Q0DFNZ1GDORFOis0mIEvHW3gNHBy/qKtuRFdZSV9lBjqiM6tJWTAaQ5TRhqJtEqxqiOKeRzIRi5IUq3ju8RpIbR01FCqlJzo4WLbXStMwIF0ylEdREP6LS5zS6gNM0BV9AK7yDOs2F5nIREWEBBIVGoSxrJiu1AkP5IKYauHD0KaeOPEKUUsfNWy6cOv+CletOcPX6K1SKVnO+o8yrN2enqiI1qjIdrr5heMckIxQV4u4pJDerFJ26h2JxHSq5nrrKTpKjSmioHKZDN70iffi9j6aipBbXt28pzEugICeEuurkZIvmOrEmO86NqnwvWqRuZDsdxiC8hiHgChXvLzIuj0QW5YUw0JvnrxwZGIbYiCJ61VCV24ajrYCk5AoOffcDF+458YNjIMnFamzfh5CUrjBvoekVKCvUkCVScuXua9YeO8/vtu5h8+XbzFu6mc0bDnDp3F2S4vKQS9VEhGairxumqXbELGKgA1KjJUhzSvng7IpKkW9+DsR5IfUWjep8U47Ih9x0J3RlvhQJr1Mbdh2t92WqXa5SF/iKVNfndLXqcHL3QVRQyYH9N8mPq2W0DSKjshGVlGPjF8jTkBBOvXnN6/g4nvgEcPbOYyRFNWYRSpkB21fBWH3vwLLTd9j+2oMbgiTSimrYtuUgu3YcRShIoqiwimpVm3mb1qp6qSw2oa8dRylpIlqQgrebJ0UFWSiKU8nODO2w0DQWjmbk+CHKckEuc6dZ6YHY9yJ1PtaoPe8ynh9J0jsbkmMEOHp4ccfGhQtXXvPDJVdKsnSk5cjIqVTilhKNe24SrgXJ+BRnceblUyKys/jh4QsKMuUoi3WEROTz8EMUN4NSOBMl4m5yPndee+Ds5Mv2rYeQFJZTV9WKttZEfWU3evU47Q0Q7p9HcpQMT2cBgV5BBPt5oa0vYWzYMGJR21Q4Gp/hiUjqQ2GxF2qlN8q4Z2jDn9EksKPU5wXNBUmUl4rxEQhxCYrnzOWXOD6P5t5VJ+4/folzkBei6mJiKvKJV0uJrsyjZqCZyLRY8/Uf5S/E3zUQd7dQXMNTeZWUw2lhLG/ECl77RBAXm8OD+2+orWmjtqqVpoYBalRdZgEGDYgSq6hX9RInzKG7vZ93DvZA/3SJZsRC31dpEqa6k6UQkFPkTVGhG21lIRR43kIV8BTRu3v010hQ15Ty5r0bj+w9cHCP58Jpe9SqQd6+9qKssgatyYi6t42GsQ56GWKQfiYne+k3NEBfL8P6ZqYGx0jIzCajXkOsoRF3SRGyunYiw7NRlupobxujvsaEskRvFqAq7qS8uAdf9zRyU6vJS1fRUNtMlaqc6Ijg6ZJMh0V8nkAdmxNEuiwUUb43MZE2NFfFoMn2ojzWiRZxFNIEf3QaFdZ37nDPxpFHtn7Y2oQjyTBQItLw8q4zDIGmTsc0erumT58CGhV5jKlVdJXkga4GhqYLXH209TeTVpFPcUsDkYm5hAZnUFPVSW52JUqFgRbDBN7uSRgNEOiZTUlBO206ePbADadXHmSmZpGRmkR/T2u9hX/MhzTPMEfKNXkUSMII9H6AMtefkqT3tJTGUJUbijI3EoU0g+vXr6NQaXF4F05SUi0pMTUUJ2qxPnAfoXM0GCdhBAzKMnqqVXSXielT5EB9Edr0cOjWYFLL6DVWM0EHWdJsPDwjqSjrokzRjrp2AK8PCTx56ElaQiXZaRoig4upKOlHLm7Dxz3BnORJ82WEBPgDI8kW9W0V76JTgomJ86asOImi9CD8HG8T7vUIZ9sziGJdaajIojg3CUVBPpLcUvy8EokQKnj6QxBKkYF3t32wt3bi3h9ukeAaRLuslM5iMUMVUkYrC2kujKWjJJWKtGAYb6O9tojCNCFMjuH8NgQnxzjCBBJuWDvx7LEvD+56kJZQTai/mJLCLspk/TRrML/0RIVlwCQMDQwCY44W6tbqI3niFNQVErKjAnB7coM7J3dz59Ievtn+BSe/XcuVc7vxdbBBLZPh7+iHPKcOhczE8ych+DjG88E2CK/nvoS89sLroR17vvqKCAdb3t0+R6KXHbkRrhTEe5MU7EytRES6wJ9wdxcuHz9LcoyCrAw9z56EcPqULYIgMRECGZLcVpKiqwnxlSIXd6OUmiiVtuLsEERTg9FcDIPxgxYTDP38vYvdVGF8JBd3b+Hyrg2UpoZhdXAlC+b/Ixs3fcZZqy3cP3ecF5evkfBBSFWehtT4ChzeRhEqEBEWmoCDjT0Pr1qzc7klsuQoSrOi2bJsBuettrJ+1Sz27llNeJg3EUEBSEV57F65nYdXbXF6GcUta2+8PfMI8BPz6Ac/0pLqyM0wUF8Fdk/CefFYyPfX3XhnH8731na4OHlNC5jq6+3++R8rEWlRsntnjmN38STnt6zk0am9BLn8wK1Lu9i85lO+/caS4+sWc2nHNuzOXyc9IBF5bi1vXnpx4sQ5Hj9+zEubJ3g52eP07B4h7q+JDXblytn9KORpbN62BN9AV4IF/qSnpnHl7FVunL7Jkxtv8HRNx9Ulkw/uuQQGFCNK0+HiJMLFKRNPdzGP7oeTnNBIsbib/OwmxPlagoOS8PcPl/z5fSAm2PnKd9+s4snFAzw/v4/sgFckuT8kwsEa631LOLVxLptnfsT+RZ9xevNqjm9Yw8XDh3l47So2t6xxeHSP8wf30q/T4GzzAElqHKHeLlw/Z8Vpq0MIgr1wdLQjLk5IfEwYDi+fI84SkZdZgMPbSJ7ZRmP7MgE3DzGSolEkRROIMvpIF/UTE9uGWDJJYeEwKakGCiUmktNqcHaLu/hnAS/unf7o7vk9A9ePr+feiU0EPruAx+1jCB6fwef2MZyv7GP33J+y6rf/g2v712N71YpXty/y9sF1Hp79ljO7tmC1fRNv799m+4olrLecz5rFC1g0ZxYL53zG3Jmf8MWsT/h66QJ+908/ZdHCmQT6uqCuq2doBBQVI5y/7Mxbl0wePYsnK3eInLxxcvIgI2uczOwxc1+uhIycHmITdQOBgtJ/+U3B/eVNR5trh7h1dD3Pz+7g1NqZ7J7zv/h22W85u24Ot/eu4vWlI9heOMb9M4e4c+YIB9YvY9uS+Vw7fgD354/4w46NLPjkN1jO/pQVC77gy9//MzN+/TELv5jNgs9n8rtf/4xF82Yza8avWLPiK4plUsanICG1kh27r+Pokord6yT8AlQkJHYSH99FYGCT2T541JKSNkRSygCZ2cP2/6oqYX1y56+eXjsycO3Qau6f2Iz1bksz8QMLPubyloWcWDWXc9uWcm7nKpbP+DmbF8/lxe0r3DtvxfHtG1g84zfM+On/ZM5vfs6mZV+xaPbvWfLlbLau+Zr5sz9l/QpLVi9fxIolC8xiplt/Px+CQ+PZsesUX87fyrFvH+Lukc2Vq944OubjH1CHv38jgtA2XtgWY2+vIjCwrS86euAvf556dPnwHTvrozw99w239q/G8fJBbuxexu55v+TEmi+xvXiEbzcv4+tZv8Rq90ZunjnOii9msnnpApbM+h17Nqxgw5J5rF44h6Vzf8+mrxezetGXLP78M7NZzpvN4i/m8Nlvf83q5ZY4v3Vgx8697Nx9jKXLtzJ/wSaOH7uPn6+YN6/SeWmXg9NbOa9fyXnxXI7N0xJevay6afHXcN1q10/sbvxBYXv5IFYb5nFhmyW3D67j7pHNWK3/ipNblnF+70aObFzOmf07uHf5NF9/OYvVCz9nveWXrPlqLivnz2LxzN+yY6Uli2f9M/M++SUHtm1greV8ls2fy7Y1q/hy5gx2bd1ERmqKOfUQZeQgFMSzbu0eLl98xulTNty45omdbQqvX+Ry9XIUjvZlvHOskd+4lvHXS4vTOH9gw4wrBzf0Xtm3jvM7l3Nmy1JOrF/M2R2rubh3EwfWWvLd7o3cPvctu9YuY8vKJXw9fw4e9s+JCfTksfV5Vsz9lM2WX7J7lSXbly9kwSe/Mj/YW1ctZ8Yvf8FXc2fj5uREX1c3cTGxTE3ByNA4jdp2rK8+NteMooQynj0J49aNIC5c8MP6enj/w4eizyz+Pdi48NM9xzcunvhu23JObFzKsbWL2GU5hwOrF3F82xouHP6Gs0f28PWCWeaZXTT7U4TeruQlRuD95ilC9ze4PbvDvTNH2bV8AStmf8JGy3msWzyPZV9+zoqvFnHH+iYDPb0kxcWTlZHJ+OiEOUXwcg/BxzPCXNmbriE1aKDDyITzu8xdFn8L7G6dPXti6wou7t/M7RP7ifZ8R05UKKHvHbA+eYxln89gxYK5bFu9jB2rl/D2yR2yooKI+PCam3/Yzf3TB/lu2wpcH1xn/RefsG7eLLYuX8yi2Z+x2nIJ32zbRbuhjfAQIaLkdKpVNWYBQf5CWgzdBAfGkJujpLK8baqnh9MW/xG4PrtrlRDgPv7e5h6edk/IiQkjwPkNO9csZ/GcGezfup79m9ditXsLIS6vcPjhMo/OHcHX5gZejy7j+fASzrfPcHDFPDbN/z2zf/G/2bhkEcvmL+DA7n2E+IdSKitDnCtFUVRKa1MbEcJo9LoWShXlREclTHSZBs9Z/Gfw8s71b4JcHfrCPJxJFATw4t5NVi+az1rLhaxfutBM/u7pPxDi+Jz396/i/fga8kgP/B6cx8ZqBxe3WiK0f4Dz3Uuc2bOFhTN+x9ollpw7eZbM9FwS49KRSZSkJmXQ1tKBICSMqclxYLK3TFnyt22bvwZJeuLvk4Whikc3r7Fz3SrWL1/MwZ1b2L5qKfvWLOP1jfP42HxPkdATSfA7ol/e5NGB1Zz6+hNOrZzJ3UMbOLlpKS4Pb3By3y5WfrWQFUu+RiqRI84voa66ieSEdPJzxQT6B9Db0ymHkRkWPyae3L753w5s33pt6+qVfYe/2cm0nT60B4HTazwf3eTu4e3E2j+gLMyVDMe7vDi8ijtb52F7bB0vT+/C7uJh8xF8//IZju79BstFSzh95iK52TLSU/Mplinx8fEbNHUan/R0G//B4r8K3x7c9/GF7759u2/7loGT+/fg9vB7XG6ex//BVZ4c3czFlbO4tmYmV1b8E+mvLiH3syXhzQ0Cn17ljtVe7lyw4uje3WxYt55nNi85d84aa+v7A16e/g6PHz/9+/0BZO/ObR8d2b7lsr/tI6n3natTca8eYnN4Mw92LMbh6GreHV9Jtv0Voh9/R4ztZewvHODagU2cP7STO9cv4ujoOJWdJ5bUaQyX2jr6/vHvRvwv4dnxfT97cnDLoWcH1jkGXDuc4nl2W43wxn6Ty7crR5Ntz40Gfn/MlOD0Q02Kj31KqsDHceu6FYciIoQ/+zF+/P8Aoz/P2DCQJKoAAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/hui-shao" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="hui-shao"><image x="340" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/iBobbyTS" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="iBobbyTS"><image x="366" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/ouzexi" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="ouzexi"><image x="392" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/nanguoyouxue" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="nanguoyouxue"><image x="418" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/cibimo" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="cibimo"><image x="444" y="80" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEcUlEQVRogdWaTW8bVRSGs4Cyp1JLVJaF8mtQq0qgdsUCUQQNLECCJRsSSGPyUdFCSEWiLvgHoPyCQisKEsJOMCS1kzaO7fnweJwm/siDznjijsczng+PnSbSK1vOnHvfd+697z33zIyNJfAHvAJcBeaBVSALqKZp1gXy3f5t1b7misSMHecfcBr4CHig6zpxANwHJqStURJ/FZg7ODioxSXuRr1eN4FZ4Nwwib8IfNxoNKpJEdddkJsCfAG8lDT5C8CfwyKu906tP4DXkyJ/eZh3XfdBs9k0gEuDkn+nWq02Rk1et2EYRhN4Py75a8dFXO+dUhNRyV8W9cdNXO8eiYthyZ9vtVoVTdPwgzR69JkENEebfpB1CLwRRP6U5TYVA18kTF53idArFd++gYdi5/0EfK7uFlAKO97Y3UFT1aGOgBrQP/CpH/lz+6Zh/vPTIms/zrG+ssD6so2VBdaW51m/+y3l/CN0o5q8gErFIh/U/1OlJFNp3EvAnKiU4PStSdLffdWN21NkfrhBKbeBXh2OACVk/0DKTf50vdGoyRCJWgnILN4gszjdQfr7r8ncSVHKbQ5tBJSQ/Tdah2ZXAihZZXcDU13BnQaWpIGNEQiYCuwf+NAp4MEJFPDbEflxXdcPBxEQxsf77SNaDAHCGTgrAq7GacA9At0+3gceFqzF7B94WwTMDyrA08d3XSjsoPrsI1p8AbMiYDURAbaPZzs+frPt5SvB+4gWX8DPIuC/pAQc+fjft760/XvKhvj4pGWNXvuIFl9AVgQoiQmw4m9G3ke0+AJKY7Va7SBZAaOL39vb2z/5Aog1hQzLTZ55u9pZA6OJrz6bQsC/UQSUtx5RMWuuvL1iLUy1uDv0+JLHIo5gozMUsxnUUhGl8KQrV5fOy/lNyy7bi3gY8SlPGw2/kS1O9+bqrpzdeW3i8UveG9mVIAFHDcpnT57uhuPapOIz/gLeEgFnQydzrt/80G8EBopf8kjm7Iz0fpCA40a6N52+5zwPTJxAAR90HSkbzaaZlIBBp1AmQEDPkdIWMesWYC26GOi7iAdpb6ktAJjxLqtUDXNteaFdAXiOBKRt95J9ZF8pGr6Pp4DPyo+3KG/nKG/nw2Mrh8QVN7KBG1kh8xfKk8ftmO18ZACfeJJ3PIV5aNlUJBhWeiA7bHAqkaNSe2rF6BH7AX7vW1oMW9ztgXVMHCSZ0wJhF3cv9CXvEHEpSnk9iaKAHlxefzMUeYeI954TAYfAu5HIR33E5F0anPY5UoYXYLTv/LVY5B0iLsoDt1AC5FAvLnR70tcGwwpotVqVyNOmj4jXLHcKECB1HymdWAf6Oylryliwvs9YqXQpH1wcpu025xMh7xDxgjzo9hqNTmFLVa26j9xlqT60Px3Ib6Ipimd1Tu9+0H0qUfIuIePAN/J6gGdpUTy72sfPPcjX268apEb6Aoj9ssd14FfrPBGxuGu7yz0pkwMvj4y4j5gzUmi1X9j4BViTaoeUbATy3f5N/ifXyLVnkuj8f7NrftOT4QiGAAAAAElFTkSuQmCC"/></a> +<a xlink:href="https://github.com/RayWangQvQ" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="RayWangQvQ"><image x="470" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/kanke233" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="kanke233"><image x="496" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/womeimingzi11" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="womeimingzi11"><image x="522" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/PaidaxingTuT" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="PaidaxingTuT"><image x="548" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/colour93" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="colour93"><image x="574" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/wele0612" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="wele0612"><image x="600" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Luoxin" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Luoxin"><image x="626" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/xxxxxliil" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="xxxxxliil"><image x="652" y="80" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEk0lEQVRogdVaW28bRRjNA5R3KrVE5TFQfg1qVQnUPvUBUdQ2cZrEog0VIARvlLRNE1wlEQj1N4AiIcFboVULQsLXNsqNXGp7d3bXDtm13YO+8Swe23vzeu3Ylo68Ws/ZOWdm59tvvvXISAQfAG8AuADgDoBVADkASqlUsgh0LM6tijbniTNylB8AxwFMAHisqioYY6DvILDbAngEYJyu1U/hbwK4bZpmmYTYsIUxTfeG3JbVYVlWCcAcgFO9FP4qgFjFsoxWEfKoKvs7KO794whlbweqorSZUMWxaR6WAXwO4LWoxZ/Gr4t/Zr7/DIXNZ2B6qV2ApnPxuQdfIb10A5mVm8isfCJwE+nlWQTl45eFPwC8HZX4cxtLM0Zyfhypb6eQX8+CGSRAaRNAo0zi/757Bcl7MSTvTTTQIX9zOa4DONut+IvZxHQltTiF5MIkUvfjyG94C6DRJvEkNrV4TSAcP5OYrgL4KKz4Sw0B15BciCGViPuOIN0yNOIyt1s+gPFOxZ8j94NiIJOYopk4E1T82NZKXKNpbxYgbgESoBs8mjRiuwKmaS0CouVvLMcNAO/4iT9G0YYWHHVIo1bHZP2iiRkeRbTyv7zDpvhulKC82EN6ZRa94uPnuacUzr0MXKdQxxfg/Tifcg5+PIP00nW8yP4FJb+P4u62FOO3oezvorCRQ+a7T3vEn+Z8ADNu4k9ZplmiEaJppmjBvwXoPHWe/eELpJdvSDG+ATq/n3qCwtYa8uuZSPl5rimHinlIt9Kok4HbfFHpJT6dTdANPu00ctRJ8u7V9jgvUNzZhHZwyDmR8Q0JjNEs3GoVf5xyG3lRNUERi2x3WyyyWNsisxdqYeu5tEgj4qsyVDt3aiSAlFXKyVUrgoXJSSFgTYRJNTI+cwCAK7KBx0No4Hdb/Chj7GW3Bhq3QDgDKQ++C14COEkGLvg0dBVgj1rYGUgG5HvMwvtk4E4nBigtTs5P/N9hM2K+BsLwmbuBOTKwGsgAfSsKCtvrvBM3qErRdcMSls/cDfxIBp77NWy6oB2fnZ4XIk47dd4tnzkbyJGBYuAZ6HDTHhWfuRvIj5TLZTOI20HEwcHB4fAbwLDfQgCeBXHbTd0nCj7zWMTBw6hP3YfgVfcJy2c+YTTwg4w6zz74UtR9nPL5WR7neTbpUvcJw2c+D7LzQQ3YdRvXfH5+wv9JHILP3A28RwZOdp7MeeXza66Vt7B85pXMiYz00RCm0w/l/cD4EBq43LSlpG3asOwHrNYtpTAxNyz7AQBfO5dVXGZhkPYD1WpVd309BeDjQd8PAJh2FC+9hXk6qPsBAE88S4vCxFitVtMGLZmrVCpUkTvtKV4ycVbX9arPg6Rv0HWdyuvvBhIvmfjwqIWzxhP3g47ESyYuGoZROeKRvxRKvGTiDIWufouv1Wpax7eNh4m33KJTL4B6tBmLRLxk4hV60d3L2TBN037RfSxS8S1GRgF845U7dQqrntvc6usfQMSfPa4C+M1vP+ERXR5SmRzA630T7mLmBBVaxR82fgKQpmoHlWwIdCzO0W/UhtqeiKLz/wDOSEggh5VeygAAAABJRU5ErkJggg=="/></a> +<a xlink:href="https://github.com/suzhelan" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="suzhelan"><image x="678" y="80" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAM2UlEQVRogcWaCWxU5RbH78x0SguVKlUKghIVHuBaxQU1UYm7ImJUsIqKYXuyRkEfbqioJCZAwQWRRESlboiKGhpC3MDIAwSqKFILCmJFoaXAtLSznpffyZz7vg6lyBN9J7m503vnfvd/zvmf5TtTzzsMkpOT06FLly63Dhs2bKbneUuysrIqW7VqtcvzvBhHKBTicyX3cnJyZgYCgeJAINDB+39Kr169CoLB4NgNGzas7tSpk3To0EF69Oghnuf5RygU0nM4HJZAICDBYFCysrL0Gn+Hw+FVnueNadu2bcHfBvypp57qnJubO+PKK6+sb9OmjSxbtkxyc3PlqKOOUmCAbNWqla8Af6NAdna2r5CjgPA5Ly+vzvO8kqKiok5/GfChQ4eGt23bNm7cuHERXtqvXz99+c0332wg9HzEEUcoWD5jbbN+69atfQW4jmKhUMhXtm3btpzre/fu/VheXl6rwwp+9uzZ3auqqsp///13GT16tL6wb9++ChTABsqlD6C5ZsoceeSRPlg8ZsoEg0E9oyDX00qv69u37z8OC/jKysoby8vLI9FoVH7++We55ZZbFFx+fr4P1qxvYI02rmJdunSRdu3a6Weo59IpFArpmmkv6HHuuefu9Tzvhj8FvrCwcPDy5cvjX375pWzevFm2bt0qt99+uwLgJWZRs2JOTo6CwZrmBQvec845R0488cT9nsvKytLv4CH3Xvfu3VkrUVRU9M//CXw4HB5BYC5evFhWrVoln3/+udx3331yxx13NMkwZn17sauQ3UOxK664Qs4444wm97Ozs/3nunXrJoWFhfpdy1z2jo0bN445JPCzZs26MRAIJHjBF198oUocf/zxUlBQINddd50PmJfgdqMJ1wwc3+Vs2WnmzJlyyimn+NQyRXLSgDt37gxt1BvmYaPgk08+mRCR/n8I/LJly7ouWLBgj/H20UcflZtuukkX5tppp53WxHInnHCCz2uzuB0ulVasWCHHHnusdOzY0f++l/4e63Xt2lXpade4z/M8O3z4cBGRSCqV6tEi+Pz8/Ow5c+aUv/LKK7rI5Zdfrgu7lMFqLGp/X3DBBX4Q2svxCgDs2aOPPlqWL1+uNOnTp48CY51gOpXimeuvv16efvppveYmA87nn38+CkhjY+NaEQm3pMPEiy66SO6//359EMsbKNKly3NLk8ccc4xWYYDgAaMIloYWUOTaa6+V1157TS655BLp3bu3n20KCws1uPk8cOBAee+99/xnXaNBx927d0t9fT16TGgWeXZ2NlWQiiiDBg3SB3v16qWLGChAAwigtvjZZ5+t8eEqigUBz8H9t99+W9555x255pprNCbI96eeeqrGE9dOPvlkeeONN5SuF198sVLNrQus+9VXX0lDQ4NSKZlMdtxPAdoDs/Cdd96pAO1hC0jLKFZJOZ911ln6Mp7lhccdd5ymS57B2igAeNLwTz/9JD/88IMsXbqUzKKfX331VXnooYd8D3M+88wzmwQx5+eee07i8bhSKZlMTsvEXxAOh+stCG+77Tafh27AWVC6BYyX0la88MILMmnSJLUoXKdoQRmy2Lp16+TXX3/1Aezdu1dMysrK5PTTT1cvXHrppfLwww+rcUggbksCplQqZY/VJRKJ/zaAOTk5Y92gueqqq/RzZmYx7roZ5IknnpBYLKarrl27VqZMmSLFxcUyYMAAVSCRSEhtba0P2MDzTCwWk02bNsncuXNVAerERx99JI8//vh+bQaxgrBe2gujfAWCweBqK/+W2y+88EJ/kZaOESNGSHl5uS5KuwEtcPfLL78sX3/9tQaeWR7BioBIJpP+31VVVfLggw9q0qiurpZnnnmmSRBTpYuKitSL6WzEGisVfCAQ6BgMBlOW0jijMdz9IwpQoF5//XWlyZYtW2Tnzp1SWVmpll2yZIns27evRQUQ4oMMhCGIkzFjxmgsmAfwDqkWDxuNkslkKhaLFXqhUOhWgLvNFV7ggT+iQGlpqdTU1CgdAPL999/LZ599pgo41pJMBQxIIn0PA6xcuVKVwCjWyXKGimSm2bNn63omDQ0NA72srKyZbvdorjvppJP8Rqyl480339TF6urqhHY7bR3lPZRCMdfaAOdvU2BvOibwEtkJgXYkB6s1FDLO7D1cBeLxeAkeWNJch0g6tN6mpWP69OlNgjRtmWatbdfsMDFur1+/3r8GWEuhWN86VHd9EVlMAG+2TYalLDxA+SfbHEyBZ599VlcCKHzHQvYCA98caFdqa2vVA9CIGMKbn376aZP2xCo04ni1EgVq3NRoWlslPJgCFD0DC2VM0mXflwMpUO98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"/></a> +<a xlink:href="https://github.com/jaxMineKa" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="jaxMineKa"><image x="704" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/XuanRikka" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="XuanRikka"><image x="730" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Na-Sizuku" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Na-Sizuku"><image x="756" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/girl-dream" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="girl-dream"><image x="782" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/whiterasbk" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="whiterasbk"><image x="808" y="80" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAYZUlEQVRogcWad3DUd5btNZ4xs/azx54xBmwcMbbBBpNssEkmg4wAEQUCEYREzsnGRCPAgJFkgogCFJBAKKGcAwIhCQWUc0ChW1Indc7dn61upubV1s682tn1zrtVXdV/9K/73Ps999xzf792cPgNYuSWCf2+OjjOdczZcedGXRmb8nXo9Ia5ae6y72LcjeMuLjJOPrtINvaHaQ3vun6YMu3krHPjfpmybHH82n4O/z/jhVG93nAY/eK23o7vF769aABDd41gyKEvmHhjKtPC5zHk4gTG+s9jqNc0HM8vZ9TOiYz/fjLvr/mITQk72FdyjIm35j4ZeWHG1lEnJ73xLwP+u0EvvdNr5J9+dRj1b5rff/0yvxv9Mn3mvovD5N/xqssr/NuKP/LS2lcYfW4yswKWMPPyUqaeXsinniMZ5D6Mz9Z/gfudDWxL28tknxlMOT2VJT7z1Ev3z/Id5z6q//8a8NeH93vxlS/e3P7ikNdUr4z+C38a8xp9J/VhyPxBvDH2VT5e0J/+c/5Er4kO9Hd5lRcmO/AX59cYtXUUjkfm4HLSFcd9s3E75Yrb2aV4XnRj2YnvWLx/PB77J/PdnAHs/WmZJlmUcjTZkPfH3xT8CwNf+rTXZ6+X/mX0O/Qe8xZvjnyD1wa8wFsDX+DP/RxwWjiCrXudCEv4Gb+grdyK+p7S1nuUd9wn/MF5dpxYwWSXUUxwHs44x0Fs3DGXTVtm4jxnAKsWfcL6BR/j/6MLouoEKiQ5hFbdeZrSnfbJbwK+3/T3Fv5h8Muq10b15c3R/Xntk5fp994LjPj4/+Ay5VNO7FxC+YMQqnPvkHT7OPf995Me9hNXTy5H3pqIWvyIK367yM+PoLH+IT5e21k6eRg/LP6WQ/NHc27VeHJ+9iRxhwvBO5eSnHyRvPZUMgUpyuSWuPn/I/CfeQ5b/edpfU29Rv6J3t/0o8/Q13n33d8z44s+HJk9msjdqxCmBJFz8ySZV0/SlHSbS1uWUHzrBPKcAIJ+XEJnQQjXT66nrSITNELklQVc27qewDVLSdywnKyNzuS4O1K+2ZWHe9YScWEvSQ9ukl4dTVpDrDmzLmbDfwv8gPWfrB+waiD9539ArxG9ePXTP/D+gBdx/vIdLq2YRca6xeRsdkWccB2ERTQk3ibd7yTJp36kKyGAhtsnMBXc5vx2RwrjztHwNAm0QlDLoLqcoKWLiVnkRNnaBTyZP4lql7k83ehGccBp8h+GEJV5jYdNiaTVRJMtSN76T4F/a3XvhZ9s+cT8wZoPGeQ2mFeGvsD7Hziw0XE499YvIsd9AWXL51C2yYXcX3eCtgY07ZSnRXJ+lycl9y7SkXIJXWkIBVFHSAw7RG1dKiABhRAkQsjNJNRpKk+XzaZq3lSkq5ZTtGwRNTe9QVFD2P1zZFXFkN+aSnprojlcEOf8XwL/8Zb3Br61urfizZVv0nvxm/T/rg/9P/s9C8a8g/9yR3JWzqN6xTza3Jx4smIqSUdWgLwEzCJkTRUkBvgR/PMu6uN9keZdQV13m6iA7VTVJdItqyU9PgxlZRE0V9J6+hDFLo5Uz51Cy5w5tG/cQO2lM1gFT5FKK7hy5xTp5VFktiYR1h6jChHEDfp/gh+xf2ivtz36lr636X0+3PYJgzwHM9b1cyZ/3Zcj00aSuWI+T51n0rRwBt3uThSvnEL8rnnQmAlGKZjUSOoqOLfPk/ros4gyvUEcQ2veRUJu7Mei7yAlPIBY39NQXwrlj8i20WeJI7VOs6lb444g6CqGxiKwdJL7NJ67KVfJaknmflcSoR1xJVFNcS/+wwQGbf7kh9eW/pm+7u8ycMsQPnYdyIylI1k1cxjeU78mxXE6pbOn0ew8hXa3adR4zCR9y2wUGSEgbAG9EbR67p39icrgY3TdPwJF50EYS2rQUerz49E1VvDLymVIg69AQxEKnwOkO02kcsECchctQRQWDIIa1JI6O+WCI8+TXhNPiiyb+5IU7tVF7vm74KccmNF/1I4x6iE7vmLA2s/5yO0zBs0ZyNARfTi00olgt8XcmTye7OkTqJo/heoF46hZOZXcNTOR374Iza2gsYDWQl18BA9PbaD1+iZU93ZD6U1QVnJtx2poayJk0zpyt3nA3cvQ8oR7878lc64TWcvdaA0Ngh4BaDqxWsRk5IRzP/8ucR1JxMvSud8Sp0qqi3vrPyXwxcrRvw7xGMPXu6YwwuMbhiwYyry1M1k0bzzJ13ypvnGJe67zCZkwkqyZYyh3HkvD8ikUrZyO0t8bOkSgBjRgbqgk7oArdb+6YY7Y+TyBzgKeXD1DZ/x9sr0Ok+a5lMYTOyEvgka/nwh3mkXiipX0pCSB8BkYZBh1XXR2VxKceIXQqjA7jVI708luT/P+D+C/XDr+jQ/nDtMMXDiCt2d8zDeuE/jsm4Fs2Lic1MjbNOZmoCzPo+r2Je4un82dScMocxpHq+sMSlbOoMXnELonxUjrOsAA6KQknnan/NwydOFboT4YUew5ENXy8LIPZTfOE79lCfmH15LtvQ0q0ghb4kzcWg8oe4q2qRZLjxBQATJuhJ8jou4+Ue0JJLQn8FCYqc6sTfi/BrBT372tw9JFo+YZd9Pu0C5pIDnmDsr2RpAIKE2PQ1FXDNImnp47RsCssTyY/S3VLrMoXjaFwm0rKPU7R+GdMFD0gF7Eo8s7KPRZSsvVlfDIGwqCofkxeRe9kCeFcs/9O9J2LqLk/A4ojCZszUKyDv+ItrQYbXsLKGRgUIFVwa07vuQIs4lvTyC8OozUZ0lkN6du/lsCGA2FFqUMND08jI8EtRRJVTHqxnLaC7NoyIpDXvoQpK0gE5C5dzsXxo7mwZK5VC2fQZXbdOr3eFJ+dBfxu9zpjr4OZXHc8hhP/ilX1LHH0Cd5Q5Y/PAhBHHiK4PnjyFzvRPkeZ+p+ckMS5ossO4auihKaKirBCMhVoFVQWZZJWNZ1cjrTiGqMIqEtieRnGQV28HfP+72FWm9FpcXU1ELGTX9orgNtD50FWSgrC6hNi6QsOhjUXdDagDIhliDX5QTNnEbZkpl0uDlS7TKN6rXOlG1eTOWP7nRc3E/p6Y1kHVjKM//vEQUdhORLkBnA4y0LCJz8OY9cp9C4ZhLNO+ZQ7bsb6eMEuqrLaWt8hlGmB40ZTHpKi1OJzw3mkSCZ2KZo4tuTSOvIsY52m9jX4fZFP1d0BtAZ0dbXURZ7n7rkOHsC+poSBHnptD9OJv2aDwjqQSmBHglx+/biP2sGyVPH0rzUieq5kyie/hVFjl/xxPkb6rYupOXIOpLWzab4p/XU+e5DFeIDkVdIXTSR2AmDiR3Rn9Jpn1OxeDzp6xciSYtEUVeDvFOCQqQAC4Ce9EeRJD0NJ6M9nrjm+yS1JfFQmMs3ruNcHK74eJ9DrwOtDl1LE+KiJ0R5n6I2IQY6WzE3lFMQHkBxZBDigixoqQGlFGthPpHrPQmfNZXECV/xeNJXlEweTt7I9yib+jkCj7lUrXeGsMvcXTWXmK2rabx4kie73QmfMoyieePIH/cpFeMHUzVnAhlu8+mMCIV2AUaFFpVCixWbJqi5m3yTpOpIkpqjiW+JIbk1gYdt2Xy7YryvwznvMykmlRxMRpRN9dSlpZB06RxZ/lcw11UgK36EIC+D8sRwon49iaWxAhRiUPdAZwelx49zb9Z0Ir/8nKJJw6ibOIiaCR/T4DyO1i2u1B7bC40V6HLSidi9BcEVH4i6SfbUYZRMGkK74wQ6XJyp2LoRQfBt6FGCxoTFalNkMyrUXI+/TFJjDEmtMSS3xZLyLI7EyigcPSYnOvhc8G4S28yVRY+6rZkHIUH0FBfCs0aMNWVYm6ppe5RKVWoM0Ze9ufvrSbLvBND2OIeSyLtQWoIi8h6Fm9YQ981nlE0dRvW0oWSN/ZSnHoso9vqRlqgw0KjsIoGgAfJSiZv1JanjPqNixgRK5zpRumMnHbdDQKkDvRmzXUQNKFFyOf4SyU2xpAkS7K/klvvcyrrEwl2ODQ4/XzgtbetutXPNqhBTGBuFpPgJaBTQ1UFrTgbS8gJKU2LIigympSyf7oZy2iuLUQuawaAEXQ/kZ5C6ZiGxk0eQO2c8kd8OJ3jOJK56rCD11hWwaMGihq4mqMkn7+g2ohdMJWbaBCKnTyF100Z6ktNArgaj1U4fLUaEBiEXIn8luvwemYJEUjviSWiJ5mTkUdyOu4gdDvgcMzSKmlBrxaBX8KzwMRE+Z+nOywWRADqakVQUUZWTRn5aLEZFF0aVGLNOAWbbIesxa0WgldAVEUTw/BmEzJ7C7fmO+MydzuFl80kMC8CKHoNtTNuGk0mKuTKfpEO7CHBdwLWFc7i3ewfU1oJSAyYzVqsVnVVHXWc13oEnuZNzi4zWBDuFYlqi2B2yi9V+a/QOPiF+hqvhN9BZFMgl7VjFAh7euc2NwwcIOelFXUYKSIWIG6uoLHyEUSe3n5beoMKMESUqTGjBrILONigpJfPYcS6vWk3gnp20PM5CLxdgRo0ahT1h2/U2eaRHBN1N0FENonbQq8FgU0QdWCxYMZD9OJn76aFEZgeR155GQksMYc33cPplEe53t+gdjl07I/XYvwGZQWw/NI2wBVN7C1UpCXYaaZpr7ZKqEXUgtnkUjFgxIdcoMGJEZ6+sFqxGMJhAZYR2CXTJQa19fopmBaDAyvOktUaDrchYrWC2KtAbOu2fsVEYo9EuKIYeKVj1+PgcIyH9HlHpQSSWRnKv4g6B9SFM+NmJjWkHxA7Hb55tXP29J95Xf7H/gJ2nJjVGwTN66quQNVUjaamjq7UBlU0+sWDEhFqvs7/XGxRolGKsahXorbYaPDd1NhsjlIL6rz2il2KVCkCrwUZwsxV09rSMiLF9r5qGyiIqHmSBQQ9aFRqJgHO+Xly+dpqIxJsEpV4joOAWe2MOM/nCYtZmHW5wcD+yOeXo5RPsPLKN6LgQDMou0MrsSdgqj1mLUSXFqFMCJntzmcxWDEZbCQGzrWI2SpjQdYjoKK6i5VExqvI6aGyl4FYAcWdOknrxHJ0FeaDR2b4GiUhn74g2swI5enqUnSRFhHLl6GHWzXVi1jdf4n38APW1RezY40lkYiA3E65yKy+ICQe+wyVyB0tT9iU6eBzecm77yT3s9drF4eP7KCnKtp+CUd6JVS0Gq40eur+Ct9iP3WqbkDbweguZ4dGc2L4Tt5mOfPvZYGaP/IIxb/fh23f6MblfH757920WfvQRs999n3G9+3J6yw607Z32JERiKRKTGqGyi8s+p5k48COG/+lV9ixZRNSNS/zs9QMKTSc/eO0iKi2M22mB+GVcY/jmCbjF7MMt45Cvg8eRLcs8DmzEdYMLG3e6s2KFMwH+56grzwerxt60Wp0Cg0mPwWREqzFiF2nbSw/usxezeuZssu+GUpZ2nzj/M8z78n2cPu/HiJcc+PKPLzDAwYE57w3k4ubdaKrqQSxF2dEKFhsNTRi1KjbOW8CIl1/l1Ao3cm7doDA1llsB54lJj+Bm9A3CUu8SmBLIjiv7mHFkEXNurmPdo5NLHNYeXN93w5HNVvcdq4hOuktNXREyia1Z1cjlNk+ux4oRs636NmvyfL4/57jcQua9RDYtdqWlMAeDoJj2pxEEnllDTeoVTq2bw/CXHRj8uxc4tXojSRdugFILYiHyZ6XoxQ0Ia2uwdIgI/eEYzv0+ZNOor8n0u4CgpoiktAgO+h4kLCeSkPS7+CcH4rhjPkt917M4aJvVM8Orr92Ruq2Y9WTPfk/cPBaQW5BKS2sFHU0VdvqYtEoMRg0qs01v/lp8rRHE2r8mYWbXytWoWirB3I68KYHoK1tozvVn7LsODHvdgZmfvE+cnx9J126CVIpV3IFZ0oRR0oJZIoHWbh54X8XHeTnxB36iOiqC0sepNIuq8bp6nOtJAYQ/iiIoO5SvPSaz/OJm9mV55/1tH7jouXCr5+LxHDm2nhO+3/MgNx55Sy0dRUXo2m0yaEGNhXaLEolFhVolg1YBCHugrZP8uFhEFYVgk0NRCf4n1qJuTGT38jEc2/gdhzxnE+T9I8UpUSDvxiDqxCgRo+juRNzZgUksQV9QQXdkEq0RsUie5GPSd6NHQWZpMkcuHeRBfQZHAo8yc/9CPO/sZ1O816a/JXB76aw3jq2erj60bxlnfHZz9MhW0m8HgEINcttkNKHERKulBylqdDopNDZBbaPdPSLqAo0UbLNE1UxS0M90lEYjrUskIegn4oKPkZvgj6y1FPQ9YNChk8hRSRWI5RLQaUCsgpZuEPWATo3J0kN9dyX+4Re5GXuZxKcxuJ/xZPrRRWyO81KvjTzwH58p3Nm7wvfSwTX8fGANjWVZGJproEPw3B2aDCjMajqMUiTmHlTyTiwN9VBTh7KyEk1THfK6MsS1TxBUZBEXeJpLJzZSmRvK0we3KX8cQWVBHGZ5G8aebmz2XS7oRiGVkVeUT2jgTa7sPYA8twjkCnTCFvtMalM3c+jsXuKeRHGvIIxxm6ey1H8r6+IOn/1PdyXidizp771qulpTlYm2IR86m0CnAnG3fSLrzBp6TD2IlAK6OhrQNdRCSxMI2+kozkNus9kqARZpE9ruaqoLE2hveISoowipsAJZVy1YlWBUg8WEWaXFajTRKmxj++YN+Oz9AcRyrN1dVJU8pqqphGvhV/j50hGSSuO4kn2Dzz2+YXvaGeWysD1///HUk2Obvo8/tIHCAF+URQ/Q1pVh7e5A1dWGSt6NRitD2SNEJmhG3VKPvqXebjWeFT1E0VJlb0p1Vz1mjQDowWIW2brcTgfbiLbaZ4oJs1YLRjNmvQG9xYBE2oWuuwtDd7fdPgi6mth2cDPXI64SnRlGwtN4dgYcZNLxxWxIP7Xb4R9FxZ6VL8oCvUu8Zo3m3uGdGJvLaSjIIj8zwW7kFF3tWGwrpVKCWSpE3d6IUdgEym7M4lZ62urA1ING1WkHrDbK0KNDY1ZjxoRSbfNEFtRyhd036VRq+xywb/DG536qs6eDyLQoMkoyeVj9kOSCRMJyI5h+cDGuod8Xzw7Z/o9vLdqiZs+agZWnflAknfqBZH8f7lw9S+Blb/JT4jF0toOq5/k2ppdjkHei6bDtyV3oRa2oRM/3Chsgkw2wSYvKYrZ7Htvo0JvtS+7zWWJ7a7HQI+u2XyMUNmMwq8gozubgBS8yyh8QnBjML/6nORV6lq92zlYtCt33qcN/Jdq9D873c59nvnViD78e38ONC6dpLHj4XC1UCoxiIUadDLNZDnoZZlk7GOT2yapRy9EbdajMJjvwHuPzBJRGi73WapvftyWg02PVqu2UMRvkWE1KAu/cYP3+zZy86cOeX/bjumUF892d8Ti2yTzp4NK5Dv9MRB/cuO74ZhfOeu3Cz/sY2eF30dqkU/fcyxuMSvsOYVR1P3ewFj1mnQqjUY/WaEKpM9mdtVRrsldfqbHZcNvhWNFIekCrRSfporWmhNi7Nzm0bwsuy+Yycd63jJk7nuHTR/PByIFMWzDVOtN9nofDfye2uUxdfdZrjyks8BLVOQ9Q1tZhbhdi7ZFgMGvs24BtK9PJReht1LK7PFCp9XbAf7NMBisapQGrwYLeLssWMBqIC7zB1uXzWb/YkYlDP2L4oHd5Z+CbvPT2y/Qf+j6vD+htnjJ3ynqH/0k8So92FrZUKVEqQSTBLOy2e3pbU+rstTXxrLGO2soKRF3dqBRq9FoDRr0FlUyNQqJELpJhVRnswPVd3egEAlAqEFeX4T5zPPNGfcr8UYMZ8sYrvNP7Jd7+oDcOLzso/vxhn3+ONv8oyooffdxcXl7SXPIUUX0TFpUSnVlPp1yM3mhAJpPRJezkQVY2l369SGxYhH1Q2UjfWdsAKh3IlaC0rYx6NE0NtBcWgKAZ4eMUHl73xeOroXz96h8Z/PpL9HutV/GHg98b6PBbRvez1j/0CITbLUqt8vm+CmqjHqlSQ49Ki05rorqsiqCr/oRdu0FpeibVGdmUJiZBl80jdSEqeoLkaSGdhXk0ZqejqChEXpCKMCEUbUI0fosXamb273d04bgxvRz+t8KgUr+lkMp8JBKJWiJX2J5n8KxTikhsuzlmawAdyuZn1KVnknzJj1hfbx7dvA71VdDdjqwwl87HD2jOSqU0KoTs88dIPLBZHb3S1TtowcJ/3R9AdDrDG2YLW9QW8mU6rEqNGZPWjFWmwNzRAc9a7E9jmu6Hc2b5YryWOOO3aS039mwj+7ofpZF3rEWhN/LaYgM331rh9Jd/GfC/FwoDfTR6XKRCqa9W2J2ERFxLp1BKa4Mh/Me9hksebtKrG9bU+m/1THp09YKvpfqpC8/q+/wWP/7vzWVF6qeWIMsAAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/wisokey" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="wisokey"><image x="834" y="80" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/WShihan" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="WShihan"><image x="2" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/xh286286" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="xh286286"><image x="28" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/AceXiamo" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="AceXiamo"><image x="54" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/xjbeta" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="xjbeta"><image x="80" y="106" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAPwklEQVRogcVZCZQU5Z1vn7p4wzDMwTBXT8/03XX2PX1XdXVVdXVXV3X39MwwXKLICihuojFeSfCpm404HrgEFa8QPILnE4zvZdXElyga0TWeT6NvdbNvMcKugK5Ewm/fVwN4gYs4ZL/3fq+ra6Zf/X7f//7KZpuEZbJSu8lKoyYrXWey0mMGK71pstJ2k5X+sg/b9917zPofRhohv7H9fy6DlZoNVjrHZKXnTFbCEYHLPlvhw8v0ULj5b0eckToNVrrWYKWPjCMlvg9VNos6F0Odi+6qsrlxgynNOnrEWel4g5XONVhpJyG+H99KACNimM5ihMphmJJQp4ofVanKDw26NmWyybsMVnrx88QnQ0CdUjDi0zHmrWDUV8JwQMEQEUJLL1QZ2TlZ5Ktf3vVJswBdxIi3hlHPEEb8JcsKw3QaQ8wg6mxyR5XNGt+W/HyDlT49FPlvK8BkFNQD5gQoBXUmtz8mUOWjqHLJPTU2v/hIyZ/1dcQnQ4DBytBZBWVOgc5J0PkcDD4Nk0uiyqZRZXOosQViqWVH4jZ7JkOAweRRocUvgNwjf6sEBUh8DEo8CS0uQeXzUJkiTL6KIW4INaqKBm2i6ivtMX1q5XDJ9xus9OHhkD9cAQcD+VuZz0EdTEFJpqHEJCi8CoXSUQqY0H0GKu4iGn4Zc4Mqxnhhp+mPuf8v8n93qGzzbQUc7F6JESGHJeSDE+TLQQM13kSVKlnZaDabRiPAouZzYZhxY26M2TIWCx3/dQIu/CbkD1eAlXG4wgHsv6/TEnS2iBKtwGRkDHMFDNNJ1H00xmgPFkXdWJpy4VIjjCvmCDi/ksRYnPnuocjPMlhp12QLOJAyvySAoEYVMEaXMS8gYz4Vx/yAFwsCbVgcPBUXitNxVa0Ld1+QxVOrFmHjPy3GBZVBFL0DOyvM4MyDCbj2m5L/JgI+70pERI2XMZvNY05fEItdAZxH2/H9WAuuLjfj3qUOPHVlGC+skvHePWfjgYs1fE+mMMp5rTRb4fMrD9aYfXQ0BOzfcZJ9dEqwRJB7jXARC0Np/ANlx0+SM3FLpRUPntGKF64awLb1Kfz3vSreXatj03czWEq1IDnleFTsLOYlTGhccVeayn7WAJKu8kjIG5xowWRzVhEaokXSBqDKyDCZolVpG7SKRkBAPRCFSTGosT7MDvmxMMxgecSBdcP9ePxsO1641IW3xxnsvDuHvzxcwWvXprB+gRPKCTaMdHfgDDqLMVqD7letVFuMaksOCKiH5eeGIgpkzyBqoQJGB0souOOoBiXre9GfgsnnrXsjcQ0VVoDO5GCG8zDiIspMHA13FPP8aYwxBdKUwQhU0aCG0XAoWBrSMC/Qj9n0KRjlbFg5tx3rT3fgwdPb8dvvTMMbV3Zi29o4PtlQwwfrRvHkpRIuTsxC7gQbSu3dMO1hNLwKGrSBKlOBTikoMdJmi3yFFWZWg9JespMlKmMRJijTWQzHihb52Yky5qYNaIEkhiIFCwaXQyUkQg3noAVzGGVELGALmM2IML056F4Fo5SOs/kqZvd48PdMM8ZH27Hu3Km4c6ENT507FR+M0/hgtRdbb6bw4V0y/uPWGu5exGFO77EQTpmCqt0PpSuMUr8IM6CjxpowmBJ0uoAKk99r8vk2m06LoyZXgObPgnySXSfk62HJQplOQ/bEUGGzqAYF5BwcSlQSjWgBgjsGLV6BGNQh0zp0toQ6L6DORFD3c2h4aYx5GFwiRHHP8kFsWNqCzStOwcs/moL/uZHBx6sGgQeGsHPDKJ65Io0f5U6FPsOG/DQb1I4OSJ1eaM40Sl4ZBqOjwlZQZlSy+xNtR0ho2EqB3HX1kIoyJaDKy5arEEsQ8oQ4EUDI1kIiFgg6huOS5TLVUBpj2QqKIQ1yyIAcbEDmFJQpGg3GjrNifTgv68XKeTrWLJbxyx/EsfmKXmxd3YYdq1qxd3UUu1apeG/NGG5bQGGB0wa12YZi+xSoXe1Qe71QXFGUKQklRkOJL5PgRZFsNptDOZiFEcmM24q+3GPDUR21oELMYgUl8XHiIkX/IOZldGy45iZsXH0HHrrhZvxi5Y1Ypjeg+FlUgwnIzrBltWrShBZKQve14HT+RFxpzMLty6K4xPTi2sUh3HepD2/dwuCj2+3AvUHsuVnFttVn4IJIO4zuU5E89RiIbdNR6ndD7achOoIQ3SmUeA1aULM2Sg3JUHkBRT6DUjgFPZraZCsFxD/WQxpGYuUJN+LzMHkBZTqF8xsLsevVd/Hwqlux6oLLsO6qq/HsfQ/j7V//Fq/88ldo8DwWR3gs5AKo034MsT04L9uMG0Y6sGGZEw9eFMTtF4q44zIJP7/Ej9fuSGPnPQl8/DMBNylNUI61IXnCcZC7nCj3U0jPdCLR4UPRl0GZkyH4sihFytDCRYu8EhSgBrPQQmlLQCWSfNNW5dVtml/AaFy3flgPy9CZDCpsBk/eeT8eumEtMn1eRGf1gm/tgO+0aViil4FtH+D1++/EunkZrCn343KhDT/WWvDAkn5suSqCF3+SxOOXJ3FRtRNXLuJx/3gZz981F+vP9+DMgA3FGTbMo0ifk8RgG4tYGwPNL6IYyCPRG0HGncKIMAwtokINSZ+RD2ahh3KoBDOohFJ/tg1H9d2CI47haMkSMJF5ElbA/vWdrVgglBBq70Ks045g20zk3V7QzdPx65/fCfzhSTx9kYg3LgvhtRUsXl5B4Y1/pPHejTlsvX02/m3dEjyzdjkeW7Mca1fU0Ug3Ie86BvGO4yHaXQhNdyPWHkG2J4e8U4LkklDwSlDZAhROQp7KQAvlLbdRuQxKXNYKXuIhVY7EbO4TYoHdxAKkMOm0uC/PZyEOBIF3P8BZShWJnn4Mdjss8nxrO6Kds7D5vnux+/lH8OLlSbx8wQxsv7oLu9f48PHaNHbcOYJXr1+I565djvE5IhYmnUj0nQy6+zQwfXZwfTQiPTGkenPIOfIQB/KQPTI0SkWJlVHmJWhB0Wq3yW7rfBYGl7V4GYyAKmPNzWjQhU9sJqdsq/KqJYDEAHGhEpVCqHUAD1y3Fs9u2ITheA7xrj4Eps2AGqDx6M03Ycerr+CdjWtxy3AT1gg23Fey4enFNvxmaQt+WpqBub0nI3PicZjt7IbU0QS+dRqYXgcYdxqMU8agowBxgCBv7bzmk1CiC9ZkRgYdQlon01kwA5Mj01kWJpNFjcpjiJKtA4ARSv2zrUzl3xqJVQ4IIFlI9Q0icFoXhqIiNq7+GbB1J1565Fd4//mXsP1fX8ULD2/CZQvOhP9EG7SZNlw8aMMDC2zYfOFU3FpvwliXDcqMDtT7QihMbYfQNAPpWT1IuyKI+coIDWgQejMoDWSguXMgHkD6JJL9iHuYxE24idGyxqes8bLOZFGnSEtSsMgPB4oYobQ3bZpfsNIoSaEEpIjlnVGE21ygpnYj2R1ANZS1XGmxalrWSPW64TzxNBQ8dtxwbhEPrhCx8ft23D7vZCxhj0F+6rGQWhnkmiMwu1hUuj0oOvzIu+NIODUM9qnQ7EnU3UmYfsFq9ExW3O/XqPKZfTNxGkNcZoI8k0Ntn4AhSsFQoIgGpW2ylSnhOlKBif+TT8WbQKzDj2wfh2DLACLtbkTaXaCn9SDU5gDd1IW03YczpAr+9Mzvsf2lp/HpW0/gT49fhZ8uC6PSdwLUzh7UnCpiJwVR6o1A6fFBtLsh9vMQBrJQnBKGPBnMpQXULfKkayVdah41TrBABnriNgeuSYtC52HSZMgnA5CCKquO22pBZaQUyFkuRD7FgQiYJgdyDh4ZOwuhPwjPSR1WXCS6/MjYGVwyZyl2vfLvuHXFNTjHnIv1K3+M91/ahF9csxzpmach0TQLtQEFSmceBXscYj+LvDsA1cdbO14PyBgJiBimxIlTB1b5ysBj3f/SALTfS3ROtlDhlSHbSFxrU33JvSR4JVfMQqTdi3Qvh4ydR7DFZXWprhM6ILkimJ3QsPed/8Ky8lww0wbgPakPOVcUT9x/Fzbe8c8Y4lkYDgZmTwqFmUmI7jRyTAJKOIpKKI4GM3GMaNAqygEVJqvBYIpfQZXVYHKqhf2ES1zeAslQWlDcq4XybVZHqnrTz5JKnLWHre5T6A8j1cMi0UVjsJOyrJB3hhGd6cEfH9+CH8xfbl3HO2jkepIYmGLH3avW4sFbboXm4yC0e6C0h6xgSzsHkWVTUMIJlIJxGIFBmKTSMoRYxWoACeEKrR4A+U6EEVS+JKC4T0AxKD59YB6o0IVlJZ8A2ZlCvj8GoS8CoS9kIWfnkOtjLf8tuILA1o+R6vZAp+OId3ggOKJgprmw+f4ncNvl10N2RTHY7kc1IELzZK20SPK6ldNJdmHFLxxqGaz8tTA55cAAVWbzFqxDME46+7OJjJabSz5xl+JKQxqIQ3REITrCEw2VIwidTkFy8hZ2/uFtnCmVEWzpguCgwE7vx4LsEPCff52Iof4YziqMIdMb+uYTHnuQkZUrHLjeHwP7Dh+++E6h7BfHVXcGsithiZAGopAGwkh1UVC9MSieMHJ9NH63/iEL87MKwq12a3p75u5/wdpLr8dQuGg9YHAWg7GEcTQFXP2VU4lyID9L8+Z2qZ4UFHcSsituocaLyNoZKB7iKl0w2BR+v+FRbN/yBt5/9jXsfedDPHHbI9bOk5mCWIE8lIgh34+CgB3GoV5Plf3i90r+LDRfBkVv0sJIVAHf3AfBwUF2h+CaMgOCg8EiqYpzynOsObnX1oK5qeqBWkLIF1yJLzx8EgV856DkrWCmpON1SthSDuRQDmQsDIVk5PtD4Jr6EG13WQFNLBE4tQNsUy+S3RPuQjpZxZMCme6IENKeHwULPF9h8oc+WrQCmsn3V2jxw4mT5Bxi7T7r2KQcSFlZJ91DIdNLI9Hpg+KOWXViXrpmkSWpmLgQuSYpeX6mPpkCdlaYvMt2OMtkJcNg8nvIIdRwREW4xY1kJ41sL4vQjAHI7gjiM70WyPxMmkBCmljgzPwo8gNxSxRxo0kSsMdgpfJhkf+cJRaRDnEirYaRsweR7eWR6eEsIaRGkPv7M8OhMAkC9hqsdIbtSJZOCfNlV+LTz4sgINcFZ8zKUkdZwB6TK5xl+zZL9aQqsiuxg1ToiQIXtWpF0ZsGCfajKODDb+w2h1qKOzkgDcS3EBHEGqRWEPeaaAmOCp4nb4psk7lkZ+q4Qn/yXMWV3qF5czDoAmrcxCg6ifjIYKUfkjdFtqO1NG9uph7IX2Myyi4igDRbJFMcCodJfJfBSisPWWGPxqqyanONU5eanPIMyRRHIIBkl6cNRlpisNL0vxnxgy2TK7SabKFhcoVxkys8anKF102usM3kCrsNVtptMNI2g5VeN1jpUYOVxg1Wahis1DoZD/9fLQw2AIxiGLUAAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/xrz-cloud" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="xrz-cloud"><image x="106" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/xsinluei" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="xsinluei"><image x="132" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/ywwzwb" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="ywwzwb"><image x="158" y="106" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE6UlEQVRogdVaW28bRRjNAy3vVGqJymOg/BrUqhKofeoDoggaEDROnDaCIvECovQaakQseOA3FEUIxFuhFQFUx26bpnVImsTxbddeW/ElPtXZzLrj8V6c9dqxLX3yeG9zzsw35/u+WY+MBPAB8CqA0wCuAZgHsAQgZxhGlca2ODYvrjnFe0b28wPgEICPANzTNA1+DMBdAON8Vj+BvwbgaqVSKfkFrlq1WjUAXAFwtJfADwD4uFarFYMCrinGQQFwCcDLQYM/BuDfXgHX2l3rHwBvBAX+ZC9HXXOwer1eAHCiW/BnisVird/gNWGFQqEO4H2/4M/uF3Ct3aXG9wr+JNnvN3CtdSaOdwp+bGdnR5cfkM/nm9/9ME3q0zKuQwBveoE/6KQ21gMLem9NswEvudIC5dyNQNgNPL/XU1k82+yd5XJ5LxITTuCPMiI6EeDoEPxXPz/EZz/E8UU0gUtB21wCybUMigVnAsKVRu0IXHVaRBYBjhDBf3o9htDNGCYCspDVvhHD09UMjKIzATELl1Xwh9xyG5kAR54dhr9bxFTANjkrCLjMgJQ7vUgAmVW6yZhMgFPN0eoF+MnZzmZAzMKHMoF7Q0jgLwv8qKZpDTedz+Xz0D0IWAA6BetGoFjQTDVyixPEDOAICZyWZUu30WYeM4o6NlI5cw2oBGRAFhA3syMxKc6tPMugbOjQHWKOjBXAOyRwzU7n1yXj782tHB6vpE2pC/WQQGJ5C6l0rg2DZXKcYBFEAvP8wVEm+K8lnVeN4L1c4L+HKayuZ/FkNWO6g2Uc2fjyFj6fi7cNwJR0P8879f3lTw+w/H+6GScA3CaBZVXnP7l+31HnvUaQ4LfLutkJFyONbboFR9bLBScc+j1/I4bwrUUsJdPmM7kuuVFAAtlmpJV1/pa/RfjEZhGybYrAhj8RCIvzF7+PY2lll4CYgfRIqVSqqAT8yKSbDAYhw6HZGC5EXswAn1kul7eHnwBsXGjCI1XYq443XaiLODJpulArAdOFADyWCXC1c8HwhpBie9JxJY6UiropxZ3EkZBNv7xnOmK/iOdlApQqLmAuGE6Zal4zELd0fKM1z3eLI1PS/XZ9cuQJngrJZ0gzcLslkHGqqbNkydVufgvj8fuPUh3ruJrrdxpHFuKbphs+kvq2jOAz2fZAdkoOz7J+t+h4qTMdd6sTQj7jiCGZkkq8TQJH1GQupyZzYhGu+dTxbuNIXsHUksyJjPTuEKbTd+R6YHwICXzQUlKyTBuWeqCqlpSCxJVhqQcAfGO7rVKpVo1BrwdqNXPX2v71FICpQa8HAJy3BS8IHJj7AwuDWg/M/oq/XbcWBYmxi9GkPmj1wEz0KXfkjrmCl0icmI4k6kHJYLcyHI4kuL3+VkfgJRLvDQiBBoB39wReInFmOvKg1u3WoN+tyfDuyJ/1BV4icXwmmiyoObqar5vtm94zQJVxqjdCks1EV/Q9u40Lidcjv2HBLlc383Wpbbc93lJv/JgQ9Yb9sy5EFhH53VSbsUDASyRe4ovujex2Qc3TZctK+bpMwKveWEqmsbZVsl50HwwUvEJkFMC3aNQMr3xdTQid6g00asxtLvf1DyDizx7nAPyZ17SG20s6+Vgzt9/N5+9wmxzAK30D7kDmMDdaxR82fgHAmJ/llg2NbXGM53gNrz0cROfPAcJcrv4gXHE+AAAAAElFTkSuQmCC"/></a> +<a xlink:href="https://github.com/zhadongmin" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="zhadongmin"><image x="184" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/AnzhiZhang" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="AnzhiZhang"><image x="210" y="106" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEWElEQVRogdWa348TVRTH90HxXRJwg48o/jUGQqKBJx+MGBV90EQfTQx0BaFdSYx/iWZdyUo0QSEiT2pEVpa2dNndzkxn2i7bdvdjvvODDmXazuzeKdsmJ510u/d8v/ee+73nnNuZGQMv4CXgNDAPLAB3AKvZbHZkeg4/Wwi/c0r/M/MsX8BB4EPgpm3b7MaAG8BZjTVJ4C8DpW6n02o4Dias1+02gSJwJE/gzwMfeZsdr7Zuk4c5rUct4HPgBdPgjwG3Vzdsvv2lSnGpwvxPVUpGreJb+aG2C38Ar5oCf7Lb7Xpuw6G2bnF5qcIXC2XOL5Y594N5W1m18BoOvV7PBU7sFfxbnud1teECArY/WwL/5Y8V5nKwlZCA79N1e8C7uwV/xnEcZH0Clr/MImAaeGGx7FucQORfSpUV/Emx3y8E3GAljqcFf3R7e7sR12vLtn25e+ATCEIoj/AphAQ0WfIZx6B9CLw2DvwBqY0GiJvAN12Hhxu2r0DabNGMmbTzi2VfhVpu4HMQB3BLcj6KwGeSSoVKoM16t/yZF/j/ahZfX6v6G/jiVfN24WqFf6p11uq27zPy38fin96fDAN/xG1vNaXzksq4NutZMy/wt+9t+Mt890Gd5Zo5u7dq8Ve5zjc/D/d/5VqVdW9LoTSbRKAkhsWYzsdNYaOZF/hNL1hSz6C1XMef+XH+RRa4NAj+oHIbEZgfovOKUS2zZj5pk+3FrFBxFDbj/C/XLHZ6fu7UTwCVVWrTRAeV2M4NHaD+lMzt1exQ5bL4B96PE7g5hQR+i8DPOo6zk3UAkyFkPyYQHJRp/AszcFgETmeZAamFNpxmrmHQvEZwzmSJAOBNEZjPQkBS19dpU7WA9ficiQ7KlASKIrCQloDei09otMlaoOqPHfeVgsB3InB3HIFowOi4z6MOOBda3FcKAndEoJ5lBSZhhfQrsD7TarW20hB41lZIINButx9NPwGmPYSAf7Ns4knYXMZNnElGlbNfzNHmdiGjqQ8ygc+7HiguJdfcow6yU1lO4rzrgVK2VOINETicJZnLux4oZU3mwoz0xhSm09fj9cDZKSTw3hMlpVrc+6MeqI71/1RJGZIoBgT6MTioy5OuBwoJ/sOi/qvEtkqjvdVMIhBloRcmXA8UEvyveR136PUU8Kk6Y5LKQdPnajqpb5PP/UDVH/fPcp3KWjKG+8HdwceJ4GO3MLcGNdqN6XTe9wOVteHnDPD7yNZiluZunvcD7vDm7rGR4GMkTuzD9vrrqcDHSLyzTwjsAG9nAp/miimP8CkMEAhn/syuwMdIHNeFW7QCed8PrIQEtA8zh80IEq9InbQCV3K+H7gfSKXU5qgR8DESz+mie6PZcYMc3jJaDyzX6tSczeii+4BR8ANEZoHLykdM1QI7QW5zaaI/AAl/7PEB8KuUImvyFqrLdbXJgRcnBnwImUNqtIY/2Pge+FvdDrVsZHoOP9Pf9B1995AJ5/8DLYRO6AO++j4AAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/zine0" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="zine0"><image x="236" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/zouzanyan" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="zouzanyan"><image x="262" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/zzjjbb" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="zzjjbb"><image x="288" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/amtoaer" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="amtoaer"><image x="314" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Silence-dream" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Silence-dream"><image x="340" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/vooidzero" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="vooidzero"><image x="366" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/BlameTwo" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="BlameTwo"><image x="392" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/HDTianRu" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="HDTianRu"><image x="418" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/holazzer" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="holazzer"><image x="444" y="106" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEpUlEQVRogdVaTY/bVBSdBS17KrWMynKg/BrUqhKoXXWBKCodWIAES34AM0kmbpNMEfRX0GYB20IrBqRuqPLdViTpJM7zcxKROJODrp+TOok/nu03mU6kq+c4tnPO+zj33JdsbCh4AXgXwHUAGQBFACUAer/fH1PQsXOu6Fxzje7ZOMkXgHMAvgTwhDGGOAHgMYBtetY6gb8HID0ajQZxgS/HeDzuA0gBuHicwM8A+MqyLFMVcLYU1CkAvgfwtmrwlwD8fVzA2erU+gvAB6rAXz3OXmc+MZlMOIArScHfME3TWjd45gTnfALg87jgb54UcLY6pbajgr9K7E8aOFscicuy4LeOjo6MKF/Q6/XmrUy472GSQesQwIdh4M/GVZs5IMMA41y07uBOGwM8ez2VDkjOgwh8lwQ8tXqrBb3ZFK07mqLt6XpSEt/4gb9IGTE2AcOwAdbu30flbg6Vwj4q+YKIQgGVXB7Vez+i02iAmTw2AUtMpU0vAum4i8xNgICWdnZRSqUXYzeF8l4WnVoNzDRjE2BiFHaWwZ9L4m0WCBT2bcDlzN5ClNIZlLU76NTriQmMhXd6bQDJVcZ92AqBfCGAgKaEABOj8IWbwJNTSOCPGfhNxtg0qc7bBJrNcAK0Bji31aiXLE9MAVwgAtele5mOl/V9FqYJvd0Wa4AWrN8aaDRgDPr+z2LyEgvgEyKQiazzKxrftMETuMARyGo4fPYMvcND71zRipYnqAgiAsXIOp/LL+q8rfXi/RysF4HMns+9hflx9+VLMcXkCPxCBCpSBDgXc/xuzlfn7dYB6ibhPrdwbWrp/t0Uus+fSy9y2iggAl0VOu/V22Hnyh7RffEiCoHDjcFgMFIhk0mjRKOTzkQiMBwO/zv9BAB0Q3WelCFE51WR6NIakMwT9hQCUJby831H54kALTinx5RGKm2rkDEYSNUTs0VcDPXzM52vN1Ddv2e7SkpKlFnVxB3RUp4ol6G/euWBYTVPzGQ0E+rnnSDw7adP7WEmS0C+RknUanYSpCRX/enn1VzhU0/MEtm1KH6ewBvDoZhmpqkmOLftBWXoKPUEgI+JwAXbzMn6eQkzFjl0MS1skZCsJ+ZmznGkj9dth6PKdGnp+wE8ctcD26eQwK2FktKaTPpSD4jh55XWE/U6rOl0saR0SKTCCcT382rqCc0mAOAHz22VEef94/DzyuoJTcOo0+G+P08B+DbwATH9vLJ6QtOo97/2BO8QOINffztYJpDUzyetJ8rOezws/hm4teiQ2Grl8obfCISFl5tUUU/8m8uT9FwKBO8icaWa1Saq7HBSO17NarS9/pEUeBeJz94QAlMAn0YC7yJxo5bVrCgkwqeQPIGq6PmbscC7SFxu5vJc2s/7EeCUqByzKFFPtPIFI/K0CSDxPh48PAj081nh58NGgCxxWD0BoTZbSsC7SLxFP3RTIgny9r1u1z+R6bqdrPxqiWG7Pfuh+6xS8EtENgHskh/x9PZhVsJcrSMs4W121voHEOfPHrcB/E7ePKqZc/z8I9omB/DO2oD7kDlPG63OHzYeAPiHdjtoy4aCjp1z9BldQ9eeV/Hl/wN0l+QOi7NDpwAAAABJRU5ErkJggg=="/></a> +<a xlink:href="https://github.com/xingchengyusi" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="xingchengyusi"><image x="470" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/HashLiver" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="HashLiver"><image x="496" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/HynemanKan" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="HynemanKan"><image x="522" y="106" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAADy0lEQVRogdWayW7TUBSGu2DYgwRUsGR6GgRCAsGKBQIEFBYgMRUoSBSEgJaXAfUB2rSpGJZIUMAJU4fYN45TSJz0Q+fGSZ3ECbFxGyfSL0Wu3fyf7/W555zroaEYPsAe4DTwEpgCPgKm4zhlkXz3jk1555ySa4b6+QF2AleAeaUUUQSkgRH5X5tpfB8wWSqVilGNt6pcLjvABLB3I41vBa66rluIy7hqkdwUYAzYHrf5Q8D7jTKu2qfWO+BgXOaPb+RdVx1UqVRs4Nj/mj9TKBTczTavPNm2XQEuRDV/vl/GVfuUGglr/rjQ99u4ah6Jo72a31+tVvOWZZEkua5bAA7/y/w2HW1sRRIFvJVw3g3gpvlzBfNHcgVc72R+byn/2/k2+YbMozmyj9PJ0nia7NN5SotFmUrDQQCTQijmjVvTGKMzGHcSotEZjNvTZO6nyH1alFF43mp+Z9ktFwUg+yStL5CTM/eSI+PuDJmHs+QWFnHXKk5TAihZpTwkGuBxWlP323AmCODBrB4BVcjLKFzyA8wPIMBc3fywUmpt0ACUUmvAbgE4LQtFEIBclARlxMtoM4B4Bk4KwMt2gOlEARiiYIAJAZjSAEphmRamsYT5NaEylrByntcawCsBWKgf0MmTzK8kS617lUaBAOQaI5CApM3qQb4RWB4qFoulfqfLKqJWV1f/DD4Agz6FgE9ND7GdcKn2h3g9jFoWSa8HLLM9jNYWsrzS5pNeD+Q+ty9kp/wr8SDUA8ppAJwQgN06mZMRGJB6QPmTOS8jTQ9aNgqk/PXAyAACXGwqKd2K68QFUE+B/3UsExGgraT0ICbiqgdaDfuPxVEPAM86tlXiqAfiBjB89UD5V9HuuD0F3IhcD2SWyX34SXZ8LnAK1qfAyvtvmNllzC/R6gHgWqB53y7M20h5etHGWsp1fIbqd1CMqN82yg7/G8Cbrq3FyM1dWd5lHfneOQisP4S/aiupGbK5W9bN3UNdzfsgjoVpr3dqCnQLg43kUfXcXj/Sk3kfxLmEAKwBZ0OZD7vF1AYQkIo0UoEQAHbtzp+PZN4HcVQ23HoGGE/rxCswDI6legaoVqv50NOmC8QBHZ26AXjpuKS8+u4/nNVTRku+j6V0pltPxroBUIs2+2Mx74PYIhvdQaPRKIhMS+frEmnEqNztJi0sYq2YTdeo4I3ubbGabwEZBl7I6wFBEDpmO731dVTzqwbPN/UFEO9lj8vArK4nQjQFfNElJW1yYMemGe8As0sard4LG6+BD9LtkJaNSL57x+Rvco6cuyuOH/8LqV34nrAeOhAAAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/5ime" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="5ime"><image x="548" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/InfinityLoop1308" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="InfinityLoop1308"><image x="574" y="106" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAXvklEQVRogcWad3TbZZb3lcS9SbKa1SVbsoplFdtylW1Z7r232HEcl1Q7xSkkTgiBQHqvhEwChAQSAqGHhAyTpQxMqAPL7LCw7JSz7MweltmXNmcKh897fj8zzNkzM+/Z2WXnfc75nkfSH9L9/u69z3Pv90oi+TZWbEKaJFY6V5IgOzgrUXVVkqx+X5Ki/5UkRf87icz8O4nU8KtZybr3ZyWrr85OUB2cnajsj4qTp0n+v67oJIUkJmH57ATZq3MSZMxJUjAnWc2sFA2zpDokMiMSuZlZcouI2TIjs1N0RKWkEZWsJjpJTVSi4pVZSamTc1JSFX8zuxOURkO0NO2AJEHxhSRBRlSyUjT8D8ZLpFokUj0SqRGJ1IREbkWSahExS24iSmYgRqb7GlpmJSqJkms+j1MZ98ep9Pr/NcOjU/XRSdr0FSk622fxajPRqXqi5LpvMFumRyLXI5EZ/mi8sMvTkcgFAtZvSMyRG0QiUXIdc2RaopV6hO+M05i+iFEYtkQpdLHfrvUpWscsqe6HsSoL8Zp0hD1aYRIRq7GJiNbYiVLbmK2yIVHYkKRmIFFkIJHbvibxNZGvPTITWiai1RaiVMaZ71ObSEjLIE5rfTNWZcn8VmyPUlo7JTLjZxKZmWiVjbg0BzFpmcRqMonTOYnTuojROolOczFb42SW2oFE6UCiEvZMJGrn168F2EXMUmaImK1MJ06XSWxaOtGqdOK0GSQZXCQZHcSl2T+dozS2/4+Mj9bYh+P1rt8LTzdG4yDR4EFq8ZNs8ZFi9iFNzyXRGCDeFCDO6CfG6CPa4CVK52OO1isiWu8XPxM/12cxR+cmSutmTpqL6DQHCQY3CQYnicYskkxuks3ZJJuzxPfxeseXUWrb4v+W8fE616J4vYt4nZvYNKe4p1j9pNrzkWXkicbL0vNRuctRuspEKJylpDpCyDNLkNmLkdkLSbLmk2TNI9GSS4LZT7zJR5zRS6whm3hDlkggxeIl1ZYjQnidZPKIRKRWn4hki3fyrzI+2ZTdGatxfKm05aGw5aN1h4g3ZIvGx+m8aL0VaDzlmHJryAg2kls9D3tBK87iDkItY/gjfWQWNmHwhdFnV6DLLkPtKkaRGUTlLCAtqxilI1/05B+MFAwXIEv3i0SEXSAizwgIn3+ZZM5u+y8Z78qvsVW0D3+SV9WFzl1MqjUPpb2AFHNAJBCv96HOKhMJCMbmVg7SNryBmq7ljE7tZHzNbkZX3EFj3zJqu8bJzK3CGazBGawmIzciwpZXidlXhsZVgNqZL0LlCKKw536DP5AQIHgj0Zj1WZI52/n/NL6uayRmavOeH27ec4LRlVsobugnPSeCPD2HZJNfDB1lZjEmfxV6fzUDk1tp6FnJ1Kbj9A9Ps3RqJ50DK1m0/FaauxYSqe/HX1BLaXUHlY19BMsbsWWHMDjzsfnL8BTXorTl/glU9jzSnAXo3EXie5nFR7LRQ7Ix6w2p2Rv9Fwls2nZo/aPPvMTV7/899z58jQ3bjlHaMIDKHiRJ70VmzcUWrMcdasMd6mDN7SfZd/QRHnr0VW694zSrVu9i3vw17Nh5kh3bj7N6agvT09uYmFhPd+8o1fVdVNZ2Eq7pIFhSS6Y/hDmrCJ27AL2zkDRnEI0Qthl+0uxB9FmF6BwFqOw5KCx+ZJZsUs2+NX/W+JqmPv2m2/d//uiVF/iHn/47N97+GYfvfpiKliHSnIUo0oOkuUrIEo1vo6xtjO3HLrJjzznu2HqSkeF19HUvZah/kunVWzm06wTbb9nDkgUTLB5exoKBcbo7Bmhu7KG+vpOamg7KK1sojLTgDdXizq/CnlsmElJleFFZfaRlBjC6CtA6ctBkBFBYPSjM2Z+lWrK0f0KgsrbjwKate7nwyDUef+b7HD55nsWrtpAf6cCSXSrGcnaoFX95F/b8BroXTrPr2EPcddfjrJrYyoL+lWxeu4tdtxxg/bJN7L55F0e2H+TCd+7nifsf4fEHHuHuo6e4dfo2lowto697iJaWPmpa+imsaiNQWo8/VIc7P4LFU4jekYvRFRR3XaZAwIfS4iHV5EZudO39T8YrNRaFL6fki7UbbuP+h5/m4ImzDC9eS03bIEXVnXiK6gmUtVLZOUq4dYTssjaWTO9j5caDPP3Ea+y7/RS3rN7Jkw9c4+KpSxzZepiTO49y4c57uHTqHPcduouTew5z75GTIpHHzz/K0X3HWLNqmsHRSRq751PR2E1lcy/hhi5yS2tx55Xhyi3F6AhgyPSjt/tIS/egMrtQmpyfK4yOPxaA6a7c5ZmeQlq6hjlw533c8+Blbrp1L13Dy2nsHaewupvcsjbah1bQs2A1FS0L2LDtBJ19yzl/zxVO7LqX21bv4JkL1zhz4DSPnD7P5fsu8HcPP8alk6e4dvEhXnzyKZ6+cIF7jx7nyM69HN6xh8N7DrPtjr2snNrM8NgKhkYm6R5cSKSui0BRlUjC7MrF6M7F4MpB5/DPeMLqRmHOWvYNgUSt61V3QS0NvYvoGFnF5n2nOHDPI8xfsZmannFC9XMpquqhqmk+Ld2L6eybYHDBWlZM3Mr0sts4fPMh7j94hhcf/S5Hb93Fsw9e4o3r3+XdG8/z9ovX+MV7b/Hrf/spP3vnNd5++TleeOYp7jqwjx2bb2H/bTvZs2UXpw6fZu8dB1g0toLh4Qmq67tx55TizAuLOSDEvzm7UEz4GI0VjT3nhmi82lGojdd5vjL7I+RUdpNb00v72FpGVm+lpncRzfMmqe4YpbpthI7+CfrmraS9axG1dYM0RHpZPjjFxrH1HN9ygB9df1V86j95/XU+fOd1Pv7JO3z0wQ/5zUfvw5f/AZ/8q0jmtetP8+SFc9y49ozoqZsXr2LD4il2b97B1g23s3h8JbX13YTrOsV8EJLclleBxpGHPMOHs7iGBJ3jK527QCPROIvnpmYEMWSXk5FXgzmnEndpC0UNcyms72d45RZaByeJNM+npnmYpvZxGptHqKsforFmkO6qXlb2L2PfTdu5cuYSp3fu4/rFh3jv5ef49Gc/5qtf/Qw+/RB+/8kMfv0rvviXD/jn117ho3/8R9574Qb37TnGtqmbWTEywcqFq1g5uZ65g4upaepjeOk6skvq8JY1k5oewF1cjyIjR7wXLP7yXoHAQeF4FMoFozeM0V8hlgCZBbUigVDToHgXCB7onT/F8KJpBobX0NaxiOa6IdrDnSxuH2X14AR71t3G8du28/rVZ3jzu5e5cvYU77/8PT754G34P7/gN//yAb/78Kf87sOf8973X+TNy1f54p9+ztvXXuCRu+5jSf8o/c39jA0tZfGitQyNTRGq7uLEuSdw5ddgDYTJzK/GmB0SLzq51b9fosjIvSpcVMJtq3YUYAqExVpF7y0lEOkQTx6BQH5FJ4XhTirqBmjrXsLYwo2sndrOpskt7LlpG3es2MRtk+u4Y/kaHjxyjPOHD3B083pefvQ8//6j1+Hz/+CrD3/Kr9/7MZ/+w4/45+de4CfPvwS//JjXHr/GU6fPs3v6dtYtXUdDVRu9PWNs3Xmc7qFJIi1DHL7nMcoaB8WyxF/agt5ZhNFdclmitOV9IBRtMmsAVWY+Rn85Wk+JCHthLe6SRvzhNopr+8Qwqm0dobFjnNauxfT1LGPn9F7O7P0Oj5x8gEsnznB0yx3smFrL3vU3cWbXNu7dsZWLh/bywgNnuXHxAq9dusSNCw/x/JlzvHv1e/z6xx9w5dRZHj95jnNHTnPPkXtob+ynqrKTydVbuXnbcXpH1tC1YIrtR86JxhscReSUtmLPDr8v0boKP9Y4ZgqqNHehaLjw9AVPWHIj5FZ1EahoxxdqxVvUTF6onfLqARraFtLVvYSh9lFWzZ9k/807uXruUd763os8//DjXDh8lPt27+bBA/u5b9c2Luzdw0P7DnDt5Gleuu8Cz999jnef+i5vP3GNxw6f5Mq9F7n/6N08deFplo2tIVLRSXlVL/PG13P6wrNM3XyQYLiL/rF15IVasTqLcfkjHwkEfqvODIqFk0BAKHkFEta8yhkSgQoy8qpwFzWRV9FFecMQta1jVDePUFnTT115G/2NcxntHGZy3mL2bNzKd3Yf5Oz+I5zbf4hn7j3Lq489zltPXuGxQ8e5sGM/V46f5tkT9/HaxSe5etcZTm/dI3rggeNneO7yi6xdtYXKqj4KytoprZ7L6s2HOH7mMpPr91BQ3kF+aSsubwVZ3vLfSFIMrt8qbQG0rnw0riBpWUWYAuWYc4RkLhNreWtOFY7CBrylbZTUzqOxZ4LOgSm6+idpbx6itryJutJGBloHWDk6yfpla7hl+Tq2r5nm/oPHeOfZF/j5jTd56eLjvHT+Ua7fc55zt+/n4u5j3Dl9O4c2buWRk/fzy/d+wcvX3+DkXQ+K90xZzQB55Z30j29k750PsWbTfnYfOkt90zzcnhIK8mt+I5Fbsj9W2wJiBZhi8Yj1t94bwlFcj6e8BU95G4Gqbrzl7SKJ7FA74aYRmvuW09YzQU11N2XFdYRDDXQ29zM+bzHLx1awdslqbl65gfWLVrFtaiP37jnKwenbObf7GFdOX+D+XXfy1tMv8tDRuzl66x4unDjLK9df5/0f/5KLl55jzaaDVLaMUdE8KqJr/moWLr+Vu05dYvu2Y7Q0zaUwL/KRRG52/5MyPVssVeP1DoQ2UukIYi2oxh1uoaJnEbWDk4Q7FuIpbScz2EReuI+S2vkUR3qpb51PVU0nkap2mpr6aG+fR0fbPHq75jM8d4wFvSM0ljeyqH8hQy0DbFxyE6d33snBTbt55/obvPeDd/jBlRd46/t/z/mzT3D56Rusnt7L+KrtNA+upmPBeur7JmnqXcaCxdNMb9rN7p3HmNc7SqS4+n1Jks5+VWZyiQSEplogkGjykCoktTeEKbeKQE0vhQ1DZJd34i3rprxlnPpu4XgbI6ekiUBRDXmhekKRNirre2lsmUff3EUsHF/N/HlLaaztZqhvIePzJthx814euvtRHjv7FP/63i+5/sR1zp+6yHeOnmPZ0k0cOP4gi6a2MX/FNuoHVlHZvYzqriW0Dy6no28xIwtWcNeR0xzfe4ybpzZcliRq0w+mGOxILUJz7SbR6CLO4CDBko3Unosj1ExB0zyKW0fwlHVgDzbhKmrDVdCOKTtCdmkz3lA9/rJGcsubCVa0UlbbQ1P3GHMXrKJncILeuctoaBqguWmQns4xervGGR6aYNHoFIM9Y4wMTTI6MkVzxzhL1+6kd9FmWobXE+6aoGVkmnD7OLUdY+IDWr1qEzeef4U3XrjB/q3b90tkJkd/st5Ggt5OotEheiHR7EZqz0GVVShKIFJbUOyDVe5SDN4q3MXt5FYMkBPpp7BxLoWN/QRrhTxpxVVULyKnvI2iml7yytupax+hKNxBeU2feDQWh9to7RilNNxKRbiN/r7FzB+7iY65k1R2LKGgcZT8pjHKuiYYWLWDqp6lhJvniV3c+ptu4ZXnXuLZx55gcmioRyI3OzUJadavhAovXm8XE1ma4UXuyEPtKUKamS9CkEgEuUTlKCfNHcGYXYM5UCuGWHpRLY7SRtFbrlCzmPhCYZhf20+ocYjKjnGxBC9vGBTL8kBpM2Ghwg130NO/lLrGQfGGD9UPUt6+hEjfSsJ9U/gbRiloHievZi455a0UljXQ2zXAiQOH2blx41fj3d0asSKNURpfiVKZSTI5SbX5kdl8JKX7SM4IkOoqItmWh9RWIHpB54mgcpSitJWgdoZI85VjyK/GVjJDILOkBWfx1yhqFE8te14thbVzya/sIVDWTqR1hJaB5YxM3iKS8OXXUdE0RHH9ELnVA2SGOslpGMEW6iK7ci7B2gHcBXWUVLfjC5QyMn8hTTUNL3/TDyTp0yeTTZkigVitnXiDG0NOmNyGPjTeMhTuYuRCX+wsQpcdEi84s18o/MpJ81Wgy6vGkFst6kV6b7l4bwhG2/KqsOdUfwNnsI7ccCfFNYPkRnpx5zdhz6kkw19BVmG9eM84CpvILGjEXtAshqvwwOwFjRTWzyPSPoZPyMnKTqE+WvoNAZnJoZCnez6XZ2SL94DclovOX4atpF58wsqsEuSOILLMXFTOfPTZRZgDpVjzIugCFWj9EXS+iBhO9vw6bMFqzJ5SUVkwuUrI8IZx5dWQld+AI6+WDF81Rk8lhqwwzoIGLP4w1kCFKOEYPeVYfBFR/TD5KkURwVXcgqukXTyRBCHNH+n7XOut/M8zhSSDa7+gRwrap6Ciab3l6P2CAleK0lUskppR0bJROwKY/cXY8iP4q3twlLVhK2rCml+LIbtUFKUEecScXYwrWI3FI2hBhVg9ZdgCM17JKm4lWNWPr6xdNNzgCYlCmtpeiNlbIV6atmAtRm+E9Nxaihrnk1PVR3peA57Srj1/okpIzT59nNb1eZzeg9wWROUumTE8s4BUe96MQmZ0k6zPJNXiwuAKkBEIiSElhJlAVggpoSg0eUuo6xll7dZ9Yi0/sX4b4aa5ZBfVi+qGScglV0g0VCgUhVAzectEGLLKyAzWiTd/VqhFDKdQ8wLW7zqNNbcWR1Hrpypn2Z8fT8nT828S1OZk84xwKxBJMvtFJVpmyiJFl0lKmhWZ3orGYkdv92LJCWPJr8Jd2oQv0oavoplQcy/LNtzOyfOPMbHuNlHdSPcWixpPuq9cjHvhqA1UtIu7EEKCF+zBapFMVkkjgUiXSMBV3ERJ0xAbdt+NwRvBVdKy+s8aL/bHmWXRqbbQGymWfGTphagdJSQavCQZspDqXUi1GUjTzMg0RpRaIwqDVVTT5IKybM8Vi0EhvFQZHlFJcAZLycguQGfzikqCoCiohJrLJJQuPjSOAozZpWhdRSIJgYBAJDO/BndJs5hPQpcoaLPecBdp7rLXTf6qvywtzpAI26Tmwk/k1kL0njAycw5SYS6gtSNNs5KqMaJQ60lVa5FqdMjTPSRbPeL9obB50Thz0Ni9yIx2EtUG0WMKYyYaW/aMSOXMFZtzES5BNswT9U+DpwSTtxR1Zv4MoUAFJl+5mAuCLptsCXwmy8hzSP4rK1EfbE8yBL/UZZWjsRWgEIYZWjspKjNytQGlxoBSpUWm0hKjNIpHrzBdiVGaxfdJWityQ7oYaqnGDFK0wkxNxxy5jhSDY4akKygqDAIBoUnXugRttIAk4WGZfWjdxeg9IUy+ChL02V9qPaUtkr9mmX11C6XmfJSWfFK0WUjTHGiMLlTadJJlGmRyNWq9VZxMzk41iwQStbaZYV2qngSVHrnujwTixfmXFaFwFDylsAdEAqnpM5Bb/SKE0JKavSSbZqC0B7+K0TjGJP+dpbKHhjNyan+f4a/E5ChEoXciVZiRyo3IlUbkKpOgkJGkc4iDvzilhQSliQSlkWS1USQgGJ+cZiJBYyZRmy56IMXsmqm5jC5B3xEhyCQCAaE7FDwh9OcKW96XMmtgkeR/svRZkTZFesGncoMflcmHxuRFoXWQkmoiXqonXmFmVrIeSVIasQozKWnpJKlMxMnTiJGqSVDoxFwQwipJlyFOIYWhXkyaTUSU0ipCmHSmmLLE3BBkdY2r4JNUW85fFzZ/aS1ct9eemVP3RqoxgNoUIFXvIUXlQKZxECdM4VMMzJEaSVBaSFRYiEnREivTil4QdtEjQrGomRnPzlYYiVLPTCjjtZnihHKOwiKSEPoSRYb/9RSL1yb5Ntf5K29GdY1OrzA4yz5VpxeiSS8kNjUTjSWAXOciWW0nSWllTmIakphUpCortqwgsVId8QojiSqzaPwsqUH8G0Ks4EWLZ6YT1NnEmfHsVPMXsRrblgS9M0byv7Xuv/ymNtK2dF+KIf/zNFuIeGUmMVILcVIryUobCTILc+I1JKWaMGb4iJMJYWYUQ02c5ifrkMhnCCRbvMitXoHA57NTTXslMuPf7g8g+09fU/hKeyfSPRU/kGndX8Ukm0UCco2DeKmR6ETNTI7IDcSlGoiVG8U/fEiSjUhkJuYobV/F6JwvJ+gcy2I01tS/meF/blXUD6oVOk9vnNS6P1mR8XSi3PxubLL+47gU3W/jZPrfxskNH8fKzO/OkZuenpViEtrAXonMov42fvz/Au2J8rt92MGGAAAAAElFTkSuQmCC"/></a> +<a xlink:href="https://github.com/InkEcau" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="InkEcau"><image x="600" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/IvanHanloth" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="IvanHanloth"><image x="626" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/OtokoNoIzumi" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="OtokoNoIzumi"><image x="652" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/NeumoNeumo" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="NeumoNeumo"><image x="678" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/liweiyi88" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="liweiyi88"><image x="704" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/oOTnTOo" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="oOTnTOo"><image x="730" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/summerkirakira" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="summerkirakira"><image x="756" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Krasuszz" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Krasuszz"><image x="782" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/kroyoo" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="kroyoo"><image x="808" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Kyrios0" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Kyrios0"><image x="834" y="106" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/a81n9" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="a81n9"><image x="2" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/ASNQAQ" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="ASNQAQ"><image x="28" y="132" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEHElEQVRogdWa32/bVBTH+8DGO5M2qvE4GH8N2jQJtD3xgBgaGzyABI+8Q5u2E2nFC38ETdqU0e5tsImyFyRQh5Y4adM2iXPtJFXzQ/2g49ir48ZOnNhdEunIVpJ77/dzz/Xx8bmemYngA7wN3AEWgQywA+j1er0lJuf2dxn7P7elzczr/ACXgC+AZ0opRjHgKfBA+jpP4e8AC81mszGqcK+1Wq06kACuxin8AvBlu92qyaDVajUS8crVl0wK8B3wZtTirxfIPH+k/USxksNQtRgADEr6Plv5nymQ+Qt4Lyrxt34r/Vhbzc6Rzi2yV3mJGQOAYQNkckl+yX7PZjlpAjfHFf9xprDUTucWSGUTrOceslfJxuIBwwb4VVshlZ23Jms9v9QBPhtV/F0R7pgArFkA8XpgQ1uh6+3TsSVShRV/S+gnBWC964kbw4q/tlVJGu4OvACGMqlWdWvgqEwpg0O9yIa2fAZAbLOUrAHvDxJ/cZeN5/06cAAkCtVUwxpQQKIwpQzLq+XqYV8POOPnSW9LOA8C+Daog7XcElr5X8rVkjVbpYjsUC9S1g+sANH1wLzvBAJf+4m/2mia9SAAOWa0pDVLMlAclnaN1Q/AaB7KUprtB7DgdxE5HcpRQtxqTJay7HQsv2sQmPOKv9RqtRt+AH6zEpelAjwgAJ32Sb0nAZSsMiiMTYKlPGEc+NwN8GwKAf5wxM8qpU4GAYRZQn5LIKolZKqa3ABPgCsCcGfQnbD3Ih5sXhHjtk/7ZALARwKwOMUACQHIDAI47WCJl6W/OdB3KVY09m2T8wO9QKH8gg0tGXAjGrf9Qy9AWgD+Gx5AUgmNunFkpwE120xMVadSLVnpcJzt93oBdgSgEgZgt28yp1tZZVAyFlX7vV6A0kyj0WiGAeiXTr+u9kdHR8fTD0DIJTRJAMgSAl5MMcBOyDA6cQDpoW5kEwyQEIDbUwzwoQBcGTaZmyQA5SRzdkb6dNoAgCfu54EHUwhwr+eRst3u1KMTEJyMGWMCdLyPlDZEIhqA01zGmx5LNhqFB4AfRiqrjArgVDOiADBbJdN3ewr4ZlSA7lFnXy/YuX7+Vb7/6lzPo1crPW1USADgq77ibYALRR5thwVwC+rN88+aV7wKAVAg/WdgaXHY4q6/B4Yt5Ib3wGa3uHs9ULwL4uYEltc/GEq8C+LTCQE4AT4JJT54i+lsHI9ni2nBmfm7I4l3QdzYqiybqwFhMFoPLFseeKyvGKGXTQDEuxqpbdlBjGuTT9kAspWbZ1WizbVIxLsg3rA2ujsts18oHB9Acdw8dja6L0Yq3gMyC8zL6wERv2owd64vgNgve9wHfpfcfAThEl2eSJkceOvchPvAXJZCq/3Cxhrwj1Q7pGQjJuf2d/Kb/Ef+ezmKwf8Hg2eKX/HnnlQAAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/iconquestion" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="iconquestion"><image x="54" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/arnoldhao" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="arnoldhao"><image x="80" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/ChuJiani" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="ChuJiani"><image x="106" y="132" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAIEElEQVRogc1aa0hVWRS2GjV6p+Gjphc1aiRE0YNeBBW9IMmsGbQIK1NRm6EUZqgfDRQU4YxK0Y8o6EFPoqLHTNKLKCqTtPoRE2pU9rbMx71l+fiGb3fWad/j9d7jTa0PLp67z97nfGvtb6+19r76+bUBAIQBSACQByAfQAmASgCfjE+l0ZZv9InnGL9vCQDBAH4FUAjfcQvAaj6rI4n/CCAXgBNtBweAHAAD2pO4P4DfANSi/eAE8CeAwLYmHwngDjoOxQAi2op8XDt7vSXUAIj9WvKJAOrx7dAAINVX8in4frDaF9nQehc0NLg2ffrEEA80NTWZ3+WaqKmhCoDGxkazL+FwOMx2m+CLF9glPxxAtT6aLyJ5kquvr0ddXZ1J9P379+q+kOF9orb287LRDXr9+rWLI+qNvjbBB0Z5Ix9gjTbiPd37bLtw4QI2bNiAe/fuqbaqqirTu/PmzcO6devw7Nkz857ubSHeaH8GBEUM554M+MPTaHqbePnyJTIzM8EhISEhOH36tGqvrq5WfQYPHoy+ffti9uzZ5hin04mLFy9i+vTp2L9/v2r78OEDfEBWS+QHGBnRBaJX6zXlcODAAWXE8OFU3Wd8/PgRZ86cgb+/v7p3+fJls/3SpUvo3bs3Bg0ahHPnzvlCXqQU7s4AlgceQe3Ta9Q1p5/eTUxMVERfvXql+lBuXLypqano1q0bcnNz1XeRYGFhoWqfNWuWrwYQf7krzFqsbazRRweJjB492pSJ4Pz588qwLVu2mJqnA4gZM2ZgyJAhalZ8hMOlADSqSrfQwx8NIQndoKioKKxYsaLZuPXr16N79+44ceKE2cbZ4/NiYmKUxL4S6boBhd4MkJiutx0/fhyBgYFKPmIU1wlDKHU+depU1VZZWWlGHz6nX79+GDt2rBmF9FDL59icmQIhH85ntEY+NIChMSIiAtnZ2ebi5uzwk5aWpqLQw4cPzTHv3r1Tf7dv347OnTtj27Zt6vvz589dCHuSqwXkHOpn7KRaBEOj9ZpSyMnJQWhoqCJACIlr166hR48e2Lx5c7OZe/ToEcLDwzFhwgS8efPGlU1Tk8saEkd5wS9+xhbPFuSBJN2nTx8kJyebbZwRkpg5cybCwsJc8oZg1apVKgLdufM5VzqdTjWOxuue5zjJ5F6Q42fsUz1CSgAxgqGQMmAeoGSEKIl06tQJc+fONfvLzNy9exfBwcFYuXJls3t6xpcQbTNL/0MDyjz10D1DQ/iSPXv2qAx86NAh1S7eoiE0jLNgld2aNWsQEBCAK1euoKKiwiTY2NjoUlvpsJGpS2jAW2+9qF2WC4ztBD1PMgsXLjQJ0ggaGBkZiaCgINy6xf36F8yZM0flhfz8fNMp5eXliIuLU2FYz8yUlsyEF1TQAI8xi96Kjo5W9c2xY8dUGz02cOBAFUK5Dt6+/eIDLl7KiP0ZeSgThs99+/apvECjBQ6HQ4VaGsZ8ImWHwN2sWFDn1YBTp06pF0yZMsX0Nj1TWlqKZcuWYfz48WacpyG8d/DgQVWNShkuKCoqwpMnT5QMr1+/jqVLl6Jnz57KsIyMDNPjNNrmGqjzKiGSY71Dbffq1QuLFy9WEuKidFfP6y+WfEHpHTlyBHl5eUhPT8ewYcNUCI6OjsbatWtRUlKCFy9eqDFlZWXquzXje5JQqbdefBD1SgIJCQkYMWKEMojlwNChQ1VdM2bMGEyaNAkjR45U8qKxnDnmBPZftGiRktuOHTuUVKQuqjZmld+5zpgnOI7Z+sGDB7YWsccwygdzUfFh9CJfKNGBJcTVq1fVPdb6LC04M/fv31cfISietJYI5eXlqry+efOmuc/YvXs3Jk6cqIzgurETRm0lMuqVyUtgjdUSDkmW0pHCzR2Yndm3oKBAlRwS3bjoOUZK9KdPn9pKZDxobRESYZic+FCZclm4nB19o0Pi+toQqRDsp5cL2dnZ6Nq1q1rc8h4pw5OSkuxEoZ9pQKinYk5ILl++XEULTrF43FMRRuJiJD1uTUpctJMnT1bhU+6lpKSgS5cuiI2NtVORfi7mjIrUNetYwGndtGmTKgW4GZE2gU6OXrZKR6+JmPBoXHFxsfI0q1OCGZoG8LvMmpdi7oa+H+ARt1tImUA9MsKwOyMJIXKgt3SPkYDIiDKQZ7CNM0W5sBQZN24cvgJp1i1lsw29QPa73Kxz0THTbty4sVmstiYukZC00wDuEZgH+vfvj8ePH7fNltIwgufzbqGXCjt37lShj0NGjRqFw4cPmxsXknRXBpM4Z2Lr1q1qHTHGk3yVcZbkA7JtH6uIHvVFyzKA+1qWAUxUrHsYpXjQxVxx9uxZHD16FLt27VIzxb58BT/x8fGmwY2tP9gialr8eQrA7+5G8EWiXwE9ffLkSUybNk3pWQgyLDKS8JrFHjM2r+fPn68qVCYvGe8jMt2SNwzwN47vTFh3VbL10/XODMoymZFqyZIliiwLvaysLOzdu1fVNuzPsT6exgluezxadHe4KxKS7R8hB72E1O16G8E22S4SciBGMBn6oP9a/lLkkbxmRKx+vE5y4m3GZiElWdmaMdnHnb7pDB+l0wAgxhZ5zYhkfB9oApDUKvLf2U9MKT6R14xYYISujkZ1q2XjwYifrNGpnXGbwaRNyGtG/GD80F3TAT90B7QpeYshPEv921Pt5AMcPPPv0H8AMQrADADcD3rdebgBx9zgMTmAoA4j3oIxITxoNQrCfwH8Z5x2MGHww2u28R77sG9IW7z8f7cAzC6UuYG4AAAAAElFTkSuQmCC"/></a> +<a xlink:href="https://github.com/Clov614" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Clov614"><image x="132" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/DGCK81LNN" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="DGCK81LNN"><image x="158" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/DannyDu26" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="DannyDu26"><image x="184" y="132" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFJElEQVRogdVaW28bRRjNA5R3KrVE5TFQfg1qVQnUPvUBUQQUHkCCRwSNk9A6l0qIF5o2gSTcJOAFlF/Q0tASIYFvTUpsk4vXa6/XdhpfkoPOeDcaLzu7a3vtEEtH62xm5ztnZuebMzMeGgrhA+A5AJcAzABYBpACUKhUKnWC3617y1aZi3xm6Cg/AE4CeAfASrFYRDcAcB/AVdY1SOLPA5huNOrVUslAGGg2GxUAUwDO9JP40wDeNau18tZOAf2AUX5SBfARgGfCJn/2x9+wOrWYxCDw0wP8DuDFsMhfuL6YLl+bjWGQuL6YMQGc75X85YkvU42xO3EcBSbmk00Ab3RL/spRER9zgJmqU/IXqP6oiY+198S5oORHbixlS14VRm7HQicZuR3zrDe6lC4DeMmP/IkfVrD6ya1WZSqELSIi1aWKOTobw7f38JDp3EvAhze/SWL8Thyfzruj3z0woYg7MRdHdCHB8fC+ivyZWq1eeZzJYz2tYT1tXzWspTX8nc0jtpbD5EJCtEa/BPyR2MFGNi9irjuRyWOv1uCrNOwmYNowDJRNd1QrJeS0gpho+ikgu6XjSbUEU8GDHAFEneRP1mq1qsp0FQpF4Vk2t3VMLfa3BzayeZglQ8RU8anX65U2A0hXSWUq8CFWurUzAAH/5EVLM6YXJwBvyQJWjqGAX23yw4ZhHPQqwC+PO8v2KsAwjAMApyngkk9BXwFB8rjfPBLpXAB74VUKmDnGAqYoYLlXATKBP1M7IhUym5CMQDaPzKaO5GNNOY9EuhPwMwWshSnALY+bAeaRSHcCUhSghylA5HGzPY8HmUci3QnQhqrVai1UAS4Een3eUGB3d3fv+AsAoNuFlVaiKL8Cai/kL8DbS0UUr6ATdp3iFQLwyL7BKwM5QfKVcgk7uQImFxO4plgvkJhfDzALeT2f2dTFgGdMNy4yV3sQL8uqWns0unTVRcuTPK32zNdJjM8pPPt8HGmfHrjp9fxcXKRaZivGtOPLnNgzUg+INDrDP6h4O1fA59+nEP0qgWmxR5OwkBQtT/KrsW21X09r0KUAsgBeGdxtvbGe1sR9rjc++y4lFi5TzvgLCSGe5ewGsieyi7YAKmTBj7+IYdTqUhvsdrYcyfv5dbcBaN/zXG/k/eNTrCTgFQo4TWNkC5heag2ycZcBxm5mywcdZE7yXusNw2glCfa8V3z2nNVQLTNnOdL7tgB2F3fGxpQVaIHTXFAUpTcgaHwAd+X1wNVjKODNtiUlt7g7qcDrFeoUhUMBeqD4B/tiO779TIEjuiUgcViB0/6yAmYBDji2XFjnA6VSayAzVcsC3OJTAIAbrtsqpfJeRQi41V6BPckwTzPVMVu08nRYZwP64TwjJrpZRfz5OHKFPVN5PAXgg/Smw8s7/DzzNIO05olwMbmQwF+Pcv9dT1jgJAngPVfy0inMQ2eOlv181M7TfToXyHrsCwF44Lm1aIkY2d/fL6n3hZJiknHm6bCwoTBzjYbYkTvrSV4Scd40zWYndrhXRDzsNLkAeDkQeUnE6/8TAQcAXuuIvCTicrlcbgT182GI2JAEWC1/pSvykohzzWbTDOLne8WotJ7gOOz4tfEQ8QKzk5+f7xUT1nrCyjYjoZCXRDzFg26tWDPd/HwY2NKq9kH3iVDJO4QMA5ikH1F5+05x0PI20YH+AMT6scfbAO4xU3Rq4Kzscpfb5ACeHRhxhZhT3Gi1frDxCwAe7urcsiH43brH/7EMy54KI/i/2HHYlv6m524AAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/EssentialCuber" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="EssentialCuber"><image x="210" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Executor-Cheng" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Executor-Cheng"><image x="236" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/F-park" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="F-park"><image x="262" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Fatpandac" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Fatpandac"><image x="288" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Akarinnnnn" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Akarinnnnn"><image x="314" y="132" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAD6UlEQVRogdWaT0gcVxzHV9Tk5kFx0zUFL8YEvXgRQfSiB09KQt2UVJQcgim21oPxDyhMD6uCtE0L3jwqKHrwoLREPOhBYhq2Vk+VrYjoTVzUrFDbuJ/ym45l152d3R1nxtkvPHaZ935vvt/ZN+/3563HYwGAT4AvgJ+AN0AICAN/ay2sXXujjXkmNp7bBFAEfAO8xzx+BbplLieJfwr8CJxjHSLAa+C+ncTzgR7gA/bhHPgWuGs1+YfA7ziHTaDcKvKf2fzUk+EMeHJT8s+Bf7g9fAS+NEv+Je5Bt5llI+rdgo/A43TJlwGnuA8fgEepyN9xeLfJFL/Jdm4kYPC6RSgUYm5uLq7NzMzQ2dmJ3++nvr6e3Nxc+vv7cQivkpG/r3nEOFRWVtLa2qqSjW2jo6OqmIWFBSKRBDO7l5JPT4CEBwloamrChfheLzDTjW3+63YdInEBoBZVkkUCBF/FCnifhQLeXZH3AdEsFBAF7nm0TIosFCD43KOleNkq4LVHy1NtFRAMBhOcoUU+5Gdht2ungI2NDfLy8mhoaEhwhl6vl/b29ptMHxJ2x+kK2NvbIxAIoCiKSkj6rlpfX5+ufW1tLW1tbVxeXib0jYyMkJOTw/r6ulkBR8LuIpWAiooK9bOgoIDm5mb16XV1dcUth62trQTb7e1tfD4fp6f6wa2iKOq8PT2SapvCX2kJMIve3l6GhoaS9iuKQl1dHUVFRaysrJgWkPYSyhSyxjc3JT9PLsDv9zMwMEB1dbXpJfSnHQKWlpYoLy83HKNoAmZnZ83eJ2TbNipRbEdHR1oCAoGA+n6Z3UZtcWRiJ082lYDGxkaqqqqYmpoy7ciepSKSKXZ2dlS7xcVFw3Fra2uUlpaSn5/P+bmpSuVTYXfP6mBOtlWxi0aTTsvFxQXT09Pqi15WVqZmfScnJ5kHc1pEKlViywTMz8+rdvv7+7r9q6urlJSUqGMmJibY3d2lsLAwzjHKr5LCwb2NzQe6rRQQDofVl7O4uJjJycn/nd3w8DAtLS3q9fHxcbVgcIWDg4OEWEnmMUDX9ZQyIao6Pj6+kR9YXl6Oi30GBwdVYoeHh1iaUgq0+nwcxsbGqKmpwYX4zpNOWeXo6Eg3xrllnCU9ngIGcD96dcnHnMJI+c6tCBqWFrOguPvQkHyMiCcuLK+3pEU+RkQn7kAUeJEReZcdMb00RT5GxGNt63IapxkvGwMRDxzenYKymVhCPkZEnnbQfebAQfcdS8lfEyK11B/0YqcbICI1f0f/AKIFgF9L7coonzCA2LyVMjlQ6BjxJGK8UmjVAsJfgD+0aoeUbKTJd7kmfTJGxnqtuPm/RwLO2aY3mCYAAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/noahzark" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="noahzark"><image x="340" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/sakurayang" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="sakurayang"><image x="366" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/zdjjj" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="zdjjj"><image x="392" y="132" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFPUlEQVRogdVaXW8TRxTNQ0vfiwSN6CMt/TUVCKkVPPWhKlXblIIDcUhsJxQHkAiBP9Mqv4CWiBQptEJNsrZp7Jgkuzter93EX6e6s2N7vJ79st0QWzryZLOze87szJ1z73piYgQfAB8BuArgKYBVAJsADNu2awRqi2Or4pwr1GfiXX4AnAbwI4A10zTBGAN9h0H7XADPAUzRtY6T+McAnhwdHVWISBttYqxUArMsD5R6z2UOarWaDWAFwLn/k/j7AK7X6/WyfHOZEH0bhV0Y+QKMggvimGkYShGMMdCgAFgA8MGoyV8A8NJ9wx4BpRInn3uwguz8PWRT95FNLQncRzaZRvbuQ+jbGli5rBTABAD8AeDTUZG/rBr1PgGWxUeZyGvX49Bic9Bu3hGYg3ZjFpnbSeh/b4HZNkzDWwBjDI1GwwJwaVjyX5XL5brfjXoEFAp8tIk8kc3cSji4nYQ2PY/M7CL0TRJQDhTAGINlWQ0A3w5K/lrQDdQClviod8gLaLF5ZOILkQSw7pSaikr+Mqk/KQIs50lcDEv+fLPZLHlFGSUostAizrcFuKYQCWhPIVoDtIgNI3CfkDnQOgTwWRD5U17RpnNBVXyn2G/bMIpFHm1owRJhGnUOatNTiaecKFSteu8XTB1ixVRap3DuJyDuR74nzvcgD2O3CH1rG9nFB87ozy7yKcPB2ylk5n/GwcafMN++hbGTV1zHf58QIqa9yJ+jHdF/jlOcf4xsguL8ErJJgXa8T6Sxv/4SupbhU4XmOwe1tzVOPpd+pO6fJKShZ3O++4SYSpMqAU9CxfnEPWg/ueK81Dbe/IPS4b+cBC1WDmpXq3zkg/rrmayzyP03umU3+dNub+MpgBapO85LC5VGn5UtZ5EatMClRb6TD+6fCRYgvFPXAJKrDBUmSUDSI0zSQvUgMGx/pn4K38sC1sZQwO9t8pOMsda4CWCMtQCcJQFXg3bCEyoAAL4kAU/HWMAKCVgdYwG/kIDtMRawSQL0MRawP1GpVI7GVUC1Wj0cfwGIOoU6ViDhYyVcfr+TL+SD+2ciTiEAW9GegIffJ0MWm4Oee9Pv96ldCcgXYqL/AIt4NVLKePehwu+L73gKB3+9Vvj9PCffyRdmvPovOALK0cJouI2Mvg2D+/qOz3f5/f2NV8gtLXv4/TQnv7f2oj9f2OzC1PWee4bZyK4EndhzQe7z7a7X7/H7ezypUfp9qgvNJDn50uEht9xMvkYbIckLAV+QgLOhzJyc1Hd8vsvv80Wqqgu5k3oLpi7nC2YXHkm9p5kTjvR5GMXvqqzC1KP/TM4HpsZQwHc9KaVXQj9YXchHwIB1IeaXUgoRK6EWsaqe064L7RZ9BMw5AoaoC7Hu6D+KXlbxq//T37wupDkblYdVIAEHG694tOJ7Q8F1jRB1IVG1Vr+eAjDjP8dF/T/hrv93Y32HrErArQQPs339Ut3aUFBdCEBMSV56C7MeWP93x3kZgqgsQj6m7HNT4MYd6Jq3lQDwwre06FvcDVEXchMOOpZRwMsLiYrcBV/ykohLcnk9jB0eFpqPnRbl9c9DkZdEfHNCBLQAfB2JvPsVU9h8YBQidEmAGPlrA5GXRFyk0OWbDwyL6f58oNloliJPGx8Rn1B08swHhsVsbz4gos35kZCXRLxHL7prxT1L5eNHgepOvv2i+9RIybuETAJ4XEfLVvr5AVBHi7zN8rH+AET82OMHAL8x02wpvb0PqA+AZ1QmB/DhsRH3EHOGCq3iBxu/AnhN1Q4q2RCoLY7R/+gcOvfMKG7+H39YiDrtua+HAAAAAElFTkSuQmCC"/></a> +<a xlink:href="https://github.com/Saobby" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Saobby"><image x="418" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/cyb233" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="cyb233"><image x="444" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/ScottSloan" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="ScottSloan"><image x="470" y="132" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEs0lEQVRogdWazW8TRxjGc2jpvUjQiB5T2r8GgZBawYlDVaq2tIcitaeWAC5pE2qQ+jf0QO8UJ8EgBYkvlVKpqtZ20mAS4q+199Mm9jp50DvedXad/ZjdHQdi6ZUdZ2fm+e3MPPPujCcmBLwAvAfgNIDrAHIASgBapmn2KOiz/V3OvuYUlZl4nS8ABwF8DeCxqqpIEgAeAThHde2l8PcBXOt2u+2kwkej1+uZALIAjoxT+NsAvrGsnkGNKooiRLzqqotuCoALAN4RLf5D1G88Ld3NQq6sQtWMMQBoaMkVLC/9BtRv/A3gqCjxJ9eWrhhS7kcUFi5D3lgZH0BjA8X8L5Bu/YD1ezM6gBNpxZ9ZzmcsEi7NX0Rh8QrkyjgBKijdmYM0P81uVul2pg/g86TizxYWLsGJAcBPYwcoEkDuwrBdCnKquOJPEv2bAlC6fZl64jiv+KkX92Y0dwVRAM5neueJURdTIgAo1pZmDAAfRYk/gPofT/0qiOqB4d+aHh4+FqxwAFD7qP3+hOw8DOD7sAp4eoBEkJv4RwWK0krUA5LdPoDzQeKPbHY0MznAjo8X8z8zIcU7s3bMoZifRdA6osQAeKlXaShN+gFc46kgFMDl42SFnmB1+q8jSgwAah/A1VHxB3s9q50ewOvjScoXOdq3+tumJwGkrDJOBWkFiCgP4Es3wON9CPDQET+pquo2dwXDMdxyeXtrZw6Mu3xlUJ40AzhMAKfj3YFVaHqbXe8JzUBLru5B+ZVhDwL4hACuxwGor/2HVrOOpu3rQ9+Xq5Ar/zPbHGd52QuQJYAcN8DCJWaTA4/3i1nPtcLLL+4CuEkAK1EAToX07nh6YLiuFVW+EAxQIoBmnB7gibAeSFV+cRdAY6Ldbnd5AF53SD4AnU5nc/8DgHMI8TTAO0ziDKdC1BACsJwWYHTCRkUSCClkEueE9sBihjUUGGJ74Cb3QsYLUCv/A7n6jKUM1BgL+lxdZYsYS7dZtioEIEsAp0QCNOvr0IyX9iOkMQxN77AVmNUvDuBjAjjMk8zxAtDdJ/F+yRqlDyxVEACgOsmcnZE+EgdQ9k+XNd3ONsUAALjvfh44tw8BvvA8UlpW3+QFCFrqd4aQEXsISRHrSOgjpQ2RHQWI4+PDSVx77p/v6+ZOvj8CIEWsI4Pvp90P9XMh2yqzqQAaLwoB+X5tkO/nd/eAxLUQEkAGm0ZNDzyeAvAd3UHm49WyK56hWVtDY70Q6ONOQ2nyfWn+IurP/2VWvFtDGXKtTHf/W1/xrlOYJ27/5vFx7x1Mnu9LIeuIPXH/Ct1atCGmtra2NO+GbPpJGM8E9BETUEBHW3RSFCreBXFC1/W+SBtMY8O6rtP2+jEu8S6Iz94QgG0An8YS74I4YxiG5QVIlsvwQsguAPvOn00k3gVxvN/v60MAskF7MoqNaRYOAM3D2MMmBOIDcie2eXs3O9i4Dcv5E0fGsUpymykh4l0Qb9FBd9ds6J5cX2C01Q3noPuAUPEjIJMAfqV8xG+9SBLWILe5uqc/ALF/7PEVgAfkFLwHfK6DPnKX+7RNDuDdPRMeAHOINlrtH2z8CUCi3Q7asqGgz/Z39D+6hq49JKLxV06p1T2Mo9cEAAAAAElFTkSuQmCC"/></a> +<a xlink:href="https://github.com/Seamain" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Seamain"><image x="496" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/seefs001" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="seefs001"><image x="522" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/shiokiri" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="shiokiri"><image x="548" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/zanjie1999" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="zanjie1999"><image x="574" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/SpenserCai" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="SpenserCai"><image x="600" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Sudsier" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Sudsier"><image x="626" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/THMonster" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="THMonster"><image x="652" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/TeAnli" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="TeAnli"><image x="678" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/g497813927" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="g497813927"><image x="704" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/sparanoid" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="sparanoid"><image x="730" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/W1ndys" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="W1ndys"><image x="756" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Weltolk" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Weltolk"><image x="782" y="132" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEs0lEQVRogdWa33MTVRTH8yD4LjNgBx9R/GscGUcgIWnqjNCqVB9whr6JM0qVtE3q+OIfoQ/q4PTVFxQGSBps0QSEtrSlbXY3Pwtt6Mc5mw3dbnc3m+wmNTtzJpvsnnO/37N37/3ecxMKBXAArwMRYBqYAXKAUqlUtsTk3PhtxrgnLD6hgzyAI8CnwC1VVTGbpmkvP83n1vuAm8CoxOol8DeAVH17q1oqaljNCt5Kws7nRX27AiSB490Efgj4TC0/Ly+uFHAyRXF+AoqqsrTauG/JxrdQ3KwCV4BXgwZ/8oufSY9MZ3Gz4eksDxY3qJQbYM0EJNMC/tIPf3E+meWj75zjXPmFu8BbQYF/Lzb5T/ns1TROFjad5x6vUy0X9xEolzQ9y+eTs5z+6i7hced4Z6+miU3lSsApX+BrMDSYuLcd/TaDm8VM5/mFdSouBCTDkfE0sWvuMaMSN5GtL8JIR+CfwHCrBsx27pu0bjkPBCT77cS+D6Ptd5tEtv5/IRBLZOvAu17BnxicyhftAHohkfdIwNztoh7aik/lysDbrcAfltFGXiK7gPIZcbPxxkvsRuBCKqu/pE6xzpnaMmOQa5d/5I4M524ExiRDVgLmgPFEhqGJWYYmMiYzvifcX2IZ+y9+f4/Baxk+cIgRdXgCQkCuA587gT+ulJ5VnAhIAAH/e3pZz/LcwzXmbWyj4DyRFRSVvx/t9517uKb/fnt+VX9Cdu9Ik8DjpzXpSgN2BFLNPupEQLIk4Lc2S3pGZby3WispIZOc1adS1tisFlldU1q0n9EJA5NW8EdE27QmkNGzJeAlm9JNrNZKzNn5KIpKUdNYWC54I7Cja6ddASiqUqZ6LwQkgHWm9WuqITXaaR/4xEzgVh8S+LMJfkDTtB0/BJz0vpPZdbFSm+2rmrYDHBMCkU4CWJ+Am95vtV5QO2wfOCMEpv0SMGfVTu8vmT7l5Q/iCSgNAkkhMBMEgb16f3af3h9OZfVJTMZ7p/XCYvsErguBB0ERaOr99y16X87PfN2Q0HMt/EfaI5ATAoXAnsBKQc982KL3Y4Y8EPkwHyyB9VC1Wn0e5BPopX+tVnvW/wQIsAv12h/pQkC+jwnkAh1GD4DA9cAmsgMikBQC4T4mcFoIHAtCzPXaX22KOUOR3uw3AsAN83pgtA8JfLxnSSklbq9LSl2MKbv6XsAUPQLw6z9vt6Q0SCS9LOpFTcoCXNawTY0vjUtWlp922z/TXNRPdFRWkQBS+pDqgSzAzbV9afz+v+u6bHYri/j1X1jbLDluTwGXWxW2pG7juD+Qyr5UnkH7R3YLW5dswRsEDn35K3fcSotudX25Zlca9OsfNQiM/cRt19Ki3+Ku271+/eON4u5JV/AmEqfaLa9302KN8vo7oXaOVbhw0MCjDdvZgA9DnRxVj1tM3cz8ExgO+TlkZySezJVc9wW6YPFUvth2t3Eh8aZsLuyt53fPxhqjzYlAwJtIvCIb3TKR2O0LBGGPVirNje7DgYK3EBkApkSP2O0PdGI0tM1kT/8AYvzZ4yLwh2hz27q/ixl6/oaUyYHXegbcgcxRKbQaf9j4DWRrl4KUbMTk3PhNrsk9cu/RIBr/D5MtcQehzHEAAAAAAElFTkSuQmCC"/></a> +<a xlink:href="https://github.com/winsrewu" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="winsrewu"><image x="808" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/yixuan" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="yixuan"><image x="834" y="132" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/lzcapp" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="lzcapp"><image x="2" y="158" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Lightning-Lion" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Lightning-Lion"><image x="28" y="158" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/LordPenguin666" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="LordPenguin666"><image x="54" y="158" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Majjcom" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Majjcom"><image x="80" y="158" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/EvanHsieh0415" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="EvanHsieh0415"><image x="106" y="158" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Map987" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Map987"><image x="132" y="158" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEJElEQVRogdWazU8bVxTFWTTpvpGSonSZNvlrqkSRWiWrSkVAjJ2qJVJZVV20ygZK+GdaseXLbihulgljE6mCYBTjebbHDv4Qv+raYzxjzzdjO1g6whrmvXvOfc/3nfdmpqZi+ACfA4+BNWAd0ICSYRhNgXw3r62b9zySNlOT/AA3gKfArlKKKABeAinpa5zEvwBeNBqNWlTig2g2mwawCtweJfFrwA+tVqMqQXVdj4W8svTVaJzVgF+BT+Mmf9dg5VXmYImTokZZGeh6KWYBFYqlI3bf/oLB8r/AV3GRf/jPu4XqhjbDVi5Bofh6hAIO2cn/yIb2PXvHyQrw4LLkv0u/XWgJ8U1tnu3cUwrFNyMdgXT+GZvabCdZOwcLbWA+Kvm5rdwTetjU5tjOpcYo4MkFoJ4KS/6hqP9YBOwcJGQk7gclfydbSJZlCPud9KbQOAUkbPH33qWqwD0/8tel2sgPVghL1ruQ77Ns55IjFnBIOr+IW/wqv2elnHsJWJJSKYrlBysZ7yPZqRCF4v5IRyDjEx945kb+drN5Zkidl1IpmR7GPiW9aAkapwDVSYpf/Gbrg0ylaScBL6QTya4X4iavBkQEiQ+sDJK/Id5GOpEseEMf4QjogeKb3qlvAMVVxp3RUQNYsArYvYIC/u6Rn1ZKnfeH0B+DU8g+BcbTXil1DtwSAY/tHVZ84Dz/J9Ee+FYErFkzILVYFpTuXyu613r13y2D42wPrIqA9UE/LguGLOl2LOK2H5hUe+BPEZB38uOydFvhtR+YVHtAEwGnQcyU135gUu2B91O1Wq3hZ2f97PSk2tfr9bOrL4BQU2icAhK+8TtTCMgF9eNu+4H4BByGit/7EdvKaJT9QJwjkAkRv1dG18L4caf9QDwCVOj4vYXskbWTKPuBywpQEeMD34iAW3YzF34/EN8I6IHjX5g505G+vIy1jWMEVHg7nbbuB1JXUEDCtqWUbVpQPz4MIVM2y6CfAPEy1YvpoEfA0JbSFLEazI87odzJ6mnp2FeAVJlK+UOnjYoUq5P9ZZdjlYbh7se9cNghf1Lc7yxE7gKSHL1/xal+EilGsXREu92suD6eAn529+NBsGiSnXcQ0L2Wzv8Uue/MwZJkf9GRvCngWp3lrJMfD475IRHWa1H73dBmMPhtz/No0f1wNxy8RiAaEr3D3bue5C0iHgwer08SO93j9a8DkbeImJ008a0uZMWdCUV++BHTRDM/F4m8RcT97HGq0vfm40G2kCqHnjYeIr40eJ61+/PRocZzqTZ3YiFvEfGJPOiuNY4qzl798qjU/+s96L4eK/kBIdPAH+0Whp93D4p2C/E2K2N9AcR82SMJZJTSz/19vB3SBkjLMTnw2diIu4i5KQet5gsbfwGv5bRDjmwE8t28Jv+Te+Tem3EE/x+Xpui3E+PDbgAAAABJRU5ErkJggg=="/></a> +<a xlink:href="https://github.com/Marcus-zh" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Marcus-zh"><image x="158" y="158" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/WindowsMEMZ" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="WindowsMEMZ"><image x="184" y="158" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/MidnightCrowing" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="MidnightCrowing"><image x="210" y="158" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAZj0lEQVRogcWaeVBc15m3LzT7vjfQzQ7N2jRLAw00OzTQ0OyLWMQmEEgsYgdJIFYBQmzaZa2WtS+WrcWSJUuWvC+SbSl2LPuTE09mkknFsZMvtpOJE39+psBTmZqazNRkJpPvV/VW3fvHrfv8zjnvue855wrCX0Em8hlnIXx3pSh8cYd1yOANq+ANj4XQ3l8Jir4/mKtH/iBS9P/KNW3XYyFk/IZT0bkddqUHK4wz1zsL/z9lHNJjbxw80GEYsOmeUegUouidGCrnsJT3Yx7Ujp68FyF8EOvkCXwLd2IavgFP3RKK9dewK96Ha+kIYWt3vh1cd6Ldr/qi/d8MXOS3QSry71oyDOz5rUHgAMbyUYwipzCOX8AqdQFp2gzuKVtxVE9jFTeBU/Ys7nkjaFpn2PPiJ+imbyBrPIa67RwJrWcJbzyFf93pr/3qLiwGtlyX/O+Re3cYCj4bNgg+XV8Jfj0I/r0I/v0YKccRKUfRj5vEOn0GT90CAflL+GUu4JoyhWPWNC7aHnZfvskbv/gl2aNH8K9dIqRoibT154lou4BX0yk8mp7Gv/P2bwP7Xhn163jB+K/Kri/r9deT9T1YBhZk/Qh+fQh+AwiyXgR5D0JkD0LMAPqxGzFPHEaatZWYskVSGw4T236W5n13uH7/Dc7cepaKbftQb1igsGMvT9z+NXHjt3Dpu4pN6yUcO68j6biJZN2l92StF2R/HXqfnmLBt+8rwX8jQuCm7yNgM0LA8nUfgqwFIaYXw5QRRAlDiBI34Vs8TePoaebOPSCq5Shrd95gdtcCM4vDpLd1oOke5sTzL3Hr8a8JHTyJU88FnDacx6/vMsqNV1H3nUPTdfDL4u6Fwv8ZvKy/TvAb+KMQOIRe2DiGUdOYqGYxjtu+EqL4KYTYjYgyxrHN3YmDbifOZbtI6HqCkQMnOXHnbRI6D1I2fILjR5/kndeep6yni+Fj+/j0i7e4+fA6MT3bkXUeRt62n+TO/azedIBN43tYmNzKwbHuby/OtrT89+ADBpuFoCGEsEmMomexTN6BU/Z+JAVHcC8+ikfpUSSlR7ArPYR14UEcco8iLTlGYPNTaIb20rGtn407h8kanGPd/Ek+vv8K333+Id3Tgxy/e4LrL4xy4bkp1u44QO7oaZKatpFW1ktTwwB7hyd4efc0Hx8a5ufHOvj8ZHP7Xwbvv7FYCJv4Vj96G6KYWWwy9qAXPY5d1hKO2gVkVYeRFi3hXn4I28KzeNa9jLTwOpLC03jV7SFjaIJn7x9k7EA9yZ0NnL3/Gj97/xnevTbDySs7mTsyyKnDDbz50i66p+Yp79rJ6rZ5CvNaWZ1RRZemgBub+viHveP87sQInx9o/fanB5sL/kvsBjGzvqKY2d8I8hEEz05EqimE6FFEqk3YacYJrtmFReIGgqqmSOo9g2/jRVwrLyMpvEJI3VVcS6aYvPoi1x+cYuvB9RQPdzFzfDd7x7S8dm4NV24Nc+pyL1/+9DA/eGk7W7ePUVLXgVZXR3FOHQ3aOpoSC9isKWBam82jXVPcHGxgXBP6ldZFFPCf04eOGgmK8QdC5CRC9Fb0YicR/FqxzRjDNXcEsaYTN20rqW1bmb/yJiGVXXjVjeHesAO3soME150iuecMu25+TM/4VsYXFoguWEfnyCSfvDrFlx8N8OBRJ+8/7uenD/v4/MN5Xn/5EJPbN5NfUkBqqhZlWApxYdnEB2tICEwlJyKTisR88qLTCfeQv+vjojD8jw2ETw4KoSMIocMIqomVed0xawxBVoJrRjM+2TW0zO7ixqNHlHe30rRtGt3UPuQbdiKrP4yrbg5Nz2F6d59nYGobN159ncb+Od794AF/f3+CLx+38s0fJvj0J7380yfb+eqD3bx3dxvXn51icXsn3d0txKrTUCiz8PXX4OufhYtzHMEBmSTGVpCcUI1CXtT75+GV0xKjpKWvzdN3YZQ4gxDZhyBvxjWjG9fEGop7xjn/2qtcv/8CL757ieuvHOWdnz4gb2g3spp9RLddQ1F/hNjabradeYJ3f36XOw/Psmmunx88eobHb3Twu083wB8Xef/Nfh6en+KNA5v5+gd7+OzhIo9e28NL1w7Q0lRNuDIesTQMv+AMvGUpiF0ikDhHEuSfSpBf+leO1pEu/47fUL20ZJm+G6u0RcyTJ3HIGMVHN0x46QDbTl3jjR895tLd8zz46BJvvL2HV14e58OfXCdxbTeFU8+TOniXlO4L1Ixt5d1fvM4XvMuhS/1ceH4nL9xc4FcfzfPFB4O8eKWcs/uLuLmjhx89s5//c3WC5/bV8/S+bq6d3k13WxseXqGITL1w803B2CIIQ1MZpmYyHOwj8JQm4e6aNv9vE1e9aG+Vse+3tprdmCfNYJ82QUzDPmq3XuD5R5/z4vsfcfveTT7+9AaPfniI1273wldHOXO+hYWrhxm7eQ913wVCaxbYfu4kr3xyldsfH+LIc8OcOLODH771Aq+fn+eL9w7z+M0JnjtWyc9emubFfR2syVSg8pWQHB5NZWEDOu06bOxiEfRCMTCJwtQiBktrFcamYQhCIIIgRzBO/NrAKvdfC0CThPkOi7S9OOkOIy09gF/VPlI2HKdm6wVWDc1R0NHBxIElnry8n65NOTz9TCef/eNhPvvyOnc/+xDNxB48G/YS2LDIwReu0T1dx8a5EobnqxnbOsCtK1c5MjvGUL2GE9tLeevZDh5e6eOdq9vprqtGHZaOlyQGU+MQLK3UCKJozG0zMDBLxMBMjYGJCpFxzMq1oXU6htZa9KzzWv9kwDZp7p5L4Rls8o6hp5nGsmAa9/IFIpoXiesconR2gdSBaSIbu8keaGf/iye5++gm9/7xEeOX3yKk4wgu607h3ryTsi1bKGrI4MChVt56+0nyqvPpHBri4P5dfPrOdR7f2M6ja6PcOjtCT2sZjfVtFBdvQBmzCgfXREQWMehbxqNvk4JglYRglohgkYieZRL6Fsv3CQjG8eiZJLy1Ai/NnnMxV898Z5x6CFPdU7g1HCek4yk8S6aQajsIWNVAx1NPE9m+i+iuw2inniJndCexdV2UD+1Fvf4gsrqjSNadxaFqmt4njnL60hM8ePkgl0+Ok19dyuyhJzl5+hSXj+3gnWObuDixCl2clKryXBIT8omIKsNblo2VUzz65koE8xgES/X3BkzVCObLJpIRzBMQTGIRjKIRGUd/Z2ASJRaMshcrbUqO4lB5GZPcY9joFpDkbCYgfR1FjUO0j2yjY+YJLMObcNMu4FW8H8/iPchKdhK7POtU7Se65iARHU+jajvIrrNXuXj+AHfOzHBh3xCp6WnsO3KGXfM7ODw+wKfnZnlpexPpMitiQ3zxkYbi4hyDo2MMNnYqTK2i0TOLQjBXIVglIJirESwSvjdjoUbfLBZ90xgMTaMxMY8uFwxXHdphWP4kQuFphMwDiEv24V80QlppK9Pbd/PCrbss7T2FKmsjHnEjGAdtRnBai2BfiWCdR0zuVsJyxlHWH6Jq8lmu3LnH5TOHeO3cIj+5d5X6uiaOnbjC5KYJntk5xyvzXRxrzWbb2iIaC3PwcQrAyToUO0s59nbKFRMmllHom0evDKUVaKtERDYJGFgnYGQZj4lFLOZWsVjaxC4Kwqo9N4SyfQilJxFKTiKuPIZLVj+hGTlsGu3lwN7tnD52ku1z50jK7Cc2bRQ7SQmC4IOrWyKC4IeFWw4+6QMUdO7jxIXrnH/qCU4tbeT03ilm5ncxPLmbmlUNnJib4dnx9SzVptBTkow60IcQSTDu1iHYm8iwt5DjZBeDnW0sZpYqDMxjEJnHom8Zh8gqHgNLFYYW0SsGLWyisbJTXROE4oUfCaW7Ma49i031GXwrn0RZNkTVmhKOH+zn3dvHuH/zIh8+/IhNW55AkzeMXNWEmZ0/5rZe2DpFYyPVIIgzEayjcfUKJ0qhoDonhY2drVSu7SezvIOcvFpaa9fwwr5tfP76JUaaq4j29SVEHIDMTo7EPACxWQCuNpFIxGrs7eIwNotCzygMwTgcPRMleiYR6BsrMDBVYGoZgYVN1GPBqmTxC8PsGSyyFhBrZsltfIq9+y9x77k5fnV/jl+8spMHV3bxyQdvcOH5V4kr24J6zQKS7AoEKwmClQJDm0RE0iLMvAswcwzHzEKCl9SHOHU28QXtpFaPkL2qD7FzEEovH7a2txLpH4ydkR0B9jKUrpFESlXInCLxcVThK03BzTkZM4tIBFEIgkEIgqECwVC+EvrGcozNwzC3jvilYKPs/kaWvY241cfwiR8jRNnHpg2L3D4+yo9ujvLrt5/k25+8zoN3XuTZO68SVzGItmcXcc1tRJZV4uqXgliShZFTNoJNCiLTYMRiBV7ukdiLwzDzzECwj0fkGIutOBw3O09WZRVRnFOJLrWYABsZaf6JZIfnEOuXQqhbEqHeGnzd07FeTmhRCHoG34Mvh55RCCKT0H/pgcjfC8Gyum9cXEqRKXpx9+9F6tWHl2c1DRXVTPQ3MT0wwPSWCcanZ9k8s4Pa9mmaeyeZXhqmvbOWrJRivFySUYTVYO+QjIt9DHbGfiiD0jA38UNkG41gF4eJUyyW9nK8XYIoTCsi2DsKVXASaUHJBJr7oHSNIjMsl0BnFeaCN6aiQIwN5YgMQxEZhSMyicDANBwL2xhcPTKQBeUTrCj5vZCZuuULZXQPPvJuHHw34Ow7iIO0ipDgBFLi4ynWFJCbrKWqopLVq6tY17ie43uXeO/6Hh5c2cHzRw/SXFBHsiKVDGUm6fIEkvyVZEbEkxgejyI0ES//GKSeIbi6eODt5ESwRIK1IMJWMCPI2psM/yR0kXmkBmcR4ZWCt1McdhYRGBuFIjIIQ9BXrJQWgmh5+CgwMo9cTmDsxQm/FDxSpz7xz9uBR+48sqIdBGVvIyylHXVsKtXZqWysLmOsvownpzaw2FfNfEcFN/cM8vBIFz8+t4nfvX2SW3sGmVubz/Udm7i9Y5A3D41xabaVFw4N88O7xxnpKkHpb0ygREDpKeBlKhDpKqAJkSAzd6BElU9hbDFR3olE+KTj65qEpUkY5pbRGJvFIBgu50I4gnEUglEEgv73ZgxMwx8LypqdNxSrFwioniS2dYHgog2klq9Hl5NHpSaBpgwVs82FnJlt4dxsPc/tbOEHpzbyD6f7+NmpLn53Z5pvXp/nx2d7+PLmNL+6vIU/vDTLRydaefx0Nz+/u5XP7i/w0pkWjm3L5uaxet4418H717Yw0ZRGljwCTagGlW8Scrc4/KWJ2JmFYyQKxUGcivFybWQcjWCswtg6EWPLBAQjJYJBOEZmMdeEczfu7hiYXaB6aCPrFyYp6KynbbyPdeuaSY5QMNm1hltnlrh0bIQ7F8f54PY2fnh5iJ9dGue9XfU8PtHIb+8M8NnFFj45WM5nJxv47kY//+/WINyfgPuj/PHhCD97uYv/+3CMb/9uL3//2gj/9NE+bh3toy5TS5g0Ci/bEIKkCUjsVVibRWBjm4CdUwZGK/VQ/EodZGqvwcw2A5G5Gj3jGAzN4xeF42cuVEwuzLNwaj9P37vEqZeOcOe9qzx/+TJjHd301hTz/p1TvPnCE3x47zB/93Avrz/dx48vz/PegUHeP9rOB4fW8Oa0jovNCl4ZTOFuXyJvjmXzYKmIn55t4quXBvnlK5v5/aOdfPvpcX5+fw/3nt5MVbI32ig1XrbBSKxC8HCMwdY8HEeHRFzdtIhMYzF3zMJcnIOVOA8rZx0WTjkrJowskper1TIhOa9PXNA48l3P0n4Wnz7Gs2+e4cVXz3Hr1GWODW9nd0cTX//gOj9/cJGP7x3hh/cWuHysnau7Rrk0NcKBttXsX1PIkdU5HClN50ZrDc+31XC7v5E7w02caNEwnhfIxrxgLi52cnphkMmOOlp06YSJXQmRyPEVh+PpGIWznRJ7WxWOTqkrrW9gkYCtWyFi3wqcfaqwkRRjJS7A2jkfc7vs7/RMEsUrFWlhw7a3M+v6UZeU0T89QG9/K2t0DZRH5bGpvIpT28YYaa9ndWky/T0lbFhfQklGLrpoLbVpRbRlldCdnk9Xgpb+1HxGcysYKahkMKeAynAFlVEKilXh1GRrCHXzIcJbTmKgiiBJKB4uUQQGaPH0TEfskoybZw5Wdsvfk3hcPMuwcSlA6leDxHf1CryZfS52zkWY22vf+NN6ICOvtT2zqIVUXS1JmjISU0pIjC0nXlmGKrwAX48E5KG5qFNq8A7JxEIcg51Eg7t3If7+Ovy80vF1T8bPIwWZZyre7km4SeNxc4vB20eFi2sI7m5y5CFqIsNSCPCNwsMpECeHECycE7H2ysdJVo5rQAVu/tW4+Vbh5FyIqXk61tY5WFhkYWWTg6O4AAeXQqwcc5dj/Z8MlFYN2+uK+75O1rQQl9REYto60rO7yMwZJDa5A1loLb7BtYSo2giK6cBd0Yy9Tw0WLgU4uWhwk6bj7pmNm7cWia8OF1kBTgEFOPjnY+2ThY13Fjaeqdh4JOPsmY6Xfzay4By8QwpwjWjAK6mHYM1mApP78YpYj4tf7Uorm1pl4exaiqu0HG/fWgLkTfgGN+DkUfa1mWPOvz1TUGs2L0Yl9RKT0k9G7jiFq+YoX72D+JQ+UrOGSEgbIDK2HblyPYGRLYSq2klL7yUnppp8ZTEpITmEeiTj555McGABCmU1IaoGfKPWIE/tQp7Wh0f0elxCm5CENeMU3Ii5VyXuCT34aTYj02xEEt2KhU8F+o469Oy0GNhoEQyTEAzUCEaJCGapCBZpCCZJc/9uVyIsd14SnTf3tbpojoxVS2grF9CVz5BdMERWTi/x8bUkJdZQXtRNka6VVHUZeeoSunW1jJWuZayynb7SNprz11GWuZY45SqkHlmExDSiTB8gNm8CpW4KeeYkfimjuEYPYBm8DitFEzbKFhyiWrANb8TUvwp9tyIEp1wE+2xMPEoxcClAsM9BsMlAME/7UjBL+vPHU5K8+QFP3RQBeSPItd0o0tdQ3tBPV88IO2a2c+30U9y/dp6rT8zw5Fg7V+eHONndwTODm7k8tpVLM0tcWjzMmcWnWNiyn67128jSdpKY2YlauxF1wTgxuRMEJA7gGtmGU9g6zILrMFeswTG2HZ/MzQTljeOt2YRt1DoMZVUILnkI0iL0Pcsw8irD2HNVz5/f2Fo2ULxk6Fe28K5qzRKZ6xYpWL+VwroeNo/McO7ECW4/c4rDU/205MbQlBbEtsYiri0t8tTIFDMtPfRWNtNc0szqwmYKdS2kZ7agK99MUuFGkkrGyKxdJKliDv/UARzDmrCWr0Ea34VjdCv2Ma14pA0QmDdOQMEE3tphpOkDCK46BEk+gms+gmPuO4JY959sLQqC4JLY6xuoHf5NZNEosUWb0VaPoinuYVXNIBs6J+ls28y6mjbWVbXQUttJpKqUgKhyAlSVKFKakKetxzu+EdeYelzimrFW1uOkbsVXuxl56RRhZdP467bgnt6HJKkLcVQrtoomLILrsZA3rPSGWUQTDuoNuGVuxDtnBHfNJuyiWr/S96nwF/4r8s8aKnRP7PrWMXwNHtEt2HgX4eibj1dQMe7eWXgvh3saJhYRmHvnIXjqEPkVY6aoRhS4CsE5E8FZg+BXvLKvah5et2LEOLAMA78CrELLcY6qxTWqAcEhCyO3YmwC67GTN2LoW/l9i3uVYhragJ6sCoPAmm8N/KryhL9EjnFda60VLVgGNWIf0ogkpBGPoDr8g2oJCKjGx70ER7F2ZQ7Xk2YjiNMRXDPRd9OiJ81EzyUDPefUlbWAvV8OUWlrySzsJTm7BVVCFcEKLY6SBCycszB0yEF/OUkdc9FzzkNPWoip/2psw9Yuz1LfOUe3NQr/HdknDNRZha/7o1N4C1J5PZ7+VQTIygnzLyPSp4hAz3zE3gXY+ZZg71e60lPG4iwE62QM7FKwdMnG1DYJM9sEnFxSkbpn4OWVQUR4MRkpDaSmtmBilYyBdQbGdlmYifMwdc7H0LkAI0kRFl6V31r5rm4W/ieSZPQWyNLav1TE1xMRXkhcUAbpQWnogpLRhGTj552Pm28lUp9KXDzLsXQqxNAqG2NrHdbiMuxcK7BxKsHBdRVitypcPasJDm9FldRPlLoHY6t0zGwzsXXOW3le7FmOrWsxls4Fv7FyLv7Lhs1/pMjSCT91/sC7CSmNJMeUoInQoVNkkhWaQ0xQKTLPAtzFWtxddfh6lOPjWYGntAKpawUuLhWInSvw9GrER7YOD9+1uPuswUlShcg0YwXe0lGDoyQfqXcZ7l6rcJEWv+PkXOj7V4H/k4nyPQbKvG0blGlDX0apu4mKWodKUU16ZCkJsjQi3RNQeWtIDiokJaQcdfAqYgMrifRbhdyzjBCfSkL8qpB5la+Eh7QQs+Ua3zYZo+VhZpeGnWPWbx0cc0YdHLRGwv+WFIULLpG6qYWIzNGvoxPbSYsrJ1uVg1aVR05sMZnKApIV+SQpikmNrCRFWYtKvgplcBnhQWWEyIoIDy5HEVKOu5cWM3EKhg5JXxvZJsyb2ST/7X4AUVWO2McVd7cl5TW9qclb811uSSuF5RvIKWwlKb2emLgqlKoqguQF+Phr8QvIwcsvC4lnMu4+acuHF99ZusS+YemlaTVzy7D7m4H/OeXU9zvlNWwsr2jfuljXOXu9pHHLRwk5rV/I4yq/8Y8o+sY9SPuFu7/mI2evxOt2EtWis7e6XBqY4vTXePk/AwHmPiA+kNXxAAAAAElFTkSuQmCC"/></a> +<a xlink:href="https://github.com/Naptie" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Naptie"><image x="236" y="158" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/NoahCodeGG" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="NoahCodeGG"><image x="262" y="158" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/OPPO9008" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="OPPO9008"><image x="288" y="158" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHklEQVRogdVaUW/bVBjtA4x3Jm1U47Ewfg3aNAm0Pe0BMQQrPIAEj7ywZl2yJoNKiP/Ayx6G+gsGmzaGRBunLm2yDto0tmM7SUnitAd913ZyE1/72rFT2khHsRx/vufc6/vdcz9nbi6DD4C3ANwAUAKwBkAFYLTb7T6Bjr1za9411ylm7v/8ADgP4HMAT5vNJkzTBH3HgX8tgCcAFuleJ0n8bQDFXq/XISI+fGKmaUnAX2sy9Pv9NoAVAJdmSfx1AF84Tr81SYLvVcPYh6HvhaLZNAIimt4xdQqAbwG8kTX5y8DDF6qyCk2rwjRbAgIWI7+1+RM2y0WoyvfYVB4wqPRdLiFuPPDwdwDvZkX+2m71fktZv4PKxj1oje1wAvoeI6/8+R2U9RyU9SUPdJws/lVtxQZwNS35m1uVvFPZWIayfheVjQK0xk4kAep5IkxkKc7HNPGqkh8A+GRa8rfEBCQ9qDxgvc7Hpo0HsJiU/DVSf1oEqO5IXIlLfuHvWtHKkkCSeJXF5wLxu9ViC8B7MvLnKNvQhKMGx0E3zc9+BMolhLUP/Pyc0nmUgG8o1bkTsDCBPMsQskmYfgRWI9sH8FUY+Uv9fq9NeZoaIaLuN48dNJt6yEKUVoDJFjlZ+47TpUdpXiSg6N6wJUHQCqQVYI7dU94+gMIk+fO0jCc1Y9mPQDMWPO80MoDkKvneSIosRsBMCACf8QKenkEBv/nk503TPJYTjB7i5AKM2I9oCI4BXCQBN+L3cpTfb8Ew6nIBWhWW1Ym4lxl7dAB8SAJKcclH+n2jDq1R9RaiXIiAPA7qCgzjALr+T+z9QoSAFRKwFvsZH/P7rtcfQ7nEkRUJWGbXBOKUEXRtN/YcAfCIBPwVT4DN+fU7E36f9/13AyL4c+K4pSE0rZZEgEoC9EQChmZr3O+Lelt2riKApr1MIqAx1+l0etMJWM4Uimfakgg4PDzsnn0BAHR5nqfMYLHMEUfAtI+QwgTQHLBjrRPsEQKwFczz9gQsmFbbzfMsTS4J/PoI0ZM4CjmWhdx1QsSDMOLqT+I1WZ5nOZvl+R2oyg8hft317PIRyIfEFthvjQM19jrhp9GSKM+LcjyRr+//wYY54NW1KlukZAvZ/v4LFt8QxpexVfkxov1Vtlj6c8RfyK4H6zJ+nudB9uAea9yy/vWGc+TTadip5+RWQhJfLnF1JUH7nBkE8AEJuOiauclNdVhdZ1swydxhHU3ycAENSbwqbd/d0g7NnOdIn8yyLDKLeACP+f3A4hkU8OnYltJxBu00fj7tfsAci89FxjvO8fiW0hOxMkkgmNej/Hza/UArEC9sv7FNvZ8XllW6XbstugFf2KJUJ8zTafcDBh8f3n63e2CHvp4C8DWthCzPay851NgKSYuMm6dLs9kPlEs4qG9A118JOLgA8KWQPPcW5nmwFmNzeVpU/0+7H8gNj4m8ZR0G1glv4j6LLC16IhaOjo4suZmb1X6gJjRzjuOQgsuR5DkRV23bHpwWO23bNpXX349FnhPx8SkRcAzgo0TkORE3W62WcxICKsP9wEiA1/O3piLPibgyGAzs0aZevh+YHrmhAJqHiR+bCBHvUHaKrt9ngbyfKinbLGRCnhPxGr3o7nU1O7x+nw6dzp7/ovtcpuQnhMwDuE9+RF7LjwfH9TaFE/0DiPdnj9sAfqVMEbe2z23MKbs8pjI5gDdPjHiImAtUaPX+sPELAIWqHVSyIdCxd45+o2vo2gtZNP4fcyr2Cae4H6AAAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/uselibrary" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="uselibrary"><image x="314" y="158" width="24" height="24" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAZx0lEQVRogcWad1DV17qwOYkajS1qmjH1xJaYmHaNJ4lRY8EaYyyxixUQFVDsJfauYC+AFOnSexWxFwRBOpsNu2/2hg3s9tvVPHeSP86dO/ecb86999zzPTPr7/W8s95Z8673XS4u/wRiBfubgRbbwotm25kQsy33pEoQHdA42varLfZ9KrN9a7Wpbf9Tm2hfujl3b5r5zJGH1gWnS6xvuvz/JNXo7Jdotnon2uzFcQ4HQQ4nVyw2QvR2jjVbOKSzs09p5bDMwoEaI4fu2jmYZuLUPQtH7xoIfSYQ0iQ8PqO0rj+gEPr9y8STn9vfTrHZTudYn5szrXZSHVYSnA6uOh1cttu5ZLBxtN3KYZ2VE80WLjXbOFFl4miRmTO3bZy830FEuYmQGiOXmq2cNdrZpBZMnkpjgKfOOuD/TDzbYe+c7bD4ZDgtxiynQJ7DTo7dRp7TRrbDScxzO4EOO+fNVs4arJyQ/y5vIVhtwb/cwqkCAxfKLFwpMxNbZeGawsr5Nhv7BTtbjFZ2dFjZ1mEz72o27g18YHjpnypf5LAMue20l92yW7hlF7jpEMhx2kizW7jjdHLH+ZxIm41Qh4OLHSYCJO2cazBzTWsnTCNwscpG8F0DaZUmEkra/5D//aRO2e3scT7nsM1KoMXBRaWVy08s5GyVP63eqRn8T5F/7DTNfuQ0Gh86rTx0mHlkN5FptxBlsZBjs1P822+k2K34m0xcFWxcVug5V20hsMFIlNpIboedjCaB+yIbRWIbQaI2zpitBDrtf6wzTiuX7TbCtTYibraTeV5PqZsGzWytQTFV/vP/Sr7KKSyrdBoc5U4TpU4bD5wCBU47YVaBIJsd/3YjZwwmDpmMnLI7CGm3ECy1cahG4Fy1kYSqDh5oTBRoBWJUJs5ozfgbBeLsDvKfO0hxOEnssBP/uI1rce3k+et5PFGC6tsO2j7poK1Pq9P8jsnzfySvcNo9JM9tNDosNDoFapxWihw2IuxWQp7b8LdZ2KC34m2ysNdiJcTuJFgn4K8wcFpt5bpUIFZmJLjNxIl2M0cFC1E2B0VWO0/sdh4Z7NwoNRBzXEnaRh2RHgoyl2uonmNEM8JAx7cC5pECxs8ERIOa1/+35NVO22yt0+FUOByonU7UTgcip5M0u4OjgkCAzc5uu8B2q4OdgpVjgpnzVgsBVisX7XaCrFauqtq5qrcR0mEm0mzlut3JA6uNJrMNpchE7UkZ+SNrSR0s575rO8W/GHg0u43yaR1ovjTSPsyIYbgZ5Yd6VENMTskE28x/SF7jcA5U2x36VoeTFudztE4ndU4HWVYLJ/R6jttsXLTZOWMWCNAKnNCYOGe1Eez4/Sq1E+Z0cN1qpUDSSmmrmaoWA1K9BXWrA1l2Gw27ZdR8UfN7eqB710zDcCuSD4woPzCj+tSI5ksD+rfMGN6yYPjAhOYjI83fCsgnmI2N84Sh/0/5Zqe9S7XNVvbEbKT5uQ3DcwfPHA4utLWyt8PIr61Gwi1OLkjbOC/Rs09iYIfKxFmbg2ibgwynkyy7gyKzDZXUiKCzYTI4MJdbqFleQ8lrDdT0bsfQw461h5X2N2w86d9KwwADja/qUb1lQjtYwDzcTtvnZnSfGWn5RqB5kpXKH3RUTGgrFS0ROv/dAPzLJdvcsys4/lTKfZ2BZ2YLh+u07JB3MCetFq90Nety1azIU7FXYeaYycrRZiPhJis5Fgf5Fis3bQKVdhsdehuGWwZkfjKUI1Xo3zSi62OmqrMecSczbZ2taLrYqOxipOZNE9UfGql/x4i0vxnNMAHdN2Z04220TLajmmOnca6FmmltlExSbfqb8kvv1g/4KE1k+uGWnp/ut+FTp8Prvha3dCPL4tuZH6phaYSOyeEqfo7XsOtxKyfuteMTJmd3spZj8Wp2x8g4FiunIFiObJkCxTtyLK8JWLrbcHR1YulpQ9vDTHkXEw9ebKX8T3pqOws8fVlP2Z+tFPRV8+D1Fp59rKfhezMSVwHZRDMNEw3ULbAgdhModtUaCyZI+/+XAMbdNJ52vdeOp0TAr8nMsnwdC2JMLI00szBKj1ucgbkxrYy+1MDyyDYmb33Gwh0yluyU4H2mHb9LZvzOWTnpZ6HsUyPGPmbs3axYXjRh7WLH3MOKokcH6tet3OmpJqWTjPwurdzprederzbuvqql+BM9ZaNMlI5u5/G4Vh5M11D9i5G6GUaqfzZRslRH0To5WUekp/6T/I/hin4zrmnNy3LVrH+oZVFCK4tjjKyMNrIyxsrSKDMrY0y4R5tZEymwNUpgmlcVY7xqmR/QimeggTUBHWw7buT4z83Uf2jA/KqAtZ8Ne1cBRx8H5v4W1AMEynp3kNZFzM1XtcT1ruF8p7sk9KwjrZeY/MEybo9W8cBVza1JcgrnKChYIuGuRzN3fJp4FKGgtMbAkw67qcho+Y8C0COwzXvrNSsbIi14JRjxTjOzIcnEhjgrPnF2PGMEPGIFVoQZ8I0ws+GyHo9gLYsv61l00oDXOYGNJ4xs3acl+JiZh/N1PHtTSUdfI0IvAaGXBeFtKy1DrVS800Z6Xxl57zSTNUzBxf7FxA4UE/1WFTnDGin6QUX+JBl5M1TkLJWTvVNMaZYSlcpKo8VJsclEYbOWbFXz2r8G4HNBX7wjxoJ7shn3fIGVqQKrIw2su25jXYKVNUkWpoW3MzWwjVVhAvOOKFh6Tc+yaxaWh1jwOGvE74yRQ5fNnN6vZFzPPcS+UkzrKwIdveyoe5jQ9hUwvCcger+FgveVPBhhIGOEguAR1VwZUc3pzx8T9pdaUl2bSZkjIXZNCc8yVchazYgtVkr1JgpkOrJr5Nyp0pJzR/7oD/kN4UJ/32jhN/c0I9tKnawttOCbZGF7koFNMXpWReuZHWNhbLCeGREdLE00Mz/OyOxoM/OvCSy6asAnyobv5Xa2+tYS80MDm16K5lznApp6taPqJlDyJx01PY0oXjdR078Z0fdG7o9QkP9lE9HfVRI1rp4jX5cQPlnG9WUN5IeKqGlsp95kobjDSkZ1K9fyJZwJLSc8QsS1cClXzsp/u3qx/Q0XnzjTQo90gQ2PbGy9a8I7xcC+VCdHUqxsum7CNaqdsZHtzEpoZ15mC8uLBJbk2liY4GBpmJU1QRZ+9C5lyi/5hM6UUz+4g9o3tdx4pQ5xzxZauptp6mLh0Uta7r/eQnavRspHdVAxT6DQVUPqdBUpS1UE/1RD3IY6HhW28KhaRWGljOiCaoLiK7mWJicyV8P5dDGX86SEZquJSOkgNEw/z8U733xm6307G7IsbLwusDHJzKYkExuTDfjlWZmVpMHrfhs7qwTWVDhYdMvKokQbs8+3sfpkG77HWvhxSQ6/rn9Kyehm2nuY6HhZQN7TQPtrFoS+FlpfsdDQX+DuGxqSetWQO1zO3dltZM1RkjurmbztDdwMUpB4spGr556RVNhA4l0pyWVqkp+2EHVHSmS+jBPJjWwJK+d8bBMh15pJuNYR4LLnjjl3bZwO3xgTezJsbM20siPdyq85ArsLjKwMEuETr8U1XMygy2KGHBHjukfK4i0VjJwczNgpgcz7KQzvZcmEfF1MfV8d+r42Onpb/xA3vu5A86qApr+Vig/aSehdRuFnEiI/LyVttpgMTzHpR6SEbqjiytoKIq5JSXyqIaZMw7VSJRHFjVx/qCK2QMHp5DouZEmJzJIRkaYkMacjy2VLjEm8PcHMjlQDWxKMbEkwczDFxuE0gbPZVlbvbWDGejHjD0n44Ewlr/qX8+GWDLq98yO9hy5nzLSzvDdkPVPfOcyB/tlkvN3As/5a5O9ZkLwjoHrPguxDgbIBOrLfqCZreA15i5TEr6rn2poK4k7VkhQpIiNLzK2ydvLrTSRWaIl9qCTynpzwIglJj6RklsqJvdFAcoGUzLvNZN5tIy5LK3LZGSXo9saZ2REtsDm4gxX7pSzdI2X8srus3SdjV0ALC33q2XCymV+Cn9F3eyB9lpyix6dudPnIi15TjvL6xBNMf/sKyR+LyflYSdFAOffeVfNwsJbHHyupGKWiYq6a0mVa8maKSVxXQWZIAyV31VTJDFSY7BTrrBQ1CSQ9aCUmW0VUkpzweAnXspqIvici4b6IwsdqbtyRk5ndRGx4LYmhTS0uW2Ittg2X25jtJ8HjoI4xP5cxYFgRX//YwMiZNczzqmfzEQ3uvrl07TOcvkMn8/Lbs3ipzwJ6Dt3M+3MjeXdMIK5fxXHqo0eEDK0i4Vs1yf8mIXdBDffW1nJ/sZSCaVLivqoiZkw5N7Y3krC7mqSzdeTGy0hLlRAd20jMRTmxp6RkXlWSdElC+OE6ooJEpN9Rk1GsJu2+jORbDaTeqCO3SM6NW1qry940m21TUCurD7eyaLOCFVva+GZaNX+ZVMXoBSKmu4vY4t+O64xjvPDi+3TuMpGefbx4590jjPwykrHf5PHjmNuscS3F940sDr39kL0fPCZ8ipj8xUqyF7cTP01D8ncq8lwVZM9RkDZbS9ZcNelrFGRukHJjh4acnUpSvZpIXSUjyVdC8i4ZN/xbyDmnJilESnqSipSM39NHRc4jLSk3lMQkiK0uexItOr8gPTsuW1l/zMCM5SLmemqZuLiJScvl/LRKxqY9Lbz/Zz+6vTCHIW/4882QZKZ+fYf5rk+ZNuwWUz68i+fwSnz638R3QCGnJpQRN1/KrR91FI5SkzJMRPSwZyR/VknoRyWEjawic6acG6t1FCxspXCRjvyVSvI8ZRStbyF/o5JCPzW521TkHJCTc15ObrCE3GglWXFSUtPFJOUoiElRtbhsDBEaNlwysfmimc1nBbwPmFntp8fLXcfa5Tq2rBTwc2/h3QFH6NVtE18NjWfyqFvM/v4hmydW4TuqDLdPH7Fo0A18vypixcAk9ky4Q+roJqr+0kHZiDaefKYj8ZMn3J5fS96yajJX1pA+s5qsuU3cXqrjxtJmbnpoubmhlfytarK3NlGwuYmczRJydojJPtBA6lERmZfquZEsI7tQRlaJmqQKrchl7Qlj7pI9ctz2aVl3wsKyrc14bmxj43ozXp4CHu4G1q1vZfS4LPq9sosPBvgz+usU5nx3i5SJeq6MlnFqppTNU8rYPOEO677IYOOIXJK/b6B6cAe3P5CT84WU9BFickfXkj/nGYWra8heUkbZRSklCUoeRKq5eU5B3mE5N84pKYrSUBAqJ/eqlIJgBfnBSm5Gq8mOEJMV30hWjoTkexJiyhRZLh4nTGfWBOhZsUfH6u0GFnvpWeFhwN29g1UeHXiu0fPxoDAGDvDnwzeP8+XgcMZ+nsrSsY85M1pJ0LgW9ox6xp4pdWz/8RG+E/NYOzYT/2/vc/tjOaXD2rjzeQtpQxrJHqYk5wclWYvrubWvmZTtjaQcqCb/bCN5xxvI3d1Azj4xaf4NpF4Qk31FTMFVGQWhCtLDxWSnKsiPl5CXKCYjp4G0m7IAl3VHrQs2HLKy5aCD9ZvMrPO2sXGdwLY1At7L2tm4Qs8Pn6Uz8oMI/tznHMPfjeCH4RnMGHkT30kiAn5q4dextWyc/IStK5/hveQW3m4FHJx8n9tjNJR/pqfyYzMPPtJw63MNt2dryF3dSMH2ZpLXy0jwkZB7SMWtYy0U7FSQt09F1BEp506KCTncRPQBERmnpMRcqCfpupQbKWpuJCvJSm4iP0fxi8uO9ZY3fvW0/rZ7jYVdHja2rbLz62o7u1ZY2L7CjM98Fd5uYlbOFzFlzBNcv33I+K9vMXtMCVtcpRyY0cKhGXJ2La5m9eInLJtfyKIlOWxb9pCw0WLufm6kdpCFmiE67o1UUjRHTaFHK/mrmkl3kxO3WELSWhnxXmJu7mwjfm0jl7ZJWOl5jw2bSzh1sJrgQ3VEnhITe1lEZqScolgNBZHK326kad/4oyI9stT2eO8SC/vd7OxcbGHXchs7l9nYvtLK8p80jBnxhDHf1vDdyArGj65k0rgyRn1TgNuYx/hNqeP0LAVBn1bhM/Q2C6bcYeLURLx9Mzmx4hlhEyXc+0RJ0791UPuzjnuz9GRP15Ht1kyWu5r05c2kLFMR6yYlYqmIyHVSAteLOO1Xz8lt1VzeX0f4YSnRR5uIPSEi3r+J9AAVCceaHvz1PXBuiXn94QUWDi6wcdjNyc6FFrYttuC31Ma8GVUsWvoI12mPGTo8mo+HRzHmm3xGf5rCL1/nsGBoIss+ziLw0yrCB1Wy5esi1k3NJCFQREGkgQT/Vh74tFM32kjZFwaKvm0n4wct+Ut0xC9uImx2JSluEhIW1HF9mYjQVRUEb6glZKuIyL2NxOwXkXhQTuIhKcmHmkjZLyVxu4Ssw81e/9GN8LH1O7zaatq1wMCu+WZ2u1nxmKlk7VIFvhsb2HtWwt7LjfidLGXrkTts2pBH2Lwyto+NI31/CSfX3mT7wusUHGkg1quC0C1PCT9UTsyhBhJ2K0hapeX+ZIHiEQLx7zVx+b1qQj6vIGq8iKhfaklaXUviyjqSVjWQ4tXI9Q31xGwTk3CgkeQjTSQfkJC4T0Ly3ibS90pJ3SQzZW/X/OeZwiZfS4Cfp5lF01X4rTaxakkTixdVsH6jhOVrq1jtV8WoGTFMmH2FHXtSuXtcTOMFHXVFHTx7KlBwW0P8NRFpQTJC95aw3z0L/7W3iNlSRby7isTJWmIHKrneX0XaR1rSvlKSNUFB6pxGYtyqiPGuJ9JLRPI6CZFrawjxriVmt5iE/WIyDkr+CCJiYwVpuxvI3yc/+V+6Ett2tw7YtrnNtNa9BV8fDVt2aJg5t4gFbg+Y+FMmI8YG8cXEk/yyKpH1CxPYOzWRgkX13PRoIvukiMyIJlKuikkKEJN8VErQ6lKCllZydUUF8X4KLi2pJnismMTvZNx2bSdlpJIcVy0ZUzWEja/j3LTHXFj8lLBlVUSvE3PFvYrQjfVc39dA2lExWcfkJO9uInVXgyFnn/hvj6cOHW/dunmdCO8l9exZJ6d/X29ef82XoZ+cZuzPkYyZfBH3b5NIHy8jbmw50X95St5PEtIW15LhU0/WXhmFhzQkb2sk1qOO+EWNhE6rIXBqLUFz6gmaUU/Szypuzuwgf1wrBdN1pM1qJXaSnKhZIsLdaolwryfcQ0z46maifTVEbRaTtLeR7MONZB2Qk7ZH5ufy9zh+tLnzoR3y0j2z6wj/XsLE7idYOiCMea/F8mX/M4z4cwB7ht0nd5CezM+aufpJOVdHlpL4s4gw18ckzqshaUk16V4NZPpIiV1Sy9WpFQSNqeT6OAnxE5uIndpExkwtN6a1cnNaKxnTVWTNbSF9oYIENxFRnrVEeYsJctMQuqSDeJ92krc1k7WniZtHVSX5B1V/v7X4OwPfXzJwVK/9+qfv6Sju28ylrs9IfEXLyX6VzOkRx9qe+YT1U5P8vpGYz5o5/1EZwZ8Uc21MJZe/eULE6CdETiglYVYdCXMbiJhRRfDEMkJHV5P4XRPpU+SkzVKTN0tD4VQVNybLyZylIM+tmYxVEpK9JUT51hC0uokrs7XErTSQ5KMjfbvKmLdPMsTlH2FY13U/F/RTOJu7OSh9ycLNF01UvGKgsK+Wi93qCOgpIqBHHWGvqQkaUs+5IcWcHniboJGl+A8q4uIntwn9/DGho54SOL6EwEklREyoIHlcEynjGkiZLCFnupIbs9Tkzvi9vJaTuUhJ1molKWvlBHtXEr1FSpynlpA5rSR46J3pfpoZ/5D8X9Op13334i4CxS/aueVi50lXO486CxR1EUjtoSO6r4rYfjoC3xGz/JVIVvcKZ3PvRIIHV3J5UBUBAx9y+dPHnPvqNgEjbhD83WMSxtaTOamJrMlyEsY2ED+lkcxFarIXK8l0U5Dr3kzqGiUX3CuJ2iQhxkNKomfHb0nuulUu/xPSe3cse9zF5rj1ooO8P5nJecFIZmeBpBf1pHXTk9qng6jXlZx49Qkru0SyuvNVtnVL5dJrFZx9q4ITbz/g9OCHHB1eyKVvHxM6ooy0CY3kTlWQP7OF1JkKkucqyFgoJ2+FkuwVUrI9lVz3khHvIyfSQ+pM8FR6uPxvyO5lmZnb2WwofMlBaicLUS8KhL+gJ66rnoiXtAR1l3K+RxUHexexs2sK21/OYF/3PC69VsXlt6o43b+ck5895dxXxcSOFRE3tp6QEWUkuEpImikhYlItgd+VE/LDM1IXSMhYJSfXU0Wmt0yfuF7y30ubv0d0F+OgmG6m0tSuRhK7mQnu1M75TnLOd5EQ2EPJhT5NXOxfSdDbpZzqfYeDXfPZ3/U2Z3uVE9lXyelX6wgY+oxr46uJmVpHwBf3OTD4JoHflxM4/hmn/q2MMFc1ibObSV/RzLV5tSXxK+sGuvwz8X9B3imgk9gnqJvWENi5nQudmjng8ozjL9dwto+UgD71nOtTRmC/p1zs+oAjnYo40buYy91rCOwp5vigUpb0C2F572C2DUnn6FePOP7FQy6NLSd8eiNXJiiI/lFvjl/Qsjd2haqLy/8Vx//U1P/oC1J//24a09GeMn7tXs6e7hUc7lbBiZdLONX9PpF967jc7Rlne5dxpvtTjnUtZs1L8Sx9JZI9w24RPVvElYl1BE2WEuwqJm6WxJQ8V3sqekr7v+4DyNHusn7+b7eu29uv8eHWlx79tunFu4S+Wk90zwpCetQQ3rWJi7+fTs+n7O9SyLYXMzn45wf8+vlDzrvWk7ZM/1vIxOYHIRMNayOmt/b9l4n/Lbw6Fb6+scf9eQe6PArIfVebfb2PuPZqd5HuQvdq26lOT2wBnR/rgl+tqg0eUpEd8JeygJ2jK+adnaF7/Z+x+b8DkzFTFP8fcjEAAAAASUVORK5CYII="/></a> +<a xlink:href="https://github.com/FlorenceZh" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="FlorenceZh"><image x="340" y="158" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/Astro-Lee" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="Astro-Lee"><image x="366" y="158" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/ryuujo1573" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="ryuujo1573"><image x="392" y="158" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> +<a xlink:href="https://github.com/SK-415" class="opencollective-svg" target="_blank" rel="nofollow sponsored" id="SK-415"><image x="418" y="158" width="24" height="24" xlink:href="data:image/png;base64,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"/></a> + </svg> \ No newline at end of file diff --git a/bb-api-collect/assets/img/delete.svg b/bb-api-collect/assets/img/delete.svg new file mode 100644 index 0000000000..6901d1a9de --- /dev/null +++ b/bb-api-collect/assets/img/delete.svg @@ -0,0 +1,9 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 844 844"> +<path fill="#A0A0A0" d="M269,697V286c0-12,9.67-22,23-22c13.33,0,30,10,30,22v411c0,13.33-16.67,23-30,23 + C278.67,720,269,710.33,269,697z M391,697V286c0-27.72,50.75-29.26,54,0v411c-1.33,13.33-16.67,23-30,23 + C401.67,720,392.33,710.33,391,697z M522,697V286c0-12,9.67-22,23-22s30,10,30,22v411c0,13.33-16.67,23-30,23S522,710.33,522,697z + M644,759l40-565H164l36,549c0,20,7.33,44.33,46,47h375C634.33,790,641.33,781.67,644,759z M622,844H230 + c-54.67-2.67-82.67-39.33-84-70l-36-580H23c-12,0-23-10.67-23-24c0-13.33,9.67-30,23-30h215V55c1.33-38.67,30.33-55,61-55h246 + c13.33,0,27.33,1.33,46,24c14.67,17.33,15,27.33,15,38v78h215c13.33,0,23,16.67,23,30c0,13.33-11,24-23,24h-86l-39,597 + C694.67,807,672.67,841.33,622,844z M530,55H318c-18.67,0-27.33,11.67-26,29v56h260V84C552,65.33,539.33,55,530,55z"/> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/img/download.svg b/bb-api-collect/assets/img/download.svg new file mode 100644 index 0000000000..dca94f28de --- /dev/null +++ b/bb-api-collect/assets/img/download.svg @@ -0,0 +1,7 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> +<path fill="#1497C7" d="M512,0C366.7,3.3,245.8,53.2,149.5,149.5S3.3,366.7,0,512c3.3,145.3,53.2,266.2,149.5,362.5 + S366.7,1020.7,512,1024c145.3-3.3,266.2-53.2,362.5-149.5S1020.7,657.3,1024,512c-3.3-145.3-53.2-266.2-149.5-362.5S657.3,3.3,512,0 + z M326,463c4-4,8.7-6,14-6h81V311c0-10.7,7.3-18,18-18h146c10.7,0,18,7.3,18,18v146h81c17.3,1.3,23.7,20,13,32L524,647 + c-6.7,6.7-17.3,6.7-24,0L327,489C320.3,482.3,319.3,471,326,463z M713,731c0,10.7-8.7,19-18,19H329c-9.3,0-18-8.3-18-19v-36 + c0-10.7,7.3-18,18-18h366c10.7,0,18,7.3,18,18V731z"/> +</svg> diff --git a/bb-api-collect/assets/img/fav.svg b/bb-api-collect/assets/img/fav.svg new file mode 100644 index 0000000000..eea2122741 --- /dev/null +++ b/bb-api-collect/assets/img/fav.svg @@ -0,0 +1,6 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> +<path d="M661.53,260c-42.67-6.67-77.67-33.33-95-72l-72-151c-25.33-49.33-86.67-49.33-116,0l-68,151 + c-20,38.67-53.67,65.33-95,72l-162,25c-52,10.67-71,65.67-35,107l122,126c29.33,28,40.33,68.67,35,110l-28,175 + c-6.67,56,43.33,90,94,66l137-75c38.67-22.67,84.33-22.67,123,0l138,75c49.33,24,96.67-10,94-66l-32-175c-5.33-41.33,5.67-82,35-110 + l122-126c36-41.33,17-96.33-35-107L661.53,260z" fill="#FB7299"/> +</svg> diff --git a/bb-api-collect/assets/img/follow.svg b/bb-api-collect/assets/img/follow.svg new file mode 100644 index 0000000000..900076bdc9 --- /dev/null +++ b/bb-api-collect/assets/img/follow.svg @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 24.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 244.04 55.01" enable-background="new 0 0 244.04 55.01" xml:space="preserve"> +<path fill="#19AAD5" d="M5.39,55.01h233.26c2.98,0,5.39-2.41,5.39-5.39V5.39c0-2.98-2.41-5.39-5.39-5.39L5.39,0 + C2.41,0,0,2.41,0,5.39l0,44.22C0,52.6,2.41,55.01,5.39,55.01z"/> +<path fill="#FFFFFF" d="M79.26,24.77V8.37c0.08-1.52,1.22-2.68,2.73-2.68s2.66,1.16,2.73,2.68v16.4h16.4 + c1.52,0.08,2.68,1.22,2.68,2.73c0,1.52-1.16,2.66-2.68,2.73h-16.4v16.4c-0.08,1.52-1.22,2.68-2.73,2.68s-2.66-1.16-2.73-2.68v-16.4 + h-16.4c-1.52-0.08-2.68-1.22-2.68-2.73c0-1.52,1.16-2.66,2.68-2.73H79.26z"/> +<g> + <path fill="#FFFFFF" d="M105.14,44.25c9.46-3.33,15.11-8.12,16.93-14.37h-16.13V26.9h16.71c0.05-0.56,0.08-3.05,0.08-7.48h-14.45 + v-2.98h9.5c-2.27-2.47-4.21-4.45-5.82-5.95l2.3-2.04c2.27,2.01,4.34,3.93,6.22,5.76l-2.53,2.23h9.44c2.05-2.86,3.85-5.53,5.4-8.03 + l3.29,1.8c-1.82,2.3-3.5,4.37-5.03,6.23h10.02v2.98h-14.97c0,3.84-0.02,6.33-0.06,7.48h17.36v2.98h-16.81 + c3.1,6.57,8.94,11.07,17.52,13.51c-1.08,1.1-2.06,2.15-2.93,3.17c-8.13-3.13-13.65-7.84-16.57-14.13 + c-2.15,6.11-7.87,10.99-17.16,14.64C106.75,46.18,105.99,45.24,105.14,44.25z"/> + <path fill="#FFFFFF" d="M147.35,19.11c1.9,1.31,4.24,3.08,7.01,5.33c-0.98,1.1-1.76,1.94-2.34,2.54c-2.77-2.51-4.99-4.39-6.65-5.64 + L147.35,19.11z M150.92,30.39c1.08,0.47,2.13,0.9,3.13,1.29c-1.45,4.59-2.97,9.61-4.55,15.04l-3.41-1.17 + C147.75,41.08,149.36,36.03,150.92,30.39z M148.86,8.97c2.56,1.91,4.84,3.81,6.85,5.72c-0.9,0.89-1.69,1.68-2.38,2.39 + c-1.42-1.49-3.59-3.47-6.49-5.95L148.86,8.97z M155.15,41.67h13.3V30.55h-10.29v-2.98h10.29v-9.48h-11.4v-2.98h12.63 + c-1.24-1.94-2.51-3.72-3.8-5.33l2.61-1.64c1.77,2.04,3.17,3.84,4.2,5.4l-2.47,1.57h13.29v2.98h-11.72v9.48h10.29v2.98h-10.29v11.12 + h12.83v2.98h-29.46V41.67z"/> +</g> +</svg> diff --git a/bb-api-collect/assets/img/history.png b/bb-api-collect/assets/img/history.png new file mode 100644 index 0000000000..dc42b04222 Binary files /dev/null and b/bb-api-collect/assets/img/history.png differ diff --git a/bb-api-collect/assets/img/home.svg b/bb-api-collect/assets/img/home.svg new file mode 100644 index 0000000000..21b5eb9c80 --- /dev/null +++ b/bb-api-collect/assets/img/home.svg @@ -0,0 +1,6 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> +<path fill="#29B28A" d="M632.4,855h35c60.4,0,112-51,112-112V518c1.3-32,24-54.7,56-56h4 + c21.3,0,37.3-13,44-33c4-17.3-1-33.7-13-47l-349-349c-46.7-44-112.3-44-159,0l-349,349c-14.7,14.7-17.3,35.3-8,54 + c9.3,14.7,23.7,23,41,23h3c32,1.3,54.7,25.3,56,56v225c1.3,64,48,110.3,112,113h35c12-1.3,21.7-9,23-21c12-86.7,79-147.7,167-149 + c88,1.3,156,62.3,168,149C610.4,845.3,620.4,855,632.4,855z"/> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/img/like.svg b/bb-api-collect/assets/img/like.svg new file mode 100644 index 0000000000..cfc8cb18fe --- /dev/null +++ b/bb-api-collect/assets/img/like.svg @@ -0,0 +1,5 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> +<path d="M250,767.13v-551h4l154-189c33.33-33.33,86-36.67,122-6c18.67,18.67,30.67,43,28,71l-6,124h235 + c29.33,0,56.33,13,75,37c16,22.67,19.67,52.67,13,78l-100,328c-17.33,62.67-68.33,104-135,108H250z M193,767.13h-80 + c-61.82,4.12-110.87-48.32-113-108v-331c0-41.33,21-77.33,57-96c18.67-9.33,37.33-13.33,56-16h80V767.13z" fill="#FB7299"/> +</svg> diff --git a/bb-api-collect/assets/img/live.svg b/bb-api-collect/assets/img/live.svg new file mode 100644 index 0000000000..4bd4e557ba --- /dev/null +++ b/bb-api-collect/assets/img/live.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"><path d="M392.448 275.911111a92.416 92.416 0 1 1-184.832 0 92.416 92.416 0 0 1 184.832 0" fill="#23ADE5"></path><path d="M826.624 464.583111l-63.744 36.864v-48.64a72.206222 72.206222 0 0 0-71.68-71.936H190.72a72.192 72.192 0 0 0-71.936 71.936V748.231111a71.936 71.936 0 0 0 71.936 71.936H691.2a71.936 71.936 0 0 0 71.936-71.936v-23.808l63.488 37.888a51.2 51.2 0 0 0 76.8-44.544V508.871111a51.2 51.2 0 0 0-76.8-44.288M572.928 369.351111c79.459556 0.142222 143.985778-64.156444 144.128-143.616 0.142222-79.459556-64.156444-143.985778-143.616-144.128-79.260444-0.142222-143.701333 63.857778-144.128 143.104-0.426667 79.459556 63.644444 144.213333 143.104 144.64h0.512" fill="#48CFE5"></path><path d="M425.216 512.967111l124.16 71.936a25.6 25.6 0 0 1 0 42.496l-124.16 71.68a25.6 25.6 0 0 1-37.12-21.248V534.471111a25.6 25.6 0 0 1 37.12-21.504" fill="#FDDE80"></path></svg> \ No newline at end of file diff --git a/bb-api-collect/assets/img/loadTV.gif b/bb-api-collect/assets/img/loadTV.gif new file mode 100644 index 0000000000..33ebcd88d6 Binary files /dev/null and b/bb-api-collect/assets/img/loadTV.gif differ diff --git a/bb-api-collect/assets/img/logo.png b/bb-api-collect/assets/img/logo.png new file mode 100644 index 0000000000..57fedbddee Binary files /dev/null and b/bb-api-collect/assets/img/logo.png differ diff --git a/bb-api-collect/assets/img/logo2.jpg b/bb-api-collect/assets/img/logo2.jpg new file mode 100644 index 0000000000..199eefc2de Binary files /dev/null and b/bb-api-collect/assets/img/logo2.jpg differ diff --git a/bb-api-collect/assets/img/musicplus.svg b/bb-api-collect/assets/img/musicplus.svg new file mode 100644 index 0000000000..a32c24e081 --- /dev/null +++ b/bb-api-collect/assets/img/musicplus.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"><path d="M128 256m25.6 0l716.8 0q25.6 0 25.6 25.6l0 512q0 25.6-25.6 25.6l-716.8 0q-25.6 0-25.6-25.6l0-512q0-25.6 25.6-25.6Z" fill="#3DA9D3"></path><path d="M153.6 256h153.6v563.2H153.6a25.6 25.6 0 0 1-25.6-25.6V281.6a25.6 25.6 0 0 1 25.6-25.6zM870.4 256h-153.6v563.2h153.6a25.6 25.6 0 0 0 25.6-25.6V281.6a25.6 25.6 0 0 0-25.6-25.6z" fill="#7DD3E0"></path><path d="M768 320m15.36 0l46.08 0q15.36 0 15.36 15.36l0 20.48q0 15.36-15.36 15.36l-46.08 0q-15.36 0-15.36-15.36l0-20.48q0-15.36 15.36-15.36Z" fill="#3DA9D3"></path><path d="M768 448m15.36 0l46.08 0q15.36 0 15.36 15.36l0 20.48q0 15.36-15.36 15.36l-46.08 0q-15.36 0-15.36-15.36l0-20.48q0-15.36 15.36-15.36Z" fill="#3DA9D3"></path><path d="M768 576m15.36 0l46.08 0q15.36 0 15.36 15.36l0 20.48q0 15.36-15.36 15.36l-46.08 0q-15.36 0-15.36-15.36l0-20.48q0-15.36 15.36-15.36Z" fill="#3DA9D3"></path><path d="M768 704m15.36 0l46.08 0q15.36 0 15.36 15.36l0 20.48q0 15.36-15.36 15.36l-46.08 0q-15.36 0-15.36-15.36l0-20.48q0-15.36 15.36-15.36Z" fill="#3DA9D3"></path><path d="M576 180.736c8.7808-2.6112 15.8976-1.92 21.3504 2.0736 5.4784 3.9936 11.008 9.8304 16.64 17.4592 5.6064 7.6544 12.544 16.256 20.7616 25.856 8.2432 9.5744 19.456 18.5088 33.6896 26.7776 12.2368 7.68 22.9632 12.9536 32.2048 15.7696l25.9584 7.8592c8.2176 2.432 16.128 5.5296 23.6544 9.2672 0 0 17.7408 9.984 25.5232 20.48 8.1152 10.9056 14.8736 19.6608 16.6144 30.976 1.7152 11.3408 1.6128 21.9136-0.4608 31.6928a72.7296 72.7296 0 0 1-9.5744 24.576c-4.2752 6.5792-7.8592 9.9328-10.752 9.9328-2.8672 0.0256-5.4016-1.6128-7.6032-5.0432-2.2272-3.3792-3.84-9.984-4.864-19.7632-1.6896-15.872-6.656-27.0336-14.976-33.4592-8.32-6.4256-21.3504-9.984-39.1424-10.7264a96.0512 96.0512 0 0 1-48.9216-15.616c-12.3648-8.0384-24.064-16.9984-34.9696-26.8032-8.8832-7.3728-15.7952-9.5488-20.8896-6.2976-4.992 3.2256-7.5776 8.1152-7.7312 14.7456l-0.5632 26.752-6.7072 273.792-0.7936 35.4048c0.1536 9.856-1.664 21.1968-5.4272 33.9968-3.7888 12.8-10.6752 25.2928-20.6592 37.4528-9.9328 12.16-23.0912 23.2192-39.4752 33.2288s-36.5824 17.3568-60.5952 22.0672c-24.448 4.7616-46.4128 3.584-65.8944-3.5072-19.456-7.0912-34.3808-17.4336-44.7744-31.0272-10.24-12.928-15.4368-29.5936-14.7712-47.5136 0.6912-18.048 8.8576-36.0448 24.4736-53.9648 15.616-17.92 32.4352-31.2832 50.432-40.1152a198.8096 198.8096 0 0 1 51.8144-17.7152 178.8416 178.8416 0 0 1 44.3136-3.0208c13.0048 1.0496 22.5792 2.3808 28.7488 3.9424 0 0 6.4512-280.1664 8.2944-341.6064 0.2304-12.1088 3.584-22.3232 9.9328-30.976 6.4-8.5504 14.7712-14.208 25.1392-16.9472z m160.9216 288.1792a12.8 12.8 0 0 1 0.3584 2.9696v40.96l41.728-6.912a12.8 12.8 0 0 1 14.8992 12.5952v15.0016a12.8 12.8 0 0 1-10.7008 12.6464l-45.952 7.6288 0.0256 45.3632a12.8 12.8 0 0 1-9.8304 12.4416l-15.36 3.6608a12.8 12.8 0 0 1-15.7696-12.4416V560.64l-41.1136 6.8608a12.8 12.8 0 0 1-14.8992-12.6208v-15.0016a12.8 12.8 0 0 1 10.7008-12.6464l45.312-7.552v-44.1344a12.8 12.8 0 0 1 9.8304-12.4672l15.36-3.6352a12.8 12.8 0 0 1 15.4112 9.472z" fill="#FFD469"></path><path d="M179.2 320m15.36 0l46.08 0q15.36 0 15.36 15.36l0 20.48q0 15.36-15.36 15.36l-46.08 0q-15.36 0-15.36-15.36l0-20.48q0-15.36 15.36-15.36Z" fill="#3DA9D3"></path><path d="M179.2 448m15.36 0l46.08 0q15.36 0 15.36 15.36l0 20.48q0 15.36-15.36 15.36l-46.08 0q-15.36 0-15.36-15.36l0-20.48q0-15.36 15.36-15.36Z" fill="#3DA9D3"></path><path d="M179.2 576m15.36 0l46.08 0q15.36 0 15.36 15.36l0 20.48q0 15.36-15.36 15.36l-46.08 0q-15.36 0-15.36-15.36l0-20.48q0-15.36 15.36-15.36Z" fill="#3DA9D3"></path><path d="M179.2 704m15.36 0l46.08 0q15.36 0 15.36 15.36l0 20.48q0 15.36-15.36 15.36l-46.08 0q-15.36 0-15.36-15.36l0-20.48q0-15.36 15.36-15.36Z" fill="#3DA9D3"></path></svg> \ No newline at end of file diff --git a/bb-api-collect/assets/img/ploading.gif b/bb-api-collect/assets/img/ploading.gif new file mode 100644 index 0000000000..1a8c97d044 Binary files /dev/null and b/bb-api-collect/assets/img/ploading.gif differ diff --git a/bb-api-collect/assets/img/ranking.svg b/bb-api-collect/assets/img/ranking.svg new file mode 100644 index 0000000000..c827ff1b3a --- /dev/null +++ b/bb-api-collect/assets/img/ranking.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 770"> +<path d="M352,0h192c36,1.33,62.67,28,64,64v704H288V64C289.33,28,316,1.33,352,0z M64,256h160v512H0V320 + C1.33,284,28,257.33,64,256z M672,320h160c36,1.33,62.67,28,64,64v384H672V320z" fill="#00a1d6"/> +</svg> diff --git a/bb-api-collect/assets/img/read.svg b/bb-api-collect/assets/img/read.svg new file mode 100644 index 0000000000..8d16156881 --- /dev/null +++ b/bb-api-collect/assets/img/read.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"><path d="M778.496 142.08h-537.6a56.832 56.832 0 0 0-60.16 54.016v630.528a56.832 56.832 0 0 0 59.136 54.016h537.6a56.832 56.832 0 0 0 59.136-54.016V196.096a56.832 56.832 0 0 0-59.136-54.016z" fill="#54E2E2"></path><path d="M298.496 679.168h421.376a25.6 25.6 0 0 0 0-52.736H298.496a25.6 25.6 0 1 0 0 52.736zM719.872 732.928H298.496a25.6 25.6 0 1 0 0 52.736h421.376a25.6 25.6 0 0 0 0-52.736z" fill="#23ADE5"></path><path d="M272.128 237.056m80.128 0l314.112 0q80.128 0 80.128 80.128l0 154.368q0 80.128-80.128 80.128l-314.112 0q-80.128 0-80.128-80.128l0-154.368q0-80.128 80.128-80.128Z" fill="#23ADE5"></path><path d="M404.992 361.472m-49.408 0a49.408 49.408 0 1 0 98.816 0 49.408 49.408 0 1 0-98.816 0Z" fill="#2EC3E5"></path><path d="M375.552 551.936l120.832-144.384a44.544 44.544 0 0 1 68.352 0l120.832 144.384z" fill="#2EC3E5"></path></svg> \ No newline at end of file diff --git a/bb-api-collect/assets/img/relation.svg b/bb-api-collect/assets/img/relation.svg new file mode 100644 index 0000000000..a9e42ecd0c --- /dev/null +++ b/bb-api-collect/assets/img/relation.svg @@ -0,0 +1,10 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 953.46 738.35"> +<path fill="#9FA0A0" d="M675.64,504c106.67-2.67,186.33-78.33,189-181c-1.33-77.33-49-143.33-125-170 + c-38.96-14.98-18.21-73.06,21-61c101.33,37.33,166.67,124.33,168,231c0,88-45.33,162-116,206c49.33,18.67,93,46,131,82 + c29.48,29.48-13.97,73.03-44,46c-61.33-57.33-140-89-224-89C633.92,568,633.92,504,675.64,504z M193.64,572 + c-97.33-53.33-159.67-150-161-266c2-86.67,32.83-158.83,92.5-216.5S259.64,2,349.64,0c89.33,2,163.83,31.83,223.5,89.5 + c59.67,57.67,90.83,129.83,93.5,216.5c-1.33,116-63.33,212.67-162,266c69.33,23.33,130.67,60,184,110c27.73,30.81-14.42,74.52-45,47 + c-80-76-183.33-118-294-118s-215,42-295,118c-29.5,29.5-75.63-17.63-44-47C63.31,632,124.31,595.33,193.64,572z M349.64,548 + c72-2,131.67-25.83,179-71.5c47.33-45.67,72-102.5,74-170.5c-2-68.67-26.67-125.67-74-171c-47.33-45.33-107-69-179-71 + c-72,2-131.83,25.67-179.5,71s-72.17,102.33-73.5,171c1.33,68,25.83,124.83,73.5,170.5S277.64,546,349.64,548z"/> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/img/share.svg b/bb-api-collect/assets/img/share.svg new file mode 100644 index 0000000000..ca3b8fc8d8 --- /dev/null +++ b/bb-api-collect/assets/img/share.svg @@ -0,0 +1,5 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> +<path d="M388.29,243V55c1.33-30.67,23.33-55,54-55c13.33,0,25,4.33,35,13l378,322c29.33,25.33,29.33,71.33,0,98 + l-378,322c-22.67,18.67-57.33,15.67-76-7c-8.67-10.67-13-22.67-13-36V539c-89.33,0-160.67,17.67-214,53s-104.33,87.67-153,157 + c-5.33,6.67-19.67,9.33-21-12c-3.33-138,21.67-253.83,75-347.5S232.96,247,388.29,243z" fill="#FB7299"/> +</svg> diff --git a/bb-api-collect/assets/img/sponsorQR.jpg b/bb-api-collect/assets/img/sponsorQR.jpg new file mode 100644 index 0000000000..9178ffc1a8 Binary files /dev/null and b/bb-api-collect/assets/img/sponsorQR.jpg differ diff --git a/bb-api-collect/assets/img/sub.svg b/bb-api-collect/assets/img/sub.svg new file mode 100644 index 0000000000..907fce8cc2 --- /dev/null +++ b/bb-api-collect/assets/img/sub.svg @@ -0,0 +1,5 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> +<path fill="#EB5D47" d="M490,783.7c-58-1.3-150.3-48.3-277-141S15.3,417.4,0,244.7C2.7,127.4,77.7,32.4,191,5.7 + c114.7-24,223,28.7,275,134c52-105.3,160.3-158,275-134c113.3,26.7,188.7,121.7,190,239c-12.7,168-75.3,299.3-188,394 + S546,781.7,490,783.7z"/> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/img/tebietuijian.svg b/bb-api-collect/assets/img/tebietuijian.svg new file mode 100644 index 0000000000..4623fa613f --- /dev/null +++ b/bb-api-collect/assets/img/tebietuijian.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"><path d="M215.04 153.6h593.92c33.93024 0 61.44 27.50976 61.44 61.44v643.3792a30.72 30.72 0 0 1-45.96224 26.6752L512 706.56l-312.43776 178.5344A30.72 30.72 0 0 1 153.6 858.4192V215.04c0-33.93024 27.50976-61.44 61.44-61.44z" fill="#9696ED"></path><path d="M512 555.392l-90.05056 46.60736a19.27168 19.27168 0 0 1-27.84256-20.41856l17.12128-98.2784-72.2432-69.32992a19.27168 19.27168 0 0 1 10.61376-32.98304l100.1216-14.32064 45.05088-89.8816a19.27168 19.27168 0 0 1 34.4576 0l45.05088 89.8816 100.11648 14.32064a19.27168 19.27168 0 0 1 10.61888 32.98304l-72.2432 69.32992 17.12128 98.2784a19.27168 19.27168 0 0 1-27.84768 20.41856L512 555.392z" fill="#FFD778"></path></svg> \ No newline at end of file diff --git a/bb-api-collect/assets/img/topic.svg b/bb-api-collect/assets/img/topic.svg new file mode 100644 index 0000000000..b26e7a0b88 --- /dev/null +++ b/bb-api-collect/assets/img/topic.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"><path d="M880.64 520.448C880.64 642.56 768 742.4 627.712 742.4H409.6l-165.632 74.496-92.928-258.56a146.688 146.688 0 0 1-3.072-37.888v-37.888c0-122.112 110.592-226.56 250.112-226.56h232.704c136.448 0 249.856 104.448 249.856 226.56v37.888zM642.304 209.408h-256a280.064 280.064 0 0 0-279.04 273.152v43.776a250.88 250.88 0 0 0 3.072 46.336L215.04 878.08l183.04-90.112h244.224c153.6 0 279.04-116.48 279.04-261.632v-43.776a279.808 279.808 0 0 0-279.04-273.152z m58.112 351.744a51.2 51.2 0 0 1-51.2-51.2 55.552 55.552 0 0 1 58.112-52.48 54.528 54.528 0 0 1 51.2 55.296 57.088 57.088 0 0 1-58.112 49.408m-179.2 0a51.2 51.2 0 0 1-51.2-51.2 55.552 55.552 0 0 1 58.112-52.48 54.528 54.528 0 0 1 51.2 55.296A59.392 59.392 0 0 1 521.216 563.2m-179.2 0a51.2 51.2 0 0 1-51.2-51.2 55.552 55.552 0 0 1 58.112-52.48 54.528 54.528 0 0 1 51.2 55.296 59.648 59.648 0 0 1-58.112 49.408m279.04-270.336h-208.384c-122.112 0-224 87.296-224 188.928V512a111.36 111.36 0 0 0 3.072 31.744L267.264 768l110.592-58.112H645.12A194.048 194.048 0 0 0 842.752 512v-29.44c-2.816-104.448-102.4-191.744-223.744-191.744" fill="#8FC31F"></path></svg> \ No newline at end of file diff --git a/bb-api-collect/assets/img/toview.png b/bb-api-collect/assets/img/toview.png new file mode 100644 index 0000000000..cd1e0aebde Binary files /dev/null and b/bb-api-collect/assets/img/toview.png differ diff --git a/bb-api-collect/assets/img/trendshift_6RepoOfTheDay.svg b/bb-api-collect/assets/img/trendshift_6RepoOfTheDay.svg new file mode 100644 index 0000000000..58bc82d49e --- /dev/null +++ b/bb-api-collect/assets/img/trendshift_6RepoOfTheDay.svg @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 250 53" width="250" height="55" data-date-format="longDate"> + <rect xmlns="http://www.w3.org/2000/svg" stroke="#4a0e99" stroke-width="1" fill="#FFFFFF" x="0.5" y="0.5" width="249" height="53" rx="10"/> + <foreignObject width="198" height="17" style="font-size: 9px;color: rgb(67, 39, 135);font-family: Arial;font-weight: 400;text-align: center;letter-spacing: 0em;line-height: 1.5;" x="6" y="10" selection="true"> + <div xmlns="http://www.w3.org/1999/xhtml">GITHUB TRENDING</div> + </foreignObject> + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Слой_1" viewBox="0 0 80 80" width="48" height="45" x="10" y="8"> + <path fill="#49278e" d="M70.71,40.31C75.74,44.3,80,37.86,80,37.86s-5.64-2.17-8.55,0.61c0.59-1.62,1.02-3.31,1.28-5.01 c4.08,2.16,6.44-2.95,6.44-2.95s-4.41-0.97-6.26,1.4c0.08-0.91,0.12-1.82,0.1-2.73c-0.01-0.36-0.02-0.73-0.05-1.09 c2.96-3.68-1.73-6.99-1.73-6.99s-2.14,5.09,0.98,7.09c0.02,0.33,0.03,0.66,0.03,1c0.01,0.76-0.03,1.52-0.1,2.27 c-0.85-2.69-4.91-3.69-4.91-3.69s-0.13,5.78,4.68,5.48c-0.28,1.69-0.73,3.35-1.34,4.95c-0.19-4.03-5.79-6.33-5.79-6.33 s-1.33,7.55,5.01,8.16c-0.38,0.8-0.8,1.57-1.25,2.32c-0.56,0.95-1.21,1.84-1.89,2.71c0.97-3.99-3.96-7.72-3.96-7.72 s-3.18,6.94,2.73,9.15c-0.38,0.43-0.8,0.81-1.2,1.21c-0.21,0.2-0.43,0.38-0.64,0.58l-0.32,0.29c-0.11,0.09-0.22,0.18-0.33,0.27 l-0.67,0.54l-0.7,0.51c-0.08,0.05-0.16,0.11-0.23,0.16c1.62-3.42-2.07-7.77-2.07-7.77s-4.21,5.55,0.49,8.78 c-1.34,0.79-2.74,1.45-4.2,1.98c1.91-2.59-0.23-6.89-0.23-6.89s-4.66,3.77-1.52,7.46c-1.15,0.33-2.33,0.57-3.51,0.74 c1.46-1.68,0.55-4.83,0.55-4.83s-3.7,2.03-2.18,5c-0.52,0.03-1.05,0.07-1.57,0.06c-0.29,0-0.57,0.01-0.86,0l-0.86-0.04 c-0.85-0.06-1.7-0.15-2.54-0.28l0.68-0.27l0.42-0.17l0.41-0.19l0.82-0.38c0,0,0.01,0,0.01,0c0.39-0.18,0.55-0.65,0.37-1.03 c-0.18-0.39-0.65-0.55-1.03-0.37l-0.04,0.02l-0.77,0.37l-0.39,0.18l-0.39,0.16l-0.79,0.33l-0.8,0.29l-0.4,0.14l-0.41,0.12L40,53.6 l-0.51-0.15l-0.41-0.12l-0.4-0.14l-0.8-0.29l-0.79-0.33l-0.39-0.16l-0.39-0.18l-0.77-0.37l-0.04-0.02c0,0,0,0-0.01,0 c-0.39-0.18-0.85-0.01-1.03,0.38c-0.18,0.39-0.01,0.85,0.38,1.03l0.82,0.38l0.41,0.19l0.42,0.17l0.68,0.27 c-0.84,0.14-1.69,0.22-2.54,0.28l-0.86,0.04c-0.29,0.01-0.57,0-0.86,0c-0.53,0.01-1.05-0.03-1.57-0.06c1.51-2.98-2.18-5-2.18-5 s-0.92,3.15,0.55,4.83c-1.19-0.16-2.36-0.41-3.51-0.74c3.15-3.7-1.52-7.46-1.52-7.46s-2.14,4.31-0.23,6.89 c-1.46-0.53-2.86-1.19-4.2-1.98c4.7-3.22,0.49-8.78,0.49-8.78s-3.69,4.34-2.07,7.77c-0.08-0.05-0.16-0.1-0.23-0.16l-0.7-0.51 l-0.67-0.54c-0.11-0.09-0.23-0.18-0.33-0.27l-0.32-0.29c-0.21-0.19-0.43-0.38-0.64-0.58c-0.4-0.4-0.82-0.79-1.2-1.21 c5.91-2.21,2.73-9.15,2.73-9.15s-4.93,3.73-3.96,7.72c-0.68-0.86-1.33-1.76-1.89-2.71c-0.46-0.75-0.87-1.53-1.25-2.32 c6.33-0.61,5.01-8.16,5.01-8.16s-5.6,2.31-5.79,6.33c-0.61-1.6-1.06-3.26-1.34-4.95c4.81,0.3,4.68-5.48,4.68-5.48 s-4.05,0.99-4.91,3.69c-0.07-0.76-0.1-1.51-0.1-2.27c0-0.33,0.01-0.66,0.03-1c3.11-2.01,0.98-7.09,0.98-7.09s-4.69,3.31-1.73,6.99 C7,28.46,6.99,28.82,6.98,29.18c-0.02,0.91,0.01,1.82,0.1,2.73c-1.84-2.38-6.26-1.4-6.26-1.4s2.37,5.11,6.44,2.95 c0.26,1.71,0.69,3.39,1.28,5.01C5.64,35.69,0,37.86,0,37.86s4.26,6.43,9.29,2.45c0.39,0.87,0.83,1.72,1.31,2.54 c0.47,0.83,1.01,1.63,1.58,2.4C8.71,43.7,4.11,47,4.11,47s5.7,5.1,9.56,0.08c0.04,0.04,0.07,0.08,0.11,0.12 c0.39,0.45,0.82,0.87,1.24,1.3c0.21,0.21,0.44,0.41,0.66,0.61l0.33,0.3c0.11,0.1,0.23,0.19,0.34,0.29l0.69,0.57l0.23,0.17 c-3.34-0.34-6.58,3.29-6.58,3.29s6.19,3.47,8.69-1.83c1.2,0.75,2.47,1.41,3.78,1.96c-2.76,0.6-4.62,4.13-4.62,4.13 s5.89,1.62,6.98-3.26c1.03,0.32,2.07,0.58,3.13,0.78c-1.63,0.99-2.39,3.38-2.39,3.38s4.31,0.39,4.61-3.07 c0.07,0.01,0.14,0.02,0.21,0.02c0.6,0.04,1.2,0.1,1.8,0.09c0.3,0,0.6,0.02,0.9,0.01l0.9-0.03c1.2-0.07,2.41-0.18,3.59-0.42 l0.45-0.08c0.15-0.03,0.29-0.07,0.44-0.1L40,55.13l0.81,0.19c0.15,0.03,0.29,0.07,0.44,0.1l0.45,0.08c1.18,0.23,2.39,0.35,3.59,0.42 l0.9,0.03c0.3,0.01,0.6-0.01,0.9-0.01c0.6,0,1.2-0.06,1.8-0.09c0.07-0.01,0.14-0.02,0.21-0.02c0.31,3.45,4.61,3.07,4.61,3.07 s-0.76-2.39-2.39-3.38c1.06-0.2,2.11-0.46,3.13-0.78c1.09,4.88,6.98,3.26,6.98,3.26s-1.86-3.52-4.62-4.13 c1.31-0.55,2.57-1.21,3.78-1.96c2.5,5.3,8.69,1.83,8.69,1.83s-3.24-3.63-6.58-3.29l0.23-0.17l0.69-0.57 c0.11-0.1,0.23-0.19,0.34-0.29l0.33-0.3c0.22-0.2,0.45-0.4,0.66-0.61c0.42-0.43,0.85-0.84,1.24-1.3c0.03-0.04,0.07-0.08,0.11-0.12 C70.19,52.1,75.89,47,75.89,47s-4.6-3.31-8.08-1.75c0.57-0.77,1.11-1.56,1.58-2.4C69.88,42.03,70.31,41.18,70.71,40.31z"/> + </svg> + <foreignObject width="230" height="35" style="font-size: 14px;color: rgb(67, 39, 135);font-family: Arial;font-weight: 700;text-align: left;letter-spacing: 0em;line-height: 1.5;" x="64" y="24"> + <div xmlns="http://www.w3.org/1999/xhtml">#6 Repository Of The Day</div> + </foreignObject> + <foreignObject width="141" height="36" style="font-size: 18px;color: rgb(74, 14, 153);font-family: Arial;font-weight: 400;text-align: center;letter-spacing: 0em;line-height: 1.5;" x="-36" y="9"> + <div xmlns="http://www.w3.org/1999/xhtml">6</div> + </foreignObject> + </svg> \ No newline at end of file diff --git a/bb-api-collect/assets/img/tuiguang.svg b/bb-api-collect/assets/img/tuiguang.svg new file mode 100644 index 0000000000..52aac0e2ee --- /dev/null +++ b/bb-api-collect/assets/img/tuiguang.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"><path d="M324.5568 660.31616v56.832c0 30.19264 24.4736 54.67136 54.67136 54.67136 30.19264 0 54.67136-24.4736 54.67136-54.67136v-14.04928l-109.34272-42.78272z m186.4704 72.96512C503.0656 799.0016 447.09376 849.92 379.22816 849.92c-73.32864 0-132.77184-59.4432-132.77184-132.77184v-87.3984l-117.15584-45.83936v0.06656a39.05024 39.05024 0 1 1-78.10048 0V411.71968a39.05024 39.05024 0 0 1 78.10048 0v0.06656l499.85024-195.59424v-23.54176a39.05024 39.05024 0 1 1 78.1056 0v610.39616a39.05024 39.05024 0 1 1-78.1056 0v-23.54176l-118.1184-46.22336z" fill="#FFD778"></path><path d="M808.78592 458.73152h124.96384A39.05024 39.05024 0 0 1 972.8 497.78176v0.13312a39.05024 39.05024 0 0 1-39.05024 39.05024h-124.96384a39.05024 39.05024 0 0 1-39.05024-39.05024v-0.13312a39.05024 39.05024 0 0 1 39.05024-39.05024z m-3.31264 130.43712l108.25728 62.61248a39.05024 39.05024 0 0 1 14.2848 53.2992l-0.05632 0.1024a39.04512 39.04512 0 0 1-53.376 14.30016l-108.25728-62.6176a39.05024 39.05024 0 0 1-14.2848-53.2992l0.05632-0.09728a39.04512 39.04512 0 0 1 53.376-14.30016z m-39.14752-250.3424l108.25728-62.61248a39.04512 39.04512 0 0 1 53.376 14.30528l0.0512 0.09216a39.05024 39.05024 0 0 1-14.2848 53.30432L805.4784 406.528a39.04512 39.04512 0 0 1-53.376-14.30016l-0.0512-0.09728a39.05024 39.05024 0 0 1 14.27968-53.2992z" fill="#FB813A"></path></svg> \ No newline at end of file diff --git a/bb-api-collect/assets/img/video_up.svg b/bb-api-collect/assets/img/video_up.svg new file mode 100644 index 0000000000..e8987f58fe --- /dev/null +++ b/bb-api-collect/assets/img/video_up.svg @@ -0,0 +1,6 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> +<path fill="#17AACC" d="M618,131.5l47-47c41.7-47.6-25-112.2-72-71l-107,106c-3.3,3.3-6,7-8,11H361c-1.3-2.7-3.3-5-6-7l-112-111 + c-21.3-17.3-51-17-71,3s-20.3,49.7-3,71l45,44H105c-56.7,0-105,48.3-105,105v417c0,56.7,48.3,105,105,105h57 + c-17.9,49.6,19.9,105,73.5,105c55.4,0,90.4-55.3,74.5-105h218c-15.9,49.7,19.1,105,74.5,105c53.6,0,91.4-55.4,73.5-105h57 + c56.7,0,105-48.3,105-105v-417c0-57.6-48.3-104-105-104L618,131.5L618,131.5z"/> +</svg> diff --git a/bb-api-collect/assets/zone_icon/ad.svg b/bb-api-collect/assets/zone_icon/ad.svg new file mode 100644 index 0000000000..3004bbff2e --- /dev/null +++ b/bb-api-collect/assets/zone_icon/ad.svg @@ -0,0 +1,14 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M576.768 153.6c32.768-32.512 132.096 13.824 221.952 103.68s136.448 189.184 103.68 221.952a27.648 27.648 0 0 1-6.144 4.608c-37.632 22.784-640 377.6-640 377.6a110.592 110.592 0 0 1-48.384-30.976 140.288 140.288 0 0 1-34.56-49.152s381.184-588.8 399.36-620.8a34.56 34.56 0 0 1 4.096-6.912z" + fill="#9796ED"></path> + <path + d="M172.288 780.032c-4.864 3.328-35.328 19.968-51.2 28.928a18.688 18.688 0 0 0-9.728 19.456 104.192 104.192 0 0 0 31.488 58.368 117.504 117.504 0 0 0 59.392 33.024 19.2 19.2 0 0 0 19.968-8.448c10.752-17.152 32-51.2 33.024-51.2a110.592 110.592 0 0 1-48.384-30.976 140.288 140.288 0 0 1-34.56-49.152z" + fill="#9289F0"></path> + <path + d="M576.768 153.6c32.768-32.512 132.096 13.824 221.952 103.68s136.448 189.184 103.68 221.952a27.648 27.648 0 0 1-6.144 4.608c-37.632 22.784-102.4 60.16-102.4 60.16s-64-4.096-173.312-113.664c-102.4-102.4-112.128-171.008-112.128-171.008s39.936-61.696 62.464-98.816a34.56 34.56 0 0 1 5.888-6.912z" + fill="#F7DF88"></path> + <path + d="M680.45816 374.49224a230.144 83.712 45 1 0 118.386645-118.386645 230.144 83.712 45 1 0-118.386645 118.386645Z" + fill="#8683EA"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/animal.svg b/bb-api-collect/assets/zone_icon/animal.svg new file mode 100644 index 0000000000..4f7708d15f --- /dev/null +++ b/bb-api-collect/assets/zone_icon/animal.svg @@ -0,0 +1,11 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M517.376 465.152a144.924444 144.924444 0 0 1 137.528889 99.214222c1.28 3.925333 2.275556 7.850667 2.901333 11.804445a132.266667 132.266667 0 0 1-14.279111 263.765333h-263.054222a132.266667 132.266667 0 0 1-14.250667-263.793778c0.625778-3.982222 1.592889-7.907556 2.872889-11.776a144.924444 144.924444 0 0 1 137.528889-99.214222h10.752zM420.693333 418.104889c50.261333-3.783111 85.617778-59.164444 79.047111-123.733333-6.599111-64.568889-52.650667-113.891556-102.912-110.108445-50.232889 3.754667-85.617778 59.164444-79.018666 123.733333 6.599111 64.568889 52.650667 113.863111 102.912 110.08zM603.306667 418.104889c50.232889 3.754667 96.284444-45.511111 102.883555-110.108445 6.599111-64.568889-28.785778-119.978667-79.018666-123.733333-50.261333-3.783111-96.312889 45.511111-102.912 110.08-6.599111 64.568889 28.785778 119.978667 79.018666 123.733333zM717.425778 551.139556c39.082667 21.816889 96.910222-4.266667 129.137778-58.225778 32.256-53.959111 26.709333-115.370667-12.373334-137.187556-39.111111-21.816889-96.938667 4.266667-129.166222 58.225778-32.256 53.959111-26.709333 115.370667 12.401778 137.187556zM306.574222 551.139556c39.111111-21.816889 44.657778-83.228444 12.401778-137.187556-32.227556-53.959111-90.055111-80.042667-129.137778-58.225778-39.111111 21.816889-44.657778 83.228444-12.430222 137.187556 32.256 53.959111 90.083556 80.042667 129.166222 58.225778z" + fill="#FB7299"></path> + <path + d="M621.511111 113.777778c76.231111-0.938667 138.467556 74.012444 149.504 173.340444 37.745778-13.312 75.861333-12.913778 107.292445 4.323556 70.712889 38.769778 80.753778 147.968 22.442666 243.911111a272.327111 272.327111 0 0 1-71.111111 78.336c9.159111 22.869333 14.222222 47.843556 14.222222 73.984V711.111111a199.111111 199.111111 0 0 1-199.111111 199.111111h-265.500444a199.111111 199.111111 0 0 1-199.111111-199.111111v-23.438222c0-26.168889 5.063111-51.114667 14.222222-74.012445a272.099556 272.099556 0 0 1-71.111111-78.307555c-58.311111-95.943111-48.270222-205.141333 22.442666-243.911111 31.431111-17.237333 69.546667-17.635556 107.320889-4.352C264.021333 187.790222 326.257778 112.839111 402.488889 113.777778c42.410667 0.540444 81.152 24.462222 109.511111 62.776889 28.359111-38.286222 67.100444-62.236444 109.511111-62.776889z" + fill="#FFD7E7"></path> + <path + d="M512 465.152a141.198222 141.198222 0 0 1 134.741333 98.958222l0.085334 0.256c1.905778 6.087111 3.015111 12.231111 3.356444 18.289778a132.266667 132.266667 0 0 1-9.728 264.163556h-256.910222a132.266667 132.266667 0 0 1-9.671111-264.192l-0.199111 4.579555c0-7.736889 1.194667-15.445333 3.498666-22.840889l0.085334-0.284444A141.198222 141.198222 0 0 1 512 465.180444zM420.693333 418.104889c50.261333-3.783111 85.617778-59.164444 79.047111-123.733333-6.599111-64.568889-52.650667-113.891556-102.912-110.108445-50.232889 3.754667-85.617778 59.164444-79.018666 123.733333 6.599111 64.568889 52.650667 113.863111 102.912 110.08zM603.306667 418.104889c50.232889 3.754667 96.284444-45.511111 102.883555-110.108445 6.599111-64.568889-28.785778-119.978667-79.018666-123.733333-50.261333-3.783111-96.312889 45.511111-102.912 110.08-6.599111 64.568889 28.785778 119.978667 79.018666 123.733333zM717.425778 551.139556c39.082667 21.816889 96.910222-4.266667 129.137778-58.225778 32.256-53.959111 26.709333-115.370667-12.373334-137.187556-39.111111-21.816889-96.938667 4.266667-129.166222 58.225778-32.256 53.959111-26.709333 115.370667 12.401778 137.187556zM306.574222 551.139556c39.111111-21.816889 44.657778-83.228444 12.401778-137.187556-32.227556-53.959111-90.055111-80.042667-129.137778-58.225778-39.111111 21.816889-44.657778 83.228444-12.430222 137.187556 32.256 53.959111 90.083556 80.042667 129.166222 58.225778z" + fill="#FB7299"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/anime.svg b/bb-api-collect/assets/zone_icon/anime.svg new file mode 100644 index 0000000000..fd797d334b --- /dev/null +++ b/bb-api-collect/assets/zone_icon/anime.svg @@ -0,0 +1,16 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M588.8 359.68l-12.032-7.424 150.272-206.592a30.976 30.976 0 0 0-51.2-36.352l-153.6 210.176L281.6 170.24a30.976 30.976 0 1 0-33.024 52.736L486.4 369.92l-22.784 31.488a30.976 30.976 0 1 0 51.2 36.352l25.6-35.072 16.128 9.728A30.976 30.976 0 1 0 588.8 359.68z" + fill="#FB813A"></path> + <path d="M763.648 850.688m-53.248 0a53.248 53.248 0 1 0 106.496 0 53.248 53.248 0 1 0-106.496 0Z" fill="#FB813A"> + </path> + <path d="M261.12 797.44a53.248 53.248 0 1 0 53.504 53.248 53.248 53.248 0 0 0-53.504-53.248z" fill="#FB813A"></path> + <path + d="M141.312 314.368m92.928 0l556.288 0q92.928 0 92.928 92.928l0 360.704q0 92.928-92.928 92.928l-556.288 0q-92.928 0-92.928-92.928l0-360.704q0-92.928 92.928-92.928Z" + fill="#FDDE80"></path> + <path d="M520.448 575.232m-128.256 0a128.256 128.256 0 1 0 256.512 0 128.256 128.256 0 1 0-256.512 0Z" + fill="#FFFFFF"></path> + <path + d="M476.928 546.56c0-26.88 19.2-37.632 42.24-25.6l49.664 28.672a25.6 25.6 0 0 1 0 48.64l-49.664 28.672c-23.04 13.568-42.24 2.56-42.24-24.32z" + fill="#FB813A"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/car.svg b/bb-api-collect/assets/zone_icon/car.svg new file mode 100644 index 0000000000..6d30f0a31e --- /dev/null +++ b/bb-api-collect/assets/zone_icon/car.svg @@ -0,0 +1,20 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M210.688 588.8h25.6a51.2 51.2 0 0 1 51.2 45.568l14.08 128A51.2 51.2 0 0 1 256 819.2H225.024a51.2 51.2 0 0 1-51.2-45.568l-14.08-128A51.2 51.2 0 0 1 204.8 588.8zM788.224 588.8h25.6a51.2 51.2 0 0 1 51.2 51.2 41.984 41.984 0 0 1 0 5.632l-14.08 128a51.2 51.2 0 0 1-51.2 45.568h-25.6a51.2 51.2 0 0 1-51.2-51.2 41.984 41.984 0 0 1 0-5.632l14.08-128a51.2 51.2 0 0 1 51.2-45.568zM906.496 392.96a38.656 38.656 0 0 1-25.6 48.128l-25.6 7.424a38.4 38.4 0 0 1-22.528-73.472l25.6-7.424a38.144 38.144 0 0 1 48.128 25.344zM215.296 422.912a38.4 38.4 0 0 1-47.872 25.6l-25.6-7.424a38.656 38.656 0 0 1-25.6-48.128 38.144 38.144 0 0 1 47.872-25.6l25.6 7.424a38.4 38.4 0 0 1 25.6 48.128z" + fill="#23ADE5"></path> + <path + d="M292.608 201.216A1109.76 1109.76 0 0 1 512 179.2a1165.568 1165.568 0 0 1 224 22.016 51.2 51.2 0 0 1 38.144 32L870.4 486.4v230.4a25.6 25.6 0 0 1-25.6 25.6H179.2a25.6 25.6 0 0 1-25.6-25.6v-230.4l102.4-253.696a51.2 51.2 0 0 1 36.608-31.488z" + fill="#48CFE5"></path> + <path + d="M204.8 512m25.6 0l102.4 0q25.6 0 25.6 25.6l0 25.6q0 25.6-25.6 25.6l-102.4 0q-25.6 0-25.6-25.6l0-25.6q0-25.6 25.6-25.6Z" + fill="#FFFFFF"></path> + <path + d="M665.6 512m25.6 0l102.4 0q25.6 0 25.6 25.6l0 25.6q0 25.6-25.6 25.6l-102.4 0q-25.6 0-25.6-25.6l0-25.6q0-25.6 25.6-25.6Z" + fill="#FFFFFF"></path> + <path + d="M327.68 270.848a1000.96 1000.96 0 0 1 172.032-14.848 1429.248 1429.248 0 0 1 196.864 15.36 25.6 25.6 0 0 1 20.992 18.176l39.68 134.656a25.6 25.6 0 0 1-17.408 31.744 24.064 24.064 0 0 1-9.472 0q-125.184-12.032-230.4-12.032a1894.4 1894.4 0 0 0-204.8 11.264 25.6 25.6 0 0 1-28.16-22.784 25.6 25.6 0 0 1 0-9.984L307.2 288.768a25.6 25.6 0 0 1 20.48-17.92z" + fill="#FDDE80"></path> + <path + d="M614.4 358.4a102.4 102.4 0 0 0-100.864 86.784h51.2a51.2 51.2 0 0 1 99.072 5.12l51.2 4.352A102.4 102.4 0 0 0 614.4 358.4z" + fill="#23ADE5"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/cinephile.svg b/bb-api-collect/assets/zone_icon/cinephile.svg new file mode 100644 index 0000000000..cad39f4b32 --- /dev/null +++ b/bb-api-collect/assets/zone_icon/cinephile.svg @@ -0,0 +1,14 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M147.2 201.728m79.616 0l571.136 0q79.616 0 79.616 79.616l0 458.24q0 79.616-79.616 79.616l-571.136 0q-79.616 0-79.616-79.616l0-458.24q0-79.616 79.616-79.616Z" + fill="#9796ED"></path> + <path + d="M222.976 269.312h77.056v57.856H222.976zM390.144 269.312h77.056v57.856h-77.056zM557.312 269.312h77.056v57.856h-77.056zM724.48 269.312h77.056v57.856H724.48zM222.976 693.76h77.056v57.856H222.976zM390.144 693.76h77.056v57.856h-77.056zM557.312 693.76h77.056v57.856h-77.056zM147.2 375.296h730.368v270.08H147.2z" + fill="#7B78EA"></path> + <path + d="M521.369822 529.707066m23.351494-23.351495l2.534271-2.53427q23.351494-23.351494 46.702989 0l199.664327 199.664327q23.351494 23.351494 0 46.702989l-2.534271 2.534271q-23.351494 23.351494-46.702988 0l-199.664328-199.664328q-23.351494-23.351494 0-46.702989Z" + fill="#FFD043"></path> + <path + d="M708.352 418.816h-25.6v-24.32a13.568 13.568 0 0 0-13.568-13.568H665.6a13.312 13.312 0 0 0-13.312 13.568v24.32h-25.6a13.568 13.568 0 0 0-13.568 13.568v5.632a13.568 13.568 0 0 0 13.568 13.568h25.6v24.32a13.312 13.312 0 0 0 13.312 13.568h5.632a13.568 13.568 0 0 0 13.568-13.568v-24.32h25.6a13.312 13.312 0 0 0 13.312-13.568v-5.632a13.312 13.312 0 0 0-15.36-13.568zM517.888 418.816h-25.6v-24.32a13.312 13.312 0 0 0-13.312-13.568h-5.632a13.568 13.568 0 0 0-13.568 13.568v24.32H435.2a13.312 13.312 0 0 0-13.312 13.568v5.632a13.312 13.312 0 0 0 13.312 13.568h25.6v24.32a13.568 13.568 0 0 0 13.568 13.568h5.632a13.312 13.312 0 0 0 13.312-13.568v-24.32h25.6a13.312 13.312 0 0 0 13.312-13.568v-5.632a13.312 13.312 0 0 0-14.336-13.568zM493.568 572.16h-18.432v-18.432a10.24 10.24 0 0 0-10.24-10.24H460.8a10.24 10.24 0 0 0-10.24 10.24v18.432h-18.432a10.24 10.24 0 0 0-10.24 10.24v4.352a10.24 10.24 0 0 0 10.24 10.24h18.432V614.4a10.24 10.24 0 0 0 10.24 10.24h4.352a10.24 10.24 0 0 0 10.24-10.24v-18.432h18.432a10.24 10.24 0 0 0 10.24-10.24v-4.352a10.24 10.24 0 0 0-10.496-9.216z" + fill="#FFD778"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/comic.svg b/bb-api-collect/assets/zone_icon/comic.svg new file mode 100644 index 0000000000..bb78da2983 --- /dev/null +++ b/bb-api-collect/assets/zone_icon/comic.svg @@ -0,0 +1,20 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M722.204444 843.491556H170.524444a70.144 70.144 0 0 1-69.973333-69.916445V400.896a70.144 70.144 0 0 1 69.973333-69.944889H722.204444a70.144 70.144 0 0 1 69.916445 69.973333v372.622223a70.144 70.144 0 0 1-69.916445 69.944889" + fill="#FDDE80"></path> + <path + d="M710.314667 341.703111c22.613333-7.338667 38.200889-29.098667 36.067555-52.792889a143.616 143.616 0 0 0-6.542222-32.142222c-39.480889-121.628444-229.12-169.045333-423.566222-105.898667C121.799111 214.016-3.783111 363.804444 35.697778 485.461333c3.413333 10.524444 7.992889 20.451556 13.596444 29.809778 12.231111 20.423111 37.603556 28.871111 60.216889 21.532445l600.803556-195.100445z" + fill="#9796ED"></path> + <path + d="M281.031111 123.676444l11.235556 34.616889c4.977778 15.331556 21.617778 23.779556 36.920889 18.801778 15.331556-4.977778 23.808-21.589333 18.830222-36.920889l-11.235556-34.588444a29.383111 29.383111 0 0 0-36.920889-18.801778c-15.36 4.949333-23.808 21.589333-18.830222 36.892444" + fill="#7B78EB"></path> + <path + d="M444.16 714.069333a139.747556 139.747556 0 0 0 138.296889-119.552 17.493333 17.493333 0 0 0-17.123556-20.195555h-242.346666a17.493333 17.493333 0 0 0-17.123556 20.195555 139.776 139.776 0 0 0 138.296889 119.552" + fill="#FFAF66"></path> + <path + d="M704.796444 680.903111L618.951111 640.284444s12.288 55.751111 71.395556 92.672c-0.085333 0.739556-0.284444 1.422222-0.369778 2.190223-12.714667 94.549333 38.200889 179.399111 113.692444 189.553777 75.491556 10.126222 146.972444-58.311111 159.687111-152.860444 12.686222-94.520889-38.200889-179.399111-113.720888-189.525333-60.017778-8.078222-117.418667 33.649778-144.839112 98.588444z" + fill="#9796ED"></path> + <path + d="M856.064 682.012444l-19.797333 99.157334a6.570667 6.570667 0 0 1-6.456889 5.290666h-17.777778a6.599111 6.599111 0 0 1-6.542222-7.537777l14.478222-99.128889a6.542222 6.542222 0 0 1 6.485333-5.660445h23.153778c4.181333 0 7.281778 3.811556 6.456889 7.879111m-22.897778 136.078223l-2.986666 16.298666a6.570667 6.570667 0 0 1-6.456889 5.404445h-20.963556a6.599111 6.599111 0 0 1-6.485333-7.651556l2.645333-16.270222a6.599111 6.599111 0 0 1 6.485333-5.546667h21.276445c4.124444 0 7.253333 3.726222 6.485333 7.765334" + fill="#C5C2FF"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/dance.svg b/bb-api-collect/assets/zone_icon/dance.svg new file mode 100644 index 0000000000..87a5ad12eb --- /dev/null +++ b/bb-api-collect/assets/zone_icon/dance.svg @@ -0,0 +1,10 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M956.672 513.792a476.416 476.416 0 0 0-890.368 0L512 727.296l-95.232 45.568a117.76 117.76 0 0 0 192.256 0L512 727.04z" + fill="#FC6B8A"></path> + <path d="M512 727.296l208.64-99.84a222.976 222.976 0 0 0-416.768 0z" fill="#FFFFFF"></path> + <path d="M405.4528 751.5392l541.184-258.5856 14.0288 29.312-541.184 258.6112z" fill="#FF5C7A"></path> + <path + d="M666.624 545.792l-18.688-15.36-112.64 135.424 40.192-173.056-23.552-5.632-40.192 172.544-40.448-172.544-23.808 5.632 40.704 173.056-112.896-135.424-18.688 15.36 111.616 134.144-391.68-186.88-13.824 29.184 541.184 258.56 14.08-29.44-87.552-41.728 136.192-163.84z" + fill="#F14767"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/digital.svg b/bb-api-collect/assets/zone_icon/digital.svg new file mode 100644 index 0000000000..56ea8f9343 --- /dev/null +++ b/bb-api-collect/assets/zone_icon/digital.svg @@ -0,0 +1,13 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M298.496 284.928l17.664-51.2a36.608 36.608 0 0 1 33.28-22.016h325.376a37.12 37.12 0 0 1 34.304 22.016l17.408 51.2h88.576a69.376 69.376 0 0 1 66.56 70.656v377.344a69.12 69.12 0 0 1-67.84 70.144H209.92a69.12 69.12 0 0 1-68.352-70.144V355.584a69.376 69.376 0 0 1 68.352-70.656z" + fill="#FFBA7B"></path> + <path d="M141.568 457.728h740.096v271.36a69.632 69.632 0 0 1-73.728 73.984H210.688a69.12 69.12 0 0 1-69.12-69.376z" + fill="#FB952C"></path> + <path d="M512 358.4a197.376 197.376 0 1 1-197.376 197.376A197.632 197.632 0 0 1 512 358.4z" fill="#FB952C"></path> + <path d="M512 409.6a148.224 148.224 0 1 1-147.968 147.968A147.968 147.968 0 0 1 512 409.6z" fill="#FFFFFF"></path> + <path d="M512 457.728a98.816 98.816 0 1 1-98.56 98.56A98.56 98.56 0 0 1 512 457.728z" fill="#FB952C"></path> + <path + d="M733.696 358.4h73.984a25.6 25.6 0 0 1 25.6 25.6 25.6 25.6 0 0 1-25.6 25.6h-73.984a25.6 25.6 0 0 1-25.6-25.6 25.6 25.6 0 0 1 25.6-25.6z" + fill="#FFFFFF"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/documentary.svg b/bb-api-collect/assets/zone_icon/documentary.svg new file mode 100644 index 0000000000..fcaf707f1c --- /dev/null +++ b/bb-api-collect/assets/zone_icon/documentary.svg @@ -0,0 +1,31 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M404.9 386.765c-70.8975-2.565-143.3475 12.06-196.65 38.1825-48.8475 23.9625-117.63 89.46-121.9275 135.5625h735.3225c-3.2175 0-12.015-9.4275-14.7375-11.52-5.0175-3.825-9.7425-7.8075-14.76-11.5425-11.9025-8.91-24.66-16.8975-37.1475-24.975a1040.175 1040.175 0 0 0-77.0625-45.585c-52.47-27.945-107.865-50.805-165.69-65.0025a533.88 533.88 0 0 0-107.3475-15.12" + fill="#47CFE5"></path> + <path + d="M744.605 489.1625c-12.7125 32.31-136.71 36.765-181.395 36.765H137.8025c-15.2325 0-29.7675 5.1975-39.7575 14.265-9.9 8.9775-14.1075 20.7675-11.7 32.355 0 0.1125 0 0.27 0.09 0.3375 9.2925 43.6725 35.73 83.34 76.365 114.6825 1.62 1.26 3.2625 2.52 4.9275 3.735 106.74 78.4575 292.5225 81.1575 423.45 43.875 41.445-11.79 80.865-28.17 115.1775-49.635 38.9925-24.39 78.795-57.3075 102.3075-91.7325 3.465-5.0625 41.22-61.1775 41.9625-60.885l-106.02-43.7625z" + fill="#47CFE5"></path> + <path + d="M918.0575 505.3175l-29.88-17.0775a75.0825 75.0825 0 0 0-70.11-2.1375 75.375 75.375 0 0 0-37.4175-59.355l-29.925-17.0775a11.4525 11.4525 0 0 0-15.66 4.275l-7.83 13.7025a59.0625 59.0625 0 0 0 21.96 80.5725l15.795 9.045a0.045 0.045 0 0 1-0.045 0.045l51.48 29.43 0.045-0.045 17.46 9.99a59.085 59.085 0 0 0 80.5725-21.9375l7.83-13.725a11.5425 11.5425 0 0 0-4.275-15.705" + fill="#2BBAE4"></path> + <path + d="M654.515 712.4975C351.3275 720.8675 266.3 564.425 266.3 564.425H85.7825a31.995 31.995 0 0 0 0.63 8.46c9.2925 43.6725 35.73 83.34 76.365 114.6825 1.62 1.2825 3.2625 2.52 4.9275 3.735 106.7175 78.4575 292.5 81.18 423.4275 43.875a509.6925 509.6925 0 0 0 63.3825-22.68" + fill="#E5E6E6"></path> + <path + d="M654.515 712.4975c-65.16 1.8-120.15-4.41-166.5675-14.2425-49.005-10.3725-26.1675 59.31-3.2175 56.79 37.485-4.0725 73.665-10.5975 106.4025-19.9125a502.3575 502.3575 0 0 0 63.3825-22.635" + fill="#E4E5E4"></path> + <path + d="M407.1275 674.9225c21.5775 69.84 69.705 117.6525 116.775 113.6475 3.735-0.3375 6.2325-4.0725 5.5125-7.74l-24.435-125.6175a5.715 5.715 0 0 0-6.6825-4.5l-86.715 16.8975a5.7825 5.7825 0 0 0-4.455 7.3125" + fill="#47CFE5"></path> + <path d="M441.2375 614.7125a29.295 29.295 0 1 1-58.6125 0.0225 29.295 29.295 0 0 1 58.6125-0.0225" fill="#0099BC"> + </path> + <path + d="M252.5975 310.4675a64.2825 64.2825 0 0 1 64.305-64.1025c18.81 0 35.73 8.1225 47.52 21.1275a64.17 64.17 0 0 1 111.7125 42.975 16.56 16.56 0 0 1-16.5825 16.5825 16.56 16.56 0 0 1-16.605-16.5825 31.05 31.05 0 0 0-61.9875-2.16h-0.18l0.1125 77.4675a16.5825 16.5825 0 1 1-33.1875 0v-75.3975c0-17.0325-13.9275-30.9375-30.96-30.9375a31.05 31.05 0 0 0-31.0275 31.0275 16.56 16.56 0 1 1-33.12 0" + fill="#47CFE5"></path> + <path + d="M364.3325 408.0275a22.2525 22.2525 0 0 1-22.2075-22.23V310.4a25.3575 25.3575 0 1 0-50.715 0.09 22.23 22.23 0 0 1-44.415 0c0-38.4525 31.365-69.75 69.9075-69.75a69.75 69.75 0 0 1 47.52 18.765 70.2 70.2 0 0 1 47.61-18.765c38.4525 0 69.75 31.2975 69.75 69.75a22.23 22.23 0 0 1-44.4375 0 25.425 25.425 0 0 0-50.7375-1.7775l-0.1575 2.385 0.09 74.7a22.2525 22.2525 0 0 1-22.2075 22.23z m-47.5425-134.19c20.16 0 36.5625 16.4025 36.5625 36.5625v75.42a10.98 10.98 0 1 0 21.915 0l-0.09-83.0925h0.9225a36.7425 36.7425 0 0 1 35.82-28.8675c20.205 0 36.6525 16.4475 36.6525 36.6525a10.98 10.98 0 0 0 21.9375 0c0-32.265-26.235-58.5-58.5-58.5-16.4475 0-32.2875 7.02-43.4475 19.305l-4.1625 4.545-4.1625-4.6125a58.635 58.635 0 0 0-43.335-19.2825 58.635 58.635 0 0 0-58.6575 58.5 10.9575 10.9575 0 0 0 21.915 0 36.675 36.675 0 0 1 36.63-36.63z" + fill="#47CFE5"></path> + <path + d="M389.87 621.2825h-66.33a47.79 47.79 0 0 1-35.0325-15.5925l-23.715-25.695a28.575 28.575 0 0 0-20.88-9.2925H91.0475a6.525 6.525 0 1 1 0-13.095h152.8875c11.4525 0 22.5675 4.9275 30.4875 13.5225l23.715 25.7175c6.66 7.2 15.93 11.34 25.425 11.34h66.33a6.525 6.525 0 1 1-0.0225 13.095" + fill="#0099BC"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/douga.svg b/bb-api-collect/assets/zone_icon/douga.svg new file mode 100644 index 0000000000..5cf324c490 --- /dev/null +++ b/bb-api-collect/assets/zone_icon/douga.svg @@ -0,0 +1,14 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M273.408 166.912h477.696c58.368 0 105.984 47.616 105.984 105.984v477.696c0 58.368-47.616 105.984-105.984 105.984H273.408c-58.368 0-105.984-47.616-105.984-105.984V273.408C166.912 215.04 215.04 166.912 273.408 166.912z" + fill="#7B78EB"></path> + <path + d="M512 525.312v98.816c33.28-14.848 72.704 0.512 87.552 33.792 14.848 33.28-0.512 72.704-33.792 87.552-16.896 7.68-35.84 7.68-53.248 0v111.616H273.408c-58.368 0-105.984-47.616-105.984-105.984V512h137.216c-21.504 19.456-24.064 53.248-4.608 74.752 19.456 21.504 53.248 24.064 74.752 4.608 21.504-18.944 24.064-53.248 4.608-74.752l-4.608-4.608H512v-40.96c-4.096 0.512-9.216 0.512-13.312 0-51.2 0-86.016-47.616-86.016-105.984s20.992-108.032 86.016-108.032h13.312V166.912h238.592c58.368 0 105.984 47.616 105.984 105.984v251.904h-120.832c20.992-23.552 19.456-59.392-3.584-80.896-23.552-20.992-59.392-19.456-80.896 3.584-19.968 21.504-19.968 55.296 0 76.8H512z" + fill="#9796ED"></path> + <path + d="M512 525.312v98.816l13.312-4.096c35.84-7.68 72.704 15.872 79.872 52.224 7.68 35.84-18.432 72.192-54.272 78.848-4.096 1.024-8.704 1.024-13.312 1.024-9.216 0-16.384-3.072-25.088-6.144v111.616h-14.336v-132.608l18.432 8.192c27.136 11.776 58.368-0.512 70.144-27.648 11.776-27.136-0.512-58.368-27.648-70.144-13.312-5.632-28.672-5.632-42.496 0l-18.432 8.192v-117.76H399.872c14.848 33.28-0.512 72.704-33.792 87.552-33.28 14.848-72.704-0.512-87.552-33.792-7.68-16.896-7.68-35.84 0-53.248H166.912V512h137.216c-21.504 19.456-24.064 53.248-4.608 74.752 19.456 21.504 53.248 24.064 74.752 4.608 21.504-19.456 24.064-53.248 4.608-74.752l-4.608-4.608H512v-39.936h-13.312c-51.2 0-86.016-47.104-86.016-105.984s20.992-109.568 86.016-109.568h13.312V166.912h13.312v105.984h-26.624c-49.664 0-73.216 33.28-73.216 94.208 0 53.248 30.72 92.672 73.216 92.672 3.584 0.512 7.68 0.512 11.264 0l15.36-2.048V512h102.912c-13.824-35.84 4.096-76.8 40.448-90.624 35.84-13.824 76.8 4.096 90.624 40.448 6.144 15.872 6.144 33.792 0 50.176h97.792v13.312h-120.832c20.992-23.552 19.456-59.392-3.584-80.896-23.552-20.992-59.392-19.456-80.896 3.584-19.968 21.504-19.968 55.296 0 76.8H512z" + fill="#6A68C6"></path> + <path + d="M444.928 693.248c-23.04 13.312-52.224 5.12-65.024-17.408-4.096-7.68-6.144-15.36-6.144-24.064V392.192c0-26.624 20.992-47.616 47.616-47.616 8.704 0 16.896 2.048 24.576 6.656l221.696 132.608c23.04 13.312 30.208 42.496 16.896 65.024-4.096 6.656-10.24 12.8-16.896 16.896" + fill="#FDDE80"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/ent.svg b/bb-api-collect/assets/zone_icon/ent.svg new file mode 100644 index 0000000000..d938420ef9 --- /dev/null +++ b/bb-api-collect/assets/zone_icon/ent.svg @@ -0,0 +1,17 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M534.442796 378.982175m36.203867 36.203867l30.592268 30.592268q36.203867 36.203867 0 72.407734l-360.590518 360.590518q-36.203867 36.203867-72.407734 0l-30.592268-30.592268q-36.203867-36.203867 0-72.407735l360.590518-360.590517q36.203867-36.203867 72.407734 0Z" + fill="#FF8693"></path> + <path + d="M369.92 543.744l137.472-137.472a38.912 38.912 0 0 1 54.528 0l48.384 48.64a38.4 38.4 0 0 1 0 54.528l-137.984 137.984z" + fill="#FC6376"></path> + <path + d="M286.133941 631.021801m12.854616 12.85013l72.601422 72.576083q12.854616 12.850129 0.004486 25.704746l-1.62889 1.629458q-12.850129 12.854616-25.704745 0.004486l-72.601422-72.576083q-12.854616-12.850129-0.004486-25.704745l1.62889-1.629459q12.850129-12.854616 25.704745-0.004486Z" + fill="#FFA9B1"></path> + <path + d="M737.024 547.584a99.328 99.328 0 0 1 62.72-62.72l51.2-13.568a27.136 27.136 0 0 0 13.056-49.664L826.624 384a98.816 98.816 0 0 1-22.784-85.76l16.896-63.232c7.168-27.136-8.96-43.52-36.096-36.096l-63.232 16.896a98.816 98.816 0 0 1-85.76-23.04l-37.376-36.864a27.136 27.136 0 0 0-49.408 13.312l-13.824 51.2a97.792 97.792 0 0 1-62.464 62.72l-51.2 13.824a27.136 27.136 0 0 0-13.312 49.408L445.44 384a97.536 97.536 0 0 1 23.04 85.504l-16.896 63.232c-7.424 27.392 8.96 43.52 36.096 36.352l63.232-16.896a97.792 97.792 0 0 1 85.76 22.784l37.376 37.376a26.88 26.88 0 0 0 49.408-13.312z" + fill="#FDDE80"></path> + <path + d="M886.272 417.536l-74.752-75.008 30.464-114.432a41.216 41.216 0 0 0-8.704-41.472A41.728 41.728 0 0 0 791.808 179.2l-114.432 30.72-74.752-76.032A41.728 41.728 0 0 0 563.2 120.576a41.216 41.216 0 0 0-28.416 31.488l-27.392 102.4L404.48 281.6a42.24 42.24 0 0 0-31.744 28.16 42.24 42.24 0 0 0 13.312 40.448L460.8 425.216l-30.72 114.432a41.728 41.728 0 0 0 8.96 41.472 37.888 37.888 0 0 0 27.392 10.752 56.832 56.832 0 0 0 14.08-2.048l114.432-30.72 74.752 75.008a45.824 45.824 0 0 0 31.232 14.336 34.304 34.304 0 0 0 8.96 0 41.216 41.216 0 0 0 28.416-31.488l27.392-102.4 102.4-27.392a41.984 41.984 0 0 0 31.488-28.416 40.96 40.96 0 0 0-13.312-41.216z m-84.736-203.52h5.12a16.896 16.896 0 0 1 0 5.12l-25.6 93.696-72.96-73.728z m-32 139.776l-34.56 128-128 34.56-102.4-102.4 34.56-128 128-34.56z m-199.424-192c0-2.56 1.792-4.096 1.792-4.608a9.984 9.984 0 0 1 4.096 3.072l59.648 59.648-87.296 23.296z m-157.696 162.048L409.6 320a12.8 12.8 0 0 1 4.864-2.048l81.152-21.76-23.552 87.808z m58.368 230.4a18.944 18.944 0 0 1-5.12 0 17.92 17.92 0 0 1 0-5.12l25.6-93.696L563.2 528.64z m230.4 51.2c0 2.816-1.536 4.096-1.536 4.864a20.992 20.992 0 0 1-4.352-3.328l-59.392-59.392 87.296-23.552z m156.16-156.16l-81.152 21.76 23.296-87.04 59.392 59.392a40.96 40.96 0 0 1 3.328 3.84 12.8 12.8 0 0 1-4.096 2.56z" + fill="#FCC029"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/fashion.svg b/bb-api-collect/assets/zone_icon/fashion.svg new file mode 100644 index 0000000000..cfb662132e --- /dev/null +++ b/bb-api-collect/assets/zone_icon/fashion.svg @@ -0,0 +1,11 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M691.2 204.8a44.032 44.032 0 0 1 29.952 34.048 117.76 117.76 0 0 1-13.056 76.8s-19.2 29.952-24.32 39.936a235.008 235.008 0 0 0-25.6 107.008v40.704H365.312v-39.424a235.008 235.008 0 0 0-25.6-107.008c-5.12-9.984-24.32-39.936-24.32-39.936a117.76 117.76 0 0 1-13.056-76.8A44.544 44.544 0 0 1 336.896 204.8V147.712a29.952 29.952 0 0 1 27.136-31.744 29.952 29.952 0 0 1 27.648 31.744v73.728A237.056 237.056 0 0 0 512 253.952a241.408 241.408 0 0 0 125.184-35.072V147.712a27.136 27.136 0 1 1 53.76 0z" + fill="#FF6A9B"></path> + <path + d="M658.432 487.936H365.312L204.8 780.288a36.352 36.352 0 0 0 10.24 46.592 492.288 492.288 0 0 0 595.456 0 36.608 36.608 0 0 0 8.704-47.36z" + fill="#FF9DC6"></path> + <path + d="M409.6 537.6a9.984 9.984 0 0 0-13.568 4.608l-124.16 250.624a10.496 10.496 0 0 0 4.608 13.568 14.848 14.848 0 0 0 4.608 0 9.984 9.984 0 0 0 8.96-5.632l124.16-250.88A10.24 10.24 0 0 0 409.6 537.6zM455.936 643.072a9.984 9.984 0 0 0-12.032 7.424l-40.448 170.752a10.24 10.24 0 0 0 7.424 12.288h2.304a9.728 9.728 0 0 0 9.728-7.936l40.448-170.752a9.984 9.984 0 0 0-7.424-11.776zM750.848 791.808l-124.16-250.624A9.984 9.984 0 0 0 614.4 537.6a10.24 10.24 0 0 0-4.608 13.312l124.16 250.88a9.984 9.984 0 0 0 8.96 5.632 14.848 14.848 0 0 0 4.608 0 10.496 10.496 0 0 0 3.328-15.616zM579.84 650.496a9.984 9.984 0 0 0-19.456 4.608l40.448 170.752a9.728 9.728 0 0 0 9.728 7.936h2.304a10.24 10.24 0 0 0 7.424-12.288z" + fill="#FF6A9B"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/food.svg b/bb-api-collect/assets/zone_icon/food.svg new file mode 100644 index 0000000000..e554eb589a --- /dev/null +++ b/bb-api-collect/assets/zone_icon/food.svg @@ -0,0 +1,32 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M192.075294 503.883294m-75.294118 0a75.294118 75.294118 0 1 0 150.588236 0 75.294118 75.294118 0 1 0-150.588236 0Z" + fill="#FA942D"></path> + <path + d="M342.663529 411.211294m-75.294117 0a75.294118 75.294118 0 1 0 150.588235 0 75.294118 75.294118 0 1 0-150.588235 0Z" + fill="#FA942D"></path> + <path + d="M284.747294 480.722824m-75.294118 0a75.294118 75.294118 0 1 0 150.588236 0 75.294118 75.294118 0 1 0-150.588236 0Z" + fill="#FE5D79"></path> + <path + d="M765.470118 532.841412m-127.427765 0a127.427765 127.427765 0 1 0 254.855529 0 127.427765 127.427765 0 1 0-254.855529 0Z" + fill="#FA942D"></path> + <path + d="M632.259765 457.547294m-133.210353 0a133.210353 133.210353 0 1 0 266.420706 0 133.210353 133.210353 0 1 0-266.420706 0Z" + fill="#FA942D"></path> + <path + d="M672.798118 556.016941m-150.588236 0a150.588235 150.588235 0 1 0 301.176471 0 150.588235 150.588235 0 1 0-301.176471 0Z" + fill="#FE5D79"></path> + <path + d="M932.291765 474.925176a28.762353 28.762353 0 0 1 28.747294 28.762353l-0.045177 1.355295-0.090353 1.355294c-14.305882 150.919529-130.605176 272.865882-280.741647 299.188706l20.178824 80.745411a23.160471 23.160471 0 0 1-22.467765 28.777412H343.371294a23.160471 23.160471 0 0 1-22.467765-28.777412l20.178824-80.745411C192.813176 779.595294 77.552941 660.329412 60.928 512.015059l-0.557176-5.376a28.958118 28.958118 0 0 1 28.822588-31.713883h843.083294z" + fill="#FDDC7A"></path> + <path + d="M442.548706 196.924235h136.146823c21.263059 0 39.800471 14.456471 44.950589 35.087059l60.732235 242.913882H336.865882l60.732236-242.898823a46.336 46.336 0 0 1 44.950588-35.102118z" + fill="#F6C338"></path> + <path + d="M688.037647 192.903529c9.441882-30.177882 28.385882-29.409882 34.680471-47.585882 7.062588-20.449882 9.366588-45.718588 6.927058-75.821176 16.850824 17.935059 25.976471 37.014588 30.945883 62.283294 4.894118 24.937412-9.125647 44.182588-29.06353 74.480941-19.922824 30.313412-8.809412 67.614118 0 94.915765-16.850824-17.92-59.904-55.777882-43.474823-108.272942zM283.361882 154.247529c11.324235-37.707294 34.063059-36.773647 41.60753-59.482353 8.493176-25.554824 11.264-57.133176 8.31247-94.765176 20.239059 22.407529 31.201882 46.260706 37.165177 77.854118 5.872941 31.171765-10.947765 55.220706-34.876235 93.108706-23.943529 37.872941-10.601412 84.48 0 118.633411-20.239059-22.422588-71.936-69.722353-52.208942-135.348706z" + fill="#C6D2E1"></path> + <path + d="M510.629647 706.605176a92.672 92.672 0 0 1 92.672 92.672v115.832471H417.957647v-115.832471a92.672 92.672 0 0 1 92.672-92.672z" + fill="#F5BC20"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/game.svg b/bb-api-collect/assets/zone_icon/game.svg new file mode 100644 index 0000000000..59a2188401 --- /dev/null +++ b/bb-api-collect/assets/zone_icon/game.svg @@ -0,0 +1,9 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M166.4 166.144m90.112 0l510.976 0q90.112 0 90.112 90.112l0 510.976q0 90.112-90.112 90.112l-510.976 0q-90.112 0-90.112-90.112l0-510.976q0-90.112 90.112-90.112Z" + fill="#58D598"></path> + <path d="M307.2 325.632h136.448v136.448H307.2zM580.096 325.632h136.448v136.448h-136.448z" fill="#17AD8A"></path> + <path + d="M443.648 462.336v75.776h-64.256v204.544h59.392v-68.096H585.216v68.096h59.136v-204.544h-64.256v-75.776h-136.448z" + fill="#17AD8A"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/guochuang.svg b/bb-api-collect/assets/zone_icon/guochuang.svg new file mode 100644 index 0000000000..a10c3e970c --- /dev/null +++ b/bb-api-collect/assets/zone_icon/guochuang.svg @@ -0,0 +1,11 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M873.472 321.792c-46.08-46.592-102.4-73.472-161.536-40.192a177.152 177.152 0 0 0-51.2-161.536s-83.456 107.52-15.104 219.648c-12.288 13.568-24.32 27.136-36.352 39.424-26.88 27.136 14.592 69.12 41.216 41.984l68.608-69.632c40.704-40.96 76.8-23.808 112.896 12.288 26.624 26.88 68.096-15.104 41.472-41.984z" + fill="#58D598"></path> + <path + d="M705.024 344.576a189.696 189.696 0 0 0-270.848 0 195.072 195.072 0 0 0-41.216 62.464 249.088 249.088 0 0 0-177.664 74.496 256 256 0 0 0 0 359.68 248.576 248.576 0 0 0 354.816 0 256 256 0 0 0 73.472-179.2 190.976 190.976 0 0 0 61.44-41.728 195.84 195.84 0 0 0 0-275.712z" + fill="#FF5C7A"></path> + <path + d="M514.304 808.704a187.136 187.136 0 0 1-267.264-5.12 193.536 193.536 0 0 1 5.12-271.104s-45.056 120.832 43.776 214.272a210.176 210.176 0 0 0 218.368 61.952" + fill="#F14767"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/information.svg b/bb-api-collect/assets/zone_icon/information.svg new file mode 100644 index 0000000000..c33d83818a --- /dev/null +++ b/bb-api-collect/assets/zone_icon/information.svg @@ -0,0 +1,17 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M760.685714 768a21.942857 21.942857 0 0 0 19.836343 21.840457L782.628571 789.942857a21.942857 21.942857 0 0 0 21.840458-19.836343L804.571429 768V321.828571h29.257142a58.514286 58.514286 0 0 1 58.514286 58.514286v438.857143a58.514286 58.514286 0 0 1-58.514286 58.514286H190.171429a58.514286 58.514286 0 0 1-58.514286-58.514286V204.8a58.514286 58.514286 0 0 1 58.514286-58.514286h512a58.514286 58.514286 0 0 1 58.514285 58.514286v563.2z" + fill="#7DD3E0"></path> + <path + d="M219.428571 234.057143m29.257143 0l394.971429 0q29.257143 0 29.257143 29.257143l0 263.314285q0 29.257143-29.257143 29.257143l-394.971429 0q-29.257143 0-29.257143-29.257143l0-263.314285q0-29.257143 29.257143-29.257143Z" + fill="#3DA9D3"></path> + <path + d="M404.772571 300.514743l129.462858 80.925257a15.945143 15.945143 0 0 1 0 27.062857l-129.462858 80.925257a15.945143 15.945143 0 0 1-24.429714-13.531428V314.046171a15.945143 15.945143 0 0 1 24.429714-13.531428z" + fill="#FFD469"></path> + <path + d="M219.428571 614.4m29.257143 0l394.971429 0q29.257143 0 29.257143 29.257143l0 0q0 29.257143-29.257143 29.257143l-394.971429 0q-29.257143 0-29.257143-29.257143l0 0q0-29.257143 29.257143-29.257143Z" + fill="#3DA9D3"></path> + <path + d="M219.428571 731.428571m29.257143 0l219.428572 0q29.257143 0 29.257143 29.257143l0 0q0 29.257143-29.257143 29.257143l-219.428572 0q-29.257143 0-29.257143-29.257143l0 0q0-29.257143 29.257143-29.257143Z" + fill="#3DA9D3"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/kichiku.svg b/bb-api-collect/assets/zone_icon/kichiku.svg new file mode 100644 index 0000000000..2d74f850ba --- /dev/null +++ b/bb-api-collect/assets/zone_icon/kichiku.svg @@ -0,0 +1,16 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M918.784 510.208a187.904 187.904 0 0 0-88.832-159.488 156.416 156.416 0 0 0 1.792-22.016 150.784 150.784 0 0 0-210.944-138.496 151.04 151.04 0 0 0-216.32 0 150.784 150.784 0 0 0-210.944 138.496 156.416 156.416 0 0 0 1.792 22.016 187.648 187.648 0 0 0-13.824 309.504v1.536a215.296 215.296 0 0 0 332.8 179.2 215.04 215.04 0 0 0 332.8-179.2v-2.56a187.904 187.904 0 0 0 71.68-148.992z" + fill="#FC6B8A"></path> + <path + d="M680.704 479.744A150.528 150.528 0 0 1 572.672 435.2a150.016 150.016 0 0 1-120.064 0 150.528 150.528 0 0 1-108.032 45.824h-11.264v167.168a166.4 166.4 0 0 0 165.888 165.888h33.536a166.4 166.4 0 0 0 165.888-165.888v-169.728a137.216 137.216 0 0 1-17.92 1.28z" + fill="#FFFFFF"></path> + <path d="M510.464 651.264m-33.536 0a33.536 33.536 0 1 0 67.072 0 33.536 33.536 0 1 0-67.072 0Z" fill="#E2006C"> + </path> + <path + d="M635.904 554.496H614.4v-21.504a12.032 12.032 0 0 0-11.776-11.776h-4.864a12.032 12.032 0 0 0-11.776 11.776v21.504h-21.248a11.776 11.776 0 0 0-11.776 11.52v5.12a11.776 11.776 0 0 0 11.776 11.52h21.248v21.504a12.032 12.032 0 0 0 11.776 11.776h4.864a12.032 12.032 0 0 0 11.776-11.776v-21.504h21.248a11.776 11.776 0 0 0 11.776-11.52v-5.12a11.776 11.776 0 0 0-11.52-11.52zM455.936 554.496H435.2v-21.504a12.032 12.032 0 0 0-11.776-11.776h-4.864a12.032 12.032 0 0 0-11.776 11.776v21.504H384a11.776 11.776 0 0 0-11.776 11.52v5.12a11.776 11.776 0 0 0 11.776 11.52h21.248v21.504a12.032 12.032 0 0 0 11.776 11.776h4.864a12.032 12.032 0 0 0 13.312-11.776v-21.504h21.248a11.52 11.52 0 0 0 11.776-11.52v-5.12a11.52 11.52 0 0 0-12.288-11.52z" + fill="#FF5C7A"></path> + <path + d="M600.32 651.008a12.288 12.288 0 0 0-12.288 12.544c0 34.048-34.816 61.696-76.8 61.696s-76.8-27.648-76.8-61.696a12.544 12.544 0 1 0-25.6 0c0 47.616 45.824 86.528 102.4 86.528s102.4-38.912 102.4-86.528a12.544 12.544 0 0 0-13.312-12.544z" + fill="#EB53A8"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/knowledge.svg b/bb-api-collect/assets/zone_icon/knowledge.svg new file mode 100644 index 0000000000..8ede0d7744 --- /dev/null +++ b/bb-api-collect/assets/zone_icon/knowledge.svg @@ -0,0 +1,18 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M492.270933 147.729067A255.342933 255.342933 0 0 1 627.2 620.2624v51.2a37.546667 37.546667 0 0 1-25.6 34.133333h-221.866667a44.654933 44.654933 0 0 1-25.6-34.133333v-51.2a256.648533 256.648533 0 0 1 138.1376-472.533333z" + fill="#FFA200"></path> + <path + d="M550.4 534.929067v-76.8h51.2c46.609067 0 51.2-26.786133 51.2-42.666667v-128c0-23.1168-17.2032-42.666667-51.2-42.666667h-213.333333c-42.103467 0-59.733333 21.111467-59.733334 42.666667v76.8h102.4v-68.266667h119.466667v119.466667h-51.2c-60.501333-0.5632-76.8 24.405333-76.8 42.666667v76.8h128z m-62.6688 24.533333a59.733333 59.733333 0 1 1-59.733333 59.733333 59.733333 59.733333 0 0 1 59.733333-59.733333z" + fill="#FFF0D3"></path> + <path d="M354.133333 739.7376h273.066667v8.533333a128 128 0 0 1-128 128h-17.066667a128 128 0 0 1-128-128v-8.533333z" + fill="#5FB5EC"></path> + <path + d="M746.666667 210.6624h119.466666a17.066667 17.066667 0 0 1 0 34.133333h-119.466666a17.066667 17.066667 0 0 1 0-34.133333z m59.733333-59.733333a17.066667 17.066667 0 0 1 17.066667 17.066666v119.466667a17.066667 17.066667 0 0 1-34.133334 0v-119.466667a17.066667 17.066667 0 0 1 17.066667-17.066666z" + fill="#FFE074"></path> + <path + d="M157.866667 662.929067h119.466666a17.066667 17.066667 0 0 1 0 34.133333h-119.466666a17.066667 17.066667 0 0 1 0-34.133333z m59.733333-59.733334a17.066667 17.066667 0 0 1 17.066667 17.066667v119.466667a17.066667 17.066667 0 0 1-34.133334 0v-119.466667a17.066667 17.066667 0 0 1 17.066667-17.066667z" + fill="#FFE074"></path> + <path d="M200.533333 662.9376h34.133334v34.133333h-34.133334z" fill="#FFE074"></path> + <path d="M789.333333 210.670933h34.133334v34.133334h-34.133334z" fill="#FFE074"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/life.svg b/bb-api-collect/assets/zone_icon/life.svg new file mode 100644 index 0000000000..ad03a79991 --- /dev/null +++ b/bb-api-collect/assets/zone_icon/life.svg @@ -0,0 +1,8 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M881.408 664.064V504.32a168.192 168.192 0 0 0-128-162.56l-7.936-1.792v144.896a12.288 12.288 0 0 1-14.592 11.776 170.752 170.752 0 0 0-30.464-2.816h-138.752v-27.648a37.632 37.632 0 0 1 11.776-27.648 175.872 175.872 0 0 0 57.856-135.68A179.2 179.2 0 0 0 460.8 132.352a175.872 175.872 0 0 0-180.992 176.128V409.6h32.256a225.536 225.536 0 0 0 15.872 19.2 36.608 36.608 0 0 1 9.472 25.6v42.496A193.792 193.792 0 0 0 179.2 712.96a197.12 197.12 0 0 0 197.12 166.656h325.12a148.48 148.48 0 0 0 45.568-6.144 217.088 217.088 0 0 0 64.256-31.744 176.896 176.896 0 0 0 18.176-15.616l4.608-4.352a156.16 156.16 0 0 0 47.36-111.872v-35.84c0.512-3.072 0.256-6.656 0-9.984z" + fill="#FFD778"></path> + <path + d="M468.736 238.592a40.192 40.192 0 1 0 40.192 40.192 40.192 40.192 0 0 0-40.192-40.192zM323.584 362.752H217.6a34.816 34.816 0 1 0 0 69.376h106.24a34.816 34.816 0 1 0 0-69.376z" + fill="#FB813A"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/movie.svg b/bb-api-collect/assets/zone_icon/movie.svg new file mode 100644 index 0000000000..5f691a4d94 --- /dev/null +++ b/bb-api-collect/assets/zone_icon/movie.svg @@ -0,0 +1,11 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M954.624 452.864H919.04v-168.96a37.376 37.376 0 0 0-25.6-36.608A36.608 36.608 0 0 0 846.848 281.6v170.24H199.936v-168.96a37.632 37.632 0 0 0-25.6-36.608A36.352 36.352 0 0 0 128 281.6v170.24H92.16a15.616 15.616 0 0 0-15.36 15.872v82.688a15.36 15.36 0 0 0 15.36 15.616h26.88v85.248a135.68 135.68 0 0 0 134.4 136.192h114.432a135.68 135.68 0 0 0 134.4-136.192v-20.992a7.936 7.936 0 0 1 7.68-7.936h25.6a7.68 7.68 0 0 1 7.68 7.936v20.992a135.936 135.936 0 0 0 134.4 136.192H793.6a135.68 135.68 0 0 0 134.4-136.192v-85.248h25.6a15.36 15.36 0 0 0 15.36-15.616v-81.664a15.616 15.616 0 0 0-15.36-15.872" + fill="#E5E6E6"></path> + <path + d="M361.216 727.552h-102.4A87.296 87.296 0 0 1 172.8 640v-79.872a61.184 61.184 0 0 1 60.416-61.44h153.6a61.184 61.184 0 0 1 60.416 61.44V640a87.296 87.296 0 0 1-86.528 87.552" + fill="#FF5C7A"></path> + <path + d="M685.568 727.552h102.4A87.296 87.296 0 0 0 873.984 640v-79.872a61.184 61.184 0 0 0-60.416-61.44h-153.6a61.184 61.184 0 0 0-60.416 61.44V640a87.296 87.296 0 0 0 86.528 87.552" + fill="#2CBAE5"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/music.svg b/bb-api-collect/assets/zone_icon/music.svg new file mode 100644 index 0000000000..408c93ce12 --- /dev/null +++ b/bb-api-collect/assets/zone_icon/music.svg @@ -0,0 +1,11 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M881.92 460.8A335.36 335.36 0 0 0 547.584 125.696h-73.216A335.616 335.616 0 0 0 139.776 460.8v313.6a18.688 18.688 0 0 0 18.432 18.688h41.984c13.568 46.336 37.888 80.384 88.576 80.384h98.304a37.376 37.376 0 0 0 37.376-36.864l1.28-284.672a36.864 36.864 0 0 0-37.12-37.12h-99.84a111.616 111.616 0 0 0-51.2 12.8v-73.216a242.432 242.432 0 0 1 241.664-241.664h67.328a242.176 242.176 0 0 1 241.408 241.664v74.496a110.592 110.592 0 0 0-54.272-14.08h-99.84a36.864 36.864 0 0 0-37.12 37.12v284.672a37.376 37.376 0 0 0 37.376 36.864h98.304c51.2 0 75.008-34.048 88.576-80.384h41.984a18.688 18.688 0 0 0 18.432-18.688z" + fill="#45C7DD"></path> + <path + d="M646.141043 825.220963m0.045396-32.511969l0.273801-196.095809q0.045395-32.511968 32.557364-32.466573l1.023999 0.00143q32.511968 0.045395 32.466573 32.557364l-0.273802 196.095809q-0.045395 32.511968-32.557363 32.466573l-1.023999-0.00143q-32.511968-0.045395-32.466573-32.557364Z" + fill="#FF5C7A"></path> + <path + d="M307.222608 825.246563m0.045395-32.511969l0.273801-196.095809q0.045395-32.511968 32.557364-32.466573l1.023999 0.00143q32.511968 0.045395 32.466573 32.557364l-0.273801 196.095809q-0.045395 32.511968-32.557364 32.466573l-1.023999-0.00143q-32.511968-0.045395-32.466573-32.557364Z" + fill="#FF5C7A"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/sports.svg b/bb-api-collect/assets/zone_icon/sports.svg new file mode 100644 index 0000000000..bd4c97e3d1 --- /dev/null +++ b/bb-api-collect/assets/zone_icon/sports.svg @@ -0,0 +1,8 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M497.8944 517.8624l23.8848 29.2608a58.5728 58.5728 0 0 1-5.6064 80.0512L241.9456 880.7424a47.7184 47.7184 0 0 1-65.6128-0.768 49.8176 49.8176 0 0 1-4.3008-66.816l108.5696-136.3712 126.1056-158.3616a58.5728 58.5728 0 0 1 91.1872-0.5632z" + fill="#1BAD8B"></path> + <path + d="M698.9312 153.6a117.1456 117.1456 0 0 1 11.4176 233.728l60.416 45.9008c4.352 3.328 10.1632 3.9168 15.104 1.5872l73.6256-34.6368a46.2848 46.2848 0 0 1 59.1104 17.5872 44.3392 44.3392 0 0 1-11.9296 59.3152l-125.952 90.2656a58.5728 58.5728 0 0 1-65.9456 1.5616l-66.048-42.752-44.1344 47.7696 70.6048 83.328c1.664 1.9456 3.2 4.0192 4.608 6.1952l1.9456 3.3024a58.5728 58.5728 0 0 1-22.8608 79.616l-192.1024 106.3424a49.3824 49.3824 0 0 1-65.7408-16.9984 52.096 52.096 0 0 1 11.904-68.5824l105.5488-83.1744-106.2912-68.3008-1.536-1.024a59.7504 59.7504 0 0 1-0.896-0.6144l-13.824-7.168a58.5728 58.5728 0 0 1-23.296-82.2784l71.68-118.8864-30.72-13.824a14.6432 14.6432 0 0 0-14.336 1.3312l-80.4864 55.6032a48.8704 48.8704 0 0 1-62.6688-5.9648 39.3472 39.3472 0 0 1 1.792-56.8576l128.2816-115.1488a58.5728 58.5728 0 0 1 57.4464-12.032l143.5392 47.2576A117.1456 117.1456 0 0 1 698.9312 153.6z" + fill="#57D59A"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/tech.svg b/bb-api-collect/assets/zone_icon/tech.svg new file mode 100644 index 0000000000..4c3795b1cd --- /dev/null +++ b/bb-api-collect/assets/zone_icon/tech.svg @@ -0,0 +1,12 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path d="M510.208 683.264h-114.176l-50.688 209.408H674.816l-50.688-209.408h-113.92z" fill="#FFD778"></path> + <path + d="M535.552 150.528v-28.16a25.6 25.6 0 1 0-51.2 0v28.16a271.872 271.872 0 0 0-244.992 269.568v97.28a25.6 25.6 0 0 0 26.88 26.88h487.936a25.6 25.6 0 0 0 25.6-26.88v-97.28a271.616 271.616 0 0 0-244.224-269.568z" + fill="#48CFE5"></path> + <path + d="M125.696 464.64m103.168 0l562.432 0q103.168 0 103.168 103.168l0 15.36q0 103.168-103.168 103.168l-562.432 0q-103.168 0-103.168-103.168l0-15.36q0-103.168 103.168-103.168Z" + fill="#2CBAE5"></path> + <path + d="M742.4 537.6a37.632 37.632 0 1 0 37.632 37.632A37.376 37.376 0 0 0 742.4 537.6zM276.736 537.6a37.632 37.632 0 1 0 37.632 37.632A37.632 37.632 0 0 0 276.736 537.6z" + fill="#FFD778"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_icon/teleplay.svg b/bb-api-collect/assets/zone_icon/teleplay.svg new file mode 100644 index 0000000000..a6a39afd10 --- /dev/null +++ b/bb-api-collect/assets/zone_icon/teleplay.svg @@ -0,0 +1,11 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="100%" height="100%"> + <path + d="M271.616 247.808a212.224 212.224 0 0 0-49.664 172.8l25.6 126.72c56.832 21.76 60.16 87.552 67.328 149.248a1167.872 1167.872 0 0 1 190.208-14.08 1247.488 1247.488 0 0 1 196.096 14.08c7.68-61.696 4.352-126.72 59.904-148.736l25.6-128a211.712 211.712 0 0 0-49.92-172.288 218.624 218.624 0 0 0-165.12-74.752h-134.912a218.624 218.624 0 0 0-165.12 74.752" + fill="#FFB161"></path> + <path + d="M505.088 412.672l-34.816-34.56a19.456 19.456 0 0 0-27.392 27.392l25.6 25.6-25.6 25.6a19.456 19.456 0 0 0 27.392 27.392l34.816-34.56 35.072 34.56a18.688 18.688 0 0 0 13.568 5.632 19.456 19.456 0 0 0 13.824-33.024l-25.6-25.6 25.6-25.6a19.456 19.456 0 0 0-13.824-33.024 18.688 18.688 0 0 0-13.568 5.632z" + fill="#FFE494"></path> + <path + d="M822.016 482.56a130.816 130.816 0 0 0-133.888 128v68.864l-368.128 1.536v-69.376a130.304 130.304 0 0 0-120.32-128h-13.568A81.92 81.92 0 0 0 102.4 563.2a76.8 76.8 0 0 0 0 13.312 79.104 79.104 0 0 0 38.912 54.784l8.96 4.352h2.304a25.6 25.6 0 0 1 15.36 22.016v63.744a112.384 112.384 0 0 0 80.896 105.472 51.2 51.2 0 0 0 98.816 5.888h313.088a51.2 51.2 0 0 0 98.816-5.888 112.384 112.384 0 0 0 79.104-105.472V650.752a25.6 25.6 0 0 1 8.192-11.52h1.536l4.608-2.816a80.384 80.384 0 0 0 51.2-61.44v-12.032a81.92 81.92 0 0 0-83.712-79.616" + fill="#FB952C"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/ai.svg b/bb-api-collect/assets/zone_v2_icon/ai.svg new file mode 100644 index 0000000000..797fd6fdd2 --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/ai.svg @@ -0,0 +1,17 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M6.11152 13.3818L12.7385 13.3818L14.074 16.2091L4.77077 16.2091L6.11152 13.3818z" + fill="#00B9E7ff"></path> + <path + d="M7.51228 5.77233C7.6183 5.49296 7.88599 5.30823 8.18479 5.30823L10.302 5.30823C10.5325 5.30823 10.6918 5.53896 10.61 5.75451L5.38035 19.5351C5.27433 19.8144 5.00664 19.9992 4.70783 19.9992L3.15565 19.9992C2.65222 19.9992 2.30452 19.4953 2.48314 19.0247L7.51228 5.77233z" + fill="#00B9E7ff"></path> + <path + d="M17.7595 5.24761C17.3688 5.24499 17.0508 5.5496 17.0515 5.92584L17.0642 19.3231C17.0648 19.6966 17.3794 19.9991 17.7673 19.9991L19.4532 19.9991C19.8415 19.9991 20.1563 19.6959 20.1563 19.322L20.1563 5.93605C20.1563 5.56393 19.8444 5.26155 19.458 5.25897L17.7595 5.24761z" + fill="#59E0F9ff"></path> + <path + d="M11.4125 5.77007C11.3065 5.4907 11.0388 5.30597 10.74 5.30597L8.14548 5.30597L13.5445 19.5328C13.6505 19.8122 13.9182 19.9969 14.217 19.9969L15.7691 19.9969C16.2726 19.9969 16.6203 19.4931 16.4417 19.0224L11.4125 5.77007z" + fill="#59E0F9ff"></path> + <path + d="M21.8385 2.26096C21.9179 2.10202 22.1446 2.10202 22.224 2.26096L22.3536 2.52039C22.6034 3.02047 22.9711 3.45233 23.4249 3.77874L23.663 3.95005C23.7826 4.03605 23.7826 4.21395 23.663 4.29994L23.4249 4.47126C22.9711 4.79767 22.6034 5.22952 22.3536 5.72961L22.224 5.98904C22.1446 6.14798 21.9179 6.14798 21.8385 5.98904L21.7089 5.72961C21.4591 5.22952 21.0914 4.79767 20.6376 4.47126L20.3995 4.29994C20.2799 4.21395 20.2799 4.03605 20.3995 3.95005L20.6376 3.77874C21.0914 3.45233 21.4591 3.02047 21.7089 2.52039L21.8385 2.26096z" + fill="#FDDE80ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/animal.svg b/bb-api-collect/assets/zone_v2_icon/animal.svg new file mode 100644 index 0000000000..74cb01e24a --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/animal.svg @@ -0,0 +1,11 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M14.36582 3.67143C15.80352 3.65373 17.00323 4.92678 17.39434 6.70047C17.46086 7.00223 17.7719 7.19548 18.07651 7.14389C18.6671 7.04388 19.24147 7.11564 19.73645 7.38712C21.21533 8.19796 21.42538 10.48176 20.20589 12.48835C19.88563 13.02058 19.48099 13.49606 19.00848 13.89667C18.84211 14.0377 18.77798 14.26694 18.84067 14.47584C18.95462 14.85523 19.01606 15.25757 19.01606 15.67392L19.01606 16.1641C19.01606 17.26858 18.57734 18.32774 17.79638 19.1087C17.01542 19.88966 15.95626 20.32838 14.85178 20.32838L9.29912 20.32838C8.19468 20.32838 7.1355 19.88966 6.35456 19.1087C5.57361 18.32774 5.13488 17.26858 5.13488 16.1641L5.13488 15.67392C5.13488 15.25699 5.19634 14.85485 5.31033 14.47517C5.37301 14.26637 5.3088 14.03712 5.14245 13.89619C4.66991 13.49578 4.26526 13.02038 3.94509 12.48835C2.72556 10.48176 2.93556 8.19796 4.41446 7.38712C4.90967 7.11554 5.48421 7.04383 6.07527 7.14374C6.37981 7.19522 6.69059 7.0019 6.75702 6.70026C7.14757 4.92688 8.34733 3.65373 9.78518 3.67143C10.47494 3.68023 11.11843 3.98481 11.64941 4.49674C11.88154 4.72055 12.26957 4.72063 12.5017 4.49685C13.03267 3.98511 13.67597 3.68023 14.36582 3.67143z" + fill="#FF5C7Aff"></path> + <path + d="M11.7289 7.80475C11.84861 8.98123 11.20435 9.99031 10.28861 10.05924C9.3728 10.12819 8.53423 9.22949 8.41399 8.05301C8.29375 6.87653 8.93848 5.86693 9.85373 5.79852C10.76957 5.72959 11.60861 6.62827 11.7289 7.80475zM15.7225 8.05301C15.60221 9.23001 14.76317 10.12762 13.8479 10.05924C12.93264 9.99083 12.28733 8.98071 12.40762 7.80423C12.52781 6.62775 13.36694 5.72959 14.28269 5.79852C15.19795 5.86693 15.84269 6.87653 15.7225 8.05301zM18.16906 11.42227C17.58182 12.4055 16.52822 12.8807 15.8161 12.48317C15.10349 12.08573 15.0024 10.96675 15.59011 9.98358C16.17734 9.00041 17.23104 8.52516 17.94365 8.92267C18.65578 9.32019 18.75677 10.43914 18.16906 11.42227zM8.55615 9.98358C9.14388 10.96675 9.04281 12.08573 8.33018 12.48317C7.61808 12.8807 6.56443 12.4055 5.97671 11.42227C5.38951 10.43914 5.49057 9.32019 6.20319 8.92267C6.9153 8.52516 7.96895 9.00041 8.55615 9.98358z" + fill="#FFCFE6ff"></path> + <path + d="M12.17328 11.43072C12.72787 11.43072 13.26845 11.60534 13.71821 11.92982C13.89734 12.05904 14.06899 12.21734 14.21914 12.39619C14.67053 12.9337 15.25728 13.46515 15.83606 13.8623C16.0105 13.98192 16.16976 14.12496 16.30896 14.28874C16.70842 14.75875 16.91242 15.36394 16.8791 15.97978C16.84579 16.59562 16.57757 17.17526 16.12973 17.5993C15.68189 18.02342 15.08851 18.25968 14.47181 18.25949L9.67882 18.25949C9.06126 18.26083 8.46676 18.02506 8.018 17.60074C7.56923 17.17651 7.30045 16.59619 7.26714 15.97949C7.23383 15.36288 7.43852 14.75693 7.83897 14.28682C7.97802 14.12352 8.137 13.98096 8.31101 13.86173C8.89154 13.46381 9.5054 12.94397 9.94973 12.39821C10.10381 12.20899 10.27306 12.04474 10.43242 11.92982C10.88218 11.60534 11.42275 11.43072 11.97734 11.43072L12.17328 11.43072z" + fill="#FFCFE6ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/car.svg b/bb-api-collect/assets/zone_v2_icon/car.svg new file mode 100644 index 0000000000..9dd5705532 --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/car.svg @@ -0,0 +1,23 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M21.24202 9.24032C21.31075 9.46754 21.28675 9.71272 21.1753 9.92231C21.06374 10.13194 20.87386 10.2888 20.64701 10.35888L20.0521 10.53139C19.93997 10.56576 19.82218 10.57776 19.70544 10.56653C19.5887 10.55539 19.47533 10.52141 19.37174 10.4664C19.26816 10.41149 19.17638 10.33661 19.1017 10.24618C19.02701 10.15574 18.97094 10.05152 18.93658 9.9394C18.90221 9.82728 18.89021 9.70949 18.90134 9.59275C18.91248 9.47601 18.94656 9.36261 19.00147 9.25902C19.05648 9.15543 19.13126 9.06369 19.2217 8.98902C19.31213 8.91435 19.41638 8.85823 19.52851 8.82385L20.12352 8.65131C20.23555 8.61552 20.35363 8.6024 20.47085 8.61272C20.58806 8.62304 20.70211 8.65659 20.80618 8.71141C20.91034 8.76624 21.0025 8.84124 21.07728 8.93204C21.15206 9.02286 21.20813 9.12765 21.24202 9.24032zM5.17807 9.93642C5.10935 10.16285 4.95356 10.35264 4.74493 10.46419C4.53631 10.57574 4.29192 10.59994 4.06548 10.53139L3.47052 10.35888C3.2437 10.2888 3.0538 10.13194 2.94231 9.92231C2.83084 9.71272 2.80684 9.46754 2.87556 9.24032C2.9089 9.12779 2.96424 9.02298 3.03839 8.932C3.11254 8.84102 3.20402 8.76568 3.30752 8.71033C3.41101 8.65499 3.52448 8.62074 3.64131 8.60959C3.75815 8.59843 3.87604 8.6106 3.98814 8.64536L4.5831 8.8179C4.69586 8.85188 4.80079 8.90785 4.89181 8.98257C4.98284 9.05729 5.05818 9.1493 5.11349 9.25328C5.16879 9.35725 5.20298 9.47115 5.21406 9.58839C5.22515 9.70564 5.21291 9.82393 5.17807 9.93642z" + fill="#00B9E7ff"></path> + <path + d="M6.97476 4.78406C8.65316 4.44467 10.36118 4.27327 12.07354 4.27239C13.82131 4.27461 15.56477 4.44596 17.27952 4.78406C17.47834 4.82236 17.6641 4.91076 17.81923 5.04089C17.97437 5.17104 18.0937 5.33861 18.16598 5.52776L20.34038 11.24707C20.38176 11.35603 20.40307 11.47171 20.40307 11.58826L20.40307 16.76659C20.40307 16.92442 20.34038 17.07571 20.22874 17.18726C20.11718 17.29882 19.96589 17.3615 19.80806 17.3615L4.33908 17.3615C4.18129 17.3615 4.02996 17.29882 3.91837 17.18726C3.8068 17.07571 3.74412 16.92442 3.74412 16.76659L3.74412 11.59834C3.74412 11.47526 3.76781 11.35325 3.8139 11.23901L6.12396 5.51586C6.19464 5.33331 6.30926 5.17102 6.45767 5.04336C6.60609 4.91571 6.7837 4.82665 6.97476 4.78406z" + fill="#00B9E7ff"></path> + <path + d="M5.529 12.00691L7.90884 12.00691C8.30549 12.00691 8.5038 12.20515 8.5038 12.60182L8.5038 13.19683C8.5038 13.59341 8.30549 13.79174 7.90884 13.79174L5.529 13.79174C5.13236 13.79174 4.93404 13.59341 4.93404 13.19683L4.93404 12.60182C4.93404 12.20515 5.13236 12.00691 5.529 12.00691z" + fill="#FDDE80ff"></path> + <path + d="M16.2383 12.00691L18.61814 12.00691C19.01482 12.00691 19.21315 12.20515 19.21315 12.60182L19.21315 13.19683C19.21315 13.59341 19.01482 13.79174 18.61814 13.79174L16.2383 13.79174C15.84173 13.79174 15.64339 13.59341 15.64339 13.19683L15.64339 12.60182C15.64339 12.20515 15.84173 12.00691 16.2383 12.00691z" + fill="#FDDE80ff"></path> + <path + d="M7.79001 6.40233C9.11029 6.17235 10.44797 6.05689 11.78813 6.05724C13.31962 6.07062 14.84832 6.1899 16.36339 6.41422C16.47677 6.43024 16.58304 6.47862 16.66954 6.55355C16.75613 6.62846 16.8192 6.72677 16.85126 6.83665L17.77344 9.96614C17.79533 10.04115 17.80224 10.11974 17.7937 10.19741C17.78525 10.27507 17.76154 10.35034 17.724 10.41878C17.68637 10.48733 17.63568 10.54771 17.57482 10.59667C17.51386 10.64554 17.44387 10.68202 17.3689 10.7039C17.29622 10.7185 17.22144 10.7185 17.14877 10.7039C15.20918 10.51747 13.42426 10.42426 11.79408 10.42426C10.20394 10.4255 8.61508 10.51286 7.0344 10.68605C6.95666 10.6943 6.87804 10.6871 6.80307 10.66502C6.72808 10.64285 6.6582 10.60608 6.59743 10.55693C6.53665 10.50778 6.48615 10.4471 6.44884 10.37837C6.41152 10.30963 6.38811 10.23427 6.37995 10.15651C6.36471 10.07993 6.36471 10.00109 6.37995 9.9245L7.31404 6.81879C7.3462 6.71165 7.40791 6.61574 7.4921 6.54207C7.57629 6.46841 7.67954 6.41997 7.79001 6.40233z" + fill="#59E1F9ff"></path> + <path + d="M3.74414 15.65299C3.74414 14.85763 4.38885 14.21299 5.18414 14.21299L5.28938 14.21299C6.08466 14.21299 6.72938 14.85763 6.72938 15.65299L6.72938 17.70653C6.72938 18.50189 6.08466 19.14653 5.28938 19.14653L5.18414 19.14653C4.38885 19.14653 3.74414 18.50189 3.74414 17.70653L3.74414 15.65299z" + fill="#00B9E7ff"></path> + <path + d="M17.42822 15.65299C17.42822 14.85763 18.07296 14.21299 18.86822 14.21299L18.97344 14.21299C19.7688 14.21299 20.41344 14.85763 20.41344 15.65299L20.41344 17.70653C20.41344 18.50189 19.7688 19.14653 18.97344 19.14653L18.86822 19.14653C18.07296 19.14653 17.42822 18.50189 17.42822 17.70653L17.42822 15.65299z" + fill="#00B9E7ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/cinephile.svg b/bb-api-collect/assets/zone_v2_icon/cinephile.svg new file mode 100644 index 0000000000..de746dccb7 --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/cinephile.svg @@ -0,0 +1,32 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M5.16093 18.89558L18.83645 18.89558C19.63171 18.89558 20.27645 18.25085 20.27645 17.45558L20.27645 6.34031C20.27645 5.54503 19.63171 4.90031 18.83645 4.90031L5.16094 4.90031C4.36565 4.90031 3.72094 5.54503 3.72094 6.34031L3.72094 17.45558C3.72094 18.25085 4.36565 18.89558 5.16093 18.89558z" + fill="#9796EDff"></path> + <path + d="M5.49187 7.15125C5.49187 7.54889 5.81423 7.87125 6.21187 7.87125L7.53881 7.87125C7.93645 7.87125 8.25881 7.54889 8.25881 7.15125C8.25881 6.75361 7.93645 6.43125 7.53881 6.43125L6.21187 6.43125C5.81423 6.43125 5.49187 6.75361 5.49187 7.15125z" + fill="#6D69E4ff"></path> + <path + d="M10.6897 7.15125C10.6897 7.54889 11.01206 7.87125 11.4097 7.87125L12.73661 7.87125C13.13424 7.87125 13.45661 7.54889 13.45661 7.15125C13.45661 6.75361 13.13424 6.43125 12.73661 6.43125L11.4097 6.43125C11.01206 6.43125 10.6897 6.75361 10.6897 7.15125z" + fill="#6D69E4ff"></path> + <path + d="M15.88733 7.15125C15.88733 7.54889 16.2097 7.87125 16.60733 7.87125L17.93424 7.87125C18.33187 7.87125 18.65424 7.54889 18.65424 7.15125C18.65424 6.75361 18.33187 6.43125 17.93424 6.43125L16.60733 6.43125C16.2097 6.43125 15.88733 6.75361 15.88733 7.15125z" + fill="#6D69E4ff"></path> + <path + d="M5.49187 17.14742C5.49187 17.54515 5.81423 17.86742 6.21187 17.86742L7.53881 17.86742C7.93645 17.86742 8.25881 17.54515 8.25881 17.14742C8.25881 16.74979 7.93645 16.42742 7.53881 16.42742L6.21187 16.42742C5.81423 16.42742 5.49187 16.74979 5.49187 17.14742z" + fill="#6D69E4ff"></path> + <path + d="M10.6897 17.14742C10.6897 17.54515 11.01206 17.86742 11.4097 17.86742L12.73661 17.86742C13.13424 17.86742 13.45661 17.54515 13.45661 17.14742C13.45661 16.74979 13.13424 16.42742 12.73661 16.42742L11.4097 16.42742C11.01206 16.42742 10.6897 16.74979 10.6897 17.14742z" + fill="#6D69E4ff"></path> + <path + d="M15.88733 17.14742C15.88733 17.54515 16.2097 17.86742 16.60733 17.86742L17.93424 17.86742C18.33187 17.86742 18.65424 17.54515 18.65424 17.14742C18.65424 16.74979 18.33187 16.42742 17.93424 16.42742L16.60733 16.42742C16.2097 16.42742 15.88733 16.74979 15.88733 17.14742z" + fill="#6D69E4ff"></path> + <path + d="M3.72094 14.9591L20.27645 14.9591L20.27645 8.83594L3.72094 8.83594L3.72094 14.9591z" + fill="#6D69E4ff"></path> + <path + d="M9.8783 12.948C9.91536 12.84787 9.93389 12.79776 9.95213 12.77434C10.02883 12.67565 10.17802 12.67565 10.25482 12.77434C10.27296 12.79776 10.29149 12.84787 10.32854 12.948C10.53485 13.50557 10.97443 13.94515 11.532 14.15146C11.63222 14.18851 11.68224 14.20704 11.70566 14.22528C11.80435 14.30198 11.80435 14.45117 11.70566 14.52787C11.68224 14.54611 11.63222 14.56464 11.532 14.6017C10.97443 14.808 10.53485 15.24758 10.32854 15.80515C10.29149 15.90528 10.27296 15.95539 10.25482 15.97882C10.17802 16.0775 10.02883 16.0775 9.95213 15.97882C9.93389 15.95539 9.91536 15.90528 9.8783 15.80515C9.672 15.24758 9.23242 14.808 8.67487 14.6017C8.5747 14.56464 8.52462 14.54611 8.50123 14.52787C8.40254 14.45117 8.40254 14.30198 8.50123 14.22528C8.52462 14.20704 8.5747 14.18851 8.67487 14.15146C9.23242 13.94515 9.672 13.50557 9.8783 12.948z" + fill="#FDDE80ff"></path> + <path + d="M13.42128 6.99748C13.50605 6.76846 13.54838 6.65394 13.58995 6.60048C13.76544 6.37484 14.10653 6.37484 14.28202 6.60048C14.32358 6.65394 14.36592 6.76846 14.45069 6.99748C14.92234 8.27225 15.92746 9.27733 17.20224 9.74909C17.4313 9.83376 17.54573 9.87619 17.5992 9.91776C17.8249 10.09325 17.8249 10.43424 17.5992 10.60973C17.54573 10.6513 17.4313 10.69373 17.20224 10.7785C15.92746 11.25014 14.92234 12.25526 14.45069 13.53005C14.36592 13.75901 14.32358 13.87354 14.28202 13.92701C14.10653 14.1527 13.76544 14.1527 13.58995 13.92701C13.54838 13.87354 13.50605 13.75901 13.42128 13.53005C12.94954 12.25526 11.94451 11.25014 10.66973 10.7785C10.44067 10.69373 10.32614 10.6513 10.27267 10.60973C10.04707 10.43424 10.04707 10.09325 10.27267 9.91776C10.32614 9.87619 10.44067 9.83376 10.66973 9.74909C11.94451 9.27733 12.94954 8.27225 13.42128 6.99748z" + fill="#FDDE80ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/dance.svg b/bb-api-collect/assets/zone_v2_icon/dance.svg new file mode 100644 index 0000000000..10822524bc --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/dance.svg @@ -0,0 +1,23 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M22.45853 11.58826C22.62758 11.94816 22.47293 12.37699 22.11302 12.54614L11.7097 17.43446C11.34979 17.60362 10.92096 17.44896 10.7519 17.08906C10.58275 16.72915 10.73741 16.30032 11.09731 16.13117L21.50064 11.24285C21.86054 11.0737 22.28938 11.22845 22.45853 11.58826z" + fill="#FFCFE6ff"></path> + <path + d="M17.59709 7.57625C17.94307 7.77225 18.06461 8.21161 17.86867 8.55759L12.62534 17.81386C12.42941 18.15984 11.99002 18.28138 11.64403 18.08544C11.29805 17.88941 11.17642 17.45002 11.37245 17.10403L16.61568 7.84786C16.81171 7.50186 17.2511 7.38026 17.59709 7.57625z" + fill="#FFCFE6ff"></path> + <path + d="M12.16022 6.47833C12.55786 6.47833 12.88022 6.80069 12.88022 7.19833L12.88022 17.40806C12.88022 17.8057 12.55786 18.12806 12.16022 18.12806C11.76259 18.12806 11.44022 17.8057 11.44022 17.40806L11.44022 7.19833C11.44022 6.80069 11.76259 6.47833 12.16022 6.47833z" + fill="#FFCFE6ff"></path> + <path + d="M6.70345 8.53544C7.03465 8.31539 7.48154 8.40548 7.7016 8.73668L13.0248 16.74845C13.24493 17.07965 13.15478 17.52653 12.82358 17.74656C12.49238 17.96669 12.0455 17.87654 11.82547 17.54534L6.5022 9.53359C6.28214 9.20239 6.37225 8.7555 6.70345 8.53544z" + fill="#FFCFE6ff"></path> + <path + d="M9.66182 17.5007C9.57036 17.28797 9.68467 17.0519 9.89453 16.95398L12.09898 15.92611L14.30141 16.95312C14.51126 17.05094 14.6256 17.28691 14.5343 17.49955C14.1288 18.44381 13.1905 19.10515 12.09782 19.10515C11.00554 19.10515 10.06752 18.44429 9.66182 17.5007z" + fill="#FFCFE6ff"></path> + <path + d="M7.16267 14.97974C7.7695 12.8303 9.75514 11.23526 12.09878 11.23526C14.44253 11.23526 16.4183 12.81062 17.02512 14.96026L22.13731 12.53549C22.50115 12.36288 22.67424 11.93654 22.5119 11.568C22.49309 11.52528 22.47504 11.48554 22.45862 11.45078C20.62118 7.57511 16.67299 4.89487 12.09878 4.89487C7.45255 4.89487 3.4522 7.66017 1.65375 11.63472L1.65375 11.63472C1.49874 11.97734 1.64364 12.38957 1.98407 12.54922C3.48774 13.25472 7.16267 14.97974 7.16267 14.97974z" + fill="#FF5C7Aff"></path> + <path + d="M1.65842 11.60611C1.82741 11.24611 2.2562 11.09126 2.61615 11.26032L12.85507 16.06723C13.21507 16.23619 13.36982 16.66502 13.20086 17.02493C13.0319 17.38493 12.60307 17.53968 12.24317 17.37072L2.00419 12.56381C1.64424 12.39485 1.48943 11.96602 1.65842 11.60611z" + fill="#FFCFE6ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/douga.svg b/bb-api-collect/assets/zone_v2_icon/douga.svg new file mode 100644 index 0000000000..00a4f8cc09 --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/douga.svg @@ -0,0 +1,26 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M5.67687 4.05598L5.67687 4.05598C4.8817 4.05598 4.23687 4.70064 4.23687 5.49582L4.23687 11.94893L8.11451 15.3912L12.12979 11.94893L12.12979 4.05598L5.67687 4.05598z" + fill="#6D69E4ff"></path> + <path + d="M15.57206 15.82656L12.12979 19.72838L5.67687 19.72838C4.88158 19.72838 4.23687 19.08365 4.23687 18.28838L4.23687 11.94893L6.74114 11.94893C6.63916 12.15446 6.58075 12.38554 6.58075 12.63053C6.58075 13.47792 7.26776 14.16461 8.11482 14.16461C8.96189 14.16461 9.64886 13.47792 9.64886 12.63053C9.64886 12.38554 9.59049 12.15446 9.48819 11.94893L12.12979 11.94893L15.57206 15.82656z" + fill="#9796EDff"></path> + <path + d="M16.00752 8.16033L12.12989 11.63318L12.12989 14.24419C12.33542 14.14195 12.56659 14.08349 12.81158 14.08349C13.65898 14.08349 14.34566 14.77046 14.34566 15.61757C14.34566 16.46467 13.65898 17.15165 12.81158 17.15165C12.56659 17.15165 12.33542 17.09357 12.12989 16.99094L12.12989 19.72838L18.46934 19.72838C19.26461 19.72838 19.90934 19.08365 19.90934 18.28838L19.90934 11.63318L16.00752 8.16033z" + fill="#6D69E4ff"></path> + <path + d="M18.46934 4.05598C19.26461 4.05598 19.90934 4.70069 19.90934 5.49598L19.90934 11.94893L17.38723 11.94893C17.48947 11.74339 17.54755 11.51222 17.54755 11.26694C17.54755 10.41984 16.86086 9.73286 16.01357 9.73286C15.16646 9.73286 14.47949 10.41984 14.47949 11.26694C14.47949 11.51222 14.53786 11.74339 14.64019 11.94893L12.12989 11.94893L12.12989 9.3073C11.92435 9.40959 11.69328 9.46768 11.44829 9.46768C10.6009 9.46768 9.91392 8.781 9.91392 7.93361C9.91392 7.08655 10.6009 6.39986 11.44829 6.39986C11.69328 6.39986 11.92435 6.45795 12.12989 6.56025L12.12989 4.05598L18.46934 4.05598z" + fill="#9796EDff"></path> + <path + d="M12.12979 9.04368L10.4809 8.09169C9.47782 7.51265 8.65694 7.98655 8.65694 9.14492L8.65694 14.57338C8.65694 14.69107 8.66543 14.80176 8.68171 14.90496L12.12979 11.94893L12.12979 9.04368z" + fill="#FDDE80ff"></path> + <path + d="M13.72944 13.75075L10.4809 15.6263C9.47782 16.20557 8.65694 15.73171 8.65694 14.57338L8.65694 14.06611C9.23658 13.84704 9.64886 13.28707 9.64886 12.63053C9.64886 12.38554 9.59049 12.15446 9.48819 11.94893L12.12979 11.94893L13.72944 13.75075z" + fill="#FDDE80ff"></path> + <path + d="M13.88794 10.05869L15.1823 10.80595C16.18531 11.38522 16.18531 12.33302 15.1823 12.9121L13.10477 14.11152C13.00982 14.09309 12.91181 14.08349 12.81158 14.08349C12.56659 14.08349 12.33542 14.14195 12.12989 14.24419L12.12989 11.63318L13.88794 10.05869z" + fill="#FDDE80ff"></path> + <path + d="M8.65694 9.14491C8.65694 7.98655 9.47781 7.51266 10.4808 8.09169L15.18221 10.80586C16.18522 11.38522 16.18522 12.33302 15.18221 12.9121L10.4808 15.6263C9.47781 16.20557 8.65694 15.73171 8.65694 14.57338L8.65694 9.14491z" + fill="#FDDE80ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/emotion.svg b/bb-api-collect/assets/zone_v2_icon/emotion.svg new file mode 100644 index 0000000000..8ed2de6dbe --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/emotion.svg @@ -0,0 +1,8 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M11.64326 6.75353C8.80572 2.45969 3.05423 4.99012 3.47601 9.85922C3.84148 14.0784 8.01705 17.41958 10.97002 19.14355C11.38675 19.38691 11.89891 19.38691 12.31574 19.14355C15.26842 17.41958 19.44403 14.0783 19.8095 9.85922C20.23123 4.99012 14.48035 2.45969 11.64326 6.75353z" + fill="#FF5C7Aff"></path> + <path + d="M16.95014 12.98275C16.39747 10.17744 12.90787 10.2649 12.09763 12.85632C11.43677 14.97024 12.67536 17.39645 13.7856 18.93235C14.06842 19.32355 14.54659 19.51978 15.02266 19.44C16.89158 19.12675 19.47754 18.27005 20.49216 16.30128C21.73584 13.88774 19.31395 11.37437 16.95014 12.98275z" + fill="#FFCFE6ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/entertainment.svg b/bb-api-collect/assets/zone_v2_icon/entertainment.svg new file mode 100644 index 0000000000..b69d02f7cb --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/entertainment.svg @@ -0,0 +1,20 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M5.92972 20.481C5.34469 21.0726 4.39035 21.075 3.80205 20.4867L3.42324 20.1078C2.83711 19.5217 2.83752 18.5713 3.42416 17.9856L12.0134 9.41117C12.372 9.05293 12.9589 9.05293 13.3175 9.41117L14.4768 10.5692C14.8355 10.9275 14.8355 11.5132 14.4768 11.8714C12.0808 14.2648 7.88596 18.5029 5.92972 20.481z" + fill="#FF5C7Aff"></path> + <path + d="M8.72852 12.693L12.0139 9.41126C12.3725 9.05302 12.9593 9.05302 13.318 9.41126L14.4773 10.5693C14.836 10.9276 14.836 11.5137 14.4773 11.872L11.1758 15.1698L8.72852 12.693z" + fill="#FC6376ff"></path> + <path + d="M16.2118 14.531C16.5704 14.8893 16.971 14.782 17.1024 14.2925L19.5843 5.04082C19.7152 4.55181 19.422 4.25849 18.932 4.38973L9.67009 6.86887C9.18053 6.99964 9.07312 7.40025 9.43176 7.75849L16.2118 14.531z" + fill="#FDDE80ff"></path> + <path + d="M20.7561 9.99241C21.1147 10.3507 21.0073 10.7508 20.5173 10.882L11.2554 13.3612C10.7658 13.4919 10.4722 13.1991 10.6036 12.7096L13.0855 3.45795C13.2164 2.96893 13.6174 2.86165 13.9761 3.21989L20.7561 9.99241z" + fill="#FDDE80ff"></path> + <path + d="M6.6992 14.7177L9.17585 17.167L8.47269 17.878L5.99603 15.4287L6.6992 14.7177z" + fill="#FFCFE6ff"></path> + <path + d="M8.67909 12.7448L11.1456 15.2003L10.44 15.909L7.97356 13.4535L8.67909 12.7448z" + fill="#FFCFE6ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/fashion.svg b/bb-api-collect/assets/zone_v2_icon/fashion.svg new file mode 100644 index 0000000000..5572bef511 --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/fashion.svg @@ -0,0 +1,14 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M16.0695 2.7305C12.7258 3.85612 10.9074 4.09695 8.30573 2.7305L12.1298 8.01044L16.0695 2.7305z" + fill="#FFCFE6ff"></path> + <path + d="M8.37409 10.243C6.22673 12.7549 5.26956 15.1018 4.17298 18.4108C4.09425 18.6483 4.10943 18.9135 4.27234 19.1035C6.38097 21.5625 16.2982 21.696 19.208 19.118C19.4281 18.923 19.4887 18.6141 19.4071 18.3315C18.4274 14.9392 16.8594 12.462 14.8639 10.243L8.37409 10.243z" + fill="#FF5C7Aff"></path> + <path + d="M6.71505 2.5833C7.21559 2.4809 7.56291 2.47743 8.05183 2.52926C8.29103 2.55462 8.50926 2.67534 8.66566 2.85809L11.0339 5.6253C11.3497 5.99425 11.9202 5.99425 12.236 5.6253L14.5849 2.88068C14.7528 2.68446 14.9917 2.56125 15.2493 2.54369C15.689 2.51373 16.0305 2.51088 16.555 2.59268C17.7675 2.77617 18.4473 4.98552 18.4928 6.49521C18.5014 6.77775 18.3517 7.04445 18.089 7.1489C17.3664 7.43628 16.3941 7.44278 15.6755 7.33024L14.8472 10.6895C12.29 11.0952 10.8825 11.103 8.42274 10.6895L7.60432 7.36766C6.85494 7.52539 5.78994 7.47444 5.07016 7.13883C4.84587 7.03425 4.71412 6.80481 4.71142 6.55735C4.69584 5.13103 5.45156 3.01836 6.71505 2.5833z" + fill="#FF5C7Aff"></path> + <path + d="M8.19688 9.85347C9.66073 10.5601 13.5345 10.7668 15.1159 9.75003L15.6793 11.2107C12.9174 12.2073 9.85241 12.1155 7.65021 11.2107L8.19688 9.85347z" + fill="#FFCFE6ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/food.svg b/bb-api-collect/assets/zone_v2_icon/food.svg new file mode 100644 index 0000000000..b9ada08649 --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/food.svg @@ -0,0 +1,23 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M3.18094 10.5647C3.18094 11.01408 3.35942 11.44493 3.67714 11.76269C3.99484 12.08035 4.42574 12.25882 4.87505 12.25882C5.32436 12.25882 5.75527 12.08035 6.07298 11.76269C6.39068 11.44493 6.56917 11.01408 6.56917 10.5647C6.56917 10.11542 6.39068 9.68453 6.07298 9.36682C5.75527 9.04911 5.32436 8.87062 4.87505 8.87062C4.42574 8.87062 3.99484 9.04911 3.67714 9.36682C3.35942 9.68453 3.18094 10.11542 3.18094 10.5647z" + fill="#FB813Aff"></path> + <path + d="M5.69523 9.30581C5.69518 9.60927 5.76987 9.90977 5.91502 10.19011C6.06016 10.47053 6.27294 10.72531 6.54118 10.93987C6.80942 11.15443 7.12788 11.32474 7.47837 11.4408C7.82887 11.55696 8.20452 11.61677 8.5839 11.61677C8.96327 11.61677 9.33893 11.55696 9.68938 11.4408C10.03987 11.32474 10.3584 11.15443 10.62662 10.93987C10.89485 10.72531 11.10758 10.47053 11.25274 10.19011C11.39789 9.90977 11.47258 9.60927 11.47258 9.30581C11.47258 9.00234 11.39789 8.70184 11.25274 8.42147C11.10758 8.1411 10.89485 7.88634 10.62662 7.67174C10.3584 7.45715 10.03987 7.28693 9.68938 7.17079C9.33893 7.05465 8.96327 6.99487 8.5839 6.99487C8.20452 6.99487 7.82887 7.05465 7.47837 7.17079C7.12788 7.28693 6.80942 7.45715 6.54118 7.67174C6.27294 7.88634 6.06016 8.1411 5.91502 8.42147C5.76987 8.70184 5.69518 9.00234 5.69523 9.30581z" + fill="#FB813Aff"></path> + <path + d="M14.90909 11.21645C14.90899 11.59296 14.9832 11.96582 15.1272 12.31373C15.2713 12.66163 15.4825 12.97766 15.7487 13.24397C16.01501 13.51018 16.33104 13.72147 16.67894 13.86557C17.02675 14.00966 17.39962 14.08378 17.77622 14.08378C18.15274 14.08378 18.5256 14.00966 18.87341 13.86557C19.22131 13.72147 19.53744 13.51018 19.80365 13.24397C20.06986 12.97766 20.28106 12.66163 20.42515 12.31373C20.56925 11.96582 20.64336 11.59296 20.64326 11.21645C20.64336 10.83994 20.56925 10.46707 20.42515 10.11917C20.28106 9.77126 20.06986 9.45516 19.80365 9.1889C19.53744 8.92264 19.22131 8.71142 18.87341 8.56733C18.5256 8.42322 18.15274 8.34905 17.77622 8.34905C17.39962 8.34905 17.02675 8.42322 16.67894 8.56733C16.33104 8.71142 16.01501 8.92264 15.7487 9.1889C15.4825 9.45516 15.2713 9.77126 15.1272 10.11917C14.9832 10.46707 14.90899 10.83994 14.90909 11.21645z" + fill="#FB813Aff"></path> + <path + d="M11.7816 9.52223C11.7816 9.91584 11.85907 10.3056 12.0097 10.66925C12.16032 11.0329 12.38112 11.36323 12.65942 11.64163C12.93773 11.91994 13.26816 12.14074 13.63181 12.29136C13.99546 12.44198 14.38522 12.51946 14.77882 12.51946C15.17242 12.51946 15.56218 12.44198 15.92582 12.29136C16.28947 12.14074 16.61981 11.91994 16.89821 11.64163C17.17651 11.36323 17.39722 11.0329 17.54784 10.66925C17.69846 10.3056 17.77603 9.91584 17.77603 9.52223C17.77603 8.72732 17.46029 7.96496 16.89821 7.40287C16.33603 6.84078 15.5737 6.525 14.77882 6.525C13.98384 6.525 13.2215 6.84078 12.65942 7.40287C12.09734 7.96496 11.7816 8.72732 11.7816 9.52223z" + fill="#FB813Aff"></path> + <path + d="M21.52992 9.91312C21.70147 9.91322 21.86602 9.98144 21.98736 10.10275C22.10861 10.22419 22.17677 10.38874 22.17677 10.56029L22.17571 10.59082L22.1737 10.62125C21.85181 14.01696 19.23504 16.76074 15.85699 17.35306L16.31107 19.16976C16.33027 19.24666 16.33171 19.32682 16.3153 19.40429C16.29878 19.48176 16.26499 19.55443 16.21622 19.61683C16.16746 19.67923 16.10515 19.72973 16.03402 19.76448C15.96288 19.79923 15.88474 19.81728 15.80554 19.81728L8.27921 19.81728C8.20003 19.81728 8.12188 19.79923 8.05071 19.76448C7.97955 19.72973 7.91723 19.67923 7.8685 19.61683C7.81977 19.55443 7.7859 19.48176 7.76947 19.40429C7.75305 19.32682 7.75449 19.24666 7.7737 19.16976L8.22772 17.35306C4.89166 16.76822 2.29831 14.08474 1.92424 10.74768L1.91171 10.62672C1.90307 10.53629 1.9134 10.44509 1.94207 10.35898C1.97073 10.27286 2.01708 10.19366 2.07813 10.12646C2.13919 10.05928 2.21362 10.0056 2.29664 9.96886C2.37965 9.93212 2.46943 9.91314 2.56021 9.91312L21.52992 9.91312z" + fill="#FDDE80ff"></path> + <path + d="M10.51066 3.65813L13.57402 3.65813C14.05238 3.65813 14.4695 3.9834 14.58538 4.44758L15.95184 9.91314L8.13281 9.91314L9.49929 4.44792C9.55566 4.22235 9.68582 4.02209 9.86909 3.87899C10.05235 3.73588 10.27814 3.65814 10.51066 3.65813z" + fill="#FDDE80ff"></path> + <path + d="M12.04234 15.12614C12.5953 15.12614 13.1257 15.34579 13.5167 15.7368C13.90771 16.1279 14.12746 16.65821 14.12746 17.21126L14.12746 19.81747L9.95722 19.81747L9.95722 17.21126C9.95722 16.65821 10.17686 16.1279 10.56787 15.7368C10.95898 15.34579 11.48928 15.12614 12.04234 15.12614z" + fill="#FB813Aff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/game.svg b/bb-api-collect/assets/zone_v2_icon/game.svg new file mode 100644 index 0000000000..7fe58421ac --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/game.svg @@ -0,0 +1,14 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M5.73713 20.26694L18.61296 20.26694C19.40822 20.26694 20.05296 19.6223 20.05296 18.82694L20.05296 5.83225C20.05296 5.03696 19.40822 4.39225 18.61296 4.39225L5.73712 4.39225C4.94183 4.39225 4.29712 5.03696 4.29712 5.83225L4.29713 18.82694C4.29713 19.6223 4.94184 20.26694 5.73713 20.26694z" + fill="#57D587ff"></path> + <path + d="M7.73276 8.05963C7.60831 8.05963 7.50647 8.16223 7.50647 8.28763L7.50647 10.96666C7.50647 11.09203 7.60831 11.19466 7.73276 11.19466L10.39162 11.19466C10.51603 11.19466 10.61789 11.09203 10.61789 10.96666L10.61789 8.28763C10.61789 8.16223 10.51603 8.05963 10.39162 8.05963L7.73276 8.05963z" + fill="#1F9F81ff"></path> + <path + d="M16.84051 8.28763C16.84051 8.16223 16.73875 8.05963 16.61424 8.05963L13.95542 8.05963C13.83091 8.05963 13.72915 8.16223 13.72915 8.28763L13.72915 10.96666C13.72915 11.09203 13.83091 11.19466 13.95542 11.19466L16.61424 11.19466C16.73875 11.19466 16.84051 11.09203 16.84051 10.96666L16.84051 8.28763z" + fill="#1F9F81ff"></path> + <path + d="M10.84416 11.19456C10.71974 11.19456 10.61789 11.29718 10.61789 11.42256L10.61789 12.70666C10.61789 12.83203 10.51603 12.93466 10.39162 12.93466L9.37919 12.93466C9.25473 12.93466 9.1529 13.03728 9.1529 13.16266L9.1529 14.27395L9.1529 14.72995L9.1529 15.84163L9.1529 16.29763L9.1529 17.40893C9.1529 17.5343 9.25473 17.63693 9.37919 17.63693L10.27843 17.63693C10.40294 17.63693 10.5047 17.5343 10.5047 17.40893L10.5047 16.29763C10.5047 16.17226 10.60656 16.06963 10.73098 16.06963L11.85658 16.06963L12.17338 16.06963L12.49066 16.06963L13.61616 16.06963C13.74058 16.06963 13.84243 16.17226 13.84243 16.29763L13.84243 17.40893C13.84243 17.5343 13.94429 17.63693 14.0687 17.63693L14.96755 17.63693C15.09197 17.63693 15.19382 17.5343 15.19382 17.40893L15.19382 16.29763L15.19382 15.84163L15.19382 14.72995L15.19382 14.27395L15.19382 13.16266C15.19382 13.03728 15.09197 12.93466 14.96755 12.93466L13.95562 12.93466C13.8311 12.93466 13.72934 12.83203 13.72934 12.70666L13.72934 11.42256C13.72934 11.29718 13.62749 11.19456 13.50298 11.19456L10.84416 11.19456z" + fill="#1F9F81ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/gym.svg b/bb-api-collect/assets/zone_v2_icon/gym.svg new file mode 100644 index 0000000000..4b1e3a8dce --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/gym.svg @@ -0,0 +1,17 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M2.00343 12.04454C2.00343 11.51434 2.41329 11.08454 2.91886 11.08454L21.22742 11.08454C21.73296 11.08454 22.14278 11.51434 22.14278 12.04454C22.14278 12.57475 21.73296 13.00454 21.22742 13.00454L2.91886 13.00454C2.41329 13.00454 2.00343 12.57475 2.00343 12.04454z" + fill="#FF8834ff"></path> + <path + d="M18.79498 5.27997L17.35498 5.27997L17.35498 18.72L18.79498 18.72C19.59034 18.72 20.23498 18.07526 20.23498 17.28L20.23498 6.71994C20.23498 5.92466 19.59024 5.27997 18.79498 5.27997z" + fill="#FFD671ff"></path> + <path + d="M8.23125 5.27997L6.79125 5.27997L6.79125 18.72L8.23125 18.72C9.02654 18.72 9.67123 18.07526 9.67123 17.28L9.67123 6.71995C9.67123 5.92467 9.02653 5.27997 8.23125 5.27997z" + fill="#FF8834ff"></path> + <path + d="M15.91498 5.28L17.35498 5.28L17.35498 18.72L15.91498 18.72C15.11971 18.72 14.47498 18.07526 14.47498 17.28L14.47498 6.71983C14.47498 5.92466 15.11981 5.28 15.91498 5.28z" + fill="#FF8834ff"></path> + <path + d="M5.35125 5.27997L6.79125 5.27997L6.79125 18.72L5.35125 18.72C4.55596 18.72 3.91125 18.07526 3.91125 17.28L3.91125 6.71994C3.91125 5.92466 4.55597 5.27997 5.35125 5.27997z" + fill="#FFD671ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/handmake.svg b/bb-api-collect/assets/zone_v2_icon/handmake.svg new file mode 100644 index 0000000000..96f3bcc460 --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/handmake.svg @@ -0,0 +1,23 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M12.62496 14.23738C12.36461 14.6424 11.77267 14.6424 11.51222 14.23757L10.54176 12.72902C10.4015 12.5111 10.4015 12.23146 10.54157 12.01344L16.35754 2.96447C16.50086 2.74146 16.80134 2.67425 16.99843 2.85151C18.05741 3.80375 18.30067 5.40988 17.50579 6.64666L12.62496 14.23738z" + fill="#6D69E4ff"></path> + <path + d="M11.37398 12.43008L12.56045 13.11504L10.65005 16.42397L9.46356 15.73901L11.37398 12.43008z" + fill="#6D69E4ff"></path> + <path + d="M11.49312 14.24842C11.75386 14.64998 12.34176 14.65008 12.60259 14.24861L13.58832 12.73152C13.73069 12.51245 13.73069 12.23011 13.58851 12.01094L7.71324 2.95969C7.56982 2.73875 7.2717 2.67196 7.07455 2.84664C6.00046 3.79827 5.75254 5.40777 6.55671 6.64666L11.49312 14.24842z" + fill="#9796EDff"></path> + <path + d="M11.37398 13.11504L12.56045 12.43008L14.40605 15.62678L13.21958 16.31174L11.37398 13.11504z" + fill="#9796EDff"></path> + <path + d="M6.8168 18.86678C5.84817 18.24422 5.56763 16.95437 6.1902 15.98573C6.81276 15.01709 8.10268 14.73648 9.07131 15.35914C10.03997 15.9817 10.32048 17.27155 9.69792 18.24019C9.07535 19.20883 7.78543 19.48934 6.8168 18.86678zM5.96217 20.19648C4.25917 19.10189 3.76595 16.83408 4.86051 15.13104C5.95507 13.4281 8.22294 12.93485 9.92592 14.02944C11.62896 15.12394 12.12221 17.39184 11.02762 19.09478C9.93302 20.79782 7.66517 21.29107 5.96217 20.19648z" + fill="#FDDE80ff"></path> + <path + d="M15.05808 18.86678C14.08944 18.24422 13.80893 16.95437 14.43149 15.98573C15.05405 15.01709 16.3439 14.73648 17.31254 15.35914C18.28118 15.9817 18.56179 17.27155 17.93914 18.24019C17.31658 19.20883 16.02672 19.48934 15.05808 18.86678zM14.20349 20.19648C12.50045 19.10189 12.0072 16.83408 13.10179 15.13104C14.19638 13.4281 16.46419 12.93485 18.16723 14.02944C19.87018 15.12394 20.36342 17.39184 19.26883 19.09478C18.17434 20.79782 15.90643 21.29107 14.20349 20.19648z" + fill="#FDDE80ff"></path> + <path + d="M13.07414 12.32688C13.07414 12.87965 12.62602 13.32778 12.07325 13.32778C11.52048 13.32778 11.07235 12.87965 11.07235 12.32688C11.07235 11.77411 11.52048 11.32598 12.07325 11.32598C12.62602 11.32598 13.07414 11.77411 13.07414 12.32688z" + fill="#FDDE80ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/health.svg b/bb-api-collect/assets/zone_v2_icon/health.svg new file mode 100644 index 0000000000..ee172e4e03 --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/health.svg @@ -0,0 +1,11 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M3.67336 7.39739C3.67336 6.59091 3.67336 6.18766 3.83031 5.87964C3.96837 5.60868 4.18866 5.38838 4.45961 5.25033C4.76765 5.09338 5.17089 5.09338 5.97736 5.09338L18.14179 5.09338C18.94829 5.09338 19.35149 5.09338 19.65955 5.25033C19.93046 5.38838 20.15078 5.60868 20.28883 5.87964C20.44579 6.18766 20.44579 6.5909 20.44579 7.39738L20.44579 16.60262C20.44579 17.40912 20.44579 17.81232 20.28883 18.12038C20.15078 18.3913 19.93046 18.61162 19.65955 18.74966C19.35149 18.90662 18.94829 18.90662 18.14179 18.90662L5.97735 18.90662C5.17089 18.90662 4.76765 18.90662 4.45961 18.74966C4.18866 18.61162 3.96837 18.3913 3.83031 18.12038C3.67336 17.81232 3.67336 17.40912 3.67336 16.60262L3.67336 7.39739z" + fill="#FF5C7Aff"></path> + <path + d="M3.09983 7.20505L3.09983 7.20505C3.09983 6.57943 3.09983 6.26662 3.19538 6.01756C3.34163 5.63638 3.64284 5.33518 4.02401 5.18893C4.27307 5.09338 4.58588 5.09338 5.2115 5.09338L5.2115 5.09338L18.93494 5.09338L18.93494 5.09338C19.56058 5.09338 19.87344 5.09338 20.12246 5.18893C20.50368 5.33518 20.80483 5.63637 20.95114 6.01757C21.04666 6.26662 21.04666 6.57944 21.04666 7.20505L21.04666 7.20505C21.04666 7.41359 21.04666 7.51786 21.01478 7.60088C20.96602 7.72794 20.8656 7.82834 20.73859 7.87709C20.65555 7.90894 20.5513 7.90894 20.34278 7.90894L3.80372 7.90894C3.59518 7.90894 3.49091 7.90894 3.40789 7.87709C3.28083 7.82834 3.18043 7.72794 3.13167 7.60088C3.09983 7.51786 3.09983 7.41359 3.09983 7.20505z" + fill="#FFCFE6ff"></path> + <path + d="M13.20672 11.86099L13.20672 9.88544C13.20672 9.62034 12.99187 9.40544 12.72672 9.40544L11.39251 9.40544C11.12736 9.40544 10.91251 9.62034 10.91251 9.88544L10.91251 11.86099L8.93696 11.86099C8.67185 11.86099 8.45696 12.07584 8.45696 12.34099L8.45696 13.6752C8.45696 13.94035 8.67185 14.1552 8.93696 14.1552L10.91251 14.1552L10.91251 16.13078C10.91251 16.39584 11.12736 16.61078 11.39251 16.61078L12.72672 16.61078C12.99187 16.61078 13.20672 16.39584 13.20672 16.13078L13.20672 14.1552L15.1823 14.1552C15.44736 14.1552 15.6623 13.94035 15.6623 13.6752L15.6623 12.34099C15.6623 12.07584 15.44736 11.86099 15.1823 11.86099L13.20672 11.86099z" + fill="#FFCFE6ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/home.svg b/bb-api-collect/assets/zone_v2_icon/home.svg new file mode 100644 index 0000000000..066b5dd2e7 --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/home.svg @@ -0,0 +1,26 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M5.59324 5.04454C5.59324 4.24928 6.2378 3.60457 7.03307 3.60457C7.06633 3.60457 7.09987 3.60457 7.13368 3.60457L14.02454 3.60457C14.05824 3.60457 14.09174 3.60457 14.12486 3.60457C14.92022 3.60456 15.56496 4.24931 15.56496 5.04468L15.56496 20.40461L7.13367 20.40461C6.28292 20.40461 5.59324 19.79482 5.59324 19.04246L5.59324 5.04454z" + fill="#FF8834ff"></path> + <path + d="M9.42703 11.3329C9.42703 11.06784 9.64195 10.8529 9.90701 10.8529L11.2512 10.8529C11.51626 10.8529 11.7312 11.06784 11.7312 11.3329L11.7312 12.67699C11.7312 12.94214 11.51626 13.15699 11.2512 13.15699L9.90701 13.15699C9.64195 13.15699 9.42703 12.94214 9.42703 12.67699L9.42703 11.3329z" + fill="#FFD671ff"></path> + <path + d="M9.42703 7.04062C9.42703 6.77553 9.64195 6.56062 9.90701 6.56062L11.2512 6.56062C11.51626 6.56062 11.7312 6.77553 11.7312 7.04062L11.7312 8.38475C11.7312 8.64985 11.51626 8.86475 11.2512 8.86475L9.90701 8.86475C9.64195 8.86475 9.42703 8.64985 9.42703 8.38475L9.42703 7.04062z" + fill="#FFD671ff"></path> + <path + d="M9.42703 15.62506C9.42703 15.36 9.64195 15.14506 9.90701 15.14506L11.2512 15.14506C11.51626 15.14506 11.7312 15.36 11.7312 15.62506L11.7312 16.96915C11.7312 17.2343 11.51626 17.44915 11.2512 17.44915L9.90701 17.44915C9.64195 17.44915 9.42703 17.2343 9.42703 16.96915L9.42703 15.62506z" + fill="#FFD671ff"></path> + <path + d="M15.56496 8.80705L19.03325 8.80705C19.82851 8.80705 20.47325 9.45176 20.47325 10.24704L20.47325 10.24704L20.47325 18.96461C20.47325 19.75987 19.82851 20.40461 19.03325 20.40461L15.56496 20.40461L15.56496 8.80705z" + fill="#FFD671ff"></path> + <path + d="M17.15616 11.3327C17.15616 11.06755 17.37101 10.8527 17.63616 10.8527L18.40205 10.8527C18.6672 10.8527 18.88205 11.06755 18.88205 11.3327L18.88205 12.6768C18.88205 12.94186 18.6672 13.1568 18.40205 13.1568L17.63616 13.1568C17.37101 13.1568 17.15616 12.94186 17.15616 12.6768L17.15616 11.3327z" + fill="#FF8834ff"></path> + <path + d="M17.15616 15.62486C17.15616 15.35971 17.37101 15.14486 17.63616 15.14486L18.40205 15.14477C18.6672 15.14477 18.88205 15.35971 18.88205 15.62477L18.88205 16.96896C18.88205 17.23402 18.6672 17.44896 18.40205 17.44896L17.63616 17.44896C17.37101 17.44896 17.15616 17.23402 17.15616 16.96896L17.15616 15.62486z" + fill="#FF8834ff"></path> + <path + d="M4.46813 19.8047C4.46813 19.2745 4.89793 18.8447 5.42813 18.8447L20.63626 18.8447C21.16646 18.8447 21.59626 19.2745 21.59626 19.8047C21.59626 20.33491 21.16646 20.7647 20.63626 20.7647L5.42813 20.7647C4.89793 20.7647 4.46813 20.33491 4.46813 19.8047z" + fill="#FF8834ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/information.svg b/bb-api-collect/assets/zone_v2_icon/information.svg new file mode 100644 index 0000000000..68a2917ed6 --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/information.svg @@ -0,0 +1,20 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M20.7696 9.43989C20.7696 8.64461 20.12486 7.99991 19.3296 7.99988C16.87613 7.9998 14.42275 7.99956 11.96928 7.99979C11.17411 7.99986 10.52957 8.64452 10.52957 9.4397L10.52957 18.96499C10.52957 19.76026 11.17421 20.40499 11.96957 20.40499C14.42285 20.40499 16.87622 20.40499 19.3296 20.40499C20.12486 20.40499 20.7696 19.76026 20.7696 18.96499C20.7696 15.78998 20.7696 12.61498 20.7696 9.43989z" + fill="#00B9E7ff"></path> + <path + d="M17.56512 4.12356L5.86988 4.12356C5.16028 4.12356 4.58508 4.65644 4.58508 5.3136L4.58508 19.21469C4.58508 19.8719 5.16028 20.4047 5.86988 20.4047L17.56512 20.4047C18.27427 20.4047 18.8495 19.8719 18.8495 19.21469L18.8495 5.3136C18.8495 4.65644 18.27427 4.12356 17.56512 4.12356z" + fill="#59E1F9ff"></path> + <path + d="M6.55239 15.36586C6.55239 14.96861 6.87441 14.64662 7.27164 14.64662L16.14778 14.64662C16.54493 14.64662 16.86701 14.96861 16.86701 15.36586C16.86701 15.7631 16.54493 16.08509 16.14778 16.08509L7.27164 16.08509C6.87441 16.08509 6.55239 15.7631 6.55239 15.36586z" + fill="#00B9E7ff"></path> + <path + d="M6.55239 17.90045C6.55239 17.5032 6.87441 17.18122 7.27164 17.18122L16.14778 17.18122C16.54493 17.18122 16.86701 17.5032 16.86701 17.90045C16.86701 18.2977 16.54493 18.61968 16.14778 18.61968L7.27164 18.61968C6.87441 18.61968 6.55239 18.2977 6.55239 17.90045z" + fill="#00B9E7ff"></path> + <path + d="M15.61574 13.17888L7.81898 13.17888C7.13058 13.17888 6.56738 12.61891 6.56738 11.93443L6.56738 7.62798C6.56738 6.94351 7.13058 6.38353 7.81898 6.38353L15.61574 6.38353C16.30416 6.38353 16.86701 6.94351 16.86701 7.62798L16.86701 11.93443C16.86701 12.61891 16.30416 13.17888 15.61574 13.17888z" + fill="#00B9E7ff"></path> + <path + d="M10.3943 8.60394C10.3943 8.06573 10.77312 7.84541 11.23603 8.11452L13.40477 9.37584C13.86768 9.64495 13.86768 10.08557 13.40477 10.35466L11.23603 11.616C10.77312 11.88566 10.3943 11.66534 10.3943 11.12659L10.3943 8.60394z" + fill="#FDDE80ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/kichiku.svg b/bb-api-collect/assets/zone_v2_icon/kichiku.svg new file mode 100644 index 0000000000..a02252b795 --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/kichiku.svg @@ -0,0 +1,20 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M21.44573 11.95363C21.44573 9.55713 19.50038 7.61437 17.10058 7.61437C15.08016 7.61437 13.38701 8.99326 12.90048 10.85837C12.61642 10.97539 12.34656 11.1191 12.09197 11.28422C11.8248 11.11114 11.54035 10.9632 11.24141 10.8431C10.7495 8.98562 9.05986 7.61437 7.04517 7.61437C4.64539 7.61437 2.7 9.55713 2.7 11.95363C2.7 13.36733 3.37985 14.61888 4.42758 15.41136C4.42758 15.4225 4.42605 15.43315 4.42605 15.4439C4.42605 18.18326 6.64974 20.40394 9.39251 20.40394C10.38893 20.40394 11.31456 20.10806 12.09197 19.60387C12.86947 20.10806 13.7951 20.40394 14.7911 20.40394C17.5343 20.40394 19.75795 18.18326 19.75795 15.4439C19.75795 15.42365 19.75488 15.40406 19.75488 15.38381C20.78198 14.59027 21.44573 13.35091 21.44573 11.95363z" + fill="#FF5C7Aff"></path> + <path + d="M12.58224 5.53555L11.71478 5.53555C9.34452 5.53555 7.40521 7.47222 7.40521 9.83926L7.40521 15.31181C7.40521 17.67888 9.34452 19.61558 11.71478 19.61558L12.58224 19.61558C14.95258 19.61558 16.89187 17.67888 16.89187 15.31181L16.89187 9.83926C16.89187 7.47222 14.95258 5.53555 12.58224 5.53555z" + fill="#ffffffff"></path> + <path + d="M9.46395 12.41309C9.51499 12.25402 9.73997 12.25402 9.79104 12.41309L9.80074 12.44323C9.99446 13.04669 10.41043 13.55386 10.96445 13.86182C11.0785 13.92528 11.0785 14.08934 10.96445 14.1527C10.41043 14.46067 9.99446 14.96784 9.80074 15.5713L9.79104 15.60154C9.73997 15.76051 9.51499 15.76051 9.46395 15.60154L9.45425 15.5713C9.26053 14.96784 8.84449 14.46067 8.29054 14.1527C8.17648 14.08934 8.17648 13.92528 8.29054 13.86182C8.84449 13.55386 9.26053 13.04669 9.45425 12.44323L9.46395 12.41309z" + fill="#FF5C7Aff"></path> + <path + d="M14.28221 12.41309C14.33328 12.25402 14.55821 12.25402 14.60928 12.41309L14.61898 12.44323C14.8127 13.04669 15.22877 13.55386 15.78269 13.86182C15.89674 13.92528 15.89674 14.08934 15.78269 14.1527C15.22877 14.46067 14.8127 14.96784 14.61898 15.5713L14.60928 15.60154C14.55821 15.76051 14.33328 15.76051 14.28221 15.60154L14.27251 15.5713C14.07878 14.96784 13.66282 14.46067 13.1088 14.1527C12.99475 14.08934 12.99475 13.92528 13.1088 13.86182C13.66282 13.55386 14.07878 13.04669 14.27251 12.44323L14.28221 12.41309z" + fill="#FF5C7Aff"></path> + <path + d="M15.88627 4.34697C15.40176 4.34697 14.94173 4.44877 14.52384 4.62983C13.90205 3.99273 13.03459 3.59566 12.07315 3.59566C11.11171 3.59566 10.24426 3.99273 9.62208 4.62983C9.20452 4.44877 8.74409 4.34697 8.25997 4.34697C6.36862 4.34697 4.83576 5.87813 4.83576 7.76653C4.83576 9.65493 6.36862 11.18611 8.25997 11.18611C9.22144 11.18611 10.08883 10.78906 10.71072 10.1519C11.12861 10.33296 11.58864 10.43482 12.07315 10.43482C12.55766 10.43482 13.0177 10.33296 13.4352 10.1519C14.05738 10.78906 14.92483 11.18611 15.88627 11.18611C17.77728 11.18611 19.3105 9.65493 19.3105 7.76653C19.3105 5.87813 17.77728 4.34697 15.88627 4.34697z" + fill="#FF5C7Aff"></path> + <path + d="M13.46515 16.05629C13.46515 16.85155 12.81917 17.49658 12.02285 17.49658C11.22586 17.49658 10.58064 16.85155 10.58064 16.05629C10.58064 15.26102 11.22586 14.616 12.02285 14.616C12.81917 14.616 13.46515 15.26102 13.46515 16.05629z" + fill="#FF5C7Aff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/knowledge.svg b/bb-api-collect/assets/zone_v2_icon/knowledge.svg new file mode 100644 index 0000000000..154fe65eae --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/knowledge.svg @@ -0,0 +1,17 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M11.314 2.23489C12.9446 2.23067 14.532 2.75886 15.8349 3.73921C17.1379 4.71955 18.0852 6.09845 18.5329 7.66636C18.9806 9.23427 18.9042 10.9055 18.3154 12.426C17.8016 13.7526 16.9223 14.9013 15.7852 15.7421C15.4744 15.972 15.2705 16.326 15.2705 16.7125L15.2705 17.592C15.2617 17.8153 15.2705 18.4288 15.2705 18.4288C15.2705 18.4288 14.2951 18.5929 13.8545 18.5929C13.4139 18.5929 8.6663 18.5929 8.6663 18.5929C8.23657 18.5929 7.26348 18.3716 7.26348 18.3716C7.26348 18.3716 7.26348 17.3741 7.26348 16.9398L7.26348 16.6997C7.26348 16.3201 7.06671 15.9714 6.76507 15.741C5.64258 14.8837 4.78051 13.7248 4.28335 12.394C3.71494 10.8724 3.65406 9.20783 4.10982 7.64882C4.56557 6.08982 5.51348 4.7201 6.81195 3.7443C8.11043 2.7685 9.68976 2.239 11.314 2.23489z" + fill="#FF8834ff"></path> + <path + d="M12.1195 12.5257C12.3663 12.5257 12.5664 12.3256 12.5664 12.0788L12.5664 11.3639C12.5664 11.1171 12.7665 10.917 13.0133 10.917L13.6389 10.917C14.6152 10.917 14.7114 10.3559 14.7114 10.0232L14.7114 6.7135C14.7114 6.22927 14.351 5.81976 13.6389 5.81976L9.17018 5.81976C8.28824 5.81976 7.91895 6.26199 7.91895 6.7135L7.91895 8.50456C7.91895 8.75099 8.11871 8.95076 8.36514 8.95076L9.61773 8.95076C9.86415 8.95076 10.0639 8.75099 10.0639 8.50456L10.0639 7.96765C10.0639 7.72085 10.264 7.52078 10.5108 7.52078L12.1195 7.52078C12.3663 7.52078 12.5664 7.72085 12.5664 7.96765L12.5664 9.57638C12.5664 9.82318 12.3663 10.0232 12.1195 10.0232L11.4939 10.0232C10.2266 10.0114 9.88517 10.5345 9.88517 10.917L9.88517 12.0788C9.88517 12.3256 10.0852 12.5257 10.332 12.5257L12.1195 12.5257zM11.2537 13.0396C11.5011 13.0396 11.7431 13.113 11.9488 13.2505C12.1546 13.388 12.315 13.5834 12.4097 13.812C12.5044 14.0407 12.5291 14.2922 12.4809 14.535C12.4326 14.7777 12.3134 15.0006 12.1384 15.1756C11.9634 15.3506 11.7405 15.4698 11.4978 15.518C11.2551 15.5663 11.0035 15.5415 10.7748 15.4468C10.5462 15.3521 10.3508 15.1918 10.2133 14.986C10.0758 14.7802 10.0024 14.5383 10.0024 14.2909C10.0024 13.959 10.1343 13.6407 10.3689 13.4061C10.6036 13.1714 10.9218 13.0396 11.2537 13.0396z" + fill="#FFE8AFff"></path> + <path + d="M7.61193 19.1082C7.56041 18.8267 7.79538 18.593 8.0816 18.593L14.5507 18.593C14.8369 18.593 15.0719 18.8267 15.0204 19.1082C14.9 19.7663 14.5593 20.4539 14.0385 20.8941C13.3787 21.4518 12.4838 21.7652 11.5507 21.7652L11.0816 21.7652C10.1485 21.7652 9.25362 21.4518 8.59382 20.8941C8.073 20.4539 7.73233 19.7663 7.61193 19.1082z" + fill="#00B9E7ff"></path> + <path + d="M6.53796 17.9091C6.53796 17.4028 6.94835 16.9924 7.45459 16.9924L14.9778 16.9924C15.484 16.9924 15.8944 17.4028 15.8944 17.9091L15.8944 18.0758C15.8944 18.582 15.484 18.9924 14.9778 18.9924L7.45459 18.9924C6.94835 18.9924 6.53796 18.582 6.53796 18.0758L6.53796 17.9091z" + fill="#FFD671ff"></path> + <path + d="M20.289 3.28204C20.345 3.15749 20.5218 3.15749 20.5779 3.28204L20.8592 3.90715C21.1186 4.4836 21.5405 4.97188 22.0732 5.31218L22.267 5.43598C22.3971 5.51903 22.3971 5.70894 22.267 5.79199L22.0821 5.91013C21.5438 6.25396 21.1188 6.74879 20.8602 7.33278L20.5783 7.96932C20.5226 8.09501 20.3442 8.09501 20.2886 7.96932L20.0206 7.36425C19.7533 6.76065 19.3084 6.25278 18.7453 5.90825L18.5589 5.79416C18.4242 5.71178 18.4242 5.51619 18.5589 5.43381L18.7543 5.3142C19.3118 4.9731 19.7535 4.47182 20.0217 3.87581L20.289 3.28204z" + fill="#FFD671ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/life_experience.svg b/bb-api-collect/assets/zone_v2_icon/life_experience.svg new file mode 100644 index 0000000000..2ef38e213a --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/life_experience.svg @@ -0,0 +1,8 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M10.61434 6.33318C10.44384 7.21354 10.50317 8.08513 10.75046 8.88596L5.69662 13.35926L5.69921 13.36157C5.57936 13.47024 5.465 13.58765 5.35702 13.7137C3.97257 15.33053 4.16094 17.76355 5.77777 19.14806C7.39459 20.53248 9.82762 20.34413 11.21203 18.7273C11.30314 18.62093 11.38742 18.51101 11.46499 18.39811L15.31018 12.58262C17.97302 12.82781 20.43984 11.0184 20.9593 8.33736C21.17885 7.20411 21.01738 6.0853 20.56435 5.11334C20.37149 4.69955 19.82563 4.66821 19.52582 5.01252L17.27568 7.59697C17.10634 7.79142 16.81142 7.81181 16.61702 7.6425L15.29088 6.48796C15.09648 6.31865 15.07603 6.02376 15.24538 5.82931L17.46605 3.27885C17.7697 2.93007 17.65584 2.38682 17.2104 2.26236C17.07254 2.22383 16.9319 2.19058 16.78886 2.16287C13.93229 1.60943 11.16778 3.47652 10.61434 6.33318z" + fill="#FDDE80ff"></path> + <path + d="M7.35426 17.3065C6.75449 16.79299 6.68461 15.8904 7.19819 15.29059C7.71177 14.69088 8.61432 14.62099 9.21409 15.1345C9.81389 15.6481 9.88378 16.55069 9.37018 17.1504C8.8566 17.75021 7.95404 17.8201 7.35426 17.3065z" + fill="#FB813Aff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/life_joy.svg b/bb-api-collect/assets/zone_v2_icon/life_joy.svg new file mode 100644 index 0000000000..1b31b6065e --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/life_joy.svg @@ -0,0 +1,14 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M4.07763 7.63768C4.05931 6.56311 5.5539 6.83651 6.30349 7.10752C7.97693 7.98802 10.8193 9.80818 8.8013 10.0448C6.27878 10.3405 4.10053 8.98089 4.07763 7.63768z" + fill="#FB813Aff"></path> + <path + d="M4.55611 14.4882C4.84141 11.4532 7.31628 10.1389 8.31998 9.82821C8.48729 9.82821 9.61772 10.5076 13.464 11.2928C16.0255 11.8156 17.6628 11.0097 18.4364 9.93394C18.805 9.42136 19.3229 9.07939 19.7434 9.55032C20.3467 10.226 21.0067 11.5269 21.0067 13.5405C21.0067 17.3561 18.0324 20.9886 12.5657 20.9886C7.48437 20.9886 4.24105 17.8397 4.55611 14.4882z" + fill="#FDDE80ff"></path> + <path + d="M14.8068 7.41519C14.8068 9.84733 12.8352 11.819 10.4031 11.819C7.97092 11.819 5.99929 9.84733 5.99929 7.41519C5.99929 4.98305 7.97092 3.01141 10.4031 3.01141C12.8352 3.01141 14.8068 4.98305 14.8068 7.41519z" + fill="#FDDE80ff"></path> + <path + d="M10.0014 7.74284C10.0014 8.297 9.5522 8.74623 8.99804 8.74623C8.44388 8.74623 7.99465 8.297 7.99465 7.74284C7.99465 7.18868 8.44388 6.73944 8.99804 6.73944C9.5522 6.73944 10.0014 7.18868 10.0014 7.74284z" + fill="#FB813Aff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/music.svg b/bb-api-collect/assets/zone_v2_icon/music.svg new file mode 100644 index 0000000000..10c5f58c91 --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/music.svg @@ -0,0 +1,17 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M20.36371 11.11344C20.36371 7.03327 17.00093 3.69495 12.89088 3.69495L11.25552 3.69495C7.1455 3.69495 3.78273 7.03327 3.78273 11.11344L3.78273 17.13898C3.78273 17.88566 4.38811 18.49114 5.1349 18.49114C5.43671 19.51978 5.98057 20.27731 7.11021 20.27731L8.35096 20.27731C8.80764 20.27731 9.17878 19.91088 9.18128 19.45718L9.21324 13.14941C9.21532 12.69274 8.84292 12.32102 8.38293 12.32102L7.11021 12.32102C6.69256 12.32102 6.29858 12.42566 5.95151 12.60826L5.95151 10.98528C5.95151 8.03846 8.38018 5.62746 11.34854 5.62746L12.85142 5.62746C15.81984 5.62746 18.24845 8.03846 18.24845 10.98528L18.24845 12.63706C17.88893 12.4368 17.47546 12.32102 17.03616 12.32102L15.76349 12.32102C15.30346 12.32102 14.93107 12.69274 14.93318 13.14941L14.96515 19.45718C14.96765 19.91088 15.33878 20.27731 15.79546 20.27731L17.03616 20.27731C18.16589 20.27731 18.70973 19.51978 19.01155 18.49114C19.75834 18.49114 20.36371 17.88566 20.36371 17.13898L20.36371 11.11344z" + fill="#59E0F9ff"></path> + <path + d="M5.11552 15.22608C5.11552 14.15078 5.11552 13.61309 5.32479 13.2024C5.50887 12.84115 5.8026 12.54739 6.16386 12.36336C6.57458 12.15408 7.11223 12.15408 8.18752 12.15408L8.61742 12.15408C9.15507 12.15408 9.4239 12.15408 9.62928 12.25872C9.80986 12.35078 9.95674 12.49757 10.0488 12.67824C10.15344 12.88358 10.15344 13.15238 10.15344 13.69008L10.15344 18.74131C10.15344 19.27891 10.15344 19.54781 10.0488 19.75315C9.95674 19.93373 9.80986 20.08061 9.62928 20.17267C9.4239 20.27731 9.15507 20.27731 8.61742 20.27731L8.18752 20.27731C7.11223 20.27731 6.57458 20.27731 6.16386 20.06803C5.8026 19.884 5.50887 19.59024 5.32479 19.22899C5.11552 18.81821 5.11552 18.28061 5.11552 17.20531L5.11552 15.22608z" + fill="#00B9E7ff"></path> + <path + d="M19.03075 15.22608C19.03075 14.15078 19.03075 13.61309 18.82147 13.2024C18.63734 12.84115 18.34368 12.54739 17.98243 12.36336C17.57165 12.15408 17.03405 12.15408 15.95875 12.15408L15.52675 12.15408C14.98906 12.15408 14.72026 12.15408 14.51491 12.25872C14.33424 12.35078 14.18736 12.49757 14.09539 12.67824C13.99075 12.88358 13.99075 13.15238 13.99075 13.69008L13.99075 18.74131C13.99075 19.27891 13.99075 19.54781 14.09539 19.75315C14.18736 19.93373 14.33424 20.08061 14.51491 20.17267C14.72026 20.27731 14.98906 20.27731 15.52675 20.27731L15.95875 20.27731C17.03405 20.27731 17.57165 20.27731 17.98243 20.06803C18.34368 19.884 18.63734 19.59024 18.82147 19.22899C19.03075 18.81821 19.03075 18.28061 19.03075 17.20531L19.03075 15.22608z" + fill="#00B9E7ff"></path> + <path + d="M13.9992 12.87389C13.9992 12.34349 14.42928 11.91341 14.95968 11.91341L14.95968 11.91341C15.49018 11.91341 15.92026 12.34349 15.92026 12.87389L15.92026 19.55741C15.92026 20.0879 15.49018 20.51798 14.95968 20.51798L14.95968 20.51798C14.42928 20.51798 13.9992 20.0879 13.9992 19.55741L13.9992 12.87389z" + fill="#FDDE80ff"></path> + <path + d="M8.24077 12.87389C8.24077 12.34349 8.67081 11.91341 9.20127 11.91341L9.20127 11.91341C9.73171 11.91341 10.16179 12.34349 10.16179 12.87389L10.16179 19.55741C10.16179 20.0879 9.73171 20.51798 9.20127 20.51798L9.20127 20.51798C8.67081 20.51798 8.24077 20.0879 8.24077 19.55741L8.24077 12.87389z" + fill="#FDDE80ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/outdoors.svg b/bb-api-collect/assets/zone_v2_icon/outdoors.svg new file mode 100644 index 0000000000..0af234df5b --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/outdoors.svg @@ -0,0 +1,14 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M9.29448 4.11732C9.64829 3.40975 10.65802 3.40975 11.01178 4.11732L18.0985 18.29069C18.4176 18.92899 17.95344 19.68 17.23978 19.68L3.06644 19.68C2.3528 19.68 1.88864 18.92899 2.20779 18.29069L9.29448 4.11732z" + fill="#1F9F81ff"></path> + <path + d="M3.05915 19.68019C2.34988 19.67482 1.89021 18.92698 2.20821 18.29098L5.83356 11.04019L6.34665 12.06643C6.62966 12.63245 7.43746 12.63245 7.72048 12.06643L8.3349 10.83754C8.68868 10.13002 9.6984 10.13002 10.05216 10.83754L12.10666 14.94643C12.38966 15.51245 13.19741 15.51245 13.48051 14.94643L14.95354 12.00029L18.09888 18.29098C18.41808 18.92928 17.95392 19.68029 17.24026 19.68029L3.26428 19.68029C3.26216 19.68019 3.26004 19.68019 3.25792 19.68019L3.05915 19.68019z" + fill="#57D587ff"></path> + <path + d="M16.01443 9.87732C16.36829 9.16975 17.37802 9.16975 17.73178 9.87732L21.9385 18.29069C22.2576 18.92899 21.79344 19.68 21.07978 19.68L12.66643 19.68C11.95277 19.68 11.48861 18.92899 11.80781 18.29069L16.01443 9.87732z" + fill="#1F9F81ff"></path> + <path + d="M19.51354 13.44L21.93888 18.29069C22.25808 18.92899 21.79392 19.68 21.08026 19.68L12.66682 19.68C11.95325 19.68 11.48909 18.92899 11.80819 18.29069L14.95354 12L17.16422 16.42138C17.34115 16.77514 17.84602 16.77514 18.02285 16.42138L19.51354 13.44z" + fill="#57D587ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/painting.svg b/bb-api-collect/assets/zone_v2_icon/painting.svg new file mode 100644 index 0000000000..2e0cd81c60 --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/painting.svg @@ -0,0 +1,23 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M12.3744 18.84662C12.69341 20.00419 13.71994 21.08438 14.85139 20.68234C18.26458 19.46938 20.71642 16.13021 20.71642 12.20093C20.71642 7.24727 16.81949 3.23156 12.01248 3.23156C7.20531 3.23156 3.30844 7.24727 3.30844 12.20093C3.33446 12.77126 3.45612 13.28774 3.61254 13.63834C4.17721 14.90381 5.61394 15.15859 6.73392 15.12922C8.03405 15.09514 9.63226 15.24019 10.56096 16.00886C11.59786 16.8671 12.11866 17.91859 12.3744 18.84662z" + fill="#FDDE80ff"></path> + <path + d="M8.78526 10.49779C8.78526 11.44157 8.02013 12.20669 7.07629 12.20669C6.13247 12.20669 5.36734 11.44157 5.36734 10.49779C5.36734 9.55393 6.13247 8.78881 7.07629 8.78881C8.02013 8.78881 8.78526 9.55393 8.78526 10.49779z" + fill="#FB813Aff"></path> + <path + d="M12.408 7.48322C12.408 8.20428 11.82355 8.78881 11.1025 8.78881C10.38144 8.78881 9.7969 8.20428 9.7969 7.48322C9.7969 6.76216 10.38144 6.17764 11.1025 6.17764C11.82355 6.17764 12.408 6.76216 12.408 7.48322z" + fill="#FB813Aff"></path> + <path + d="M16.3633 7.48323C16.3633 8.02254 15.92611 8.45974 15.38678 8.45974C14.84755 8.45974 14.41027 8.02254 14.41027 7.48323C14.41027 6.94392 14.84755 6.50672 15.38678 6.50672C15.92611 6.50672 16.3633 6.94392 16.3633 7.48323z" + fill="#FB813Aff"></path> + <path + d="M14.71584 14.62147C14.41421 14.09914 14.58682 13.43146 15.10368 13.1207L21.1801 9.46733C21.82541 9.07934 22.66397 9.30876 23.02195 9.97121C23.37216 10.61933 23.12429 11.4287 22.4711 11.76941L16.18522 15.04906C15.6599 15.32304 15.012 15.1345 14.71584 14.62147z" + fill="#FB813Aff"></path> + <path + d="M11.78429 14.75242C12.32054 14.68214 12.92227 13.98 13.23936 13.54013L15.35971 16.06061C13.86586 16.96474 11.96122 16.30694 11.5559 15.00941C11.51616 14.88211 11.65219 14.76979 11.78429 14.75242z" + fill="#FB813Aff"></path> + <path + d="M16.15882 14.96486C15.96509 15.86717 15.07661 16.44154 14.1743 16.24781C13.272 16.05408 12.69763 15.1655 12.89136 14.2633C13.08509 13.36099 13.97366 12.78662 14.87587 12.98035C15.77818 13.17408 16.35254 14.06256 16.15882 14.96486z" + fill="#FB813Aff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/parenting.svg b/bb-api-collect/assets/zone_v2_icon/parenting.svg new file mode 100644 index 0000000000..719ea97a18 --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/parenting.svg @@ -0,0 +1,26 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M5.96079 9.69571C5.59021 9.81677 5.26667 9.8328 4.86949 9.85738L9.89213 5.07405L10.87805 9.6721L15.83242 9.6721C17.87904 9.6721 19.53811 11.33117 19.53811 13.37779C19.53811 15.42432 17.87904 17.08339 15.83242 17.08339L10.16016 17.08339C7.92572 17.08339 6.09908 15.30134 6.04398 13.06752L5.96079 9.69571z" + fill="#FDDE80ff"></path> + <path + d="M9.6025 4.46082C10.41341 5.55808 9.75648 7.49415 8.20206 8.64297C6.64761 9.79181 3.96818 10.40179 3.055 9.26052C1.96426 7.89731 3.63332 5.60959 5.18777 4.46077C6.74222 3.31196 8.79157 3.36356 9.6025 4.46082z" + fill="#FDDE80ff"></path> + <path + d="M6.87196 6.71961C6.87196 7.12133 6.5463 7.447 6.14457 7.447C5.74284 7.447 5.41718 7.12133 5.41718 6.71961C5.41718 6.31788 5.74284 5.99222 6.14457 5.99222C6.5463 5.99222 6.87196 6.31788 6.87196 6.71961z" + fill="#FB813Aff"></path> + <path + d="M6.14543 12.70627L10.23763 14.1047L8.64211 18.77357L4.54988 17.37514L6.14543 12.70627z" + fill="#FDDE80ff"></path> + <path + d="M14.78726 14.63981L18.7393 12.88387L20.74282 17.3928L16.79078 19.14874L14.78726 14.63981z" + fill="#FDDE80ff"></path> + <path + d="M21.96979 15.99082C22.31914 16.3897 22.27901 16.99613 21.88022 17.34547C15.86986 22.61002 7.48995 22.30915 2.4827 17.30218C2.10779 16.9273 2.10778 16.31942 2.48267 15.94454C2.85756 15.56966 3.4654 15.56966 3.84032 15.94454C8.08284 20.18688 15.31133 20.54678 20.61514 15.90125C21.01392 15.5519 21.62045 15.59203 21.96979 15.99082z" + fill="#FB813Aff"></path> + <path + d="M19.39718 14.39482C19.72656 11.1407 18.06538 10.3655 17.14954 9.91958C17.37629 9.69235 18.31123 9.5818 19.1807 9.99101C20.37235 10.55174 21.10224 11.98934 21.42298 12.9239C21.54499 13.27949 21.33542 13.65331 20.98474 13.78877C20.39798 14.01523 19.57814 14.33251 19.39718 14.39482z" + fill="#FB813Aff"></path> + <path + d="M10.83811 9.66922C10.11696 4.5294 7.26305 3.30956 5.97503 3.99554C5.97565 3.79332 5.97577 3.52899 5.97581 3.2852C5.97588 2.91278 6.25105 2.59212 6.62292 2.5719C11.19946 2.32295 12.21792 7.17193 12.41837 9.66922C12.19757 9.69322 11.40576 9.66922 10.83811 9.66922z" + fill="#FB813Aff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/rural.svg b/bb-api-collect/assets/zone_v2_icon/rural.svg new file mode 100644 index 0000000000..86890a67cf --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/rural.svg @@ -0,0 +1,17 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M10.91453 10.73011C7.95237 9.85407 7.59103 5.97928 10.11072 4.12781C13.15738 5.65305 12.98035 8.82602 10.91453 10.73011z" + fill="#57D587ff"></path> + <path + d="M18.67613 9.33284C18.19392 12.384 14.39933 13.24752 12.2351 10.99085C13.34995 7.77122 16.51891 7.53296 18.67613 9.33284z" + fill="#57D587ff"></path> + <path + d="M11.30275 17.05469C7.42624 18.98832 3.35071 15.35866 4.16538 11.05008C8.74932 9.70172 11.6015 13.12618 11.30275 17.05469z" + fill="#57D587ff"></path> + <path + d="M19.80106 14.7049C19.08797 18.83357 13.92499 19.93133 11.03338 16.8288C12.60778 12.48394 16.91021 12.22205 19.80106 14.7049z" + fill="#57D587ff"></path> + <path + d="M16.30752 5.67904C16.56192 6.14421 16.39104 6.72755 15.92592 6.98196C13.72982 8.183 12.6264 10.43021 12.22214 12.83395C11.81539 15.25277 12.15562 17.6279 12.63734 18.80381C12.83827 19.29446 12.60346 19.8551 12.1128 20.05603C11.62224 20.25706 11.0616 20.02224 10.86058 19.53158C10.22304 17.97514 9.87216 15.2304 10.32874 12.51552C10.78781 9.78549 12.10214 6.88484 15.00461 5.29743C15.46973 5.04302 16.05312 5.21388 16.30752 5.67904z" + fill="#1F9F81ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/shortplay.svg b/bb-api-collect/assets/zone_v2_icon/shortplay.svg new file mode 100644 index 0000000000..dae673617d --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/shortplay.svg @@ -0,0 +1,26 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M3.28234 9.44915C3.28234 8.65385 3.92704 8.00915 4.72234 8.00915L18.60384 8.00915C19.3991 8.00915 20.04384 8.65385 20.04384 9.44915L20.04384 18.55642C20.04384 19.35168 19.3991 19.99642 18.60384 19.99642L4.72234 19.99642C3.92704 19.99642 3.28234 19.35168 3.28234 18.55642L3.28234 9.44915z" + fill="#6D69E4ff"></path> + <path + d="M3.30774 6.48804C3.30774 5.77451 3.83026 5.16858 4.53603 5.06368L10.46851 4.18192C11.26406 4.06368 12.07267 4.06356 12.86813 4.18158L18.81648 5.06397C19.52246 5.1687 20.04518 5.77471 20.04518 6.48839L20.04518 8.03538L3.30774 8.03538L3.30774 6.48804z" + fill="#FDDE80ff"></path> + <path + d="M3.2646 18.55642L3.2646 8.01092L10.72051 8.01092C10.72051 10.45459 8.77914 15.92371 4.72764 15.92371C6.42906 15.92371 6.81611 17.75664 6.79081 19.16352C6.78217 19.64362 6.36905 19.99642 5.88889 19.99642L4.7046 19.99642C3.90932 19.99642 3.2646 19.35168 3.2646 18.55642z" + fill="#9796EDff"></path> + <path + d="M20.04586 18.55642L20.04586 8.01094L12.59002 8.01094C12.59002 10.45459 14.53133 15.92371 18.58282 15.92371C16.88141 15.92371 16.49434 17.75664 16.51968 19.16352C16.52832 19.64362 16.94141 19.99642 17.4216 19.99642L18.60586 19.99642C19.40112 19.99642 20.04586 19.35168 20.04586 18.55642z" + fill="#9796EDff"></path> + <path + d="M6.42128 8.02812L3.28242 8.02812L3.28242 16.0439C6.1361 16.0439 6.56402 10.70006 6.42128 8.02812z" + fill="#6D69E4ff"></path> + <path + d="M16.90704 8.02812L20.04586 8.02812L20.04586 16.0439C17.19216 16.0439 16.76429 10.70006 16.90704 8.02812z" + fill="#6D69E4ff"></path> + <path + d="M3.2646 15.24941L5.88621 15.24941C6.4164 15.24941 6.84621 15.6792 6.84621 16.20941L6.84621 16.20941C6.84621 16.73962 6.4164 17.16941 5.88621 17.16941L3.2646 17.16941L3.2646 15.24941z" + fill="#FDDE80ff"></path> + <path + d="M20.04586 15.24941L17.42016 15.24941C16.88995 15.24941 16.46016 15.6792 16.46016 16.20941L16.46016 16.20941C16.46016 16.73962 16.88995 17.16941 17.42016 17.16941L20.04586 17.16941L20.04586 15.24941z" + fill="#FDDE80ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/sports.svg b/bb-api-collect/assets/zone_v2_icon/sports.svg new file mode 100644 index 0000000000..70f6360076 --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/sports.svg @@ -0,0 +1,8 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M11.96112 11.90266L12.51312 12.57888C12.73104 12.84586 12.83904 13.18579 12.81494 13.52957C12.79085 13.87334 12.63658 14.19494 12.38362 14.4289L6.04611 20.28893C5.83904 20.48045 5.56644 20.58538 5.2844 20.58211C5.00236 20.57875 4.7323 20.46749 4.52977 20.27117C4.32434 20.07216 4.20036 19.80374 4.18199 19.51834C4.16362 19.23283 4.25216 18.95078 4.43037 18.7271L6.93946 15.57552L9.85382 11.91571C9.97968 11.7576 10.13942 11.62973 10.32115 11.54141C10.50298 11.45309 10.70227 11.40653 10.90435 11.40528C11.10643 11.40403 11.3063 11.4481 11.48918 11.53411C11.67206 11.62022 11.83334 11.74618 11.96112 11.90266z" + fill="#1F9F81ff"></path> + <path + d="M16.60733 3.48445C17.30227 3.48483 17.97043 3.75239 18.47347 4.23176C18.97651 4.71111 19.27603 5.36557 19.30992 6.05964C19.34381 6.75371 19.10957 7.43424 18.65558 7.96035C18.2017 8.48647 17.56282 8.81788 16.87123 8.88599L18.26746 9.94675C18.36806 10.02369 18.50237 10.0373 18.61651 9.98345L20.31802 9.18298C20.5559 9.07102 20.82662 9.05058 21.07862 9.12555C21.33053 9.20052 21.54614 9.36564 21.6841 9.58942C21.82022 9.81035 21.86755 10.07472 21.81638 10.32912C21.76522 10.58362 21.61939 10.80912 21.40838 10.96022L18.49757 13.0463C18.27658 13.2047 18.01296 13.29283 17.74118 13.29926C17.46931 13.3057 17.20186 13.23014 16.97357 13.0824L15.44717 12.09437L14.42717 13.19837L16.05888 15.12403C16.09757 15.16934 16.13309 15.21725 16.16544 15.26726L16.21037 15.34358C16.38432 15.6576 16.42637 16.02787 16.3273 16.37299C16.22822 16.71802 15.9961 17.00957 15.68208 17.18352L11.24246 19.64112C10.98701 19.78234 10.6872 19.82035 10.40458 19.7473C10.12205 19.67424 9.87821 19.49568 9.72317 19.24829C9.56556 18.99667 9.50644 18.69571 9.55721 18.4031C9.60797 18.11059 9.76512 17.84707 9.9983 17.66333L12.43757 15.74112L9.98122 14.16269L9.9457 14.13898C9.93869 14.13437 9.93178 14.12966 9.92496 14.12486L9.60547 13.95917C9.44086 13.87421 9.29545 13.75632 9.17823 13.6129C9.06103 13.46938 8.9745 13.30339 8.92404 13.12512C8.87357 12.94694 8.86022 12.76022 8.88483 12.57658C8.90943 12.39293 8.97147 12.21638 9.06708 12.0577L10.72368 9.31018L10.01366 8.9907C9.96048 8.96686 9.90202 8.95716 9.84403 8.96255C9.78595 8.96794 9.73027 8.98823 9.68237 9.02147L7.82232 10.30646C7.60337 10.45786 7.338 10.52707 7.07301 10.50182C6.80803 10.47658 6.56048 10.35859 6.37402 10.16861C6.28791 10.08096 6.22047 9.97679 6.17576 9.86235C6.13105 9.74791 6.10999 9.62558 6.11386 9.50278C6.11773 9.37997 6.14645 9.25923 6.19828 9.14782C6.25011 9.03642 6.32398 8.93669 6.41543 8.85463L9.38007 6.1935C9.55734 6.03445 9.77347 5.925 10.00656 5.87618C10.23965 5.82735 10.48147 5.8409 10.70765 5.91543L14.02493 7.00758C13.89667 6.60188 13.86595 6.17168 13.93507 5.75185C14.00419 5.33202 14.17133 4.93441 14.42285 4.59125C14.67437 4.24808 15.00326 3.96903 15.38275 3.77674C15.76234 3.58444 16.18186 3.4843 16.60733 3.48445L16.60733 3.48445z" + fill="#57D587ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/tech.svg b/bb-api-collect/assets/zone_v2_icon/tech.svg new file mode 100644 index 0000000000..9874d4e579 --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/tech.svg @@ -0,0 +1,23 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M12.02688 16.19126L9.47718 16.19126L8.48827 20.24736C8.41458 20.54966 8.64349 20.84102 8.95461 20.84102L12.02688 20.84102L15.09946 20.84102C15.41059 20.84102 15.63955 20.54966 15.56582 20.24736L14.57693 16.19126L12.02688 16.19126z" + fill="#FDDE80ff"></path> + <path + d="M12.0265 5.11161C11.68627 5.11161 11.40749 4.83518 11.40749 4.49694L11.40749 2.92935C11.40749 2.59111 11.68627 2.31468 12.0265 2.31468C12.36662 2.31468 12.6455 2.59111 12.6455 2.92935L12.6455 4.49694C12.6455 4.83518 12.36662 5.11161 12.0265 5.11161z" + fill="#00B9E7ff"></path> + <path + d="M5.44948 12.45869L5.44948 10.1089C5.44948 6.51677 8.40948 3.57738 12.02678 3.57738C15.64464 3.57738 18.60461 6.51677 18.60461 10.1089L18.60461 12.45869C18.60461 12.81619 18.31267 13.10611 17.95267 13.10611L6.1014 13.10611C5.74138 13.10611 5.44948 12.81619 5.44948 12.45869z" + fill="#00B9E7ff"></path> + <path + d="M18.30816 16.26451L5.74677 16.26451C4.34618 16.26451 3.20062 15.15648 3.20062 13.80269C3.20062 12.44851 4.34618 11.34048 5.74677 11.34048L18.30816 11.34048C19.7088 11.34048 20.85427 12.44851 20.85427 13.80269C20.85427 15.15648 19.7088 16.26451 18.30816 16.26451z" + fill="#59E1F9ff"></path> + <path + d="M18.0864 13.80269C18.0864 14.2633 17.71018 14.63683 17.2463 14.63683C16.78205 14.63683 16.40621 14.2633 16.40621 13.80269C16.40621 13.34208 16.78205 12.96845 17.2463 12.96845C17.71018 12.96845 18.0864 13.34208 18.0864 13.80269z" + fill="#00B9E7ff"></path> + <path + d="M7.64822 13.80259C7.64822 14.2632 7.272 14.63683 6.80816 14.63683C6.3439 14.63683 5.9681 14.2632 5.9681 13.80259C5.9681 13.34198 6.3439 12.96835 6.80816 12.96835C7.272 12.96835 7.64822 13.34198 7.64822 13.80259z" + fill="#00B9E7ff"></path> + <path + d="M12.91315 13.8025C12.91315 14.2631 12.53693 14.63674 12.07315 14.63674C11.6089 14.63674 11.23306 14.2631 11.23306 13.8025C11.23306 13.34189 11.6089 12.96826 12.07315 12.96826C12.53693 12.96826 12.91315 13.34189 12.91315 13.8025z" + fill="#00B9E7ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/travel.svg b/bb-api-collect/assets/zone_v2_icon/travel.svg new file mode 100644 index 0000000000..e2891a1ebe --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/travel.svg @@ -0,0 +1,26 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M7.28637 20.13062C7.28637 19.42819 7.85893 18.85872 8.56137 18.85872C9.2638 18.85872 9.83635 19.42819 9.83635 20.13062C9.83635 20.83306 9.2638 21.40253 8.56137 21.40253C7.85893 21.40253 7.28637 20.83306 7.28637 20.13062z" + fill="#59E1F9ff"></path> + <path + d="M14.51731 20.13062C14.51731 19.42819 15.08986 18.85872 15.79229 18.85872C16.49472 18.85872 17.06726 19.42819 17.06726 20.13062C17.06726 20.83306 16.49472 21.40253 15.79229 21.40253C15.08986 21.40253 14.51731 20.83306 14.51731 20.13062z" + fill="#59E1F9ff"></path> + <path + d="M9.77107 3.69966C9.29394 3.69966 8.90712 4.08648 8.90712 4.56366L8.90712 9.36919L7.75512 9.36919L7.75512 4.56366C7.75512 3.45025 8.65771 2.54766 9.77107 2.54766L14.35613 2.54766C15.46954 2.54766 16.37213 3.45025 16.37213 4.56366L16.37213 9.63337L15.22013 9.63337L15.22013 4.56366C15.22013 4.08648 14.83325 3.69966 14.35613 3.69966L9.77107 3.69966z" + fill="#59E1F9ff"></path> + <path + d="M7.37112 4.56367C7.37112 3.23819 8.44563 2.16366 9.77107 2.16366L14.35613 2.16366C15.6816 2.16366 16.75613 3.23818 16.75613 4.56366L16.75613 10.01737L14.83613 10.01737L14.83613 4.56366C14.83613 4.29856 14.62118 4.08366 14.35613 4.08366L9.77107 4.08366C9.50603 4.08366 9.29112 4.29856 9.29112 4.56367L9.29112 9.7532L7.37112 9.7532L7.37112 4.56367zM9.77107 2.93166C8.86979 2.93166 8.13912 3.66233 8.13912 4.56367L8.13912 8.9852L8.52312 8.9852L8.52312 4.56367C8.52312 3.87442 9.08187 3.31566 9.77107 3.31566L14.35613 3.31566C15.04541 3.31566 15.60413 3.87441 15.60413 4.56366L15.60413 9.24937L15.98813 9.24937L15.98813 4.56366C15.98813 3.66233 15.25747 2.93166 14.35613 2.93166L9.77107 2.93166z" + fill="#59E1F9ff"></path> + <path + d="M9.77146 4.03555C9.47984 4.03555 9.24345 4.27194 9.24345 4.56355L9.24345 4.80656C9.24345 5.31025 8.83513 5.71857 8.33145 5.71857C7.82776 5.71857 7.41945 5.31025 7.41945 4.80656L7.41945 4.56355C7.41945 3.26458 8.47247 2.21155 9.77146 2.21155L14.35642 2.21155C15.65539 2.21155 16.70842 3.26458 16.70842 4.56355L16.70842 4.90056C16.70842 5.40424 16.30013 5.81256 15.79642 5.81256C15.2928 5.81256 14.88442 5.40424 14.88442 4.90056L14.88442 4.56355C14.88442 4.27194 14.64806 4.03555 14.35642 4.03555L9.77146 4.03555z" + fill="#59E1F9ff"></path> + <path + d="M5.11429 8.49827C5.11429 7.7029 5.75914 7.05815 6.55452 7.05827C10.23398 7.05876 13.91347 7.05902 17.59296 7.05831C18.38842 7.05816 19.03334 7.70292 19.03334 8.49836L19.03334 18.42451C19.03334 19.21978 18.3887 19.86451 17.59334 19.86451C13.91366 19.86451 10.23398 19.86451 6.55429 19.86451C5.75901 19.86451 5.11429 19.21978 5.11429 18.42451L5.11429 8.49827z" + fill="#00B9E7ff"></path> + <path + d="M8.86945 11.22643C8.86945 10.69622 9.29926 10.26643 9.82944 10.26643C10.35965 10.26643 10.78944 10.69622 10.78944 11.22643L10.78944 15.69638C10.78944 16.22659 10.35965 16.65638 9.82944 16.65638C9.29926 16.65638 8.86945 16.22659 8.86945 15.69638L8.86945 11.22643z" + fill="#FDDE80ff"></path> + <path + d="M13.35821 11.22643C13.35821 10.69622 13.788 10.26643 14.31821 10.26643C14.84842 10.26643 15.27821 10.69622 15.27821 11.22643L15.27821 15.69638C15.27821 16.22659 14.84842 16.65638 14.31821 16.65638C13.788 16.65638 13.35821 16.22659 13.35821 15.69638L13.35821 11.22643z" + fill="#FDDE80ff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/assets/zone_v2_icon/vlog.svg b/bb-api-collect/assets/zone_v2_icon/vlog.svg new file mode 100644 index 0000000000..bb8343d055 --- /dev/null +++ b/bb-api-collect/assets/zone_v2_icon/vlog.svg @@ -0,0 +1,26 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%"> + <path + d="M19.21968 13.77802C19.42733 13.68547 19.56115 13.47936 19.56115 13.25194L19.56115 10.74586L20.71315 9.59381L20.71315 14.2224C20.71315 14.90957 20.30602 15.53146 19.67616 15.80621L13.80115 18.3696L10.51142 17.65949L19.21968 13.77802z" + fill="#6D69E4ff"></path> + <path + d="M19.56115 10.74586L20.71315 10.74586L20.71315 11.32186C20.71315 11.6399 20.4552 11.89786 20.13715 11.89786L19.56115 11.89786L19.56115 10.74586z" + fill="#6D69E4ff"></path> + <path + d="M18.40877 7.866C18.40877 7.54788 18.66662 7.29 18.98477 7.29L20.13677 7.29C20.45491 7.29 20.71277 7.54788 20.71277 7.866L20.71277 10.74595C20.71277 11.0641 20.45491 11.32195 20.13677 11.32195L18.98477 11.32195C18.66662 11.32195 18.40877 11.0641 18.40877 10.74595L18.40877 7.866z" + fill="#6D69E4ff"></path> + <path + d="M17.54477 3.8339L5.44875 3.8339C4.65346 3.8339 4.00875 4.47862 4.00875 5.2739L4.00875 12.76195C4.00875 13.55722 4.65347 14.20195 5.44875 14.20195L17.54477 14.20195C18.34003 14.20195 18.98477 13.55722 18.98477 12.76195L18.98477 5.2739C18.98477 4.47862 18.34003 3.8339 17.54477 3.8339z" + fill="#6D69E4ff"></path> + <path + d="M6.31312 6.13781C6.31312 5.50158 6.82889 4.98581 7.46512 4.98581L14.95315 4.98581C15.58934 4.98581 16.10515 5.50158 16.10515 6.13781L16.10515 11.89786C16.10515 12.53405 15.58934 13.04986 14.95315 13.04986L7.46512 13.04986C6.82889 13.04986 6.31312 12.53405 6.31312 11.89786L6.31312 6.13781z" + fill="#FDDE80ff"></path> + <path + d="M9.76877 7.50189C9.76877 7.04184 10.2815 6.76744 10.66426 7.02263L13.08182 8.63436C13.42387 8.86236 13.42387 9.36489 13.08182 9.59289L10.66426 11.20464C10.2815 11.45981 9.76877 11.18544 9.76877 10.72531L9.76877 7.50189z" + fill="#6D69E4ff"></path> + <path + d="M10.34515 16.50586C10.34515 15.7105 10.98989 15.06586 11.78515 15.06586L13.51315 15.06586C14.30842 15.06586 14.95315 15.7105 14.95315 16.50586L14.95315 19.09786C14.95315 19.89312 14.30842 20.53786 13.51315 20.53786L11.78515 20.53786C10.98989 20.53786 10.34515 19.89312 10.34515 19.09786L10.34515 16.50586z" + fill="#6D69E4ff"></path> + <path + d="M10.34515 17.8895L14.95315 17.8895L14.95315 18.8495L10.34515 18.8495L10.34515 17.8895z" + fill="#9796EDff"></path> +</svg> \ No newline at end of file diff --git a/bb-api-collect/docs/APP_widget/splash.md b/bb-api-collect/docs/APP_widget/splash.md new file mode 100644 index 0000000000..2a3179c471 --- /dev/null +++ b/bb-api-collect/docs/APP_widget/splash.md @@ -0,0 +1,567 @@ +# APP端开屏图片 + +## 获取APP端开屏图片列表 + +> https://app.bilibili.com/x/v2/splash/brand/list + +*请求方式:GET* + +鉴权方式:APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|--------|-----|-------|---------|-----| +| appkey | str | APP密钥 | APP方式必要 | | +| ts | num | 当前时间戳 | APP方式必要 | | +| sign | str | APP签名 | APP方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|---------------------------------------| +| code | num | 返回值 | 0:成功<br />-3:API校验密匙错误<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------------|-------|--------|--------| +| pull_interval | num | 1800 | 作用尚不明确 | +| forcibly | bool | false | 作用尚不明确 | +| rule | str | order | 作用尚不明确 | +| list | array | 开屏图片列表 | | +| show | array | 默认显示项 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|-----------|-----| +| 0 | obj | 开屏图片1 | | +| n | obj | 开屏图片(n+1) | | +| …… | obj | …… | …… | + +`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|----------|-----|---------------------|-----| +| id | num | 开屏图片id | | +| thumb | str | 开屏图片url | | +| logo_url | str | “bilibili”logo图片url | | + +`data`中的`show`数组: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|-------|-----| +| 0 | obj | 套了个娃? | | + +`show`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------|-----|--------|--------| +| id | num | 开屏图片id | | +| begin_time | num | 起始时间? | 时间戳 | +| end_time | num | 结束时间? | 时间戳 | +| probability | num | 0 | 作用尚不明确 | +| duration | num | 显示时间? | 单位为毫秒 | + +**示例:** + +```shell +curl -G 'https://app.bilibili.com/x/v2/splash/brand/list' \ +--data-urlencode 'appkey=1d8b6e7d45233436' \ +--data-urlencode 'ts=0' \ +--data-urlencode 'sign=78a89e153cd6231a4a4d55013aa063ce' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "pull_interval": 1800, + "forcibly": false, + "rule": "order", + "list": [ + { + "id": 10, + "thumb": "http://i0.hdslb.com/bfs/archive/e2d2f57e08b511d1a47203859f7bddb4ef9d4e16.png", + "logo_url": "http://i0.hdslb.com/bfs/archive/ecc9b29bb4b803daf2a46fe5ef71bf530300162c.png" + }, + { + "id": 11, + "thumb": "http://i0.hdslb.com/bfs/archive/fe737da5cdedf9dad038e5fd30e957be8a063bc2.png", + "logo_url": "http://i0.hdslb.com/bfs/archive/ecc9b29bb4b803daf2a46fe5ef71bf530300162c.png" + }, + { + "id": 12, + "thumb": "http://i0.hdslb.com/bfs/archive/574469a4a20f41ba4dc9ecd41d15f94eea875ed9.png", + "logo_url": "http://i0.hdslb.com/bfs/archive/ecc9b29bb4b803daf2a46fe5ef71bf530300162c.png" + }, + { + "id": 13, + "thumb": "http://i0.hdslb.com/bfs/archive/af0f4f611faa34340bd4f91def1973ccbfb8fbb3.png", + "logo_url": "http://i0.hdslb.com/bfs/archive/ecc9b29bb4b803daf2a46fe5ef71bf530300162c.png" + }, + { + "id": 14, + "thumb": "http://i0.hdslb.com/bfs/archive/1d40e975b09d5c87b11b3ae0c9ce6c6b82f63d9e.png", + "logo_url": "http://i0.hdslb.com/bfs/archive/ecc9b29bb4b803daf2a46fe5ef71bf530300162c.png" + } + ], + "show": [ + { + "id": 12, + "begin_time": 1597564800, + "end_time": 1630753108, + "probability": 0, + "duration": 700 + } + ] + } +} +``` + +</details> + +如id=11的图片为: + +<img src="https://i0.hdslb.com/bfs/archive/fe737da5cdedf9dad038e5fd30e957be8a063bc2.png" referrerpolicy="no-referrer" /> + + +## 获取APP端开屏幕广告信息 + +> https://app.bilibili.com/x/v2/splash/list + +*请求方式: GET* + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|----------|-----|-----------------------|-----|-----| +| build | int | 客户端内部版本号 | 必要 | | +| mobi_app | str | android, iphone, ipad | 必要 | | +| platform | str | android, ios | 必要 | | +| height | int | 屏幕高度 | 必要 | | +| width | int | 屏幕宽度 | 必要 | | +| birth | str | 生日日期(四位数,例 0101) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|---------------------------------------| +| code | num | 返回值 | 0:成功<br />-3:API校验密匙错误<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------------|--------|---------------------|---------| +| splash_request_id | 当前请求id | 长度为33, 前13位是当前秒级时间戳 | | +| max_time | int | 最长显示时间? | | +| min_interval | int | 最少显示时间? | 千分之一秒单位 | +| pull_interval | int | 显示时间? | | +| keep_ids | int | 显示时间? | | +| list | list | 广告 list | | + +`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|----------------------------|-------|---------------|--------| +| id | int | 广告id | | +| type | int | 1 | | +| card_type | int | 39 | | +| duration | int | 持续时间? | | +| begin_time | int | 开始展示时间 | 秒级时间戳 | +| end_time | int | 停止展示时间 | 毫秒级时间戳 | +| thumb | url | 广告图片 | | +| hash | str | 作用尚不明确 | | +| logo_url | str | 空值 | | +| logo_hash | str | 空值 | | +| skip | int | 是否跳转? | | +| uri | str | 跳转的url | | +| video_url | str | 视频url | | +| video_hash | str | 视频hash | | +| video_width | num | 视频宽度 | | +| video_height | num | 视频高度 | | +| uri_title | str | 空值 | | +| source | int | 929 | | +| cm_mark | int | 1 | | +| ad_cb | str | 作用尚不明确 | | +| resource_id | int | 926 | | +| request_id | str | 作用尚不明确 | | +| client_ip | str | 客户端IP | | +| is_ad | bool | 作用尚不明确 | | +| is_ad_loc | bool | 作用尚不明确 | | +| schema_title | str | 滑动进入第三方应用 | | +| schema_callup_white_list | array | 跳转的 APP 的白名单 | | +| extra | obj | 显示信息? | | +| enable_pre_download | bool | 是否可以当场下载 APP? | | +| enable_background_download | bool | 是否可以静默下载 APP? | | +| interact_type | int | 是否可以跳转(互动)? | | +| interact_url | str | 跳转(互动) url | | +| interact_distance | int | 作用尚不明确 | | +| guide_button_list | array | 所有的按钮 | | +| mark_with_skip_style | num | 作用尚不明确 | | +| skip_button_height | num | 作用尚不明确 | | + +`extra`对象: + +| 字段 | 类型 | 内容 | 备注 | +|----------------------------|-------|-----|-----| +| use_ad_web_v2 | bool | | | +| show_urls | array | | | +| click_urls | array | | | +| show_1s_urls | array | | | +| download_whitelist | array | | | +| open_whitelist | array | | | +| card | obj | | | +| report_time | num | | | +| sales_type | num | | | +| special_industry | bool | | | +| preload_landingpage | num | | | +| share_info | obj | | | +| upzone_entrance_type | num | | | +| upzone_entrance_report_id | num | | | +| topview_pic_url | str | | | +| topview_video_url | str | | | +| click_area | num | | | +| shop_id | num | | | +| up_mid | num | | | +| track_id | str | | | +| enable_store_direct_launch | int | | | +| enable_double_jump | bool | | | +| store_callup_card | bool | | | +| enable_h5_alert | bool | | | +| special_industry_style | num | | | +| macro_replace_priority | num | | | +| feedback_panel_style | num | | | +| ad_content_type | num | | | +| enable_h5_pre_load | num | | | +| hot_activity_id | num | | | +| product_id | num | | | +| landingpage_download_style | num | | | + +`guide_button_list` 中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|------------------------------|-------|-----|-------| +| id | int | | | +| x | int | | | +| y | int | | | +| bg_color | str | | | +| bg_color_night | str | | | +| text_color | str | | | +| text_color_night | str | | | +| guide_instructions | str | | | +| guide_instructions_new | str | 空值 | | +| width | str | | | +| jump_url | str | | | +| schema_package_name | str | | | +| schema_title | str | | | +| schema_title_new | str | 空值 | | +| height | str | | | +| slide_threshold_value | str | | | +| slide_border_color | str | | | +| guide_image_url | str | | | +| guide_image_md5 | str | | | +| interact_style | str | | | +| jump_image_url | str | | | +| jump_image_md5 | str | | | +| schema_image_url | str | | | +| schema_image_md5 | str | | | +| click_expand_ratio | str | | | +| logo_image_url | str | | | +| logo_image_md5 | str | | | +| related_ids | array | 空 | | +| schema_list | array | 空 | | +| font_ratio | num | | | +| seq | num | | | +| degrade_type | num | | | +| twist_angle | num | | | +| twist_speed | num | | | +| secondary_guide_instructions | str | | | +| secondary_font_ratio | num | | | +| secondary_text_color | str | | | +| secondary_text_color_night | str | | | +| activity_time | num | | 秒级时间戳 | +| time_show_type | num | | | + +**示例:** + +```shell +curl -X GET 'https://app.bilibili.com/x/v2/splash/list' \ + --data-urlencode 'build=999999999' \ + --data-urlencode 'mobi_app=android' \ + --data-urlencode 'platform=android' \ + --data-urlencode 'height=1920' \ + --data-urlencode 'width=1080' \ + --data-urlencode 'birth=0101' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "max_time": 4, + "min_interval": 14400, + "pull_interval": 900, + "keep_ids": null, + "list": [ + { + "id": 9460, + "type": 1, + "card_type": 39, + "duration": 5, + "begin_time": 1663689600, + "end_time": 1663775999, + "thumb": "https://i0.hdslb.com/bfs/sycp/creative_img/202208/cb001c291c6011940e29531dcce6b1e8.webp", + "hash": "712d3df973f99fdcd30c2419d19630dc", + "logo_url": "", + "logo_hash": "", + "skip": 1, + "uri": "https://market.m.taobao.com/app/mwdk-industry/mwdk-shopping-base/pages/peppa.html?disableNav=YES&merchantCode=HM&pageId=105240&path=%2Fact%2Frax%2Fmanual1455861656935693595&renderChannelCode=HM&siteCode=HM_8_7dd8299642994fa196f9a9aae4fd4391_3&spma=a225z&usePayment=alipayMiniApp&utm_campaign=dwlx&utm_source=1234&targetShopId=199273419", + "video_url": "http://upos-sz-static.bilivideo.com/ssaxcode/89/jl/n220831a21uql976d44zun4y0ykmjl89-1-SPLASH.mp4", + "video_hash": "ae10333c160452cc2755d079db10b597", + "video_width": 1080, + "video_height": 1920, + "uri_title": "", + "source": 929, + "cm_mark": 1, + "ad_cb": "COfrARC7jxUY9EkgADDWwCE4oQdCIDE2NjM2NDY2MzY1ODhxMTcyYTI2YTE5MmE5NnE1NDE0SKy0xMi1MFIG5aSp5rSlaP///////////wFw////////////AYABS4gB5+sBsgEg8mQFw0bBxGOGYE8OBhMOd3DE8OGFZXhookrFX4s3UrrwAruPFdgD9Ek=", + "resource_id": 926, + "request_id": "1663646636588q172a26a192a96q5414", + "client_ip": "117.14.146.37", + "is_ad": true, + "is_ad_loc": true, + "schema_title": "滑动进入第三方应用", + "schema_callup_white_list": [ + "tmall", + "taobao", + "openapp.jdmobile", + "weixin", + "alipays", + "tbopen", + "eleme", + "qqmusic", + "pddopen", + "upwallet", + "yocial://plaza/?tab=0", + "hiapplink", + "meiju", + "midea-meiju", + "uclink", + "qklink", + "taobaolite", + "lazyaudio", + "meituanwaimai", + "baiduboxapp://", + "baiduboxapp", + "fleamarket", + "dewuapp", + "duappmoblink", + "cmblife", + "imeituan", + "vmall", + "music", + "pinduoduo" + ], + "extra": { + "use_ad_web_v2": true, + "show_urls": [ + "https://g.cn.miaozhen.com/x/k=2315612&p=8EUuC&dx=__IPDX__&rt=2&pro=s&ns=__IP__&ni=__IESID__&v=__LOC__&xa=__ADPLATFORM__&tr=__REQUESTID__&vg=__AUTOPLAY__&nh=__AUTOREFRESH__&mo=__OS__&m0=__OPENUDID__&m0a=__DUID__&m1=__ANDROIDID1__&m1a=__ANDROIDID__&m2=__IMEI__&m4=__AAID__&m5=__IDFA__&m6=__MAC1__&m6a=__MAC__&m11=__OAID__&m14=__CAID__&m5a=__IDFV__&mn=__ANAME__&m5b=__IDFA1__&m11a=__OAID1__&m14a=__CAID1__&o=" + ], + "click_urls": [ + "https://e.cn.miaozhen.com/r/k=2315612&p=8EUuC&dx=__IPDX__&rt=2&pro=s&ns=__IP__&ni=__IESID__&v=__LOC__&xa=__ADPLATFORM__&tr=__REQUESTID__&mo=__OS__&m0=__OPENUDID__&m0a=__DUID__&m1=__ANDROIDID1__&m1a=__ANDROIDID__&m2=__IMEI__&m4=__AAID__&m5=__IDFA__&m6=__MAC1__&m6a=__MAC__&m11=__OAID__&m14=__CAID__&m5a=__IDFV__&mn=__ANAME__&m5b=__IDFA1__&m11a=__OAID1__&m14a=__CAID1__&o=" + ], + "show_1s_urls": [], + "download_whitelist": [], + "open_whitelist": [ + "tmall", + "taobao", + "openapp.jdmobile", + "weixin", + "alipays", + "tbopen", + "eleme", + "qqmusic", + "pddopen", + "upwallet", + "yocial://plaza/?tab=0", + "hiapplink", + "meiju", + "midea-meiju", + "uclink", + "qklink", + "taobaolite", + "lazyaudio", + "meituanwaimai", + "baiduboxapp://", + "baiduboxapp", + "fleamarket", + "dewuapp", + "duappmoblink", + "cmblife", + "imeituan", + "vmall", + "music", + "pinduoduo" + ], + "card": { + "card_type": 0, + "extreme_team_status": false, + "support_transition": false, + "under_player_interaction_style": 0, + "grade_denominator": 0, + "star_level": 0, + "live_booking_population_threshold": 0, + "ori_mark_hidden": 0, + "use_multi_cover": false, + "fold_time": 0, + "live_room_popularity": 0, + "live_tag_show": false, + "grade_level": 0 + }, + "report_time": 0, + "sales_type": 75, + "special_industry": false, + "preload_landingpage": 0, + "share_info": {}, + "upzone_entrance_type": 0, + "upzone_entrance_report_id": 0, + "topview_pic_url": "", + "topview_video_url": "", + "click_area": 0, + "shop_id": 0, + "up_mid": 0, + "track_id": "pbaes.Y5ATuPVlG6ysPF6cvl6W8B-BYexhSJzrKH3NYfC3KIHDb9W5cxPA4_FTEPWYDED5DjfRwb3tcrLppYAqQ87SSg==", + "enable_store_direct_launch": 0, + "enable_double_jump": false, + "store_callup_card": false, + "enable_h5_alert": false, + "special_industry_style": 0, + "macro_replace_priority": 1, + "feedback_panel_style": 0, + "ad_content_type": 0, + "enable_h5_pre_load": 0, + "hot_activity_id": 0, + "product_id": 0, + "landingpage_download_style": 2 + }, + "enable_pre_download": true, + "enable_background_download": true, + "interact_type": 1, + "interact_url": "https://market.m.taobao.com/app/mwdk-industry/mwdk-shopping-base/pages/peppa.html?disableNav=YES&merchantCode=HM&pageId=105240&path=%2Fact%2Frax%2Fmanual1455861656935693595&renderChannelCode=HM&siteCode=HM_8_7dd8299642994fa196f9a9aae4fd4391_3&spma=a225z&usePayment=alipayMiniApp&utm_campaign=dwlx&utm_source=1234&targetShopId=199273419", + "interact_distance": 60, + "guide_button_list": [ + { + "id": 49037, + "x": 50, + "y": 78, + "bg_color": "#80000000", + "bg_color_night": "#80000000", + "text_color": "#FFFFFFFF", + "text_color_night": "#FFFFFFFF", + "guide_instructions": "点击进入活动页", + "guide_instructions_new": "", + "width": 70, + "jump_url": "https://market.m.taobao.com/app/mwdk-industry/mwdk-shopping-base/pages/peppa.html?disableNav=YES&merchantCode=HM&pageId=105240&path=%2Fact%2Frax%2Fmanual1455861656935693595&renderChannelCode=HM&siteCode=HM_8_7dd8299642994fa196f9a9aae4fd4391_3&spma=a225z&usePayment=alipayMiniApp&utm_campaign=dwlx&utm_source=1234&targetShopId=199273419", + "schema_package_name": "", + "schema_title": "", + "schema_title_new": "", + "height": 7, + "slide_threshold_value": 5, + "slide_border_color": "#40FFFFFF", + "guide_image_url": "", + "guide_image_md5": "", + "interact_style": 6, + "jump_image_url": "https://i0.hdslb.com/bfs/sycp/creative_img/202208/f61a66cf54bc71d9bd1b81bde79c0140.json", + "jump_image_md5": "26d8b4b516f83a3f9b15fef643464cc6", + "schema_image_url": "https://i0.hdslb.com/bfs/sycp/creative_img/202208/f61a66cf54bc71d9bd1b81bde79c0140.json", + "schema_image_md5": "26d8b4b516f83a3f9b15fef643464cc6", + "click_expand_ratio": 100, + "logo_image_url": "https://i0.hdslb.com/bfs/sycp/mgk/img/202106/17006d50ec506813727b1cb5c6fc58b1.png", + "logo_image_md5": "86bc1b68ce4708d918cd4e01a975ca17", + "related_ids": [], + "schema_list": [], + "font_ratio": 0.23, + "seq": 0, + "degrade_type": 1, + "twist_angle": 0, + "twist_speed": -1, + "secondary_guide_instructions": "", + "secondary_font_ratio": 0, + "secondary_text_color": "", + "secondary_text_color_night": "", + "activity_time": 1662532059, + "time_show_type": 0 + }, + { + "id": 49040, + "x": 50, + "y": 83, + "bg_color": "#80000000", + "bg_color_night": "#80000000", + "text_color": "#FFFFFFFF", + "text_color_night": "#FFFFFFFF", + "guide_instructions": "即可前往 开吃新品", + "guide_instructions_new": "", + "width": 64, + "jump_url": "https://market.m.taobao.com/app/mwdk-industry/mwdk-shopping-base/pages/peppa.html?disableNav=YES&merchantCode=HM&pageId=105240&path=%2Fact%2Frax%2Fmanual1455861656935693595&renderChannelCode=HM&siteCode=HM_8_7dd8299642994fa196f9a9aae4fd4391_3&spma=a225z&usePayment=alipayMiniApp&utm_campaign=dwlx&utm_source=1234&targetShopId=199273419", + "schema_package_name": "", + "schema_title": "滑动进入第三方应用", + "schema_title_new": "", + "height": 3, + "slide_threshold_value": 5, + "slide_border_color": "#40FFFFFF", + "guide_image_url": "", + "guide_image_md5": "", + "interact_style": 3, + "jump_image_url": "https://i0.hdslb.com/bfs/sycp/creative_img/202208/f61a66cf54bc71d9bd1b81bde79c0140.json", + "jump_image_md5": "26d8b4b516f83a3f9b15fef643464cc6", + "schema_image_url": "https://i0.hdslb.com/bfs/sycp/creative_img/202208/f61a66cf54bc71d9bd1b81bde79c0140.json", + "schema_image_md5": "26d8b4b516f83a3f9b15fef643464cc6", + "click_expand_ratio": 100, + "logo_image_url": "https://i0.hdslb.com/bfs/sycp/mgk/img/202106/17006d50ec506813727b1cb5c6fc58b1.png", + "logo_image_md5": "86bc1b68ce4708d918cd4e01a975ca17", + "related_ids": [ + 49037 + ], + "schema_list": [], + "font_ratio": 0.23, + "seq": 99, + "degrade_type": 0, + "twist_angle": 0, + "twist_speed": -1, + "secondary_guide_instructions": "", + "secondary_font_ratio": 0, + "secondary_text_color": "", + "secondary_text_color_night": "", + "activity_time": 1662532059, + "time_show_type": 0 + } + ], + "mark_with_skip_style": 0, + "skip_button_height": 0.0557 + } + ], + "splash_request_id": "1663646636605q172a24a57a232q5796" + } +} +``` +</details> diff --git a/bb-api-collect/docs/APP_widget/ver.md b/bb-api-collect/docs/APP_widget/ver.md new file mode 100644 index 0000000000..3296c87a62 --- /dev/null +++ b/bb-api-collect/docs/APP_widget/ver.md @@ -0,0 +1,236 @@ +# 获取最新 APP 版本 + +## 获取版本信息 + +> https://app.bilibili.com/x/v2/version + +*请求方法: GET* + +<!--{ + "from": { + "url": "https://app.bilibili.com/" + } +}--> + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --- | --- | --- | --- | --- | +| mobi_app | str | 目标客户端类型 | 不必要 | 留空为最新有更新的平台<br />android: Android 版<br />iphone: iPhone 版<br />ipad: iPad HD 版<br />win: UWP 版<br />android_tv_yst: TV 版<br />android_car: 车机版<br />pc_client: PC 客户端 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | int | 返回值 | 0: 成功 | +| message | str | 错误信息 | 默认为 `0` | +| ttl | int | 1 | | +| data | array | 版本信息列表 | | + +`data` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| plat | int | 平台 | 0: Android<br />1: iPhone<br />2: iPad HD<br />3: UWP<br />12: TV 版<br />35: 车机版<br />40: PC 客户端 | +| desc | str | 版本描述 | | +| version | str | 版本号 | | +| build | int | 内部版本号 | | + +**示例:** + +```shell +curl -G 'https://app.bilibili.com/x/v2/version' \ +--url-query'mobi_app=android' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "plat": 0, + "desc": "-修复了一些bug,切了个大西瓜~", + "version": "8.9.0", + "build": 8090300, + "ptime": 1723612377 + }, + // ... + { + "plat": 0, + "desc": "[修正]横屏状态下,视频列表加载失败的问题\n[修正]超过48kHz采样率的音频无法播放的问题\n[修正]部分系统黑屏的问题\nPS:帮下面的同学祈祷早日上架", + "version": "2.0.4", + "build": 0, + "ptime": 1382630400 + } + ] +} +``` + +</details> + +## 版本升级 + +> https://app.bilibili.com/x/v2/version/fawkes/upgrade + +*请求方式: GET* + +鉴权方式(非必须):[APP API 签名与鉴权](../misc/sign/APP.md) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| - | - | - | - | - | +| abi | str | 设备 CPU ABI | 不必要 | 如 `arm64-v8a` | +| appid | str | 客户端类型 | 不必要 | 如 `tv.danmaku.bili` | +| brand | str | 设备品牌 | 不必要 | 如 `google` | +| build | int | 当前 APP 版本号 | 必要 | 如 `8000200` | +| channel | str | APP 分发渠道 | 必要 | 如 `master` | +| deviceid | str | 设备唯一 ID | 不必要 | 即 XU-Prefixed BUVID,见 [device_identity](../misc/device_identity.md) | +| env | str | APP 分发环境 | 不必要 | 默认 `prod` | +| iv | int | 当前 APP innerVer | 不必要 | 如 `8000210` | +| mobi_app | str | APP mobi_app | 必要 | 如 `android` | +| model | str | 设备型号 | 不必要 | 如 `Pixel 2 XL` | +| nt | str | - | 必要 | 默认 `1` | +| ov | str | 设备 OS 版本 | 必要 | 安卓即 API Level,如 Android 11 为 `30` | +| platform | str | 设备平台 | 不必要 | 如 `android` | +| screen | str | 设备屏幕参数 | 不必要 | 如 `2712_1440@537.882_537.882` +| sn | int | 当前 APP SN | 必要 | 如 `15088473` | +| vn | str | 当前 APP 版本名称 | 必要 | 如 `8.0.0` | + +**标头参数(Headers):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| - | - | - | - | - | +| app-key | str | APPKey 名称 | 必要 | 大体等同于 [`mobi_app`](../misc/sign/APPKey.md)。特别地:64 位版本粉版客户端应为 `android64` | +| buvid | str | BUVID | 必要 | XU-Prefixed BUVID,见 [device_identity](../misc/device_identity.md) | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| - | - | - | - | +| code | int | 返回值 | 0: 成功<br />-304: 木有改动<br />-400: 请求异常 | +| message | str | 错误信息 | 默认为 `0` | +| ttl | int | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| - | - | - | - | +| title | str | 标题 | | +| content | str | 内容 | | +| version | str | 最新版本名称 | | +| version_code | int | 最新版本号 | 即 `build` | +| url | str | 下载地址 | | +| size | int | 大小 | 单位字节 | +| md5 | str | MD5 值 | | +| silent | int | 是否静默安装? | | +| upgrade_type | int | 升级类型? | | +| cycle | int | 升级周期? | | +| policy | int | 升级策略? | | +| policy_url | str | 升级策略链接? | | +| ptime | int | 发布时间 | | + +**示例:** + +```shell +curl -G 'https://app.bilibili.com/x/v2/version/fawkes/upgrade' \ +--url-query 'build=1145141' \ +--url-query 'channel=apt' \ +--url-query 'mobi_app=android' \ +--url-query 'nt=awa' \ +--url-query 'ov=qwq' \ +--url-query 'platform=archlinux' \ +--url-query 'sn=919810' \ +--url-query 'vn=!!!' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "title": "升级提醒", + "content": "-修复了一些bug,并吃了一桶冰淇凌~\n-记得检查暑假作业哦!", + "version": "8.10.0", + "version_code": 8100300, + "url": "https://dl.hdslb.com/mobile/pack/android64/15793300/iBiliPlayer-apinkRelease-8.10.0-b15793300.apk", + "size": 132432843, + "md5": "f196c0ea68ff894dab0cf380cafad802", + "silent": 0, + "upgrade_type": 1, + "cycle": 4, + "policy": 0, + "policy_url": "", + "is_gray": 0, + "ptime": 1724207041 + } +} +``` + +</details> + +## 拼接最新版本下载地址 + +> https://api.bilibili.com/x/web-frontend/getappversion + +*请求方法: GET* + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---- | ---- | ---- | ---- | ---- | +| target | string | 目标平台 | 目测仅 `pc_electron`, 错误的值会导致返回 `HTTP 404` | +| cdn_url | string | CDN URL | 任意字符串, 默认 `https://dl.hdslb.com/mobile/fixed/bili_win/bili_win-install.exe` | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | number | 返回值 | 0: 成功<br />-1: need target | +| message | string | 错误消息 | 成功时无此项 | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| cdn_url | string | CDN URL | 内容同请求参数 `cdn_url` | +| sole_cdn_url | string | 带版本的 CDN URL | `cdn_url + "?v=" + 最新版本` | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/web-frontend/getappversion' \ +--url-query 'target=pc_electron' \ +--url-query 'cdn_url=https://dl.hdslb.com/mobile/fixed/bili_win/bili_win-install.exe' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "cdn_url": "https://dl.hdslb.com/mobile/fixed/bili_win/bili_win-install.exe", + "sole_cdn_url": "https://dl.hdslb.com/mobile/fixed/bili_win/bili_win-install.exe?v=1.16.1-2" + } +} +``` + +</details> diff --git a/bb-api-collect/docs/activity/info.md b/bb-api-collect/docs/activity/info.md new file mode 100644 index 0000000000..ddf2f682c8 --- /dev/null +++ b/bb-api-collect/docs/activity/info.md @@ -0,0 +1,93 @@ +# 活动主题信息 + +## 主题信息 + +> https://api.bilibili.com/x/activity/subject/info + +*请求方式: GET* + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| - | - | - | - | - | +| sid | num | 活动 id | 必要 | | +| bvid | str | 来源视频 bvid | 非必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| - | - | - | - | +| code | num | 返回值 | 0: 成功<br />-400: 请求错误 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| - | - | - | - | +| id | num | 活动 id | | +| oid | num | 0 | | +| type | num | 13 | | +| state | num | 1 | | +| stime | num | 开始时间 | UNIX 秒级时间戳 | +| etime | num | 结束时间 | UNIX 秒级时间戳 | +| ctime | num | 创建时间 | UNIX 秒级时间戳 | +| mtime | num | 修改时间 | UNIX 秒级时间戳 | +| name | str | 活动名称 | | +| act_url | str | 活动链接 | | +| lstime | num | ? | 作用尚不明确 | +| letime | num | ? | 作用尚不明确 | +| cover | str | 封面图片 | | +| dic | str | 简介 | | +| h5_cover | str | H5 封面 | | +| android_url | str | Android 端活动链接 | | +| ios_url | str | iOS 端活动链接 | | +| child_sids | str | 子活动 id? | | +| calendar | str | 日历? | 空 或 `{}`? | +| lid | num | ? | 仅在传入 bvid 时存在 | + +**示例:** + +```shell +curl -G --url 'https://api.bilibili.com/x/activity/subject/info' \ +--url-query 'sid=4017552' \ +--url-query 'bvid=BV1mKY4e8ELy' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "id": 4017552, + "oid": 0, + "type": 13, + "state": 1, + "stime": 1720540800, + "etime": 1728575999, + "ctime": 1720439769, + "mtime": 1720591285, + "name": "科技猎手2024第2季", + "act_url": "https://www.bilibili.com/blackboard/era/kejilieshou2PC.html", + "lstime": 1720540800, + "letime": 1728575999, + "cover": "https://i0.hdslb.com/bfs/activity-plat/static/98bc38873cc71e154019070975cd20a0/fLOEOStVUV.jpg", + "dic": "科技猎手召集中!投稿赢奖金>>", + "h5_cover": "https://i0.hdslb.com/bfs/activity-plat/static/98bc38873cc71e154019070975cd20a0/PTIFsXkV0o.jpg", + "android_url": "https://www.bilibili.com/blackboard/era/kejilieshou2H5.html", + "ios_url": "https://www.bilibili.com/blackboard/era/kejilieshou2H5.html", + "child_sids": "", + "calendar": "", + "lid": 294258214 + } +} +``` + +</details> diff --git a/bb-api-collect/docs/activity/list.md b/bb-api-collect/docs/activity/list.md new file mode 100644 index 0000000000..f187bd50ee --- /dev/null +++ b/bb-api-collect/docs/activity/list.md @@ -0,0 +1,213 @@ +# 活动列表 + +## 获取活动列表 + +> https://api.bilibili.com/x/activity/page/list + +*请求方式: GET* + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| plat | str | 活动平台类型? | 必要 | 可选范围 [1, 3], 以半角逗号分隔, 默认 `1,3` | +| mold | int | 0 | 非必要 | | +| http | int | 3 | 非必要 | | +| pn | int | 目标页码 | 非必要 | 默认为 `1` | +| ps | int | 每页条数 | 非必要 | 默认为 `15` | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| - | - | - | - | +| code | int | 返回值 | 0:成功<br />-400:请求错误 | +| message | str | 错误信息 | 默认为 0 | +| ttl | int | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| - | - | - | - | +| list | array | 活动列表 | | +| num | int | 当前页码 | | +| size | int | 每页条数 | | +| total | int | 总条数 | | + +`list` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| - | - | - | - | +| id | int | 活动 ID | | +| state | int | 1 | | +| stime | int | 开始时间 | UNIX 秒级时间戳 | +| etime | int | 结束时间 | UNIX 秒级时间戳 | +| ctime | int | 创建时间? | UNIX 秒级时间戳, 可能为 0 | +| mtime | int | 修改时间? | UNIX 秒级时间戳, 可能为 0 | +| name | str | 活动名称 | | +| author | str | 空 || +| pc_url | str | 空 || +| rank | int | 0 | | +| h5_url | str | 活动链接 | | +| pc_cover | str | 空 | | +| h5_cover | str | 活动封面 | | +| page_name | str | 页面名称 | | +| plat | int | 活动平台类型? | 即 URL 中 `plat` 参数 | +| desc | str | 活动描述 | | +| click | int | 0 | | +| type | int | 0 | | +| mold | int | 0 | | +| series | int | 0 | | +| dept | int | 0 | | +| reply_id | int | 0 | | +| tp_id | int | 0 | | +| ptime | int | 0 | | +| catalog | int | 0 | | +| creator | str | 空 | | +| spm_id | str | 空 | | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/activity/page/list' \ +--url-query 'plat=1,2,3' \ +--url-query 'ps=4' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "id": 207, + "state": 1, + "stime": 1723262400, + "etime": 1724774399, + "ctime": 0, + "mtime": 0, + "name": "原神fes2024", + "author": "", + "pc_url": "", + "rank": 0, + "h5_url": "https://www.bilibili.com/blackboard/era/DK8i0NS7fxwcLBgm.html", + "pc_cover": "", + "h5_cover": "https://i0.hdslb.com/bfs/activity-plat/static/d32c2bb79f59192cb072d7bf79b61c6d/In2tYOLFTZ.png", + "page_name": "原神fes2024", + "plat": 2, + "desc": "", + "click": 0, + "type": 0, + "mold": 0, + "series": 0, + "dept": 0, + "reply_id": 0, + "tp_id": 0, + "ptime": 0, + "catalog": 0, + "creator": "", + "spm_id": "" + }, + { + "id": 210, + "state": 1, + "stime": 1723219200, + "etime": 1725983999, + "ctime": 0, + "mtime": 0, + "name": "暗区突围端游海外版全员夺金冲榜挑战赛", + "author": "", + "pc_url": "", + "rank": 0, + "h5_url": "https://www.bilibili.com/blackboard/era/UP8CZSTfboDVZuGr.html", + "pc_cover": "", + "h5_cover": "https://i0.hdslb.com/bfs/activity-plat/static/f9a67e268d55d029e6b27d81246fc59a/LPN9dlcRlW.png", + "page_name": "暗区突围端游海外版全员夺金冲榜挑战赛", + "plat": 2, + "desc": "", + "click": 0, + "type": 0, + "mold": 0, + "series": 0, + "dept": 0, + "reply_id": 0, + "tp_id": 0, + "ptime": 0, + "catalog": 0, + "creator": "", + "spm_id": "" + }, + { + "id": 199, + "state": 1, + "stime": 1723089600, + "etime": 1725897599, + "ctime": 0, + "mtime": 0, + "name": "剑与远征:启程公测创作者激励", + "author": "", + "pc_url": "", + "rank": 0, + "h5_url": "https://www.bilibili.com/blackboard/era/HkHatvvW9nJZXEMh.html", + "pc_cover": "", + "h5_cover": "https://i0.hdslb.com/bfs/activity-plat/static/7785e7ecb0434c85530b92e3586f32ff/CgKENr0ftC.jpeg", + "page_name": "剑与远征:启程公测创作者激励", + "plat": 2, + "desc": "", + "click": 0, + "type": 0, + "mold": 0, + "series": 0, + "dept": 0, + "reply_id": 0, + "tp_id": 0, + "ptime": 0, + "catalog": 0, + "creator": "", + "spm_id": "" + }, + { + "id": 203, + "state": 1, + "stime": 1723089600, + "etime": 1724255999, + "ctime": 0, + "mtime": 0, + "name": "王者荣耀新英雄少司缘创作激励", + "author": "", + "pc_url": "", + "rank": 0, + "h5_url": "https://www.bilibili.com/blackboard/era/g0gn2j4ZENrCLYLn.html", + "pc_cover": "", + "h5_cover": "https://i0.hdslb.com/bfs/activity-plat/static/a99ba278036e9fbfa81b9100d13d9e7e/9UHZg6r0Y5.jpg", + "page_name": "王者荣耀新英雄少司缘创作激励", + "plat": 2, + "desc": "", + "click": 0, + "type": 0, + "mold": 0, + "series": 0, + "dept": 0, + "reply_id": 0, + "tp_id": 0, + "ptime": 0, + "catalog": 0, + "creator": "", + "spm_id": "" + } + ], + "num": 1, + "size": 4, + "total": 5391 + } +} +``` + +</details> diff --git a/bb-api-collect/docs/album/action.md b/bb-api-collect/docs/album/action.md new file mode 100644 index 0000000000..1d42821ecf --- /dev/null +++ b/bb-api-collect/docs/album/action.md @@ -0,0 +1,174 @@ +# 相簿操作 + +<details> +<summary>功能已下线</summary> + +## ~~点赞相簿~~ + +> https://api.vc.bilibili.com/link_draw/v2/Vote/operate + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | ------ | ---------------------- | +| doc_id | num | 相簿id | 必要 | | +| type | num | 操作方式 | 必要 | 1:点赞<br />2:取消赞 | +| csrf_token | str | CSRF Token(位于cookie) | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />1:参数错误<br />3:未登录<br />110022:已经操作过了 | +| msg | str | 错误信息 | 默认为success | +| message | str | 错误信息 | 默认为success | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---------------------- | +| type | num | 操作方式 | 1:点赞<br />2:取消赞 | + +**示例:** + +点赞相簿`id=99184721` + +```shell +curl 'https://api.vc.bilibili.com/link_draw/v2/Vote/operate' \ +--data-urlencode 'doc_id=99184721' \ +--data-urlencode 'type=1' \ +--data-urlencode 'csrf_token=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "message": "success", + "data": { + "type": 1 + } +} +``` + +</details> + +## ~~收藏相簿~~ + +> https://api.vc.bilibili.com/user_plus/v1/Fav/add + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | ------ | ------------ | +| fav_id | num | 相簿id | 必要 | | +| biz_type | num | 2 | 必要 | 作用尚不明确 | +| csrf_token | str | CSRF Token(位于cookie) | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-400:参数错误<br />-500:未登录<br />-507:已收藏 | +| msg | str | 错误信息 | 默认为OK | +| message | str | 错误信息 | 默认为OK | +| data | array | 空 | | + +**示例:** + +收藏相簿`id=99184721` + +```shell +curl 'https://api.vc.bilibili.com/user_plus/v1/Fav/add' \ +--data-urlencode 'fav_id=99184721' \ +--data-urlencode 'biz_type=2' \ +--data-urlencode 'csrf_token=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + + +```json +{ + "code": 0, + "msg": "OK", + "message": "OK", + "data": [] +} +``` + +</details> + +## 取消收藏相簿 + +> https://api.vc.bilibili.com/user_plus/v1/Fav/delete + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | ------ | ------------ | +| fav_id | num | 相簿id | 必要 | | +| biz_type | num | 2 | 必要 | 作用尚不明确 | +| csrf_token | str | CSRF Token(位于cookie) | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | --------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-400:参数错误<br />-500:未登录 | +| msg | str | 错误信息 | 默认为OK | +| message | str | 错误信息 | 默认为OK | +| data | array | 空 | | + +**示例:** + +取消收藏相簿`id=99184721` + +```shell +curl 'https://api.vc.bilibili.com/user_plus/v1/Fav/delete' \ +--data-urlencode 'fav_id=99184721' \ +--data-urlencode 'biz_type=2' \ +--data-urlencode 'csrf_token=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + + +```json +{ + "code": 0, + "msg": "OK", + "message": "OK", + "data": [] +} +``` + +</details> +</details> diff --git a/bb-api-collect/docs/album/activity_list.md b/bb-api-collect/docs/album/activity_list.md new file mode 100644 index 0000000000..4c82f37025 --- /dev/null +++ b/bb-api-collect/docs/album/activity_list.md @@ -0,0 +1,152 @@ +# 相簿活动列表 + +<details> +<summary>功能已下线</summary> + +## 获取相簿热门活动列表 + +> https://api.vc.bilibili.com/photo_activity/v2/Activity/list + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | -------- | ------ | --------------------------------------------- | +| type | num | 活动类型 | 非必要 | 0:全部<br/>1:展示类<br/>2:比赛类 | +| biz | num | 分区 | 非必要 | 0:全部<br />1:画友<br/>2:摄影<br />默认为0 | +| page_num | num | 页码 | 非必要 | 默认为4 | +| page_size | num | 每页项数 | 非必要 | 默认为0 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------ | +| code | num | 返回值 | 0:成功<br />1:参数错误 | +| msg | str | 错误信息 | 默认为success | +| message | str | 错误信息 | 默认为success | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----- | ---------- | ---- | +| total_count | str | 总计活动数 | | +| items | array | 活动列表 | | + +`data`中的`items`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------- | ---- | +| 0 | obj | 活动 1 | | +| n | obj | 活动 (n+1) | | +| …… | obj | …… | …… | + +`data`中的`items`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------- | ------------------------ | +| cover | str | 活动图片url | | +| title | str | 活动标题 | | +| link | str | 活动页面url | | +| type | num | 活动类型 | 1:展示类<br/>2:比赛类 | +| biz | num | 所属分区 | 1:画友<br/>2:摄影 | +| tag | str | 活动关联的TAG | | +| start_time | num | 开始时间 | 时间戳 | +| end_time | num | 结束时间 | 时间戳 | +| desc | str | 备注 | | +| desc_type | num | 活动状态 | 1:已结束<br />2:进行中 | + +**示例:** + +获取`画友`分区,全部类型的5条活动 + +```shell +curl -G 'https://api.vc.bilibili.com/photo_activity/v2/Activity/list' \ +--data-urlencode 'type=0' \ +--data-urlencode 'biz=1' \ +--data-urlencode 'page_num=0' \ +--data-urlencode 'page_size=5' +``` + +<details> +<summary>查看响应示例:</summary> + + +```json +{ + "code": 0, + "msg": "success", + "message": "success", + "data": { + "total_count": 21, + "items": [ + { + "cover": "http://i0.hdslb.com/bfs/vc/344d175cf88f217ce8bd0f004a2c5e770eff2e03.png", + "title": "#月饼拟人#创作大赛!丰厚奖励等你来拿!", + "link": "https://www.bilibili.com/read/cv1102416", + "type": 1, + "biz": 1, + "tag": "", + "start_time": 1535817600, + "end_time": 1540915200, + "desc": "已结束", + "desc_type": 1 + }, + { + "cover": "http://i0.hdslb.com/bfs/vc/63d48fbc37f0142a9c72e06ebc950d4089f881d6.png", + "title": "「ISLAND」同人绘画大赛", + "link": "https://www.bilibili.com/blackboard/activity-rkOlNomMQ.html", + "type": 2, + "biz": 1, + "tag": "ISLAND同人绘画", + "start_time": 1530720000, + "end_time": 1534435200, + "desc": "已结束", + "desc_type": 1 + }, + { + "cover": "http://i0.hdslb.com/bfs/vc/08d20bc6c10e1e310946ebaaf56c2c90c921644d.jpg", + "title": "我家大师兄脑子有坑同人绘画大赛", + "link": "https://www.bilibili.com/blackboard/activity-S1lV0Ot6M.html", + "type": 2, + "biz": 1, + "tag": "兄坑同人绘画大赛", + "start_time": 1525449600, + "end_time": 1528473600, + "desc": "已结束", + "desc_type": 1 + }, + { + "cover": "http://i0.hdslb.com/bfs/vc/4eb48398ec0824e96fc878235536f2e0b4a8aef5.jpg", + "title": "国宝复“活”计划", + "link": "https://www.bilibili.com/blackboard/activity-SJ4hL_UFz.html", + "type": 2, + "biz": 1, + "tag": "国宝复“活”计划", + "start_time": 1521388800, + "end_time": 1525017600, + "desc": "已结束", + "desc_type": 1 + }, + { + "cover": "http://i0.hdslb.com/bfs/vc/9068f91f62ea5a36cbafff263d7e47af99cc9836.jpg", + "title": "画师专访——管郁生", + "link": "https://www.bilibili.com/blackboard/interview-guanyusheng.html", + "type": 1, + "biz": 1, + "tag": "", + "start_time": 1517414400, + "end_time": 0, + "desc": "进行中", + "desc_type": 2 + } + ] + } +} +``` + +</details> +</details> diff --git a/bb-api-collect/docs/album/info.md b/bb-api-collect/docs/album/info.md new file mode 100644 index 0000000000..5489857950 --- /dev/null +++ b/bb-api-collect/docs/album/info.md @@ -0,0 +1,249 @@ +# 相簿基本信息 + +<details> +<summary>功能已下线</summary> + +## 获取相簿详细信息 + +>https://api.vc.bilibili.com/link_draw/v1/doc/detail + +*请求方式:GET* + +认证方式:Cookie(SESSDSTA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---------- | ------ | ---- | +| doc_id | num | 目标相簿id | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------------- | +| code | num | 返回值 | 0:成功<br />110001:找不到目标相簿 | +| msg | str | 错误信息 | 默认为success | +| message | str | 错误信息 | 默认为success | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| user | obj | 作者信息 | | +| item | obj | 相簿信息 | | + +`data`中的`user`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ---------- | ---- | +| uid | num | 作者mid | | +| head_url | str | 头像url | | +| name | str | 昵称 | | +| vip | obj | 会员信息 | | +| upload_count | str | 相簿投稿数 | | + +`user`中的`vip`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ------------ | ------------------------------------------------- | +| vipType | num | 会员类型 | 0:无<br />1:月度大会员<br />2:年度及以上大会员 | +| vipDueDate | num | 会员到期时间 | 毫秒 时间戳 | +| dueRemark | str | 空 | 作用尚不明确 | +| accessStatus | num | 0 | 作用尚不明确 | +| vipStatus | num | 会员开通状态 | 0:无<br />1:有 | +| vipStatusWarn | str | 空 | 作用尚不明确 | +| themeType | num | 0 | 作用尚不明确 | +| label | obj | ? | 作用尚不明确 | + +`vip`中的`label`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ------------ | +| path | str | 空 | 作用尚不明确 | + +`data`中的`item`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ----- | ------------------ | ------------------------------------------------------------ | +| biz | num | 相簿分区 | 1:画友<br />2:摄影<br />3:日常 | +| doc_id | num | 相簿id | | +| poster_uid | num | 作者mid | | +| category | str | 子分区标识 | cos:cosplay<br />daily:日常<br />illustration:插画<br />comic:漫画<br />draw:其他<br />sifu:私服 | +| type | num | 相簿类型 | 0:原创<br />1:同人 | +| title | str | 标题 | | +| tags | array | 相簿TAG | | +| pictures | array | 相簿图片 | | +| source | null | | 作用尚不明确 | +| upload_time | str | 投稿时间(时间码) | YYYY-MM-DD hh:mm:ss | +| upload_timestamp | num | 投稿时间(时间戳) | | +| upload_time_text | str | 投稿时间(文本) | | +| description | str | 简介 | | +| role | null | | 作用尚不明确 | +| settings | obj | 权限配置 | | +| already_collected | num | 是否已收藏 | 需要登录(Cookie)<br />否则恒为0 | +| already_liked | num | 0 | 作用尚不明确 | +| user_status | num | 0 | 作用尚不明确 | +| at_control | str | 空 | 作用尚不明确 | +| view_count | num | 观看数 | | +| like_count | num | 0 | 作用尚不明确 | +| collect_count | num | 收藏数 | | +| verify_status | num | 1 | 作用尚不明确 | +| already_voted | num | 是否已点赞 | 需要登录(Cookie)<br />否则恒为0 | +| vote_count | num | 点赞数 | | +| comment_count | num | 评论数 | | + +`item`中的`tags`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---- | +| 0 | obj | TAG 1 | | +| n | obj | TAG (n+1) | | +| …… | obj | …… | …… | + +`item`中的`tags`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | --------------- | --------------- | +| tag | str | TAG名 | | +| type | num | 类型? | | +| category | str | TAG所属子分区名 | | +| link | str | 活动页面url | 是活动TAG有此项 | +| text | str | TAG名 | | +| name | str | TAG名 | | + +`item`中的`pictures`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------- | ---- | +| 0 | obj | 图片 1 | | +| n | obj | 图片 (n+1) | | +| …… | obj | …… | …… | + +`item`中的`pictures`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | -------- | ----------- | +| img_src | str | 图片url | | +| img_width | num | 图片宽度 | | +| img_height | num | 图片高度 | | +| img_size | num | 图片大小 | 单位为KByte | + +`item`中的`settings`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | ------------ | ------------------------------------------------------------ | +| copy_forbidden | num | 禁止转载标志 | 0:不设置转载权限<br />1:开放授权-署名-非商用转载<br />2:作者授权-署名-非商用转载<br />3:禁止转载 | + +**示例:** + +查询相簿`id=99184721`的详细信息 + +```shell +curl -G 'https://api.vc.bilibili.com/link_draw/v1/doc/detail' \ +--data-urlencode 'doc_id=99184721' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + + +```json +{ + "code": 0, + "msg": "success", + "message": "success", + "data": { + "user": { + "uid": 813818, + "head_url": "https://i2.hdslb.com/bfs/face/26b12390399f3e82fb913922938f8a6662d28665.jpg", + "name": "QYS3", + "vip": { + "vipType": 2, + "vipDueDate": 1613750400000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "upload_count": "171" + }, + "item": { + "biz": 1, + "doc_id": 99184721, + "poster_uid": 813818, + "category": "illustration", + "type": 1, + "title": "旅行", + "tags": [ + { + "tag": "魔女之旅", + "type": 4, + "category": "illustration", + "text": "魔女之旅", + "name": "魔女之旅" + }, + { + "tag": "伊蕾娜", + "type": 3, + "category": "illustration", + "text": "伊蕾娜", + "name": "伊蕾娜" + }, + { + "tag": "旅行", + "type": 3, + "category": "illustration", + "text": "旅行", + "name": "旅行" + }, + { + "tag": "魔女", + "type": 3, + "category": "illustration", + "text": "魔女", + "name": "魔女" + } + ], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/d531e3dae34ef65b44ecdb2914d4cc4f5a4da998.jpg", + "img_width": 1236, + "img_height": 1600, + "img_size": 508 + } + ], + "source": null, + "upload_time": "2020-11-23 23:03:12", + "upload_timestamp": 1606143792, + "upload_time_text": "3天前", + "description": "伊蕾娜世界第一~!", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 143699, + "like_count": 0, + "collect_count": 54, + "verify_status": 1, + "already_voted": 0, + "vote_count": 2258, + "comment_count": 98 + } + } +} +``` + +</details> +</details> diff --git a/bb-api-collect/docs/album/list.md b/bb-api-collect/docs/album/list.md new file mode 100644 index 0000000000..44adb6fe8e --- /dev/null +++ b/bb-api-collect/docs/album/list.md @@ -0,0 +1,2438 @@ +# 相簿列表 + +<details> +<summary>功能已下线</summary> + +## 获取画友首页列表 + +> https://api.vc.bilibili.com/link_draw/v2/Doc/index + +*请求方式:GET* + +认证方式:Cookie(SESSDSTA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | -------- | ------ | ------------------------------------------- | +| type | str | 排序方式 | 必要 | recommend:推荐<br/>hot:最热<br/>new:最新 | +| page_num | num | 页码 | 非必要 | 默认为1 | +| page_size | num | 每页项数 | 非必要 | 默认为45 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------ | +| code | num | 返回值 | 0:成功<br />1:参数错误 | +| msg | str | 错误信息 | 默认为success | +| message | str | 错误信息 | 默认为success | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----- | ---------- | ---- | +| items | array | 相簿列表 | | +| total_count | num | 总计条目数 | | + +`data`中的`items`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------- | ---- | +| 0 | obj | 相簿 1 | | +| n | obj | 相簿 (n+1) | | +| …… | obj | …… | …… | + +`data`中的`items`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| user | obj | 作者信息 | | +| item | obj | 相簿信息 | | + +`data`中的`items`数组中的对象中的`user`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------- | ---- | +| uid | num | 作者mid | | +| head_url | str | 头像url | | +| name | str | 昵称 | | + +`data`中的`items`数组中的对象中的`item`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ----- | ---------- | --------------------------------- | +| doc_id | num | 相簿id | | +| poster_uid | num | 作者mid | | +| pictures | array | 相簿图片 | | +| title | str | 标题 | | +| category | str | 子分区名 | | +| upload_time | num | 投稿时间 | 时间戳 | +| already_liked | num | 0 | 作用尚不明确 | +| already_voted | num | 是否已点赞 | 需要登录(Cookie)<br />否则恒为0 | + +`item`中的`pictures`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------- | ---- | +| 0 | obj | 图片 1 | | +| n | obj | 图片 (n+1) | | +| …… | obj | …… | …… | + +`item`中的`pictures`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | -------- | ---- | +| img_src | str | 图片url | | +| img_width | num | 图片宽度 | | +| img_height | num | 图片高度 | | + +**示例:** + +用按热度排序方式获取画友首页列表 + +```shell +curl -G 'https://api.vc.bilibili.com/link_draw/v2/Doc/index' \ +--data-urlencode 'type=hot' \ +--data-urlencode 'page_num=1' \ +--data-urlencode 'page_size=5' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "message": "success", + "data": { + "items": [ + { + "user": { + "uid": 813818, + "head_url": "http://i2.hdslb.com/bfs/face/26b12390399f3e82fb913922938f8a6662d28665.jpg", + "name": "QYS3" + }, + "item": { + "doc_id": 99184721, + "poster_uid": 813818, + "pictures": [ + { + "img_src": "http://i0.hdslb.com/bfs/album/d531e3dae34ef65b44ecdb2914d4cc4f5a4da998.jpg", + "img_width": 1236, + "img_height": 1600, + "img_size": 508 + } + ], + "title": "旅行", + "category": "illustration", + "upload_time": 1606143792, + "already_liked": 0, + "already_voted": 1 + } + }, + { + "user": { + "uid": 813818, + "head_url": "http://i2.hdslb.com/bfs/face/26b12390399f3e82fb913922938f8a6662d28665.jpg", + "name": "QYS3" + }, + "item": { + "doc_id": 99456663, + "poster_uid": 813818, + "pictures": [ + { + "img_src": "http://i0.hdslb.com/bfs/album/cb202244684de733f026240b60ac28bb32ba39fd.jpg", + "img_width": 849, + "img_height": 1200, + "img_size": 513 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/30b8fb29d4ab3237018be7aeddc678fff9860885.jpg", + "img_width": 849, + "img_height": 1200, + "img_size": 513 + } + ], + "title": "大头", + "category": "illustration", + "upload_time": 1606405574, + "already_liked": 0, + "already_voted": 0 + } + }, + { + "user": { + "uid": 2244861, + "head_url": "http://i2.hdslb.com/bfs/face/7fd263548d587465b9f2ad5797e483b6c9182941.jpg", + "name": "Slancx" + }, + "item": { + "doc_id": 186801, + "poster_uid": 2244861, + "pictures": [ + { + "img_src": "http://i0.hdslb.com/bfs/vc/cd9443a37ce08ec5b3df65166107f7cae23172e3.jpg", + "img_width": 1939, + "img_height": 2841, + "img_size": 1824 + }, + { + "img_src": "http://i0.hdslb.com/bfs/vc/8c282a9d76372c4ff3cc27b92fbeb2feb6b45767.jpg", + "img_width": 1954, + "img_height": 2902, + "img_size": 1996 + }, + { + "img_src": "http://i0.hdslb.com/bfs/vc/a9e0163001ce17f996b205f95627ea550b5793db.jpg", + "img_width": 3778, + "img_height": 5728, + "img_size": 6070 + } + ], + "title": "边边封面", + "category": "illustration", + "upload_time": 1504255746, + "already_liked": 0, + "already_voted": 0 + } + }, + { + "user": { + "uid": 751036, + "head_url": "http://i2.hdslb.com/bfs/face/be1cf20d37cd104b32e2e935fb2ef65bfe09e2bc.jpg", + "name": "洛书23333333" + }, + "item": { + "doc_id": 1091581, + "poster_uid": 751036, + "pictures": [ + { + "img_src": "http://i0.hdslb.com/bfs/album/e78d3f6bbc487a003a3a72677c1975f781ac2090.jpg", + "img_width": 1289, + "img_height": 1108, + "img_size": 188 + } + ], + "title": "青鸟", + "category": "illustration", + "upload_time": 1512041349, + "already_liked": 0, + "already_voted": 0 + } + }, + { + "user": { + "uid": 21833522, + "head_url": "http://i2.hdslb.com/bfs/face/9037fc1027d780083ecc2e818b512b69b9267e7c.jpg", + "name": "欧阳鹏杰-OY" + }, + "item": { + "doc_id": 835730, + "poster_uid": 21833522, + "pictures": [ + { + "img_src": "http://i0.hdslb.com/bfs/vc/acb88974c768aa24c092927ae59291023d55f175.jpg", + "img_width": 1200, + "img_height": 832, + "img_size": 914 + }, + { + "img_src": "http://i0.hdslb.com/bfs/vc/9dff2455d595835c8a214d73f3cf10633304acbe.jpg", + "img_width": 3000, + "img_height": 2000, + "img_size": 2305 + }, + { + "img_src": "http://i0.hdslb.com/bfs/vc/643f775358085c55b598b1d6f5941ea0114344ea.jpg", + "img_width": 1494, + "img_height": 1000, + "img_size": 475 + } + ], + "title": "OY超写实钢笔画:轨迹", + "category": "illustration", + "upload_time": 1509533004, + "already_liked": 0, + "already_voted": 0 + } + } + ] + } +} +``` + +</details> + +## 获取摄影首页列表 + +> https://api.vc.bilibili.com/link_draw/v2/Photo/index + +*请求方式:GET* + +认证方式:Cookie(SESSDSTA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | -------- | ------ | --------------- | +| type | str | 排序方式 | 必要 | recommend:推荐 | +| page_num | num | 页码 | 非必要 | 默认为1 | +| page_size | num | 每页项数 | 非必要 | 默认为45 | + +**json回复:** + +见[获取画友首页列表](#获取画友首页列表)中的响应内容 + +**示例:** + +用推荐方式获取画友首页列表 + +```shell +curl -G 'https://api.vc.bilibili.com/link_draw/v2/Photo/index' \ +--data-urlencode 'type=recommend' \ +--data-urlencode 'page_num=1' \ +--data-urlencode 'page_size=5' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "message": "success", + "data": { + "items": [ + { + "user": { + "uid": 2487587, + "head_url": "https://i0.hdslb.com/bfs/face/4cd0d05708c4826737eef2cf3c5cb3c5361a2a2a.jpg", + "name": "是茶茶茶茶子呀" + }, + "item": { + "doc_id": 1164937, + "poster_uid": 2487587, + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/07019ac09fa0bc63a6403eb28db1222792ab4768.jpg", + "img_width": 2048, + "img_height": 3623, + "img_size": 3501 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/469cdb91f88822cbaf9639b2fa12b0a481e3ac60.jpg", + "img_width": 2048, + "img_height": 3072, + "img_size": 3173 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/61d5a369f93debbc3187026fd35df8f994156f3b.jpg", + "img_width": 2048, + "img_height": 1365, + "img_size": 1788 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/39f4bf47a96842a5834e5a49420fbf960bc7f5b7.jpg", + "img_width": 2048, + "img_height": 1365, + "img_size": 2046 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/4f14ad7008f0b5ce3a99c4234543f8ee05ecbfd8.jpg", + "img_width": 2048, + "img_height": 1365, + "img_size": 2154 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/6aebb9afb4139b8a83da8f276a20ab9201b29bb9.jpg", + "img_width": 2048, + "img_height": 3072, + "img_size": 3109 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/1942e0ffd95283898b0ee0fa5e236cdf146cf492.jpg", + "img_width": 2048, + "img_height": 1365, + "img_size": 1342 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/02e83961560492ae947347b2c49ae0aad305790b.jpg", + "img_width": 2048, + "img_height": 1365, + "img_size": 1537 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/8cadaf8660136fae7f75cb35b56fd6b39fe4913c.jpg", + "img_width": 2048, + "img_height": 3072, + "img_size": 3430 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/1ac1fdbb883b68a65d5e575a43c68c56afa98b91.jpg", + "img_width": 2048, + "img_height": 3072, + "img_size": 4446 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/352242d86a6689fb9935a76360ddc010edc844ea.jpg", + "img_width": 2048, + "img_height": 1365, + "img_size": 1443 + } + ], + "title": "COS 明日香", + "category": "cos", + "upload_time": 1512184831, + "already_liked": 0, + "already_voted": 0 + } + }, + { + "user": { + "uid": 13104471, + "head_url": "https://i1.hdslb.com/bfs/face/af36442eafccc5b743cc1aff7922d84fd9279005.jpg", + "name": "Shika小鹿鹿鹿" + }, + "item": { + "doc_id": 1225984, + "poster_uid": 13104471, + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/6ba1d9a136566c21a3950c8707a6c3b3121b81bb.jpg", + "img_width": 1728, + "img_height": 1080, + "img_size": 315 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/be5d659cde3b17c8ec60db503e33769a6a0183ae.jpg", + "img_width": 1080, + "img_height": 1620, + "img_size": 348 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/14676962db356877a81b175024da24230305688e.jpg", + "img_width": 1080, + "img_height": 1620, + "img_size": 256 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/ee3f7b04f17c2b612311b145a7dde5bf782e91ae.jpg", + "img_width": 1728, + "img_height": 1080, + "img_size": 242 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/88e88b000379d0e51346e74d84dfc3952f17d34b.jpg", + "img_width": 1080, + "img_height": 1620, + "img_size": 312 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/16342927703a298024fce2e0a16018bdf9f3e634.jpg", + "img_width": 1728, + "img_height": 1080, + "img_size": 318 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/1098a86a0b186840b4eec74cae6a92b16dcfaf5c.jpg", + "img_width": 1728, + "img_height": 1080, + "img_size": 288 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/7bd01b575e391f218a4c86e04964fab514aed2b7.jpg", + "img_width": 1728, + "img_height": 1080, + "img_size": 336 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/2aca94992789eb6ea35a4a398f0f98c83ac48449.jpg", + "img_width": 1620, + "img_height": 1080, + "img_size": 302 + } + ], + "title": "清月之辉——阎魔", + "category": "cos", + "upload_time": 1512472775, + "already_liked": 0, + "already_voted": 0 + } + }, + { + "user": { + "uid": 2651372, + "head_url": "https://i1.hdslb.com/bfs/face/06285d510887ab8f08f3639de021273d31aa6e9f.jpg", + "name": "假酒澡堂" + }, + "item": { + "doc_id": 1161521, + "poster_uid": 2651372, + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/41b7f22f31faedf0e6fb7ea694e5cd460ed01744.jpg", + "img_width": 2667, + "img_height": 4000, + "img_size": 7063 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/66af6e9685516820a92aa959caf47776afd95899.jpg", + "img_width": 4000, + "img_height": 2667, + "img_size": 5164 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/f69af7f3802aec88616e3d0567930eb74a0c0b49.jpg", + "img_width": 4000, + "img_height": 2667, + "img_size": 6863 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/cabd2bd20c2b47bcebb8a33c2f645ecbfe610aac.jpg", + "img_width": 6480, + "img_height": 4320, + "img_size": 13374 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/2780c80797cfb709d3d00b884f0c8c491c2fb33e.jpg", + "img_width": 2667, + "img_height": 4000, + "img_size": 5553 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/c221300d9c9949eb2654dc65288437d2509716e9.jpg", + "img_width": 6480, + "img_height": 4320, + "img_size": 14213 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/be4710e76452d48aaae6a45e4ad813248a79efe2.jpg", + "img_width": 4000, + "img_height": 2667, + "img_size": 4733 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/c87cabbfcdca90e9136d7c66e4b9b9ec586af957.jpg", + "img_width": 4000, + "img_height": 2667, + "img_size": 5654 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/65892d474ae09290f4e7f64461f0c21b4ee4664c.jpg", + "img_width": 4000, + "img_height": 2667, + "img_size": 4657 + } + ], + "title": "奥雅之光-异梦守护者", + "category": "cos", + "upload_time": 1512168749, + "already_liked": 0, + "already_voted": 0 + } + }, + { + "user": { + "uid": 7732095, + "head_url": "https://i0.hdslb.com/bfs/face/d0c465d55d457bd15760651e2eb7f9278055b40c.jpg", + "name": "超高校级的鲷鱼烧" + }, + "item": { + "doc_id": 1159580, + "poster_uid": 7732095, + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/256ee4ccd4f3ed859fd71702513a345c2b4beeb4.jpg", + "img_width": 2159, + "img_height": 1569, + "img_size": 801 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/c76707f83078c61d48a8ff1ee2888542bb64cef3.jpg", + "img_width": 1480, + "img_height": 1973, + "img_size": 617 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/a363e8ac04a90d4aecb567ff278a88b051886122.jpg", + "img_width": 1620, + "img_height": 2160, + "img_size": 876 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/06bc09d1927ba65e7210650e0cfe887d37b7871b.jpg", + "img_width": 1620, + "img_height": 2160, + "img_size": 885 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/ea5e47d7c99b1be8f799b1bf356ef81d58926a0c.jpg", + "img_width": 2160, + "img_height": 1620, + "img_size": 701 + } + ], + "title": "lolita私影", + "category": "sifu", + "upload_time": 1512148075, + "already_liked": 0, + "already_voted": 0 + } + }, + { + "user": { + "uid": 65579886, + "head_url": "https://i2.hdslb.com/bfs/face/b5f66542be47c508dd425d13fb7245655bc02413.jpg", + "name": "丹砂Scorpius" + }, + "item": { + "doc_id": 1177247, + "poster_uid": 65579886, + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/53b14da232bb4aacc7bfeeba0caf8ebb1d9f0395.jpg", + "img_width": 3000, + "img_height": 2001, + "img_size": 3959 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/58f2fbc6c285571fa31cc032fb790fae5f8ffac0.jpg", + "img_width": 3000, + "img_height": 2001, + "img_size": 4106 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/018f4ddacf1ae792d2e6169ee394f336155d369e.jpg", + "img_width": 4000, + "img_height": 2668, + "img_size": 6534 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/874e31e7e3d6a3653c797583e6643d5d778d7a2c.jpg", + "img_width": 3000, + "img_height": 2001, + "img_size": 5484 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/7ff9b60bcecd80b5923194dee4de29251b37ce2c.jpg", + "img_width": 2000, + "img_height": 2998, + "img_size": 5969 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/0926b507b8e6ff11951b36732e9a089d49836e0e.jpg", + "img_width": 2000, + "img_height": 3000, + "img_size": 3671 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/c55994fbf1e8a20425066bd6f4acc4347c197d11.jpg", + "img_width": 3000, + "img_height": 2001, + "img_size": 3069 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/03e621a23626d8d9f584a0d0663e1a77bd2832f1.jpg", + "img_width": 3000, + "img_height": 2001, + "img_size": 4339 + } + ], + "title": "天涯明月刀ol明月心", + "category": "cos", + "upload_time": 1512214505, + "already_liked": 0, + "already_voted": 0 + } + } + ], + "total_count": 200 + } +} +``` + +</details> + +## 获取画友列表 + +> https://api.vc.bilibili.com/link_draw/v2/Doc/list + +*请求方式:GET* + +认证方式:Cookie(SESSDSTA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | -------- | ------ | ------------------------------------------------------------ | +| category | str | 类型 | 必要 | all:全部<br/>illustration:插画<br/>comic:漫画<br/>draw:其他 | +| type | str | 排序方式 | 必要 | hot:最热<br/>new:最新 | +| page_num | num | 页码 | 非必要 | 默认为1 | +| page_size | num | 每页项数 | 非必要 | 默认为45 | + +**json回复:** + +见[获取画友首页列表](#获取画友首页列表)中的响应内容 + +**示例:** + +用按热度排序方式获取`全部`类型的画友列表 + +```shell +curl -G 'https://api.vc.bilibili.com/link_draw/v2/Doc/list' \ +--data-urlencode 'category=all' \ +--data-urlencode 'type=hot' \ +--data-urlencode 'page_num=1' \ +--data-urlencode 'page_size=5' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "message": "success", + "data": { + "total_count": 500, + "items": [ + { + "user": { + "uid": 1403138, + "head_url": "https://i0.hdslb.com/bfs/face/member/noface.jpg", + "name": "莉莎娜" + }, + "item": { + "doc_id": 99421434, + "poster_uid": 1403138, + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/5191163a4f1a2e567adda32f4dd6d4c024455d8d.png", + "img_width": 2286, + "img_height": 1760, + "img_size": 4147 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/74943ba725ee352d95e8356d9c7f823b329e51bf.png", + "img_width": 812, + "img_height": 1218, + "img_size": 885 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/c0b17e496963203fb966ea046bddcc0d26dee066.png", + "img_width": 812, + "img_height": 1218, + "img_size": 892 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/099327c21f789294c6e8f2e9de9a280bed80eea5.png", + "img_width": 812, + "img_height": 1216, + "img_size": 895 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/4ae0365073300541ab34b214499a7e4e79d6d205.png", + "img_width": 812, + "img_height": 1216, + "img_size": 875 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/5912fd5dc436580f3d5d59e089c4119da532635a.png", + "img_width": 812, + "img_height": 1218, + "img_size": 921 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/6e0ac1a10d1e55439cb8347df8948d263321cc42.png", + "img_width": 812, + "img_height": 1218, + "img_size": 971 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/fa4738bfda93079e9db0df0bdd67ecf316eba099.png", + "img_width": 812, + "img_height": 1218, + "img_size": 860 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/d841f61d1ffdcdd8ae0831307c6479f3b8a2c803.png", + "img_width": 812, + "img_height": 1216, + "img_size": 839 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/685b75cff31f98af4881e3c1af5f58703ef8780e.png", + "img_width": 812, + "img_height": 1216, + "img_size": 928 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/2deb81f4813843c628a0cfbd3fe033e3f70ddd95.png", + "img_width": 812, + "img_height": 1218, + "img_size": 932 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/d93d03bc4f17ef4bf684f8eb8b0f48ef4c52f204.png", + "img_width": 812, + "img_height": 1218, + "img_size": 875 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/06e00c35e198de27a69a00284fb99b1ca6b77ca0.png", + "img_width": 812, + "img_height": 1216, + "img_size": 991 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/f1c18fd5cc062623d0b7789fc20ee5938aa83c37.png", + "img_width": 846, + "img_height": 725, + "img_size": 877 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/7f937d022f34f72fd9c7dcf25122671b9d6c87b4.png", + "img_width": 847, + "img_height": 733, + "img_size": 896 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/5e693c5d3b995d5553357b2b2e270ccc68562f91.png", + "img_width": 848, + "img_height": 740, + "img_size": 967 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/e8f1574af6244f8f4df5876f2bce4a9b03b02021.png", + "img_width": 848, + "img_height": 741, + "img_size": 1181 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/ceca23740750a545b26c2b35b12d357e24b887af.png", + "img_width": 856, + "img_height": 748, + "img_size": 1246 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/98439a15f2a8fdaa16c20b18d436894f2a667969.png", + "img_width": 837, + "img_height": 745, + "img_size": 1248 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/cda219582d4bc824a0f3b276944bb440f94c3365.jpg", + "img_width": 550, + "img_height": 441, + "img_size": 53 + } + ], + "title": "ufotable 剧场版", + "category": "draw", + "upload_time": 1606386642, + "already_liked": 0, + "already_voted": 0 + } + }, + { + "user": { + "uid": 5030761, + "head_url": "https://i0.hdslb.com/bfs/face/2feef28d962b0e5c8bbd573cffe84d5e13277747.jpg", + "name": "深井玑" + }, + "item": { + "doc_id": 3674543, + "poster_uid": 5030761, + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/c52e9b3a1fa307095cac0e82f5932baba4f0a286.png", + "img_width": 6142, + "img_height": 4724, + "img_size": 5314 + } + ], + "title": "小02", + "category": "illustration", + "upload_time": 1524970836, + "already_liked": 0, + "already_voted": 0 + } + }, + { + "user": { + "uid": 401154, + "head_url": "https://i1.hdslb.com/bfs/face/4c57866c6c8f21ff2fc8577369a613ed8397fae8.jpg", + "name": "oO大黄Oo" + }, + "item": { + "doc_id": 979620, + "poster_uid": 401154, + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/vc/8f5342382b5c92a14cd37f93e887124813ba2163.jpg", + "img_width": 1920, + "img_height": 1051, + "img_size": 549 + } + ], + "title": "八云家的早晨", + "category": "illustration", + "upload_time": 1510916676, + "already_liked": 0, + "already_voted": 0 + } + }, + { + "user": { + "uid": 21833522, + "head_url": "https://i2.hdslb.com/bfs/face/9037fc1027d780083ecc2e818b512b69b9267e7c.jpg", + "name": "欧阳鹏杰-OY" + }, + "item": { + "doc_id": 663050, + "poster_uid": 21833522, + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/vc/7b20f041ad7c04bbaf8c54ba520be6fd4953583e.jpg", + "img_width": 770, + "img_height": 999, + "img_size": 798 + }, + { + "img_src": "https://i0.hdslb.com/bfs/vc/0710b08b54013b06249170e8adf08b41a41030aa.jpg", + "img_width": 1024, + "img_height": 1024, + "img_size": 475 + }, + { + "img_src": "https://i0.hdslb.com/bfs/vc/09f168697210ce4ff62df3f0f1284574795ea96b.png", + "img_width": 863, + "img_height": 1283, + "img_size": 1257 + } + ], + "title": "OY手绘:白玫瑰", + "category": "illustration", + "upload_time": 1507952704, + "already_liked": 0, + "already_voted": 0 + } + } + ] + } +} +``` + +</details> + +## 获取摄影列表 + +> https://api.vc.bilibili.com/link_draw/v2/Photo/list + +*请求方式:GET* + +认证方式:Cookie(SESSDSTA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | -------- | ------ | --------------------------- | +| category | str | 类型 | 必要 | cos:Cosplay<br/>sifu:私服 | +| type | str | 排序方式 | 必要 | hot:最热<br/>new:最新 | +| page_num | num | 页码 | 非必要 | 默认为1 | +| page_size | num | 每页项数 | 非必要 | 默认为45 | + +**json回复:** + +见[获取画友首页列表](#获取画友首页列表)中的响应内容 + +**示例:** + +用按热度排序方式获取`Cosplay`类型的摄影列表 + +```shell +curl -G 'https://api.vc.bilibili.com/link_draw/v2/Photo/list' \ +--data-urlencode 'category=cos' \ +--data-urlencode 'type=hot' \ +--data-urlencode 'page_num=1' \ +--data-urlencode 'page_size=5' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "message": "success", + "data": { + "total_count": 500, + "items": [ + { + "user": { + "uid": 639050, + "head_url": "http://i0.hdslb.com/bfs/face/cb5ea5f15e4503cc26598bd307faa2a5413f914f.jpg", + "name": "Mayuri阮陌" + }, + "item": { + "doc_id": 1207334, + "poster_uid": 639050, + "pictures": [ + { + "img_src": "http://i0.hdslb.com/bfs/album/323049c9389d31525ab301e22915a3343172216e.jpg", + "img_width": 969, + "img_height": 599, + "img_size": 210 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/3e2fb000f8865092f378a480ab454fea3aa09380.jpg", + "img_width": 1920, + "img_height": 2880, + "img_size": 1369 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/b3aa55a8529935692be9a2d9e0ccf65e9bae6d87.jpg", + "img_width": 1920, + "img_height": 2880, + "img_size": 520 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/90a1b083e7d1c876aa6a82cf6440d11e84d8b4c3.jpg", + "img_width": 1920, + "img_height": 2880, + "img_size": 1442 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/eb1af3d84f2238ca63717a5c7e10a23d55d577c7.jpg", + "img_width": 1920, + "img_height": 2880, + "img_size": 1155 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/69bae275fce8d85cc1822cd520675281fa8f89a9.jpg", + "img_width": 1920, + "img_height": 2880, + "img_size": 1606 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/fbb77786fd531d081ea2867ae93cc1231326da58.jpg", + "img_width": 1920, + "img_height": 2880, + "img_size": 1329 + } + ], + "title": "式雪鸟", + "category": "cos", + "upload_time": 1512360622, + "already_liked": 0, + "already_voted": 0 + } + }, + { + "user": { + "uid": 55183010, + "head_url": "http://i0.hdslb.com/bfs/face/9484cb85e2f3acc4fcc953deab4090424b5a5aa3.jpg", + "name": "HaneAme雨波" + }, + "item": { + "doc_id": 99103637, + "poster_uid": 55183010, + "pictures": [ + { + "img_src": "http://i0.hdslb.com/bfs/album/99cfb9601146d85622d0950b4689e2016e827ca6.jpg", + "img_width": 1366, + "img_height": 2048, + "img_size": 395 + } + ], + "title": "雨波 cos少女前线 OTS14 cos", + "category": "cos", + "upload_time": 1606070733, + "already_liked": 0, + "already_voted": 0 + } + }, + { + "user": { + "uid": 55183010, + "head_url": "http://i0.hdslb.com/bfs/face/9484cb85e2f3acc4fcc953deab4090424b5a5aa3.jpg", + "name": "HaneAme雨波" + }, + "item": { + "doc_id": 99103785, + "poster_uid": 55183010, + "pictures": [ + { + "img_src": "http://i0.hdslb.com/bfs/album/bfb54c1ef7b9891ab458f2171fb1c115b8c94147.jpg", + "img_width": 1366, + "img_height": 2048, + "img_size": 601 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/2e8fd0d327cabc6ff9aa3fdc7f21d12949cd3774.jpg", + "img_width": 1366, + "img_height": 2048, + "img_size": 383 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/82050a1badfd2cce0e3888b0de501da8d0052285.jpg", + "img_width": 2048, + "img_height": 1366, + "img_size": 445 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/25223cd3d5bb7e4e96bdf5dded8538e9737762c4.jpg", + "img_width": 1366, + "img_height": 2048, + "img_size": 497 + } + ], + "title": "雨波 cos 英雄联盟阿狸KDA cos", + "category": "cos", + "upload_time": 1606071173, + "already_liked": 0, + "already_voted": 0 + } + }, + { + "user": { + "uid": 12429622, + "head_url": "http://i2.hdslb.com/bfs/face/af7fd8dfba51c0735303a381e1d7115c6dd13ad5.jpg", + "name": "ayaco_" + }, + "item": { + "doc_id": 6029076, + "poster_uid": 12429622, + "pictures": [ + { + "img_src": "http://i0.hdslb.com/bfs/album/41bd20d921f8310243856665ee15c9f4a2dca89a.jpg", + "img_width": 1080, + "img_height": 720, + "img_size": 775 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/e6f7ea5b8f74d97239d307db43851341a802ee58.jpg", + "img_width": 591, + "img_height": 5672, + "img_size": 2714 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/af1795fb3873202f4668d0a598c36371f4b0addb.jpg", + "img_width": 591, + "img_height": 5641, + "img_size": 2305 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/15cf752ba3c3568828c5245cedd21d74b05b79cc.jpg", + "img_width": 591, + "img_height": 5602, + "img_size": 2158 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/6b19e916ad10e167503d1e002211cf84457f780b.jpg", + "img_width": 1080, + "img_height": 720, + "img_size": 571 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/a92b4286a1322c1315a18520af27759ee13bee69.jpg", + "img_width": 591, + "img_height": 887, + "img_size": 580 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/104001f3ea13753f5a74ca40f302c8bf82fd75ee.jpg", + "img_width": 591, + "img_height": 887, + "img_size": 479 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/6edb8fe0835c2ab284012889abe5306ed0122eb1.jpg", + "img_width": 1080, + "img_height": 720, + "img_size": 622 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/ef1be9ab93fae60f5425c2a5e6411bdb72a16bee.jpg", + "img_width": 591, + "img_height": 887, + "img_size": 389 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/7250c928a6458cd30face9403889c8bb9eda19ef.jpg", + "img_width": 1080, + "img_height": 635, + "img_size": 550 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/34439287647262eb80d6d4f16f38b4801f32c193.jpg", + "img_width": 591, + "img_height": 887, + "img_size": 472 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/253325d97fce756812a73eb609d8e082bf1eae12.jpg", + "img_width": 1080, + "img_height": 720, + "img_size": 576 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/00a05300453d0b14e44ba2051cc3714dabc46fd1.jpg", + "img_width": 1080, + "img_height": 720, + "img_size": 1047 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/1416e50ce1ab2e364212ebb2503cec247ca8642d.jpg", + "img_width": 1080, + "img_height": 720, + "img_size": 582 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/23661c4843e4c1d32aa7432683153be3813d771a.jpg", + "img_width": 591, + "img_height": 887, + "img_size": 372 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/161753dced7278876055e38114e3773106dbedf5.jpg", + "img_width": 4743, + "img_height": 3162, + "img_size": 1395 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/224ff973a91566b3dc364fde122e71520b56fdc6.jpg", + "img_width": 591, + "img_height": 887, + "img_size": 432 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/6495534c72147d512c79b4c2bbc06011635d4913.jpg", + "img_width": 591, + "img_height": 886, + "img_size": 453 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/0474e1479a0228cc6e97891f0f4d1cdbc1370222.jpg", + "img_width": 591, + "img_height": 887, + "img_size": 370 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/5a19599960129f2060c125e3896d20dccf5a6f25.jpg", + "img_width": 591, + "img_height": 887, + "img_size": 367 + } + ], + "title": "剑网3cos明教成女", + "category": "cos", + "upload_time": 1532692182, + "already_liked": 0, + "already_voted": 0 + } + }, + { + "user": { + "uid": 25000899, + "head_url": "http://i2.hdslb.com/bfs/face/4017d03cfe42da7a0c93277cb46fb5a47a9b2415.jpg", + "name": "狩子和光哥" + }, + "item": { + "doc_id": 13690635, + "poster_uid": 25000899, + "pictures": [ + { + "img_src": "http://i0.hdslb.com/bfs/album/5f497ae7b064c5e323ad1e008b0068d3fb95b3f0.jpg", + "img_width": 1908, + "img_height": 3332, + "img_size": 3852 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/96e6743d04b0d31e9c17e171d767ceab75c9ac35.jpg", + "img_width": 1908, + "img_height": 3392, + "img_size": 3444 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/2116c3fe1bb5fbfd77a641fd0c29c6e6408b050e.jpg", + "img_width": 1908, + "img_height": 3328, + "img_size": 3793 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/6de08b62d633a84e5e50c8da0b42334f88ca50cb.jpg", + "img_width": 1812, + "img_height": 3176, + "img_size": 3513 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/02f1e419e79e45572c671a534f4271f411f2771f.jpg", + "img_width": 1908, + "img_height": 3392, + "img_size": 3660 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/348bf5b4f887f3ecd690cb1a1442bdda43898652.jpg", + "img_width": 3814, + "img_height": 3392, + "img_size": 7891 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/c50a2cc182c8ad07850e2f364b76d14cd6b1729c.jpg", + "img_width": 3839, + "img_height": 2160, + "img_size": 1630 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/b051883ca18556c78e72bf07d3981324394541c8.jpg", + "img_width": 2437, + "img_height": 2159, + "img_size": 1869 + }, + { + "img_src": "http://i0.hdslb.com/bfs/album/42e5f13601067a772d5ddc47a8756fecfec9f8cb.jpg", + "img_width": 2121, + "img_height": 3023, + "img_size": 2021 + } + ], + "title": "玉藻前", + "category": "cos", + "upload_time": 1548154774, + "already_liked": 0, + "already_voted": 0 + } + } + ] + } +} +``` + +</details> + +## 获取指定用户的相簿列表 + +> https://api.vc.bilibili.com/link_draw/v1/doc/others + +*请求方式:GET* + +认证方式:Cookie(SESSDSTA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------- | ------ | --------------------------------------------- | +| biz | num | 分区 | 非必要 | 0:全部<br />1:画友<br/>2:摄影<br />默认为0 | +| poster_uid | num | 作者mid | 必要 | 默认为20 | +| page_num | num | 页码 | 非必要 | 默认为1 | +| page_size | num | 每页项数 | 非必要 | 默认为45 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------ | +| code | num | 返回值 | 0:成功<br />1:参数错误 | +| msg | str | 错误信息 | 默认为success | +| message | str | 错误信息 | 默认为success | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----- | ---------- | ---- | +| total_count | str | 总计相簿数 | | +| user | obj | 作者信息 | | +| items | array | 相簿列表 | | + +`data`中的`user`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------- | ---- | +| uid | str | 作者mid | | +| head_url | str | 头像url | | +| name | str | 昵称 | | + +`data`中的`item`对象: + +同[获取画友首页列表](#获取画友首页列表)中的`item`对象 + +**示例:** + +获取用户` 1360010 `的所有类型相簿 + +```shell +curl -G 'https://api.vc.bilibili.com/link_draw/v1/doc/others' \ +--data-urlencode 'biz=0' \ +--data-urlencode 'poster_uid=1360010' \ +--data-urlencode 'page_num=1' \ +--data-urlencode 'page_size=5' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "message": "success", + "data": { + "total_count": "290", + "user": { + "uid": "1360010", + "head_url": "https://i2.hdslb.com/bfs/face/865c7b03575a69822e503ef291ac26199c6a540a.jpg", + "name": "楚楚子" + }, + "items": [ + { + "biz": 3, + "doc_id": 85097979, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/65604d9697a644686c6ad811f9663a9fe308b164.jpg", + "img_width": 1347, + "img_height": 1792, + "img_size": 363 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/3f4448059ddaa8cbcd9094851ecfb84b184b0dc9.jpg", + "img_width": 1347, + "img_height": 1792, + "img_size": 506 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/edd1b6b424c078ba6a5b267db355cf7e8522f27a.jpg", + "img_width": 1347, + "img_height": 1792, + "img_size": 424 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/a615ce43ce3412060e487c3fcbc73ed08da23c56.jpg", + "img_width": 2268, + "img_height": 4032, + "img_size": 2192 + } + ], + "source": null, + "upload_time": "2020-08-03 16:48:30", + "upload_timestamp": 1596444510, + "upload_time_text": "3月前", + "description": "“绝望吧~!”\n#江之岛盾子#弹丸论破# \n黑历史重刷,终于又出了盾子 ​​​", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 53822, + "like_count": 0, + "collect_count": 40, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 84200785, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/8aa4ad3fc7b9f01a21f4c398565788bbe92cff2d.jpg", + "img_width": 2464, + "img_height": 3280, + "img_size": 2059 + } + ], + "source": null, + "upload_time": "2020-07-29 18:06:52", + "upload_timestamp": 1596017212, + "upload_time_text": "4月前", + "description": "莫西莫西?", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 49659, + "like_count": 0, + "collect_count": 6, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 83943309, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/4f4321bec1ddc55a3ed98b63a40175ec90820b4a.jpg", + "img_width": 2464, + "img_height": 3280, + "img_size": 2432 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/e2ed6aecfa713e109867198a1b0292eb9180aec9.jpg", + "img_width": 2464, + "img_height": 3280, + "img_size": 1949 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/92694ea7db527663a8c97a6747125e12c6300bc4.jpg", + "img_width": 2464, + "img_height": 3280, + "img_size": 1978 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/1757e958088dc7477fae30f2bf0daba034dd5de2.jpg", + "img_width": 2464, + "img_height": 3280, + "img_size": 1849 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/60d55f032f4332387a165d6aa4e7ab0d2f628b1d.jpg", + "img_width": 2464, + "img_height": 3280, + "img_size": 2032 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/12bdbda0c8ea40505449ef4f4ad764780ad991ec.jpg", + "img_width": 1623, + "img_height": 2160, + "img_size": 1068 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/4e51f06fb2c9aedfd077eb9341ada50aea5a2d50.jpg", + "img_width": 2464, + "img_height": 3280, + "img_size": 2106 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/5e8d27655c9741b0cb8c3e257677b9fc14b4cb5b.jpg", + "img_width": 2996, + "img_height": 3289, + "img_size": 3347 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/0018b04da7f9897b0a80dae64267fda16a7d3249.jpg", + "img_width": 700, + "img_height": 659, + "img_size": 122 + } + ], + "source": null, + "upload_time": "2020-07-28 02:18:39", + "upload_timestamp": 1595873919, + "upload_time_text": "4月前", + "description": "CP26第一天的集邮#CP26#\np1@流一_喵喵喵喵喵喵 流一爸爸太好看呜呜\np2@星之迟迟 我迟哥天仙下凡 新本太可了推荐\np3@紅吸式咖啡 师姐是俺永远的珍宝!\np4@伏笔小哥哥 我家儿子人间导弹杀伤力巨大[doge]\np5@鹤祈W 我家鹅鹅[喜极而泣]老色批又偷偷亲我\np6@拉花一哥虚年gg 虚虚今天也是又白又可口\np7@沐阳_阳阳阳阳羊哞 又御又有气场爱了\nP8战利品?", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "[{\"type\":1,\"location\":86,\"length\":7,\"data\":\"44500220\"}]", + "view_count": 67546, + "like_count": 0, + "collect_count": 18, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 83305352, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/9700a04ea0adc0fc4e0d0be54432210f7cb0ca08.jpg", + "img_width": 2996, + "img_height": 4096, + "img_size": 3687 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/bea5b177169027506afb7f11f91aecaf770f50a8.jpg", + "img_width": 2232, + "img_height": 4032, + "img_size": 2435 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/94c170c09acfc22bcdf541dc2a173cac0c3ca5eb.jpg", + "img_width": 1080, + "img_height": 1080, + "img_size": 349 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/53b082a3352a4cbf05dd796b60fe06ad5ba443f9.jpg", + "img_width": 2148, + "img_height": 2864, + "img_size": 1712 + } + ], + "source": null, + "upload_time": "2020-07-24 11:12:03", + "upload_timestamp": 1595560323, + "upload_time_text": "4月前", + "description": "cp26认衣服。?[笑哭]\nD1, 瑶-遇见神鹿(游场\nD2,嘉德罗斯-酒吞童子(凹凸世界展台8.1馆CPB25 ​​​", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 45415, + "like_count": 0, + "collect_count": 5, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 81307632, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/bf3e274cf5a013a9ae8ddfaa756ad4f22d643ff4.jpg", + "img_width": 2464, + "img_height": 3280, + "img_size": 2418 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/e8ad8f1297048e9adbcd70c8ca589dc306679c6e.jpg", + "img_width": 1656, + "img_height": 2205, + "img_size": 692 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/44e2d7d566833a67b151b5f0eba67bb70c34e6b7.jpg", + "img_width": 2464, + "img_height": 3280, + "img_size": 2430 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/0c11a891a71a567899b45801049cb44e8e09984b.jpg", + "img_width": 2464, + "img_height": 3280, + "img_size": 2513 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/92e0f0a0e6c38c693511b705acfd25caa9c14125.jpg", + "img_width": 1656, + "img_height": 2205, + "img_size": 664 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/235e63ecfa8db0bb21a4dbd4d82c7be321c96b73.jpg", + "img_width": 2464, + "img_height": 3280, + "img_size": 2149 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/98a3eb965f07a75b24d59cc6446a7752ad8211bd.jpg", + "img_width": 1656, + "img_height": 2205, + "img_size": 580 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/0dc3637addb53bf8ebea2a1896f41bcedafee42f.jpg", + "img_width": 1656, + "img_height": 2205, + "img_size": 669 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/f1ccbe4b61022cea2545eaa4cd26ac0617f9c12c.jpg", + "img_width": 2464, + "img_height": 3280, + "img_size": 3329 + } + ], + "source": null, + "upload_time": "2020-07-12 01:03:34", + "upload_timestamp": 1594487014, + "upload_time_text": "4月前", + "description": "绿茶公主切?听说你想和我一起喝奶茶\n新风格自拍⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄希望喜欢\n\n裙子和领结是我家 海盐气泡", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 80832, + "like_count": 0, + "collect_count": 110, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 80611117, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/4cb935b7f542891c42e5b90a8cd6a9cc3817fdad.jpg", + "img_width": 1728, + "img_height": 3072, + "img_size": 1136 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/d99cd3d16fb1353a4dd42e72f4a1b4dce786bdf7.jpg", + "img_width": 1728, + "img_height": 3072, + "img_size": 1429 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/4a5b947929a8a748a1cd8a165e07e39cf9efbac1.jpg", + "img_width": 1728, + "img_height": 3072, + "img_size": 1052 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/c9972c6681e22d50f03bc80337f09c5bca12ce83.jpg", + "img_width": 1728, + "img_height": 3072, + "img_size": 1324 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/57137ce057e0c8098b17ed7ef9dbd6230cc08f31.jpg", + "img_width": 1728, + "img_height": 3072, + "img_size": 1361 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/f6ef2ffe0de5e336e12be620a2460fb9226da2d7.jpg", + "img_width": 1728, + "img_height": 3072, + "img_size": 1261 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/75c9012a5447025f533539e7e0c91aa7d47436e1.jpg", + "img_width": 1728, + "img_height": 3072, + "img_size": 986 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/07088481611b53a35bffc797e00ab39361cac764.jpg", + "img_width": 1728, + "img_height": 3072, + "img_size": 1361 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/2126d4a1f5882d1bd37db64e5acb17b3ba70a454.jpg", + "img_width": 1728, + "img_height": 3072, + "img_size": 991 + } + ], + "source": null, + "upload_time": "2020-07-07 14:13:32", + "upload_timestamp": 1594102412, + "upload_time_text": "4月前", + "description": "出镜:楚楚子\n摄影@猫尾先生DK \n服装@诺琪旗舰店 \n后勤:鹤祈 伏笔\n#cosplay##cos##cos正片##初音未来##初音ミク##初音##Miku##初音miku# ​​​", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 72419, + "like_count": 0, + "collect_count": 93, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 80314152, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/8debaeafd8463f06132f46776d2e100d7fc7da62.jpg", + "img_width": 2160, + "img_height": 3840, + "img_size": 2793 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/c930d2b3b8533b28c18ebd69d7bb62027a96dc64.jpg", + "img_width": 3072, + "img_height": 4096, + "img_size": 3688, + "img_tags": [ + { + "tid": 0, + "orientation": 2, + "type": 2, + "text": "鹤祈w", + "mid": 319699970, + "textString": "@鹤祈w", + "x": 69531, + "y": 74547, + "source_type": 0, + "item_id": 0 + }, + { + "tid": 0, + "orientation": 2, + "type": 2, + "text": "楚楚子", + "mid": 1360010, + "textString": "@楚楚子", + "x": 24845, + "y": 88315, + "source_type": 0, + "item_id": 0 + } + ] + } + ], + "source": null, + "upload_time": "2020-07-05 15:30:19", + "upload_timestamp": 1593934219, + "upload_time_text": "4月前", + "description": "又出了拉姆蕾姆双子快乐!#蕾姆##拉姆##从零开始的异世界生活#", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 53346, + "like_count": 0, + "collect_count": 27, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 78948058, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/63d3158d33e4e7e74b04ad522841b746795a2c58.jpg", + "img_width": 1080, + "img_height": 1080, + "img_size": 321 + } + ], + "source": null, + "upload_time": "2020-06-25 12:47:54", + "upload_timestamp": 1593060474, + "upload_time_text": "5月前", + "description": "端午节安康哦!大家", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 56377, + "like_count": 0, + "collect_count": 19, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 78732068, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/bce1fbe78f222b669cd2ecf154faee55fffa4c22.jpg", + "img_width": 828, + "img_height": 1295, + "img_size": 431 + } + ], + "source": null, + "upload_time": "2020-06-23 20:06:14", + "upload_timestamp": 1592913974, + "upload_time_text": "5月前", + "description": "阿荣正片发我微博了(楚楚子w)\n还有转发抽500软妹币哦~[tv_调侃]", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 49872, + "like_count": 0, + "collect_count": 2, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 78601963, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/952125a9d23e9845c359752919d7a4919c5146b2.jpg", + "img_width": 2160, + "img_height": 3840, + "img_size": 2219 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/206a554bf8ca9f8f5b20f819a3a3d4caaf8cc7c8.jpg", + "img_width": 2160, + "img_height": 3840, + "img_size": 2093 + } + ], + "source": null, + "upload_time": "2020-06-22 17:17:02", + "upload_timestamp": 1592817422, + "upload_time_text": "5月前", + "description": "“拉菲…喜欢指挥官”\n#碧蓝航线#", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 47885, + "like_count": 0, + "collect_count": 6, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 77719612, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/8c78cfc991f160e649530ef124958a40174d1edf.jpg", + "img_width": 2464, + "img_height": 3280, + "img_size": 2902 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/e7e5d9fd004461ccc06bd4a2070fe8984cc910ab.jpg", + "img_width": 1906, + "img_height": 1080, + "img_size": 182 + } + ], + "source": null, + "upload_time": "2020-06-15 11:59:27", + "upload_timestamp": 1592193567, + "upload_time_text": "5月前", + "description": "#转生成为了只有乙女游戏破灭FLAG的邪恶##转生恶役只好拔除破灭旗标##卡塔丽娜##COS#\n猴王来了(不是)", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 52101, + "like_count": 0, + "collect_count": 5, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 77344908, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/a7d74d4ee9fc7b000ce325f56d7f20c2f46097ce.jpg", + "img_width": 614, + "img_height": 584, + "img_size": 35 + } + ], + "source": null, + "upload_time": "2020-06-12 17:58:43", + "upload_timestamp": 1591955923, + "upload_time_text": "5月前", + "description": "都和你们说了多少次了我没有男朋友,我有女朋友!!!!别问了[笑哭]giao", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 48760, + "like_count": 0, + "collect_count": 0, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 77340591, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/d53eae5957290841e99182b57dec41b73536c31f.jpg", + "img_width": 1440, + "img_height": 1080, + "img_size": 247 + } + ], + "source": null, + "upload_time": "2020-06-12 17:20:47", + "upload_timestamp": 1591953647, + "upload_time_text": "5月前", + "description": "昨天的自拍[tv_斜眼笑][tv_doge]", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 43730, + "like_count": 0, + "collect_count": 1, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 77255303, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/0ec917d17f79e7dbd07e60c4eba78add95f8db1e.jpg", + "img_width": 1080, + "img_height": 1619, + "img_size": 292 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/d3509348d52329d415a0022a1d79651645201dfc.jpg", + "img_width": 1080, + "img_height": 1620, + "img_size": 531 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/6e2b6f49b6c8650ade51e66c4dc6008a4fd10b9e.jpg", + "img_width": 1619, + "img_height": 1080, + "img_size": 235 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/c31455b0d11a982f09fdcd13ce24354743410a95.jpg", + "img_width": 1080, + "img_height": 1619, + "img_size": 353 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/d6bcaf3c8cdcd5d680e359f20b7514e39337ed0c.jpg", + "img_width": 1619, + "img_height": 1080, + "img_size": 253 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/4151fe1cf8f4a47c3843f12ae10eb8449660d80f.jpg", + "img_width": 1080, + "img_height": 1619, + "img_size": 413 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/29e2f6361e0773342b9f8adae7c44515231415da.jpg", + "img_width": 1619, + "img_height": 1080, + "img_size": 337 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/88b42ea572b95ba2d0bbdec0253f3cf5f87bf1e9.jpg", + "img_width": 1080, + "img_height": 1619, + "img_size": 459 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/4f96eea84478eaeccf80b5e34b263e6d7e04e382.jpg", + "img_width": 1619, + "img_height": 1080, + "img_size": 325 + } + ], + "source": null, + "upload_time": "2020-06-11 21:10:12", + "upload_timestamp": 1591881012, + "upload_time_text": "5月前", + "description": "#LOLITA##国牌LOLITA##LOLITA装扮#\n 🌹雾都小姐🍷酒红色🍷\n\n出镜:楚楚子\n裙子:@Neverland星芙颂 \n\n摄影感谢@夜_綰灵 ​​​", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 48652, + "like_count": 0, + "collect_count": 20, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 76904631, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/d89d1ae4dbb98c7b4ab40d3cb76543b4d5b9d471.jpg", + "img_width": 3987, + "img_height": 4032, + "img_size": 2898 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/8292a3ffe10baaf3b957605bc9fa450848746598.jpg", + "img_width": 3987, + "img_height": 4032, + "img_size": 3059 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/e6992efada737c6340b400ad8541ec8f550cd490.jpg", + "img_width": 4016, + "img_height": 4000, + "img_size": 2628 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/b4af594407dc4115779aa82d30000005f1940cee.jpg", + "img_width": 4000, + "img_height": 4012, + "img_size": 2602 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/6bc9ed0a4456806972793c8c9ff6b6dab7d82492.jpg", + "img_width": 828, + "img_height": 831, + "img_size": 156 + } + ], + "source": null, + "upload_time": "2020-06-08 17:19:55", + "upload_timestamp": 1591607995, + "upload_time_text": "5月前", + "description": "做了粉丝向小周边是蕾姆cos的扑克牌\n可以拿去打扑克[tv_点赞]搜店铺【楚王的宝库】就看到了,54张➕铁盒包装➕包邮 ​​​", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 40875, + "like_count": 0, + "collect_count": 1, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 76895569, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/0f35f75e31dd1298673207292f06ed73c44ab7d6.jpg", + "img_width": 1080, + "img_height": 1620, + "img_size": 290 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/487f3ba4891b52825965337cc67b386cd61ef2ae.jpg", + "img_width": 1080, + "img_height": 1620, + "img_size": 403 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/01e0a911f6efab97191def3d3fab36d656f395a4.jpg", + "img_width": 1080, + "img_height": 1620, + "img_size": 306 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/62903ff9bad9d8f67fa44d0ec745f041f7c48e69.jpg", + "img_width": 1620, + "img_height": 1080, + "img_size": 230 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/f4ff78679627139c8f0bad222cd4a148cfc48212.jpg", + "img_width": 1080, + "img_height": 1620, + "img_size": 277 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/8444278d213ee9a88ee4e0672999625b9fe08ac3.jpg", + "img_width": 1080, + "img_height": 1620, + "img_size": 244 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/b726178928cd90091dbb424a1d67e65509b27415.jpg", + "img_width": 1080, + "img_height": 1512, + "img_size": 322 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/736c90c02dafb3bf846936220084505a0da2ff55.jpg", + "img_width": 1620, + "img_height": 1080, + "img_size": 394 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/3fe89476c5f6572e7c42f10af219adf8cb80fa5b.jpg", + "img_width": 1620, + "img_height": 1080, + "img_size": 370 + } + ], + "source": null, + "upload_time": "2020-06-08 15:41:20", + "upload_timestamp": 1591602080, + "upload_time_text": "5月前", + "description": "死亡爱丽丝联动蕾姆\n\n蕾姆:楚楚子\n服装@悠悠cos微博 \n摄影@菜菜1911 \n\n#从零开始的异世界生活##蕾姆##COSPLAY#", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "[{\"type\":1,\"location\":32,\"length\":8,\"data\":\"92962087\"}]", + "view_count": 62523, + "like_count": 0, + "collect_count": 74, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 76277041, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/04b5e6ca741e16504e32a8afcaff02d26e3dbb02.jpg", + "img_width": 2105, + "img_height": 2105, + "img_size": 756 + } + ], + "source": null, + "upload_time": "2020-06-03 20:58:17", + "upload_timestamp": 1591189097, + "upload_time_text": "5月前", + "description": "听说最近虚拟女友很火?我也想应聘一下(๑¯ω¯๑)\n你们喜欢哪种声音的呢?\n定制虚拟恋人的方式在评论区\n顺便我在评论区抓一个粉丝做一期体验视频\n记得关注我和【甜味陪伴】哦[tv_害羞]", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 53645, + "like_count": 0, + "collect_count": 4, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 74762578, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/6d9c4a1c5a313880c9917b7a37810d37d06df056.png", + "img_width": 1792, + "img_height": 828, + "img_size": 4752 + }, + { + "img_src": "https://i0.hdslb.com/bfs/album/9a5e21c9e620fd58f4ffa0f23c6758c6be004c16.png", + "img_width": 1792, + "img_height": 828, + "img_size": 5322 + } + ], + "source": null, + "upload_time": "2020-05-23 10:33:32", + "upload_timestamp": 1590201212, + "upload_time_text": "6月前", + "description": "我冲了!#碧蓝航线#", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 71068, + "like_count": 0, + "collect_count": 1, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 74397184, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/de4711846523f58a1e17da281a3033b40296e5c6.jpg", + "img_width": 5304, + "img_height": 7952, + "img_size": 16275 + } + ], + "source": null, + "upload_time": "2020-05-20 13:34:51", + "upload_timestamp": 1589952891, + "upload_time_text": "6月前", + "description": "是金发辣妹风格的jk\n520表白大家\n裙子是我家的万佳灯火@风間original \n感谢摄影:远野咲夜", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 74593, + "like_count": 0, + "collect_count": 12, + "verify_status": 1 + }, + { + "biz": 3, + "doc_id": 74246310, + "poster_uid": 1360010, + "category": "daily", + "type": 0, + "title": "", + "tags": [], + "pictures": [ + { + "img_src": "https://i0.hdslb.com/bfs/album/e4541718610d4f19c9228bebf580db4f96e7a911.png", + "img_width": 1792, + "img_height": 828, + "img_size": 3884 + } + ], + "source": null, + "upload_time": "2020-05-19 10:06:53", + "upload_timestamp": 1589854013, + "upload_time_text": "6月前", + "description": "上古老婆队我也有了[tv_微笑]开心", + "role": null, + "settings": { + "copy_forbidden": 0 + }, + "already_collected": 0, + "already_liked": 0, + "user_status": 0, + "at_control": "", + "view_count": 48537, + "like_count": 0, + "collect_count": 0, + "verify_status": 1 + } + ] + } +} +``` + +</details> +</details> diff --git a/bb-api-collect/docs/album/recommend_author.md b/bb-api-collect/docs/album/recommend_author.md new file mode 100644 index 0000000000..ba57f07c57 --- /dev/null +++ b/bb-api-collect/docs/album/recommend_author.md @@ -0,0 +1,169 @@ +# 相簿推荐作者 + +<details> +<summary>功能已下线</summary> + +## 获取摄影推荐作者 + +> https://api.vc.bilibili.com/link_draw/v2/Photo/uper + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ------- | +| num | num | 请求数量 | 非必要 | 默认为6 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | ------------- | +| code | num | 返回值 | 0:成功 | +| msg | str | 错误信息 | 默认为success | +| message | str | 错误信息 | 默认为success | +| data | array | 信息本体 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------- | ---- | +| 0 | obj | 作者 1 | | +| n | obj | 作者 (n+1) | | +| …… | obj | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ------- | ------------ | +| uid | num | 作者mid | | +| head_url | str | 头像url | | +| name | str | 昵称 | | +| is_followed | num | 0 | 作用尚不明确 | + +**示例:** + +请求获取摄影推荐作者,数量为5 + +```shell +curl -G 'https://api.vc.bilibili.com/link_draw/v2/Photo/uper' \ +--data-urlencode 'num=5' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "message": "success", + "data": [ + { + "uid": 36974706, + "head_url": "https://i2.hdslb.com/bfs/face/fa7ef3a5124e2ebfd2094e0bc2f42c752c1abd21.jpg", + "name": "幹物小幺", + "is_followed": 0 + }, + { + "uid": 3223860, + "head_url": "https://i0.hdslb.com/bfs/face/c5400d25eb7700cd41d88dff5b800bd55ec27cfe.jpg", + "name": "您算哪根葱", + "is_followed": 0 + }, + { + "uid": 941228, + "head_url": "https://i2.hdslb.com/bfs/face/f38f000d4df21e9bea96d3573efdf81ae02f4ddf.jpg", + "name": "碳酸熊卡", + "is_followed": 0 + }, + { + "uid": 2624541, + "head_url": "https://i0.hdslb.com/bfs/face/86ccd746af8b1e8bfcdd432de7f0ce1e2b2cb8b0.jpg", + "name": "_一之濑光", + "is_followed": 0 + }, + { + "uid": 29963706, + "head_url": "https://i1.hdslb.com/bfs/face/c054f097f1b882fc6ad8a67d0f0f88e3acd3bc88.jpg", + "name": "公子温温温如", + "is_followed": 0 + } + ] +} +``` + +</details> + +## 获取画友推荐作者 + +> https://api.vc.bilibili.com/link_draw/v2/Doc/drawer + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ------- | +| num | num | 请求数量 | 非必要 | 默认为6 | + +**json回复:** + +见[获取摄影推荐作者](#获取摄影推荐作者)中的响应内容 + +**示例:** + +请求获取画友推荐作者,数量为5 + +```shell +curl -G 'https://api.vc.bilibili.com/link_draw/v2/Doc/drawer' \ +--data-urlencode 'num=5' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "message": "success", + "data": [ + { + "uid": 7905675, + "head_url": "http://i1.hdslb.com/bfs/face/d4765fd020e8b96e331861cb4d6a3afde4e70d1d.jpg", + "name": "我真的是离城", + "is_followed": 0 + }, + { + "uid": 20356494, + "head_url": "http://i0.hdslb.com/bfs/face/0686141506894df969832d7dda91f2a0c4cdc24b.jpg", + "name": "ZM-PANDA", + "is_followed": 0 + }, + { + "uid": 4836885, + "head_url": "http://i1.hdslb.com/bfs/face/48822c5aa7aeae9d3dd2010388baa2b0e1c5cc0a.jpg", + "name": "六六子w", + "is_followed": 0 + }, + { + "uid": 2575079, + "head_url": "http://i1.hdslb.com/bfs/face/cb3d6f4fb2fbe5aa85ab8773a1a19cec6d8ff1e1.jpg", + "name": "念萦墨葵", + "is_followed": 0 + }, + { + "uid": 1904878, + "head_url": "http://i0.hdslb.com/bfs/face/f6de926b3905ec7bb9e36202d80eb931d12f70ac.jpg", + "name": "fedsnk", + "is_followed": 0 + } + ] +} +``` + +</details> +</details> diff --git a/bb-api-collect/docs/article/action.md b/bb-api-collect/docs/article/action.md new file mode 100644 index 0000000000..c195594f8b --- /dev/null +++ b/bb-api-collect/docs/article/action.md @@ -0,0 +1,172 @@ +# 专栏点赞&投币&收藏 + +## 点赞文章 + +<img src="../../assets/img/like.svg" width="100" height="100"/> + +> https://api.bilibili.com/x/article/like + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------- | ------ | ---------------------- | +| id | num | 文章cvid | 必要 | | +| type | num | 操作方式 | 必要 | 1:点赞<br />2:取消赞 | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功 <br />-101:账号未登录<br />-111:csrf校验失败<br />-400:请求错误<br />10003:不存在该稿件<br />65006:已赞过<br />65004:取消点赞失败 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +为文章`cv5806746`点赞 + +```shell +curl 'https://api.bilibili.com/x/article/like' \ +--data-urlencode 'id=5806746' \ +--data-urlencode 'type=1' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +## 投币文章 + +<img src="../../assets/img/coin.svg" width="100" height="100"/> + +> https://api.bilibili.com/x/web-interface/coin/add + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------------- | ------ | ------- | +| aid | num | 文章cvid | 必要 | | +| upid | num | 文章作者mid | 必要 | | +| multiply | num | 投币数量 | 必要 | 上限为2 | +| avtype | num | 2 | 必要 | 必须为2 | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-102:账号被封停<br />-104:硬币不足<br />-111:csrf校验失败<br />-400:请求错误<br />10003:不存在该稿件<br />34002:不能给自己投币<br />34003:非法的投币数量<br />34005:超过投币上限 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +data 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------ | ----------------------------------------------------- | +| like | bool | 是否点赞成功 | true:成功<br />false:失败<br />已赞过则附加点赞失败 | + +**示例:** + +为文章`cv5806746`投币1枚 + +```shell +curl 'https://api.bilibili.com/x/web-interface/coin/add' \ +--data-urlencode 'aid=5806746' \ +--data-urlencode 'upid=486980924' \ +--data-urlencode 'multiply=1' \ +--data-urlencode 'avtype=2' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "like": false + } +} +``` + +</details> + +## 收藏文章 + +<img src="../../assets/img/fav.svg" width="100" height="100"/> + +>https://api.bilibili.com/x/article/favorites/add + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------- | ------ | ---- | +| id | num | 文章cvid | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf校验失败<br />-400:请求错误<br />-404:无此项 | +| message | str | 错误信息 | 正确为success | +| data | obj | 信息本体 | | + +**示例:** + +收藏文章`cv5806746` + +```shell +curl 'https://api.bilibili.com/x/article/favorites/add' \ +--data-urlencode 'id=5806746' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> diff --git a/bb-api-collect/docs/article/articles.md b/bb-api-collect/docs/article/articles.md new file mode 100644 index 0000000000..0890ca946f --- /dev/null +++ b/bb-api-collect/docs/article/articles.md @@ -0,0 +1,311 @@ +# 文集基本信息 + +## 获取文集基本信息 + +> https://api.bilibili.com/x/article/list/web/articles + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| id | num | 文集rlid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-404:无此信息 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | ---------------- | ------------------------------------------------------------ | +| list | obj | 文集概览 | | +| articles | array | 文集内的文章列表 | | +| author | obj | 文集作者信息 | | +| last | obj | - | 作用尚不明确<br />结构与data.articles[]中相似 | +| attention | bool | 是否关注文集作者 | false:未关注<br />true:已关注<br />需要登录(Cookie) <br />未登录为false | + +`data`中的`list`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | --------------- | ------------ | +| id | num | 文集rlid | | +| mid | num | 文集作者mid | | +| name | str | 文集名称 | | +| image_url | str | 文集封面图片url | | +| update_time | num | 文集更新时间 | 时间戳 | +| ctime | num | 文集创建时间 | 时间戳 | +| publish_time | num | 文集发布时间 | 时间戳 | +| summary | str | 文集简介 | | +| words | num | 文集字数 | | +| read | num | 文集阅读量 | | +| articles_count | num | 文集内文章数量 | | +| state | num | 1或3 | 作用尚不明确 | +| reason | str | 空 | 作用尚不明确 | +| apply_time | str | 空 | 作用尚不明确 | +| check_time | str | 空 | 作用尚不明确 | + +`data`中的`articles`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------------- | ---- | +| 0 | obj | 文集中第1篇文章 | | +| n | obj | 文集中第(n+1)篇文章 | | + +`data`中的`articles`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ----- | -------------- | ------------------------------------------------------------ | +| id | num | 专栏cvid | | +| title | str | 文章标题 | | +| state | num | 0 | 作用尚不明确 | +| publish_time | num | 发布时间 | 秒时间戳 | +| words | num | 文章字数 | | +| image_urls | array | 文章封面 | | +| category | obj | 文章标签 | | +| categories | array | 文章标签列表 | | +| summary | str | 文章摘要 | | +| stats | obj | 文章状态数信息 | | +| like_state | num | 是否点赞 | 0:未点赞<br />1:已点赞<br />需要登录(Cookie) <br />未登录为0 | + +`articles`数组中的对象中的`stats`: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ---------- | ---- | +| view | num | 阅读数 | | +| favorite | num | 收藏数 | | +| like | num | 点赞数 | | +| dislike | num | 点踩数 | | +| reply | num | 评论数 | | +| share | num | 分享数 | | +| coin | num | 投币数 | | +| dynamic | num | 动态转发数 | | + +`articles`数组中的对象中的`author`: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | -------------- | ---- | +| mid | num | 作者mid | | +| name | str | 作者昵称 | | +| face | str | 作者头像url | | +| official_verify | obj | 作者认证信息 | | +| nameplate | obj | 作者勋章 | | +| vip | obj | 作者大会员状态 | | + +**示例:** + +查询文集`rl207146`的基本信息 + +```shell +curl -G 'https://api.bilibili.com/x/article/list/web/articles' \ +--data-urlencode 'id=207146' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": { + "id": 207146, + "mid": 293793435, + "name": "B站api研究笔记", + "image_url": "https://i0.hdslb.com/bfs/article/96d2b3d2a72e6497a011c885ab9245c51507ce18.png", + "update_time": 1585036952, + "ctime": 1582718126, + "publish_time": 1585045493, + "summary": "", + "words": 8697, + "read": 1654, + "articles_count": 3, + "state": 1, + "reason": "", + "apply_time": "", + "check_time": "" + }, + "articles": [ + { + "id": 4815593, + "title": "【B站API】api研究笔记ep1-视频基本信息", + "state": 0, + "publish_time": 1582643908, + "words": 2906, + "image_urls": [ + "https://i0.hdslb.com/bfs/article/00497c8df7130f22e5b953694b8931a22d32f133.jpg" + ], + "category": { + "id": 26, + "parent_id": 17, + "name": "数码" + }, + "categories": [ + { + "id": 17, + "parent_id": 0, + "name": "科技" + }, + { + "id": 26, + "parent_id": 17, + "name": "数码" + } + ], + "summary": "各位小可爱们大家好啊,终于可以结束我长达一年的咕咕了.........在这蝠想联翩的日子里也闲的没事,除了上课就是睡觉,还不如搞点事情哪个猿不想拥有自己的B站爬虫呢(误),当然自制一个B站的综合信息台也是可以的,比如显示粉丝数 获赞数(掉粉警告)于是就萌生了这个研究B站api的想法,以后也会继续不定期分享我的主体思路是利用Chrome中的F12工具进行分析,再用curl进行验证先从视频下手吧qwq我们以av2075941为例network检测下,有各种图片、视频、网页、js。。。。。的传输记录", + "stats": { + "view": 578, + "favorite": 19, + "like": 26, + "dislike": 0, + "reply": 19, + "share": 6, + "coin": 10, + "dynamic": 0 + }, + "like_state": 0 + }, + { + "id": 4820548, + "title": "【B站API】api研究笔记ep2-视频其他信息", + "state": 0, + "publish_time": 1582688189, + "words": 4319, + "image_urls": [ + "https://i0.hdslb.com/bfs/article/2416ee72759a5c2c8bba0f10d42e789fc0c0ae2b.jpg" + ], + "category": { + "id": 26, + "parent_id": 17, + "name": "数码" + }, + "categories": [ + { + "id": 17, + "parent_id": 0, + "name": "科技" + }, + { + "id": 26, + "parent_id": 17, + "name": "数码" + } + ], + "summary": "大家中午好鸭昨天我们研究了B站api的获取方法和使用方法 这一期我们继续分享另一个从网页中寻找api的方法以及研究视频的其他api接口以av170001为例首先打开视频,在F12的network下的监控中加载页面筛选XHR对象用搜索法的效率较低,不如我们直接进行筛选&观察通过对资源路径的观察可以猜到某些有关的项比如playurl有可能是播放的地址,pagelist可能是分P列表,view不就是昨天研究的『视频基本信息』吗通过继续分析我总结出了以下api这个可以在只想获取简介时应用,而不用处理多余", + "stats": { + "view": 737, + "favorite": 14, + "like": 18, + "dislike": 0, + "reply": 14, + "share": 1, + "coin": 1, + "dynamic": 0 + }, + "like_state": 0 + }, + { + "id": 5263184, + "title": "【B站API】api研究笔记Special-AV与BV互转", + "state": 0, + "publish_time": 1585045493, + "words": 1472, + "image_urls": [ + "https://i0.hdslb.com/bfs/article/b520939046899303cfcac1511308eb87ede760d7.jpg" + ], + "category": { + "id": 26, + "parent_id": 17, + "name": "数码" + }, + "categories": [ + { + "id": 17, + "parent_id": 0, + "name": "科技" + }, + { + "id": 26, + "parent_id": 17, + "name": "数码" + } + ], + "summary": "昨天视频新编号BV上线了,所有视频的编号默认都变成了BVxxx,不再是avxxx,兼容在链接和搜索中输入av号,评论区和动态av和bv都可以一键传送显然日益增长的投稿量对于编号是个问题,int是有上限的,但一串“乱码”缺少了灵魂,还会让我们想到磁力链接或者熊掌盘的链接(手动狗头)看到av170001,我会想到“法克儿~~”,但看到BV17x411w7KC,我?????其实av号并没有消失,只不过它已经隐藏于大众的视野里了,av和bv本质上是可以双向转换的方法一(电脑版推荐):打开一个视频,会发现", + "stats": { + "view": 343, + "favorite": 9, + "like": 13, + "dislike": 0, + "reply": 9, + "share": 0, + "coin": 2, + "dynamic": 0 + }, + "like_state": 0 + } + ], + "author": { + "mid": 293793435, + "name": "社会易姐QwQ", + "face": "http://i1.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg", + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0 + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "nameplate": { + "nid": 4, + "name": "青铜殿堂", + "image": "http://i1.hdslb.com/bfs/face/2879cd5fb8518f7c6da75887994c1b2a7fe670bd.png", + "image_small": "http://i1.hdslb.com/bfs/face/6707c120e00a3445933308fd9b7bd9fad99e9ec4.png", + "level": "普通勋章", + "condition": "单个自制视频总播放数>=1万" + }, + "vip": { + "type": 2, + "status": 1, + "due_date": 0, + "vip_pay_type": 0, + "theme_type": 0, + "label": null + } + }, + "last": { + "id": 0, + "title": "", + "state": 0, + "publish_time": 0, + "words": 0, + "image_urls": [ ], + "category": { + "id": 0, + "parent_id": 0, + "name": "" + }, + "categories": [ ], + "summary": "" + }, + "attention": true + } +} +``` + +</details> \ No newline at end of file diff --git a/bb-api-collect/docs/article/card.md b/bb-api-collect/docs/article/card.md new file mode 100644 index 0000000000..a21a25f78d --- /dev/null +++ b/bb-api-collect/docs/article/card.md @@ -0,0 +1,463 @@ +# 卡片信息 + +## 获取专栏显示卡片信息 + +> https://api.bilibili.com/x/article/cards + +*请求方法: GET* + +鉴权方式: 请求头 `Referer` 在 `.bilibili.com` 下 + +**URL 参数:** + +| 参数 | 类型 | 内容 | 必要性 | 备注 | +| ----- | ------ | ---- | ------ | ---- | +| ids | string | 被查询的 id 列表 | 不必要 | 以 `,` 分隔, 可填视频完整 AV/BV 号, 专栏 CV 号, 直播间长短 lv 号 (可能会合并同类项) | +| web_location | string | `333.1305` | 不必要 | | +| w_rid | string | WBI 签名 | 不必要 | 参见 [WBI 签名](../misc/sign/wbi.md) | +| wts | number | UNIX 秒级时间戳 | 不必要 | 参见 [WBI 签名](../misc/sign/wbi.md) | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | number | 返回值 | 0: 成功 | +| data | object | 数据本体 | | +| message | string | 错误信息 | 成功时为 `0` | +| ttl | number | `1` | | + +`data` 对象: + +以请求时 `ids` 字段中每一项为键, 其内容对象为值的表, 注意可能会合并同类项 + +`data` 中代表视频的对象 (`avxxx` 或 `Bvxxxxxxxxxx`): + +详细可参见 [视频基本信息] (../video/info.md) + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| aid | number | | | +| bvid | string | | | +| cid | number | | | +| copyright | number | | | +| cover43 | string | | | +| ctime | number | | | +| desc | string | | | +| dimension | object | | | +| duration | number | | | +| dynamic | string | | | +| owner | object | | | +| pic | string | | | +| pubdate | number | | | +| rights | object | | | +| short_link_v2 | string | | | +| stat | object | | | +| state | number | | | +| tid | number | | | +| title | string | | | +| tname | string | | | +| videos | number | | | +| vt_switch | boolean | | | + +`data` 中代表专栏的对象 (`cvxxx`): + +详细可参见 [专栏内容](view.md) + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| act_id | number | | | +| apply_time | string | | | +| attributes | number | | | +| authenMark | null | | | +| author | object | | | +| banner_url | string | | | +| categories | object[] | | | +| category | object | | | +| check_state | number | | | +| check_time | string | | | +| content_pic_list | null | | | +| cover_avid | number | | | +| ctime | number | | | +| dispute | null | | | +| dynamic | string | | | +| id | number | | | +| image_urls | string[] | | | +| is_like | boolean | | | +| list | object | | | +| media | object | | | +| mtime | number | | | +| origin_image_urls | string[] | | | +| origin_template_id | number | | | +| original | number | | | +| private_pub | number | | | +| publish_time | number | | | +| reprint | number | | | +| state | number | | | +| stats | object | | | +| summary | string | | | +| template_id | number | | | +| title | string | | | +| top_video_info | null | | | +| type | number | | | +| words | number | | | + +`data` 中代表直播间的对象: + +详细可参见 [直播间基本信息](../live/info.md) + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| area_v2_name | string | 分区完整名称 | | +| cover | string | 直播封面 | | +| face | string | 主播头像 | | +| live_status | number | 直播状态 | | +| online | number | 在线人数 | | +| pendent_ru | string | | | +| pendent_ru_color | string | | | +| pendent_ru_pic | string | | | +| role | number | | | +| room_id | number | 直播间长 id | | +| title | string | 直播间标题 | | +| uid | number | 主播 UID (mid) | | +| uname | string | 主播用户名 | | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/article/cards?ids=av2,cv1,cv2,15111509,lv1,lv5440' \ + --referer 'https://www.bilibili.com/' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "av2": { + "aid": 2, + "bvid": "BV1xx411c7mD", + "cid": 62131, + "copyright": 2, + "cover43": "", + "ctime": 1497344798, + "desc": "www", + "dimension": { + "height": 360, + "rotate": 0, + "width": 480 + }, + "duration": 2055, + "dynamic": "", + "owner": { + "face": "https://i2.hdslb.com/bfs/face/ef0457addb24141e15dfac6fbf45293ccf1e32ab.jpg", + "mid": 2, + "name": "碧诗" + }, + "pic": "http://static.hdslb.com/images/transparent.gif", + "pubdate": 1252458549, + "rights": { + "arc_pay": 0, + "autoplay": 1, + "bp": 0, + "download": 0, + "elec": 0, + "hd5": 0, + "is_cooperation": 0, + "movie": 0, + "no_background": 0, + "no_reprint": 0, + "pay": 0, + "pay_free_watch": 0, + "ugc_pay": 0, + "ugc_pay_preview": 0 + }, + "short_link_v2": "https://b23.tv/BV1xx411c7mD", + "stat": { + "aid": 2, + "coin": 38042, + "danmaku": 121342, + "dislike": 0, + "favorite": 107375, + "his_rank": 0, + "like": 261036, + "now_rank": 0, + "reply": 86021, + "share": 20052, + "view": 4983587, + "vt": 0, + "vv": 0 + }, + "state": 0, + "tid": 130, + "title": "字幕君交流场所", + "tname": "音乐综合", + "videos": 1, + "vt_switch": false + }, + "cv1": { + "act_id": 0, + "apply_time": "", + "attributes": 24, + "authenMark": null, + "author": { + "face": "https://i1.hdslb.com/bfs/face/89fe260a17891fdadc3365a9698fee52796c7765.jpg", + "fans": 0, + "level": 0, + "mid": 91221505, + "name": "健行见远渐忘", + "nameplate": { + "condition": "2018.6.26-7.8某一天是年度大会员", + "image": "https://i2.hdslb.com/bfs/face/421179426c929dfeaed4117461c83f5d07ffb148.png", + "image_small": "https://i1.hdslb.com/bfs/face/682001c2e1c2ae887bdf2a0e18eef61180c48f84.png", + "level": "稀有勋章", + "name": "大会员2018年度勋章", + "nid": 74 + }, + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i1.hdslb.com/bfs/face/7ae15f06f8c912435206a2578509d6bc77c12353.png", + "name": "作文鬼才", + "pid": 255 + }, + "vip": { + "avatar_subscript": 1, + "due_date": 0, + "label": { + "label_theme": "annual_vip", + "path": "http://i0.hdslb.com/bfs/vip/label_annual.png", + "text": "年度大会员" + }, + "nickname_color": "#FB7299", + "status": 1, + "theme_type": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "banner_url": "https://i0.hdslb.com/bfs/article/b1e1029c08d8ad1bb06460d736839a7741dd7925.jpg", + "categories": [ + { + "id": 3, + "name": "生活", + "parent_id": 0 + }, + { + "id": 15, + "name": "日常", + "parent_id": 3 + } + ], + "category": { + "id": 15, + "name": "日常", + "parent_id": 3 + }, + "check_state": 0, + "check_time": "", + "content_pic_list": null, + "cover_avid": 0, + "ctime": 1497973729, + "dispute": null, + "dynamic": "It's now or never !", + "id": 1, + "image_urls": [ + "https://i0.hdslb.com/bfs/article/d2eedf1fd338bceca10099e2f7b33fa9017c859b.jpg" + ], + "is_like": false, + "list": { + "apply_time": "", + "articles_count": 0, + "check_time": "", + "ctime": 1588601669, + "id": 253534, + "image_url": "", + "mid": 91221505, + "name": "静夜思", + "publish_time": 1625900652, + "read": 0, + "reason": "", + "state": 1, + "summary": "", + "update_time": 1625900518, + "words": 3059 + }, + "media": { + "area": "", + "cover": "", + "media_id": 0, + "score": 0, + "season_id": 0, + "spoiler": 0, + "title": "", + "type_id": 0, + "type_name": "" + }, + "mtime": 1589209079, + "origin_image_urls": [ + "https://i0.hdslb.com/bfs/article/b1e1029c08d8ad1bb06460d736839a7741dd7925.jpg" + ], + "origin_template_id": 4, + "original": 0, + "private_pub": 0, + "publish_time": 1519913233, + "reprint": 0, + "state": 0, + "stats": { + "coin": 2545, + "dislike": 1, + "dynamic": 0, + "favorite": 17524, + "like": 32489, + "reply": 14399, + "share": 616, + "view": 1631442 + }, + "summary": "天空像是倾倒出的墨水,黑得静谧而深邃。黎明还远,光亮全无。夜不能寐。披衣,起床。茶香的弥漫,一盏灯的相伴。夜,你是我久别重逢的朋友,那一刹那的相见,带给了我久违的安思。如果不是梦魇的皮闹,我本不该投入", + "template_id": 4, + "title": "未知的光", + "top_video_info": null, + "type": 0, + "words": 1190 + }, + "cv2": { + "act_id": 0, + "apply_time": "", + "authenMark": null, + "author": { + "face": "http://i0.hdslb.com/bfs/face/ff6b51c3b339dae5f341d1693f52132ab11c86b6.jpg", + "fans": 0, + "level": 0, + "mid": 144900660, + "name": "专栏小天使", + "nameplate": { + "condition": "", + "image": "", + "image_small": "", + "level": "", + "name": "", + "nid": 0 + }, + "official_verify": { + "desc": "专栏小天使 官方账号", + "type": 0 + }, + "pendant": { + "expire": 0, + "image": "", + "name": "", + "pid": 0 + }, + "vip": { + "avatar_subscript": 0, + "due_date": 0, + "label": { + "label_theme": "", + "path": "", + "text": "" + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 0, + "vip_pay_type": 0 + } + }, + "banner_url": "https://i0.hdslb.com/bfs/article/131b1d41b857d5308f5bff36591d117bddc48d96.jpg@90p.webp", + "categories": [ + { + "id": 3, + "name": "生活", + "parent_id": 0 + }, + { + "id": 15, + "name": "日常", + "parent_id": 3 + } + ], + "category": { + "id": 15, + "name": "日常", + "parent_id": 3 + }, + "check_state": 0, + "check_time": "", + "content_pic_list": null, + "cover_avid": 0, + "ctime": 1497973871, + "dispute": null, + "id": 2, + "image_urls": [ + "https://i0.hdslb.com/bfs/article/0a72422ce8e77d8512f010d93b1b7f9bc4e64e52.jpg" + ], + "is_like": false, + "list": null, + "media": { + "area": "", + "cover": "", + "media_id": 0, + "score": 0, + "season_id": 0, + "spoiler": 0, + "title": "", + "type_id": 0, + "type_name": "" + }, + "mtime": 1640696950, + "origin_image_urls": [ + "https://i0.hdslb.com/bfs/article/131b1d41b857d5308f5bff36591d117bddc48d96.jpg" + ], + "origin_template_id": 4, + "original": 0, + "private_pub": 0, + "publish_time": 1509517123, + "reprint": 1, + "state": 0, + "stats": { + "coin": 3590, + "dislike": 0, + "dynamic": 0, + "favorite": 5614, + "like": 16956, + "reply": 1944, + "share": 371, + "view": 1184187 + }, + "summary": "欢迎各位使用Bilibili专栏,为了保证Bilibili专栏的内容质量,维护专栏的内容生态,让创作者和读者都拥有良好的使用体验和阅读体验,请各位谨遵以下规范条例:\n\n严令禁止条例\nbilibili严", + "template_id": 4, + "title": "专栏行为准则 ", + "top_video_info": null, + "type": 0, + "words": 3711 + }, + "lv5440": { + "area_v2_name": "历史·人文·综合", + "cover": "https://i0.hdslb.com/bfs/live/9fe50921ab9b49e80dcb398f65135191d1b8252c.jpg", + "face": "https://i0.hdslb.com/bfs/face/8f6a614a48a3813d90da7a11894ae56a59396fcd.jpg", + "live_status": 2, + "online": 0, + "pendent_ru": "", + "pendent_ru_color": "", + "pendent_ru_pic": "", + "role": 0, + "room_id": 5440, + "title": "一场穿越20年的直播|梦回千禧文学", + "uid": 9617619, + "uname": "哔哩哔哩直播" + } + }, + "message": "0", + "ttl": 1 +} +``` +</details> + +<!-- Generated by json-apidoc-gen @ 2025-04-26T08:24:57.605652577Z --> diff --git a/bb-api-collect/docs/article/category.md b/bb-api-collect/docs/article/category.md new file mode 100644 index 0000000000..833fa40f0f --- /dev/null +++ b/bb-api-collect/docs/article/category.md @@ -0,0 +1,81 @@ +# 专栏分类 + +## 游戏 + +| id | parent_id | name | +|-----|-----------|------| +| 1 | 0 | 游戏 | +| 6 | 1 | 单机游戏 | +| 7 | 1 | 电子竞技 | +| 8 | 1 | 手机游戏 | +| 9 | 1 | 网络游戏 | +| 10 | 1 | 桌游棋牌 | + +## 动画 + +| id | parent_id | name | +|-----|-----------|------| +| 2 | 0 | 动画 | +| 4 | 2 | 动漫杂谈 | +| 5 | 2 | 动漫资讯 | +| 31 | 2 | 动画技术 | + +## 生活 + +| id | parent_id | name | +|-----|-----------|------| +| 3 | 0 | 生活 | +| 13 | 3 | 美食 | +| 14 | 3 | 时尚 | +| 15 | 3 | 日常 | +| 21 | 3 | 萌宠 | +| 22 | 3 | 运动 | + +## 轻小说 + +| id | parent_id | name | +|-----|-----------|------| +| 16 | 0 | 轻小说 | +| 18 | 16 | 原创连载 | +| 19 | 16 | 同人连载 | +| 20 | 16 | 小说杂谈 | +| 32 | 16 | 短篇小说 | + +## 科技 + +| id | parent_id | name | +|-----|-----------|------| +| 17 | 0 | 科技 | +| 25 | 17 | 人文历史 | +| 26 | 17 | 数码 | +| 27 | 17 | 汽车 | +| 33 | 17 | 自然 | +| 34 | 17 | 学习 | + +## 影视 + +| id | parent_id | name | +|-----|-----------|------| +| 28 | 0 | 影视 | +| 12 | 28 | 电影 | +| 35 | 28 | 电视剧 | +| 36 | 28 | 纪录片 | +| 37 | 28 | 综艺 | + +## 兴趣 + +| id | parent_id | name | +|-----|-----------|------| +| 29 | 0 | 兴趣 | +| 11 | 29 | 模型手办 | +| 23 | 29 | 绘画 | +| 24 | 29 | 手工 | +| 38 | 29 | 摄影 | +| 39 | 29 | 音乐舞蹈 | + +## 笔记 + +| id | parent_id | name | +|-----|-----------|------| +| 41 | 0 | 笔记 | +| 42 | 41 | 全部笔记 | diff --git a/bb-api-collect/docs/article/info.md b/bb-api-collect/docs/article/info.md new file mode 100644 index 0000000000..7e986f0bc0 --- /dev/null +++ b/bb-api-collect/docs/article/info.md @@ -0,0 +1,182 @@ +# 专栏基本信息 + +## 获取专栏文章基本信息 + +> https://api.bilibili.com/x/article/viewinfo + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| id | num | 专栏cvid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-404:无此信息 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ------ | ---------------- | ------------------------------------------------------------ | +| like | num | 是否点赞 | 0:未点赞<br />1:已点赞<br />需要登录(Cookie) <br />未登录为0 | +| attention | bool | 是否关注文章作者 | false:未关注<br />true:已关注<br />需要登录(Cookie) <br />未登录为false | +| favorite | bool | 是否收藏 | false:未收藏<br />true:已收藏<br />需要登录(Cookie) <br />未登录为false | +| coin | num | 为文章投币数 | | +| stats | obj | 状态数信息 | | +| title | str | 文章标题 | | +| banner_url | str | 文章头图url | | +| mid | num | 文章作者mid | | +| author_name | str | 文章作者昵称 | | +| is_author | bool | true | 作用尚不明确 | +| image_urls | array | 动态封面 | | +| origin_image_urls | array | 封面图片 | | +| shareable | bool | true | 作用尚不明确 | +| show_later_watch | bool | true | 作用尚不明确 | +| show_small_window | bool | true | 作用尚不明确 | +| in_list | bool | 是否收于文集 | false:否<br />true:是 | +| pre | num | 上一篇文章cvid | 无为0 | +| next | num | 下一篇文章cvid | 无为0 | +| share_channels | array | 分享方式列表 | | +| type | num | 文章类别 | 0:文章<br />2:笔记 | + + +`stats`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ---------- | ---- | +| view | num | 阅读数 | | +| favorite | num | 收藏数 | | +| like | num | 点赞数 | | +| dislike | num | 点踩数 | | +| reply | num | 评论数 | | +| share | num | 分享数 | | +| coin | num | 投币数 | | +| dynamic | num | 动态转发数 | | + +`data`中的`image_urls`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | str | 动态封面图片url | | + +`data`中的`origin_image_urls`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | str | 文章封面图片url | | + +`data`中的`share_channels`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | ---- | +| 0 | obj | 分享项:qq | | +| 1 | obj | 分享项:qq空间 | | +| 2 | obj | 分享项:微信 | | +| 3 | obj | 分享项:朋友圈 | | +| 4 | obj | 分享项:微博 | | + +`data`中的`share_channels`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ----------- | ---- | +| name | str | 分享名称 | | +| picture | str | 分享图片url | | +| share_channel | str | 分享代号 | | + +**示例:** + +查询文章`cv2`的基本信息 + +```shell +curl -G 'https://api.bilibili.com/x/article/viewinfo' \ +--data-urlencode 'id=2' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "like": 0, + "attention": false, + "favorite": false, + "coin": 0, + "stats": { + "view": 1072619, + "favorite": 5481, + "like": 16465, + "dislike": 0, + "reply": 1865, + "share": 351, + "coin": 3436, + "dynamic": 37 + }, + "title": "专栏行为准则 ", + "banner_url": "https://i0.hdslb.com/bfs/article/131b1d41b857d5308f5bff36591d117bddc48d96.jpg@90p.webp", + "mid": 144900660, + "author_name": "专栏小天使", + "is_author": true, + "image_urls": [ + "https://i0.hdslb.com/bfs/article/0a72422ce8e77d8512f010d93b1b7f9bc4e64e52.jpg" + ], + "origin_image_urls": [ + "https://i0.hdslb.com/bfs/article/131b1d41b857d5308f5bff36591d117bddc48d96.jpg" + ], + "shareable": true, + "show_later_watch": true, + "show_small_window": true, + "in_list": false, + "pre": 115914, + "next": 38575, + "share_channels": [ + { + "name": "QQ", + "picture": "https://i0.hdslb.com/bfs/album/114ccfb3a999df9c4d11f274c8c61a804c8f8803.png", + "share_channel": "QQ" + }, + { + "name": "QQ空间", + "picture": "https://i0.hdslb.com/bfs/album/30e9608bbce725bca45b5910866f60ab4d5e18b3.png", + "share_channel": "QZONE" + }, + { + "name": "微信", + "picture": "https://i0.hdslb.com/bfs/album/658af3c22431cd78bb7c50be3394f7c032eba12c.png", + "share_channel": "WEIXIN" + }, + { + "name": "朋友圈", + "picture": "https://i0.hdslb.com/bfs/album/c1ebcec8c5302f29f792d15f04e0d6dcef53ec27.png", + "share_channel": "WEIXIN_MONMENT" + }, + { + "name": "微博", + "picture": "https://i0.hdslb.com/bfs/album/3707fc23f7d3e24022712320284b0de9aa78c87d.png", + "share_channel": "SINA" + } + ], + "type": 0, + "video_url": "", + "location": "", + "disable_share": false + } +} +``` + +</details> diff --git a/bb-api-collect/docs/article/view.md b/bb-api-collect/docs/article/view.md new file mode 100644 index 0000000000..d7630685f4 --- /dev/null +++ b/bb-api-collect/docs/article/view.md @@ -0,0 +1,1346 @@ +# 专栏内容 + +## 获取专栏正文内容 + +> https://api.bilibili.com/x/article/view + +*请求方法: GET* + +鉴权方式: 请求头 `User-Agent` + +**URL 参数:** + +| 参数 | 类型 | 内容 | 必要性 | 备注 | +| ----- | ------ | ----------- | ------ | ---- | +| id | number | 专栏文章 ID | 必要 | | +| gaia_source | string | `main_web` | 不必要 | | +| w_rid | string | WBI 签名 | 不必要 | 参见 [WBI 签名](../misc/sign/wbi.md) | +| wts | number | UNIX 秒级时间戳 | 不必要 | 参见 [WBI 签名](../misc/sign/wbi.md) | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | number | 返回值 | 0: 成功<br />-352: 请求被风控<br />-400: 请求错误<br />-404: 啥都木有 | +| data | object | 数据本体 | 见下 | +| message | string | 错误信息 | 成功时为 `0` | +| ttl | number | `1` | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| act_id | number | 操作 ID? | | +| apply_time | string | 应用时间? | | +| attributes | number | 属性位? | 可能不存在 | +| authenMark | null | 授权码? | | +| author | object | 作者信息 | 参考 [用户基本信息](../user/info.md) | +| banner_url | string | 文章头图 URL | 空则为无 | +| categories | object[] | 专栏分类信息 | 首项为主分区, 第二项为子分区 | +| category | object | 专栏分类信息 | 子分区 | +| check_state | number | 检查状态? | | +| check_time | string | 检查时间? | | +| content | string | 文章内容 | `type` 字段为 `0` 为 HTML, `3` 为 JSON | +| content_pic_list | unknown | 内容图片列表? | | +| cover_avid | number | 封面视频 AV 号 | `0` 为无视频 | +| ctime | number | 创建时间 | UNIX 秒级时间戳 | +| dispute | unknown | 争议信息? | | +| dyn_id_str | string | 动态 opus id | | +| dynamic | string | 动态信息? | 可能不存在 | +| id | number | 专栏文章 ID | | +| image_urls | string[] | 图片 URL | | +| is_like | boolean | 是否喜欢? | | +| keywords | string | 关键词 | 以 `,` 分隔 | +| list | object | 文集信息 | 见下 | +| media | object | 媒体信息? | | +| mtime | number | 修改时间 | UNIX 秒级时间戳 | +| opus | object | opus 信息 | 当 `type` 字段为 `3` 时存在, 包含了更加详细的富文本信息 | +| origin_image_urls | string[] | 原始图片 URL | | +| origin_template_id | number | 原始模板 ID? | | +| original | number | 是否原创 | 0: 非原创<br />1: 原创 | +| private_pub | number | 仅自己可见 | | +| publish_time | number | 发布时间 | UNIX 秒级时间戳 | +| reprint | number | 是否允许转载 | 0: 不允许<br />1: 允许规范转载 | +| state | number | 专栏状态 | | +| stats | object | 统计数据 | | +| summary | string | 专栏开头部分内容 | 纯文本 | +| tags | object[] | 专栏标签 | | +| template_id | number | 模板 ID? | | +| title | string | 专栏标题 | | +| top_video_info | unknown | 封面食品信息? | | +| total_art_num | number | 作者总文章数 | | +| type | number | 类型? | | +| version_id | number | 版本 ID? | | +| words | number | 文章总词数 | | + +`data.categories[]` 对象: + +另见 [专栏分类](category.md) + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| id | number | 分类 ID | | +| name | string | 分类名称 | | +| parent_id | number | 父分类 ID | | + +`data.category` 对象: + +同 `data.categories[]` 中的对象 + +`data.content` 为字符串形式的 JSON 时代表的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | -------- | ---- | ---- | +| ops | object[] | 以 JSON 呈现的文本内容 | 套了个娃 | + +`data.content` 代表的对象中的 `ops` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | -------- | ---- | ---- | +| attribute | object? | 属性 | 见下 | +| insert | string \| object | 插入内容 | | + + +`data.content` 代表的对象中的 `ops[].attribute` 对象: + +注: 此处属性备注为页面实际渲染的情况 + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | -------- | ---- | ---- | +| align | string? | 文字对齐 | 参见 [text-align](https://developer.mozilla.org/zh-CN/docs/Web/CSS/text-align) | +| blockquote | boolean? | 块级引用 | 参见 [\<blockquote\>:块级引用元素](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Reference/Elements/blockquote) | +| bold | boolean? | 加粗 | 参见 [\<strong\>](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Reference/Elements/strong) | +| class | string? | 类名 | 参见 [class](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Reference/Global_attributes/class) | +| color | string? | 颜色 | 十六进制颜色值, 参见 [color](https://developer.mozilla.org/zh-CN/docs/Web/CSS/color) | +| header | number? | 标题级别 | 参见 [\<h1\>–\<h6\>:HTML 区域标题元素](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Reference/Elements/Heading_Elements) | +| strike | boolean? | 删除线 | 参见 [\<s\>](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Reference/Elements/s) | +| link | string? | 站内链接 | 参见 [\<a\>:锚元素](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Reference/Elements/a) | +| italic | boolean? | 斜体 | 参见 [\<em\>:强调元素](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Reference/Elements/em) | list | string? | 列表 | `bullet`: 无序列表, 参见 [\<ul\>:无序列表元素](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Reference/Elements/ul)<br />`ordered`: 有序列表, 参见 [\<ol\>](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Reference/Elements/ol) | + +`data.content` 代表的对象中的 `ops[].insert` 为对象时的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| native-image | object? | 原生图片 | 见下, 另见 [\<img\>:图像嵌入元素](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Reference/Elements/img) | +| cut-off | object? | 分割线 | 见下 | +| video-card | object? | 视频卡片 | 见下 | +| article-card | object? | 专栏卡片 | 见下 | +| vote-card | object? | 投票卡片 | 见下 | +| live-card | object? | 投票卡片 | 见下 | + +`data.content` 代表的对象中的 `ops[].insert.native-image` 对象: + +注: 此处属性备注为页面实际渲染的情况 + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| alt | string | 图像的备用文本描述 | 即 `<img>` 的 `alt` 属性 | +| url | string | 图像的 URL | 即 `<img>` 的 `src` 属性 | +| width | number | 图像的宽度 | 即 `<img>` 的 `data-w` 属性 | +| height | number | 图像的高度 | 即 `<img>` 的 `data-h` 属性 | +| size | number | 图像的文件大小 | 即 `<img>` 的 `data-size` 属性 | +| status | number | `"loaded"` | 即 `<img>` 的 `data-status` 属性 | + +`data.content` 代表的对象中的 `ops[].insert.cut-off` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ------ | ---- | ---- | +| type | string | 类型 | 没错, 就是字符串 | +| url | string | 分割线图片 URL | | + +`data.content` 代表的对象中的 `ops[].insert.video-card` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ------ | ---- | ---- | +| alt | string | | | +| height | number | 卡片高度 | 似乎恒定为 `352` | +| id | string | 视频 id | 如 `av99999999` | +| size | null | | | +| status | string | `loaded` | | +| tid | number | `1.1` | | +| url | string | 卡片图片 URL | | +| width | number | 卡片宽度 | 似乎恒定为 `2632` | + +`data.content` 代表的对象中的 `ops[].insert.article-card` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ------ | ---- | ---- | +| alt | string | | | +| height | number | 卡片高度 | 似乎恒定为 `320` | +| id | string | 文章 id | 如 `cv1` | +| size | null | | | +| status | string | `loaded` | | +| tid | number | `2` | | +| url | string | 卡片图片 URL | | +| width | number | 卡片宽度 | 似乎恒定为 `2632` | + +`data.content` 代表的对象中的 `ops[].insert.vote-card` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ------ | ---- | ---- | +| alt | string | | | +| height | number | 卡片高度 | 似乎恒定为 `320` | +| id | string | 投票 id | 确实是字符串, 如 `15111509` | +| size | null | | | +| status | string | `loaded` | | +| tid | number | `7` | | +| url | string | 卡片图片 URL | | +| width | number | 卡片宽度 | 似乎恒定为 `2632` | + +`data.content` 代表的对象中的 `ops[].insert.live-card` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ------ | ---- | ---- | +| alt | string | | | +| height | number | 卡片高度 | 似乎恒定为 `352` | +| id | string | 直播间 id | 可能为长也可能为短, 如 `lv1` `lv5440` | +| size | null | | | +| status | string | `loaded` | | +| tid | number | `8` | | +| url | string | 卡片图片 URL | | +| width | number | 卡片宽度 | 似乎恒定为 `2632` | + + +`data.list` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| apply_time | string | 空 | | +| articles_count | number | 0 | | +| check_time | string | 空 | | +| ctime | number | 创建时间 | UNIX 秒级时间戳 | +| id | number | 文集 ID | | +| image_url | string | 文集封面 URL | | +| mid | number | 作者 mid | | +| name | string | 文集名称 | | +| publish_time | number | 最新发布时间 | UNIX 秒级时间戳 | +| read | number | 0 | | +| reason | string | 审核不通过理由? | | +| state | number | 文集状态 | | +| summary | string | 文集描述 | | +| update_time | number | 文集更新时间 | UNIX 秒级时间戳 | +| words | number | 文集总词数 | | + +`data.media` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| area | string | | | +| cover | string | | | +| media_id | number | | | +| score | number | | | +| season_id | number | | | +| spoiler | number | | | +| title | string | | | +| type_id | number | | | +| type_name | string | | | + +`data.stats` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| coin | number | 硬币数 | | +| dislike | number | 点踩数 | 0 | +| dynamic | number | 动态数? | | +| favorite | number | 收藏数 | | +| like | number | 点赞数 | | +| reply | number | 回复数 | | +| share | number | 分享数 | | +| view | number | 查看数 | | + +`data.tags[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| name | string | 标签名 | | +| tid | number | 标签 ID | | + +**示例:** + +`type=0`: `cv1` 未知的光 + +```shell +curl -G 'https://api.bilibili.com/x/article/view' \ +--url-query 'id=1' \ +-A 'Mozilla/5.0' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "act_id": 0, + "apply_time": "", + "attributes": 24, + "authenMark": null, + "author": { + "face": "https://i1.hdslb.com/bfs/face/89fe260a17891fdadc3365a9698fee52796c7765.jpg", + "fans": 3051, + "level": 6, + "mid": 91221505, + "name": "健行见远渐忘", + "nameplate": { + "condition": "2018.6.26-7.8某一天是年度大会员", + "image": "https://i0.hdslb.com/bfs/face/421179426c929dfeaed4117461c83f5d07ffb148.png", + "image_small": "https://i0.hdslb.com/bfs/face/682001c2e1c2ae887bdf2a0e18eef61180c48f84.png", + "level": "稀有勋章", + "name": "大会员2018年度勋章", + "nid": 74 + }, + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i1.hdslb.com/bfs/face/7ae15f06f8c912435206a2578509d6bc77c12353.png", + "name": "作文鬼才", + "pid": 255 + }, + "vip": { + "avatar_subscript": 1, + "due_date": 0, + "label": { + "label_theme": "annual_vip", + "path": "http://i0.hdslb.com/bfs/vip/label_annual.png", + "text": "年度大会员" + }, + "nickname_color": "#FB7299", + "status": 1, + "theme_type": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "banner_url": "https://i0.hdslb.com/bfs/article/b1e1029c08d8ad1bb06460d736839a7741dd7925.jpg", + "categories": [ + { + "id": 3, + "name": "生活", + "parent_id": 0 + }, + { + "id": 15, + "name": "日常", + "parent_id": 3 + } + ], + "category": { + "id": 15, + "name": "日常", + "parent_id": 3 + }, + "check_state": 0, + "check_time": "", + "content": "<p>天空像是倾倒出的墨水,黑得静谧而深邃。黎明还远,光亮全无。</p><p>夜不能寐。披衣,起床。茶香的弥漫,一盏灯的相伴。夜,你是我久别重逢的朋友,那一刹那的相见,带给了我久违的安思。如果不是梦魇的皮闹,我本不该投入你的怀抱,此时此刻,万念侵扰,思绪咆哮。</p><p>台灯在角落里静静注视着我,不稳定的电流偶尔会吱吱作响。一切都像打在海绵上的水,渐渐消失,慢慢隐身于黑夜,独独留下我自己。一盏灯就可以把夜撕出个伤口,我似乎听到夜逃离光亮的脚步声,窸窸窣窣。它在蔓延,吞噬的野心已越过了窗沿。</p><p>我捧着茶杯,仿佛是在捧着一整个空间,凝重而诡异。茶香绕过茶杯脱落的瓷层向四周扩散,空气闻到了茶香,于是身边的气息似乎活跃了起来。转念一想,人生如茶。器皿的束缚不是茶香的归宿,所以人生的低谷也不是生命的全部。黑暗是光明的束缚,但光明却是黑暗的归宿。</p><p>灯光下,书架上一本金色题字的书的书名熠熠发光,我起身取下书,发现是海伦写的《假如给我三天光明》,我内心一热,忽然间有些感动。一个身体残疾的孩子,孱弱的身躯却支撑起了刚劲的灵魂。她的眼前一片漆黑,但内心世界却是光彩艳丽的。她的心中永远都有一抹无形的光,指引着她踏遍人生的路途。</p><p>时钟告诉我现在是凌晨四点。我舒展下筋骨,刚要起身,一只飞虫不偏不斜恰好闯入我的视线。灯光是它唯一的追寻。我不敢有任何的动作,只好也只能静静看着这只可爱的生灵。它好像不知道我是它的伙伴,也许它真的以为光亮是它唯一的追寻。但是我却欣慰于这突如其来的伙伴。光明可以带来很多东西,有时候也包括一份黑暗中的灵魂的一份安慰。我不忍打扰它与光明的约会,于是悄悄起身慢慢摸索着到了阳台。</p><p>阳台和我沉入了外面黑暗的梦乡。隐约可以听到一些不知名的昆虫在开着它们的舞会,我猜它们都端着无形的酒杯。它们在黑暗中买醉,因为明天的天明将是它们的散会。我有些感怀,也有些悲哀。</p><p>夜风股股咆哮着,我昂首顶住风头,仰望着漆黑的四周。很远很远处,灯塔若隐若现。它向来就是一头巨大的野兽,而此时它却空荡的像杯将尽的酒。它散发出柔弱的灯光在风中摇曳,忽明忽暗,像是一场与黑暗的决斗,随时都可能葬身在这黎明的前奏。</p><p>不忍心这惨烈的一幕,我踱步来到窗前。窗子很旧了,旧到已经无法再承受住时间的践踏了。可无论它多么陈旧,此时的它是神奇的——窗外黑暗窗内光。人心不也是一扇窗户吗?一半明媚一半伤。窗户把光亮的一面给了光明,人心是不是也应该把明媚的一半朝向世界呢?</p><p>屋内的灯倏忽闪了闪,我晃过神来,发现天边已经有抹淡红色了。黎明的脚步已经迈出了一半。那只与台灯约会的虫子似乎很满意,兴高采烈的向着呼之欲出的朝阳的方向窜去了。我望着它的背影,轻轻挥了挥手,心中暗念:“亲爱的朋友,恭喜你找到了属于自己的方向和追求,希望你能在光和热中接受生命的升华。”</p><p>天空见亮了,有点空灵,光晕中泛着感动。第一缕曙光穿透了云层,是的,我看到了,那一抹光,越来越近,越来越亮……</p>", + "content_pic_list": null, + "cover_avid": 0, + "ctime": 1497973729, + "dispute": null, + "dyn_id_str": "38554821905721204", + "dynamic": "It's now or never !", + "id": 1, + "image_urls": [ + "https://i0.hdslb.com/bfs/article/d2eedf1fd338bceca10099e2f7b33fa9017c859b.jpg" + ], + "is_like": false, + "keywords": "天空像是倾倒出的墨水,黑得静谧而深邃。黎明还远,光亮全无。夜不能寐。披衣,起床。茶香的弥漫,一盏灯的相伴。夜,你是我久别重逢的朋友,那一刹那的相见,带给了我久违的安思。如果不是梦魇的皮闹,我本不该投入", + "list": { + "apply_time": "", + "articles_count": 0, + "check_time": "", + "ctime": 1588601669, + "id": 253534, + "image_url": "", + "mid": 91221505, + "name": "静夜思", + "publish_time": 1625900652, + "read": 0, + "reason": "", + "state": 1, + "summary": "", + "update_time": 1625900518, + "words": 3059 + }, + "media": { + "area": "", + "cover": "", + "media_id": 0, + "score": 0, + "season_id": 0, + "spoiler": 0, + "title": "", + "type_id": 0, + "type_name": "" + }, + "mtime": 1589209079, + "origin_image_urls": [ + "https://i0.hdslb.com/bfs/article/b1e1029c08d8ad1bb06460d736839a7741dd7925.jpg" + ], + "origin_template_id": 4, + "original": 0, + "private_pub": 0, + "publish_time": 1519913233, + "reprint": 0, + "state": 0, + "stats": { + "coin": 2543, + "dislike": 1, + "dynamic": 0, + "favorite": 17520, + "like": 32484, + "reply": 14399, + "share": 616, + "view": 1631212 + }, + "summary": "天空像是倾倒出的墨水,黑得静谧而深邃。黎明还远,光亮全无。夜不能寐。披衣,起床。茶香的弥漫,一盏灯的相伴。夜,你是我久别重逢的朋友,那一刹那的相见,带给了我久违的安思。如果不是梦魇的皮闹,我本不该投入", + "tags": [ + { + "name": "静夜思", + "tid": 239416 + } + ], + "template_id": 4, + "title": "未知的光", + "top_video_info": null, + "total_art_num": 5, + "type": 0, + "version_id": 0, + "words": 1190 + }, + "message": "0", + "ttl": 1 +} +``` +</details> + +<!-- Generated by json-apidoc-gen @ 2025-04-22T16:42:30.354080534Z --> + +`type=3`: `cv41358718` 通过 DevTools 绕过 SSR 抓包某站专栏正文接口 + +```shell +curl 'https://api.bilibili.com/x/article/view?id=41358718' \ +-A 'Mozilla/10.0' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "id": 41358718, + "category": { + "id": 26, + "parent_id": 17, + "name": "数码" + }, + "categories": [ + { + "id": 17, + "parent_id": 0, + "name": "科技" + }, + { + "id": 26, + "parent_id": 17, + "name": "数码" + } + ], + "title": "通过 DevTools 绕过 SSR 抓包某站专栏正文接口", + "summary": "背景\n最近没什么事做, 又回 BAC 看看有什么接口可以抓, 于是看到了陈年的专栏正文内容的 Issue #859\n由于泽生自己是写前端的, 对于浏览器 DevTools 的各项调试工具还算是比较了解, 打算想办法把专栏正文的接口抓下来 :)\n思路\n由于专栏正文完整的内容在页面加载的时候就已经通过 SSR (Server-Side Rendering, 服务端渲染) 的方式通过 <script> 标签注入到 HTML 网页中, 直接通过看 DevTools 的网络面板肯定是没用的\n[图片]\n最直接的方法是", + "banner_url": "", + "template_id": 4, + "state": 0, + "author": { + "mid": 645769214, + "name": "Session小胡", + "face": "https://i2.hdslb.com/bfs/face/77906db03b1eefac02613de184afad03f7bc58d7.jpg", + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0 + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "nameplate": { + "nid": 4, + "name": "青铜殿堂", + "image": "https://i2.hdslb.com/bfs/face/2879cd5fb8518f7c6da75887994c1b2a7fe670bd.png", + "image_small": "https://i0.hdslb.com/bfs/face/6707c120e00a3445933308fd9b7bd9fad99e9ec4.png", + "level": "普通勋章", + "condition": "单个自制视频总播放数>=1万" + }, + "vip": { + "type": 1, + "status": 0, + "due_date": 0, + "vip_pay_type": 0, + "theme_type": 0, + "label": { + "path": "", + "text": "", + "label_theme": "" + }, + "avatar_subscript": 0, + "nickname_color": "" + }, + "fans": 347, + "level": 4 + }, + "reprint": 1, + "image_urls": [ + "https://i0.hdslb.com/bfs/article/9071997152b6fec0ae465fe2a86b580e645769214.jpg" + ], + "publish_time": 1744789930, + "ctime": 1744789930, + "mtime": 1744789930, + "stats": { + "view": 51, + "favorite": 2, + "like": 3, + "dislike": 0, + "reply": 0, + "share": 0, + "coin": 2, + "dynamic": 0 + }, + "tags": [ + { + "tid": 12005, + "name": "HTML" + }, + { + "tid": 336733, + "name": "API" + }, + { + "tid": 854101, + "name": "BAC" + }, + { + "tid": 2573142, + "name": "JavaScript" + }, + { + "tid": 2709088, + "name": "Bilibili" + }, + { + "tid": 2719113, + "name": "GitHub" + }, + { + "tid": 2822654, + "name": "Web" + }, + { + "tid": 3161936, + "name": "Chromium" + }, + { + "tid": 3416147, + "name": "DevTools" + } + ], + "words": 2039, + "origin_image_urls": [ + "https://i0.hdslb.com/bfs/article/9071997152b6fec0ae465fe2a86b580e645769214.jpg" + ], + "list": { + "id": 326286, + "mid": 645769214, + "name": "电脑", + "image_url": "", + "update_time": 1744789924, + "ctime": 1601636259, + "publish_time": 1744789930, + "summary": "", + "words": 9501, + "read": 0, + "articles_count": 0, + "state": 1, + "reason": "", + "apply_time": "", + "check_time": "" + }, + "is_like": false, + "media": { + "score": 0, + "media_id": 0, + "title": "", + "cover": "", + "area": "", + "type_id": 0, + "type_name": "", + "spoiler": 0, + "season_id": 0 + }, + "apply_time": "", + "check_time": "", + "original": 1, + "act_id": 0, + "dispute": null, + "authenMark": null, + "cover_avid": 0, + "top_video_info": null, + "type": 3, + "check_state": 0, + "origin_template_id": 4, + "private_pub": 0, + "content_pic_list": null, + "content": "{\"ops\":[{\"insert\":\"背景\"},{\"attributes\":{\"header\":2},\"insert\":\"\\n\"},{\"insert\":\"最近没什么事做, 又回 BAC 看看有什么接口可以抓, 于是看到了陈年的专栏正文内容的 Issue #859\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"由于泽生自己是写前端的, 对于浏览器 DevTools 的各项调试工具还算是比较了解, 打算想办法把专栏正文的接口抓下来 :)\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"思路\"},{\"attributes\":{\"header\":2},\"insert\":\"\\n\"},{\"insert\":\"由于专栏正文完整的内容在页面加载的时候就已经通过 SSR (Server-Side Rendering, 服务端渲染) 的方式通过 <script> 标签注入到 HTML 网页中, 直接通过看 DevTools 的网络面板肯定是没用的\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"attributes\":{\"class\":\"normal-img\"},\"insert\":{\"native-image\":{\"alt\":\"read-normal-img\",\"url\":\"https://i0.hdslb.com/bfs/new_dyn/7bb121008990850bbd333fe504eebc90645769214.png\",\"width\":748,\"height\":494,\"size\":185239,\"status\":\"loaded\"}}},{\"insert\":\"最直接的方法是找到专栏相关的 JavaScript 代码, 通过大脑在没有 SourceMap 的情况下沿着 bundle 逆向出接口, 这种方法对于泽生明显不可行, 其中一个原因是屏幕太小而源码太大 (-.-;)\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"另一个方法是通过伪造 SSR 不工作, 从而诱导页面脚本手动通过 API 去获取内容, 不过伪造的方法也比较麻烦, 但可行度相对较高 😆\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"关于如何伪造 SSR 不工作的现象, 就需要分析 SSR 是如何被使用的, 某站的 SSR 是通过向页面注入 JavaScript 代码实现的, 具体是在 window 全局对象上加了个属性 __INITIAL_STATE__, 具体结构需要具体页面分析\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"目标就是要在读取之前移除这个属性, 移除方法简单, 无非是直接 window.__INITIAL_STATE__ = undefined (或者任意无效值), 或者 delete window.__INITIAL_STATE__, 别的 ES6 的反射之类的方法就不说了, 这不是重点\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"但这个脚本注入的位置就很恶心, 不在 <head> 里面, 也不在 <body> 底部, 就刚好在读取 __INITIAL_STATE__ 的脚本前面, 这使得无法使用篡改猴一类的用户脚本插件进行修改, 因为提供的用户脚本执行方式会出现还没写属性和已经读过属性的问题 (゜-゜)\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"接着就是传统的 DevTools 调试面板, 但正常手动暂停脚本执行往往已经脚本执行完成了, 解决方法就是网络节流或者 <head> 处用户脚本 debugger 语句\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"正好篡改猴高级设置允许用户脚本执行前暂停开始调试, 原理就是 debugger 语句, 只要把脚本执行位置放在 <body> 之前就有机会打断点把 __INITIAL_STATE__ 删掉 💥\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"attributes\":{\"class\":\"normal-img\"},\"insert\":{\"native-image\":{\"alt\":\"read-normal-img\",\"url\":\"https://i0.hdslb.com/bfs/new_dyn/1a20d186e8c8cddc043b5295d481c719645769214.png\",\"width\":625,\"height\":563,\"size\":320286,\"status\":\"loaded\"}}},{\"insert\":\"实践\"},{\"attributes\":{\"header\":2},\"insert\":\"\\n\"},{\"insert\":\"使用 Chromium (理论上 Firefox 也可以, 但其 DevTools 泽生用起来不是很舒服) 安装篡改猴扩展 🐒, 新建一个用户脚本, 里面是否写内容无所谓, 执行位置为 document-head, 然后在篡改猴的设置里面把调试脚本打开\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"接着打开一个使用 SSR 的网页, 不过注意要保持 DevTools 打开, 否则调试就不会生效, 页面脚本自动暂停后, 你将看到你的脚本和该页面已经加载的内容, 包含 HTML 网页, JavaScript 代码, 和 CSS 文本\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"你所需要做的就是检查 SSR 的情况是否如你所想的那样, 放在 window.__INITIAL_STATE__ 那里, 如果是直接渲染成页面元素的话, 抱歉上帝来了也救不了你, 某站 JavaScript 前端可不会管 HTML 的事情 🫠\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"如果在 __INITIAL_STATE__ 里面, 恭喜, 你可以直接继续了. 如果不是, 那就检查一下当前页面路径之类的, 看看有没有不同版本的相同内容, 毕竟专栏分新旧版, 专栏网页也分新旧版, 往往旧版能带来惊喜 ✨\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"找到了合适的 __INITIAL_STATE__, 你只需要在原地打个断点, 然后继续执行脚本, 页面就会在那里暂停, 接着执行下一步, 此时赋值完成, 可以开始改属性了\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"切到控制台, 执行那句期待已久的语句: window.__INITIAL_STATE__ = undefined, 大功告成! 🎉\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"恢复页面脚本执行, 你会看到页面好像卡了一下, 然后文章还是加载了出来, 这个时候就可以看看网络面板的情况了\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"attributes\":{\"class\":\"normal-img\"},\"insert\":{\"native-image\":{\"alt\":\"read-normal-img\",\"url\":\"https://i0.hdslb.com/bfs/new_dyn/87c88df1e15195996e34835456493d55645769214.png\",\"width\":892,\"height\":831,\"size\":473706,\"status\":\"loaded\"}}},{\"insert\":\"可以观察到, 多了一个你从来没见到过的叫 view 的野生请求, 点开详细, 复制地址, 记下参数, 保存响应, 发 Issue 去也~\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"如果这时回过头看控制台, 你会发现有这么一段错误十分显眼, 无法读取 undefined 的属性, 正是由于这个错误, 加之某站程序员的细心, 你才得以看到文章和抓到接口\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"后话\"},{\"attributes\":{\"header\":2},\"insert\":\"\\n\"},{\"insert\":\"Issue 已经发了, 估计写到文档里也是泽生的事情 🥴\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"这样的因 SSR 而省下的相关接口应该也有很多, 一个个慢慢打断点抓也不是个长久之计, 毕竟一旦直接渲染成 HTML, 就没的办法了 😮‍💨\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"学习正经的前端知识还是有利于不正经的逆向的 📚\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"希望大家都能来一起帮忙, Make BAC Great Again! 🥂\"},{\"attributes\":{\"list\":\"bullet\"},\"insert\":\"\\n\"},{\"insert\":\"有改动, 原文地址: https://sess.xhustudio.eu.org/posts/2025/devtools-vs-ssr-bac/\"},{\"attributes\":{\"blockquote\":true},\"insert\":\"\\n\"}]}", + "keywords": "BULLET,HEADER,WINDOW,LIST,SSR,WIDTH,html,undefined,VIEW,FIREFOX,BAC,JAVASCRIPT,CLASS,脚本插件,SIZE,TRUE,es6,ALT,长久之计,HTTPS,CSS,控制台,一起帮,A_PI,解决方法,期待已久,大功告成,没什么,有什么,浏览器,很舒服,无所谓,有没有,程序员,有利于,不正经", + "version_id": 0, + "opus": { + "opus_id": 1056353752004427792, + "opus_source": 2, + "title": "通过 DevTools 绕过 SSR 抓包某站专栏正文接口", + "content": { + "paragraphs": [ + { + "para_type": 1, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "背景", + "font_size": 22, + "style": { + "bold": true + }, + "font_level": "xLarge" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 1 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "最近没什么事做, 又回 BAC 看看有什么接口可以抓, 于是看到了陈年的专栏正文内容的 Issue #859", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 2 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "由于泽生自己是写前端的, 对于浏览器 DevTools 的各项调试工具还算是比较了解, 打算想办法把专栏正文的接口抓下来 :)", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 1, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "思路", + "font_size": 22, + "style": { + "bold": true + }, + "font_level": "xLarge" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 1 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "由于专栏正文完整的内容在页面加载的时候就已经通过 SSR (Server-Side Rendering, 服务端渲染) 的方式通过 <script> 标签注入到 HTML 网页中, 直接通过看 DevTools 的网络面板肯定是没用的", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 2, + "pic": { + "pics": [ + { + "url": "https://i0.hdslb.com/bfs/new_dyn/7bb121008990850bbd333fe504eebc90645769214.png", + "width": 748, + "height": 494, + "size": 180.8974609375 + } + ], + "style": 1 + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 1 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "最直接的方法是找到专栏相关的 JavaScript 代码, 通过大脑在没有 SourceMap 的情况下沿着 bundle 逆向出接口, 这种方法对于泽生明显不可行, 其中一个原因是屏幕太小而源码太大 (-.-;)", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 2 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "另一个方法是通过伪造 SSR 不工作, 从而诱导页面脚本手动通过 API 去获取内容, 不过伪造的方法也比较麻烦, 但可行度相对较高 😆", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 3 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "关于如何伪造 SSR 不工作的现象, 就需要分析 SSR 是如何被使用的, 某站的 SSR 是通过向页面注入 JavaScript 代码实现的, 具体是在 window 全局对象上加了个属性 __INITIAL_STATE__, 具体结构需要具体页面分析", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 4 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "目标就是要在读取之前移除这个属性, 移除方法简单, 无非是直接 window.__INITIAL_STATE__ = undefined (或者任意无效值), 或者 delete window.__INITIAL_STATE__, 别的 ES6 的反射之类的方法就不说了, 这不是重点", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 5 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "但这个脚本注入的位置就很恶心, 不在 <head> 里面, 也不在 <body> 底部, 就刚好在读取 __INITIAL_STATE__ 的脚本前面, 这使得无法使用篡改猴一类的用户脚本插件进行修改, 因为提供的用户脚本执行方式会出现还没写属性和已经读过属性的问题 (゜-゜)", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 6 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "接着就是传统的 DevTools 调试面板, 但正常手动暂停脚本执行往往已经脚本执行完成了, 解决方法就是网络节流或者 <head> 处用户脚本 debugger 语句", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 7 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "正好篡改猴高级设置允许用户脚本执行前暂停开始调试, 原理就是 debugger 语句, 只要把脚本执行位置放在 <body> 之前就有机会打断点把 __INITIAL_STATE__ 删掉 💥", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 2, + "pic": { + "pics": [ + { + "url": "https://i0.hdslb.com/bfs/new_dyn/1a20d186e8c8cddc043b5295d481c719645769214.png", + "width": 625, + "height": 563, + "size": 312.779296875 + } + ], + "style": 1 + } + }, + { + "para_type": 1, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "实践", + "font_size": 22, + "style": { + "bold": true + }, + "font_level": "xLarge" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 1 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "使用 Chromium (理论上 Firefox 也可以, 但其 DevTools 泽生用起来不是很舒服) 安装篡改猴扩展 🐒, 新建一个用户脚本, 里面是否写内容无所谓, 执行位置为 document-head, 然后在篡改猴的设置里面把调试脚本打开", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 2 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "接着打开一个使用 SSR 的网页, 不过注意要保持 DevTools 打开, 否则调试就不会生效, 页面脚本自动暂停后, 你将看到你的脚本和该页面已经加载的内容, 包含 HTML 网页, JavaScript 代码, 和 CSS 文本", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 3 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "你所需要做的就是检查 SSR 的情况是否如你所想的那样, 放在 window.__INITIAL_STATE__ 那里, 如果是直接渲染成页面元素的话, 抱歉上帝来了也救不了你, 某站 JavaScript 前端可不会管 HTML 的事情 🫠", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 4 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "如果在 __INITIAL_STATE__ 里面, 恭喜, 你可以直接继续了. 如果不是, 那就检查一下当前页面路径之类的, 看看有没有不同版本的相同内容, 毕竟专栏分新旧版, 专栏网页也分新旧版, 往往旧版能带来惊喜 ✨", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 5 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "找到了合适的 __INITIAL_STATE__, 你只需要在原地打个断点, 然后继续执行脚本, 页面就会在那里暂停, 接着执行下一步, 此时赋值完成, 可以开始改属性了", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 6 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "切到控制台, 执行那句期待已久的语句: window.__INITIAL_STATE__ = undefined, 大功告成! 🎉", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 7 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "恢复页面脚本执行, 你会看到页面好像卡了一下, 然后文章还是加载了出来, 这个时候就可以看看网络面板的情况了", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 2, + "pic": { + "pics": [ + { + "url": "https://i0.hdslb.com/bfs/new_dyn/87c88df1e15195996e34835456493d55645769214.png", + "width": 892, + "height": 831, + "size": 462.603515625 + } + ], + "style": 1 + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 1 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "可以观察到, 多了一个你从来没见到过的叫 view 的野生请求, 点开详细, 复制地址, 记下参数, 保存响应, 发 Issue 去也~", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 2 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "如果这时回过头看控制台, 你会发现有这么一段错误十分显眼, 无法读取 undefined 的属性, 正是由于这个错误, 加之某站程序员的细心, 你才得以看到文章和抓到接口", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 1, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "后话", + "font_size": 22, + "style": { + "bold": true + }, + "font_level": "xLarge" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 1 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "Issue 已经发了, 估计写到文档里也是泽生的事情 🥴", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 2 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "这样的因 SSR 而省下的相关接口应该也有很多, 一个个慢慢打断点抓也不是个长久之计, 毕竟一旦直接渲染成 HTML, 就没的办法了 😮‍💨", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 3 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "学习正经的前端知识还是有利于不正经的逆向的 📚", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 6, + "format": { + "list_format": { + "level": 1, + "order": 4 + } + }, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "希望大家都能来一起帮忙, Make BAC Great Again! 🥂", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + }, + { + "para_type": 4, + "text": { + "nodes": [ + { + "node_type": 1, + "word": { + "words": "有改动, 原文地址: https://sess.xhustudio.eu.org/posts/2025/devtools-vs-ssr-bac/", + "font_size": 17, + "style": {}, + "font_level": "regular" + } + } + ] + } + } + ] + }, + "tags": [ + { + "tag": { + "show_text": "HTML", + "link_type": 36 + } + }, + { + "tag": { + "show_text": "API", + "link_type": 36 + } + }, + { + "tag": { + "show_text": "BAC", + "link_type": 36 + } + }, + { + "tag": { + "show_text": "JavaScript", + "link_type": 36 + } + }, + { + "tag": { + "show_text": "Bilibili", + "link_type": 36 + } + }, + { + "tag": { + "show_text": "GitHub", + "link_type": 36 + } + }, + { + "tag": { + "show_text": "Web", + "link_type": 36 + } + }, + { + "tag": { + "show_text": "Chromium", + "link_type": 36 + } + }, + { + "tag": { + "show_text": "DevTools", + "link_type": 36 + } + } + ], + "pub_info": { + "uid": 645769214, + "pub_time": 1744789930 + }, + "article": { + "category_id": 26, + "list_id": 326286, + "originality": 1, + "reproduced": 1, + "cover": [ + { + "url": "http://i0.hdslb.com/bfs/article/9071997152b6fec0ae465fe2a86b580e645769214.jpg", + "width": 768, + "height": 430, + "size": 58.13671875 + } + ], + "biz_tags": [ + "JavaScript", + "HTML", + "Chromium", + "DevTools", + "BAC", + "GitHub", + "API", + "Bilibili", + "Web" + ] + }, + "version": { + "cvid": 41358718, + "version_id": 140614555890906624 + } + }, + "dyn_id_str": "1056353752004427792", + "total_art_num": 4 + } +} +``` + +</details> diff --git a/bb-api-collect/docs/audio/action.md b/bb-api-collect/docs/audio/action.md new file mode 100644 index 0000000000..8199f0582c --- /dev/null +++ b/bb-api-collect/docs/audio/action.md @@ -0,0 +1,148 @@ +# 音频投币&收藏 + +## 查询音频收藏状态 + +> https://www.bilibili.com/audio/music-service-c/web/collections/songs-coll + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +鉴权方式:Cookie中`DedeUserID`存在且不为0 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| sid | num | 音频auid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />72000000:参数错误<br />72010002:账号未登陆<br />7201006:该音频不存在或已被下架 | +| msg | str | 错误信息 | 默认为success | +| data | bool | 是否收藏 | false:未收藏<br />true:已收藏 | + +**示例:** + +查询音频`au13598`的收藏状态 + +```shell +curl -G 'https://www.bilibili.com/audio/music-service-c/web/collections/songs-coll' \ +--data-urlencode 'sid=13598' \ +-b 'SESSDATA=xxx;DedeUserID=1;' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "data": true +} +``` + +</details> + +## 查询音频投币数 + +> https://www.bilibili.com/audio/music-service-c/web/coin/audio + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +鉴权方式:Cookie中`DedeUserID`存在且不为0 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| sid | num | 音频auid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />72000000:参数错误<br />72010002:账号未登陆<br />7201006:该音频不存在或已被下架 | +| msg | str | 错误信息 | 默认为success | +| data | num | 投币数量 | 0为未投币,上限为2 | + +**示例:** + +查询音频`au13598`的投币数 + +```shell +curl -G 'https://www.bilibili.com/audio/music-service-c/web/coin/audio' \ +--data-urlencode 'sid=15664' \ +-b 'SESSDATA=xxx;DedeUserID=1;' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "data": 1 +} +``` + +</details> + +## 投币音频 + +> https://www.bilibili.com/audio/music-service-c/web/coin/add + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------------------- | ------ | ---- | +| sid | num | 音频 auid | 必要 | | +| multiply | num | 投币数量(最大为 2) | 必要 | | +| csrf | str | CSRF Token(位于 cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />72000000:参数错误<br />72010002:账号未登陆<br />7201006:该音频不存在或已被下架 | +| msg | str | 错误信息 | 默认为 0 | +| data | str | 当前投币数量 | 0 为未投币,上限为 2 | + +**示例:** + +为音频`au13598`投币 + +```shell +curl -G 'https://www.bilibili.com/audio/music-service-c/web/coin/add' \ +--data-urlencode 'sid=15664' \ +-b 'SESSDATA=xxx;DedeUserID=1;' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "0", + "data": "1" +} +``` + +</details> diff --git a/bb-api-collect/docs/audio/info.md b/bb-api-collect/docs/audio/info.md new file mode 100644 index 0000000000..2b296ff470 --- /dev/null +++ b/bb-api-collect/docs/audio/info.md @@ -0,0 +1,425 @@ +# 歌曲基本信息 + +## 查询歌曲基本信息 + +> https://www.bilibili.com/audio/music-service-c/web/song/info + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| sid | num | 音频auid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ----------------------------- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />72000000:参数错误<br />7201006:该音频不存在或已被下架<br />72010027:版权音乐重定向 | +| msg | str | 错误信息 | 默认为success | +| data | 正确时:obj<br />错误时:null | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ------ | ------------------ | ------------------ | +| id | num | 音频auid | | +| uid | num | UP主mid | | +| uname | str | UP主昵称 | | +| author | str | 作者名 | | +| title | str | 歌曲标题 | | +| cover | str | 封面图片url | | +| intro | str | 歌曲简介 | | +| lyric | str | lrc歌词url | | +| crtype | num | 1 | **作用尚不明确** | +| duration | num | 歌曲时间长度 | 单位为秒 | +| passtime | num | 歌曲发布时间 | 时间戳 | +| curtime | num | 当前请求时间 | 时间戳 | +| aid | num | 关联稿件avid | 无为0 | +| bvid | str | 关联稿件bvid | 无为空 | +| cid | num | 关联视频cid | 无为0 | +| msid | num | 0 | **作用尚不明确** | +| attr | num | 0 | **作用尚不明确** | +| limit | num | 0 | **作用尚不明确** | +| activityId | num | 0 | **作用尚不明确** | +| limitdesc | str | 空 | **作用尚不明确** | +| ctime | null | - | **作用尚不明确** | +| statistic | obj | 状态数 | | +| vipInfo | obj | UP主会员状态 | | +| collectIds | array | 歌曲所在的收藏夹mlid | 需要登录(SESSDATA) | +| coin_num | num | 投币数 | | + +`data`中的`statistic`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---- | +| sid | num | 音频auid | | +| play | num | 播放次数 | | +| collect | num | 收藏数 | | +| comment | num | 评论数 | | +| share | num | 分享数 | | + +`data`中的`vipInfo`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ------------ | ----------------------------------- | +| type | num | 会员类型 | 0:无<br />1:月会员<br />2:年会员 | +| status | num | 会员状态 | 0:无<br />1:有 | +| due_date | num | 会员到期时间 | 时间戳 毫秒 | +| vip_pay_type | num | 会员开通状态 | 0:无<br />1:有 | + +`data`中的`collectIds`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------------------- | ---- | +| 0 | num | 第1个所在的收藏夹mlid | | +| n | num | 第(n+1)个所在的收藏夹mlid | | +| …… | num | …… | …… | + +**示例:** + +查询音频`au13598`的基本信息 + +```shell +curl -G 'https://www.bilibili.com/audio/music-service-c/web/song/info' \ +--data-urlencode 'sid=13598' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "data": { + "id": 13598, + "uid": 486183, + "uname": "排骨教主", + "author": "排骨教主", + "title": "牵丝戏", + "cover": "http://i0.hdslb.com/bfs/music/cf50d93b4dc08bfc6d3112041d6de0e56045ac5b.jpg", + "intro": "自制 这次要特别感谢山东省京剧院的各位年轻的老师们对我戏腔发声的悉心指导\n关注排骨的微博@排骨节操收割机\n排骨QQ群456237456\n感谢@妄北没睡够(新浪微博) 画的视频图,太美了!!!!!\n", + "lyric": "http://i0.hdslb.com/bfs/music/150587810313598.lrc", + "crtype": 1, + "duration": 239, + "passtime": 1501640683, + "curtime": 1590154258, + "aid": 2554020, + "bvid": "BV1us411S7E6", + "cid": 3990196, + "msid": 0, + "attr": 0, + "limit": 0, + "activityId": 0, + "limitdesc": "", + "ctime": null, + "statistic": { + "sid": 13598, + "play": 1028516, + "collect": 30914, + "comment": 523, + "share": 384 + }, + "vipInfo": { + "type": 2, + "status": 1, + "due_date": 1620316800000, + "vip_pay_type": 0 + }, + "collectIds": [ + 15967839 + ], + "coin_num": 1777 + } +} +``` + +</details> + +## 查询歌曲TAG + +> https://www.bilibili.com/audio/music-service-c/web/tag/song + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| sid | num | 音频auid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ------ | -------- | ------------- | +| code | num | 返回值 | 0:成功 | +| msg | str | 错误信息 | 默认为success | +| data | array | TAG列表 | 无为空 | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| 0 | str | TAG1 | | +| n | str | TAG(n+1) | | +| …… | str | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ---------- | ---------------- | +| type | str | song | **作用尚不明确** | +| subtype | num | ??? | **作用尚不明确** | +| key | num | TAG id?? | **作用尚不明确** | +| info | str | TAG名 | | + +**示例:** + +查询音频`au15664`的TAG + +```shell +curl -G 'https://www.bilibili.com/audio/music-service-c/web/tag/song' \ +--data-urlencode 'sid=15664' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "data": [ + { + "type": "song", + "subtype": 0, + "key": 1, + "info": "音乐" + }, + { + "type": "song", + "subtype": 1, + "key": 3, + "info": "人声" + }, + { + "type": "song", + "subtype": 2, + "key": 2, + "info": "翻唱" + }, + { + "type": "song", + "subtype": 3, + "key": 33, + "info": "日语" + }, + { + "type": "song", + "subtype": 5, + "key": 41, + "info": "网络歌曲" + }, + { + "type": "song", + "subtype": 4, + "key": 7, + "info": "流行" + } + ] +} +``` + +</details> + +## 查询歌曲创作成员列表 + +> https://www.bilibili.com/audio/music-service-c/web/member/song + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| sid | num | 音频auid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ------ | ------------ | ------------- | +| code | num | 返回值 | 0:成功 | +| msg | str | 错误信息 | 默认为success | +| data | array | 成员类型列表 | 无为空 | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---- | +| 0 | str | 成员类型1 | | +| n | str | 成员类型(n+1) | | +| …… | str | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ------ | ------------ | ------------------------------------------------------------ | +| list | array | 成员列表 | | +| type | num | 成员类型代码 | 1:歌手<br />2:作词<br />3:作曲<br />4:编曲<br />5:后期/混音<br />7:封面制作<br />8:音源<br />9:调音<br />10:演奏<br />11:乐器<br />127:UP主 | + +`data`数组中的对象中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---- | +| 0 | str | 成员1 | | +| n | str | 成员(n+1) | | +| …… | str | …… | …… | + +`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ---------- | ---------------- | +| mid | num | 0 | **作用尚不明确** | +| name | str | 成员名 | | +| member_id | num | 成员id?? | **作用尚不明确** | + +**示例:** + +查询音频`au815861`的创作成员信息 + +```shell +curl -G 'https://www.bilibili.com/audio/music-service-c/web/member/song' \ +--data-urlencode 'sid=815861' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "data": [ + { + "list": [ + { + "mid": 0, + "name": "匀子Cyrena", + "member_id": 164341 + } + ], + "type": 1 + }, + { + "list": [ + { + "mid": 0, + "name": "圣月樱泪 ", + "member_id": 12349 + } + ], + "type": 2 + }, + { + "list": [ + { + "mid": 0, + "name": "Days的Wing翼", + "member_id": 13777 + } + ], + "type": 3 + }, + { + "list": [ + { + "mid": 0, + "name": "Days的Wing翼", + "member_id": 13777 + } + ], + "type": 4 + }, + { + "list": [ + { + "mid": 0, + "name": "嘟比Dubi", + "member_id": 40902 + } + ], + "type": 5 + }, + { + "list": [ + { + "mid": 0, + "name": "匀子Cyrena", + "member_id": 164222 + } + ], + "type": 127 + } + ] +} +``` + +</details> + +## 获取歌曲歌词 + +> https://www.bilibili.com/audio/music-service-c/web/song/lyric + +*请求方式:GET* + +同[查询歌曲基本信息](#查询歌曲基本信息)中的lrc歌词 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| sid | num | 音频auid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ----------------------------- | --------------- | ------------- | +| code | num | 返回值 | 0:成功 | +| msg | str | 错误信息 | 默认为success | +| data | 正确时:str<br />错误时:null | lrc格式歌词信息 | 无为空 | + +**示例:** + +获取音频`au15664`的歌词信息 + +```shell +curl -G 'https://www.bilibili.com/audio/music-service-c/web/song/lyric' \ +--data-urlencode 'sid=15664' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "data": "[ar:萧忆情]\n\n[ti:威风堂堂]\n\n[00:26.64]引诱谁去摘下禁果\n\n[00:28.11]甜美滋味偷咬一口\n\n[00:30.03]触及到了最深处果核\n\n[00:31.82]身体开始颤抖\n\n[00:33.85]舌尖已濡湿双腿内侧\n\n[00:35.55]神经末梢警报响彻\n\n[00:37.39]自内而外逐渐变得火热\n\n[00:39.14]现在无须再遵守规则\n\n[00:42.14]还故作矜持说违心的话\n\n[00:45.84]为何动作不停下\n\n[00:47.85]停下来\n\n[00:48.39]已经快停不下来\n\n[00:49.42]还想索取更多\n\n[00:50.46]踩碎那PRIDE\n\n[00:51.41]忘记毫无意义的理智存在\n\n[00:53.27]让暧昧因子在四处的徘徊\n\n[00:55.19]给我收起你那\n\n[00:56.21]太虚伪的STYLE\n\n[00:57.01]直白赤裸的爱\n\n[00:58.00]最原始的DIVE\n\n[00:58.86]喘息中断续的声音叫期待\n\n[01:00.65]别掩饰此刻\n\n[01:01.50]那让人意乱情迷的SMILE\n\n[01:10.90]缓慢吐息迷惑双眼的雾\n\n[01:12.49]强制禁锢身下轻舔锁骨\n\n[01:14.23]就让封锁的心渐渐领悟\n\n[01:15.97]别继续装无辜\n\n[01:17.54]开始脱下的衬衫\n\n[01:19.08]最后的纽扣解开它\n\n[01:20.98]快感get\n\n[01:21.85]从此不顾一切\n\n[01:23.32]还在犹豫什么\n\n[01:24.78]Darling\n\n[01:26.54]站在自由世界的正中央\n\n[01:30.09]窥探你幻想的是否太过浪荡\n\n[01:33.99]太难耐\n\n[01:34.41]分分秒秒太难耐\n\n[01:35.61]床笫间的狩猎\n\n[01:36.63]充满野心的TRY\n\n[01:37.66]不承认口头上无理的摊牌\n\n[01:39.58]只想要在身体里深埋\n\n[01:41.34]现在由我掌控\n\n[01:42.36]随心所欲的LIFE\n\n[01:43.40]给你要的未来\n\n[01:44.41]永远不腐坏\n\n[01:45.32]所有的阴暗面统统藏起来\n\n[01:46.70]仅为你一人展现那能骄傲夸耀的MIND\n\n[01:49.90]将不安的情绪碾至粉末\n\n[01:53.14]抹在你胸口印上最鲜艳的红\n\n[02:21.06]别打算缩起来置身之外\n\n[02:22.64]无论何时\n\n[02:23.27]NO TIME\n\n[02:23.58]ALL RIGHT\n\n[02:24.21]打破一切的羞耻值\n\n[02:25.43]哪里奇怪\n\n[02:26.06]哪里奇怪\n\n[02:26.68]哪里奇怪\n\n[02:27.30]BURN BURN BURN\n\n[02:28.22]想要的就是那\n\n[02:29.17]啊 没错\n\n[02:29.87]再给我更多的触摸\n\n[02:31.62]顺位交换贴近肌肤的DANCE\n\n[02:33.34]好吧 肆无忌惮\n\n[02:34.98]停下来\n\n[02:35.35]已经快停不下来\n\n[02:36.50]还想索取更多\n\n[02:37.68]踩碎那PRIDE\n\n[02:38.38]忘记毫无意义的理智存在\n\n[02:40.27]让暧昧因子在四处的徘徊\n\n[02:42.11]给我收起你那\n\n[02:43.16]太虚伪的STYLE\n\n[02:44.00]直白赤裸的爱\n\n[02:45.06]最原始的DIVE\n\n[02:45.90]喘息中断续的声音叫期待\n\n[02:47.76]别掩饰此刻那让人意乱情迷的SMILE\n\n[02:50.64]将不安的情绪碾至粉末\n\n[02:54.09]抹在你胸口印上最鲜艳的红\n\n[02:58.35]抛弃所有只想拥有此刻\n\n" +} +``` + +</details> diff --git a/bb-api-collect/docs/audio/music_list.md b/bb-api-collect/docs/audio/music_list.md new file mode 100644 index 0000000000..8e8dff0ec6 --- /dev/null +++ b/bb-api-collect/docs/audio/music_list.md @@ -0,0 +1,782 @@ +# 歌单&音频收藏夹详细信息 + +## 查询自己创建的歌单 + +> https://www.bilibili.com/audio/music-service-c/web/collections/list + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +鉴权方式:Cookie中`DedeUserID`存在且不为0 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| pn | num | 页码 | 必要 | | +| ps | num | 每页项数 | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ----------------------------- | -------- | ----------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />72000000:参数错误<br />72010002:未登录 | +| msg | str | 错误信息 | 默认为success | +| data | 正确时:obj<br />错误时:null | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ------ | ------------ | ---- | +| curPage | num | 当前页码 | | +| pageCount | num | 总计页数 | | +| totalSize | num | 总计收藏夹数 | | +| pageSize | num | 当前页面项数 | | +| data | array | 歌单列表 | | + +`data`中的`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------------- | ---- | +| 0 | obj | 音频收藏夹mlid1 | | +| n | obj | 音频收藏夹mlid(n+1) | | +| …… | obj | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ------ | ------------------------ | -------------------------------- | +| id | num | 音频收藏夹mlid | | +| uid | num | 创建用户mid | | +| uname | str | 创建用户昵称 | | +| title | str | 歌单标题 | | +| type | num | 收藏夹属性 | 0:普通收藏夹<br />1:默认收藏夹 | +| published | num | 是否公开 | 0:不公开<br />1:公开 | +| cover | str | 歌单封面图片url | | +| ctime | num | 歌单创建时间 | 时间戳 | +| song | num | 歌单中的音乐数量 | | +| desc | str | 歌单备注信息 | | +| sids | array | 歌单中的音乐 | | +| menuId | num | 音频收藏夹对应的歌单amid | | +| statistic | obj | 歌单状态数信息 | | + +`data`中的`sids`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------------- | ---------------- | +| 0 | num | 收藏的音频auid1 | | +| n | num | 收藏的音频auid(n+1) | 按照歌单顺序排列 | +| …… | num | …… | …… | + +`data`中的`statistic`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ------------------------ | ---- | +| sid | num | 音频收藏夹对应的歌单amid | | +| play | num | 播放数 | | +| collect | num | 收藏数 | | +| comment | null | 评论数 | | +| share | num | 分享数 | | + +**示例:** + +```shell +curl -G 'https://www.bilibili.com/audio/music-service-c/web/collections/list' \ +--data-urlencode 'ps=2' \ +--data-urlencode 'pn=1' \ +-b 'SESSDATA=xxx;DedeUserID=1;' +``` + +共计创建了两个歌单,如下 + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "data": { + "curPage": 1, + "pageCount": 1, + "totalSize": 2, + "pageSize": 2, + "data": [ + { + "id": 15967839, + "uid": 293793435, + "uname": "社会易姐QwQ", + "title": "默认歌单", + "type": 1, + "published": 1, + "cover": "http://i0.hdslb.com/bfs/music/1e079693701d2f525850c288fcc48fa4259a73f6.jpg", + "ctime": 1519295502, + "song": 13, + "desc": "", + "sids": [ + 11673, + 276404, + 15664, + 737904, + 108588, + 1286999, + 658085, + 682118, + 736952, + 48716, + 15711, + 13598, + 57744 + ], + "menuId": 15958713, + "statistic": { + "sid": 15958713, + "play": 0, + "collect": 0, + "comment": null, + "share": 0 + } + }, + { + "id": 30894022, + "uid": 293793435, + "uname": "社会易姐QwQ", + "title": "test", + "type": 0, + "published": 1, + "cover": "", + "ctime": 1590154346, + "song": 0, + "desc": "test1", + "sids": [], + "menuId": 30866686, + "statistic": { + "sid": 30866686, + "play": 0, + "collect": 0, + "comment": 0, + "share": 0 + } + } + ] + } +} +``` + +</details> + +## 查询音频收藏夹(默认歌单)信息 + +> https://www.bilibili.com/audio/music-service-c/web/collections/info + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +鉴权方式:Cookie中`DedeUserID`存在且不为0 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------ | ------ | ------------------ | +| sid | num | 音频收藏夹mlid | 必要 | 必须为默认收藏夹mlid | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ----------------------------- | -------- | ----------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />72000000:参数错误<br />72010002:未登录 | +| msg | str | 错误信息 | 默认为success | +| data | 正确时:obj<br />错误时:null | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ------ | ------------------------ | ---------------------- | +| id | num | 音频收藏夹mlid | | +| uid | num | 创建用户mid | | +| uname | str | 创建用户昵称 | | +| title | str | 默认歌单 | 恒为`默认歌单` | +| type | num | 1 | 恒为`1` | +| published | num | 是否公开 | 0:不公开<br />1:公开 | +| cover | str | 歌单封面图片url | | +| ctime | num | 歌单创建时间 | 时间戳 | +| song | num | 歌单中的音乐数量 | | +| desc | str | 空 | 恒为空 | +| sids | array | 歌单中的音乐 | | +| menuId | num | 音频收藏夹对应的歌单amid | 与普通歌单不同通用 | +| statistic | obj | 歌单状态数信息 | | + +`data`中的`sids`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------------- | ---------------- | +| 0 | num | 收藏的音频auid1 | | +| n | num | 收藏的音频auid(n+1) | 按照歌单顺序排列 | +| …… | num | …… | …… | + +`data`中的`statistic`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ------------------------ | ---- | +| sid | num | 音频收藏夹对应的歌单amid | | +| play | num | 0 | | +| collect | num | 0 | | +| comment | null | - | | +| share | num | 0 | | + +**示例:** + +查询我的默认歌单,id为` 15967839 ` + +```shell +curl -G 'https://www.bilibili.com/audio/music-service-c/web/collections/info' \ +--data-urlencode 'sid=15967839 ' \ +-b 'SESSDATA=xxx;DedeUserID=1;' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "data": { + "id": 15967839, + "uid": 293793435, + "uname": "社会易姐QwQ", + "title": "默认歌单", + "type": 1, + "published": 1, + "cover": "http://i0.hdslb.com/bfs/music/1e079693701d2f525850c288fcc48fa4259a73f6.jpg", + "ctime": 1519295502, + "song": 13, + "desc": "", + "sids": [ + 11673, + 276404, + 15664, + 737904, + 108588, + 1286999, + 658085, + 682118, + 736952, + 48716, + 15711, + 13598, + 57744 + ], + "menuId": 15958713, + "statistic": { + "sid": 15958713, + "play": 0, + "collect": 0, + "comment": null, + "share": 0 + } + } +} +``` + +</details> + + +## 查询热门歌单 + +> https://www.bilibili.com/audio/music-service-c/web/menu/hit + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --- | --- | ---- | --- | --- | +| pn | num | 页码 | 必要 | | +| ps | num | 每页项数 | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | --------------------- | ---- | ----------------------------------------- | +| code | num | 返回值 | 0:成功<br />72000000:参数错误<br />72010002:未登录 | +| msg | str | 错误信息 | 默认为success | +| data | 正确时:obj<br />错误时:null | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | ------ | --- | +| curPage | num | 当前页码 | | +| pageCount | num | 总计页数 | | +| totalSize | num | 总计收藏夹数 | | +| pageSize | num | 当前页面项数 | | +| data | array | 歌单列表 | | + +`data`中的`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | --- | -------------- | --- | +| 0 | obj | 音频收藏夹mlid1 | | +| n | obj | 音频收藏夹mlid(n+1) | | +| …… | obj | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | --- | -------------- | ----------------------------- | +| menuId | num | 音频收藏夹对应的歌单amid | | +| uid | num | 创建用户mid | | +| uname | str | 创建用户昵称 | | +| title | str | 歌单标题 | | +| cover | str | 歌单封面图片url | | +| intro | str | 歌单介绍 | | +| type | num | 歌单属性 | 1:普通歌单<br/>2:置顶歌单<br/>5:PGC歌单 | +| off | num | 歌单是否公开 | 0:公开<br/>1:私密 | +| ctime | num | 歌单创建时间 | 时间戳 | +| curtime | num | 当前时间 | 时间戳 | +| statistic | obj | 歌单状态数信息 | | +| snum | num | 歌单包含歌曲个数 | | + +`data`中的`statistic`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | --- | -------------- | --- | +| sid | num | 音频收藏夹对应的歌单amid | | +| play | num | 播放数 | | +| collect | num | 收藏数 | | +| comment | num | 评论数 | | +| share | num | 分享数 | | + +**示例:** + +```shell +curl -G 'https://www.bilibili.com/audio/music-service-c/web/menu/hit' \ + +--data-urlencode 'ps=1' \ + +--data-urlencode 'pn=6' +``` + +使用参数:`ps=1&qn=2` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "data": { + "curPage": 1, + "pageCount": 1, + "totalSize": 11, + "pageSize": 3, + "data": [{ + "menuId": 10624, + "uid": 32708543, + "uname": "大家的音乐姬", + "title": "新曲推荐", + "cover": "http://i0.hdslb.com/bfs/music/a32c1ed4f6ec3f74f8240f4486a750dda3a509e5.jpg", + "intro": "每天11:00更新,为你推送最新音乐", + "type": 2, + "off": 0, + "ctime": 1501209433, + "curtime": 1655712354, + "statistic": { + "sid": 10624, + "play": 2366255, + "collect": 20565, + "comment": 1104, + "share": 622 + }, + "snum": 16, + "attr": 0, + "isDefault": 0, + "collectionId": 0 + }, { + "menuId": 125312, + "uid": 32708543, + "uname": "大家的音乐姬", + "title": "丧甜可口?你意想不到的软萌电音", + "cover": "http://i0.hdslb.com/bfs/music/04f6c29ed094368253bc05fecb7bf990cee2d3a3.jpg", + "intro": "这个化学反应是怦然心动?", + "type": 1, + "off": 0, + "ctime": 1533298738, + "curtime": 1655712354, + "statistic": { + "sid": 125312, + "play": 298018, + "collect": 9928, + "comment": 89, + "share": 239 + }, + "snum": 19, + "attr": 0, + "isDefault": 0, + "collectionId": 0 + }, { + "menuId": 26241, + "uid": 32708543, + "uname": "大家的音乐姬", + "title": "那些听了会泪目的动漫歌曲", + "cover": "http://i0.hdslb.com/bfs/music/006832318fc85fdf287667d51d83dba3b78be808.jpg", + "intro": "那些年陪伴我们的动漫歌曲,你还记得吗?\n", + "type": 1, + "off": 0, + "ctime": 1509608572, + "curtime": 1655712354, + "statistic": { + "sid": 26241, + "play": 370120, + "collect": 8390, + "comment": 110, + "share": 131 + }, + "snum": 12, + "attr": 0, + "isDefault": 0, + "collectionId": 0 + }] + } +} +``` + +</details> + +## 查询热门榜单 + +> https://www.bilibili.com/audio/music-service-c/web/menu/rank + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --- | --- | ---- | --- | --- | +| pn | num | 页码 | 必要 | | +| ps | num | 每页项数 | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | --------------------- | ---- | ----------------------------------------- | +| code | num | 返回值 | 0:成功<br />72000000:参数错误<br />72010002:未登录 | +| msg | str | 错误信息 | 默认为success | +| data | 正确时:obj<br />错误时:null | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | ------ | --- | +| curPage | num | 当前页码 | | +| pageCount | num | 总计页数 | | +| totalSize | num | 总计收藏夹数 | | +| pageSize | num | 当前页面项数 | | +| data | array | 歌单列表 | | + +`data`中的`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | --- | -------------- | --- | +| 0 | obj | 音频收藏夹mlid1 | | +| n | obj | 音频收藏夹mlid(n+1) | | +| …… | obj | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | -------------- | ----------------------------- | +| menuId | num | 音频收藏夹对应的歌单amid | | +| uid | num | 创建用户mid | | +| uname | str | 创建用户昵称 | | +| title | str | 歌单标题 | | +| cover | str | 歌单封面图片url | | +| intro | str | 歌单介绍 | | +| type | num | 歌单属性 | 1:普通歌单<br/>2:置顶歌单<br/>5:PGC歌单 | +| off | num | 歌单是否公开 | 0:公开<br/>1:私密 | +| ctime | num | 歌单创建时间 | 时间戳 | +| curtime | num | 当前时间 | 时间戳 | +| statistic | obj | 歌单状态数信息 | | +| snum | num | 歌单包含歌曲个数 | | +| audios | array | 歌单中的音乐信息(部分) | | + +`data`数组中的`statistic`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | --- | -------------- | --- | +| sid | num | 音频收藏夹对应的歌单amid | | +| play | num | 收藏数 | | +| collect | num | 点赞数 | | +| comment | num | 评论数 | | +| share | num | 分享数 | | + +`data`数组中的`audios`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | --- | ------- | --- | +| 0 | obj | 音频1 | | +| n | obj | 音频(n+1) | | +| …… | obj | …… | …… | + +`audios`数组中的`audios`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | --- | ---- | ------- | +| id | num | 音频id | | +| title | str | 音频标题 | | +| duration | num | 音频时长 | 单位:秒(s) | + + + +**示例:** + +```shell +curl -G 'https://www.bilibili.com/audio/music-service-c/web/menu/rank' \ + +--data-urlencode 'ps=1' \ + +--data-urlencode 'pn=6' +``` + +使用参数:`ps=1&qn=6` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "data": { + "curPage": 1, + "pageCount": 2, + "totalSize": 12, + "pageSize": 6, + "data": [{ + "menuId": 10624, + "uid": 32708543, + "uname": "大家的音乐姬", + "title": "新曲推荐", + "cover": "http://i0.hdslb.com/bfs/music/a32c1ed4f6ec3f74f8240f4486a750dda3a509e5.jpg", + "intro": "每天11:00更新,为你推送最新音乐", + "type": 2, + "off": 0, + "ctime": 1501209433, + "curtime": 1655713346, + "statistic": { + "sid": 10624, + "play": 2366255, + "collect": 20565, + "comment": 1104, + "share": 622 + }, + "snum": 16, + "attr": 0, + "isDefault": 0, + "collectionId": 0, + "audios": [{ + "id": 1572281, + "title": "【Mitchie M】Nechusho No!No! (feat. 初音未来 & MEIKO)", + "duration": 112 + }, { + "id": 1551077, + "title": "【洛天依原创】双星伴生", + "duration": 197 + }, { + "id": 1544428, + "title": "【小柔】寄り酔い(cover)", + "duration": 216 + }] + }, { + "menuId": 10627, + "uid": 32708543, + "uname": "大家的音乐姬", + "title": "热歌榜(每日11:00更新)", + "cover": "http://i0.hdslb.com/bfs/music/bc735b32ab123f7ddc602b9194defae2cd66062f.jpg", + "intro": "每日上午11:00更新,精选三日内热门投稿作品。", + "type": 2, + "off": 0, + "ctime": 1501211353, + "curtime": 1655713346, + "statistic": { + "sid": 10627, + "play": 2289612, + "collect": 11437, + "comment": 434, + "share": 223 + }, + "snum": 20, + "attr": 0, + "isDefault": 0, + "collectionId": 0, + "audios": [{ + "id": 1955567, + "title": "山海(原唱:草东没有派对)", + "duration": 215 + }, { + "id": 923884, + "title": "platiunm", + "duration": 181 + }, { + "id": 1954370, + "title": "Dark Dawn v1", + "duration": 200 + }] + }, { + "menuId": 10628, + "uid": 32708543, + "uname": "大家的音乐姬", + "title": "原创榜(每日11:00更新)", + "cover": "http://i0.hdslb.com/bfs/music/58782504cefb307878d12422fd365ed7f971fad1.jpg", + "intro": "每日上午11:00更新,精选三日内原创投稿音乐。", + "type": 2, + "off": 0, + "ctime": 1501211627, + "curtime": 1655713346, + "statistic": { + "sid": 10628, + "play": 395817, + "collect": 2583, + "comment": 314, + "share": 88 + }, + "snum": 20, + "attr": 0, + "isDefault": 0, + "collectionId": 0, + "audios": [{ + "id": 923884, + "title": "platiunm", + "duration": 181 + }, { + "id": 1954370, + "title": "Dark Dawn v1", + "duration": 200 + }, { + "id": 1954654, + "title": "张真源 - 你要快乐 (Live)", + "duration": 235 + }] + }, { + "menuId": 10629, + "uid": 32708543, + "uname": "大家的音乐姬", + "title": "中文人声三日榜", + "cover": "http://i0.hdslb.com/bfs/music/f547e3b96d3f283eaa6a3a071de22092fb5101f8.jpg", + "intro": "每日上午11:00更新,精选三日内中文人声投稿音乐。", + "type": 2, + "off": 0, + "ctime": 1501211818, + "curtime": 1655713346, + "statistic": { + "sid": 10629, + "play": 842507, + "collect": 5102, + "comment": 362, + "share": 137 + }, + "snum": 20, + "attr": 0, + "isDefault": 0, + "collectionId": 0, + "audios": [{ + "id": 1955567, + "title": "山海(原唱:草东没有派对)", + "duration": 215 + }, { + "id": 1955546, + "title": "爱你", + "duration": 86 + }, { + "id": 1954654, + "title": "张真源 - 你要快乐 (Live)", + "duration": 235 + }] + }, { + "menuId": 10630, + "uid": 32708543, + "uname": "大家的音乐姬", + "title": "日文人声三日榜", + "cover": "http://i0.hdslb.com/bfs/music/7dd5d629f50481e22e2f5eced510f5fbd89f5233.jpg", + "intro": "每日上午11:00更新,精选三日内日文人声投稿音乐。", + "type": 2, + "off": 0, + "ctime": 1501211959, + "curtime": 1655713346, + "statistic": { + "sid": 10630, + "play": 891268, + "collect": 8671, + "comment": 601, + "share": 169 + }, + "snum": 20, + "attr": 0, + "isDefault": 0, + "collectionId": 0, + "audios": [{ + "id": 1954053, + "title": "派对浪客诸葛孔明 插入歌『ChocoPate』久远七海 starring Lezel", + "duration": 117 + }, { + "id": 1956316, + "title": "ただ君に晴れ(只给予你的晴天)", + "duration": 196 + }, { + "id": 1956321, + "title": "うまぴょい伝説(马儿蹦跳传说)", + "duration": 262 + }] + }, { + "menuId": 10631, + "uid": 32708543, + "uname": "大家的音乐姬", + "title": "VOCALOID三日榜", + "cover": "http://i0.hdslb.com/bfs/music/ce8b1646cbbd5513de7976ba81d0fd9c340c1899.jpg", + "intro": "每日上午11:00更新,精选三日内VOCALOID投稿音乐。", + "type": 2, + "off": 0, + "ctime": 1501212166, + "curtime": 1655713346, + "statistic": { + "sid": 10631, + "play": 170112, + "collect": 2900, + "comment": 528, + "share": 60 + }, + "snum": 10, + "attr": 0, + "isDefault": 0, + "collectionId": 0, + "audios": [{ + "id": 1954717, + "title": "弦歌引-翻调", + "duration": 230 + }, { + "id": 1956148, + "title": "告RADIO - 春色リップ", + "duration": 253 + }, { + "id": 1954302, + "title": "susan说", + "duration": 195 + }] + }] + } +} +``` + +</details> diff --git a/bb-api-collect/docs/audio/musicstream_url.md b/bb-api-collect/docs/audio/musicstream_url.md new file mode 100644 index 0000000000..26f9c2c1dd --- /dev/null +++ b/bb-api-collect/docs/audio/musicstream_url.md @@ -0,0 +1,279 @@ +# 音频流URL + +<img src="../../assets/img/download.svg" width="100" height="100"/> + +## 音质qn参数定义 + +音质`qn`参数: + +| 代码 | 含义 | +| ---- | -------------------- | +| 0 | 流畅 128K | +| 1 | 标准 192K | +| 2 | 高品质 320K | +| 3 | 无损 FLAC (大会员) | + +## 获取音频流URL(web端) + +> https://www.bilibili.com/audio/music-service-c/web/url + +*请求方式:GET* + +**注:web端无法播放完整付费歌曲,付费歌曲为30s试听片段** + +本接口仅能获取192K音质的音频 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| sid | num | 音频auid | 必要 | | +| quality | num | 2 | 不必要 | | +| privilege | num | 2 | 不必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ----------------------------------------------------------- | +| code | num | 返回值 | 0: 成功<br />4511006: 已跳过无法播放的歌曲<br />7201006:未找到或已下架<br />72000000:请求错误 | +| message | str | 返回值 | 字符串形式的 code | +| msg | str | 返回信息 | 成功为 success | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | --------- | --------------------------------------- | +| sid | num | 音频auid | | +| type | num | 音质标识 | -1:试听片段(192K)<br />1:192K | +| info | str | 空 | | +| timeout | num | 有效时长 | 单位为秒<br />一般为3h | +| size | num | 文件大小 | 单位为字节<br />当`type`为-1时`size`为0 | +| cdns | array | 音频流url | | +| qualities | null | | | +| title | str | 空 | | +| cover | str | 空 | | + +`data`对象的`cdns`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---- | +| 0 | str | 音频流url | | +| 1 | str | 备用音频流url | 可能不存在 | + +**示例:** + +```shell +curl -G 'https://www.bilibili.com/audio/music-service-c/web/url' \ +--data-urlencode 'sid=777180' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "sid": 777180, + "title": "", + "cover": "", + "type": 1, + "info": "", + "timeout": 10800, + "size": 5579903, + "cdns": [ + "https://upos-sz-mirrorcos.bilivideo.com/ugaxcode/m190314ws1dikiap1oivtapctuj1agjc-192k.m4a?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1725013547&gen=playurlv2&os=cosbv&oi=1746706124&trid=493923009cef4225ab8e1b9bda42c635B&mid=0&platform=pc&og=cos&upsig=043779511e2770cf6c3da04ed8a89f25&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform,og&bvc=vod&nettype=0&orderid=0,1&logo=00000000" + ], + "qualities": null + }, + "message": "0", + "msg": "success" +} +``` + +</details> + +## 获取音频流URL(可获取付费音频) + +> https://api.bilibili.com/audio/music-service-c/url + +*请求方式:GET* + +认证方式:APP或Cookie(SESSDATA) + +**注:付费音乐需要有带大会员或音乐包的账号登录(Cookie或APP),否则为试听片段** + +无损音质需要登录的用户为会员 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | -------------- | +| access_key | str | APP登录Token | APP方式必要 | | +| songid | num | 音频auid | 必要 | | +| quality | num | 音质代码 | 必要 | **详情见上表** | +| privilege | num | 必须为`2` | 必要 | | +| mid | num | 当前用户mid | 必要 | 可为任意值 | +| platform | str | 平台标识 | 必要 | 可为任意值 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ----------------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />7201006:未找到或已下架<br />72000000:请求错误 | +| msg | str | 错误信息 | 默认为success | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | ----------- | ------------------------------------------------------------ | +| sid | num | 音频auid | | +| type | num | 音质标识 | -1:试听片段(192K)<br />0:128K<br />1:192K<br />2:320K<br />3:FLAC | +| info | str | 空 | **作用尚不明确** | +| timeout | num | 有效时长 | 单位为秒<br />一般为3h | +| size | num | 文件大小 | 单位为字节<br />当`type`为-1时`size`为0 | +| cdns | array | 音频流url | | +| qualities | array | 音质列表 | | +| title | str | 音频标题 | | +| cover | str | 音频封面url | | + +`data`对象的`cdns`数组: + + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---- | +| 0 | str | 音频流url | | +| 1 | str | 备用音频流url | | + +`data`对象的`qualities`数组: + + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---------------- | +| 0 | obj | 音质1 | 音质由高向低顺序 | +| n | obj | 音质(n+1) | | + +`qualities`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ---------------- | ---------------------- | +| type | num | 音质代码 | **详情见上表** | +| desc | str | 音质名称 | | +| size | num | 该音质的文件大小 | 单位为字节 | +| bps | str | 比特率标签 | | +| tag | str | 音质标签 | | +| require | num | 是否需要会员权限 | 0:不需要<br />1:需要 | +| requiredesc | str | 会员权限标签 | | + +**示例:** + +获取音频`au682118`的音频流url,音质为`3(无损)` + +Cookie方式: + +```shell +curl -G 'https://api.bilibili.com/audio/music-service-c/url' \ +--data-urlencode 'songid=682118' \ +--data-urlencode 'quality=3' \ +--data-urlencode 'privilege=2' \ +--data-urlencode 'platform=android' \ +--data-urlencode 'mid=293793435' \ +-b 'SESSDATA=xxx' +``` + +APP方式: + +```shell +curl -G 'https://api.bilibili.com/audio/music-service-c/url' \ +--data-urlencode 'access_key=xxx' \ +--data-urlencode 'songid=682118' \ +--data-urlencode 'quality=3' \ +--data-urlencode 'privilege=2' \ +--data-urlencode 'platform=android' \ +--data-urlencode 'mid=293793435' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "data": { + "sid": 682118, + "type": 3, + "info": "", + "timeout": 10800, + "size": 34456494, + "cdns": [ + "https://upos-sz-mirrorkodo.bilivideo.com/ugaxcode/m190102ws2pzf6jitbem841vq2x0du5x-flac.flac?deadline=1595332269&gen=uga&os=kodobv&uparams=deadline,gen,os&upsig=ac2284d97a61ef8758681eccf621c56d", + "https://upos-sz-mirrorks3.bilivideo.com/ugaxcode/m190102ws2pzf6jitbem841vq2x0du5x-flac.flac?deadline=1595332269&gen=uga&os=ks3bv&uparams=deadline,gen,os&upsig=3ac7d94dda5664f6f95dbfffeb289744" + ], + "qualities": [ + { + "type": 3, + "desc": "无损音质", + "size": 34456494, + "bps": "", + "tag": "SQ", + "require": 1, + "requiredesc": "付费享受" + }, + { + "type": 2, + "desc": "高品质", + "size": 10788682, + "bps": "320kbit/s", + "tag": "HQ", + "require": 0, + "requiredesc": "" + }, + { + "type": 1, + "desc": "标准", + "size": 6491973, + "bps": "192kbit/s", + "tag": "", + "require": 0, + "requiredesc": "" + }, + { + "type": 0, + "desc": "流畅", + "size": 4343667, + "bps": "128kbit/s", + "tag": "", + "require": 0, + "requiredesc": "" + } + ], + "title": "aLIEz", + "cover": "http://i0.hdslb.com/bfs/music/61d3f8cfdce14d2d1b006af59559c9bd22a2d21b.jpg" + } +} +``` + +</details> + +## 音频流的获取 + +将 `data.cdns[n]` 作为 URL 进行 GET 操作 + +需要验证请求头 `User-Agent` 不为空且不含敏感字串, 且 `Referer` 必须在 `.bilibili.com` 下 + +**示例:** + +使用 cURL + FFPlay 直接从音频流播放 + +```shell +curl -G "https://upos-sz-mirrorcos.bilivideo.com/ugaxcode/7bf6a3a3e94421ccc653f005457b1e8c-192k.m4a?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1725013121&gen=playurlv2&os=cosbv&oi=1823807031&trid=1a4703f1e7344bb891691c5857e8cfb9B&mid=0&platform=pc&og=cos&upsig=e3a9fba59b46ab2720c8b1807844e9f3&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform,og&bvc=vod&nettype=0&orderid=0,1&logo=00000000" \ +--referer 'https://www.bilibili.com/' -A 'Mozilla/5.0' \ +--output - | ffplay - +``` diff --git a/bb-api-collect/docs/audio/rank.md b/bb-api-collect/docs/audio/rank.md new file mode 100644 index 0000000000..ff2a809058 --- /dev/null +++ b/bb-api-collect/docs/audio/rank.md @@ -0,0 +1,1160 @@ +# 音频榜单 + +以下接口均来自页面 https://music.bilibili.com/pc/rank + +## 获取音频榜单每期列表 + +> https://api.bilibili.com/x/copyright-music-publicity/toplist/all_period + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | ------------------------ | ------ | ---------------------- | +| list_type | num | 榜单类型 | 必要 | 1:热榜<br />2:原创榜 | +| csrf | str | CSRF Token(位于cookie) | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| list | obj | 年份索引 | | + +`data`中的`list`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ----- | ---------------------- | ---- | +| {年份} | array | 对应年份索引的每期信息 | | +| …… | array | …… | | + +`list`中的`{年份}`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------------- | ---- | +| 0 | obj | 该年中的单期数据 | | +| …… | obj | …… | …… | + +`{年份}`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | -------- | -------- | +| ID | num | 榜单 id | | +| priod | num | 榜单期数 | | +| publish_time | num | 发布时间 | 秒时间戳 | + +**示例:** + +```bash +curl -G 'https://api.bilibili.com/x/copyright-music-publicity/toplist/all_period' \ + --data-urlencode 'list_type=1' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": { + "2022": [ + { + "ID": 38, + "priod": 29, + "publish_time": 1672394399 + }, + { + "ID": 36, + "priod": 28, + "publish_time": 1671789599 + }, + { + "ID": 34, + "priod": 27, + "publish_time": 1671184800 + }, + { + "ID": 32, + "priod": 26, + "publish_time": 1670579999 + }, + { + "ID": 30, + "priod": 25, + "publish_time": 1669976540 + }, + { + "ID": 28, + "priod": 24, + "publish_time": 1669370757 + }, + { + "ID": 26, + "priod": 23, + "publish_time": 1668766987 + }, + { + "ID": 22, + "priod": 22, + "publish_time": 1668163419 + }, + { + "ID": 21, + "priod": 21, + "publish_time": 1667558276 + }, + { + "ID": 20, + "priod": 20, + "publish_time": 1666951199 + }, + { + "ID": 19, + "priod": 19, + "publish_time": 1666346399 + }, + { + "ID": 18, + "priod": 18, + "publish_time": 1665741599 + }, + { + "ID": 17, + "priod": 17, + "publish_time": 1665136799 + }, + { + "ID": 16, + "priod": 16, + "publish_time": 1664531999 + }, + { + "ID": 15, + "priod": 15, + "publish_time": 1663927199 + }, + { + "ID": 14, + "priod": 14, + "publish_time": 1663322399 + }, + { + "ID": 13, + "priod": 13, + "publish_time": 1662717599 + }, + { + "ID": 12, + "priod": 12, + "publish_time": 1662113559 + }, + { + "ID": 11, + "priod": 11, + "publish_time": 1661508657 + }, + { + "ID": 10, + "priod": 10, + "publish_time": 1660903199 + }, + { + "ID": 9, + "priod": 9, + "publish_time": 1660298400 + }, + { + "ID": 8, + "priod": 8, + "publish_time": 1659693599 + }, + { + "ID": 7, + "priod": 7, + "publish_time": 1659088799 + }, + { + "ID": 6, + "priod": 6, + "publish_time": 1658483999 + }, + { + "ID": 5, + "priod": 5, + "publish_time": 1657879200 + }, + { + "ID": 4, + "priod": 4, + "publish_time": 1657274399 + }, + { + "ID": 3, + "priod": 3, + "publish_time": 1656669600 + }, + { + "ID": 2, + "priod": 2, + "publish_time": 1656064800 + }, + { + "ID": 1, + "priod": 1, + "publish_time": 1655460091 + } + ], + "2023": [ + { + "ID": 76, + "priod": 48, + "publish_time": 1683885696 + }, + { + "ID": 74, + "priod": 47, + "publish_time": 1683281010 + }, + { + "ID": 72, + "priod": 46, + "publish_time": 1682675999 + }, + { + "ID": 70, + "priod": 45, + "publish_time": 1682071442 + }, + { + "ID": 68, + "priod": 44, + "publish_time": 1681466400 + }, + { + "ID": 66, + "priod": 43, + "publish_time": 1680861599 + }, + { + "ID": 64, + "priod": 42, + "publish_time": 1680256799 + }, + { + "ID": 62, + "priod": 41, + "publish_time": 1679652088 + }, + { + "ID": 60, + "priod": 40, + "publish_time": 1679047199 + }, + { + "ID": 58, + "priod": 39, + "publish_time": 1678442399 + }, + { + "ID": 56, + "priod": 38, + "publish_time": 1677837600 + }, + { + "ID": 54, + "priod": 37, + "publish_time": 1677232800 + }, + { + "ID": 52, + "priod": 36, + "publish_time": 1676628000 + }, + { + "ID": 50, + "priod": 35, + "publish_time": 1676023199 + }, + { + "ID": 48, + "priod": 34, + "publish_time": 1675418399 + }, + { + "ID": 46, + "priod": 33, + "publish_time": 1674813599 + }, + { + "ID": 44, + "priod": 32, + "publish_time": 1674208799 + }, + { + "ID": 42, + "priod": 31, + "publish_time": 1673603999 + }, + { + "ID": 40, + "priod": 30, + "publish_time": 1672999199 + } + ] + } + } +} +``` + +</details> + +## 查询音频榜单单期信息 + +> https://api.bilibili.com/x/copyright-music-publicity/toplist/detail + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | ------------------------ | ------ | ------------------------------------------------ | +| list_id | num | 榜单 id | 必要 | 见 [获取音频榜单每期列表](#获取音频榜单每期列表) | +| csrf | str | CSRF Token(位于cookie) | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ----------------------- | ------------------------------------------------------------ | +| listen_fid | num | 畅听版歌单收藏夹原始 id | 非真实收藏夹 mlid<br />需要在后方拼接用户 mid 的后两位,如`16484498`->`1648449844` | +| all_fid | num | 完整版歌单收藏夹原始 id | 非真实收藏夹 mlid<br />算法同上 | +| fav_mid | num | 绑定收藏夹用户的 mid | 例如`1164440244`([音乐热榜bot](https://space.bilibili.com/1164440244)账号) | +| cover_url | str | 榜单封面 url | | +| is_subscribe | bool | 是否已订阅榜单 | `true`:已订阅<br />`false`:未订阅<br />需要登录(Cookie 或 APP),未登录恒为`false` | +| listen_count | num | 平台有版权音频的数量 | | + +**示例:** + +查询 [第 48 期音频榜单](https://music.bilibili.com/pc/rank?list_id=76)(id=76) 信息 + +```bash +curl -G 'https://api.bilibili.com/x/copyright-music-publicity/toplist/detail' \ + --data-urlencode 'list_id=76' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "listen_fid": 23317138, + "all_fid": 23672948, + "fav_mid": 1164440244, + "cover_url": "http://i0.hdslb.com/bfs/music-publicity/d8509dc6ee94dd5cc4658a2cbca4f525b4396df5.png", + "is_subscribe": false, + "listen_count": 5 + } +} +``` + +</details> + +## 获取音频榜单单期内容 + +> https://api.bilibili.com/x/copyright-music-publicity/toplist/music_list + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | ------------------------ | ------ | ------------------------------------------------ | +| list_id | num | 榜单 id | 必要 | 见 [获取音频榜单每期列表](#获取音频榜单每期列表) | +| csrf | str | CSRF Token(位于cookie) | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ----- | -------- | ---- | +| list | array | 内容列表 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | ---- | +| 0 | obj | 榜单内容 1 | | +| n | obj | 榜单内容 (n+1) | | +| …… | obj | …… | …… | + +`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ----- | ------------------ | ------------------------------------------- | +| music_id | str | 音频 MAID | 例如`MA409252256362326366` | +| music_title | str | 音频标题 | | +| singer | str | 音频作者 | | +| album | str | 音频专辑 | | +| mv_aid | num | 音频 MV 的 avid | 若该音频无 MV 则该字段为 0 | +| mv_bvid | str | 音频 MV 的 bvid | | +| mv_cover | str | 音频封面 url | | +| heat | num | 热度值 | | +| rank | num | 排序值 | 1 为最高排序,DESC 方式 | +| can_listen | bool | 平台是否有版权 | `true`:平台有版权<br />`false`:平台无版权 | +| recommendation | str | (?) | | +| creation_aid | num | 关联稿件 avid | | +| creation_bvid | str | 关联稿件 bvid | | +| creation_cover | str | 关联稿件封面 url | | +| creation_title | str | 关联稿件标题 | | +| creation_up | num | 关联稿件 UP 主 mid | | +| creation_nickname | str | 关联稿件 UP 主昵称 | | +| creation_duration | num | 关联稿件时长 | 单位为秒 | +| creation_play | num | 关联稿件播放量 | | +| creation_reason | str | 关联稿件二级分区名 | | +| achievements | array | 获得成就 | | +| material_id | num | (?) | | +| material_use_num | num | (?) | | +| material_duration | num | (?) | | +| material_show | num | (?) | | +| song_type | num | (?) | | + +`list`数组中的对象中的`achievements`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | ---- | +| 0 | str | 成就文案 1 | | +| n | str | 成就文案 (n+1) | | +| …… | str | …… | …… | + +**示例:** + +查询 [第 48 期音频榜单](https://music.bilibili.com/pc/rank?list_id=76)(id=76) 榜单内容列表 + +```bash +curl -G 'https://api.bilibili.com/x/copyright-music-publicity/toplist/music_list' \ + --data-urlencode 'list_id=76' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "music_id": "MA409252256362326366", + "music_title": "極楽浄土", + "singer": "GARNiDELiA", + "album": "約束 -Promise code-", + "mv_aid": 28361833, + "mv_bvid": "BV1us41137Fd", + "mv_cover": "https://i0.hdslb.com/bfs/station_src/music_metadata/07e0d9826c574e37df25387cab6df062.jpg", + "heat": 5328979, + "rank": 1, + "can_listen": true, + "recommendation": "", + "creation_aid": 910787823, + "creation_bvid": "BV1HM4y1b79Z", + "creation_cover": "http://i1.hdslb.com/bfs/archive/5780a05437ec9880301ed093537d6af97b0f8bdb.jpg", + "creation_title": "【MARiA】乘风2023初舞台!《极乐净土》,虽迟但到!", + "creation_up": 110352985, + "creation_nickname": "GARNiDELiA", + "creation_duration": 100, + "creation_play": 13487670, + "creation_reason": "官方现场", + "achievements": [ + "重回榜单", + "最高排名1" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA456045402056087707", + "music_title": "アイドル", + "singer": "YOASOBI", + "album": "アイドル", + "mv_aid": 227499491, + "mv_bvid": "BV17h411u7sb", + "mv_cover": "http://i0.hdslb.com/bfs/station_src/music_metadata/4bf2fe90e9d2361c3c4ddf59064c6e69.jpg", + "heat": 1856277, + "rank": 2, + "can_listen": false, + "recommendation": "", + "creation_aid": 952765045, + "creation_bvid": "BV1Ws4y1A7fS", + "creation_cover": "http://i0.hdslb.com/bfs/archive/8326350bab039ffee9274d7e1f94240d170fa096.jpg", + "creation_title": "【中文字幕】我推的孩子「アイドル」官方MV(4K 60帧/Hi-Res)", + "creation_up": 11585165, + "creation_nickname": "爱莉丝青贝尔克", + "creation_duration": 226, + "creation_play": 3742892, + "creation_reason": "音乐MV", + "achievements": [ + "本期排名持平", + "最高排名1" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA458652518440821364", + "music_title": "野火wildfire", + "singer": "HOYO- Mix,Jonathan Steingard", + "album": "雪融于烬", + "mv_aid": 0, + "mv_bvid": "", + "mv_cover": "https://i0.hdslb.com/bfs/station_src/music_metadata/e0825a2cfee22ce77f02d4d80826a1d9.jpg", + "heat": 1767135, + "rank": 3, + "can_listen": false, + "recommendation": "", + "creation_aid": 355732312, + "creation_bvid": "BV1ZX4y117Dx", + "creation_cover": "http://i0.hdslb.com/bfs/archive/c98bd629876e8b7b4c056d39bcfeaabe7327e996.jpg", + "creation_title": "这首“野火”神曲,我还能再听亿遍!!!", + "creation_up": 394861137, + "creation_nickname": "Hanserのcece", + "creation_duration": 219, + "creation_play": 2158925, + "creation_reason": "动画创作", + "achievements": [ + "本期排名↑1", + "最高排名3" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA459088929228874460", + "music_title": "不问别离", + "singer": "指尖笑", + "album": "不问别离", + "mv_aid": 0, + "mv_bvid": "", + "mv_cover": "http://i0.hdslb.com/bfs/station_src/music_metadata/b1507c1649500a0dcf0295b4b68e4b15.jpg", + "heat": 1576823, + "rank": 4, + "can_listen": false, + "recommendation": "", + "creation_aid": 740818022, + "creation_bvid": "BV1Sk4y1E7qH", + "creation_cover": "http://i2.hdslb.com/bfs/archive/5301b2fee7ad520c8946b5eb92888cf8be563a80.jpg", + "creation_title": "日推歌单 | \"我叹那春花秋月不问别离 长风起孤城笛声里全是你\" |《不问ciaga》", + "creation_up": 550445292, + "creation_nickname": "peach63", + "creation_duration": 164, + "creation_play": 274898, + "creation_reason": "音乐MV", + "achievements": [ + "本期排名↑10", + "最高排名4" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA459819223808501000", + "music_title": "Spicy", + "singer": "aespa", + "album": "MY WORLD - The 3rd Mini Album", + "mv_aid": 570920682, + "mv_bvid": "BV1qz4y1a7m8", + "mv_cover": "http://i0.hdslb.com/bfs/station_src/music_metadata/6455687e7d72dd838ffd2aa753fd7761.jpg", + "heat": 1441365, + "rank": 5, + "can_listen": false, + "recommendation": "", + "creation_aid": 570920682, + "creation_bvid": "BV1qz4y1a7m8", + "creation_cover": "http://i2.hdslb.com/bfs/archive/cd5456735bd645343a51b8df9b4a91236b08e657.jpg", + "creation_title": "aespa《Spicy》MV", + "creation_up": 3493085782739496, + "creation_nickname": "SMTOWN", + "creation_duration": 205, + "creation_play": 2363321, + "creation_reason": "官方MV", + "achievements": [ + "新晋上榜", + "最高排名5" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA458946536466866804", + "music_title": "UNFORGIVEN (feat. Nile Rodgers)", + "singer": "LE SSERAFIM,Nile Rodgers", + "album": "UNFORGIVEN", + "mv_aid": 528370662, + "mv_bvid": "BV1LM41137Pc", + "mv_cover": "http://i0.hdslb.com/bfs/station_src/music_metadata/47e6685cfe44185ec4daab5e765e3b26.jpg", + "heat": 1362593, + "rank": 6, + "can_listen": true, + "recommendation": "", + "creation_aid": 698312930, + "creation_bvid": "BV1wm4y1y76i", + "creation_cover": "http://i1.hdslb.com/bfs/archive/4f097f5067fc3408118f7d59b2c36d8278660dd9.jpg", + "creation_title": "假如让金采源唱全曲......", + "creation_up": 496743369, + "creation_nickname": "YuueFriloeyyy_", + "creation_duration": 183, + "creation_play": 319267, + "creation_reason": "歌曲演唱", + "achievements": [ + "本期排名↑3", + "最高排名6" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA451591354456234292", + "music_title": "雪 Distance", + "singer": "Capper,罗言", + "album": "Uniconfication", + "mv_aid": 0, + "mv_bvid": "", + "mv_cover": "https://i0.hdslb.com/bfs/station_src/music_metadata/5899008cea7ed157b8bdb6f9b89dd7ff.jpg", + "heat": 1233174, + "rank": 7, + "can_listen": false, + "recommendation": "", + "creation_aid": 355903423, + "creation_bvid": "BV1QX4y127jq", + "creation_cover": "http://i2.hdslb.com/bfs/archive/e3542cf8d7cf7cc58268c840d845bb12d4c52662.jpg", + "creation_title": "⚡️“可是雪啊,埋进土里”⚡️", + "creation_up": 22169833, + "creation_nickname": "寒了个羽", + "creation_duration": 158, + "creation_play": 2622705, + "creation_reason": "音乐创作", + "achievements": [ + "本期排名↓1", + "最高排名3" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA460246447678301091", + "music_title": "Ghost Face (鬼脸) (LIVE版)", + "singer": "法老", + "album": "中国说唱巅峰对决2023 第一期", + "mv_aid": 0, + "mv_bvid": "", + "mv_cover": "https://i0.hdslb.com/bfs/station_src/music_metadata/0d4050feb7cac1a568849832d5fa9f67.jpg", + "heat": 1163291, + "rank": 8, + "can_listen": false, + "recommendation": "", + "creation_aid": 355995337, + "creation_bvid": "BV1qX4y1y78r", + "creation_cover": "http://i0.hdslb.com/bfs/archive/f5e7a51dbe1f48441042dad1e45148c400a3f9fe.jpg", + "creation_title": "【法老Pharaoh】虽迟但到!说唱巅峰对决《Ghost Face》live", + "creation_up": 12807175, + "creation_nickname": "法老爷爷", + "creation_duration": 79, + "creation_play": 885856, + "creation_reason": "官方现场", + "achievements": [ + "新晋上榜", + "最高排名8" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA458974797167092444", + "music_title": "F*ck My Life", + "singer": "SEVENTEEN", + "album": "SEVENTEEN 10th Mini Album 'FML'", + "mv_aid": 313423265, + "mv_bvid": "BV1tP41117mv", + "mv_cover": "http://i0.hdslb.com/bfs/station_src/music_metadata/6723df38fcca9b2ab85b564e3809426e.jpg", + "heat": 735517, + "rank": 9, + "can_listen": true, + "recommendation": "", + "creation_aid": 313423265, + "creation_bvid": "BV1tP41117mv", + "creation_cover": "http://i1.hdslb.com/bfs/archive/38377552bd74cc32851d6466343dc3a26983c3b6.jpg", + "creation_title": "SEVENTEEN 'F*ck My Life' Official MV", + "creation_up": 692206640, + "creation_nickname": "SEVENTEEN", + "creation_duration": 220, + "creation_play": 1008830, + "creation_reason": "官方MV", + "achievements": [ + "新晋上榜", + "最高排名9" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA460247474041267107", + "music_title": "Control's Wishes", + "singer": "Steven Grove,塞壬唱片-MSR", + "album": "孤星OST", + "mv_aid": 0, + "mv_bvid": "", + "mv_cover": "http://i0.hdslb.com/bfs/station_src/music_metadata/6068f2c64c6796f68b8dae7772f891ac.jpg", + "heat": 628233, + "rank": 10, + "can_listen": false, + "recommendation": "", + "creation_aid": 740625544, + "creation_bvid": "BV1ck4y1E7KJ", + "creation_cover": "http://i1.hdslb.com/bfs/archive/11381997120391d655c91b19bc08e110ca8201e5.jpg", + "creation_title": "【小提琴/钢琴】明日方舟四周年孤星PV曲《Control's Wishes》", + "creation_up": 2016022052, + "creation_nickname": "-桑榆墨景-", + "creation_duration": 193, + "creation_play": 37881, + "creation_reason": "器乐演奏", + "achievements": [ + "新晋上榜", + "最高排名10" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA459266635128138957", + "music_title": "花园种花(在小小的花园里种小小的花)", + "singer": "桃子老师花开富贵", + "album": "花园种花", + "mv_aid": 0, + "mv_bvid": "", + "mv_cover": "http://i0.hdslb.com/bfs/station_src/music_metadata/fb1d6a44bb8337edf6c9d32c421e9c89.jpg", + "heat": 623604, + "rank": 11, + "can_listen": false, + "recommendation": "", + "creation_aid": 398216313, + "creation_bvid": "BV1uo4y1x7UF", + "creation_cover": "http://i0.hdslb.com/bfs/archive/9562b126010376f7dcfedf0397170696eb1a19c5.jpg", + "creation_title": "姬子老师:开拓者家长们,路上有点堵车,这节挖呀挖呀挖课来晚了", + "creation_up": 391636983, + "creation_nickname": "动漫跳舞姬", + "creation_duration": 33, + "creation_play": 566777, + "creation_reason": "动画创作", + "achievements": [ + "新晋上榜", + "最高排名11" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA455203227252613620", + "music_title": "Cupid", + "singer": "FIFTY FIFTY", + "album": "The Beginning: Cupid", + "mv_aid": 226830843, + "mv_bvid": "BV1sh41137rs", + "mv_cover": "http://i0.hdslb.com/bfs/station_src/music_metadata/e91891c4e2573f4d4ada329db9a86b30.jpg", + "heat": 562273, + "rank": 12, + "can_listen": false, + "recommendation": "", + "creation_aid": 485862497, + "creation_bvid": "BV19T411b7nE", + "creation_cover": "http://i2.hdslb.com/bfs/archive/ece27463e3eb13f9fbbcb799436375495a795e3c.jpg", + "creation_title": "挑战在cp29和一百位coser比心!", + "creation_up": 1477074, + "creation_nickname": "菌儿rikushi", + "creation_duration": 148, + "creation_play": 1216246, + "creation_reason": "COSPLAY创作", + "achievements": [ + "重回榜单", + "最高排名12" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA457806074590836885", + "music_title": "星间旅行", + "singer": "HOYO-MiX,茶理理理子", + "album": "崩坏星穹铁道-星间旅行 Interstellar Journ", + "mv_aid": 612992200, + "mv_bvid": "BV1rh4y1n77f", + "mv_cover": "https://i0.hdslb.com/bfs/station_src/music_metadata/20ddff696bbbd7f00fc8b76f7b5334f7.jpg", + "heat": 515238, + "rank": 13, + "can_listen": false, + "recommendation": "", + "creation_aid": 995418876, + "creation_bvid": "BV1vs4y197gt", + "creation_cover": "http://i0.hdslb.com/bfs/archive/2d6997320bd2bb20f50b363a894033f325fed871.jpg", + "creation_title": "《星穹铁道玩家现状》", + "creation_up": 551188239, + "creation_nickname": "企鹅带带北极熊", + "creation_duration": 88, + "creation_play": 1570181, + "creation_reason": "音乐创作", + "achievements": [ + "本期排名↓10", + "最高排名2" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA434298821720206219", + "music_title": "可愛くてごめん (feat. かぴ)", + "singer": "HoneyWorks,かぴ", + "album": "告白実行委員会 -FLYING SONGS- 恋してる", + "mv_aid": 779733306, + "mv_bvid": "BV1iy4y1Z7Ri", + "mv_cover": "https://i0.hdslb.com/bfs/station_src/music_metadata/45ce3f52d31386741589a3a5ca9a420c.jpg", + "heat": 438720, + "rank": 14, + "can_listen": true, + "recommendation": "", + "creation_aid": 862702118, + "creation_bvid": "BV1gG4y117nV", + "creation_cover": "http://i1.hdslb.com/bfs/archive/38d94515fe5f6294bf7712d8b26eb049ec3cf627.jpg", + "creation_title": "这么可爱真是抱歉!❤️(*/∇\*)天台宅舞", + "creation_up": 434476793, + "creation_nickname": "优联酱uu", + "creation_duration": 140, + "creation_play": 1199819, + "creation_reason": "舞蹈创作", + "achievements": [ + "重回榜单", + "最高排名2" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA440555130794857381", + "music_title": "阳光开朗大男孩", + "singer": "卦者灵风", + "album": "阳光开朗大男孩", + "mv_aid": 421697247, + "mv_bvid": "BV1z341187Y9", + "mv_cover": "https://i0.hdslb.com/bfs/station_src/music_metadata/220c674ca22acb91114f6e0705d0f426.jpg", + "heat": 371851, + "rank": 15, + "can_listen": true, + "recommendation": "", + "creation_aid": 995281134, + "creation_bvid": "BV1as4y1d7QR", + "creation_cover": "http://i0.hdslb.com/bfs/archive/4628837eb5baf879a2be79b16836c90e0466dd6c.jpg", + "creation_title": "【灵能手书】阳光开朗大男孩", + "creation_up": 8504036, + "creation_nickname": "kipoki", + "creation_duration": 81, + "creation_play": 627123, + "creation_reason": "动画创作", + "achievements": [ + "重回榜单", + "最高排名1" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA406539170333366962", + "music_title": "此生不换", + "singer": "青鸟飞鱼", + "album": "仙剑奇侠传三 电视剧原声带", + "mv_aid": 0, + "mv_bvid": "", + "mv_cover": "http://i0.hdslb.com/bfs/station_src/music_metadata/450bd04688ef6a691b1adb816ace6155.jpg", + "heat": 361410, + "rank": 16, + "can_listen": false, + "recommendation": "", + "creation_aid": 545438082, + "creation_bvid": "BV1Cq4y1J7Ge", + "creation_cover": "http://i1.hdslb.com/bfs/archive/1b8b80f7ba9dccaf648cfb641b40e1d38965a4a4.jpg", + "creation_title": "开口爷青回!男生宿舍回忆向翻唱仙剑3插曲《此生不换》|我和室友的翻唱日常.", + "creation_up": 346782115, + "creation_nickname": "陈家淇_B11", + "creation_duration": 258, + "creation_play": 2976435, + "creation_reason": "歌曲演唱", + "achievements": [ + "重回榜单", + "最高排名15" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA444928930235832050", + "music_title": "太空电梯", + "singer": "阿鲲", + "album": "流浪地球2电影原声大碟", + "mv_aid": 0, + "mv_bvid": "", + "mv_cover": "https://i0.hdslb.com/bfs/station_src/music_metadata/c64c10b911ace04ae45b3172abe3a1d8.jpg", + "heat": 352572, + "rank": 17, + "can_listen": false, + "recommendation": "", + "creation_aid": 269421756, + "creation_bvid": "BV1ic41157cc", + "creation_cover": "http://i0.hdslb.com/bfs/archive/39a27b9d804750325b260f6bc69a3afa8c01a1dc.jpg", + "creation_title": "都说是涂装问题了,看,这战斗力不就上来了吗!", + "creation_up": 478832800, + "creation_nickname": "大刀王五EP", + "creation_duration": 87, + "creation_play": 706377, + "creation_reason": "动画创作", + "achievements": [ + "重回榜单", + "最高排名1" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA400017093531020491", + "music_title": "兰亭序", + "singer": "周杰伦", + "album": "魔杰座", + "mv_aid": 0, + "mv_bvid": "", + "mv_cover": "https://i0.hdslb.com/bfs/station_src/music_metadata/a03f7d174c3b01e4c6b3907a115c5434.jpg", + "heat": 347017, + "rank": 18, + "can_listen": false, + "recommendation": "", + "creation_aid": 825572396, + "creation_bvid": "BV1kg4y1L7v6", + "creation_cover": "http://i0.hdslb.com/bfs/archive/59e8436511ff45402e3d5dcf2c01feeb94897103.jpg", + "creation_title": "无关风月我题序等你回《兰亭序》", + "creation_up": 628615890, + "creation_nickname": "qqq还在梦里", + "creation_duration": 125, + "creation_play": 522133, + "creation_reason": "歌曲演唱", + "achievements": [ + "重回榜单", + "最高排名6" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA457811156946443719", + "music_title": "I'll Do It", + "singer": "Heidi Montag", + "album": "Superficial", + "mv_aid": 0, + "mv_bvid": "", + "mv_cover": "https://i0.hdslb.com/bfs/station_src/music_metadata/e1d95f62257da69db1dc36e949f789f5.jpg", + "heat": 345773, + "rank": 19, + "can_listen": false, + "recommendation": "", + "creation_aid": 313275936, + "creation_bvid": "BV1XP411y7UD", + "creation_cover": "http://i1.hdslb.com/bfs/archive/c42e54074a50ee1eaddbd5495091c2152aad8ecf.jpg", + "creation_title": "“嗨,老婆” 【崩坏星穹铁道】", + "creation_up": 14158002, + "creation_nickname": "Ishi丶", + "creation_duration": 61, + "creation_play": 103542, + "creation_reason": "动画创作", + "achievements": [ + "本期排名↓12", + "最高排名6" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + }, + { + "music_id": "MA409255441550338398", + "music_title": "失恋阵线联盟", + "singer": "草蜢", + "album": "失恋阵线联盟", + "mv_aid": 0, + "mv_bvid": "", + "mv_cover": "https://i0.hdslb.com/bfs/station_src/music_metadata/5d6b27035d5f7c0e7781b779871aca04.jpg", + "heat": 337176, + "rank": 20, + "can_listen": false, + "recommendation": "", + "creation_aid": 415864088, + "creation_bvid": "BV1QV411b7CT", + "creation_cover": "http://i1.hdslb.com/bfs/archive/8735563d73f86ef7073ed580a41e12c409bd2a5b.jpg", + "creation_title": "年会舞蹈《失恋阵线联盟》完整版", + "creation_up": 451425930, + "creation_nickname": "舞大师舞蹈工作室", + "creation_duration": 135, + "creation_play": 5336890, + "creation_reason": "舞蹈创作", + "achievements": [ + "重回榜单", + "最高排名20" + ], + "material_id": 0, + "material_use_num": 0, + "material_duration": 0, + "material_show": 1, + "song_type": 2 + } + ] + } +} +``` + +</details> + +## 订阅或退订榜单 + +> https://api.bilibili.com/x/copyright-music-publicity/toplist/subscribe/update + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | ------------------------ | --------------- | ------------------------------------------------ | +| state | num | 操作代码 | 必要 | 1:订阅<br />2:退订 | +| list_id | num | 榜单 id | 非必要 | 见 [获取音频榜单每期列表](#获取音频榜单每期列表) | +| csrf | str | CSRF Token(位于cookie) | Cookie 方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf 验证失败<br />400:请求错误 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | + +**示例:** + +```bash +curl 'https://api.bilibili.com/x/copyright-music-publicity/toplist/subscribe/update' \ + --data-urlencode 'state=1' \ + --data-urlencode 'state=76' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> diff --git a/bb-api-collect/docs/audio/status_number.md b/bb-api-collect/docs/audio/status_number.md new file mode 100644 index 0000000000..62621c1f79 --- /dev/null +++ b/bb-api-collect/docs/audio/status_number.md @@ -0,0 +1,63 @@ +# 音频状态数 + +## 歌曲状态数 + +>https://www.bilibili.com/audio/music-service-c/web/stat/song + +*请求方式:GET* + +唯缺投币数2333333 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| sid | num | 音频auid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ------------------------------- | +| code | num | 返回值 | 0:成功<br />72000000:参数错误 | +| msg | str | 错误信息 | 默认为success | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---- | +| sid | num | 音频auid | | +| play | num | 播放次数 | | +| collect | num | 收藏数 | | +| comment | num | 评论数 | | +| share | num | 分享数 | | + +**示例:** + +查询歌曲`au15664`的状态数 + +```shell +curl -G 'https://www.bilibili.com/audio/music-service-c/web/stat/song' \ +--data-urlencode 'sid=15664' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "data": { + "sid": 15664, + "play": 1377390, + "collect": 44340, + "comment": 2756, + "share": 4114 + } +} +``` + +</details> diff --git a/bb-api-collect/docs/bangumi/follow.md b/bb-api-collect/docs/bangumi/follow.md new file mode 100644 index 0000000000..a614e27e30 --- /dev/null +++ b/bb-api-collect/docs/bangumi/follow.md @@ -0,0 +1,124 @@ +# 追番相关 + +## 追番 +> https://api.bilibili.com/pgc/web/follow/add + +*请求方式:POST* + +鉴权方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|----------|-----|--------|-----|-----| +| season_id | str | 剧集ssid | 必要 | | +| csrf | str | csrf token(位于cookies中的bili_jct) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ------ | ------------------------------- | +| code | num | 返回值 | 0:成功<br />-111:csrf校验失败 | +| message | str | 信息 | 成功时:success | +| result | obj |见下表| | + +根对象中的`result`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ---------- | ---- | +| fmid | num | 0 | | +| relation | bool | false | | +| status | num | 2 | | +| toast | str | 自己追的番就要好好看完哟^o^ | | + +**示例:** + +追番`ssid=41410`的番剧 + +```shell +curl -G 'https://api.bilibili.com/pgc/web/follow/add' \ +--data-urlencode 'season_id=41410' \ +--data-urlencode 'csrf=xxx' \ +``` + +<details> + +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "success", + "result": { + "fmid": 0, + "relation": false, + "status": 2, + "toast": "自己追的番就要好好看完哟^o^" + } +} +``` +</details> + +## 取消追番 + +> https://api.bilibili.com/pgc/web/follow/del + +*请求方式:POST* + +鉴权方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | ----------------------------------- | ------ | ---- | +| season_id | str | 剧集ssid | 必要 | | +| csrf | str | csrf token(位于cookies中的bili_jct) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ------ | ------------------------------- | +| code | num | 返回值 | 0:成功<br />-111:csrf校验失败 | +| message | str | 信息 | 成功时:success | +| result | obj | 见下表 | | + +根对象中的`result`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ---------- | ---- | +| fmid | num | 0 | | +| relation | bool | true | | +| status | num | 0 | | +| toast | str | 已取消追番 | | + +**示例:** + +取消`ssid=41410`的追番 + +```shell +curl -G 'https://api.bilibili.com/pgc/web/follow/del' \ +--data-urlencode 'season_id=41410' \ +--data-urlencode 'csrf=xxx' \ +``` + +<details> + +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "success", + "result": { + "fmid": 0, + "relation": false, + "status": 0, + "toast": "已取消追番" + } +} +``` +</details> diff --git a/bb-api-collect/docs/bangumi/info.md b/bb-api-collect/docs/bangumi/info.md new file mode 100644 index 0000000000..6345107b70 --- /dev/null +++ b/bb-api-collect/docs/bangumi/info.md @@ -0,0 +1,1510 @@ +# 剧集地区一览 + +| ID | 名称 | +|----|-------| +| 1 | 中国大陆 | +| 2 | 日本 | +| 3 | 美国 | +| 4 | 英国 | +| 5 | 加拿大 | +| 6 | 中国香港 | +| 7 | 中国台湾 | +| 8 | 韩国 | +| 9 | 法国 | +| 10 | 泰国 | +| 11 | 马来西亚 | +| 12 | 新加坡 | +| 13 | 西班牙 | +| 14 | 俄罗斯 | +| 15 | 德国 | +| 16 | 其他 | +| 17 | 丹麦 | +| 18 | 乌克兰 | +| 19 | 以色列 | +| 20 | 伊朗 | +| 21 | 保加利亚 | +| 22 | 克罗地亚 | +| 23 | 冰岛 | +| 24 | 匈牙利 | +| 25 | 南非 | +| 26 | 印尼 | +| 27 | 印度 | +| 28 | 哥伦比亚 | +| 30 | 土耳其 | +| 31 | 墨西哥 | +| 32 | 委内瑞拉 | +| 33 | 巴西 | +| 34 | 希腊 | +| 35 | 意大利 | +| 36 | 挪威 | +| 37 | 捷克 | +| 38 | 摩洛哥 | +| 39 | 新西兰 | +| 40 | 智利 | +| 41 | 比利时 | +| 42 | 波兰 | +| 43 | 澳大利亚 | +| 44 | 爱尔兰 | +| 45 | 瑞典 | +| 46 | 瑞士 | +| 47 | 芬兰 | +| 48 | 苏联 | +| 49 | 荷兰 | +| 50 | 越南 | +| 51 | 阿根廷 | +| 52 | 马耳他 | +| 53 | 古巴 | +| 54 | 菲律宾 | +| 55 | 哈萨克斯坦 | +| 56 | 黎巴嫩 | +| 57 | 塞浦路斯 | +| 58 | 卡塔尔 | +| 59 | 阿联酋 | +| 60 | 奥地利 | +| 61 | 西德 | +| 62 | 卢森堡 | +| 63 | 罗马尼亚 | +| 64 | 印度尼西亚 | +| 65 | 南斯拉夫 | +| 66 | 蒙古 | +| 70 | 葡萄牙 | + +# 剧集基本信息 + +## 剧集基本信息(mdid方式) + +> https://api.bilibili.com/pgc/review/user + +*请求方式:GET* + +鉴权方式:Cookie(SESSDATA)或APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|----------|-----|--------|-----|-----| +| media_id | str | 剧集mdid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|----------------------------------| +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-404:错误 | +| message | str | 错误信息 | 默认为success | +| result | obj | 信息本体 | | + +`result`对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------|-----|--------|----------| +| media | obj | 剧集信息 | | +| review | obj | 用户操作信息 | 仅登录时存在此项 | + +`result`中的`media`对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------------------|-------|-----------|--------------------------------------------------------------| +| areas | array | 地区 | | +| cover | str | 封面图片url | | +| horizontal_picture | str | 横板封面图片url | | +| media_id | num | 剧集mdid | | +| new_ep | obj | 最新一话信息 | | +| rating | obj | 评分信息 | | +| season_id | num | 剧集ssid | | +| share_url | url | 剧集详情页连接 | | +| title | str | 标题 | | +| type | num | 剧集类型id | 1:番剧<br/>2:电影<br/>3:纪录片<br/>4:国创<br/>5:电视剧<br/>6:漫画<br/>7:综艺 | +| type_name | str | 剧集类型 | | + +`media`中的`areas`数组: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|-----------|-----| +| 0 | obj | 地区信息1 | | +| n | obj | 地区信息(n+1) | | +| …… | obj | …… | | + +`areas`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|------|-----|--------|-------------------| +| id | num | 所属地区编号 | [剧集地区一览](#剧集地区一览) | +| name | str | 所属地区名称 | | + +`media`中的`new_ep`对象: + +| 字段 | 类型 | 内容 | 备注 | +|------------|-----|-----------|--------------------| +| id | num | 最新一话的epid | | +| index | str | 最新一话名称 | | +| index_show | str | 最新一话显示名称 | eg. `第1话`、`更新至第4话` | + +`media`中的`rating`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------|-----|--------|-----| +| count | num | 总计评分人数 | | +| score | num | 评分 | | + +`result`中的`review`对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|-----|--------| +| is_coin | num | 0 | 作用尚不明确 | +| is_open | num | 1 | 作用尚不明确 | + +**示例:** + +查询剧集`md28220978`的基本信息 + +```shell +curl -G 'https://api.bilibili.com/pgc/review/user' \ +--data-urlencode 'media_id=28220978' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "success", + "result": { + "media": { + "areas": [ + { + "id": 2, + "name": "日本" + } + ], + "cover": "http://i0.hdslb.com/bfs/bangumi/8aa0bfce050c72c6626b63d3093a88527c251026.jpg", + "horizontal_picture": "http://i0.hdslb.com/bfs/bangumi/8aa0bfce050c72c6626b63d3093a88527c251026.jpg", + "media_id": 28220978, + "new_ep": { + "id": 21278, + "index": "14", + "index_show": "全14话" + }, + "rating": { + "count": 80693, + "score": 9.9 + }, + "season_id": 1172, + "share_url": "https://www.bilibili.com/bangumi/media/md28220978", + "title": "轻音少女 第一季", + "type": 1, + "type_name": "番剧" + } + } +} +``` + +</details> + +## 获取剧集明细(web端)(ssid/epid方式) + +> https://api.bilibili.com/pgc/view/web/season + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|-----------|-----|--------|--------|---------------------| +| season_id | num | 番剧ssid | 必要(可选) | season_id与ep_id任选其一 | +| ep_id | num | 剧集epid | 必要(可选) | season_id与ep_id任选其一 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|-------------------| +| code | num | 返回值 | 0:成功<br />-404:错误 | +| message | str | 错误信息 | 默认为success | +| result | obj | 信息本体 | | + +`result`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------------------|-------|----------------|----------------------------------------------------------| +| activity | obj | 参与的活动 | | +| actors | str | | | +| alias | str | 空 | 作用尚不明确 | +| areas | array | | | +| bkg_cover | str | 网页背景图片url | 无则为空 | +| cover | str | 剧集封面图片url | | +| delivery_fragment_video | bool | | | +| enable_vt | bool | | | +| episodes | array | 正片剧集列表 | | +| evaluate | str | 简介 | | +| freya | obj | | | +| hide_ep_vv_vt_dm | num | | | +| icon_font | obj | | | +| jp_title | str | 空 | 作用尚不明确 | +| link | str | 简介页面url | | +| media_id | num | 剧集mdid | | +| mode | num | 2 | 作用尚不明确 | +| multi_view_info | obj | | | +| new_ep | obj | 更新信息 | | +| payment | obj | 会员&付费信息 | 若无相关内容则无此项 | +| payPack | obj | 付费包信息 | 目前只有霹雳布袋戏付费套餐一种 | +| play_strategy | obj | | | +| positive | obj | | | +| publish | obj | 发布信息 | | +| rating | obj | 评分信息 | 若无相关内容则无此项 | +| record | str | 备案号 | 无则为空 | +| rights | obj | 属性标志信息 | | +| season_id | num | 番剧ssid | | +| season_title | str | 剧集标题 | | +| seasons | array | 同系列所有季信息 | | +| section | array | 花絮、PV、番外等非正片内容 | 若无相关内容则无此项 | +| section_bottom_desc | str | | | +| series | obj | 系列信息 | | +| share_copy | str | 《{标题}》+{备注} | | +| share_sub_title | str | 备注 | | +| share_url | str | 番剧播放页面url | | +| show | obj | 网页全屏标志 | | +| show_season_type | num | 1,2,3,4,5,7 | | +| square_cover | str | 方形封面图片url | | +| staff | str | 制作人员信息 | | +| stat | obj | 状态数 | | +| status | num | | | +| styles | array | 标签 | | +| subtitle | str | 剧集副标题 | | +| title | str | 剧集标题 | | +| total | num | 总计正片集数 | 未完结:大多为-1<br />已完结:正整数 | +| type | num | 剧集类型 | 1:番剧<br />2:电影<br />3:纪录片<br />4:国创<br />5:电视剧<br />7:综艺 | +| up_info | obj | UP主信息 | 若无相关内容则无此项 | +| user_status | obj | | | + +`result`中的`activity`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------|-------|------|--------| +| cover | str | | | +| head_bg_url | str | 空 | 作用尚不明确 | +| id | num | 活动id | | +| link | str | | | +| pendants | array | | | +| title | str | 活动标题 | | + +`activity`中的`pendants`数组 + +| 字段名 | 类型 | 内容 | 备注 | +|-------|-----|----|----| +| image | str | | | +| name | str | | | +| pid | num | | | + +`result`中的`areas`数组 + +| 字段名 | 类型 | 内容 | 备注 | +|------|-----|--------|-------------------| +| id | num | 所属地区编号 | [剧集地区一览](#剧集地区一览) | +| name | str | 所属地区名称 | | + +`result`中的`episodes`数组: + +| 项 | 类型 | 内容 | 备注 | +|----|-----|-----------|--------| +| 0 | obj | 正片第1集 | | +| n | obj | 正片第(n+1)集 | 按照顺序排列 | +| …… | obj | | | + +`episodes`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------------------|-------|---------------------|----------------| +| aid | num | 单集稿件avid | | +| archive_attr | num | | | +| badge | str | 标签文字 | 例如`会员`、`限免`等 | +| badge_info | obj | | | +| badge_type | num | | | +| bvid | str | 单集稿件bvid | | +| cid | num | 视频cid | | +| cover | str | 单集封面url | | +| dimension | obj | 分辨率信息 | | +| duration | num | | | +| enable_vt | bool | | | +| ep_id | num | | | +| from | str | | | +| id | num | 单集epid | | +| interaction | obj | | | +| is_sub_view | bool | | | +| is_view_hide | bool | | | +| link | str | 单集网页url | | +| long_title | str | 单集完整标题 | | +| multi_view_eps | array | | | +| pub_time | num | 发布时间 | 时间戳 | +| pv | num | 0 | 作用尚不明确 | +| release_date | str | 空 | 作用尚不明确 | +| rights | obj | | | +| section_type | num | | | +| share_copy | str | 《{标题}》+第n话+{单集完整标题} | | +| share_url | str | 单集网页url | | +| short_link | str | 单集网页url短链接 | | +| show_title | str | | | +| showDrmLoginDialog | bool | | | +| skip | obj | | | +| status | num | | | +| subtitle | str | 单集副标题 | 观看次数文字 | +| title | str | 单集标题 | | +| toast_title | str | | | +| vid | str | 单集vid | vupload_+{cid} | + +`episodes`中的`badge_info`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|----------------|-----|----|----| +| bg_color | str | | | +| bg_color_night | str | | | +| text | str | | | + +`episodes`中的`dimension`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|--------|-----|----|----| +| height | num | | | +| rotate | num | | | +| width | num | | | + +`episodes`中的`interaction`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|---------------|------|----|----| +| graph_version | num | | | +| interaction | bool | | | + +`episodes`中的`multi_view_eps`数组 + +| 字段名 | 类型 | 内容 | 备注 | +|-------|-----|----|----| +| ep_id | num | | | + +`episodes`中的`rights`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|----------------|-----|----|----| +| allow_demand | num | | | +| allow_dm | num | | | +| allow_download | num | | | +| area_limit | num | | | + +`episodes`中的`skip`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-----|-----|----|----| +| ed | obj | | | +| op | obj | | | + +`skip`对象中的`ed`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-------|-----|----|----| +| end | num | | | +| start | num | | | + +`skip`对象中的`op`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-------|-----|----|----| +| end | num | | | +| start | num | | | + +`result`中的`freya`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-----------------|-----|----|----| +| bubble_desc | str | | | +| bubble_show_cnt | num | | | +| icon_show | num | | | + +`result`中的`icon_font`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|------|-----|----|----| +| name | str | | | +| text | str | | | + +`result`中的`multi_view_info`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|----------------------|------|----|----| +| changing_dance | str | | | +| is_multi_view_season | bool | | | + +`result`中的`new_ep`对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------|-----|----------|--------------| +| desc | str | 更新备注 | | +| id | num | 最新一话epid | | +| is_new | num | 是否最新发布 | 0:否<br />1:是 | +| title | str | 最新一话标题 | | + +`result`中的`payment`对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------------------|-----|---------|--------| +| discount | num | 折扣 | 100为原价 | +| pay_type | obj | 支付相关 | | +| price | str | 售价 | | +| promotion | str | 推广信息 | | +| tip | str | | | +| view_start_time | num | | | +| 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`中的`payPack`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-----------------------|-----|----|----| +| id | num | | | +| not_paid_text_for_app | str | | | +| paid_text_for_app | str | | | +| pay_pack_url | str | | | +| status | num | | | +| title | str | | | + +`result`中的`play_strategy`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|------------|-------|----|----| +| strategies | array | | | + +`result`中的`positive`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------|-----|----|----| +| id | num | | | +| title | str | | | + +`result`中的`publish`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-----------------|-----|----------|----------------------| +| is_finish | num | 完结状态 | 0:未完结<br />1:已完结 | +| is_started | num | 是否发布 | 0:未发布<br />1:已发布 | +| pub_time | str | 发布时间 | YYYY-MM-DDD hh:mm:ss | +| pub_time_show | str | 发布时间文字介绍 | | +| unknow_pub_date | num | 0 | 作用尚不明确 | +| weekday | num | 0 | 作用尚不明确 | + +`result`中的`rating`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------|-----|--------|----| +| count | num | 总计评分人数 | | +| score | num | 评分 | | + +`result`中的`rights`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------------|-----|------|---------------------------| +| allow_bp | num | | | +| allow_bp_rank | num | | | +| allow_download | num | | | +| allow_review | num | | | +| area_limit | num | | | +| ban_area_show | num | | | +| can_watch | num | | | +| copyright | str | 版权标志 | bilibili:授权<br />dujia:独家 | +| forbid_pre | num | | | +| freya_white | num | | | +| is_cover_show | num | | | +| is_preview | num | | | +| only_vip_download | num | | | +| resource | str | | | +| watch_platform | num | | | + +`result`中的`seasons`数组: + +| 项 | 类型 | 内容 | 备注 | +|----|-----|------------|--------| +| 0 | obj | 同系列剧集1 | | +| n | obj | 同系列剧集(n+1) | 按照顺序排列 | +| …… | obj | | | + +`seasons`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|-----------------------|------|----|----| +| badge | str | | | +| badge_info | obj | | | +| badge_type | num | | | +| cover | str | | | +| enable_vt | bool | | | +| horizontal_cover_1610 | str | | | +| horizontal_cover_169 | str | | | +| icon_font | obj | | | +| media_id | num | | | +| new_ep | obj | | | +| season_id | num | | | +| season_title | str | | | +| season_type | num | | | +| stat | obj | | | + +`seasons`中的`badge_info`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|----------------|-----|----|----| +| bg_color | str | | | +| bg_color_night | str | | | +| text | str | | | + +`seasons`中的`icon_font`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|------|-----|----|----| +| name | str | | | +| text | str | | | + +`seasons`中的`new_ep`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|------------|-----|----|----| +| cover | str | | | +| id | num | | | +| index_show | str | | | + +`seasons`中的`stat`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|---------------|-----|----|----| +| favorites | num | | | +| series_follow | num | | | +| views | num | | | +| vt | num | | | + +`result`中的`section`数组: + +| 项 | 类型 | 内容 | 备注 | +|----|-----|------------|--------| +| 0 | obj | 其他内容块1 | | +| n | obj | 其他内容块(n+1) | 按照顺序排列 | +| …… | obj | | | + +`section`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------|-------|-------|----| +| attr | num | | | +| episode_id | num | 0 | | +| episode_ids | array | | | +| episodes | array | 板块内容 | | +| id | num | 板块id? | | +| report | obj | | | +| title | str | 板块标题 | | +| type | num | ? | | +| type2 | num | | | + +`episodes`数组中的对象 + +| 字段名 | 类型 | 内容 | 备注 | +|--------------------|------|----|----| +| aid | num | | | +| archive_attr | num | | | +| badge | str | | | +| badge_info | obj | | | +| badge_type | num | | | +| bvid | str | | | +| cid | num | | | +| cover | str | | | +| dimension | obj | | | +| duration | num | | | +| enable_vt | bool | | | +| ep_id | num | | | +| from | str | | | +| icon_font | obj | | | +| id | num | | | +| interaction | obj | | | +| is_view_hide | bool | | | +| link | str | | | +| link_type | str | | | +| long_title | str | | | +| pub_time | num | | | +| pv | num | | | +| release_date | str | | | +| report | obj | | | +| rights | obj | | | +| section_type | num | | | +| share_copy | str | | | +| share_url | str | | | +| short_link | str | | | +| show_title | str | | | +| showDrmLoginDialog | bool | | | +| skip | obj | | | +| stat | obj | | | +| stat_for_unity | obj | | | +| status | num | | | +| subtitle | str | | | +| title | str | | | +| toast_title | str | | | +| up_info | obj | | | +| vid | str | | | + +`badge_info`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|----------------|-----|----|----| +| bg_color | str | | | +| bg_color_night | str | | | +| text | str | | | + +`dimension`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|--------|-----|----|----| +| height | num | | | +| rotate | num | | | +| width | num | | | + +`icon_font`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|------|-----|----|----| +| name | str | | | +| text | str | | | + +`interaction`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|---------------|------|----|----| +| graph_version | num | | | +| interaction | bool | | | + +`report`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|--------------|-----|----|----| +| aid | str | | | +| ep_title | str | | | +| position | str | | | +| season_id | str | | | +| season_type | str | | | +| section_id | str | | | +| section_type | str | | | + +`rights`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|----------------|-----|----|----| +| allow_demand | num | | | +| allow_dm | num | | | +| allow_download | num | | | +| area_limit | num | | | + +`skip`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-----|-----|----|----| +| ed | obj | | | +| op | obj | | | + +`ed`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-------|-----|----|----| +| end | num | | | +| start | num | | | + +`op`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-------|-----|----|----| +| end | num | | | +| start | num | | | + +`stat_for_unity`对象 + +### 根对象 -> `result`对象 -> `section`数组中的对象 -> `episodes`数组中的对象 -> `stat_for_unity`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|---------|-----|----|----| +| coin | num | | | +| danmaku | obj | | | +| likes | num | | | +| reply | num | | | +| vt | obj | | | + +`danmaku`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-----------|-----|----|----| +| icon | str | | | +| pure_text | str | | | +| text | str | | | +| value | num | | | + +`vt`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-----------|-----|----|----| +| icon | str | | | +| pure_text | str | | | +| text | str | | | +| value | num | | | + +`stat`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|----------|-----|----|----| +| coin | num | | | +| danmakus | num | | | +| likes | num | | | +| play | num | | | +| reply | num | | | +| vt | num | | | + +`up_info`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|--------------|-----|----|----| +| avatar | str | | | +| follower | num | | | +| is_follow | num | | | +| mid | num | | | +| uname | str | | | +| verify_type | num | | | +| verify_type2 | num | | | + +`report`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|--------------|-----|----|----| +| season_id | str | | | +| season_type | str | | | +| sec_title | str | | | +| section_id | str | | | +| section_type | str | | | + + +`result`中的`series`对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------------|-----|------|----| +| display_type | num | | | +| series_id | num | 系列id | | +| series_title | str | 系列名 | | + +`result`中的`show`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------|-----|------|----------------| +| wide_screen | num | 是否全屏 | 0:正常<br />1:全屏 | + +`result`中的`stat`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------|-----|-----|----| +| coins | num | 投币数 | | +| danmakus | num | 弹幕数 | | +| favorite | num | | | +| favorites | num | 收藏数 | | +| follow_text | str | | | +| hot | num | | | +| likes | num | 点赞数 | | +| reply | num | 评论数 | | +| share | num | 分享数 | | +| views | num | 播放数 | | +| vt | num | | | + +`result`中的`up_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +|----------------------|-----|---------|----| +| avatar | str | 头像图片url | | +| avatar_subscript_url | str | | | +| follower | num | 粉丝数 | | +| is_follow | num | 0 | | +| mid | num | UP主mid | | +| nickname_color | str | | | +| pendant | obj | | | +| theme_type | num | 0 | | +| uname | str | UP主昵称 | | +| verify_type | num | | | +| vip_label | obj | | | +| vip_status | num | | | +| vip_type | num | | | + +`up_info`中的`pendant`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-------|-----|----|----| +| image | str | | | +| name | str | | | +| pid | num | | | + +`up_info`中的`vip_label`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|--------------|-----|----|----| +| bg_color | str | | | +| bg_style | num | | | +| border_color | str | | | +| text | str | | | +| text_color | str | | | + +`result`中的`user_status`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|---------------|-----|----|----| +| area_limit | num | | | +| ban_area_show | num | | | +| follow | num | | | +| follow_status | num | | | +| login | num | | | +| pay | num | | | +| pay_pack_paid | num | | | +| sponsor | num | | | + +# 获取剧集分集信息 + +> https://api.bilibili.com/pgc/web/season/section + +*请求方式:GET* + +鉴权方式:Cookie(SESSDATA)或APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|-----------|-----|--------|-----|-----| +| season_id | str | 剧集ssid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|-------------------| +| code | num | 返回值 | 0:成功<br />-404:错误 | +| message | str | 错误信息 | 默认为success | +| result | obj | 信息本体 | | + +`result`对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------------|-------|--------|-----| +| main_section | obj | 正片信息 | | +| section | array | 花絮、PV等 | | + +`result`中的`main_section`对象: + +| 字段 | 类型 | 内容 | 备注 | +|----------|-------|------------------------------|-----| +| episodes | array | 分集信息 | | +| id | num | 分组id | | +| type | num | 0:正片<br/>1:PV&其他<br/>2:OP&ED | | +| title | str | | | + +`episodes`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------|-----|----------|-----| +| aid | num | 视频av号 | | +| badge | str | | | +| badge_info | obj | | | +| badge_type | num | 0 | | +| cid | num | 分集cid | | +| cover | str | 分集封面 | | +| from | str | bangumi | | +| id | num | 分集epId | | +| is_premiere | num | 0 | | +| long_title | str | 长标题 | | +| share_url | str | 分集播放页url | | +| status | num | 2 | | +| title | str | 短标题 | | +| vid | str | | | + +`badge_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +|----------------|-----|-----|-----| +| bg_color | str | | | +| bg_color_night | str | | | +| text | str | | | + +`section`数组中的对象: + +**同`main_section`对象** + +**示例:** + +```shell +curl -L -X GET 'https://api.bilibili.com/pgc/web/season/section?season_id=42290' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "success", + "result": { + "main_section": { + "episodes": [ + { + "aid": 300876247, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 772096113, + "cover": "http://i0.hdslb.com/bfs/archive/c09aec64c1787e287b0187498a4443177cc2112c.jpg", + "from": "bangumi", + "id": 606591, + "is_premiere": 0, + "long_title": "瞒天过海!罪犯新选组", + "share_url": "https://www.bilibili.com/bangumi/play/ep606591", + "status": 2, + "title": "1", + "vid": "" + }, + { + "aid": 555940678, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 779868818, + "cover": "http://i0.hdslb.com/bfs/archive/52ccef75fc179c7f8a4f2ff989a1249c78f564e0.jpg", + "from": "bangumi", + "id": 606592, + "is_premiere": 0, + "long_title": "光芒四射!遗物日本刀", + "share_url": "https://www.bilibili.com/bangumi/play/ep606592", + "status": 2, + "title": "2", + "vid": "" + }, + { + "aid": 216208730, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 779450100, + "cover": "http://i0.hdslb.com/bfs/archive/7eee64ff758fb426b6cd16bc7d525f4de98fd4dc.jpg", + "from": "bangumi", + "id": 606596, + "is_premiere": 0, + "long_title": "乔装打扮!潜入花街", + "share_url": "https://www.bilibili.com/bangumi/play/ep606596", + "status": 2, + "title": "3", + "vid": "" + }, + { + "aid": 386385026, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 786667756, + "cover": "http://i0.hdslb.com/bfs/archive/6851be597e1fa496a8b1486000e83654c2fac45c.jpg", + "from": "bangumi", + "id": 606597, + "is_premiere": 0, + "long_title": "一探究竟!神秘妖刀", + "share_url": "https://www.bilibili.com/bangumi/play/ep606597", + "status": 2, + "title": "4", + "vid": "" + }, + { + "aid": 729094525, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 793386614, + "cover": "http://i0.hdslb.com/bfs/archive/5dfa30d48188b26c616a05745132a59f6823dade.jpg", + "from": "bangumi", + "id": 606598, + "is_premiere": 0, + "long_title": "展现无遗!和尚与医生的决心", + "share_url": "https://www.bilibili.com/bangumi/play/ep606598", + "status": 2, + "title": "5", + "vid": "" + }, + { + "aid": 599314561, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 798315932, + "cover": "http://i0.hdslb.com/bfs/archive/3daae9ee434d335ff9e5a9d8244bc1e6b7ffa8d0.jpg", + "from": "bangumi", + "id": 606599, + "is_premiere": 0, + "long_title": "直捣敌巢!败德白川屋", + "share_url": "https://www.bilibili.com/bangumi/play/ep606599", + "status": 2, + "title": "6", + "vid": "" + }, + { + "aid": 259686552, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 807199844, + "cover": "http://i0.hdslb.com/bfs/archive/9ff73932c210abe64373be6f3959c2eee6c7470b.jpg", + "from": "bangumi", + "id": 606600, + "is_premiere": 0, + "long_title": "全力阻止!新选组解散", + "share_url": "https://www.bilibili.com/bangumi/play/ep606600", + "status": 2, + "title": "7", + "vid": "" + }, + { + "aid": 514942530, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 814175863, + "cover": "http://i0.hdslb.com/bfs/archive/31a19bf3af61e58f1e8c4a387779fc3272cb47a7.jpg", + "from": "bangumi", + "id": 606601, + "is_premiere": 0, + "long_title": "激烈战斗!池田屋事件", + "share_url": "https://www.bilibili.com/bangumi/play/ep606601", + "status": 2, + "title": "8", + "vid": "" + }, + { + "aid": 515024193, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 819960797, + "cover": "http://i0.hdslb.com/bfs/archive/68a0a12a74e99b6cd85cfa0fb7be70d82d8b6558.jpg", + "from": "bangumi", + "id": 606602, + "is_premiere": 0, + "long_title": "真心炸裂!人之思绪 鬼之念想", + "share_url": "https://www.bilibili.com/bangumi/play/ep606602", + "status": 2, + "title": "9", + "vid": "" + }, + { + "aid": 430293537, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 827739564, + "cover": "http://i0.hdslb.com/bfs/archive/6411f71c947ba9b011ca0fe2891334147ef1e14d.jpg", + "from": "bangumi", + "id": 606603, + "is_premiere": 0, + "long_title": "全力守护!美利坚黑船", + "share_url": "https://www.bilibili.com/bangumi/play/ep606603", + "status": 2, + "title": "10", + "vid": "" + }, + { + "aid": 858116183, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 833436271, + "cover": "http://i0.hdslb.com/bfs/archive/48736284b5cf0f3515cddb95f1c1b8658ec6c5ff.jpg", + "from": "bangumi", + "id": 606604, + "is_premiere": 0, + "long_title": "勇往直前!京都大决战", + "share_url": "https://www.bilibili.com/bangumi/play/ep606604", + "status": 2, + "title": "11", + "vid": "" + }, + { + "aid": 773279679, + "badge": "会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "会员" + }, + "badge_type": 0, + "cid": 840839493, + "cover": "http://i0.hdslb.com/bfs/archive/316f7c8a750699bf53ee44d43669fabb0271be86.jpg", + "from": "bangumi", + "id": 606605, + "is_premiere": 0, + "long_title": "替身传说!罪犯新选组", + "share_url": "https://www.bilibili.com/bangumi/play/ep606605", + "status": 13, + "title": "12", + "vid": "" + } + ], + "id": 81861, + "title": "正片", + "type": 0 + }, + "section": [ + { + "episodes": [ + { + "aid": 898153042, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 766274696, + "cover": "http://i0.hdslb.com/bfs/archive/ac27ed20081e99fc36720ef0714f81d8df2c279a.png", + "from": "bangumi", + "id": 576387, + "is_premiere": 0, + "long_title": "", + "share_url": "https://www.bilibili.com/bangumi/play/ep576387", + "status": 2, + "title": "PV", + "vid": "" + }, + { + "aid": 215937670, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 773008915, + "cover": "http://i0.hdslb.com/bfs/archive/0a6b589e9175dfee1d9699fb55c5c0677941994a.png", + "from": "bangumi", + "id": 606995, + "is_premiere": 0, + "long_title": "", + "share_url": "https://www.bilibili.com/bangumi/play/ep606995", + "status": 2, + "title": "西川贵教", + "vid": "" + }, + { + "aid": 813460609, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 773007362, + "cover": "http://i0.hdslb.com/bfs/archive/6c8f4136731c1c2f8171f5c006f79f0603d11bdf.png", + "from": "bangumi", + "id": 606998, + "is_premiere": 0, + "long_title": "", + "share_url": "https://www.bilibili.com/bangumi/play/ep606998", + "status": 2, + "title": "幕末替身声优采访", + "vid": "" + }, + { + "aid": 556287340, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 785468206, + "cover": "http://i0.hdslb.com/bfs/archive/77564ca30f1a4d3a64cfc292a7fd989c09a30027.png", + "from": "bangumi", + "id": 660464, + "is_premiere": 0, + "long_title": "", + "share_url": "https://www.bilibili.com/bangumi/play/ep660464", + "status": 2, + "title": "声优对谈 01", + "vid": "" + }, + { + "aid": 984099086, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 792637456, + "cover": "http://i0.hdslb.com/bfs/archive/77564ca30f1a4d3a64cfc292a7fd989c09a30027.png", + "from": "bangumi", + "id": 669591, + "is_premiere": 0, + "long_title": "", + "share_url": "https://www.bilibili.com/bangumi/play/ep669591", + "status": 2, + "title": "声优对谈 02", + "vid": "" + }, + { + "aid": 259364452, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 798995285, + "cover": "http://i0.hdslb.com/bfs/archive/77564ca30f1a4d3a64cfc292a7fd989c09a30027.png", + "from": "bangumi", + "id": 670446, + "is_premiere": 0, + "long_title": "", + "share_url": "https://www.bilibili.com/bangumi/play/ep670446", + "status": 2, + "title": "声优对谈 03", + "vid": "" + }, + { + "aid": 772146427, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 808201440, + "cover": "http://i0.hdslb.com/bfs/archive/77564ca30f1a4d3a64cfc292a7fd989c09a30027.png", + "from": "bangumi", + "id": 672539, + "is_premiere": 0, + "long_title": "", + "share_url": "https://www.bilibili.com/bangumi/play/ep672539", + "status": 2, + "title": "声优对谈 04", + "vid": "" + }, + { + "aid": 687381109, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 814826609, + "cover": "http://i0.hdslb.com/bfs/archive/77564ca30f1a4d3a64cfc292a7fd989c09a30027.png", + "from": "bangumi", + "id": 676133, + "is_premiere": 0, + "long_title": "", + "share_url": "https://www.bilibili.com/bangumi/play/ep676133", + "status": 2, + "title": "声优对谈 05", + "vid": "" + }, + { + "aid": 730289528, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 826951152, + "cover": "http://i0.hdslb.com/bfs/archive/77564ca30f1a4d3a64cfc292a7fd989c09a30027.png", + "from": "bangumi", + "id": 676134, + "is_premiere": 0, + "long_title": "", + "share_url": "https://www.bilibili.com/bangumi/play/ep676134", + "status": 2, + "title": "声优对谈 07", + "vid": "" + }, + { + "aid": 602813211, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 826951370, + "cover": "http://i0.hdslb.com/bfs/archive/77564ca30f1a4d3a64cfc292a7fd989c09a30027.png", + "from": "bangumi", + "id": 676135, + "is_premiere": 0, + "long_title": "", + "share_url": "https://www.bilibili.com/bangumi/play/ep676135", + "status": 2, + "title": "声优对谈 08", + "vid": "" + }, + { + "aid": 515295782, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 826951255, + "cover": "http://i0.hdslb.com/bfs/archive/77564ca30f1a4d3a64cfc292a7fd989c09a30027.png", + "from": "bangumi", + "id": 676137, + "is_premiere": 0, + "long_title": "", + "share_url": "https://www.bilibili.com/bangumi/play/ep676137", + "status": 2, + "title": "声优对谈 09", + "vid": "" + }, + { + "aid": 815269384, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 826951558, + "cover": "http://i0.hdslb.com/bfs/archive/77564ca30f1a4d3a64cfc292a7fd989c09a30027.png", + "from": "bangumi", + "id": 676138, + "is_premiere": 0, + "long_title": "", + "share_url": "https://www.bilibili.com/bangumi/play/ep676138", + "status": 2, + "title": "声优对谈 10", + "vid": "" + } + ], + "id": 82126, + "title": "PV&其他", + "type": 1 + }, + { + "episodes": [ + { + "aid": 556712105, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 794382832, + "cover": "http://i0.hdslb.com/bfs/archive/1f4ab8b9af0689900e7c486c4e676e27988091be.png", + "from": "bangumi", + "id": 670062, + "is_premiere": 0, + "long_title": "", + "share_url": "https://www.bilibili.com/bangumi/play/ep670062", + "status": 2, + "title": "NCOP", + "vid": "" + }, + { + "aid": 259129266, + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "text": "" + }, + "badge_type": 0, + "cid": 794382772, + "cover": "http://i0.hdslb.com/bfs/archive/d08738a452187a0229c3b99beaf1cb4ff868a030.png", + "from": "bangumi", + "id": 670063, + "is_premiere": 0, + "long_title": "", + "share_url": "https://www.bilibili.com/bangumi/play/ep670063", + "status": 2, + "title": "NCED", + "vid": "" + } + ], + "id": 85065, + "title": "OP&ED", + "type": 2 + } + ] + } +} +``` + +</details> diff --git a/bb-api-collect/docs/bangumi/season_index.md b/bb-api-collect/docs/bangumi/season_index.md new file mode 100644 index 0000000000..013227df97 --- /dev/null +++ b/bb-api-collect/docs/bangumi/season_index.md @@ -0,0 +1,806 @@ +# 剧集索引 + +## 获取剧集索引 + +> https://api.bilibili.com/pgc/season/index/result +> +*请求方式:GET* + +鉴权方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------------------- | ---- | --------------- | -------------- | --------------------------------------------------------------------------------------- | +| season_type | num | 类别 | 必要 | 番剧:`1`   电影:`2`   纪录片:`3`<br>国创:`4`   电视剧:`5`   综艺:`7` | +| type | num | 未知作用 | 必要 | 固定为 `1` | +| page | num | 页码 | 非必要 | 默认为 `1` | +| pagesize | num | 每页项数 | 非必要 | 定义域:[1,∞),<br>超出最大项数则返回最大项数 | +| season_version | num | 类型 | 非必要 | 全部:`-1`   正片:`1`   电影:`2`   其他:`3` | +| spoken_language_type | num | 配音 | 非必要 | 全部:`-1`   原声:`1`   中文配音:`2` | +| area | str | 地区 | 非必要 | 地区代码列表 ∈N∩[1,70] 例如日本:`2` 中国:`1,6,7` [完整地区代码见表](info.md#剧集地区一览)<br>`-1`代表全部,前端页面有具体国家则可以单独请求具体国家如日本`2`,<br>将[1,70]中前端页面有的国家排除后一一列出则代表其他如`1,4,5,6,7,8...69,70` | +| is_finish | num | 状态 | 非必要 | 全部:`-1`   完结:`1`   连载:`0` | +| copyright | str | 版权 | 非必要 | 全部:`-1`   独家:`3`   其他:`1,2,4` | +| season_status | str | 付费类型 | 非必要 | 全部:`-1`   免费:`1`   付费:`2,6`   大会员:`4,6` | +| season_month | num | 季度 | 非必要 | 全部:`-1`   一月:`1`   四月:`4`   七月:`7`   十月:`10` | +| year | str | 年份 | 非必要 | 适用于`国创`和`番剧`类别<br>除了`-1`代表全部外,其他情况以左闭右开区间形式表示,<br>如`[2025,2026)`代表2025年,`[2010,2015)`代表2010-2014年,`[1990,2000)`代表90年代,`[,1980)`代表更早 | +| release_date | str | 年份 | 非必要 | 适用于`电影`,`电视剧`和`纪录片`类别<br>和year参数类似只是精确到秒级,<br>如`[2025-01-01 00:00:00,2026-01-01 00:00:00)`代表2025年,<br>`[1990-01-01 00:00:00,2000-01-01 00:00:00)`代表90年代 | +| style_id | num | 风格 | 非必要 | 全部:`-1`   特定风格则值为该风格id,如原创:`10010` | +| producer_id | num | 出品方 | 非必要 | 全部:`-1`   特定出品方则值为该出品方id,如央视:`4` | +| order | num | 排序指标 | 非必要 | 更新时间:`0`   弹幕数量:`1`   播放数量:`2`  <br>追剧人数:`3`   最高评分:`4`   开播时间:`5`   上映时间:`6` | +| sort | num | 排序方向 | 非必要 | 增序:`1`   降序:`0` 默认为降序 | +| st | num | 未知作用 | 非必要 | 值与 `season_type` 相同,合理怀疑是其缩写 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|-----------|------|----------|--------------------------------------------| +| code | num | 返回值 | 0:成功<br>-400:请求错误<br>-404:错误 | +| message | str | 错误信息 | 默认为 success | +| data | obj | 数据本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +|-----------|--------|------------|--------------------| +| has_next | num | 是否有下一页 | 1:有<br>0:无 | +| list | array | 剧集列表 | | +| num | num | 当前页码 | | +| size | num | 每页数量 | | +| total | num | 总剧集数 | | + +`data` 中的 `list` 数组: + +| 项 | 类型 | 内容 | 备注 | +|------|------|-----------------|------| +| 0 | obj | 剧集信息 1 | | +| n | obj | 剧集信息 (n+1) | | +| …… | obj | …… | | + +`list` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------------|--------|----------------|----------------------------------------------------------------------| +| badge | str | 角标文本 | 例如 `大会员`、`独家` 等 | +| badge_info | obj | 角标信息 | | +| badge_type | num | 角标类型 | | +| cover | str | 封面图片 URL | | +| first_ep | obj | 第一话信息 | | +| index_show | str | 剧集进度显示 | 例如 `全48话` | +| is_finish | num | 是否完结 | `1`:完结<br>`0`:未完结 | +| link | str | 剧集播放页链接 | | +| media_id | num | 剧集 md id | | +| order | str | 排序显示文本 | 例如 `9.9分` | +| order_type | str | 排序类型 | | +| score | str | 评分 | | +| season_id | num | 剧集 ss id | | +| season_status | num | 剧集状态 | 普通剧集为 `2`,大会员或独家等有角标的剧集为 `13` | +| season_type | num | 剧集类别 | 值同参数中的 `season_type` | +| subTitle | str | 副标题 | | +| title | str | 标题 | | +| title_icon | str | 标题图标 URL | | + +`list` 项中的 `badge_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +|-----------------|------|-------------|----------| +| bg_color | str | 角标背景色 | 日间模式 | +| bg_color_night | str | 角标背景色 | 夜间模式 | +| text | str | 角标文本 | | + +`list` 项中的 `first_ep` 对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------|------|----------------|------| +| cover | str | 第一话封面 URL | | +| ep_id | num | 第一话 ep id | | + +**示例:** + +查询番剧类别索引按最高评分降序排序 + +```shell +curl -G 'https://api.bilibili.com/pgc/season/index/result' \ +--data-urlencode 'type=1' \ +--data-urlencode 'season_type=1' \ +--data-urlencode 'order=4' \ +--data-urlencode 'sort=0' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "has_next": 1, + "list": [ + { + "badge": "大会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "大会员" + }, + "badge_type": 0, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/dc1d94ded94ae470db35d76edeb106f606e27e96.png", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/archive/0a8ca0a60401b16838c8fae3d09223ead44f445a.png", + "ep_id": 2197678 + }, + "index_show": "全48话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss113090", + "media_id": 27736357, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 113090, + "season_status": 13, + "season_type": 1, + "subTitle": "平成刑侦风假面骑士", + "title": "假面骑士驰骑", + "title_icon": "" + }, + { + "badge": "大会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "大会员" + }, + "badge_type": 0, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/834bdb5d36c401179b9e91fdc1de520a6664c2a7.png", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/archive/ba36c397ede8ba668cc726c34e0aaf5c0195958c.jpg", + "ep_id": 1404783 + }, + "index_show": "全24话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss80512", + "media_id": 24449643, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 80512, + "season_status": 13, + "season_type": 1, + "subTitle": "穿越百夜,仰望千空", + "title": "Dr.STONE 石纪元 (第四季)", + "title_icon": "" + }, + { + "badge": "独家", + "badge_info": { + "bg_color": "#00C0FF", + "bg_color_night": "#0B91BE", + "text": "独家" + }, + "badge_type": 1, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/dcd6e746842fdb988775c8b5f8217ad19b6d4de2.png", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/archive/400927077a6718848bd44de634bf09a3ad029d22.jpg", + "ep_id": 1938328 + }, + "index_show": "全12话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss102891", + "media_id": 26714035, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 102891, + "season_status": 13, + "season_type": 1, + "subTitle": "可燃乌龙茶又回来了", + "title": "碧蓝之海 第二季", + "title_icon": "" + }, + { + "badge": "独家", + "badge_info": { + "bg_color": "#00C0FF", + "bg_color_night": "#0B91BE", + "text": "独家" + }, + "badge_type": 1, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/c72d6ee8b3cba39355af14bebd4857935b4fb083.png", + "first_ep": { + "cover": "https://i0.hdslb.com/bfs/bangumi/image/f9c6876d58c7dc77f04f9780d51fcac08863f9fb.png", + "ep_id": 1655818 + }, + "index_show": "更新至第13话", + "is_finish": 0, + "link": "https://www.bilibili.com/bangumi/play/ss91812", + "media_id": 25581526, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 91812, + "season_status": 13, + "season_type": 1, + "subTitle": "一马当先,万马无光", + "title": "赛马娘 芦毛灰姑娘", + "title_icon": "" + }, + { + "badge": "大会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "大会员" + }, + "badge_type": 0, + "cover": "http://i0.hdslb.com/bfs/bangumi/image/087b862b772ee4e644478a36c757a26db476193d.png", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/bangumi/1e47fe925cb543c09250a142c31c8e42ab4bcbbd.jpg", + "ep_id": 393434 + }, + "index_show": "全200话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss38157", + "media_id": 28233839, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 38157, + "season_status": 13, + "season_type": 1, + "subTitle": "最无厘头的热血动画", + "title": "银魂", + "title_icon": "" + }, + { + "badge": "大会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "大会员" + }, + "badge_type": 0, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/f3ebb500b701a387f5abde67516c5c96bbd2faff.png", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/archive/6f20908042a02bcbb4ab1e0e5f36c06cfb4eb781.png", + "ep_id": 779775 + }, + "index_show": "全28话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss46089", + "media_id": 21087073, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 46089, + "season_status": 13, + "season_type": 1, + "subTitle": "花海盛开,故人归来", + "title": "葬送的芙莉莲", + "title_icon": "" + }, + { + "badge": "独家", + "badge_info": { + "bg_color": "#00C0FF", + "bg_color_night": "#0B91BE", + "text": "独家" + }, + "badge_type": 1, + "cover": "http://i0.hdslb.com/bfs/bangumi/image/f6709b76e88f50aa132d1e09e2d8de9663a09b3e.png", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/bangumi/69c9e8b5548356e04f8a52a5a7e270fc1786123d.jpg", + "ep_id": 293001 + }, + "index_show": "全24话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss4213", + "media_id": 28223483, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 4213, + "season_status": 13, + "season_type": 1, + "subTitle": "真是high到不行", + "title": "JOJO的奇妙冒险 星尘远征军 埃及篇", + "title_icon": "" + }, + { + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "" + }, + "badge_type": 0, + "cover": "http://i0.hdslb.com/bfs/bangumi/065926cbda8f464a31293758054620cca15e5589.jpg", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/archive/315d88aa2b1e723089b29ddc2febb5b937ef68c9.jpg", + "ep_id": 249469 + }, + "index_show": "全55话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss357", + "media_id": 132112, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 357, + "season_status": 2, + "season_type": 1, + "subTitle": "童年经典,百看不厌", + "title": "猫和老鼠 旧版", + "title_icon": "" + }, + { + "badge": "", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "" + }, + "badge_type": 0, + "cover": "http://i0.hdslb.com/bfs/bangumi/e46cc26d95a6b09541a8bda484f041eebb474c1a.png", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/bangumi/e15c1305e4d54ca1a92f44e0953eee5d6006397e.jpg", + "ep_id": 247270 + }, + "index_show": "全203话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss1376", + "media_id": 1376, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 1376, + "season_status": 2, + "season_type": 1, + "subTitle": "我的老师是婴儿", + "title": "家庭教师HITMAN REBORN!", + "title_icon": "" + }, + { + "badge": "大会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "大会员" + }, + "badge_type": 0, + "cover": "http://i0.hdslb.com/bfs/bangumi/image/d432ca132f5b8e8d72257704817f270595f92148.png", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/archive/c0fa966ef05e15a52625a764b8c829b9a204c984.jpg", + "ep_id": 396924 + }, + "index_show": "全52话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss38385", + "media_id": 28234069, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 38385, + "season_status": 13, + "season_type": 1, + "subTitle": "那一年,我变为了光", + "title": "迪迦奥特曼(中配)", + "title_icon": "" + }, + { + "badge": "大会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "大会员" + }, + "badge_type": 0, + "cover": "http://i0.hdslb.com/bfs/bangumi/image/00e9bc51f9f3677f88dc9cea41fbf430ee4eff7a.png", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/archive/adc9c65cd4b224da7d3c8a70593cf3b4ee0f4906.png", + "ep_id": 397306 + }, + "index_show": "全64话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss38158", + "media_id": 28233840, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 38158, + "season_status": 13, + "season_type": 1, + "subTitle": "最无厘头的热血动画", + "title": "银魂 第二季", + "title_icon": "" + }, + { + "badge": "大会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "大会员" + }, + "badge_type": 0, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/60a1806c76d5816ddabf80ab5641c1a2bb112117.png", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/archive/18ead60d3895843e4476bc8459a8cada1e55fba1.png", + "ep_id": 2081361 + }, + "index_show": "全13话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss109360", + "media_id": 27366597, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 109360, + "season_status": 13, + "season_type": 1, + "subTitle": "用怪兽打败怪兽", + "title": "奥特银河 大怪兽之战 无尽的圣战", + "title_icon": "" + }, + { + "badge": "大会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "大会员" + }, + "badge_type": 0, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/8eb3d284a1109218ab6c61768d18942011b4a101.png", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/archive/6912de2f07dd6223b1d321b3fabfc7ce031f8ba1.png", + "ep_id": 2081328 + }, + "index_show": "全13话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss109321", + "media_id": 27362342, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 109321, + "season_status": 13, + "season_type": 1, + "subTitle": "用怪兽打败怪兽", + "title": "奥特银河 大怪兽之战", + "title_icon": "" + }, + { + "badge": "大会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "大会员" + }, + "badge_type": 0, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/c4bc29a81716afdcaa4e859176e889366a554021.png", + "first_ep": { + "cover": "https://i0.hdslb.com/bfs/bangumi/image/a5c64d1762845307cf8bb5de00327eaf7969d773.png", + "ep_id": 1718028 + }, + "index_show": "全1话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss99364?theme=movie", + "media_id": 26339285, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 99364, + "season_status": 13, + "season_type": 1, + "subTitle": "日剧感强的假面骑士", + "title": "假面骑士圣刃 深罪三重奏", + "title_icon": "" + }, + { + "badge": "大会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "大会员" + }, + "badge_type": 0, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/f72fac0118e212e577ee4a3a0b0b0e3021c90e58.png", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/archive/7b9294cbed2bd10e880a449923968d60762ae4e0.png", + "ep_id": 1692216 + }, + "index_show": "全13话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss98694", + "media_id": 26271690, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 98694, + "season_status": 13, + "season_type": 1, + "subTitle": "少年获得神奇手表", + "title": "少年骇客 第一季 中文配音", + "title_icon": "" + }, + { + "badge": "大会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "大会员" + }, + "badge_type": 0, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/00983f73ba7043f14f8a473051e8ccdf502b4466.png", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/archive/d49a210847788bb9b56ccdf7d117f67377470139.jpg", + "ep_id": 1670641 + }, + "index_show": "全26话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss97528", + "media_id": 26154494, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 97528, + "season_status": 13, + "season_type": 1, + "subTitle": "快看!是彩虹小马!", + "title": "小马宝莉 友谊的魔法 第一季 中文配音", + "title_icon": "" + }, + { + "badge": "大会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "大会员" + }, + "badge_type": 0, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/f0aa6018ab3d68b981a874a2ffc2881a8eb1d3a9.png", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/archive/8037892942512985339b60cb022a268596561eeb.png", + "ep_id": 1568817 + }, + "index_show": "全12话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss91765", + "media_id": 25576803, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 91765, + "season_status": 13, + "season_type": 1, + "subTitle": "天才变谐星?!", + "title": "失忆投捕", + "title_icon": "" + }, + { + "badge": "独家", + "badge_info": { + "bg_color": "#00C0FF", + "bg_color_night": "#0B91BE", + "text": "独家" + }, + "badge_type": 1, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/56af151182c0b499b37e59b582d756d7bae6bc9d.png", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/archive/ea0fd1b78b85f5fd4242643eeec77e965c651aed.png", + "ep_id": 1518097 + }, + "index_show": "全1话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss91516", + "media_id": 25551928, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 91516, + "season_status": 13, + "season_type": 1, + "subTitle": "主打一个不滑滑板", + "title": "无限滑板 特别篇", + "title_icon": "" + }, + { + "badge": "独家", + "badge_info": { + "bg_color": "#00C0FF", + "bg_color_night": "#0B91BE", + "text": "独家" + }, + "badge_type": 1, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/2f5946880c07914d1cccd112702884f232b647e0.png", + "first_ep": { + "cover": "https://i0.hdslb.com/bfs/bangumi/image/e38897af6ec62b387918c5966d1fa60f27affff5.png", + "ep_id": 1524613 + }, + "index_show": "全12话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss90684", + "media_id": 25467691, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 90684, + "season_status": 13, + "season_type": 1, + "subTitle": "让AI顺应你的心", + "title": "末日后酒店", + "title_icon": "" + }, + { + "badge": "大会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "大会员" + }, + "badge_type": 0, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/d2c1d3d379d385b2c6abcffd48a55a93deb6889d.png", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/archive/cf4aca7382f42d01c3d2b10f3c8a0dcc9fd011a1.jpg", + "ep_id": 1404755 + }, + "index_show": "全13话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss76133", + "media_id": 24006597, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 76133, + "season_status": 13, + "season_type": 1, + "subTitle": "教练,我想学滑冰!", + "title": "金牌得主", + "title_icon": "" + }, + { + "badge": "大会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "大会员" + }, + "badge_type": 0, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/6b431f3e7aef2fd476a11a59449096f20e5c34a4.jpg", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/archive/57d3f50996c97c804ec03dbd769b2feee9ae6f3f.png", + "ep_id": 1113923 + }, + "index_show": "全12话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss48811", + "media_id": 23053814, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 48811, + "season_status": 13, + "season_type": 1, + "subTitle": "治愈之旅的延续", + "title": "夏目友人帐 第七季", + "title_icon": "" + }, + { + "badge": "大会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "大会员" + }, + "badge_type": 0, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/6e9309a647368c4afabbfb23537f37e7b311a014.png", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/archive/847348eeaec3e4617eaffd102a402409b1905106.png", + "ep_id": 835243 + }, + "index_show": "全40话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss48643", + "media_id": 22923892, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 48643, + "season_status": 13, + "season_type": 1, + "subTitle": "小羊肖恩拯救不开心", + "title": "小羊肖恩 第一季", + "title_icon": "" + }, + { + "badge": "大会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "大会员" + }, + "badge_type": 0, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/93c420e293be6135c7b3474394239fce339bfc99.jpg", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/archive/33d907c4af25805ea283aa3bdd1223f95653acad.png", + "ep_id": 812175 + }, + "index_show": "全50话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss47245", + "media_id": 21195727, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 47245, + "season_status": 13, + "season_type": 1, + "subTitle": "本大爷要支配世界!", + "title": "虫王战队超王者", + "title_icon": "" + }, + { + "badge": "大会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "大会员" + }, + "badge_type": 0, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/67f7082099cf201a50a979a5788490c9b6989931.jpg", + "first_ep": { + "cover": "http://i0.hdslb.com/bfs/archive/df4429a10a9a113a9eac97aec1fd63d05ba475ad.png", + "ep_id": 771376 + }, + "index_show": "全272话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss45840", + "media_id": 20342554, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 45840, + "season_status": 13, + "season_type": 1, + "subTitle": "活泼又聪明的蓝精灵", + "title": "蓝精灵 中文配音", + "title_icon": "" + }, + { + "badge": "大会员", + "badge_info": { + "bg_color": "#FB7299", + "bg_color_night": "#D44E7D", + "text": "大会员" + }, + "badge_type": 0, + "cover": "https://i0.hdslb.com/bfs/bangumi/image/05b90f3e078e2f67a92df5cbf150bdd85d9f824b.jpg", + "first_ep": { + "cover": "https://i0.hdslb.com/bfs/bangumi/image/9e267f05ae866de3c368317983e5702cf46cbd72.jpg", + "ep_id": 744262 + }, + "index_show": "全52话", + "is_finish": 1, + "link": "https://www.bilibili.com/bangumi/play/ss45014", + "media_id": 20222550, + "order": "9.9分", + "order_type": "4", + "score": "9.9", + "season_id": 45014, + "season_status": 13, + "season_type": 1, + "subTitle": "如何在游戏中学习", + "title": "布鲁伊 第三季", + "title_icon": "" + } + ], + "num": 1, + "size": 25, + "total": 4147 + }, + "message": "success" +} +``` + +</details> diff --git a/bb-api-collect/docs/bangumi/timeline.md b/bb-api-collect/docs/bangumi/timeline.md new file mode 100644 index 0000000000..6742cb7c3f --- /dev/null +++ b/bb-api-collect/docs/bangumi/timeline.md @@ -0,0 +1,799 @@ +# 番剧或影视时间线 + +## 获取番剧或影视时间线 + +> https://api.bilibili.com/pgc/web/timeline +*请求方式:GET* + +鉴权方式:Cookie(SESSDATA)或APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------ | ------ | ----------------------------- | +| types | str | 类别 | 必要 | 1:`番剧`<br />3:`电影`<br />4:`国创` | +| before | num | 开始于前几日 | 必要 | ∈N∩[0,7] | +| after | num | 结束于后几日 | 必要 | ∈N∩[0,7] | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | ------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-404:错误 | +| message | str | 错误信息 | 默认为success | +| result | array | 信息本体 | | + +`result`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------------------- | ---- | +| 0 | obj | `before`天前信息 | | +| n | obj | 从`before`天前开始第n天信息 | | +| …… | obj | …… | | + +`result`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----- | -------------- | ----------------- | +| date | str | 当日日期 | | +| date_ts | num | 当日日期时间戳 | | +| day_of_week | num | 一周中第几天 | ∈N∩[1,7] | +| episodes | array | 剧集列表 | | +| is_today | num | 是否今日 | | + +`result`数组中的对象中的`episodes`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---- | +| 0 | obj | 剧集1 | | +| n | obj | 剧集(n+1) | | +| …… | obj | …… | | + +`episodes`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | -------------- | --------------- | +| cover | str | 封面图url | | +| delay | num | 是否推迟 | | +| delay_id | num | 推迟一话epid | | +| delay_index | str | 推迟一话名称 | | +| delay_reason | str | 推迟原因 | | +| ep_cover | str | 最新一话图url | | +| episode_id | num | 最新一话的epid | | +| pub_index | str | 最新一话名称 | | +| pub_time | str | 发布时间 | | +| pub_ts | num | 发布时间戳 | | +| published | num | 是否已发布 | | +| follows | str | - | | +| plays | str | - | | +| season_id | num | 剧集ssid | | +| square_cover | str | 缩略图url | | +| title | str | 剧集标题 | | + +**示例:** + +查询从`3`天前到`7`天后的`番剧`时间轴 + +```shell +curl -G 'https://api.bilibili.com/pgc/web/timeline' \ +--data-urlencode 'types=1' \ +--data-urlencode 'before=3' \ +--data-urlencode 'after=7' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "success", + "result": [ + { + "date": "5-15", + "date_ts": 1652544000, + "day_of_week": 7, + "episodes": [ + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/9918f6e67c26d6bd1ddad8dab70bcc7af3bfae9b.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/archive/0067a09911e2fa252a3ef5126d8dc5392189dd8a.jpg", + "episode_id": 508403, + "follows": "-", + "plays": "-", + "pub_index": "第3话", + "pub_time": "01:30", + "pub_ts": 1652549400, + "published": 1, + "season_id": 41416, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/926fd09277605204c2f7c94b322de3156ef9da52.png", + "title": "式守同学不只可爱而已" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/3a9815ca239735c51fc7daf2399c3721bbe00160.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/archive/56e8d4b13dac855c51060dcda286be049fde4a46.png", + "episode_id": 466766, + "follows": "-", + "plays": "-", + "pub_index": "第6话", + "pub_time": "11:00", + "pub_ts": 1652583600, + "published": 1, + "season_id": 41005, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/b3dd92da1ca35758f329fa5aa649991b118a98ca.png", + "title": "鬼灭之刃 无限列车篇 中配版" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/71d54cae830d32a5af776dcc46632146fbdba868.jpg", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/archive/00c1dff8457183671f0402e0a2826313a1994a9b.jpg", + "episode_id": 480434, + "follows": "-", + "plays": "-", + "pub_index": "第240话", + "pub_time": "17:30", + "pub_ts": 1652607000, + "published": 1, + "season_id": 5978, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/3121473d5dd03a9bcccb8490034207e724e731b3.jpg", + "title": "博人传 火影忍者新时代" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/91e75030be41d67b9f19b96bb512b0c98ae781bd.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/archive/e701f39cef52e6b0737e3463faf7cb0cee61e935.jpg", + "episode_id": 510647, + "follows": "-", + "plays": "-", + "pub_index": "第4话", + "pub_time": "20:00", + "pub_ts": 1652616000, + "published": 1, + "season_id": 41557, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/4329384cba4ab0390eae1a84a719e4649bf61cfb.png", + "title": "这个治疗有点烦" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/c9723d8c77d881a8debba2852d580e97826b43d0.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/archive/2a01ab590fd8b1331096b94cc6fc09dbdad1bbec.png", + "episode_id": 478918, + "follows": "-", + "plays": "-", + "pub_index": "第7话", + "pub_time": "21:00", + "pub_ts": 1652619600, + "published": 1, + "season_id": 41591, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/1ffa24e100583c3aa96812dea680943291c5c384.jpg", + "title": "恋爱游戏世界对路人角色很不友好" + } + ], + "is_today": 0 + }, + { + "date": "5-16", + "date_ts": 1652630400, + "day_of_week": 1, + "episodes": [ + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/e468c854628b97b5373baaf4c43e1346a9806baa.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/archive/219161297558531d2475da73e863dc237e83baa1.png", + "episode_id": 511342, + "follows": "-", + "plays": "-", + "pub_index": "第1话", + "pub_time": "20:00", + "pub_ts": 1652702400, + "published": 1, + "season_id": 41419, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/75a291010c128ce2de17267fd2a4842d19898236.png", + "title": "魔法使黎明期" + } + ], + "is_today": 0 + }, + { + "date": "5-17", + "date_ts": 1652716800, + "day_of_week": 2, + "episodes": [ + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/4e6c505b1b1631c542ea76c3da1ce08bb43faad6.jpg", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/archive/bf37e15c52889a7a9dca16346354bb7c6663c899.png", + "episode_id": 510132, + "follows": "-", + "plays": "-", + "pub_index": "第146话", + "pub_time": "18:00", + "pub_ts": 1652781600, + "published": 1, + "season_id": 23841, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/5c2f289eac0ec49bc5e6b9483f4191c42ffa2254.jpg", + "title": "美妙☆频道" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/9eef1df9ab157be52d2c4d70d3500442f00cafc3.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/archive/d9831c3170bcbba38edc2204ee5059f583823913.png", + "episode_id": 509043, + "follows": "-", + "plays": "-", + "pub_index": "第11话", + "pub_time": "18:00", + "pub_ts": 1652781600, + "published": 1, + "season_id": 38950, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/13fd7c96659a20c61409e155a2a913a59348d122.png", + "title": "魔法纪录 魔法少女小圆外传 第二季" + } + ], + "is_today": 0 + }, + { + "date": "5-18", + "date_ts": 1652803200, + "day_of_week": 3, + "episodes": [ + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/fba0229f1a6eec6ed692b7ae91c634d5cbde0727.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/0ebefe529449ff98d544395d1576402bb0d0ae5b.png", + "episode_id": 510498, + "follows": "-", + "plays": "-", + "pub_index": "第7话", + "pub_time": "21:00", + "pub_ts": 1652878800, + "published": 0, + "season_id": 41413, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/247f8326019e035338529306e94baea3336c43b4.png", + "title": "盾之勇者成名录 第二季" + } + ], + "is_today": 1 + }, + { + "date": "5-19", + "date_ts": 1652889600, + "day_of_week": 4, + "episodes": [ + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/99277ce3f41d1cb4dcda9f6010ebe9c9e6d345e5.jpg", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/c989d496e3a075e8bc134b0d4d53d6ca5c2ae634.jpg", + "episode_id": 510760, + "follows": "-", + "plays": "-", + "pub_index": "第2话", + "pub_time": "12:00", + "pub_ts": 1652932800, + "published": 0, + "season_id": 41417, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/ef45828cb99309169e95d1bf54ec833d7968bf22.png", + "title": "夏日重现" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/1cd26af47cf9d9ca045ec36f56ce14a66867438d.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/3dc8d348937528779b7ad9a3070d37276518080f.png", + "episode_id": 399655, + "follows": "-", + "plays": "-", + "pub_index": "第50话", + "pub_time": "18:00", + "pub_ts": 1652954400, + "published": 0, + "season_id": 38353, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/4bd7b0a4c270ce62ca2adf3e18487a96e4fde92e.png", + "title": "通灵王" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/5f5b16bc8edd1310fbf0ac8bce04a11144dc858e.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/aed167a32445ed294ea75ed674442c766d56cb2a.png", + "episode_id": 511494, + "follows": "-", + "plays": "-", + "pub_index": "第4话", + "pub_time": "23:00", + "pub_ts": 1652972400, + "published": 0, + "season_id": 41422, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/924c550415ccdd142145dbf102bd81fcbb018ffd.png", + "title": "骸骨骑士大人奇幻世界冒险中" + } + ], + "is_today": 0 + }, + { + "date": "5-20", + "date_ts": 1652976000, + "day_of_week": 5, + "episodes": [ + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/a29f3b00a94d1b4a029054f72963cc10d98bae99.jpg", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/4b9b98677b039b9126614f5a5259aa1484cea227.jpg", + "episode_id": 510757, + "follows": "-", + "plays": "-", + "pub_index": "第2话", + "pub_time": "01:28", + "pub_ts": 1652981280, + "published": 0, + "season_id": 41520, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/2a0ca7be587039eef380f802f8ae71bd21d2ea2c.png", + "title": "街角魔族 第二季" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/ecb52c79def9f5a6099c5a0770f56e20479fb008.jpg", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/36d3079e1b24395b07f9f95128adc9568459c3e5.png", + "episode_id": 478238, + "follows": "-", + "plays": "-", + "pub_index": "第17话", + "pub_time": "02:25", + "pub_ts": 1652984700, + "published": 0, + "season_id": 40873, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/13f437706d3f27dee7566a5e489928605663e40f.png", + "title": "川尻小玉的懒散生活" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/a7517ca25c5c7a132a16f589e3a3c4d9f49af196.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/17f34f6c51b8b9371af1998f0612d51f0ba03df2.png", + "episode_id": 508842, + "follows": "-", + "plays": "-", + "pub_index": "第6话", + "pub_time": "07:00", + "pub_ts": 1653001200, + "published": 0, + "season_id": 41534, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/3267da68f7f832ccfc7eaa77c6ab3fb806d2de98.png", + "title": "银河英雄传说:全新命题 激战" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/fecb68763f24d371167389abedf05742b0bf024f.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/f4116e5dcc44d6104cd72d9e0e833cde3959a835.png", + "episode_id": 476164, + "follows": "-", + "plays": "-", + "pub_index": "第32话", + "pub_time": "18:25", + "pub_ts": 1653042300, + "published": 0, + "season_id": 38366, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/56b8e4369871fc0c55bfa9df3f3f8002d40f0691.png", + "title": "妖怪手表" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/81c9dc929e6071a2d42f1b5a207bbcef4a1aead7.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/7c62ad9f559ee6b0fafc1c08d990636c21c4fa8d.png", + "episode_id": 510653, + "follows": "-", + "plays": "-", + "pub_index": "第7话", + "pub_time": "21:30", + "pub_ts": 1653053400, + "published": 0, + "season_id": 41432, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/930ae7ff644dc31ada9abcb3ea30fee5fbc6f397.png", + "title": "约会大作战 第四季" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/d464543dd6720efd43e5487acee74b646423b4d1.jpg", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/ca7a19d51feb54162d8f286af416aa5a804e72c4.png", + "episode_id": 511497, + "follows": "-", + "plays": "-", + "pub_index": "第7话", + "pub_time": "22:00", + "pub_ts": 1653055200, + "published": 0, + "season_id": 41418, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/ab50117450baffba62c71c80052ecbad1842a1f3.png", + "title": "恋爱要在世界征服后" + } + ], + "is_today": 0 + }, + { + "date": "5-21", + "date_ts": 1653062400, + "day_of_week": 6, + "episodes": [ + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/68aee547fc85b1eab8be3d5c7e946276e4252b79.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/75583ce830522c6fd391cd6ffac31e3ab96db50e.png", + "episode_id": 510568, + "follows": "-", + "plays": "-", + "pub_index": "第8话", + "pub_time": "00:30", + "pub_ts": 1653064200, + "published": 0, + "season_id": 39725, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/a4fa3f4ecaa4efc883aa1ef2ca7ed736edb38b8c.png", + "title": "理科生坠入情网,故尝试证明。 第二季" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/f711a34e0f18293ba5068fd85d8de891bb01c2be.jpg", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/aa3e0fc7ecb422c7c8ed107267befaa18f6dcf89.png", + "episode_id": 510935, + "follows": "-", + "plays": "-", + "pub_index": "第8话", + "pub_time": "00:30", + "pub_ts": 1653064200, + "published": 0, + "season_id": 41506, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/d2dea82606b8dd0ee7934c62dbc7016b0a17255f.png", + "title": "处刑少女的生存之道" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/91ec1f4bc4af307dbfbd68c9ba6d838b27adee0f.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/6d9499e4e5453e5e353939980524102c3b707edb.png", + "episode_id": 477129, + "follows": "-", + "plays": "-", + "pub_index": "第8话", + "pub_time": "01:25", + "pub_ts": 1653067500, + "published": 0, + "season_id": 39180, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/f23cf19d1d6068e83edfd6b3d207ce692ef58ef3.png", + "title": "测不准的阿波连同学" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/bad807ac5a8d4094ead26c08ec2d9b97dbb8c4a1.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/8e563a29a9fb6b91df791a12eb5f869d038fc1e9.png", + "episode_id": 510677, + "follows": "-", + "plays": "-", + "pub_index": "第2话", + "pub_time": "02:00", + "pub_ts": 1653069600, + "published": 0, + "season_id": 41533, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/4ef341fa95646a7c2549e08ba00358b411fba0ee.png", + "title": "舞动不止" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/4ab5cf1efbd1c5883b8f0580cb0304f5452c4665.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/8ea1f90444d04a0b989584df9f18e59a824b0e90.png", + "episode_id": 341403, + "follows": "-", + "plays": "-", + "pub_index": "第71话", + "pub_time": "09:30", + "pub_ts": 1653096600, + "published": 0, + "season_id": 34425, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/ae36d43ebe7ea7176d18bab794de3d8930284feb.png", + "title": "勇者斗恶龙 达伊的大冒险" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/23f393513ab8fdfbb351aa80e8b7423e7361ad98.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/d470a1bf53c96210f2238024dc1947f52cb58f3a.png", + "episode_id": 510681, + "follows": "-", + "plays": "-", + "pub_index": "第2话", + "pub_time": "18:00", + "pub_ts": 1653127200, + "published": 0, + "season_id": 41535, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/f3f69f8747e8464ba46b9bbe24678966809c8021.png", + "title": "Love All Play热血羽毛球" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/38e2a273f528fd01c34f1fc4df0f69c64487efad.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/6c108526eade13d04882b803f1d1e0dfe2a1886e.png", + "episode_id": 459329, + "follows": "-", + "plays": "-", + "pub_index": "第1101话", + "pub_time": "19:30", + "pub_ts": 1653132600, + "published": 0, + "season_id": 33378, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/ecc9a64f3f43eb00ee2bf1549b6ab76182cf5f8b.png", + "title": "名侦探柯南" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/f641f81aa1933d73c91d5ef76b525acbcdbcf3e7.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/c7ccf71fcf65b4e5655403b01a7af3529d2891e8.png", + "episode_id": 510754, + "follows": "-", + "plays": "-", + "pub_index": "第10话", + "pub_time": "20:00", + "pub_ts": 1653134400, + "published": 0, + "season_id": 39433, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/1b4cc42a3909ad2d03563d3163b105c6cad80d20.png", + "title": "鬼灭之刃 游郭篇" + } + ], + "is_today": 0 + }, + { + "date": "5-22", + "date_ts": 1653148800, + "day_of_week": 7, + "episodes": [ + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/3a9815ca239735c51fc7daf2399c3721bbe00160.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/30908825b7c8076b9d7b58d8cd949a87f48866e6.png", + "episode_id": 466767, + "follows": "-", + "plays": "-", + "pub_index": "第7话", + "pub_time": "11:00", + "pub_ts": 1653188400, + "published": 0, + "season_id": 41005, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/b3dd92da1ca35758f329fa5aa649991b118a98ca.png", + "title": "鬼灭之刃 无限列车篇 中配版" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/71d54cae830d32a5af776dcc46632146fbdba868.jpg", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/3baf5335e3f1df882b54d69c0c6c9ffa76069eef.png", + "episode_id": 480435, + "follows": "-", + "plays": "-", + "pub_index": "第241话", + "pub_time": "17:30", + "pub_ts": 1653211800, + "published": 0, + "season_id": 5978, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/3121473d5dd03a9bcccb8490034207e724e731b3.jpg", + "title": "博人传 火影忍者新时代" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/91e75030be41d67b9f19b96bb512b0c98ae781bd.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/cff6617c1c7e28f8cd9db3d33d5366a5029e3aa9.png", + "episode_id": 510648, + "follows": "-", + "plays": "-", + "pub_index": "第5话", + "pub_time": "20:00", + "pub_ts": 1653220800, + "published": 0, + "season_id": 41557, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/4329384cba4ab0390eae1a84a719e4649bf61cfb.png", + "title": "这个治疗有点烦" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/c9723d8c77d881a8debba2852d580e97826b43d0.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/c91b2b96c272eb28aa3dd74aa58fc272fc62d577.png", + "episode_id": 478919, + "follows": "-", + "plays": "-", + "pub_index": "第8话", + "pub_time": "21:00", + "pub_ts": 1653224400, + "published": 0, + "season_id": 41591, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/1ffa24e100583c3aa96812dea680943291c5c384.jpg", + "title": "恋爱游戏世界对路人角色很不友好" + } + ], + "is_today": 0 + }, + { + "date": "5-23", + "date_ts": 1653235200, + "day_of_week": 1, + "episodes": [ + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/e468c854628b97b5373baaf4c43e1346a9806baa.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/26f87214a2481680a93bfda294ac080c0b336a40.png", + "episode_id": 511343, + "follows": "-", + "plays": "-", + "pub_index": "第2话", + "pub_time": "20:00", + "pub_ts": 1653307200, + "published": 0, + "season_id": 41419, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/75a291010c128ce2de17267fd2a4842d19898236.png", + "title": "魔法使黎明期" + } + ], + "is_today": 0 + }, + { + "date": "5-24", + "date_ts": 1653321600, + "day_of_week": 2, + "episodes": [ + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/4e6c505b1b1631c542ea76c3da1ce08bb43faad6.jpg", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/4e6c505b1b1631c542ea76c3da1ce08bb43faad6.jpg", + "episode_id": 510133, + "follows": "-", + "plays": "-", + "pub_index": "第147话", + "pub_time": "18:00", + "pub_ts": 1653386400, + "published": 0, + "season_id": 23841, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/5c2f289eac0ec49bc5e6b9483f4191c42ffa2254.jpg", + "title": "美妙☆频道" + }, + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/9eef1df9ab157be52d2c4d70d3500442f00cafc3.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/a651c55bb430cdea19d5f4253969d1f7b83567c7.png", + "episode_id": 509044, + "follows": "-", + "plays": "-", + "pub_index": "第12话", + "pub_time": "18:00", + "pub_ts": 1653386400, + "published": 0, + "season_id": 38950, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/13fd7c96659a20c61409e155a2a913a59348d122.png", + "title": "魔法纪录 魔法少女小圆外传 第二季" + } + ], + "is_today": 0 + }, + { + "date": "5-25", + "date_ts": 1653408000, + "day_of_week": 3, + "episodes": [ + { + "cover": "http://i0.hdslb.com/bfs/bangumi/image/fba0229f1a6eec6ed692b7ae91c634d5cbde0727.png", + "delay": 0, + "delay_id": 0, + "delay_index": "", + "delay_reason": "", + "ep_cover": "http://i0.hdslb.com/bfs/bangumi/image/0ebefe529449ff98d544395d1576402bb0d0ae5b.png", + "episode_id": 510499, + "follows": "-", + "plays": "-", + "pub_index": "第8话", + "pub_time": "21:00", + "pub_ts": 1653483600, + "published": 0, + "season_id": 41413, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/247f8326019e035338529306e94baea3336c43b4.png", + "title": "盾之勇者成名录 第二季" + } + ], + "is_today": 0 + } + ] +} +``` + +</details> \ No newline at end of file diff --git a/bb-api-collect/docs/bangumi/videostream_url.md b/bb-api-collect/docs/bangumi/videostream_url.md new file mode 100644 index 0000000000..e8a53da758 --- /dev/null +++ b/bb-api-collect/docs/bangumi/videostream_url.md @@ -0,0 +1,359 @@ +# 视频流URL + +<img src="../../assets/img/download.svg" width="100" height="100"/> + +B站的番剧视频为http流媒体,需要对应的api以视频id获取取流url,并进行取流 + +## qn视频清晰度标识 + +**注:该值在dash模式且非下载模式时无效** + +| 值 | 含义 | 备注 | +|-----|-------------|-----------------------------------------------------------------------------| +| 6 | 240P 极速 | 仅mp4方式支持 | +| 16 | 360P 流畅 | | +| 32 | 480P 清晰 | | +| 64 | 720P 高清 | web端默认值<br />B站前端需要登录才能选择,但是直接发送请求可以不登录就拿到720P的取流地址<br />**无720P时则为720P60** | +| 74 | 720P60 高帧率 | 需要认证登录账号 | +| 80 | 1080P 高清 | TV端与APP端默认值<br />需要认证登录账号 | +| 100 | 智能修复 | 仅支持dash方式<br />需要`fnval&12240=12240`<br />需要认证登录账号 | +| 112 | 1080P+ 高码率 | 大多情况需求认证大会员账号 | +| 116 | 1080P60 高帧率 | 大多情况需求认证大会员账号 | +| 120 | 4K 超清 | 需要`fnval&128=128`且`fourk=1`<br />大多情况需求认证大会员账号 | +| 125 | HDR 真彩色 | 仅支持dash方式<br />需要`fnval&64=64`<br />大多情况需求认证大会员账号 | +| 126 | 杜比视界 | 仅支持dash方式<br />需要`fnval&512=512`<br />大多情况需求认证大会员账号 | +| 127 | 8K 超高清 | 仅支持dash方式<br />需要`fnval&1024=1024`<br />大多情况需求认证大会员账号 | + +例如:请求1080P+的视频,则`qn=112` + +## fnver视频流版本标识 + +目前该值恒为0,即`fnver=0` + +## fnval视频流格式标识 + +该代码为二进制属性位,如需组合功能需要使用`OR`运算结合一下数值 + +| 值 | 含义 | 备注 | +|------|-------------|-------------------------------------------------------------| +| 0 | flv格式 | 仅H.264编码<br />部分老视频存在分段现象<br />与mp4格式及dash格式互斥 | +| 1 | mp4格式 | 仅H.264编码<br />不存在视频分段<br />与flv格式及dash格式互斥 | +| 16 | dash格式 | H.264编码或H.265编码<br />部分老视频的清晰度上限低于flv格式<br />与mp4格式及flv格式互斥 | +| 64 | 是否需求 HDR 视频 | 必须为dash格式<br />需要`qn=125`<br />大多情况需求认证大会员账号 | +| 128 | 是否需求 4K 分辨率 | 该值与`fourk`字段协同作用<br />需要`qn=120`<br />大多情况需求认证大会员账号 | +| 256 | 是否需求杜比音频 | 必须为dash格式<br />大多情况需求认证大会员账号 | +| 512 | 是否需求杜比视界 | 必须为dash格式<br />大多情况需求认证大会员账号 | +| 1024 | 是否需求 8K 分辨率 | 必须为dash格式<br />需要`qn=127`<br />大多情况需求认证大会员账号 | +| 2048 | 是否需求 av1 编码 | 必须为dash格式 | +| 12240 | 是否需求智能修复 | 必须为dash格式<br />需要认证大会员账号 | + +例如:请求dash格式且需要HDR的视频流,则`fnval=16|64=80` + +## 视频编码代码 + +| 值 | 含义 | 备注 | +|-----|--------|----------| +| 7 | AVC编码 | 8K视频无此格式 | +| 12 | HEVC编码 | | +| 13 | AV1编码 | | + +## 视频伴音音质代码 + +| 值 | 含义 | +|-------|------| +| 30216 | 64K | +| 30232 | 132K | +| 30280 | 192K | + +## 获取番剧视频流URL + +> https://api.bilibili.com/pgc/player/web/playurl + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +--- + +关于视频流会员鉴权: + +- 获取480P及以上清晰度视频时需要登录(Cookie) + +- 获取高帧率(1080P60)/高码率(1080P+)视频时需要有大会员的账号登录(Cookie) + +- 获取会员专属番剧视频时需要登录(Cookie) + +--- + +获取的url有效时间为120min,超时失效需要重新获取 + +**部分视频**会有**分段**,需要特别注意 + +若视频有分P,仅为单P的视频的url,换P则需更换cid重新获取 + +需要设置Referer为`https://www.bilibili.com`,否则无法获取1080清晰度以上的流信息。 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|---------------|-----|----------|--------|--------------------------------------------------------------------------------------------------| +| avid | num | 稿件avid | 非必要 | | +| bvid | str | 稿件bvid | 非必要 | | +| ep_id | num | 稿件epid | 必要(可选) | ep_id与cid任选一个 | +| cid | num | 视频cid | 必要(可选) | ep_id与cid任选一个 | +| qn | num | 视频清晰度选择 | 非必要 | 未登录默认32(480P)<br />登录默认64(720P)<br />**值含义见上表**<br />注:dash方式无效 | +| fnval | num | 视频获取方式选择 | 非必要 | 默认为0<br />0 2:flv方式(可能会有分段)<br />1:低清mp4方式(仅240P与360P,且限速65K/s)<br />16 80:dash方式(音视频分流,支持H.265) | +| fnver | num | 0 | 非必要 | 固定为0 | +| fourk | num | 是否允许4K视频 | 非必要 | 默认为0<br />画质最高1080P:0<br />画质最高4K:1 | +| session | str | | 非必要 | 从视频播放页的网页源码中获取 | +| from_client | str | BROWSER | 非必要 | | +| drm_tech_type | num | 2 | 非必要 | | + + + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----------------------|------|------------------------------------| +| code | num | 返回值 | 0:成功 <br />-400:请求错误<br />-404:无视频 | +| message | str | 错误信息 | 成功为success | +| result | 有效时:obj<br />无效时:null | 数据本体 | | + +`result`对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------------------|-------|-----------------------------------|----------------------------| +| code | num | 0 | 作用尚不明确 | +| is_preview | num | 0 | 作用尚不明确 | +| fnver | num | 请求时提供的fnver | | +| fnval | num | 请求时提供的fnval | | +| video_project | bool | true | | +| type | str | 视频流类型(DASH、FLV、MP4) | DASH | +| bp | num | 是否可以承包 | 0 | +| vip_type | num | 当前用户大会员类型 | | +| vip_status | num | 当前用户大会员状态 | | +| is_drm | bool | false | | +| no_rexcode | num | 0 | | +| has_paid | bool | false | | +| status | num | 2 | | +| from | str | local | 作用尚不明确 | +| result | str | suee | 作用尚不明确 | +| message | str | 空 | 作用尚不明确 | +| quality | num | 当前的视频分辨率代码 | **值含义见上表** | +| format | str | 视频格式 | | +| timelength | num | 视频长度 | 单位为毫秒<br />不同分辨率/格式可能有略微差异 | +| accept_format | str | 视频支持的全部格式 | 每项用`,`分隔 | +| accept_description | array | 视频支持的分辨率列表 | | +| accept_quality | array | 视频支持的分辨率代码列表 | **值含义见上表** | +| video_codecid | num | 默认选择视频流的编码id | 见**视频编码代码** | +| seek_param | str | 固定值:start | 作用尚不明确 | +| seek_type | str | offset(dash、flv)<br/> second(mp4) | 作用尚不明确 | +| durl | array | 视频分段 | **注:仅flv/mp4存在此项** | +| dash | obj | dash音视频流信息 | **注:仅dash存在此项** | +| support_formats | array | 支持格式的详细信息 | | +| clip_info_list | array | | 空,待补充 | +| record_info | obj | 备案登记信息 | | + +`result`中的`accept_description`数组: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|------------|-----| +| 0 | str | 分辨率名称1 | | +| n | str | 分辨率名称(n+1) | | +| …… | str | …… | | + +`result`中的`accept_quality`数组: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|------------|-----| +| 0 | str | 分辨率代码1 | | +| n | str | 分辨率代码(n+1) | | +| …… | str | …… | | + +`result`中的`support_formats`数组: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|---------------|-----| +| 0 | obj | 播放格式详细信息1 | | +| n | obj | 播放格式详细信息(n+1) | | +| …… | obj | …… | | + +`support_formats`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|-----------------|-------|---------|-----| +| quality | num | 视频清晰度代码 | | +| format | str | 视频格式 | | +| new_description | str | 格式描述 | | +| description | str | 格式描述 | | +| display_desc | str | 格式描述 | | +| superscript | str | (?) | | +| codecs | array | 编码格式列表 | | +| need_login | bool | 需要登录 | | +| need_vip | bool | 需要大会员 | | + +`support_formats`中的`codecs`数组: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|------|-----------------------------| +| 0 | str | 编码格式 | 如:avc1.640032,意为AVC编码 | +| 1 | str | 编码格式 | 如:hev1.1.6.L153.90,意为HEVC编码 | + +`result`中的`record_info`对象: + +| 项 | 类型 | 内容 | 备注 | +|-------------|-----|------|-----------------------| +| record_icon | str | 空串 | | +| record | str | 显示文案 | 登记号:10417060172092207 | + +--- + +**flv/mp4方式:** + +`result`中的`durl`数组: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|-------------|------------------| +| 0 | obj | 视频分段1信息 | **注:仅flv方式具有分段** | +| n | obj | 视频分段(n+1)信息 | | +| …… | obj | …… | | + +`durl`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|------------|-------|--------|-----------------------------------| +| order | num | 视频分段序号 | 某些视频会分为多个片段(从1顺序增长) | +| length | num | 视频长度 | 单位为毫秒 | +| size | num | 视频大小 | 单位为Byte | +| vhead | str | 空 | 作用尚不明确 | +| url | str | 视频流url | **注:url内容存在转义符**<br />有效时间为120min | +| backup_url | array | 备用视频流 | | + +`durl`数组中的对象中的`backup_url`数组: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|----------------|-----------------------------------| +| 0 | str | 备用视频流url 1 | **注:url内容存在转义符**<br />有效时间为120min | +| n | str | 备用视频流url (n+1) | | +| …… | str | …… | | + +**示例:** + +**视频无分段时:** + +获取视频`ep85046`/`av2325306`中的1P(cid=`3629601`)的视频流url,清晰度为480p,使用flv方式获取 + +avid/epid方式: + +```shell +curl -G 'https://api.bilibili.com/pgc/player/web/playurl' \ +--data-urlencode 'avid=2325306' \ +--data-urlencode 'cid=3629601' \ +--data-urlencode 'ep_id=85046' \ +-b 'SESSDATA=xxx' +``` +https://api.bilibili.com/pgc/player/web/playurl?avid=2325306&cid=3629601&ep_id=85046 + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "success", + "result": { + "accept_format": "flv480,mp4", + "code": 0, + "seek_param": "start", + "is_preview": 0, + "fnval": 0, + "video_project": true, + "fnver": 0, + "type": "FLV", + "bp": 0, + "result": "suee", + "seek_type": "offset", + "from": "local", + "video_codecid": 7, + "record_info": { + "record_icon": "", + "record": "" + }, + "durl": [ + { + "size": 111138876, + "ahead": "", + "length": 1394090, + "vhead": "", + "backup_url": [ + "https://upos-sz-mirrorcoso1.bilivideo.com/upgcxcode/01/96/3629601/3629601_da8-1-32.flv?e=ig8euxZM2rNcNbRVhwdVhwdlhWdVhwdVhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1656098195&gen=playurlv2&os=coso1bv&oi=2946990771&trid=a1db84b216ea45dd89225f02a09093fdp&mid=0&platform=pc&upsig=878be08cc0e6bdea705952529e7e6785&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform&bvc=vod&nettype=0&orderid=1,3&agrr=1&bw=79726&logo=40000000", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/01/96/3629601/3629601_da8-1-32.flv?e=ig8euxZM2rNcNbRVhwdVhwdlhWdVhwdVhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1656098195&gen=playurlv2&os=cosbv&oi=2946990771&trid=a1db84b216ea45dd89225f02a09093fdp&mid=0&platform=pc&upsig=8c31064c84d8e981704815992cfe315c&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform&bvc=vod&nettype=0&orderid=2,3&agrr=1&bw=79726&logo=40000000" + ], + "url": "https://cn-lnsy-cu-v-02.bilivideo.com/upgcxcode/01/96/3629601/3629601_da8-1-32.flv?e=ig8euxZM2rNcNbRVhwdVhwdlhWdVhwdVhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1656098195&gen=playurlv2&os=bcache&oi=2946990771&trid=0000a1db84b216ea45dd89225f02a09093fdp&mid=0&platform=pc&upsig=7a5c4f25b9056359127191390a73bedc&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform&cdnid=3281&bvc=vod&nettype=0&orderid=0,3&agrr=1&bw=79726&logo=80000000", + "order": 1, + "md5": "" + } + ], + "no_rexcode": 0, + "format": "flv480", + "support_formats": [ + { + "display_desc": "480P", + "superscript": "", + "codecs": [ ], + "format": "flv480", + "description": "清晰 480P", + "quality": 32, + "new_description": "480P 清晰" + }, + { + "display_desc": "360P", + "superscript": "", + "codecs": [ ], + "format": "mp4", + "description": "流畅 360P", + "quality": 16, + "new_description": "360P 流畅" + } + ], + "message": "", + "accept_quality": [ + 32, + 16 + ], + "quality": 32, + "timelength": 1394090, + "has_paid": false, + "clip_info_list": [ ], + "accept_description": [ + "清晰 480P", + "流畅 360P" + ], + "status": 2 + } +} +``` + +</details> + +## 视频的取流(web端及APP端) + +**注意:** + +1. 如flv模式则可能产生分段情况,将`$.data.durl[1-n].url`或`$.data.durl[1-n].backup_url[0]`中的内容作为url进行GET操作, 如果有多个视频, 需要手动合并处理 +2. 如mp4模式则需要获取对应的视频流(方法同上) +3. 如dash模式则需要同时获取对应的视频流和伴音流(方法同上) +4. web端取流需要验证防盗链,即`referer`为 `.bilibili.com`域名下且UA不能为空;app端也需要验证防盗链,即UA需要含有`Mozilla/5.0 BiliDroid/*.*.* (bbcallen@gmail.com)`(*为版本);如`referer`或UA错误的情况会被判定为盗链,返回403 Forbidden故无法取流 +5. **注意unicode转义符** + +以上述视频流url为例: + +```shell +wget 'https://upos-sz-mirrorhwo1.bilivideo.com/upgcxcode/01/96/3629601/3629601_da8-1-32.flv?e=ig8euxZM2rNcNbRVhwdVhwdlhWdVhwdVhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1656098026&gen=playurlv2&os=hwo1bv&oi=0&trid=f0a1d2d854264369803462f3dd524154p&mid=0&platform=pc&upsig=76c1438153942fda51fbf4eb07e6e5a1&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform&bvc=vod&nettype=0&orderid=0,2&agrr=1&bw=79726&logo=80000000' \ +--referer 'https://www.bilibili.com' \ +-O 'Download_video.flv' +``` + +响应正文将返回一个flv文件 diff --git a/bb-api-collect/docs/blackroom/banlist.md b/bb-api-collect/docs/blackroom/banlist.md new file mode 100644 index 0000000000..9895a0c08e --- /dev/null +++ b/bb-api-collect/docs/blackroom/banlist.md @@ -0,0 +1,301 @@ +# 封禁公示 + +## Enum类型代码 + +### 表1:已知的封禁原因类型代码总览 + +| 代码 | 含义 | +| ---- | -------------------- | +| 1 | 刷屏 | +| 2 | 抢楼 | +| 3 | 发布色情低俗信息 | +| 4 | 发布赌博诈骗信息 | +| 5 | 发布违禁相关信息 | +| 6 | 发布垃圾广告信息 | +| 7 | 发布人身攻击言论 | +| 8 | 发布侵犯他人隐私信息 | +| 9 | 发布引战言论 | +| 10 | 发布剧透信息 | +| 11 | 恶意添加无关标签 | +| 12 | 恶意删除他人标签 | +| 13 | 发布色情信息 | +| 14 | 发布低俗信息 | +| 15 | 发布暴力血腥信息 | +| 16 | 涉及恶意投稿行为 | +| 17 | 发布非法网站信息 | +| 18 | 发布传播不实信息 | +| 19 | 发布怂恿教唆信息 | +| 20 | 恶意刷屏 | +| 21 | 账号违规 | +| 22 | 恶意抄袭 | +| 23 | 冒充自制原创 | +| 24 | 发布青少年不良内容 | +| 25 | 破坏网络安全 | +| 26 | 发布虚假误导信息 | +| 27 | 仿冒官方认证账号 | +| 28 | 发布不适宜内容 | +| 29 | 违反运营规则 | +| 30 | 恶意创建话题 | +| 31 | 发布违规抽奖 | +| 32 | 恶意冒充他人 | + +### 表2:已知的违规类型代码 + +| 代码 | 含义 | +| ---- | -------- | +| 0 | 全部类型 | +| 1 | 评论 | +| 2 | 弹幕 | +| 3 | 私信 | +| 4 | 标签 | +| 5 | 个人资料 | +| 6 | 投稿 | +| 8 | 专栏 | +| 10 | 动态 | +| 11 | 相簿 | + +## 获取封禁用户公示列表 + +> https://api.bilibili.com/x/credit/blocked/list + +*请求方式:GET* + +每页最多10项 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ------------------------------------------------------------ | +| btype | num | 来源筛选 | 非必要 | 空:全部类型<br />`0`:系统封禁<br />`1`:风纪仲裁(仲裁系统升级后此类型已不再更新) | +| otype | num | 类型筛选 | 非必要 | **见[表2](#表2已知的违规类型代码)**<br />默认为`0`:全部类型 | +| pn | num | 页码 | 非必要 | 默认为`1` | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | -------- | ------------ | +| code | num | 返回值 | `0`:成功 | +| message | str | 错误信息 | 默认为`0` | +| ttl | num | `1` | | +| data | array | 公示列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ------ | --------------- | ---- | +| 0 | object | 封禁公示1 | | +| n | object | 封禁公示(n+1) | | +| …… | object | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------- | ---- | ---------------- | ------------------------------------------- | +| id | num | 封禁公示id | | +| uname | str | 对象用户名 | | +| face | str | 对象用户头像url | | +| uid | num | 对象用户mid | | +| originTitle | str | 来源标题 | | +| blockedRemark | str | | | +| originUrl | str | 来源url | | +| originContentModify | str | 裁决正文 | | +| originType | num | 来源类型 | **见[表2](#表2已知的违规类型代码)** | +| originTypeName | str | 来源名 | | +| punishTitle | str | 公示标题 | | +| punishTime | num | 处罚时间 | 时间戳 | +| punishType | num | 处理手段类型 | `2`:封禁<br />`3`:永久封禁 | +| punishTypeName | str | 处理手段名 | | +| moralNum | num | `0`节操值 | 被封禁用户节操值均为`0` | +| blockedDays | num | 封禁天数 | 永封为`0` | +| publishStatus | num | `1` | 作用尚不明确 | +| blockedType | num | 处理来源 | `0`:系统封禁<br />1:风纪仲裁 | +| blockedForever | num | 是否永封 | `0`:非永封<br />`1`:永封 | +| reasonType | num | 封禁原因类型 | **见[表1](#表1已知的封禁原因类型代码总览)** | +| reasonTypeName | str | 封禁原因类型名称 | | +| operatorName | str | 空 | 作用尚不明确 | +| caseId | num | 仲裁信息id | 系统封禁时固定为0 | +| ctime | num | 创建时间 | 时间戳 | +| commentSum | num | 该条目评论数 | | + +**示例:** + +查询所有类型,所有来源的第1页的封禁公示列表 + +```shell +curl -G 'https://api.bilibili.com/x/credit/blocked/list' \ +--data-urlencode 'btype=' \ +--data-urlencode 'otype=0' \ +--data-urlencode 'pn=1' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [{ + "id": 1118220, + "uname": "漫城林语", + "face": "http://i2.hdslb.com/bfs/face/970f2da4a58f83879e69e259f4a9d3587cba03f0.jpg", + "uid": 135913, + "originTitle": "【罗翔】聊聊网络喷子与键盘侠", + "blockedRemark": "内容涉及人身攻击", + "originUrl": "https://www.bilibili.com/video/av752825895", + "originContentModify": "<p>案情:</p><p>1、大量刷屏/引战</p><p>我看新闻了,竹鼠全部被ZF无害化处理了,看的爽死我了,亏死你们,啊哈哈哈(x10)</p><p>【BV16g4y187he,2020-4-21 10:46:23~10:46:47】</p><p>2、大量人身攻击</p><p>N * * L</p><p>Deine Mu**er ist tot. (x10)</p><p>【BV1rk4y1R7id,2020-4-21 20:31:08~20:32:23】</p><p>3、引战</p><p>每次看他厨房乱七八糟的,可能有数不清的小强,你们还看美食看的有味也是奇PA</p><p>【BV1Kg4y1z7mA,2020-4-22  00:52:37】<br/></p><p>批注:</p><p>满地狼藉招摇过,人皆愤懑怒拳握。</p><p>余恶不堪漏夜扫,正气于心涤龌龊。</p><p><br/></p><p>(发现违规引战、人身攻击、刷屏评论,请按照相应分类进行举报。若发现反复进行上述行为,可联系工作人员反馈相关违规账号信息,我们会予以排查。)</p><p>(案例感想请发布在小黑屋评论区讨论,请勿骚扰被封禁的用户)</p><p>【本次判罚为管理员判定,请注意案件右上无蓝色标记(风纪委员众裁)】</p><p><br/></p>", + "originType": 1, + "originTypeName": "评论", + "punishTitle": "在评论中发布人身攻击言论", + "punishTime": 1587494264, + "punishType": 3, + "punishTypeName": "永久封禁", + "moralNum": 0, + "blockedDays": 0, + "publishStatus": 1, + "blockedType": 0, + "blockedForever": 1, + "reasonType": 7, + "reasonTypeName": "发布人身攻击言论", + "operatorName": "", + "caseId": 0, + "ctime": 1587494264, + "commentSum": 606 + }, { + "id": 1091621, + "uname": "风纪委员会会长零八", + "face": "http://i1.hdslb.com/bfs/face/6ea4296f7591b9a724f540a41d48df728a0881b0.jpg", + "uid": 305542374, + "originTitle": "巅峰赛大乔游走辅助,队友说自家法师湖南卫视都不敢像法师这么演哈哈!", + "blockedRemark": "内容涉及传播不实信息", + "originUrl": "https://www.bilibili.com/video/av882552073", + "originContentModify": "<p>具体违规情况说明:</p><ol class=\" list-paddingleft-2\" style=\"list-style-type: decimal;\"><li><p>经查实确认,该账号<span style=\"text-decoration: underline;\">从未申请</span>亦<span style=\"text-decoration: underline;\">从未担任</span>过风纪委员职务。</p></li><li><p>发布多条 “您的稿件/评论涉及违规,即将下架/删除”的恐吓性言论。</p></li><li><p>谎称曾经封禁了某个up主,事实上风纪委员<span style=\"text-decoration: underline;\">无法封禁up主投稿</span>,且该up也从未被封禁。</p></li><li><p>威胁他人“要不要到小黑屋坐坐”,事实上风纪委员无法直接封禁用户。通过管理员封禁或风纪委员投票封禁的账号亦有据实申诉的机会。</p></li><li><p>故意挑衅他人“那你可以试着骂我,我们试试(举报)有没有用”。</p></li><li><p>误导他人“此评论区和弹幕无需保持礼仪”。</p></li></ol><p>批注:</p><p>如您发现:假冒风纪委员身份招摇撞骗、炫耀风纪委员身份、借风纪委员职务之便威胁恐吓他人、在风纪观点中发布违规内容等违规行为,请及时联系我们进行举报。您可直接将举报材料发送至judgement@bilibili.com。</p><p>(案例感想请发布在小黑屋评论区讨论,请勿骚扰被封禁的用户)</p><p>【本次判罚为管理员判定,请注意案件右上无蓝色标记(风纪委员众裁)】</p>", + "originType": 1, + "originTypeName": "评论", + "punishTitle": "在评论中发布传播不实信息", + "punishTime": 1585560309, + "punishType": 2, + "punishTypeName": "封禁", + "moralNum": 0, + "blockedDays": 15, + "publishStatus": 1, + "blockedType": 0, + "blockedForever": 0, + "reasonType": 18, + "reasonTypeName": "发布传播不实信息", + "operatorName": "", + "caseId": 0, + "ctime": 1585560309, + "commentSum": 2379 + }, + ………… + ] +} +``` + +</details> + +## 封禁处理公示详情 + +> https://api.bilibili.com/x/credit/blocked/info + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---------- | ------ | ---- | +| id | num | 封禁公示id | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-404:无此信息 | +| message | str | 错误信息 | 默认为`0` | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------- | ---- | ---------------- | ------------------------------------------- | +| id | num | 封禁公示id | | +| uname | str | 对象用户名 | | +| face | str | 对象用户头像url | | +| uid | num | 对象用户mid | | +| originTitle | str | 来源标题 | | +| blockedRemark | str | | | +| originUrl | str | 来源url | | +| originContentModify | str | 裁决正文 | | +| originType | num | 来源类型 | **见[表2](#表2已知的违规类型代码)** | +| originTypeName | str | 来源名 | | +| punishTitle | str | 公示标题 | | +| punishTime | num | 处罚时间 | 时间戳 | +| punishType | num | 处理手段类型 | `2`:封禁<br />`3`:永久封禁 | +| punishTypeName | str | 处理手段名 | | +| moralNum | num | `0`节操值 | 被封禁用户节操值均为`0` | +| blockedDays | num | 封禁天数 | 永封为`0` | +| publishStatus | num | `1` | 作用尚不明确 | +| blockedType | num | 处理来源 | `0`:系统封禁<br />`1`:风纪仲裁 | +| blockedForever | num | 是否永封 | `0`:非永封<br />`1`:永封 | +| reasonType | num | 封禁原因类型 | **见[表1](#表1已知的封禁原因类型代码总览)** | +| reasonTypeName | str | 封禁原因类型名称 | | +| operatorName | str | 空 | 作用尚不明确 | +| caseId | num | 仲裁信息id | 系统封禁时固定为0 | +| ctime | num | 创建时间 | 时间戳 | +| commentSum | num | 该条目评论数 | | + +**示例:** + +查询公示id为`1091621`的公示详情 + +```shell +curl -G 'https://api.bilibili.com/x/credit/blocked/info' \ +--data-urlencode 'id=1091621' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "id": 1091621, + "uname": "风纪委员会会长零八", + "face": "http://i1.hdslb.com/bfs/face/6ea4296f7591b9a724f540a41d48df728a0881b0.jpg", + "uid": 305542374, + "originTitle": "巅峰赛大乔游走辅助,队友说自家法师湖南卫视都不敢像法师这么演哈哈!", + "blockedRemark": "内容涉及传播不实信息", + "originUrl": "https://www.bilibili.com/video/BV1qK4y1C7dd", + "originContentModify": "<p>具体违规情况说明:</p><ol class=\" list-paddingleft-2\" style=\"list-style-type: decimal;\"><li><p>经查实确认,该账号<span style=\"text-decoration: underline;\">从未申请</span>亦<span style=\"text-decoration: underline;\">从未担任</span>过风纪委员职务。</p></li><li><p>发布多条 “您的稿件/评论涉及违规,即将下架/删除”的恐吓性言论。</p></li><li><p>谎称曾经封禁了某个up主,事实上风纪委员<span style=\"text-decoration: underline;\">无法封禁up主投稿</span>,且该up也从未被封禁。</p></li><li><p>威胁他人“要不要到小黑屋坐坐”,事实上风纪委员无法直接封禁用户。通过管理员封禁或风纪委员投票封禁的账号亦有据实申诉的机会。</p></li><li><p>故意挑衅他人“那你可以试着骂我,我们试试(举报)有没有用”。</p></li><li><p>误导他人“此评论区和弹幕无需保持礼仪”。</p></li></ol><p>批注:</p><p>如您发现:假冒风纪委员身份招摇撞骗、炫耀风纪委员身份、借风纪委员职务之便威胁恐吓他人、在风纪观点中发布违规内容等违规行为,请及时联系我们进行举报。您可直接将举报材料发送至judgement@bilibili.com。</p><p>(案例感想请发布在小黑屋评论区讨论,请勿骚扰被封禁的用户)</p><p>【本次判罚为管理员判定,请注意案件右上无蓝色标记(风纪委员众裁)】</p>", + "originType": 1, + "originTypeName": "评论", + "punishTitle": "在评论中发布传播不实信息", + "punishTime": 1585560309, + "punishType": 2, + "punishTypeName": "封禁", + "moralNum": 0, + "blockedDays": 15, + "publishStatus": 1, + "blockedType": 0, + "blockedForever": 0, + "reasonType": 18, + "reasonTypeName": "发布传播不实信息", + "operatorName": "", + "caseId": 0, + "ctime": 1585560309, + "commentSum": 2379 + } +} +``` + +</details> diff --git a/bb-api-collect/docs/blackroom/jury/action.md b/bb-api-collect/docs/blackroom/jury/action.md new file mode 100644 index 0000000000..700fed30bb --- /dev/null +++ b/bb-api-collect/docs/blackroom/jury/action.md @@ -0,0 +1,361 @@ +# 仲裁操作 + +## 申请加入风纪委员会 + +> https://api.bilibili.com/x/credit/v2/jury/apply + +*请求方式:POST* + +认证方式:Cookie + +只有用户会员90天内无违规、实名认证且非封禁状态才可以申请加入风纪委员会 + + +申请成功后可获得30天资格 + +**正文参数( application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | +| ------ | ---- | ---------------------- | ------ | +| csrf | str | cookie中`bili_jct`的值 | 必要 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ------ | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf 校验失败<br />25001:申请等级限制(会员等级<3)<br />25002:没有实名认证<br />25003:90天内有封禁记录<br />25013:不能重复申请风纪委资格<br />25016:当日风纪委员名额已发完 | +| message | str | 信息 | 默认为0 | +| ttl | num | 1 | | + + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +#### 旧API +<details> +<summary>查看旧版API:</summary> + +> https://api.bilibili.com/x/credit/jury/apply + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或APP + +只有用户会员等级≥Lv4、90天内无违规、实名认证且非封禁状态才可以申请加入风纪委员会 + +每日10:00开放新名额 + +申请成功后可获得30天资格 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | ---- | +| access_key | str | APP登录Token | APP方式必要 | | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ------ | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf 校验失败<br />25001:申请等级限制(会员等级<3)<br />25002:没有实名认证<br />25003:90天内有封禁记录<br />25013:不能重复申请风纪委资格<br />25016:当日风纪委员名额已发完 | +| message | str | 信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +Cookie方式: + +```shell +curl 'https://api.bilibili.com/x/credit/jury/apply' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +APP方式: + +```shell +curl 'https://api.bilibili.com/x/credit/jury/apply' \ +--data-urlencode 'access_key=xxx' +``` +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> +</details> + +## 拉取新案件 + +> https://api.bilibili.com/x/credit/v2/jury/case/next + +*请求方式:GET* + +认证方式:Cookie + +**标头参数(Headers):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------ | ------ | ---- | +| Cookie | str | Cookie | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br/>25006:风纪委员资格已过期<br />25008:没有案件<br/>25014:已审满 | +| message | str | 信息 | 默认为0,当code不为0时,显示错误信息 | +| ttl | num | 1 | 作用尚不明确 | +| data | object | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ---------- | ---- | +| case_id | str | 仲裁案件id | | + +**示例:** + +Cookie方式: + +```shell +curl -G 'https://api.bilibili.com/x/credit/v2/jury/case/next' \ +--header 'cookie: XXXXX' +``` + + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "case_id": "AC2m4HlrIrHv" + } +} +``` + +</details> + +#### 旧API +<details> +<summary>查看旧版API:</summary> + +> https://api.bilibili.com/x/credit/jury/caseObtain + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或APP + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | ---- | +| access_key | str | APP登录Token | APP方式必要 | | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br/>25005:不是风纪委员<br />25008:没有案件<br/>25014:已审满 | +| message | str | 信息 | 默认为0 | +| ttl | num | 1 | 作用尚不明确 | +| data | object | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------- | ---- | +| id | num | 仲裁案件id | | + +**示例:** + +Cookie方式: + +```shell +curl 'https://api.bilibili.com/x/credit/jury/caseObtain' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +APP方式: + +```shell +curl 'https://api.bilibili.com/x/credit/jury/caseObtain' \ +--data-urlencode 'access_key=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "id": 1239790 + } +} +``` + +</details> +</details> + + +## 进行仲裁投票 + +> https://api.bilibili.com/x/credit/v2/jury/vote + +*请求方式:POST* + +认证方式:Cookie + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | ---------------------- | ------ | ----------------------------------------------------- | +| case_id | str | 案件id | 必要 | | +| vote | num | 投票类型 | 必要 | 见「[众裁信息](judgement_info.md)」中表 | +| insiders | num | 是否观看此类视频 | 非必要 | 默认值为0<br/>见「[众裁信息](judgement_info.md)」中表 | +| content | str | 理由 | 非必要 | | +| anonymous | num | 是否匿名 | 非必要 | 默认值为0<br/>0:不匿名<br />1:匿名 | +| csrf | str | cookie中`bili_jct`的值 | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ------ | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br/>-101:未登录<br />-111:csrf 错误<br />-400:请求错误(投票类型错误)<br />25005:不是风纪委员<br />25011:投票类型错误<br />25018:不能进行此操作<br/><br/>*注:新版本对于一个不存在的`case_id`,不会报错。* | +| message | str | 信息 | 默认为0 | +| ttl | num | 1 | 作用尚不明确 | + + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +#### 旧API +<details> +<summary>查看旧版API:</summary> +> https://api.bilibili.com/x/credit/jury/vote + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或APP + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------- | ---- | ------------------------ | -------------- | --------------------------------------- | +| cid | num | 案件id | 必要 | | +| vote | num | 投票类型 | 必要 | 见「[众裁信息](judgement_info.md)」中表 | +| content | str | 理由 | 非必要 | 见「[众裁信息](judgement_info.md)」中表 | +| likes | nums | 支持的观点 | 非必要 | | +| hates | nums | 反对的观点 | 非必要 | | +| attr | num | 是否匿名 | 非必要 | 0:匿名<br />1:不匿名 | +| apply_type | num | 是否更改原因 | 非必要 | 0:保持原来原因<br />1:投票给新原因 | +| origin_reason | num | 原始原因 | 非必要 | 见「封禁公示」中表 | +| apply_reason | num | 新原因 | 非必要 | 见「封禁公示」中表 | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ------ | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br/>-101:未登录<br />-111:csrf 错误<br />-400:请求错误(投票类型错误)<br />25005:不是风纪委员<br />25009: 案件不存在<br/>25011:投票类型错误<br />25012:重复投票 | +| message | str | 信息 | 默认为0 | +| ttl | num | 1 | 作用尚不明确 | + +**示例:** + +为案件`2333`投票,建议封禁,无理由,不匿名,无支持/反对观点,不修改投票原因 + +Cookie方式: + +```shell +curl 'https://api.bilibili.com/x/credit/jury/vote' \ +--data-urlencode 'cid=2333' \ +--data-urlencode 'vote=1' \ +--data-urlencode 'content=' \ +--data-urlencode 'likes=' \ +--data-urlencode 'hates=' \ +--data-urlencode 'attr=1' \ +--data-urlencode 'apply_type=0' \ +--data-urlencode 'origin_reason=' \ +--data-urlencode 'apply_reason=' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +APP方式: + +```shell +curl 'https://api.bilibili.com/x/credit/jury/vote' \ +--data-urlencode 'access_key=xxx' \ +--data-urlencode 'cid=2333' \ +--data-urlencode 'vote=1' \ +--data-urlencode 'content=' \ +--data-urlencode 'likes=' \ +--data-urlencode 'hates=' \ +--data-urlencode 'attr=1' \ +--data-urlencode 'apply_type=0' \ +--data-urlencode 'origin_reason=' \ +--data-urlencode 'apply_reason=' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> +</details> \ No newline at end of file diff --git a/bb-api-collect/docs/blackroom/jury/base_info.md b/bb-api-collect/docs/blackroom/jury/base_info.md new file mode 100644 index 0000000000..c86c9fcb86 --- /dev/null +++ b/bb-api-collect/docs/blackroom/jury/base_info.md @@ -0,0 +1,331 @@ +# 风纪委员会用户基本信息 + +## 基本数据 + +> https://api.bilibili.com/x/credit/v2/jury/jury + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +**url 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | ---- | +| access_key | str | APP 登录 Token | APP 方式必要 | | + +**json 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录 | +| message | str | 信息 | 默认为 0 | +| ttl | num | 1 | | +| data | object | 数据本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ------------ | -------------------------------------------------------------------------------------------------- | +| allow_apply | bool | true | 尚不明确(用户从未担任风纪委员时也为 true) | +| apply_status | num | 任期审核状态 | -1 资格失效,且未申请<br />0 刚申请连任时<br />5 申请后,等待审核<br />3 申请连任成功,status 为 1 | +| case_total | num | 总众裁数 | | +| err_msg | str | 空 | 尚不明确 | +| face | str | 用户头像 url | | +| status | num | 当前资格状态 | 0 未曾拥有资格<br />1 任期内<br />2 资格失效 | +| term_end | num | 任期结束时间 | 时间戳(秒级),无任期时为 0 | +| uname | str | 用户昵称 | | + +## 基本数据(旧API) + +部分字段信息停留在 2021 年 10 月。 + +<details> +<summary>查看折叠内容:</summary> + +> https://api.bilibili.com/x/credit/jury/jury + +根数据与新 API 一致,`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | -------------------- | ---------------------------- | +| caseTotal | num | 总众裁数 | | +| face | str | 用户头像 url | | +| restDays | num | 当前资格剩余天数 | 自 2021 年 10 月起,固定为 0 | +| rightRadio | num | 当前裁决正确率百分比 | 裁决数小于 3 时固定为 50 | +| status | num | 当前状态 | 1:具有资格<br />2:资格失效 | +| uname | str | 用户昵称 | | + +</details> + +## 统计信息 + +新API(2021年10月任期之后) + +>https://api.bilibili.com/x/credit/v2/jury/kpi + +*方式:GET* + +认证方式:Cookie + +**备注**:该api只收录2021年10月开始,风纪委员改版之后的数据,且每次只返回一次任期的数据。 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | ------- | ------------ | -------------------------------------- | +| term_id | num | 任期 id | 可不传此参数或将值留空或设为`0` | 未传参或留空时,**只**返回最近一次已结束的任期的数据 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />25018:不能进行此操作(还没有成为新风纪委员,或传入了不属于你的`term_id`) | +| message | str | 信息 | 默认为 0 | +| ttl | num | 1 | | +| data | object | 数据本体 | | + +`data` 对象: + +| 项 | 类型 | 内容 | 备注 | +| --------------- | ------ | ------------------ | ------------------------------------------------------------ | +| mid | num | 用户 UID | | +| uname | str | 留空 | | +| face | str | 留空 | | +| term_id | num | 任期 ID | 未传入`term_id`时,返回的是最近一次已结束的任期的id | +| term_start | num | 任期开始时间 | 时间戳,精确到秒 | +| term_end | num | 任期结束时间 | 时间戳,精确到秒 | +| case_total | num | 任内总投票数 | | +| active_days | num | 活跃天数 | | +| like_num | num | 发表观点,被点赞数 | | +| accuracy_rate | num | 投中率 | 所选观点与大多数风纪委员一致,记为一次“投中” | +| pass | num | 任期是否合格 | 0 不合格<br />1 合格 | +| status | num | 当前资格状态 | 0 未曾拥有资格<br />1 任期内<br />2 资格失效 | +| apply_status | num | 当前资格申请状态 | -1 资格失效,且未申请<br />0 刚申请连任时<br />5 申请后,等待审核<br />3 申请连任成功,status 为 1 | +| prev_term_id | num | 上一任期的任期 ID | 新版风纪委员启用后的第一个任期,此项的值为 0 | +| next_term_id | num | 下一任期的任期 ID | 若当前任期尚未结束,此项的值为 0 | +| rewards | object | 任期奖励 | 有`pendant`和`coin`两个子项 | +| rewards.pendant | num | 头像挂件礼包 ID | 合格后一般为 1,不合格为 0 | +| rewards.coin | num | 硬币礼包 ID | 合格后一般为 3,不合格为 0 | + +<details> +<summary>查看响应示例:</summary> + +注:本示例未传入`term_id`,返回的是最近一次已结束任期的统计结果 + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "mid": 10001, + "uname": "", + "face": "", + "term_id": 300009, + "term_start": 1669100000, + "term_end": 1671690000, + "case_total": 591, + "active_days": 30, + "like_num": 0, + "accuracy_rate": 74, + "pass": 1, + "status": 1, + "apply_status": 3, + "prev_term_id": 300007, + "next_term_id": 0, + "rewards": { + "pendant": 1, + "coin": 3 + } + } +} +``` +</details> + +## 统计信息(旧API) + +<details> +<summary>查看折叠内容:</summary> + +> https://api.bilibili.com/x/credit/jury/kpi + +*方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +**备注**:该api只统计到2021年9月任期,风纪委员改版之前。风纪委员改版之后的数据未收录 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | ---- | +| access_key | str | APP登录Token | APP方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录 | +| message | str | 信息 | 默认为0 | +| ttl | num | 1 | | +| data | array | 数据本体 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------------- | ---- | +| 0 | obj | 第1个月统计 | | +| n | obj | 第(n+1)个月统计 | | +| …… | obj | …… | …… | + +`data` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | -------------------------------- | --------------------- | +| id | num | 0 | | +| mid | num | 用户id | | +| number | num | 风纪委员编号 | | +| day | num | 数据生成时间(也是任期结束时间) | 时间戳,精确到秒 | +| rate | num | 任期完成度 | 1=A;2=S;3=S+;4=S++ | +| rank | num | 尚不明确 | | +| rankper | num | 尚不明确 | | +| rankTotal | num | 尚不明确 | | +| point | num | 32767 | | +| activeDays | num | 活跃天数 | | +| voteTotal | num | 投票总数 | | +| voteRadio | num | 投中率 | | +| blockedTotal | num | 尚不明确 | | +| termStart | num | 任期开始时间 | 时间戳,精确到秒 | +| termEnd | num | 任期结束时间(数据生成时间一致) | 时间戳,精确到秒 | +| opinion_likes | num | 观点获赞 | | + +**示例:** + +Cookie方式: + +```shell +curl 'https://api.bilibili.com/x/credit/jury/kpi' \ +-b 'SESSDATA=xxx' +``` + +APP方式: + +```shell +curl -G 'https://api.bilibili.com/x/credit/jury/kpi' \ +--data-urlencode 'access_key=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "id": 0, + "mid": 114343368, + "number": 199046, + "day": 1539792000, + "rate": 1, + "rank": 0, + "rankper": 1, + "rankTotal": 39584, + "point": 32767, + "activeDays": 23, + "voteTotal": 422, + "voteRadio": 0, + "blockedTotal": 0, + "termStart": 1537200000, + "termEnd": 1539792000, + "opinion_likes": 18 + } + ] +} +``` + +</details> +</details> + +## 检查申请风纪委员会资格 + +> ~~https://api.bilibili.com/x/credit/jury/requirement~~ (旧版) + +> https://api.bilibili.com/x/credit/v2/jury/requirement (新版) + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +新版 api 与旧版的区别仅在新版没有 `level` 字段(新版风纪委员没有等级限制)。 + +只有用户~~会员等级≥Lv4、~~ 90 天内无违规、实名认证且非封禁状态才可以申请加入风纪委员会。 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | ---- | +| access_key | str | APP登录Token | APP方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录 | +| message | str | 信息 | 默认为0 | +| ttl | num | 1 | | +| data | object | 数据本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ---------------- | ------------------------------------- | +| blocked | bool | 是否被封禁 | true:是<br />false:否<br />**下同** | +| cert | bool | 是否实名认证 | | +| level | bool | 等级是否>=4 | 新版无该字段 | +| rule | bool | 是否90天内无违规 | | + +**示例:** + +Cookie方式: + +```shell +curl 'https://api.bilibili.com/x/credit/v2/jury/requirement' \ +-b 'SESSDATA=xxx' +``` + +APP方式: + +```shell +curl -G 'https://api.bilibili.com/x/credit/v2/jury/requirement' \ +--data-urlencode 'access_key=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "blocked": false, + "cert": true, + "rule": true + } +} +``` + +</details> diff --git a/bb-api-collect/docs/blackroom/jury/judgement_info.md b/bb-api-collect/docs/blackroom/jury/judgement_info.md new file mode 100644 index 0000000000..9b2d9d3b17 --- /dev/null +++ b/bb-api-collect/docs/blackroom/jury/judgement_info.md @@ -0,0 +1,978 @@ +# 众裁信息 + +## Enum类型代码 + +### 投票类型码总览 + +| 代码 | 含义 | +| ---- | --- | +| 0 | 未投票 | +| 1 | 封禁 | +| 2 | 否 | +| 3 | 弃权 | +| 4 | 删除 | + +### 投票选项码总览 + +<table> + <tr> + <th>任务类型</th> + <th>代码</th> + <th>含义</th> + </tr> + <tr> + <td rowspan="4">单条评论(弹幕)</td> + <td>1</td> + <td>合适</td> + </tr> + <tr> + <td>2</td> + <td>一般</td> + </tr> + <tr> + <td>3</td> + <td>不合适</td> + </tr> + <tr> + <td>4</td> + <td>无法判断</td> + </tr> + <tr> + <td rowspan="4">评论(弹幕)氛围</td> + <td>11</td> + <td>好</td> + </tr> + <tr> + <td>12</td> + <td>一般</td> + </tr> + <tr> + <td>13</td> + <td>差</td> + </tr> + <tr> + <td>14</td> + <td>无法判断</td> + </tr> +</table> + + + +## 获取单个案件信息 + +> https://api.bilibili.com/x/credit/v2/jury/case/info + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +可查询任意案件,无论自己是否参与投票。 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ------------ | ------ | ------------- | ------------- | +| access_key | str | APP登录Token | APP方式必要 | | +| case_id | str | 案件id | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | -------- | ------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-400:请求错误 | +| 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 | 投票信息 | | + +`data` 对象下的`case_info`对象 + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ------ | ------------ | ----------------------------------------------- | +| 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 | 评论内容 | | +| child_comments | object | 子评论(对该评论的回复) | 见「对象:评论信息」,单条评论和子评论下无`child_comments`字段 | + + +对象:弹幕信息 + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------- | ------- | +| id_str | str | 弹幕dmid | | +| content | str | 弹幕内容 | | +| progress | num | | 尚不明确 | + +`data` 对象下的`my_point`对象 + +记录了自己的投票(观点)信息,仅当自己投过票才有该字段。 + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ---------------- | ------------------------------------------------------------ | +| opid | num | 观点编号 | 每当某个一个风纪委员给某个仲裁案件发表观点,就+1 | +| mid | num | 风纪委员用户ID | | +| uname | str | 风纪委员用户名 | 风纪委勾选匿名投票则显示“匿名用户” | +| face | str | 头像URL | 头像 | +| vote | num | 投票选项 | “合适题”分别为 `1` 或者 `2` 或者 `3` 或者 `4`,<br/>对应:“合适”、“一般”、“不合适”、“无法判断”<br/><br/>“氛围题”分别为 `11` 或者 `12` 或者 `13` 或者 `14`,<br/>对应:“好”、“一般”、“差”、“无法判断”<br/><br/>注释<br/>合适题:“单条弹幕(评论)是否合适?”<br/>氛围题:“弹幕(评论区)氛围如何” | +| vote_text | | 内容为空 | *现在系统已不再展示其他风纪委所投的票* | +| content | str | 观点内容 | 该风纪委员所发表的观点内容 | +| anonymous | num | 0 | 尚不明确 | +| like | num | 被点赞数量 | | +| hate | num | 被点踩数量 | | +| like_status | num | 点赞(踩)状态 | 本账号是否给该条评论点赞:<br/>0:没做操作;1:给评论点赞;2:给评论点踩 | +| vote_time | num | 投票时间 | 时间戳,精确到秒 | +| insiders | num | 是否观看此类视频 | 1:平时观看此类视频;0:平时不观看此类视频 | + +`data` 对象下的`vote_info`对象 + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ----- | -------- | -------------------------------------------- | +| all_count | num | 总投票数 | | +| counts | array | 观点分布 | 格式:`[合适, 一般, 不合适, 无法判断]` | +| insiders_counts | array | 行为分布 | 格式:`[平时会看此类视频, 平时不看此类视频]` | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/credit/v2/jury/case/info' \ + --data-urlencode 'case_id=AC2SiaD8jlrL' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "case_id": "AC2SiaD8jlrL", + "case_type": 3, + "jury_state": 1, + "participate": 1, + "vote_items": [ + { + "vote": 1, + "vote_text": "合适" + }, + { + "vote": 2, + "vote_text": "一般" + }, + { + "vote": 3, + "vote_text": "不合适" + }, + { + "vote": 4, + "vote_text": "无法判断" + } + ], + "default_vote": 4, + "status": 1, + "origin_start": 0, + "avid": 727792866, + "cid": 756815216, + "vote_cd": -1, + "result": 3, + "result_text": "不合适", + "title": "“国家队”守门员和朋友打赌,谁能在湿滑的地面踢进足球就送美刀", + "case_info": { + "comment": null, + "danmu_img": "", + "comments": null, + "single_danmu": { + "id_str": "1086612690354524160", + "content": "这守门员干啥呢?给块骨头我家狗都比他防的好", + "progress": 27859 + } + }, + "my_point": { + "opid": 10001, + "mid": 10001, + "uname": "风纪委员用户名", + "face": "http://i0.hdslb.com/bfs/face/e48952d599dbf011c2235239fafa2bf0deccef5a.jpg", + "vote": 3, + "vote_text": "不合适", + "content": "", + "anonymous": 0, + "like": 0, + "hate": 0, + "like_status": 0, + "vote_time": 1663655000, + "insiders": 1 + }, + "vote_info": { + "all_count": 306, + "counts": [90, 33, 177, 6], + "insiders_counts": [245, 61] + } + } +} +``` +</details> + +**旧 api:** + +<details> +<summary>查看旧 api:</summary> + +> https://api.bilibili.com/x/credit/jury/juryCase + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +只能查询自己参与众裁的 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ------------ | ------ | ------------- | ------------- | +| access_key | str | APP登录Token | APP方式必要 | | +| cid | num | 案件id | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | -------- | ------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-400:请求错误<br />25010:没有权限查看案件 | +| message | str | 信息 | 默认为0 | +| ttl | num | 1 | | +| data | object | 数据本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ------ | -------- | ------------ | +| id | num | 案件id | | +| mid | num | 被举报用户mid | | +| status | num | 裁决状态 | 1:投票中<br />2:停止发放<br />3:复核中(结案中)<br />4:已裁决<br />5:待重启<br />6:未裁决<br />7:冻结中<br />8:队列中 | +| statusTitle | str | 封禁时间文字 | `judgeType`=1时有效 | +| originType | num | 来源类型 | 见「封禁公示」中表 | +| reasonType | num | 原因类型 | 见「封禁公示」中表 | +| originContent | str | 被举报的原文 | | +| punishResult | num | 处理结果 | 0:无<br />1:封禁3天<br />2:封禁7天<br />3:永封<br />4:其他封禁天数<br />5:封禁15天<br />6:仅删除不封禁 | +| punishTitle | str | 处罚原因 | | +| judgeType | num | 裁决类型 | `status`=4时有效<br />0:未裁决<br/>1:违规<br/>2:不违规 | +| originUrl | str | 来源url | | +| blockedDays | num | 封禁时间 | `judgeType`=1时有效 | +| putTotal | num | ??? | 作用尚不明确 | +| voteRule | num | 投票不违规人数 | | +| voteBreak | num | 投票建议封禁人数 | | +| voteDelete | num | 投票建议删除人数 | | +| startTime | num | 裁决起始时间 | 时间戳 | +| endTime | num | 裁决截止时间 | 时间戳<br />未结案固定为24小时 | +| ctime | num | 举报创建时间 | 时间戳 | +| mtime | num | 开始拉取时间 | 时间戳 | +| originTitle | str | 来源标题 | | +| relationId | str | 违规关系标识字 | {评论rpid}-{违规类型id}-{来源对象id} | +| face | str | 被举报用户头像url | | +| uname | str | 被举报用户昵称 | | +| vote | num | 我的投票 | **见上表** | +| case_type | num | 众裁类型 | 0:小众众裁<br />1:大众众裁 | + +**示例:** + +查询案件`1239790`的信息 + +Cookie方式: + +```shell +curl -G 'https://api.bilibili.com/x/credit/jury/juryCase' \ +--data-urlencode 'cid=1239790' \ +-b 'SESSDATA=xxx' +``` + +APP方式: + +```shell +curl -G 'https://api.bilibili.com/x/credit/jury/juryCase' \ +--data-urlencode 'access_key=xxx' \ +--data-urlencode 'cid=1239790' \ +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "id": 1239790, + "mid": 351783425, + "status": 4, + "statusTitle": "封禁7天", + "originType": 1, + "reasonType": 9, + "originContent": "up主,在和平精英里的喷子是霰(xian)弹枪,不是散(san)弹枪。", + "punishResult": 0, + "punishTitle": "在评论中发布引战言论", + "judgeType": 2, + "originUrl": "https://www.bilibili.com/video/BV15x411X7eV/#reply1728344012", + "blockedDays": 7, + "putTotal": 272, + "voteRule": 409, + "voteBreak": 17, + "voteDelete": 89, + "startTime": 1594467941, + "endTime": 1594471525, + "ctime": 1594464499, + "mtime": 1594471678, + "originTitle": "和平精英揭秘真相68:氪金试水最新抽奖活动,到底是亏了还是赚了?", + "relationId": "1728344012-1-57465308", + "face": "http://i2.hdslb.com/bfs/face/e1018566c615059b664dc6eae3a5235c31cd92fe.jpg", + "uname": "零酱a", + "vote": 4, + "case_type": 0 + } +} +``` + +</details> +</details> + +## 查询案件众裁信息 + +注:这是一个旧版的API,暂未找到对应的新版API。 +<details> +<summary>展开:</summary> +> https://api.bilibili.com/x/credit/jury/caseInfo + +*请求方式:GET* + +注:该接口无需登录 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------ | ------ | ---- | +| cid | num | 案件id | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | -------------------------------- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误 | +| message | str | 信息 | 默认为0 | +| ttl | num | 1 | | +| data | 有效时:object<br />无效时:null | 数据本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ----------------- | ------------------------------------------------------------ | +| id | num | 案件id | | +| mid | num | 被举报用户mid | | +| status | num | 裁决状态 | 1:投票中<br />2:停止发放<br />3:复核中(结案中)<br />4:已裁决<br />5:待重启<br />6:未裁决<br />7:冻结中<br />8:队列中 | +| originType | num | 来源类型 | 见「封禁公示」中表 | +| reasonType | num | 原因类型 | 见「封禁公示」中表 | +| originContent | str | 被举报的原文 | | +| punishResult | num | 处理结果 | 0:无<br />1:封禁3天<br />2:封禁7天<br />3:永封<br />4:其他封禁天数<br />5:封禁15天<br />6:仅删除不封禁 | +| judgeType | num | 裁决类型 | `status`=4时有效<br />0:未裁决<br/>1:违规<br/>2:不违规 | +| originUrl | str | 来源url | | +| blockedDays | num | 封禁时间 | `judgeType`=1时有效 | +| putTotal | num | ??? | 作用尚不明确 | +| voteRule | num | 投票不违规人数 | | +| voteBreak | num | 投票建议封禁人数 | | +| voteDelete | num | 投票建议删除人数 | | +| startTime | num | 裁决起始时间 | 时间戳 | +| endTime | num | 裁决截止时间 | 时间戳<br />未结案固定为24小时 | +| ctime | num | 举报创建时间 | 时间戳 | +| mtime | num | 开始拉取时间 | 时间戳 | +| originTitle | str | 来源标题 | | +| relationId | str | 违规关系标识字 | {评论rpid}-{违规类型id}-{来源对象id} | +| face | str | 被举报用户头像url | | +| uname | str | 被举报用户昵称 | | +| vote | num | 0 | 固定为0 | +| case_type | num | 众裁类型 | 0:小众众裁<br />1:大众众裁 | + +**示例:** + +查询案件`1239790`的信息 + +```shell +curl -G 'https://api.bilibili.com/x/credit/jury/juryCase' \ +--data-urlencode 'cid=1239790' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "id": 1239790, + "mid": 351783425, + "status": 4, + "originType": 1, + "reasonType": 9, + "originContent": "up主,在和平精英里的喷子是霰(xian)弹枪,不是散(san)弹枪。", + "punishResult": 0, + "judgeType": 2, + "originUrl": "https://www.bilibili.com/video/BV15x411X7eV/#reply1728344012", + "blockedDays": 7, + "putTotal": 272, + "voteRule": 409, + "voteBreak": 17, + "voteDelete": 89, + "startTime": 1594467941, + "endTime": 1594471525, + "ctime": 1594464499, + "mtime": 1594471678, + "originTitle": "和平精英揭秘真相68:氪金试水最新抽奖活动,到底是亏了还是赚了?", + "relationId": "1728344012-1-57465308", + "face": "http://i2.hdslb.com/bfs/face/e1018566c615059b664dc6eae3a5235c31cd92fe.jpg", + "uname": "零酱a", + "vote": 0, + "case_type": 0 + } +} +``` +</details> +</details> + +## 查询我的众裁记录 + +> https://api.bilibili.com/x/credit/v2/jury/case/list + +*请求方式:GET* + +认证方式:Cookie + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | -------------------- | +| pn | num | 页码 | 非必要 | 默认为1 | +| ps | num | 每页显示数量 | 非必要 | 默认为30<br />最大30 | + +**Headers参数** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---- | ------ | ---- | +| cookie | str | | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ------ | ------------ | ------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-400:请求错误 | +| message | str | 信息 | 默认为0 | +| ttl | num | 1 | | +| data | object | 数据本体 | | +| data.total | num | 仲裁案例数 | | +| data.list | array | 仲裁记录列表 | | + +`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ------ | --------------- | ------------ | +| 0 | object | 仲裁记录1 | | +| n | object | 仲裁记录(n+1) | 按照时间顺序 | +| …… | object | …… | …… | + +`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | ------------------------------------------------------------ | +| case_id | str | 案件id | | +| case_type | num | 案件类型 | 1:单条评论<br/>2:评论氛围<br/>3:单条弹幕<br/>4:弹幕氛围 | +| status | num | 裁决状态 | 0:投票中<br />1:已结束 | +| vote | num | 投票选项 | “单条评论(弹幕)”分别为 `1` 或者 `2` 或者 `3` 或者 `4`,<br/>对应:“合适”、“一般”、“不合适”、“无法判断”<br/><br/>“评论(弹幕)氛围”分别为 `11` 或者 `12` 或者 `13` 或者 `14`,<br/>对应:“好”、“一般”、“差”、“无法判断” | +| vote_text | str | 投票选项文本 | *参考上条* | +| vote_time | num | 投票时间 | 时间戳,精确到秒 | + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "total": 5428, + "list": [ + { + "case_id": "AC2sOiNenwj1", + "case_type": 4, + "status": 1, + "vote": 11, + "vote_text": "好", + "vote_time": 1662700609 + } + ] + } +} +``` + +</details> + +## 查询案件众裁信息(旧 api) + +<details> +<summary>查看旧版API:</summary> + +> https://api.bilibili.com/x/credit/jury/caseList + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ------------ | ------ | ------------- | ------------- | +| access_key | str | APP登录Token | APP方式必要 | | +| pn | num | 页码 | 非必要 | 默认为1 | +| ps | num | 每页显示数量 | 非必要 | 默认为30<br />最大30 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | -------- | ------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-400:请求错误 | +| message | str | 信息 | 默认为0 | +| ttl | num | 1 | | +| data | array | 仲裁记录列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ------ | --------------- | ------------ | +| 0 | object | 仲裁记录1 | | +| n | object | 仲裁记录(n+1) | 按照时间顺序 | +| …… | object | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ----------------- | ------------------------------------------------------------ | +| id | num | 案件id | | +| mid | num | 被举报用户mid | | +| status | num | 裁决状态 | 1:投票中<br />2:停止发放<br />3:复核中(结案中)<br />4:已裁决<br />5:待重启<br />6:未裁决<br />7:冻结中<br />8:队列中 | +| originType | num | 来源类型 | 见「封禁公示」中表 | +| reasonType | num | 原因类型 | 见「封禁公示」中表 | +| originContent | str | 被举报的原文 | | +| punishResult | num | 处理结果 | 0:无<br />1:封禁3天<br />2:封禁7天<br />3:永封<br />4:其他封禁天数<br />5:封禁15天<br />6:仅删除不封禁 | +| punishTitle | str | 处罚原因 | | +| judgeType | num | 裁决类型 | `status`=4时有效<br />0:未裁决<br/>1:违规<br/>2:不违规 | +| originUrl | str | 来源url | | +| blockedDays | num | 封禁时间 | `judgeType`=1时有效 | +| putTotal | num | ??? | 作用尚不明确 | +| voteRule | num | 投票不违规人数 | | +| voteBreak | num | 投票建议封禁人数 | | +| voteDelete | num | 投票建议删除人数 | | +| startTime | num | 裁决起始时间 | 时间戳 | +| endTime | num | 裁决截止时间 | 时间戳<br />未结案固定为24小时 | +| ctime | num | 举报创建时间 | 时间戳 | +| mtime | num | 开始拉取时间 | 时间戳 | +| originTitle | str | 来源标题 | | +| relationId | str | 违规关系标识字 | {评论rpid}-{违规类型id}-{来源对象id} | +| face | str | 被举报用户头像url | | +| uname | str | 被举报用户昵称 | | +| vote | num | 我的投票 | **见上表** | +| voteTime | num | 我的裁决时间 | 毫秒 时间戳 | +| case_type | num | 众裁类型 | 0:小众众裁<br />1:大众众裁 | + +**示例:** + +查询我的历史众裁,第1页,每页显示1个案件 + +Cookie方式: + +```shell +curl -G 'https://api.bilibili.com/x/credit/jury/caseList' \ +--data-urlencode 'ps=1' \ +--data-urlencode 'pn=1' \ +-b 'SESSDATA=xxx' +``` + +APP方式: +```shell +curl -G 'https://api.bilibili.com/x/credit/jury/caseList' \ +--data-urlencode 'access_key=xxx' \ +--data-urlencode 'ps=1' \ +--data-urlencode 'pn=1' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "id": 1241808, + "mid": 298264370, + "status": 4, + "originType": 1, + "reasonType": 9, + "originContent": "别在发这种傻逼视频了好吗?真要搞到禁摩才甘心。", + "punishResult": 6, + "punishTitle": "在评论中发布引战言论", + "judgeType": 1, + "originUrl": "https://www.bilibili.com/video/av328669697/#reply3165369965", + "blockedDays": 7, + "putTotal": 251, + "voteRule": 14, + "voteBreak": 140, + "voteDelete": 373, + "startTime": 1594528662, + "endTime": 1594530687, + "ctime": 1594528108, + "mtime": 1594530802, + "originTitle": "我这里有记录仪!略略略略略略哈哈哈,干得漂亮!", + "relationId": "3165369965-1-328669697", + "face": "http://i1.hdslb.com/bfs/face/d69912bb2a51f08176bcdbf4ba15e4c2b0962ad9.jpg", + "uname": "MyLSTicKnight", + "vote": 4, + "voteTime": 1594528700000, + "case_type": 0 + } + ] +} +``` + +</details> +</details> + +## 获取众议观点 + +> https://api.bilibili.com/x/credit/v2/jury/case/opinion + +*请求方式:GET* + +认证方式:Cookie + +**标头参数(Headers):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------ | ------ | ---- | +| Cookie | str | Cookie | 必要 | | + +**URL参数(Query Params):** + +| 参数名 | 类型 | 内容 | 备注 | +| ------- | ---- | ---------- | ------------------------------------------- | +| case_id | str | 仲裁案件id | **必填** | +| pn | num | | 显示第x页(default = 1) | +| ps | num | | 每页显示y条观点(Max = 20)(default = 10) | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功;<br />-400:`ps`参数大于可允许的最大值`20` | +| message | str | 信息 | 默认为0 | +| ttl | num | 1 | 作用尚不明确 | +| data | object | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ----- | -------------------------- | ---- | +| total | num | 当前案件众议观点总数 | | +| list | array | 无数据时是一个空数组:“[]” | | + +`data.list`对象是一个数组,里面包含`ps`个object(参数`ps`见上文,object结构见「[附表4](#附表4data-对象下的my_point对象)」) + +**示例:** + +查看案件`AC1xx411c7ac`的众议观点,每页`2`项,查看第`1`页 + +```shell +curl -G 'https://api.bilibili.com/x/credit/v2/jury/case/opinion' \ +--data-urlencode 'case_id=AC1xx411c7ac' \ +--data-urlencode 'pn=1' \ +--data-urlencode 'ps=2' \ +--header 'cookie: xxxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "total": 48, + "list": [ + { + "opid": 46087379, + "mid": 22006415, + "uname": "匿名用户", + "face": "http://i0.hdslb.com/bfs/face/e48952d599dbf011c2235239fafa2bf0deccef5a.jpg", + "vote": 11, + "vote_text": "", + "content": "正常评论", + "anonymous": 1, + "like": 0, + "hate": 0, + "like_status": 0, + "vote_time": 1661430391, + "insiders": 1 + }, + { + "opid": 46087280, + "mid": 19243907, + "uname": "匿名用户", + "face": "http://i0.hdslb.com/bfs/face/e85d7ab3425d3dd0f0796bd7f945b47ac27ca82a.jpg", + "vote": 11, + "vote_text": "", + "content": "并未发现明显问题。", + "anonymous": 1, + "like": 0, + "hate": 0, + "like_status": 0, + "vote_time": 1661430337, + "insiders": 0 + } + ] + } +} +``` + +</details> + +**旧 api** + +<details> +<summary>查看旧版API:</summary> + +> https://api.bilibili.com/x/credit/jury/case/opinion + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ------------ | ------ | ------------- | ------------- | +| cid | num | 案件id | 必要 | | +| ps | num | 每页项数 | 非必要 | 默认为10 | +| pn | num | 页码 | 非必要 | 默认为1 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | -------- | ------------ | +| code | num | 返回值 | 0:成功<br />-400:请求错误 | +| message | str | 信息 | 默认为0 | +| ttl | num | 1 | | +| data | object | 数据本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ------ | -------- | ------------ | +| count | num | 观点总数 | | +| opinion | 有效时:array<br />无效时:null | 观点列表 | | + +`data` 中的`opinion` 数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ------ | ----------- | ------------ | +| 0 | object | 观点1 | | +| n | object | 观点(n+1) | 按照时间顺序 | +| …… | object | …… | …… | + +`opinion` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ------ | -------- | ------------ | +| mid | num | 用户mid | 仅非匿名有此项 | +| face | str | 用户头像 | 仅非匿名有此项 | +| name | str | 用户昵称 | 仅非匿名有此项 | +| opid | num | 观点id | | +| vote | num | 投票选择 | **见上表** | +| content | str | 观点内容 | | +| attr | num | 是否匿名 | 0:匿名<br />1:不匿名 | +| hate | num | 喜欢人数 | | +| like | num | 不喜欢人数 | | + +**示例:** + +查看案件`1239790`的众议观点,每页10项,查看第一页 + +```shell +curl -G 'https://api.bilibili.com/x/credit/jury/case/opinion' \ +--data-urlencode 'cid=1239790' \ +--data-urlencode 'ps=10' \ +--data-urlencode 'pn=1' \ +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "count": 23, + "opinion": [ + { + "opid": 250943982, + "vote": 2, + "content": "不懂,正常的科普也有人杠吗?没文化真可怕", + "attr": 0, + "hate": 0, + "like": 0 + }, + { + "mid": 59894, + "face": "http://i2.hdslb.com/bfs/face/0cc48fc40867537d5a09a125e90f76183efbfdfa.gif", + "name": "雷歐諾斯", + "opid": 250956267, + "vote": 2, + "content": "这个虽然不是正确的说法,但本身是一种观点。而且已经成为一种梗了。不属于引战。", + "attr": 1, + "hate": 0, + "like": 0 + }, + { + "opid": 250956259, + "vote": 2, + "content": "正常科普,不构成引战。", + "attr": 0, + "hate": 0, + "like": 0 + }, + { + "mid": 215020429, + "face": "http://i1.hdslb.com/bfs/face/1d43c302e67db4d21b9c5c0f0dc0b8786e8086d5.jpg", + "name": "瞎子广_广告歌41", + "opid": 250955160, + "vote": 2, + "content": "这个其实也没啥事真的", + "attr": 1, + "hate": 0, + "like": 0 + }, + { + "mid": 108194360, + "face": "http://i0.hdslb.com/bfs/face/b78c92a69ff9977b7d08d4f7edc0a051a3d6ea3e.jpg", + "name": "籽云奕", + "opid": 250953998, + "vote": 2, + "content": "仅仅是科普评论,无过激言论", + "attr": 1, + "hate": 0, + "like": 0 + }, + { + "mid": 34503714, + "face": "http://i2.hdslb.com/bfs/face/eb2d0853235a56d035303f4f3614dcb6e0cf66fa.jpg", + "name": "十六夜紅月丶", + "opid": 250950982, + "vote": 2, + "content": "无过激言论,正常科普罢了", + "attr": 1, + "hate": 0, + "like": 0 + }, + { + "opid": 250950973, + "vote": 2, + "content": "其实两种读法都是正确的,虽然想要纠正别人的错误。不过自己本身就错了。还是保留吧,没什么引战的", + "attr": 0, + "hate": 0, + "like": 0 + }, + { + "mid": 436136443, + "face": "http://i1.hdslb.com/bfs/face/6b4151d8e030eddd073add6ef18ccbb00aa48d0f.jpg", + "name": "兄弟好牛啤", + "opid": 250950417, + "vote": 2, + "content": "有点经典的争议,但可能还会有人不知道", + "attr": 1, + "hate": 0, + "like": 0 + }, + { + "mid": 87385400, + "face": "http://i2.hdslb.com/bfs/face/0f567e7fa49bcef22010f3ff78e90553d8fffb09.jpg", + "name": "小学生de王者荣耀", + "opid": 250950402, + "vote": 2, + "content": "合理纠正up主的错误,建议追究恶意举报者的责任", + "attr": 1, + "hate": 0, + "like": 0 + }, + { + "opid": 250949840, + "vote": 2, + "content": "正常科普,没有过激言论,建议保留", + "attr": 0, + "hate": 0, + "like": 0 + } + ] + } +} +``` + +</details> +</details> diff --git a/bb-api-collect/docs/broadcast/readme.md b/bb-api-collect/docs/broadcast/readme.md new file mode 100644 index 0000000000..a99feddf83 --- /dev/null +++ b/bb-api-collect/docs/broadcast/readme.md @@ -0,0 +1,180 @@ +# 全站广播 + +## 获取广播服务器地址 + +> https://api.bilibili.com/x/web-interface/broadcast/servers + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | -------- | ------ | --------------------------------- | +| platform | str | 平台选择 | 必要 | 为web时输出域名<br />其他时输出ip | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ------ | ------------------ | ---- | +| domain | str | 广播服务器url | | +| tcp_port | num | tcp端口 | | +| ws_port | num | websocket端口 | | +| wss_port | num | websocket ssl端口 | | +| heartbeat | num | 最大心跳包间隔时间 | | +| nodes | array | 服务节点地址列表 | | +| backoff | obj | ??? | | +| heartbeat_max | num | ??? | | + +`data`中的`nodes`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---- | +| 0 | str | 服务节点1 | | +| n | str | 服务节点(n+1) | | +| …… | str | …… | | + +`data`中的`backoff`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------ | ---- | +| max_delay | num | ??? | | +| base_delay | num | ??? | | +| factor | num | ??? | | +| jitter | num | ??? | | + +示例: + +当`platform`=`web`时,不显示节点ip + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/broadcast/servers' \ +--data-urlencode 'platform=web' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "domain": "broadcast.chat.bilibili.com", + "tcp_port": 7821, + "ws_port": 7822, + "wss_port": 7823, + "heartbeat": 30, + "nodes": ["broadcast.chat.bilibili.com"], + "backoff": { + "max_delay": 300, + "base_delay": 3, + "factor": 1.8, + "jitter": 0.3 + }, + "heartbeat_max": 3 + } +} +``` + +</details> + +当`platform`=其他时,显示节点ip + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/broadcast/servers' \ +--data-urlencode 'platform=1' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "domain": "broadcast.chat.bilibili.com", + "tcp_port": 7821, + "ws_port": 7822, + "wss_port": 7823, + "heartbeat": 30, + "nodes": ["134.175.207.130", "120.92.150.90", "120.92.150.212", "192.144.173.136", "154.8.217.108"], + "backoff": { + "max_delay": 300, + "base_delay": 3, + "factor": 1.8, + "jitter": 0.3 + }, + "heartbeat_max": 3 + } +} +``` + +</details> + +## 服务器数据包 + +连接服务器分为三种方式,分别是ws wss tcp,数据包分为上行和下行 + +单个数据包分为头部和正文 + +其中上行的有认证包 心跳包,下行的有认证包回复 心跳包回复 普通包 + +建立连接后超过30s内未发送认证包,或握手后30s内未发送心跳包,或发送了错误的认证包,都会被强制断开连接 + +操作流程: + +1.发送认证包,等待接收认证回复 + +2.确认握手成功后,每30s内发送心跳包,并立即接收心跳包回复 + +3.空闲时间接收普通包 + +### 数据包结构 + +头部通用于上行和下行数据包 + +头部格式: + +| 偏移量 | 长度(字节) | 类型 | 含义 | +| ------ | ------------ | ------ | ---------------------------------------------------- | +| 0x00 | 4 | uint32 | 封包总大小(头部大小+正文大小) | +| 0x04 | 2 | uint16 | 头部大小(一般为0x0012,18字节) | +| 0x06 | 2 | uint16 | 协议版本,可取常数1 | +| 0x08 | 4 | uint32 | 操作码(包类型)<br />**见下表** | +| 0x0C | 4 | uint32 | sequence(请求次数),可取常数1<br />对于普通包恒为0 | +| 0x10 | 2 | uint16 | 保留,一般为0 | + +操作码: + +| 代码 | 含义 | +| ---- | -------- | +| 2 | 心跳 | +| 3 | 心跳回复 | +| 7 | 认证 | +| 8 | 认证回复 | +| 1000 | 实时弹幕 | + +**示例:** + +以下为一个认证包示例,正文为文本`test` + +``` +00000000 00 00 00 16 00 12 00 01 00 00 00 07 00 00 00 01 |................| +00000010 00 00 74 65 73 74 |..test| +``` + + diff --git a/bb-api-collect/docs/broadcast/video_room.md b/bb-api-collect/docs/broadcast/video_room.md new file mode 100644 index 0000000000..b0dd5518a3 --- /dev/null +++ b/bb-api-collect/docs/broadcast/video_room.md @@ -0,0 +1,144 @@ +# 视频实时信息 + +## 认证包(上行) + +**正文内容json:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ------ | -------- | ------------------------------ | +| room_id | str | 目标视频 | `video://{稿件avid}/{视频cid}` | +| platform | str | 平台标识 | 默认为`web` | +| accepts | array | 操作标识 | | + +`array`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ------------ | +| 0 | num | 1000 | 作用尚不明确 | +| 1 | num | 1015 | 作用尚不明确 | + +**示例:** + +发送视频`av706`(1P的cid为` 3724723 `)的认证包 + +``` +00000000 00 00 00 55 00 12 00 01 00 00 00 07 00 00 00 01 |...U............| +00000010 00 00 7b 22 72 6f 6f 6d 5f 69 64 22 3a 22 76 69 |..{"room_id":"vi| +00000020 64 65 6f 3a 2f 2f 37 30 36 2f 33 37 32 34 37 32 |deo://706/372472| +00000030 33 22 2c 22 70 6c 61 74 66 72 6f 6d 22 3a 22 77 |3","platfrom":"w| +00000040 65 62 22 2c 22 61 63 63 65 70 74 73 22 3a 5b 31 |eb","accepts":[1| +00000050 30 30 30 2c 31 30 31 35 5d 7d |000,1015]}| +``` + +## 认证包回复(下行) + +**正文内容json:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | -------- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | 默认为OK | +| version | num | 版本号 | | + +示例: + +``` +00000000 00 00 00 37 00 12 00 01 00 00 00 08 00 00 00 01 |...7............| +00000010 00 00 7b 22 63 6f 64 65 22 3a 30 2c 22 6d 65 73 |..{"code":0,"mes| +00000020 73 61 67 65 22 3a 22 4f 4b 22 2c 22 76 65 72 73 |sage":"OK","vers| +00000030 69 6f 6e 22 3a 31 7d |ion":1}| +``` + +## 心跳包(上行) + +正文可为任意内容或为空 + +**示例:** + +正文为空的示例 + +``` +00000000 00 00 00 12 00 12 00 01 00 00 00 02 00 00 00 01 |................| +00000010 00 00 |..| +``` + +正文为`[object Object]`的示例 + +``` +00000000 00 00 00 21 00 12 00 01 00 00 00 02 00 00 00 01 |...!............| +00000010 00 00 5b 6f 62 6a 65 63 74 20 4f 62 6a 65 63 74 |..[object Object| +00000020 5d |]| +``` + +## 心跳包回复(实时观看数)(下行) + +**正文内容json:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | -------- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | 默认为OK | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------------- | ---- | +| room | obj | 视频实时观看信息 | | + +`data`中的`room`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ------------ | ------------------------------ | +| online | num | 实时观看人数 | | +| room_id | str | 目标视频 | `video://{稿件avid}/{视频cid}` | + +**示例:** + +当前视频`av706`实时观看人数为13 + +``` +00000000 00 00 00 68 00 12 00 01 00 00 00 03 00 00 00 01 |...h............| +00000010 00 00 7b 22 63 6f 64 65 22 3a 30 2c 22 6d 65 73 |..{"code":0,"mes| +00000020 73 61 67 65 22 3a 22 30 22 2c 22 64 61 74 61 22 |sage":"0","data"| +00000030 3a 7b 22 72 6f 6f 6d 22 3a 7b 22 6f 6e 6c 69 6e |:{"room":{"onlin| +00000040 65 22 3a 31 33 2c 22 72 6f 6f 6d 5f 69 64 22 3a |e":13,"room_id":| +00000050 22 76 69 64 65 6f 3a 2f 2f 37 30 36 2f 33 37 32 |"video://706/372| +00000060 34 37 32 33 22 7d 7d 7d |4723"}}}| +``` + +## 普通包(实时弹幕)(下行) + +**正文内容json:** + +根数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------ | ------------------------------------------------------------ | +| 0 | str | 弹幕属性信息 | 详见[「弹幕」中的属性 p](https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/danmaku/danmaku_xml.md) | +| 1 | str | 弹幕内容 | | + +**示例:** + +弹幕属性为`0.25,1,25,16777215,1588433046,1588431486568150,0,33ad5d91,32134068443807747` + +弹幕内容为`此生无悔入东方,来世愿生幻想乡` + +``` +00000000 00 00 00 91 00 12 00 01 00 00 03 e8 00 00 00 00 |................| +00000010 00 00 5b 22 30 2e 32 35 2c 31 2c 32 35 2c 31 36 |..["0.25,1,25,16| +00000020 37 37 37 32 31 35 2c 31 35 38 38 34 33 33 30 34 |777215,158843304| +00000030 36 2c 31 35 38 38 34 33 31 34 38 36 35 36 38 31 |6,15884314865681| +00000040 35 30 2c 30 2c 33 33 61 64 35 64 39 31 2c 33 32 |50,0,33ad5d91,32| +00000050 31 33 34 30 36 38 34 34 33 38 30 37 37 34 37 22 |134068443807747"| +00000060 2c 22 e6 ad a4 e7 94 9f e6 97 a0 e6 82 94 e5 85 |,"此 生 无 悔| +00000070 a5 e4 b8 9c e6 96 b9 ef bc 8c e6 9d a5 e4 b8 96 |入 东 方 ,来 世 | +00000080 e6 84 bf e7 94 9f e5 b9 bb e6 83 b3 e4 b9 a1 22 |愿 生 幻 想 乡"| +00000090 5d |]| +``` diff --git a/bb-api-collect/docs/cheese/info.md b/bb-api-collect/docs/cheese/info.md new file mode 100644 index 0000000000..b3f0b89e0c --- /dev/null +++ b/bb-api-collect/docs/cheese/info.md @@ -0,0 +1,640 @@ +# 课程基本信息 + +课程ssid与epid和番剧不互通 + +课程avid与普通视频绝大部分api接口不能互通,少部分互通接口如下: + +1. 获取视频简介 +2. 查询视频状态数 +3. 查询分P列表 +4. 视频快照 +5. 获取弹幕(使用cid) +6. 发送弹幕 +7. 高能进度条(使用cid) + +## 获取课程基本信息 + +> https://api.bilibili.com/pugv/view/web/season + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +鉴权方式:referer为 `.bilibili.com`域名下 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | -------- | ------------ | -------------------------------------------------- | +| season_id | num | 课程ssid | 必要(可选) | season_id与ep_id任选其一<br />**与番剧ssid不互通** | +| ep_id | num | 课程epid | 必要(可选) | season_id与ep_id任选其一<br />**与番剧epid不互通** | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------- | +| code | num | 返回值 | 0:成功<br />-404:错误 | +| message | str | 错误信息 | 默认为success | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------- | ------ | ----------------------------- | ------------------------------------------------------------ | +| brief | obj | 课程概述信息 | | +| coupon | obj | 优惠信息 | 若无优惠则无此项 | +| cover | str | 课程封面url | | +| episode_page | obj | 课程分集信息 | | +| episode_sort | num | 1 | **作用尚不明确** | +| episodes | array | 课程分集列表 | | +| faq | obj | 常见问题信息1 | 合并格式 | +| faq1 | obj | 常见问题信息2 | 分离格式 | +| payment | obj | 付费信息 | | +| purchase_note | obj | 购买须知信息 | | +| purchase_protocol | obj | 付费内容协议信息 | | +| release_bottom_info | str | 底部更新状态文字 | | +| release_info | str | 更新状态文字+更新连载状态文字 | | +| release_info2 | str | 更新连载状态文字 | | +| release_status | str | 更新状态文字 | | +| season_id | num | 课程ssid | **与番剧ssid不互通** | +| share_url | str | 页面url | | +| short_link | str | bilibili uri链接 | | +| stat | obj | 播放数信息 | | +| status | num | 10 | **作用尚不明确** | +| subtitle | str | 课程简介信息 | | +| title | str | 课程标题 | | +| up_info | obj | UP主信息 | | +| user_status | obj | 用户状态信息 | **需要登录(SESSDATA)且referer为`https://www.bilibili.com`** | + +`data`中的`brief`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | -------- | ---- | +| content | str | 空 | | +| img | array | 简介图片 | | +| title | str | 课程概述 | | +| type | num | 2 | | + +`brief`中的`img`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | obj | 简介图片1 | | +| n | obj | 简介图片(n+1) | | +| …… | obj | …… | …… | + +`img`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ----------- | ---------------- | +| aspect_ratio | num | ??? | **作用尚不明确** | +| url | str | 简介图片url | | + +`data`中的`coupon`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | --------- | ------------------- | +| amount | num | 折扣乘数 | | +| expire_time | str | 结束时间 | YYYY-MM-DD HH:MM:SS | +| start_time | str | 起始时间 | YYYY-MM-DD HH:MM:SS | +| status | num | ??? | **作用尚不明确** | +| title | str | 优惠标题 | | +| token | str | 领取token | | + +`data`中的`episode_page`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | -------- | ---- | +| next | bool | false | | +| num | num | 1 | | +| size | num | 总计集数 | | +| total | num | 总计集数 | | + +`data`中的`episodes`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | obj | 课程分集1 | | +| n | obj | 课程分集(n+1) | | +| …… | obj | …… | …… | + +`episodes`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | ---------------- | ------------------------------------------------------------ | +| aid | num | 课程分集avid | **与普通稿件avid部分不互通** | +| cid | num | 课程分集cid | **与普通视频cid部分不互通** | +| duration | num | 课程分集时间长度 | 单位为秒 | +| from | str | pugv | | +| id | num | 课程分集epid | **与番剧epid不互通** | +| index | num | 课程分集数 | | +| page | num | 1 | | +| play | num | 课程分集播放量 | | +| release_date | num | 课程分集发布时间 | 时间戳 | +| status | num | 分集权限属性 | 1:可观看<br />2:不可观看 | +| title | str | 课程分集标题 | | +| watched | bool | 是否观看该集 | **需要登录(SESSDATA)且referer为`https://www.bilibili.com`**<br />false:未观看<br />true:已观看 | +| watchedHistory | num | 该集观看历史 | **需要登录(SESSDATA)且referer为`https://www.bilibili.com`** | + +`data`中的`faq`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | --------------- | ---- | +| content | str | 常见问题信息 | | +| link | str | 常见问题页面url | | +| title | str | 常见问题 | | + +`data`中的`faq1`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ------ | ------------ | ---- | +| items | array | 常见问题列表 | | +| title | str | 常见问题 | | + +`faq1`中的`items`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | obj | 常见问题1 | | +| n | obj | 常见问题(n+1) | | +| …… | obj | …… | …… | + +`items`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------- | ---- | +| answer | str | 回答信息 | | +| question | str | 问题信息 | | + +`data`中的`payment`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | -------------------- | ----------------------- | +| desc | str | 付费价格说明 | | +| discount_desc | str | 折扣说明信息 | 若无优惠则无此项 | +| discount_prefix | str | 折扣类型前缀 | 若无优惠则无此项 | +| pay_shade | str | 观看所有视频付费说明 | | +| price | num | 课程价格 | 单位为B币(折扣后价格) | +| price_format | str | 课程价格 | 单位为B币折扣后价格) | + +`data`中的`purchase_note`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------------------- | ---- | +| content | str | 购买须知信息文字内容 | | +| link | str | 购买须知页面url | | +| title | str | 购买须知 | | + +`data`中的`purchase_protocol`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ------------------- | ---- | +| link | str | 付费内容协议页面url | | +| title | str | 付费内容协议 | | + +`data`中的`stat`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | -------------- | ---- | +| play | num | 播放量 | | +| play_desc | str | 播放量文字信息 | | + +`data`中的`up_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | ------------------------------------------------------------ | +| avatar | str | UP主头像url | | +| brief | str | UP主备注 | 非个人签名 | +| follower | num | UP主粉丝数 | | +| is_follow | num | 是否关注UP主 | **需要登录(SESSDATA)且referer为`https://www.bilibili.com`**<br />0:未关注<br />1:已关注 | +| link | str | UP主空间url | | +| mid | num | UP主uid | | +| pendant | obj | ??? | **作用尚不明确** | +| uname | str | UP主昵称 | | + +`up_info`中的`pendant`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ---- | ---------------- | +| image | str | 空 | **作用尚不明确** | +| name | str | 空 | **作用尚不明确** | +| follower | num | 0 | **作用尚不明确** | + +`data`中的`user_status`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | -------- | ------------------------ | +| favored | num | 是否收藏 | 0:未收藏<br />1:已收藏 | +| favored_count | num | 1 | **作用尚不明确** | +| payed | num | 是否购买 | 0:未购买<br />1:已购买 | +| progress | obj | 课程进度 | 未登录无此项 | + +`user_status`中的`progress`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ------------------ | -------- | +| last_ep_id | num | 最后观看的epid | | +| last_ep_index | str | 最后观看的标题 | | +| last_time | num | 最后观看的时间进度 | 单位为秒 | + +**示例:** + +查询课程`ss61`或分集`ep790`的信息 + +ssid方式: + +```shell +curl -G 'https://api.bilibili.com/pugv/view/web/season' \ +--data-urlencode 'season_id=61' \ +-b 'SESSDATA=xxx' \ +-e 'https://www.bilibili.com' +``` + +epid方式: + +```shell +curl -G 'https://api.bilibili.com/pugv/view/web/season' \ +--data-urlencode 'ep_id=790' \ +-b 'SESSDATA=xxx' \ +-e 'https://www.bilibili.com' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "brief": { + "content": "", + "img": [ + { + "aspect_ratio": 0.9375, + "url": "http://i0.hdslb.com/bfs/archive/29942f338ee570632838403a09871bad130cfe9a.jpg" + }, + { + "aspect_ratio": 0.9375, + "url": "http://i0.hdslb.com/bfs/archive/913e5c37d836d7954ae9ca19da62a43ba5b34219.jpg" + }, + { + "aspect_ratio": 1.3359375, + "url": "http://i0.hdslb.com/bfs/archive/a974555bd4a52f0aa865bd192c1e3401ed4cb0ad.jpg" + }, + { + "aspect_ratio": 1.3359375, + "url": "http://i0.hdslb.com/bfs/archive/73cd7669b251db9d2b62b921bee49a137c3d65dc.jpg" + }, + { + "aspect_ratio": 1.0625, + "url": "http://i0.hdslb.com/bfs/archive/b084ac8f6710c8eddbc58770a4254508de75eb02.jpg" + }, + { + "aspect_ratio": 1.2890625, + "url": "http://i0.hdslb.com/bfs/archive/44e32c2cf64b894563829ce65bbef199220f4121.jpg" + }, + { + "aspect_ratio": 1.3203125, + "url": "http://i0.hdslb.com/bfs/archive/90764fd095810565713b92606dc9cd0cfb25adae.jpg" + }, + { + "aspect_ratio": 1.15234375, + "url": "http://i0.hdslb.com/bfs/archive/c35ca0ced0ad075a2c13b8fdc1e47b88573bce45.jpg" + } + ], + "title": "课程概述", + "type": 2 + }, + "coupon": { + "amount": 0.66, + "expire_time": "2020-06-30 00:00:00", + "start_time": "2020-05-21 00:00:00", + "status": 1, + "title": "【上新限时6.6折】《唐盾:0-N4日语精讲》", + "token": "B20200521135929161905873" + }, + "cover": "http://i0.hdslb.com/bfs/archive/95d4de9e6691ccc2b18f087f5f654652dee3c01b.jpg", + "episode_page": { + "next": false, + "num": 1, + "size": 66, + "total": 66 + }, + "episode_sort": 1, + "episodes": [ + { + "aid": 76973173, + "cid": 132105993, + "duration": 2223, + "from": "pugv", + "id": 790, + "index": 1, + "page": 1, + "play": 2406406, + "release_date": 1574762407, + "status": 1, + "title": "唐盾:一起从0基础学日语吧(含50音 词汇试听)", + "watched": false, + "watchedHistory": 0 + }, + { + "aid": 77114885, + "cid": 132110244, + "duration": 3003, + "from": "pugv", + "id": 795, + "index": 2, + "page": 1, + "play": 49100, + "release_date": 1574766759, + "status": 2, + "title": "50音あ行假名/音调/送气与不送气音", + "watched": false, + "watchedHistory": 0 + }, + { + "aid": 77120689, + "cid": 131913553, + "duration": 3253, + "from": "pugv", + "id": 797, + "index": 3, + "page": 1, + "play": 49518, + "release_date": 1574770029, + "status": 2, + "title": "50音图的か行、さ行、た行假名", + "watched": false, + "watchedHistory": 0 + }, + ………… + ], + "faq": { + "content": "Q:课程在什么时间更新?\nA:课程更新频次以页面前端展示为准。购买成功后,课程更新将通过账号动态提示,方便及时观看。\n\nQ:课程购买后有收看时间限制吗?\nA:购买后除不可抗力因素外,课程均可永久收看,请您放心购买。\n\nQ:原价购买课程后,如遇到优惠折扣,是否可以退还差价或重新购买?\nA:虚拟商品付款后无法返还,请您随时留意各类课程折扣信息,按需购买。\n\nQ:购买课程后是否可以加入老师的粉丝群或者用户群?\nA:如老师设置用户群,我们将邀您加入,但我们无法承诺所有老师均提供用户群服务,感谢理解。", + "link": "http://m.bilibili.com", + "title": "常见问题" + }, + "faq1": { + "items": [ + { + "answer": "课程更新频次以页面前端展示为准。购买成功后,课程更新将通过账号动态提示,方便及时观看。", + "question": "课程在什么时间更新?" + }, + { + "answer": "购买后除不可抗力因素外,课程均可永久收看,请您放心购买。", + "question": "课程购买后有收看时间限制吗?" + }, + { + "answer": "虚拟商品付款后无法返还,请您随时留意各类课程折扣信息,按需购买。", + "question": "原价购买课程后,如遇到优惠折扣,是否可以退还差价或重新购买?" + }, + { + "answer": "如老师设置用户群,我们将邀您加入,但我们无法承诺所有老师均提供用户群服务,感谢理解。", + "question": "购买课程后是否可以加入老师的粉丝群或者用户群?" + } + ], + "title": "常见问题" + }, + "payment": { + "desc": "券后 262.68 B币起/53期", + "discount_desc": "262.68 B币", + "discount_prefix": "券后", + "pay_shade": "券后支付 262.68 B币即可观看所有视频", + "price": 398.0, + "price_format": "398" + }, + "purchase_note": { + "content": "1. 本内容为付费内容,购买成功后方可观看。<br/>2. 本内容为虚拟服务,已购买内容不支持退款,敬请谅解。<br/>3. 实际购买价格以页面展示的价格及订单结算页显示价格为准。<br/>4. 如您在购买付费内容时有任何疑问,可随时咨询在线客服。<br/>完整的购买协议,请点击阅读<a href=\"https://www.bilibili.com/blackboard/activity-y-SJTTYBp.html\" color=\"#0ba395\" target=\"_blank\">《bilibili付费内容购买协议》</a>", + "link": "https://www.bilibili.com/blackboard/activity-y-SJTTYBp.html", + "title": "购买须知" + }, + "purchase_protocol": { + "link": "https://www.bilibili.com/blackboard/activity-y-SJTTYBp.html", + "title": "bilibili付费内容购买协议" + }, + "release_bottom_info": "没有更多啦~", + "release_info": "已完结,共53期", + "release_info2": "共53期", + "release_status": "已完结", + "season_id": 61, + "share_url": "https://m.bilibili.com/cheese/play/ss61", + "short_link": "bilibili://cheese/season/61", + "stat": { + "play": 2878146, + "play_desc": "287.8万播放" + }, + "status": 10, + "subtitle": "新东方名师唐盾的精品日语课,包含50音/N5/N4的词汇/语法/课文/练习精讲,让我们一起轻松学日语~", + "title": "唐盾:0-N4日语精讲", + "up_info": { + "avatar": "http://i1.hdslb.com/bfs/face/564421428d1f74314ed50e16a8f570ad968828b0.jpg", + "brief": "唐盾:前新东方日语名师,倾注日语教学、翻译14年。曾任新东方欧亚教育长沙中心总监。", + "follower": 21333, + "is_follow": 0, + "link": "https://space.bilibili.com/19452605", + "mid": 19452605, + "pendant": { + "image": "", + "name": "", + "pid": 0 + }, + "uname": "盾盾桑教你学日语" + }, + "user_status": { + "favored": 1, + "favored_count": 1, + "payed": 0, + "progress": { + "last_ep_id": 790, + "last_ep_index": "唐盾:一起从0基础学日语吧(含50音 词汇试听)", + "last_time": 1 + } + } + }, + "message": "success" +} +``` + +</details> + +## 获取课程分集列表 + +> https://api.bilibili.com/pugv/view/web/ep/list + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +鉴权方式:referer为 `.bilibili.com`域名下 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | -------- | ------ | -------------------- | +| season_id | num | 课程ssid | 必要 | **与番剧ssid不互通** | +| ps | num | 每页项数 | 非必要 | 默认为50 | +| pn | num | 页码 | 非必要 | 默认为1 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------- | +| code | num | 返回值 | 0:成功<br />-404:错误 | +| message | str | 错误信息 | 默认为success | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ------ | ------------ | ---- | +| items | array | 课程分集列表 | | +| page | obj | 列表分页信息 | | + +`data`中的`items`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | obj | 课程分集1 | | +| n | obj | 课程分集(n+1) | | +| …… | obj | …… | …… | + +`items`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | ---------------- | ------------------------------------------------------------ | +| aid | num | 课程分集avid | **与普通稿件avid部分不互通** | +| cid | num | 课程分集cid | **与普通视频cid部分不互通** | +| duration | num | 课程分集时间长度 | 单位为秒 | +| from | str | pugv | | +| id | num | 课程分集epid | **与番剧epid不互通** | +| index | num | 课程分集数 | | +| page | num | 1 | | +| play | num | 课程分集播放量 | | +| release_date | num | 课程分集发布时间 | 时间戳 | +| status | num | 分集权限属性 | 1:可观看<br />2:不可观看 | +| title | str | 课程分集标题 | | +| watched | bool | 是否观看该集 | **需要登录(SESSDATA)且referer为`https://www.bilibili.com`**<br />false:未观看<br />true:已观看 | +| watchedHistory | num | 该集观看历史 | **需要登录(SESSDATA)且referer为`https://www.bilibili.com`** | + +`data`中的`page`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | -------------- | ----------------------------------------- | +| next | bool | 是否存在下一页 | false:不存在下一页<br />true:存在下一页 | +| num | num | 当前页码 | | +| size | num | 每页项数 | | +| total | num | 总价项数 | | + +**示例:** + +按照每页5项查询课程`ss61`的分集列表第1页 + +```shell +curl -G 'https://api.bilibili.com/pugv/view/web/ep/list' \ +--data-urlencode 'season_id=61' \ +--data-urlencode 'ps=5 ' \ +--data-urlencode 'pn=1' \ +-b 'SESSDATA=xxx' \ +-e 'https://www.bilibili.com' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "items": [ + { + "aid": 76973173, + "cid": 132105993, + "duration": 2223, + "from": "pugv", + "id": 790, + "index": 1, + "page": 1, + "play": 2406951, + "release_date": 1574762407, + "status": 1, + "title": "唐盾:一起从0基础学日语吧(含50音 词汇试听)", + "watched": false, + "watchedHistory": 0 + }, + { + "aid": 77114885, + "cid": 132110244, + "duration": 3003, + "from": "pugv", + "id": 795, + "index": 2, + "page": 1, + "play": 49106, + "release_date": 1574766759, + "status": 2, + "title": "50音あ行假名/音调/送气与不送气音", + "watched": false, + "watchedHistory": 0 + }, + { + "aid": 77120689, + "cid": 131913553, + "duration": 3253, + "from": "pugv", + "id": 797, + "index": 3, + "page": 1, + "play": 49522, + "release_date": 1574770029, + "status": 2, + "title": "50音图的か行、さ行、た行假名", + "watched": false, + "watchedHistory": 0 + }, + { + "aid": 77606110, + "cid": 132897199, + "duration": 2823, + "from": "pugv", + "id": 806, + "index": 4, + "page": 1, + "play": 35800, + "release_date": 1575128696, + "status": 2, + "title": "50音图的な行、は行、ま行假名", + "watched": false, + "watchedHistory": 0 + }, + { + "aid": 78015255, + "cid": 133651764, + "duration": 2165, + "from": "pugv", + "id": 812, + "index": 5, + "page": 1, + "play": 25842, + "release_date": 1575446218, + "status": 2, + "title": "や行、ら行、わ行假名、拨音", + "watched": false, + "watchedHistory": 0 + } + ], + "page": { + "next": true, + "num": 1, + "size": 5, + "total": 66 + } + }, + "message": "success" +} +``` + +</details> diff --git a/bb-api-collect/docs/cheese/videostream_url.md b/bb-api-collect/docs/cheese/videostream_url.md new file mode 100644 index 0000000000..fee29ddcc7 --- /dev/null +++ b/bb-api-collect/docs/cheese/videostream_url.md @@ -0,0 +1,222 @@ +# 课程视频流URL + +<img src="../../assets/img/download.svg" width="100" height="100"/> + +## 获取课程视频流URL(web端) + +> https://api.bilibili.com/pugv/player/web/playurl + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**注:** + +1. 本接口为课程视频专用,故与普通视频不互通 +2. 大部分使用方法及视频的取流方法继承[视频流url文档](../video/videostream_url.md) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------------- | ------ | ------------------------------------------------------------ | +| avid | num | 课程avid | 必要 | | +| ep_id | num | 课程epid | 必要 | | +| cid | num | 视频cid | 必要 | | +| qn | num | 视频清晰度选择 | 非必要 | 参考[qn定义](../video/videostream_url.md#qn视频清晰度标识) | +| fnver | num | 视频流版本 | 非必要 | 参考[fnver定义](../video/videostream_url.md#fnver视频流版本标识) | +| fnval | num | 视频流类型 | 非必要 | 参考[fnval定义](../video/videostream_url.md#fnval视频流格式标识) | +| fourk | num | 是否允许4K视频 | 非必要 | 默认为0<br />画质最高1080P:0<br />画质最高4K:1 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功 <br />-400:请求错误<br />-404:无视频<br />-403:权限不足(未购买) | +| message | str | 错误信息 | 默认为success | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------ | ------ | ---------------------- | ---------------------------------------- | +| accept_format | str | 视频支持的分辨率的格式 | | +| code | num | 0 | | +| durl | array | 视频分段 | | +| seek_param | str | start | | +| no_rexcode | num | 0 | | +| format | str | 视频格式 | | +| fnval | num | 0 | | +| video_project | bool | true | | +| fnver | num | 0 | | +| message | str | 空 | | +| type | str | 视频格式 | | +| accept_quality | array | 视频支持的分辨率列表 | | +| quality | num | 视频分辨率代码 | **值含义见上表** | +| timelength | num | 视频长度 | 单位为毫秒<br />不同分辨率可能有略微差异 | +| result | str | suee | **作用尚不明确** | +| seek_type | str | offset | **作用尚不明确** | +| has_paid | bool | false | **作用尚不明确** | +| supportFormats | array | 视频分辨率详细列表 | | +| from | str | local | **作用尚不明确** | +| video_codecid | num | ??? | **作用尚不明确** | +| accept_description | array | 视频支持的分辨率列表 | | +| status | num | 0 | **作用尚不明确** | + +`data`中的`durl`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------------- | ---- | +| 0 | obj | 视频分段1信息 | | +| n | obj | 视频分段(n+1)信息 | | +| …… | obj | …… | | + +`durl`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ------ | ------------ | ---------------------------------- | +| size | num | 视频大小 | 单位为Byte | +| ahead | str | 空 | 作用尚不明确 | +| length | num | 视频长度 | 单位为毫秒 | +| vhead | str | 空 | 作用尚不明确 | +| backup_url | array | 备用视频流 | | +| url | str | 视频流url | 链接有效时间为120min | +| order | num | 视频分段序号 | 某些视频会分为多个片段 | + +`durl`数组中的对象中的`backup_url`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---------------- | +| 0 | str | 备用视频流url | 有效时间为120min | + +`data`中的`supportFormats`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------------- | ---- | +| 0 | obj | 分辨率详细信息1 | | +| n | obj | 分辨率详细信息(n+1) | | +| …… | obj | …… | …… | + +`supportFormats`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ---------- | ---- | +| format | str | 分辨率名称 | | +| description | atr | 分辨率备注 | | +| quality | num | 分辨率代码 | | + +`data`中的`accept_description`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | str | 分辨率名称1 | | +| n | str | 分辨率名称(n+1) | | +| …… | str | …… | …… | + +**示例:** + +获取课程`ep790`(cid=`132105993`,avid=`76973173`)的视频流url,清晰度为1080P60 + +```shell +curl -G 'https://api.bilibili.com/pugv/player/web/playurl' \ +--data-urlencode 'ep_id=790' \ +--data-urlencode 'avid=76973173' \ +--data-urlencode 'cid=132105993' \ +--data-urlencode 'qn=116' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "accept_format": "flv_p60,flv720_p60,flv,flv720,flv480,flv360", + "code": 0, + "durl": [ + { + "size": 1105854161, + "ahead": "", + "length": 2222204, + "vhead": "", + "backup_url": [ + "https://upos-sz-mirrorks3c.bilivideo.com/upgcxcode/93/59/132105993/132105993_da2-1-116.flv?e=ig8euxZM2rNcNbNghzTBhwdlhbNz7bUVhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1591596728&gen=playurl&os=ks3cbv&oi=606633803&trid=76bea9a9e56f4cb89a9aff2f8213c9acu&platform=pc&upsig=b271bf493bff32ffe62969582c8d18b4&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=0&orderid=1,2&logo=40000000" + ], + "url": "https://upos-sz-mirrorks3.bilivideo.com/upgcxcode/93/59/132105993/132105993_da2-1-116.flv?e=ig8euxZM2rNcNbNghzTBhwdlhbNz7bUVhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1591596728&gen=playurl&os=ks3bv&oi=606633803&trid=76bea9a9e56f4cb89a9aff2f8213c9acu&platform=pc&upsig=6a8ae3711bd0bb2a484ec2427d659b14&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=0&orderid=0,2&logo=80000000", + "order": 1, + "md5": "" + } + ], + "seek_param": "start", + "no_rexcode": 0, + "format": "flv_p60", + "fnval": 0, + "video_project": true, + "fnver": 0, + "message": "", + "type": "FLV", + "accept_quality": [ + 116, + 74, + 80, + 64, + 32, + 16 + ], + "quality": 116, + "timelength": 2222204, + "result": "suee", + "seek_type": "offset", + "has_paid": false, + "supportFormats": [ + { + "format": "flv_p60", + "description": "高清 1080P60", + "quality": 116 + }, + { + "format": "flv720_p60", + "description": "高清 720P60", + "quality": 74 + }, + { + "format": "flv", + "description": "高清 1080P", + "quality": 80 + }, + { + "format": "flv720", + "description": "高清 720P", + "quality": 64 + }, + { + "format": "flv480", + "description": "清晰 480P", + "quality": 32 + }, + { + "format": "flv360", + "description": "流畅 360P", + "quality": 16 + } + ], + "from": "local", + "video_codecid": 7, + "accept_description": [ + "高清 1080P60", + "高清 720P60", + "高清 1080P", + "高清 720P", + "清晰 480P", + "流畅 360P" + ], + "status": 0 + }, + "message": "success" +} +``` + +</details> \ No newline at end of file diff --git a/bb-api-collect/docs/clientinfo/ip.md b/bb-api-collect/docs/clientinfo/ip.md new file mode 100644 index 0000000000..a767cffd5d --- /dev/null +++ b/bb-api-collect/docs/clientinfo/ip.md @@ -0,0 +1,157 @@ +# 通过ip确定地理位置 + +## 根据请求IP确定属地 + +> https://api.bilibili.com/x/web-interface/zone +> +> https://api.live.bilibili.com/xlive/web-room/v1/index/getIpInfo +> +> https://app.bilibili.com/x/resource/ip + +*请求方式:GET* + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ------------- | ------------ | +| addr | str | 公网IP地址 | | +| country | str | 国家/地区名 | | +| province | str | 省/州 | 非必须存在项 | +| city | str | 城市 | 非必须存在项 | +| isp | str | 运营商名 | | +| latitude | num | 纬度 | | +| longitude | num | 经度 | | +| zone_id | num | ip数据库id | 第二个接口无 | +| country_code | num | 国家/地区代码 | 第二个接口无 | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/web-interface/zone' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code":0, + "message":"0", + "ttl":1, + "data":{ + "addr":"36.40.120.145", + "country":"中国", + "province":"陕西", + "city":"渭南", + "isp":"电信", + "latitude":34.4995, + "longitude":109.492821, + "zone_id":4472912, + "country_code":86 + } +} +``` + +</details> + +## 查询任意 IP 地址的归属地 + +> https://api.live.bilibili.com/ip_service/v1/ip_service/get_ip_addr +> https://api.live.bilibili.com/client/v1/Ip/getInfoNew + +注: 以上接口等效 + +*请求方式:GET* + +**URL参数:** + + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| ip | str | IP地址 | 不必要 | IPv4或IPv6地址不限, 留空与[根据请求IP确定地理位置](#根据请求ip确定地理位置)基本相同 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0: 成功 | +| message | str | 错误信息 | 默认为空 | +| msg | str | 错误信息 | 同message | +| data | obj | 信息本体 | 出错时为空数组 | + +`data`对象: + +与[根据请求IP确定地理位置](#根据请求ip确定地理位置)回复的`data`对象基本相同, 但无 `zone_id` `country_code` 字段 + +**示例:** + +查询请求IP地址的归属地: + +```shell +curl -G 'https://api.live.bilibili.com/client/v1/Ip/getInfoNew' +``` + +<details> +<summary>查看响应示例:</summary> + + +```json +{ + "code": 0, + "msg": "", + "message": "", + "data": { + "addr": "104.28.156.113", + "country": "新加坡", + "province": "新加坡", + "city": "", + "isp": "cloudflare.com", + "latitude": "1.352083", + "longitude": "103.819836" + } +} +``` + +</details> + +查询IP地址`8.8.8.8`的归属地: + +```shell +curl -G 'https://api.live.bilibili.com/ip_service/v1/ip_service/get_ip_addr' \ +--data-urlencode 'ip=8.8.8.8' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "", + "message": "", + "data": { + "addr": "8.8.8.8", + "country": "GOOGLE.COM", + "province": "GOOGLE.COM", + "city": "", + "isp": "level3.com", + "latitude": "", + "longitude": "" + } +} +``` + +</details> diff --git a/bb-api-collect/docs/comment/action.md b/bb-api-collect/docs/comment/action.md new file mode 100644 index 0000000000..a0f4823091 --- /dev/null +++ b/bb-api-collect/docs/comment/action.md @@ -0,0 +1,535 @@ +# 评论区操作 + +## 发表评论 + +> https://api.bilibili.com/x/v2/reply/add + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或APP + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | ------------------------------------------------------------ | +| access_key | str | APP登录Token | APP方式必要 | | +| type | num | 评论区类型代码 | 必要 | **[类型代码见表](readme.md#评论区类型代码)** | +| oid | num | 目标评论区id | 必要 | | +| root | num | 根评论rpid | 非必要 | 二级评论以上使用 | +| parent | num | 父评论rpid | 非必要 | 二级评论同根评论id<br />大于二级评论为要回复的评论id | +| message | str | 发送评论内容 | 必要 | 最大1000字符<br />表情使用表情转义符 | +| plat | num | 发送平台标识 | 非必要 | 1:web端<br />2:安卓客户端<br />3:ios客户端<br />4:wp客户端<br />默认为1 | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-102:账号被封停<br />-111:csrf校验失败<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`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ----------------------------- | -------------- | ------------------------------------------------------------ | +| success_action | num | 0 | **作用尚不明确** | +| success_toast | str | 状态文字 | | +| need_captcha | bool | false | 评论需要验证码(未证实) | +| url | str | 空 | **作用尚不明确** | +| rpid | num | 评论rpid | | +| rpid_str | str | 评论rpid | 字串格式 | +| dialog | num | 回复对方rpid | 若为一级评论则为0<br />若为二级评论则为该评论id<br />大于二级评论为上一级评论id | +| dialog_str | str | 回复对方rpid | 字串格式 | +| root | num | 根评论rpid | 若为一级评论则为0<br />大于一级评论则为根评论id | +| root_str | str | 根评论rpid | 字串格式 | +| parent | num | 回复父评论rpid | 若为一级评论则为0<br />若为二级评论则为根评论id<br />大于二级评论为上一级评论id | +| parent_str | str | 回复父评论rpid | 字串格式 | +| emote | obj | 表情转义符信息 | [对象定义见表](readme.md#评论条目对象) | +| reply | 有效时:obj<br />无效时:null | | [对象定义见表](readme.md#评论条目对象) | + +**示例:** + +给视频`av243322853`发送内容为`测试test[泠鸢yousa_awsl]`的评论(带有表情转义符),平台标识为1(web端) + +```shell +curl 'https://api.bilibili.com/x/v2/reply/add' \ +--data-urlencode 'type=1' \ +--data-urlencode 'oid=243322853' \ +--data-urlencode 'message=测试test[泠鸢yousa_awsl]' \ +--data-urlencode 'plat=1' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "success_action": 0, + "success_toast": "发送成功", + "need_captcha": false, + "url": "", + "rpid": 3043212039, + "rpid_str": "3043212039", + "dialog": 0, + "dialog_str": "0", + "root": 0, + "root_str": "0", + "parent": 0, + "parent_str": "0", + "emote": { + "[泠鸢yousa_awsl]": { + "id": 2086, + "package_id": 93, + "state": 0, + "type": 3, + "attr": 0, + "text": "[泠鸢yousa_awsl]", + "url": "http://i0.hdslb.com/bfs/emote/7663b729161bd4556c2ec318c07791000743eb56.png", + "meta": { + "size": 2 + }, + "mtime": 1589776042 + } + }, + "reply": { + "rpid": 3043212039, + "oid": 243322853, + "type": 1, + "mid": 293793435, + "root": 0, + "parent": 0, + "dialog": 0, + "count": 0, + "rcount": 0, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1592233764, + "rpid_str": "3043212039", + "root_str": "0", + "parent_str": "0", + "like": 0, + "action": 0, + "member": { + "mid": "293793435", + "uname": "社会易姐QwQ", + "sex": "男", + "sign": "高中技术宅一枚,爱好MC&电子&8-bit音乐&数码&编程,资深猿厨", + "avatar": "http://i1.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg", + "rank": "10000", + "DisplayRank": "0", + "level_info": { + "current_level": 5, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 1888, + "name": "泠鸢yousa", + "image": "http://i0.hdslb.com/bfs/garb/item/3e66e712b8e70c6b02393c54ad5fd8d993eb39f9.png", + "expire": 0, + "image_enhance": "http://i0.hdslb.com/bfs/garb/item/3e66e712b8e70c6b02393c54ad5fd8d993eb39f9.png" + }, + "nameplate": { + "nid": 0, + "name": "", + "image": "", + "image_small": "", + "level": "", + "condition": "" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1612454400000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip" + } + }, + "fans_detail": null, + "following": 0, + "is_followed": 0, + "user_sailing": { + "pendant": { + "id": 1888, + "name": "泠鸢yousa", + "image": "http://i0.hdslb.com/bfs/garb/item/3e66e712b8e70c6b02393c54ad5fd8d993eb39f9.png", + "jump_url": "", + "type": "suit" + }, + "cardbg": null, + "cardbg_with_focus": null + } + }, + "content": { + "message": "测试test[泠鸢yousa_awsl]", + "plat": 1, + "device": "", + "members": [], + "emote": { + "[泠鸢yousa_awsl]": { + "id": 2086, + "package_id": 93, + "state": 0, + "type": 3, + "attr": 0, + "text": "[泠鸢yousa_awsl]", + "url": "http://i0.hdslb.com/bfs/emote/7663b729161bd4556c2ec318c07791000743eb56.png", + "meta": { + "size": 2 + }, + "mtime": 1589776042 + } + }, + "jump_url": {}, + "max_line": 0 + }, + "replies": null, + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "https://www.bilibili.com/blackboard/foldingreply.html" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false + } + } +} +``` + +</details> + +## 点赞评论 + +> https://api.bilibili.com/x/v2/reply/action + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或APP + +点赞成功后会同时消去该评论的点踩 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | -------------------------------------------- | +| access_key | str | APP登录Token | APP方式必要 | | +| type | num | 评论区类型代码 | 必要 | **[类型代码见表](readme.md#评论区类型代码)** | +| oid | num | 目标评论区id | 必要 | | +| rpid | num | 目标评论rpid | 必要 | | +| action | num | 操作代码 | 非必要 | 默认为0<br />0:取消赞<br />1:点赞 | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-102:账号被封停<br />-111:csrf校验失败<br />-400:请求错误<br />-404:无此项<br />-509:请求过于频繁<br />12002:评论区已关闭<br />12004:禁止操作 赞或踩<br />12006:没有该评论<br />12009:评论主体的type不合法<br />12011:不合法的赞或踩<br />**(其他错误码有待补充)** | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +点赞视频`av243322853`下评论`rpid=3039053308` + +```shell +curl 'https://api.bilibili.com/x/v2/reply/action' \ +--data-urlencode 'type=1' \ +--data-urlencode 'oid=243322853' \ +--data-urlencode 'rpid=3039053308' \ +--data-urlencode 'action=1' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +## 点踩评论 + +> https://api.bilibili.com/x/v2/reply/hate + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或APP + +点踩成功后会同时消去该评论的点赞 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | -------------------------------------------- | +| access_key | str | APP登录Token | APP方式必要 | | +| type | num | 评论区类型代码 | 必要 | **[类型代码见表](readme.md#评论区类型代码)** | +| oid | num | 目标评论区id | 必要 | | +| rpid | num | 目标评论rpid | 必要 | | +| action | num | 操作代码 | 非必要 | 默认为0<br />0:取消踩<br />1:点踩 | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-102:账号被封停<br />-111:csrf校验失败<br />-400:请求错误<br />-404:无此项<br />-509:请求过于频繁<br />12002:评论区已关闭<br />12004:禁止操作 赞或踩<br />12006:没有该评论<br />12009:评论主体的type不合法<br />12011:不合法的赞或踩<br />**(其他错误码有待补充)** | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +点踩视频`av243322853`下评论`rpid=3039053308` + +```shell +curl 'https://api.bilibili.com/x/v2/reply/hate' \ +--data-urlencode 'type=1' \ +--data-urlencode 'oid=243322853' \ +--data-urlencode 'rpid=3039053308' \ +--data-urlencode 'action=1' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +## 删除评论 + +> https://api.bilibili.com/x/v2/reply/del + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或APP + +只能删除自己的评论,或自己管理的评论区下的评论 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | -------------------------------------------- | +| access_key | str | APP登录Token | APP方式必要 | | +| type | num | 评论区类型代码 | 必要 | **[类型代码见表](readme.md#评论区类型代码)** | +| oid | num | 目标评论区id | 必要 | | +| rpid | num | 目标评论rpid | 必要 | | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-102:账号被封停<br />-111:csrf校验失败<br />-400:请求错误<br />-403:权限不足<br />-404:无此项<br />-509:请求过于频繁<br />12002:评论区已关闭<br />12009:评论主体的type不合法<br />12022:已经被删除了<br />**(其他错误码有待补充)** | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | **作用尚不明确** | + +**示例:** + +删除`av243322853`下评论`rpid=3039053308` + +```shell +curl 'https://api.bilibili.com/x/v2/reply/del' \ +--data-urlencode 'type=1' \ +--data-urlencode 'oid=243322853' \ +--data-urlencode 'rpid=3039053308' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +## 置顶评论 + +> https://api.bilibili.com/x/v2/reply/top + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或APP + +只能置顶自己管理的评论区中的一级评论 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | -------------------------------------------- | +| access_key | str | APP登录Token | APP方式必要 | | +| type | num | 评论区类型代码 | 必要 | **[类型代码见表](readme.md#评论区类型代码)** | +| oid | num | 目标评论区id | 必要 | | +| rpid | num | 目标评论rpid | 必要 | | +| action | num | 操作代码 | 非必要 | 默认为0<br />0:取消置顶<br />1:设为置顶 | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-102:账号被封停<br />-111:csrf校验失败<br />-400:请求错误<br />-403:权限不足<br />-404:无此项<br />-509:请求过于频繁<br />12002:评论区已关闭<br />12006:没有该评论<br />12009:评论主体的type不合法<br />12029:已经有置顶评论<br />12030:不能置顶非一级评论<br />**(其他错误码有待补充)** | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +置顶视频`av243322853`下评论`rpid=2940645593` + +```shell +curl 'https://api.bilibili.com/x/v2/reply/top' \ +--data-urlencode 'type=1' \ +--data-urlencode 'oid=243322853' \ +--data-urlencode 'rpid=2940645593' \ +--data-urlencode 'action=1' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +## 举报评论 + +> https://api.bilibili.com/x/v2/reply/report + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或APP + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | -------------------------------------------- | +| access_key | str | APP登录Token | APP方式必要 | | +| type | num | 评论区类型代码 | 必要 | **[类型代码见表](readme.md#评论区类型代码)** | +| oid | num | 目标评论区id | 必要 | | +| rpid | num | 目标评论rpid | 必要 | | +| reason | num | 举报类型 | 必要 | **类型代码见下表** | +| content | str | 其他举报备注 | 非必要 | `reason=0`时有效 | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +举报类型`reason`: + +| 代码 | 含义 | +| ---- | -------------- | +| 0 | 其他 | +| 1 | 垃圾广告 | +| 2 | 色情 | +| 3 | 刷屏 | +| 4 | 引战 | +| 5 | 剧透 | +| 6 | 政治 | +| 7 | 人身攻击 | +| 8 | 内容不相关 | +| 9 | 违法违规 | +| 10 | 低俗 | +| 11 | 非法网站 | +| 12 | 赌博诈骗 | +| 13 | 传播不实信息 | +| 14 | 怂恿教唆信息 | +| 15 | 侵犯隐私 | +| 16 | 抢楼 | +| 17 | 青少年不良信息 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-102:账号被封停<br />-111:csrf校验失败<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 | | + +**示例:** + +举报视频` av752881391 `下评论`rpid=3062537442`,理由是`引战` + +```shell +curl 'https://api.bilibili.com/x/v2/reply/report' \ +--data-urlencode 'type=1' \ +--data-urlencode 'oid=752881391' \ +--data-urlencode 'rpid=3062537442' \ +--data-urlencode 'reason=4' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> diff --git a/bb-api-collect/docs/comment/list.md b/bb-api-collect/docs/comment/list.md new file mode 100644 index 0000000000..e371a4e411 --- /dev/null +++ b/bb-api-collect/docs/comment/list.md @@ -0,0 +1,3722 @@ +# 评论区明细 + +## 获取评论区明细_翻页加载 + +> https://api.bilibili.com/x/v2/reply + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | -------------------------------------------------------- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| type | num | 评论区类型代码 | 必要 | [类型代码见表](readme.md#评论区类型代码) | +| oid | num | 目标评论区 id | 必要 | | +| sort | num | 排序方式 | 非必要 | 默认为0<br />0:按时间<br />1:按点赞数<br />2:按回复数 | +| nohot | num | 是否不显示热评 | 非必要 | 默认为0<br />1:不显示<br />0:显示 | +| ps | num | 每页项数 | 非必要 | 默认为20<br />定义域:1-20 | +| pn | num | 页码 | 非必要 | 默认为1 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----------------------------- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-404:无此项<br />12002:评论区已关闭<br />12009:评论主体的type不合法 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 正确时:obj<br />错误时:null | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | -------------------------------- | -------- | ---------------- | +| page | obj | 页信息 | | +| config | obj | 评论区显示控制 | | +| replies | 禁用时:null<br />正常时:array | 评论列表 | | +| hots | 禁用时:null<br />正常时:array | 热评列表 | | +| upper | obj | 置顶评论 | | +| top | null | (?) | | +| notice | 无效时:null<br />有效时:obj | 评论区公告信息 | | +| vote | num | 投票评论? | | +| blacklist | num | (?) | | +| assist | num | (?) | | +| mode | num | 评论区类型id | | +| support_mode | array | 评论区支持的类型id | | +| folder | obj | 折叠相关信息 | | +| lottery_card | null | (?) | | +| show_bvid | bool | 显示bvid? | | +| control | obj | 评论区输入属性 | | + +`data`中的`page`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ------------ | ---- | +| num | num | 当前页码 | | +| size | num | 每页项数 | | +| count | num | 根评论条数 | | +| acount | num | 总计评论条数 | | + +`data`中的`config`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ------------------------- | ---- | +| showadmin | num | 是否显示管理置顶 | | +| showentry | num | (?) | | +| showfloor | num | 是否显示楼层号 | | +| showtopic | num | 是否显示话题 | | +| show_up_flag | bool | 是否显示“UP 觉得很赞”标志 | | +| read_only | bool | 是否只读评论区 | | +| show_del_log | bool | 是否显示删除记录 | | + +`data`中的`replies`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | -------------------------------------- | +| 0 | obj | 评论条目 1 | [对象定义见表](readme.md#评论条目对象) | +| n | obj | 评论条目 (n+1) | 按照指定的顺序排列 | +| …… | obj | …… | …… | + +`data`中的`hots`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | -------------------------------------- | +| 0 | obj | 热评条目 1 | [对象定义见表](readme.md#评论条目对象) | +| n | obj | 热评条目 (n+1) | 按照热评热度排列 | +| …… | obj | …… | …… | + +`data`中的`upper`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ----------------------------- | ---------- | -------------------------------------- | +| mid | num | UP 主 mid | | +| top | 有效时:obj<br />无效时:null | 置顶条目 | [对象定义见表](readme.md#评论条目对象) | +| vote | 有效时:obj<br />无效时:null | 投票评论? | | + +`data`中的`notice`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ---------------- | ---- | +| content | str | 公告正文 | | +| id | num | 公告 id | | +| link | str | 公告页面链接 url | | +| title | str | 公告标题 | | + +`data`中的`folder`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ---------------------- | ---- | +| has_folded | bool | 评论区是否存在折叠评论 | | +| is_folded | bool | 是否折叠? | | +| rule | str | 相关规则页面 url | | + +`data`中的`control`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------------ | ---- | ------------------ | ----------------------------------- | +| input_disable | bool | 是否禁止新增评论 | 用户涉及合约争议,锁定该用户所有稿件、动态的评论区,不允许新增评论,`root_input_text`和`child_input_text`值为“当前评论区不可新增评论” | +| root_input_text | str | 评论框文字 | | +| child_input_text | str | 评论框文字 | | +| bg_text | str | 空评论区文字 | | +| web_selection | bool | 评论是否筛选后可见 | false:无需筛选<br />true:需要筛选 | +| answer_guide_text | str | 答题页面链接文字 | | +| answer_guide_icon_url | str | 答题页面图标 url | | +| answer_guide_ios_url | str | 答题页面 ios url | | +| answer_guide_android_url | str | 答题页面安卓 url | | + +**示例:** + +获取视频`av2`的评论区明细,不显示热评,按照热度排序,每页5项,查看第1页 + +```shell +curl -G 'https://api.bilibili.com/x/v2/reply' \ +--data-urlencode 'type=1' \ +--data-urlencode 'oid=2' \ +--data-urlencode 'sort=1' \ +--data-urlencode 'ps=5' \ +--data-urlencode 'pn=1' \ +--data-urlencode 'nohot=1' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "page": { + "num": 1, + "size": 5, + "count": 60971, + "acount": 76792 + }, + "config": { + "showadmin": 1, + "showentry": 1, + "showfloor": 0, + "showtopic": 1, + "show_up_flag": true, + "read_only": false, + "show_del_log": false + }, + "replies": [ + { + "rpid": 104192624480, + "oid": 2, + "type": 1, + "mid": 621197713, + "root": 0, + "parent": 0, + "dialog": 0, + "count": 0, + "rcount": 0, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1646205507, + "rpid_str": "104192624480", + "root_str": "0", + "parent_str": "0", + "like": 1, + "action": 0, + "member": { + "mid": "621197713", + "uname": "小鹿不跑路", + "sex": "保密", + "sign": "", + "avatar": "http://i1.hdslb.com/bfs/face/3e220c95ead8f2bc72bd2dcee72d195b723192fa.jpg", + "rank": "10000", + "DisplayRank": "0", + "face_nft_new": 0, + "is_senior_member": 0, + "level_info": { + "current_level": 4, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "nameplate": { + "nid": 0, + "name": "", + "image": "", + "image_small": "", + "level": "", + "condition": "" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1648051200000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "大会员", + "label_theme": "vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png", + "nickname_color": "" + }, + "fans_detail": null, + "following": 0, + "is_followed": 0, + "user_sailing": { + "pendant": null, + "cardbg": null, + "cardbg_with_focus": null + }, + "is_contractor": false, + "contract_desc": "" + }, + "content": { + "message": "我赶上了我们这个年龄段二次元的末班车,这一年,巨人出了最终季,诚哥的新作玲芽户缔(好像是叫这个)也要在今年秋上映,后悔没有早进入这个圈子,现在只好紧追慢赶,慢慢的补番,我小时候都在干什么啊[大哭]", + "plat": 0, + "device": "", + "members": [], + "emote": { + "[大哭]": { + "id": 5, + "package_id": 1, + "state": 0, + "type": 1, + "attr": 0, + "text": "[大哭]", + "url": "http://i0.hdslb.com/bfs/emote/2caafee2e5db4db72104650d87810cc2c123fc86.png", + "meta": { + "size": 1 + }, + "mtime": 1597738918, + "jump_title": "大哭" + } + }, + "jump_url": {}, + "max_line": 6 + }, + "replies": [], + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "https://www.bilibili.com/blackboard/foldingreply.html" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": { + "time_desc": "6小时前发布" + } + }, + { + "rpid": 104184937184, + "oid": 2, + "type": 1, + "mid": 560450695, + "root": 0, + "parent": 0, + "dialog": 0, + "count": 0, + "rcount": 0, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1646199089, + "rpid_str": "104184937184", + "root_str": "0", + "parent_str": "0", + "like": 0, + "action": 0, + "member": { + "mid": "560450695", + "uname": "還講幾韆", + "sex": "保密", + "sign": "", + "avatar": "http://i1.hdslb.com/bfs/face/e8bcd1f3fed1a8b266e83f7e5952db525b692227.jpg", + "rank": "10000", + "DisplayRank": "0", + "face_nft_new": 0, + "is_senior_member": 0, + "level_info": { + "current_level": 3, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "nameplate": { + "nid": 0, + "name": "", + "image": "", + "image_small": "", + "level": "", + "condition": "" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 0, + "vipDueDate": 0, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "" + }, + "fans_detail": null, + "following": 0, + "is_followed": 0, + "user_sailing": { + "pendant": null, + "cardbg": null, + "cardbg_with_focus": null + }, + "is_contractor": false, + "contract_desc": "" + }, + "content": { + "message": "电视宇宙第二个视频[滑稽][滑稽][滑稽]", + "plat": 0, + "device": "", + "members": [], + "emote": { + "[滑稽]": { + "id": 27, + "package_id": 1, + "state": 0, + "type": 1, + "attr": 0, + "text": "[滑稽]", + "url": "http://i0.hdslb.com/bfs/emote/d15121545a99ac46774f1f4465b895fe2d1411c3.png", + "meta": { + "size": 1 + }, + "mtime": 1645206695, + "jump_title": "滑稽" + } + }, + "jump_url": {}, + "max_line": 6 + }, + "replies": [], + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "https://www.bilibili.com/blackboard/foldingreply.html" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": { + "time_desc": "7小时前发布" + } + }, + { + "rpid": 104179775904, + "oid": 2, + "type": 1, + "mid": 1616523766, + "root": 0, + "parent": 0, + "dialog": 0, + "count": 0, + "rcount": 0, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1646195814, + "rpid_str": "104179775904", + "root_str": "0", + "parent_str": "0", + "like": 1, + "action": 0, + "member": { + "mid": "1616523766", + "uname": "关查者网", + "sex": "保密", + "sign": "", + "avatar": "http://i1.hdslb.com/bfs/face/8bb6aab1f6bcc960f4482aa97b8ca4e61cf81d0d.jpg", + "rank": "10000", + "DisplayRank": "0", + "face_nft_new": 0, + "is_senior_member": 0, + "level_info": { + "current_level": 3, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "nameplate": { + "nid": 0, + "name": "", + "image": "", + "image_small": "", + "level": "", + "condition": "" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1626451200000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "" + }, + "fans_detail": null, + "following": 0, + "is_followed": 0, + "user_sailing": { + "pendant": null, + "cardbg": null, + "cardbg_with_focus": null + }, + "is_contractor": false, + "contract_desc": "" + }, + "content": { + "message": "考古队已到达[doge]", + "plat": 0, + "device": "", + "members": [], + "emote": { + "[doge]": { + "id": 26, + "package_id": 1, + "state": 0, + "type": 1, + "attr": 0, + "text": "[doge]", + "url": "http://i0.hdslb.com/bfs/emote/3087d273a78ccaff4bb1e9972e2ba2a7583c9f11.png", + "meta": { + "size": 1 + }, + "mtime": 1645206695, + "jump_title": "doge" + } + }, + "jump_url": {}, + "max_line": 6 + }, + "replies": [], + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "https://www.bilibili.com/blackboard/foldingreply.html" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": { + "time_desc": "8小时前发布" + } + }, + { + "rpid": 104163851152, + "oid": 2, + "type": 1, + "mid": 27553613, + "root": 0, + "parent": 0, + "dialog": 0, + "count": 0, + "rcount": 0, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1646183484, + "rpid_str": "104163851152", + "root_str": "0", + "parent_str": "0", + "like": 1, + "action": 0, + "member": { + "mid": "27553613", + "uname": "念晚心", + "sex": "男", + "sign": "", + "avatar": "http://i2.hdslb.com/bfs/face/8b8f32c22651904a23eeb83b048041b7c1c8ffd6.jpg", + "rank": "10000", + "DisplayRank": "0", + "face_nft_new": 0, + "is_senior_member": 0, + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "nameplate": { + "nid": 74, + "name": "大会员2018年度勋章", + "image": "http://i2.hdslb.com/bfs/face/421179426c929dfeaed4117461c83f5d07ffb148.png", + "image_small": "http://i0.hdslb.com/bfs/face/682001c2e1c2ae887bdf2a0e18eef61180c48f84.png", + "level": "稀有勋章", + "condition": "2018.6.26-7.8某一天是年度大会员" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1650470400000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png", + "nickname_color": "#FB7299" + }, + "fans_detail": null, + "following": 0, + "is_followed": 0, + "user_sailing": { + "pendant": null, + "cardbg": { + "id": 5476, + "name": "嘉然今天吃什么", + "image": "http://i0.hdslb.com/bfs/garb/item/4442641bd4001214518a81fa8f790ae7469d3cf7.png", + "jump_url": "https://www.bilibili.com/h5/mall/fans/recommend/5461?navhide=1&mid=27553613&from=reply", + "fan": { + "is_fan": 1, + "number": 14705, + "color": "#f76a6b", + "name": "嘉然今天吃什么", + "num_desc": "014705" + }, + "type": "suit" + }, + "cardbg_with_focus": null + }, + "is_contractor": false, + "contract_desc": "" + }, + "content": { + "message": "当时只看优酷和土豆", + "plat": 0, + "device": "", + "members": [], + "jump_url": {}, + "max_line": 6 + }, + "replies": [], + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "https://www.bilibili.com/blackboard/foldingreply.html" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": { + "time_desc": "12小时前发布" + } + }, + { + "rpid": 104163545120, + "oid": 2, + "type": 1, + "mid": 31937033, + "root": 0, + "parent": 0, + "dialog": 0, + "count": 0, + "rcount": 0, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1646183209, + "rpid_str": "104163545120", + "root_str": "0", + "parent_str": "0", + "like": 1, + "action": 0, + "member": { + "mid": "31937033", + "uname": "夜声已尽", + "sex": "男", + "sign": "六八四十二", + "avatar": "http://i2.hdslb.com/bfs/face/e35e81a00596883532ba47c58ca0434618fab3d0.jpg", + "rank": "10000", + "DisplayRank": "0", + "face_nft_new": 0, + "is_senior_member": 0, + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 33465, + "name": "乃琳Queen", + "image": "http://i2.hdslb.com/bfs/garb/item/4ad130e4068f88c54728ac510a172b97e187826f.png", + "expire": 0, + "image_enhance": "http://i2.hdslb.com/bfs/garb/item/4ad130e4068f88c54728ac510a172b97e187826f.png", + "image_enhance_frame": "" + }, + "nameplate": { + "nid": 62, + "name": "有爱大佬", + "image": "http://i0.hdslb.com/bfs/face/a10ee6b613e0d68d2dfdac8bbf71b94824e10408.png", + "image_small": "http://i2.hdslb.com/bfs/face/54f4c31ab9b1f1fa2c29dbbc967f66535699337e.png", + "level": "普通勋章", + "condition": "当前持有粉丝勋章最高等级>=15级" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1671465600000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png", + "nickname_color": "#FB7299" + }, + "fans_detail": null, + "following": 0, + "is_followed": 0, + "user_sailing": { + "pendant": { + "id": 33465, + "name": "乃琳Queen", + "image": "http://i0.hdslb.com/bfs/garb/item/4ad130e4068f88c54728ac510a172b97e187826f.png", + "jump_url": "", + "type": "suit", + "image_enhance": "http://i0.hdslb.com/bfs/garb/item/4ad130e4068f88c54728ac510a172b97e187826f.png", + "image_enhance_frame": "" + }, + "cardbg": { + "id": 33494, + "name": "乃琳Queen", + "image": "http://i0.hdslb.com/bfs/garb/item/34f8c1ef43332883f62e17fed44c1a70930e4811.png", + "jump_url": "https://www.bilibili.com/h5/mall/fans/recommend/33498?navhide=1&mid=31937033&from=reply", + "fan": { + "is_fan": 1, + "number": 50766, + "color": "#576690", + "name": "乃琳Queen", + "num_desc": "050766" + }, + "type": "suit" + }, + "cardbg_with_focus": null + }, + "is_contractor": false, + "contract_desc": "" + }, + "content": { + "message": "考古", + "plat": 0, + "device": "", + "members": [], + "jump_url": {}, + "max_line": 6 + }, + "replies": [], + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "https://www.bilibili.com/blackboard/foldingreply.html" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": { + "time_desc": "12小时前发布" + } + } + ], + "hots": [], + "upper": { + "mid": 2, + "top": null, + "vote": null + }, + "top": null, + "notice": null, + "vote": 0, + "blacklist": 0, + "assist": 0, + "mode": 3, + "support_mode": [ + 1, + 2, + 3 + ], + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "https://www.bilibili.com/blackboard/foldingreply.html" + }, + "lottery_card": null, + "show_bvid": false, + "control": { + "input_disable": false, + "root_input_text": "发一条友善的评论", + "child_input_text": "", + "giveup_input_text": "不发没关系,请继续友善哦~", + "bg_text": "看看下面~来发评论吧", + "web_selection": false, + "answer_guide_text": "需要升级成为lv2会员后才可以评论,先去答题转正吧!", + "answer_guide_icon_url": "http://i0.hdslb.com/bfs/emote/96940d16602cacbbac796245b7bb99fa9b5c970c.png", + "answer_guide_ios_url": "https://www.bilibili.com/h5/newbie/entry?navhide=1&re_src=12", + "answer_guide_android_url": "https://www.bilibili.com/h5/newbie/entry?navhide=1&re_src=6", + "show_type": 1, + "show_text": "", + "disable_jump_emote": false + } + } +} +``` + +</details> + +## 获取评论区明细_懒加载 + +> https://api.bilibili.com/x/v2/reply/wbi/main + +> ~~https://api.bilibili.com/x/v2/reply/main~~ + +*请求方式:GET* + +鉴权方式:[Wbi 签名](../misc/sign/wbi.md) + +注: Wbi 签名错误时返回 -403 而非 -352 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | ------------------------------------------------------------ | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| type | num | 评论区类型代码 | 必要 | [类型代码见表](readme.md#评论区类型代码) | +| oid | num | 目标评论区 id | 必要 | | +| mode | num | 排序方式 | 非必要 | 默认为 3<br />0 3:仅按热度<br />1:按热度+按时间<br />2:仅按时间 | +| next | num | 翻页 | 非必要 | 不推荐, 已弃用, 优先级比 `pagination_str` 高 | +| pagination_str | obj | 分页信息 | 非必要 | 见下 | +| plat | num | 平台类型 | 非必要 | 如 `1` | +| seek_rpid | str | 空 | 非必要 | 当获取第一页评论时存在 | +| web_location | str | 1315875 | 非必要 | | + +`pagination_str`: + +| 参数名 | 类型 | 内容 | 备注 | +| ----- | - | ------|------| +| offset | str | 一个套着字符串皮的 JSON Object | 上次响应 `data.cursor.pagination_reply.next_offset` 的值, 获取第一页时为空, 其余见下参考 | + +`pagination_str` 中的 `offset`: + +| 参数名 | 类型 | 内容 | 备注 | +| ----- | ---- | -- | - | +| type | num | 类型 | 当 URL 参数 mode 为 2 时, 此项为 3<br />当 URL 参数 mode 为 3 时, 此项为 1 | +| direction | num | 方向 | 1: 正序(默认)<br />2: 倒序 | +| data | obj | 分页数据 | 当 type 为 1 时存在 | +| Data | obj | 分页数据 | 当 type 为 3 时存在 | +<!--not typo here--> + +`offset` 中的 `data` (type=1): + +| 参数名 | 类型 | 内容 | 备注 | +| - | - | - | - | +| pn | num | 页码 (上次响应 `data.cursor.next` 的值) | | + +`offset` 中的 `Data` (type=3): + +| 参数名 | 类型 | 内容 | 备注 | +| - | - | - | - | +| cursor | num | 上次响应 `data.cursor.next` 的值 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----------------------------- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-404:无此项<br />12002:评论区已关闭<br />12009:评论主体的type不合法 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 正确时:obj<br />错误时:null | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | -------------------------------- | -------- | ---------------- | +| cursor | obj | 游标信息 | | +| hots | 禁用时:null<br />正常时:array | 热评列表 | | +| notice | 无效时:null<br />有效时:obj | 评论区公告信息 | | +| replies | 禁用时:null<br />正常时:array | 评论列表 | | +| top | obj | 置顶信息 | | +| top_replies | obj | 置顶评论 | [对象定义见表](readme.md#评论条目对象) | +| lottery_card | null | 抽奖评论 | | +| folder | obj | 评论折叠信息 | | +| up_selection | obj | (?) | | +| cm | obj | 广告 | | +| cm_info | obj | 广告控制 | | +| effects | obj | (?) | | +| assist | num | (?) | | +| blacklist | num | (?) | | +| vote | num | (?) | | +| lottery | num | (?) | | +| config | obj | 评论区显示控制 | | +| upper | obj | UP主信息 | | +| show_bvid | bool | 显示 bvid? | | +| control | obj | 评论区输入属性 | | +| note | num | 1 | | +| esports_grade_card | null | | | +| callbacks | null | | | +| context_feature | str | | | + +`data`中的`cursor`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ----- | -------------- | ----------------------- | +| all_count | num | 全部评论条数 | | +| is_begin | bool | 是否为第一页 | false:否<br />true:是 | +| prev | num | 上页页码 | | +| next | num | 下页页码 | | +| is_end | bool | 是否为最后页 | false:否<br />true:是 | +| mode | num | 排序方式 | | +| support_mode | array | 支持的排序方式 | | +| name | str | 评论区类型名 | | +| pagination_reply | str | 用于下一次请求的偏移信息 | | +| session_id | str | 空 | | + +`cursor`中的`pagination_reply`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -- | - | +| next_offset | str | 用于下一次请求的偏移信息 | | +| prev_offset | str | 用于本次请求的偏移信息 | | + +`data`中的`config`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ------------------------- | ---- | +| showadmin | num | 是否显示管理置顶 | | +| showentry | num | ? | | +| showfloor | num | 是否显示楼层号 | | +| showtopic | num | 是否显示话题 | | +| show_up_flag | bool | 是否显示“UP 觉得很赞”标志 | | +| read_only | bool | 是否只读评论区 | | +| show_del_log | bool | 是否显示删除记录 | | + +`data`中的`hots`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | -------------------------------------- | +| 0 | obj | 热评条目 1 | [对象定义见表](readme.md#评论条目对象) | +| n | obj | 热评条目 (n+1) | 按照热评热度排列 | +| …… | obj | …… | …… | + +`data`中的`replies`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | -------------------------------------- | +| 0 | obj | 评论条目 1 | [对象定义见表](readme.md#评论条目对象) | +| n | obj | 评论条目 (n+1) | 按照指定的顺序排列 | +| …… | obj | …… | …… | + +`data`中的`top`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ----------------------------- | -------------- | -------------------------------------- | +| admin | 有效时:obj<br />无效时:null | 管理员置顶条目 | [对象定义见表](readme.md#评论条目对象) | +| upper | 有效时:obj<br />无效时:null | UP 主置顶条目 | [对象定义见表](readme.md#评论条目对象) | +| vote | 有效时:obj<br />无效时:null | 投票置顶条目 | [对象定义见表](readme.md#评论条目对象) | + +`data`中的`upper`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---- | +| mid | num | UP 主 mid | | + +`data`中的`notice`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ---------------- | ---- | +| content | str | 公告正文 | | +| id | num | 公告 id | | +| link | str | 公告页面链接 url | | +| title | str | 公告标题 | | + +`data`中的`folder`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ---------------------- | ---- | +| has_folded | bool | 评论区是否存在折叠评论 | | +| is_folded | bool | 是否折叠? | | +| rule | str | 相关规则页面 url | | + +`data`中的`control`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------------ | ---- | ------------------ | ----------------------------------- | +| input_disable | bool | (?) | | +| root_input_text | str | 评论框文字 | | +| child_input_text | str | 评论框文字 | | +| bg_text | str | 空评论区文字 | | +| web_selection | bool | 评论是否筛选后可见 | false:无需筛选<br />true:需要筛选 | +| answer_guide_text | str | 答题页面链接文字 | | +| answer_guide_icon_url | str | 答题页面图标 url | | +| answer_guide_ios_url | str | 答题页面 ios url | | +| answer_guide_android_url | str | 答题页面安卓 url | | + +**示例:** + +获取视频`av2`的评论区明细, 按时间排序, 第一页 + +```shell +curl -G 'https://api.bilibili.com/x/v2/reply/wbi/main' \ +--data-urlencode 'oid=2' \ +--data-urlencode 'type=1' \ +--data-urlencode 'mode=2' \ +--data-urlencode 'w_rid=xxx' \ +--data-urlencode 'wts=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```jsonc +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "cursor": { + "is_begin": true, + "prev": 71880, + "next": 71859, + "is_end": false, + "mode": 2, + "mode_text": "", + "all_count": 86234, + "support_mode": [ + 2, + 3 + ], + "name": "最新评论", + "pagination_reply": { + "next_offset": "{\"type\":3,\"direction\":1,\"Data\":{\"cursor\":71859}}" + }, + "session_id": "" + }, + "replies": [ + { + "rpid": 237740291920, + "oid": 2, + "type": 1, + "mid": 1201423076, + "root": 0, + "parent": 0, + "dialog": 0, + "count": 0, + "rcount": 0, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1723639342, + "mid_str": "1201423076", + "oid_str": "2", + "rpid_str": "237740291920", + "root_str": "0", + "parent_str": "0", + "dialog_str": "0", + "like": 0, + "action": 0, + "member": { + "mid": "1201423076", + "uname": "天堂いyoulin", + "sex": "保密", + "sign": "", + "avatar": "https://i2.hdslb.com/bfs/face/d0925e782198cadc0c400a3ed4fbdf94142357fb.jpg", + "rank": "10000", + "face_nft_new": 0, + "is_senior_member": 0, + "senior": {}, + "level_info": { + "current_level": 4, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0 + }, + "nameplate": { + "nid": 0, + "name": "", + "image": "", + "image_small": "", + "level": "", + "condition": "" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 0, + "vipDueDate": 0, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "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/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png" + }, + "avatar_subscript": 0, + "nickname_color": "" + }, + "fans_detail": null, + "user_sailing": { + "pendant": null, + "cardbg": null, + "cardbg_with_focus": null + }, + "user_sailing_v2": {}, + "is_contractor": false, + "contract_desc": "", + "nft_interaction": null, + "avatar_item": { + "container_size": { + "width": 1.8, + "height": 1.8 + }, + "fallback_layers": { + "layers": [ + { + "visible": true, + "general_spec": { + "pos_spec": { + "coordinate_pos": 2, + "axis_x": 0.9, + "axis_y": 0.9 + }, + "size_spec": { + "width": 1, + "height": 1 + }, + "render_spec": { + "opacity": 1 + } + }, + "layer_config": { + "tags": { + "AVATAR_LAYER": {} + }, + "is_critical": true, + "layer_mask": { + "general_spec": { + "pos_spec": { + "coordinate_pos": 2, + "axis_x": 0.9, + "axis_y": 0.9 + }, + "size_spec": { + "width": 1, + "height": 1 + }, + "render_spec": { + "opacity": 1 + } + }, + "mask_src": { + "src_type": 3, + "draw": { + "draw_type": 1, + "fill_mode": 1, + "color_config": { + "day": { + "argb": "#FF000000" + } + } + } + } + } + }, + "resource": { + "res_type": 3, + "res_image": { + "image_src": { + "src_type": 1, + "placeholder": 6, + "remote": { + "url": "https://i2.hdslb.com/bfs/face/d0925e782198cadc0c400a3ed4fbdf94142357fb.jpg", + "bfs_style": "widget-layer-avatar" + } + } + } + } + } + ], + "is_critical_group": true + }, + "mid": "1201423076" + } + }, + "content": { + "message": "好多20年和18年的[辣眼睛]", + "members": [], + "emote": { + "[辣眼睛]": { + "id": 2374, + "package_id": 1, + "state": 0, + "type": 1, + "attr": 0, + "text": "[辣眼睛]", + "url": "https://i0.hdslb.com/bfs/emote/35d62c496d1e4ea9e091243fa812866f5fecc101.png", + "meta": { + "size": 1, + "suggest": [ + "" + ] + }, + "mtime": 1668688325, + "jump_title": "辣眼睛" + } + }, + "jump_url": {}, + "max_line": 6 + }, + "replies": [], + "assist": 0, + "up_action": { + "like": false, + "reply": false + }, + "invisible": false, + "reply_control": { + "max_line": 6, + "time_desc": "21分钟前发布", + "location": "IP属地:河北" + }, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "" + }, + "dynamic_id_str": "0", + "note_cvid_str": "0", + "track_info": "" + }, + // ... + { + "rpid": 237689432448, + "oid": 2, + "type": 1, + "mid": 1647250883, + "root": 0, + "parent": 0, + "dialog": 0, + "count": 0, + "rcount": 0, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1723624563, + "mid_str": "1647250883", + "oid_str": "2", + "rpid_str": "237689432448", + "root_str": "0", + "parent_str": "0", + "dialog_str": "0", + "like": 1, + "action": 0, + "member": { + "mid": "1647250883", + "uname": "小烟同学424", + "sex": "保密", + "sign": "墓前玩使命,墓前暑假", + "avatar": "https://i2.hdslb.com/bfs/face/930661ca1bcacf8005efcca499b7380dcd4c2716.jpg", + "rank": "10000", + "face_nft_new": 0, + "is_senior_member": 0, + "senior": {}, + "level_info": { + "current_level": 5, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0 + }, + "nameplate": { + "nid": 0, + "name": "", + "image": "", + "image_small": "", + "level": "", + "condition": "" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 0, + "vipDueDate": 0, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "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/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png" + }, + "avatar_subscript": 0, + "nickname_color": "" + }, + "fans_detail": null, + "user_sailing": { + "pendant": null, + "cardbg": null, + "cardbg_with_focus": null + }, + "user_sailing_v2": {}, + "is_contractor": false, + "contract_desc": "", + "nft_interaction": null, + "avatar_item": { + "container_size": { + "width": 1.8, + "height": 1.8 + }, + "fallback_layers": { + "layers": [ + { + "visible": true, + "general_spec": { + "pos_spec": { + "coordinate_pos": 2, + "axis_x": 0.9, + "axis_y": 0.9 + }, + "size_spec": { + "width": 1, + "height": 1 + }, + "render_spec": { + "opacity": 1 + } + }, + "layer_config": { + "tags": { + "AVATAR_LAYER": {} + }, + "is_critical": true, + "layer_mask": { + "general_spec": { + "pos_spec": { + "coordinate_pos": 2, + "axis_x": 0.9, + "axis_y": 0.9 + }, + "size_spec": { + "width": 1, + "height": 1 + }, + "render_spec": { + "opacity": 1 + } + }, + "mask_src": { + "src_type": 3, + "draw": { + "draw_type": 1, + "fill_mode": 1, + "color_config": { + "day": { + "argb": "#FF000000" + } + } + } + } + } + }, + "resource": { + "res_type": 3, + "res_image": { + "image_src": { + "src_type": 1, + "placeholder": 6, + "remote": { + "url": "https://i2.hdslb.com/bfs/face/930661ca1bcacf8005efcca499b7380dcd4c2716.jpg", + "bfs_style": "widget-layer-avatar" + } + } + } + } + } + ], + "is_critical_group": true + }, + "mid": "1647250883" + } + }, + "content": { + "message": "还。。。有人吗?", + "members": [], + "jump_url": {}, + "max_line": 6 + }, + "replies": [], + "assist": 0, + "up_action": { + "like": false, + "reply": false + }, + "invisible": false, + "reply_control": { + "max_line": 6, + "time_desc": "4小时前发布", + "location": "IP属地:陕西" + }, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "" + }, + "dynamic_id_str": "0", + "note_cvid_str": "0", + "track_info": "" + } + ], + "top": { + "admin": null, + "upper": null, + "vote": null + }, + "top_replies": [], + "up_selection": { + "pending_count": 0, + "ignore_count": 0 + }, + "effects": { + "preloading": "" + }, + "assist": 0, + "blacklist": 0, + "vote": 0, + "config": { + "showtopic": 1, + "show_up_flag": true, + "read_only": false + }, + "upper": { + "mid": 2 + }, + "control": { + "input_disable": false, + "root_input_text": "你渴望拥有力量吗?评论让力量更强大", + "child_input_text": "你渴望拥有力量吗?评论让力量更强大", + "giveup_input_text": "不发没关系,请继续友善哦~", + "screenshot_icon_state": 1, + "upload_picture_icon_state": 1, + "answer_guide_text": "需要升级成为lv2会员后才可以评论,先去答题转正吧!", + "answer_guide_icon_url": "http://i0.hdslb.com/bfs/emote/96940d16602cacbbac796245b7bb99fa9b5c970c.png", + "answer_guide_ios_url": "https://www.bilibili.com/h5/newbie/entry?navhide=1&re_src=12", + "answer_guide_android_url": "https://www.bilibili.com/h5/newbie/entry?navhide=1&re_src=6", + "bg_text": "", + "empty_page": null, + "show_type": 1, + "show_text": "", + "web_selection": false, + "disable_jump_emote": false, + "enable_charged": false, + "enable_cm_biz_helper": false, + "preload_resources": null + }, + "note": 1, + "esports_grade_card": null, + "callbacks": null, + "context_feature": "" + } +} +``` + +</details> + +## 获取指定评论的回复 + +> https://api.bilibili.com/x/v2/reply/reply + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +按照回复顺序排序 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | ---------------------------------------- | +| access_key | str | APP登录 Token | APP 方式必要 | | +| type | num | 评论区类型代码 | 必要 | [类型代码见表](readme.md#评论区类型代码) | +| oid | num | 目标评论区 id | 必要 | | +| root | num | 根回复 rpid | 必要 | | +| ps | num | 每页项数 | 非必要 | 默认为20<br />定义域:1-49 <br /> 但 data_replies 的最大内容数为20,因此设置为49其实也只会有20条回复被返回 | +| pn | num | 页码 | 非必要 | 默认为1 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----------------------------- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-404:无此项<br />12002:评论区已关闭<br />12009:评论主体的type不合法 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 正确时:obj<br />错误时:null | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | -------------- | -------------------------------------- | +| config | obj | 评论区显示控制 | | +| control | obj | 评论区输入属性 | | +| page | obj | 页面信息 | | +| replies | array | 评论对话树列表 | 最大内容数为20 | +| root | obj | 根评论信息 | [对象定义见表](readme.md#评论条目对象) | +| show_bvid | bool | 显示 bvid? | | +| show_text | str | (?) | | +| show_type | num | (?) | | +| upper | obj | UP主 mid | | + +`data`中的`config`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ------------------------ | ---- | +| showadmin | num | 是否显示管理置顶 | | +| showentry | num | ? | | +| showfloor | num | 是否显示楼层号 | | +| showtopic | num | 是否显示话题 | | +| show_up_flag | bool | 是否显示“UP觉得很赞”标志 | | +| read_only | bool | 是否只读评论区 | | +| show_del_log | bool | 是否显示删除记录 | | + +`data`中的`control`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------------ | ---- | ------------------ | ----------------------------------- | +| input_disable | bool | (?) | | +| root_input_text | str | 评论框文字 | | +| child_input_text | str | 评论框文字 | | +| bg_text | str | 空评论区文字 | | +| web_selection | bool | 评论是否筛选后可见 | false:无需筛选<br />true:需要筛选 | +| answer_guide_text | str | 答题页面链接文字 | | +| answer_guide_icon_url | str | 答题页面图标 url | | +| answer_guide_ios_url | str | 答题页面 ios url | | +| answer_guide_android_url | str | 答题页面安卓 url | | + +`data`中的`page`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ---------- | ---- | +| count | num | 二级评论数 | | +| num | num | 当前页码 | | +| size | num | 每页项数 | | + +`data`中的`replies`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------------ | -------------------------------------- | +| 0 | obj | 对话评论条目 1 | [对象定义见表](readme.md#评论条目对象) | +| n | obj | 对话评论条目 (n+1) | 按照回复顺序排列 | +| …… | obj | …… | …… | + +`data`中的`upper`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---- | +| mid | num | UP 主 mid | | + +**示例:** + +获取视频`av201022189`下评论`rpid=3030790837`的回复,每页5项,获取第1页 + +```shell +curl -G 'https://api.bilibili.com/x/v2/reply/reply' \ +--data-urlencode 'type=1' \ +--data-urlencode 'oid=201022189' \ +--data-urlencode 'root=3030790837' \ +--data-urlencode 'ps=5' \ +--data-urlencode 'pn=1' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "config": { + "showadmin": 0, + "showentry": 0, + "showfloor": 0, + "showtopic": 0, + "show_up_flag": false, + "read_only": false, + "show_del_log": false + }, + "control": { + "input_disable": false, + "root_input_text": "发一条友善的评论", + "child_input_text": "", + "giveup_input_text": "不发没关系,请继续友善哦~", + "bg_text": "看看下面~来发评论吧", + "web_selection": false, + "answer_guide_text": "需要升级成为lv2会员后才可以评论,先去答题转正吧!", + "answer_guide_icon_url": "http://i0.hdslb.com/bfs/emote/96940d16602cacbbac796245b7bb99fa9b5c970c.png", + "answer_guide_ios_url": "https://www.bilibili.com/h5/newbie/entry?navhide=1&re_src=12", + "answer_guide_android_url": "https://www.bilibili.com/h5/newbie/entry?navhide=1&re_src=6", + "show_type": 1, + "show_text": "", + "disable_jump_emote": false + }, + "page": { + "count": 230, + "num": 1, + "size": 5 + }, + "replies": [ + { + "rpid": 3030802207, + "oid": 201022189, + "type": 1, + "mid": 172604528, + "root": 3030790837, + "parent": 3030790837, + "dialog": 3030802207, + "count": 0, + "rcount": 0, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1592018067, + "rpid_str": "3030802207", + "root_str": "3030790837", + "parent_str": "3030790837", + "like": 41, + "action": 0, + "member": { + "mid": "172604528", + "uname": "超高校级的认真", + "sex": "男", + "sign": "just do it for yourself", + "avatar": "http://i2.hdslb.com/bfs/face/d0d957faa6162388467cb0750a9d33cf616e73e9.jpg", + "rank": "10000", + "DisplayRank": "0", + "face_nft_new": 0, + "is_senior_member": 0, + "level_info": { + "current_level": 5, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "nameplate": { + "nid": 0, + "name": "", + "image": "", + "image_small": "", + "level": "", + "condition": "" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1626364800000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "" + }, + "fans_detail": null, + "following": 0, + "is_followed": 0, + "user_sailing": { + "pendant": null, + "cardbg": null, + "cardbg_with_focus": null + }, + "is_contractor": false, + "contract_desc": "" + }, + "content": { + "message": "怎么上p站呀,翻吗", + "plat": 0, + "device": "", + "members": [], + "jump_url": {}, + "max_line": 999 + }, + "replies": null, + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": { + "time_desc": "627天前发布" + } + }, + { + "rpid": 3030810089, + "oid": 201022189, + "type": 1, + "mid": 342581997, + "root": 3030790837, + "parent": 3030802207, + "dialog": 3030802207, + "count": 0, + "rcount": 0, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1592018123, + "rpid_str": "3030810089", + "root_str": "3030790837", + "parent_str": "3030802207", + "like": 7, + "action": 0, + "member": { + "mid": "342581997", + "uname": "VAN样斯基", + "sex": "保密", + "sign": "", + "avatar": "http://i0.hdslb.com/bfs/face/bc9c6d37b5a4c8b3b0a3cd483fd66e63b1ae0cec.jpg", + "rank": "10000", + "DisplayRank": "0", + "face_nft_new": 0, + "is_senior_member": 0, + "level_info": { + "current_level": 5, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "nameplate": { + "nid": 0, + "name": "", + "image": "", + "image_small": "", + "level": "", + "condition": "" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1626364800000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "" + }, + "fans_detail": null, + "following": 0, + "is_followed": 0, + "user_sailing": { + "pendant": null, + "cardbg": null, + "cardbg_with_focus": null + }, + "is_contractor": false, + "contract_desc": "" + }, + "content": { + "message": "回复 @中等校级的努力 :是啊", + "plat": 0, + "device": "", + "members": [], + "jump_url": {}, + "max_line": 999 + }, + "replies": null, + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": { + "time_desc": "627天前发布" + } + }, + { + "rpid": 3030843245, + "oid": 201022189, + "type": 1, + "mid": 92586428, + "root": 3030790837, + "parent": 3030790837, + "dialog": 3030843245, + "count": 0, + "rcount": 0, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1592018688, + "rpid_str": "3030843245", + "root_str": "3030790837", + "parent_str": "3030790837", + "like": 588, + "action": 0, + "member": { + "mid": "92586428", + "uname": "浪潮工作室", + "sex": "保密", + "sign": "洞见时代的浪潮。", + "avatar": "http://i2.hdslb.com/bfs/face/67f183f13f8fe3afb374916d32f9810df8ef042a.jpg", + "rank": "10000", + "DisplayRank": "0", + "face_nft_new": 0, + "is_senior_member": 0, + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "nameplate": { + "nid": 0, + "name": "", + "image": "", + "image_small": "", + "level": "", + "condition": "" + }, + "official_verify": { + "type": 0, + "desc": "专栏优质UP主" + }, + "vip": { + "vipType": 0, + "vipDueDate": 0, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "" + }, + "fans_detail": null, + "following": 0, + "is_followed": 0, + "user_sailing": { + "pendant": null, + "cardbg": null, + "cardbg_with_focus": null + }, + "is_contractor": false, + "contract_desc": "" + }, + "content": { + "message": "不会吧不会吧,不会真的有人上P站不是为了学习吧", + "plat": 0, + "device": "", + "members": [], + "jump_url": {}, + "max_line": 999 + }, + "replies": null, + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": { + "time_desc": "627天前发布" + } + }, + { + "rpid": 3030881609, + "oid": 201022189, + "type": 1, + "mid": 393121222, + "root": 3030790837, + "parent": 3030802207, + "dialog": 3030802207, + "count": 0, + "rcount": 0, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1592019208, + "rpid_str": "3030881609", + "root_str": "3030790837", + "parent_str": "3030802207", + "like": 110, + "action": 0, + "member": { + "mid": "393121222", + "uname": "鱼氏博物馆", + "sex": "保密", + "sign": "", + "avatar": "http://i1.hdslb.com/bfs/face/f61a8ea36828884d760d855293136a838fa9e848.jpg", + "rank": "10000", + "DisplayRank": "0", + "face_nft_new": 0, + "is_senior_member": 0, + "level_info": { + "current_level": 5, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "nameplate": { + "nid": 0, + "name": "", + "image": "", + "image_small": "", + "level": "", + "condition": "" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1602691200000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "" + }, + "fans_detail": null, + "following": 0, + "is_followed": 0, + "user_sailing": { + "pendant": null, + "cardbg": null, + "cardbg_with_focus": null + }, + "is_contractor": false, + "contract_desc": "" + }, + "content": { + "message": "回复 @中等校级的努力 :p是什么,当然是plane啦,plane站其实就是✈场[doge]所以去p站就是去✈场啦", + "plat": 0, + "device": "", + "members": [], + "emote": { + "[doge]": { + "id": 26, + "package_id": 1, + "state": 0, + "type": 1, + "attr": 0, + "text": "[doge]", + "url": "http://i0.hdslb.com/bfs/emote/3087d273a78ccaff4bb1e9972e2ba2a7583c9f11.png", + "meta": { + "size": 1 + }, + "mtime": 1645206695, + "jump_title": "doge" + } + }, + "jump_url": {}, + "max_line": 999 + }, + "replies": null, + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": { + "time_desc": "627天前发布" + } + }, + { + "rpid": 3030978856, + "oid": 201022189, + "type": 1, + "mid": 11814633, + "root": 3030790837, + "parent": 3030790837, + "dialog": 3030978856, + "count": 0, + "rcount": 0, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1592020635, + "rpid_str": "3030978856", + "root_str": "3030790837", + "parent_str": "3030790837", + "like": 60, + "action": 0, + "member": { + "mid": "11814633", + "uname": "我到四川省来", + "sex": "保密", + "sign": "保持内心的平静", + "avatar": "http://i0.hdslb.com/bfs/face/1c7cad967633c718ddef302f4aa39efaed53a2e4.jpg", + "rank": "10000", + "DisplayRank": "0", + "face_nft_new": 0, + "is_senior_member": 0, + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 1885, + "name": "公主连结凯露", + "image": "http://i0.hdslb.com/bfs/garb/item/ecf1b11044845abc92e576dfdf93ad4f5e5a0958.png", + "expire": 0, + "image_enhance": "http://i0.hdslb.com/bfs/garb/item/ecf1b11044845abc92e576dfdf93ad4f5e5a0958.png", + "image_enhance_frame": "" + }, + "nameplate": { + "nid": 3, + "name": "白银殿堂", + "image": "http://i0.hdslb.com/bfs/face/f6a31275029365ae5dc710006585ddcf1139bde1.png", + "image_small": "http://i0.hdslb.com/bfs/face/b09cdb4c119c467cf2d15db5263b4f539fa6e30b.png", + "level": "高级勋章", + "condition": "单个自制视频总播放数>=10万" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1715270400000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png", + "nickname_color": "#FB7299" + }, + "fans_detail": null, + "following": 0, + "is_followed": 0, + "user_sailing": { + "pendant": { + "id": 1885, + "name": "公主连结凯露", + "image": "http://i0.hdslb.com/bfs/garb/item/ecf1b11044845abc92e576dfdf93ad4f5e5a0958.png", + "jump_url": "", + "type": "vip", + "image_enhance": "http://i0.hdslb.com/bfs/garb/item/ecf1b11044845abc92e576dfdf93ad4f5e5a0958.png", + "image_enhance_frame": "" + }, + "cardbg": null, + "cardbg_with_focus": null + }, + "is_contractor": false, + "contract_desc": "" + }, + "content": { + "message": "看有机化学考研视频", + "plat": 0, + "device": "", + "members": [], + "jump_url": {}, + "max_line": 999 + }, + "replies": null, + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": { + "time_desc": "627天前发布" + } + } + ], + "root": { + "rpid": 3030790837, + "oid": 201022189, + "type": 1, + "mid": 342581997, + "root": 0, + "parent": 0, + "dialog": 0, + "count": 268, + "rcount": 230, + "state": 0, + "fansgrade": 0, + "attr": 768, + "ctime": 1592017909, + "rpid_str": "3030790837", + "root_str": "0", + "parent_str": "0", + "like": 8018, + "action": 0, + "member": { + "mid": "342581997", + "uname": "VAN样斯基", + "sex": "保密", + "sign": "", + "avatar": "http://i0.hdslb.com/bfs/face/bc9c6d37b5a4c8b3b0a3cd483fd66e63b1ae0cec.jpg", + "rank": "10000", + "DisplayRank": "0", + "face_nft_new": 0, + "is_senior_member": 0, + "level_info": { + "current_level": 5, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "nameplate": { + "nid": 0, + "name": "", + "image": "", + "image_small": "", + "level": "", + "condition": "" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1626364800000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "" + }, + "fans_detail": null, + "following": 0, + "is_followed": 0, + "user_sailing": { + "pendant": null, + "cardbg": null, + "cardbg_with_focus": null + }, + "is_contractor": false, + "contract_desc": "" + }, + "content": { + "message": "去P站当然只是为了学习啊[doge]", + "plat": 0, + "device": "", + "members": [], + "emote": { + "[doge]": { + "id": 26, + "package_id": 1, + "state": 0, + "type": 1, + "attr": 0, + "text": "[doge]", + "url": "http://i0.hdslb.com/bfs/emote/3087d273a78ccaff4bb1e9972e2ba2a7583c9f11.png", + "meta": { + "size": 1 + }, + "mtime": 1645206695, + "jump_title": "doge" + } + }, + "jump_url": {}, + "max_line": 999 + }, + "replies": null, + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "https://www.bilibili.com/blackboard/foldingreply.html" + }, + "up_action": { + "like": true, + "reply": true + }, + "show_follow": false, + "invisible": false, + "card_label": [ + { + "rpid": 3030790837, + "text_content": "UP主觉得很赞", + "text_color_day": "#757575", + "text_color_night": "#939393", + "label_color_day": "#F4F4F4", + "label_color_night": "#1E1E1E", + "image": "", + "type": 0, + "background": "", + "background_width": 0, + "background_height": 0, + "jump_url": "" + } + ], + "reply_control": { + "up_reply": true, + "sub_reply_entry_text": "共230条回复", + "sub_reply_title_text": "相关回复共230条", + "time_desc": "627天前发布" + } + }, + "show_bvid": true, + "show_text": "", + "show_type": 2, + "upper": { + "mid": 92586428 + } + } +} +``` + +</details> + +## 获取指定评论对话树 + +> https://api.bilibili.com/x/v2/reply/dialog/cursor + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +按照对话链排列 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | ---------------------------------------- | +| access_key | str | APP登录 Token | APP 方式必要 | | +| type | num | 评论区类型代码 | 必要 | [类型代码见表](readme.md#评论区类型代码) | +| oid | num | 目标评论区 id | 必要 | | +| root | num | 根回复 rpid | 必要 | | +| dialog | num | 对话树根 rpid | 必要 | | +| size | num | 每页最大项数 | 必要 | | +| min_floor | num | (?) | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----------------------------- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-404:无此项<br />12002:评论区已关闭<br />12009:评论主体的type不合法 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 正确时:obj<br />错误时:null | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | -------------- | ---- | +| cursor | obj | 页楼层信息 | | +| dialog | obj | 对话楼层信息 | | +| replies | array | 评论对话树列表 | | +| assist | num | (?) | | +| blacklist | num | (?) | | +| vote | num | (?) | | +| lottery | num | (?) | | +| config | obj | 评论区显示控制 | | +| upper | obj | UP主 mid | | +| show_bvid | bool | 显示 bvid? | | +| control | obj | 评论区输入属性 | | +| note | num | (?) | | + +`data`中的`cursor`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ---------------- | ---- | +| min_floor | num | 本页最低对话楼层 | | +| max_floor | num | 本页最高对话楼层 | | +| size | num | 本页项数 | | + +`data`中的`dialog`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | -------------------- | ---- | +| min_floor | num | 二级评论最低对话楼层 | | +| max_floor | num | 二级评论最高对话楼层 | | + +`data`中的`replies`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------------ | -------------------------------------- | +| 0 | obj | 对话评论条目 1 | [对象定义见表](readme.md#评论条目对象) | +| n | obj | 对话评论条目 (n+1) | 按照对话链排列 | +| …… | obj | …… | …… | + +`data`中的`config`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ------------------------- | ---- | +| showadmin | num | 是否显示管理置顶 | | +| showentry | num | ? | | +| showfloor | num | 是否显示楼层号 | | +| showtopic | num | 是否显示话题 | | +| show_up_flag | bool | 是否显示“UP 觉得很赞”标志 | | +| read_only | bool | 是否只读评论区 | | +| show_del_log | bool | 是否显示删除记录 | | + +`data`中的`upper`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---- | +| mid | num | UP 主 mid | | + +`data`中的`control`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------------ | ---- | ------------------ | ----------------------------------- | +| input_disable | bool | (?) | | +| root_input_text | str | 评论框文字 | | +| child_input_text | str | 评论框文字 | | +| bg_text | str | 空评论区文字 | | +| web_selection | bool | 评论是否筛选后可见 | false:无需筛选<br />true:需要筛选 | +| answer_guide_text | str | 答题页面链接文字 | | +| answer_guide_icon_url | str | 答题页面图标 url | | +| answer_guide_ios_url | str | 答题页面 ios url | | +| answer_guide_android_url | str | 答题页面安卓 url | | + +**示例:** + +获取视频`av201022189`下评论`rpid=3030790837`的对话`rpid=3030978856`,每页最大5项 + +```shell +curl -G 'https://api.bilibili.com/x/v2/reply/dialog/cursor' \ +--data-urlencode 'type=1' \ +--data-urlencode 'oid=201022189' \ +--data-urlencode 'root=3030790837' \ +--data-urlencode 'dialog=3030978856' \ +--data-urlencode 'size=5' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "cursor": { + "min_floor": 5, + "max_floor": 99, + "size": 5 + }, + "dialog": { + "min_floor": 0, + "max_floor": 243 + }, + "replies": [ + { + "rpid": 3030978856, + "oid": 201022189, + "type": 1, + "mid": 11814633, + "root": 3030790837, + "parent": 3030790837, + "dialog": 3030978856, + "count": 0, + "rcount": 0, + "floor": 5, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1592020635, + "rpid_str": "3030978856", + "root_str": "3030790837", + "parent_str": "3030790837", + "like": 60, + "action": 0, + "member": { + "mid": "11814633", + "uname": "我到四川省来", + "sex": "保密", + "sign": "保持内心的平静", + "avatar": "http://i0.hdslb.com/bfs/face/1c7cad967633c718ddef302f4aa39efaed53a2e4.jpg", + "rank": "10000", + "DisplayRank": "0", + "face_nft_new": 0, + "is_senior_member": 0, + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 1885, + "name": "公主连结凯露", + "image": "http://i0.hdslb.com/bfs/garb/item/ecf1b11044845abc92e576dfdf93ad4f5e5a0958.png", + "expire": 0, + "image_enhance": "http://i0.hdslb.com/bfs/garb/item/ecf1b11044845abc92e576dfdf93ad4f5e5a0958.png", + "image_enhance_frame": "" + }, + "nameplate": { + "nid": 3, + "name": "白银殿堂", + "image": "http://i2.hdslb.com/bfs/face/f6a31275029365ae5dc710006585ddcf1139bde1.png", + "image_small": "http://i0.hdslb.com/bfs/face/b09cdb4c119c467cf2d15db5263b4f539fa6e30b.png", + "level": "高级勋章", + "condition": "单个自制视频总播放数>=10万" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1715270400000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png", + "nickname_color": "#FB7299" + }, + "fans_detail": null, + "following": 0, + "is_followed": 0, + "user_sailing": { + "pendant": { + "id": 1885, + "name": "公主连结凯露", + "image": "http://i0.hdslb.com/bfs/garb/item/ecf1b11044845abc92e576dfdf93ad4f5e5a0958.png", + "jump_url": "", + "type": "vip", + "image_enhance": "http://i0.hdslb.com/bfs/garb/item/ecf1b11044845abc92e576dfdf93ad4f5e5a0958.png", + "image_enhance_frame": "" + }, + "cardbg": null, + "cardbg_with_focus": null + }, + "is_contractor": false, + "contract_desc": "" + }, + "content": { + "message": "看有机化学考研视频", + "plat": 0, + "device": "", + "members": [], + "jump_url": {}, + "max_line": 999 + }, + "replies": null, + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": { + "time_desc": "627天前发布" + } + }, + { + "rpid": 3049044835, + "oid": 201022189, + "type": 1, + "mid": 34598825, + "root": 3030790837, + "parent": 3032092982, + "dialog": 3030978856, + "count": 0, + "rcount": 0, + "floor": 54, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1592368714, + "rpid_str": "3049044835", + "root_str": "3030790837", + "parent_str": "3032092982", + "like": 1, + "action": 0, + "member": { + "mid": "34598825", + "uname": "人宇君sayo", + "sex": "男", + "sign": "", + "avatar": "http://i2.hdslb.com/bfs/face/bf61490cabaedd8e98740f2c98a342ac6d2c607d.jpg", + "rank": "10000", + "DisplayRank": "0", + "face_nft_new": 0, + "is_senior_member": 0, + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "nameplate": { + "nid": 0, + "name": "", + "image": "", + "image_small": "", + "level": "", + "condition": "" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1629561600000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "" + }, + "fans_detail": null, + "following": 0, + "is_followed": 0, + "user_sailing": { + "pendant": null, + "cardbg": null, + "cardbg_with_focus": null + }, + "is_contractor": false, + "contract_desc": "" + }, + "content": { + "message": "回复 @緑箭口香糖 :牛的", + "plat": 0, + "device": "", + "members": [], + "jump_url": {}, + "max_line": 999 + }, + "replies": null, + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": { + "time_desc": "623天前发布" + } + }, + { + "rpid": 3049581999, + "oid": 201022189, + "type": 1, + "mid": 479083152, + "root": 3030790837, + "parent": 3030978856, + "dialog": 3030978856, + "count": 0, + "rcount": 0, + "floor": 93, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1592378703, + "rpid_str": "3049581999", + "root_str": "3030790837", + "parent_str": "3030978856", + "like": 2, + "action": 0, + "member": { + "mid": "479083152", + "uname": "人间多了许茫然", + "sex": "保密", + "sign": "无聊...\n", + "avatar": "http://i0.hdslb.com/bfs/face/6e7ee177b5cc681b9609c07f8d5eb574b52d409c.jpg", + "rank": "10000", + "DisplayRank": "0", + "face_nft_new": 0, + "is_senior_member": 0, + "level_info": { + "current_level": 5, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "nameplate": { + "nid": 0, + "name": "", + "image": "", + "image_small": "", + "level": "", + "condition": "" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1632240000000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "" + }, + "fans_detail": null, + "following": 0, + "is_followed": 0, + "user_sailing": { + "pendant": null, + "cardbg": null, + "cardbg_with_focus": null + }, + "is_contractor": false, + "contract_desc": "" + }, + "content": { + "message": "回复 @我到四川省来 :哈哈,考研不考化学吧", + "plat": 0, + "device": "", + "members": [], + "jump_url": {}, + "max_line": 999 + }, + "replies": null, + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": { + "time_desc": "623天前发布" + } + }, + { + "rpid": 3049578129, + "oid": 201022189, + "type": 1, + "mid": 11814633, + "root": 3030790837, + "parent": 3049581999, + "dialog": 3030978856, + "count": 0, + "rcount": 0, + "floor": 94, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1592378760, + "rpid_str": "3049578129", + "root_str": "3030790837", + "parent_str": "3049581999", + "like": 1, + "action": 0, + "member": { + "mid": "11814633", + "uname": "我到四川省来", + "sex": "保密", + "sign": "保持内心的平静", + "avatar": "http://i0.hdslb.com/bfs/face/1c7cad967633c718ddef302f4aa39efaed53a2e4.jpg", + "rank": "10000", + "DisplayRank": "0", + "face_nft_new": 0, + "is_senior_member": 0, + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 1885, + "name": "公主连结凯露", + "image": "http://i0.hdslb.com/bfs/garb/item/ecf1b11044845abc92e576dfdf93ad4f5e5a0958.png", + "expire": 0, + "image_enhance": "http://i0.hdslb.com/bfs/garb/item/ecf1b11044845abc92e576dfdf93ad4f5e5a0958.png", + "image_enhance_frame": "" + }, + "nameplate": { + "nid": 3, + "name": "白银殿堂", + "image": "http://i2.hdslb.com/bfs/face/f6a31275029365ae5dc710006585ddcf1139bde1.png", + "image_small": "http://i0.hdslb.com/bfs/face/b09cdb4c119c467cf2d15db5263b4f539fa6e30b.png", + "level": "高级勋章", + "condition": "单个自制视频总播放数>=10万" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1715270400000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png", + "nickname_color": "#FB7299" + }, + "fans_detail": null, + "following": 0, + "is_followed": 0, + "user_sailing": { + "pendant": { + "id": 1885, + "name": "公主连结凯露", + "image": "http://i0.hdslb.com/bfs/garb/item/ecf1b11044845abc92e576dfdf93ad4f5e5a0958.png", + "jump_url": "", + "type": "vip", + "image_enhance": "http://i0.hdslb.com/bfs/garb/item/ecf1b11044845abc92e576dfdf93ad4f5e5a0958.png", + "image_enhance_frame": "" + }, + "cardbg": null, + "cardbg_with_focus": null + }, + "is_contractor": false, + "contract_desc": "" + }, + "content": { + "message": "回复 @转手告别旧生活 :专业课 考啊", + "plat": 0, + "device": "", + "members": [], + "jump_url": {}, + "max_line": 999 + }, + "replies": null, + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": { + "time_desc": "623天前发布" + } + }, + { + "rpid": 3049748009, + "oid": 201022189, + "type": 1, + "mid": 39891232, + "root": 3030790837, + "parent": 3032092982, + "dialog": 3030978856, + "count": 0, + "rcount": 0, + "floor": 99, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1592382373, + "rpid_str": "3049748009", + "root_str": "3030790837", + "parent_str": "3032092982", + "like": 1, + "action": 0, + "member": { + "mid": "39891232", + "uname": "夏次一町and庵野一洋", + "sex": "保密", + "sign": "嘚儿~驾!", + "avatar": "http://i1.hdslb.com/bfs/face/79fbbc56271053565f6dd4395cd77120bad7c568.jpg", + "rank": "10000", + "DisplayRank": "0", + "face_nft_new": 0, + "is_senior_member": 0, + "level_info": { + "current_level": 5, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 452, + "name": "灵笼", + "image": "http://i1.hdslb.com/bfs/face/9c5f14d6749daded668f3f66998baf4a50e7d8da.png", + "expire": 0, + "image_enhance": "http://i1.hdslb.com/bfs/face/9c5f14d6749daded668f3f66998baf4a50e7d8da.png", + "image_enhance_frame": "" + }, + "nameplate": { + "nid": 0, + "name": "", + "image": "", + "image_small": "", + "level": "", + "condition": "" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1628870400000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "" + }, + "fans_detail": null, + "following": 0, + "is_followed": 0, + "user_sailing": { + "pendant": { + "id": 452, + "name": "灵笼", + "image": "http://i0.hdslb.com/bfs/face/9c5f14d6749daded668f3f66998baf4a50e7d8da.png", + "jump_url": "", + "type": "vip", + "image_enhance": "http://i0.hdslb.com/bfs/face/9c5f14d6749daded668f3f66998baf4a50e7d8da.png", + "image_enhance_frame": "" + }, + "cardbg": null, + "cardbg_with_focus": null + }, + "is_contractor": false, + "contract_desc": "" + }, + "content": { + "message": "回复 @緑箭口香糖 :不收费啊", + "plat": 0, + "device": "", + "members": [], + "jump_url": {}, + "max_line": 999 + }, + "replies": null, + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": { + "time_desc": "623天前发布" + } + } + ], + "assist": 0, + "blacklist": 0, + "vote": 0, + "lottery": 0, + "config": { + "showadmin": 1, + "showentry": 1, + "showfloor": 0, + "showtopic": 1, + "show_up_flag": true, + "read_only": false, + "show_del_log": true + }, + "upper": { + "mid": 92586428 + }, + "show_bvid": false, + "control": { + "input_disable": false, + "root_input_text": "发一条友善的评论", + "child_input_text": "", + "giveup_input_text": "不发没关系,请继续友善哦~", + "bg_text": "看看下面~来发评论吧", + "web_selection": false, + "answer_guide_text": "需要升级成为lv2会员后才可以评论,先去答题转正吧!", + "answer_guide_icon_url": "http://i0.hdslb.com/bfs/emote/96940d16602cacbbac796245b7bb99fa9b5c970c.png", + "answer_guide_ios_url": "https://www.bilibili.com/h5/newbie/entry?navhide=1&re_src=12", + "answer_guide_android_url": "https://www.bilibili.com/h5/newbie/entry?navhide=1&re_src=6", + "show_type": 1, + "show_text": "", + "disable_jump_emote": false + }, + "note": 1 + } +} +``` + +</details> + +## 获取评论区热评 + +> https://api.bilibili.com/x/v2/reply/hot + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +按照热评排列 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | ---------------------------------------- | +| access_key | str | APP登录 Token | APP 方式必要 | | +| type | num | 评论区类型代码 | 必要 | [类型代码见表](readme.md#评论区类型代码) | +| oid | num | 目标评论区 id | 必要 | | +| root | num | 根回复 rpid | 必要 | | +| ps | num | 每页项数 | 非必要 | 默认为20<br />定义域:1-49 | +| pn | num | 页码 | 非必要 | 默认为1 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----------------------------- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-404:无此项<br />12002:评论区已关闭<br />12009:评论主体的type不合法 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 正确时:obj<br />错误时:null | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---- | +| page | obj | 页面信息 | | +| replies | obj | 热评列表 | | + +`data`中的`page`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | -------- | ---- | +| acount | num | 总评论数 | | +| count | num | 热评数 | | +| num | num | 当前页码 | | +| size | num | 每页项数 | | + +`data`中的`replies`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | -------------------------------------- | +| 0 | obj | 热评条目 1 | [对象定义见表](readme.md#评论条目对象) | +| n | obj | 热评条目 (n+1) | 按照热评排列 | +| …… | obj | …… | …… | + +**示例:** + +获取视频`av2`的评论区热评,每页5项,查看第1页 + +```shell +curl -G 'https://api.bilibili.com/x/v2/reply/hot' \ +--data-urlencode 'type=1' \ +--data-urlencode 'oid=2' \ +--data-urlencode 'ps=5' \ +--data-urlencode 'pn=1' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "page": { + "acount": 76796, + "count": 60975, + "num": 1, + "size": 5 + }, + "replies": [ + { + "rpid": 476670, + "oid": 2, + "type": 1, + "mid": 58426, + "root": 0, + "parent": 0, + "dialog": 0, + "count": 2733, + "rcount": 2608, + "floor": 2, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1291350931, + "like": 90425, + "action": 0, + "member": null, + "content": { + "message": "貌似没人来", + "plat": 0, + "device": "", + "members": null, + "jump_url": null, + "max_line": 999 + }, + "replies": null, + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": {} + }, + { + "rpid": 917945205, + "oid": 2, + "type": 1, + "mid": 34762090, + "root": 0, + "parent": 0, + "dialog": 0, + "count": 461, + "rcount": 365, + "floor": 17977, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1532071373, + "like": 29795, + "action": 0, + "member": null, + "content": { + "message": "7.20日,站长被封7天\n\n历史性留名[2233娘_卖萌]", + "plat": 0, + "device": "", + "members": null, + "jump_url": null, + "max_line": 999 + }, + "replies": null, + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": {} + }, + { + "rpid": 2576184175, + "oid": 2, + "type": 1, + "mid": 24512285, + "root": 0, + "parent": 0, + "dialog": 0, + "count": 1066, + "rcount": 1000, + "floor": 40932, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1584945297, + "like": 44309, + "action": 0, + "member": null, + "content": { + "message": "人类最古のav号(挂了的不算)也变成bv了[大哭][大哭][大哭]青春结束了", + "plat": 0, + "device": "", + "members": null, + "jump_url": null, + "max_line": 999 + }, + "replies": null, + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": {} + }, + { + "rpid": 495059, + "oid": 2, + "type": 1, + "mid": 2, + "root": 0, + "parent": 0, + "dialog": 0, + "count": 898, + "rcount": 838, + "floor": 5, + "state": 2, + "fansgrade": 0, + "attr": 0, + "ctime": 1291918239, + "like": 34224, + "action": 0, + "member": null, + "content": { + "message": "wwwww", + "plat": 0, + "device": "", + "members": null, + "jump_url": null, + "max_line": 999 + }, + "replies": null, + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": {} + }, + { + "rpid": 646408628, + "oid": 2, + "type": 1, + "mid": 33066927, + "root": 0, + "parent": 0, + "dialog": 0, + "count": 173, + "rcount": 160, + "floor": 10914, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 1519135750, + "like": 7197, + "action": 0, + "member": null, + "content": { + "message": "第一首:来夢緑 - kagome-kagome ~ 月の眷属達カラオケ\n第二首:dBu music - 千年幻想郷 -Aurora sky edition-\n第三首:Sensitive Heart - 千年幻想郷 ~ History of the Moon\n第四首:Yellow-Zebra - 月の律动~Rhythm of the moon~(东方永夜抄 “千年幻想郷 ~ History of the Moon”)\n第五首:工藤舞 - D.S.F.S(ヴォヤージュ1969)\n第六首:Angelic Quasar - かの郷は永き幻の\n第七首:東方永夜抄 - 黒髪のアマンダ\n第八首:君の美術館 - 千年幻想郷 ~ History of the Moon\n\n------------------------\n这些是av:2出现的音乐,应该不会缺少的喵~。(笑) 如果有需要有兴趣的话欢迎复制喵~~(`・ω・´)\n复制的9818楼的\n前排提示:本视频只有大会员能看", + "plat": 0, + "device": "", + "members": null, + "jump_url": null, + "max_line": 999 + }, + "replies": null, + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": {} + } + ] + } +} +``` + +</details> + +## 获取指定评论信息 + +该接口已经弃用 + +<details> +<summary>点击展开折叠内容:</summary> + +> https://api.bilibili.com/x/v2/reply/info + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------------- | ------ | -------------------------------------------- | +| type | num | 评论区类型代码 | 非必要 | **[类型代码见表](readme.md#评论区类型代码)** | +| oid | num | 目标评论区 id | 非必要 | | +| rpid | num | 目标评论 rpid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----------------------------- | -------- | --------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-404:无此项 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 正确时:obj<br />错误时:null | 评论条目 | [对象定义见表](readme.md#评论条目对象) | + +**示例:** + +获取视频`av379743801`评论区下`rpid=95737567200`的信息 + +```bash +curl -G 'https://api.bilibili.com/x/v2/reply/info' \ +--data-urlencode 'type=1' \ +--data-urlencode 'oid=379743801' \ +--data-urlencode 'rpid=95737567200' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "rpid": 95737567200, + "oid": 379743801, + "type": 1, + "mid": 293793435, + "root": 0, + "parent": 0, + "dialog": 0, + "count": 34, + "rcount": 34, + "floor": 382, + "state": 0, + "fansgrade": 0, + "attr": 514, + "ctime": 1639916028, + "like": 154, + "action": 0, + "member": { + "mid": "293793435", + "uname": "社会易姐QwQ", + "sex": "男", + "sign": "普通带砖技术宅,爱好MC 编程 电子,是车万人也是术术人,粉丝群:1136462265,博客:shakianee.top", + "avatar": "http://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg", + "rank": "10000", + "DisplayRank": "0", + "face_nft_new": 0, + "is_senior_member": 0, + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 2511, + "name": "初音未来13周年", + "image": "http://i0.hdslb.com/bfs/garb/item/4f8f3f1f2d47f0dad84f66aa57acd4409ea46361.png", + "expire": 0, + "image_enhance": "http://i0.hdslb.com/bfs/garb/item/fe0b83b53e2342b16646f6e7a9370d8a867decdb.webp", + "image_enhance_frame": "http://i0.hdslb.com/bfs/garb/item/127c507ec8448be30cf5f79500ecc6ef2fd32f2c.png" + }, + "nameplate": { + "nid": 4, + "name": "青铜殿堂", + "image": "http://i2.hdslb.com/bfs/face/2879cd5fb8518f7c6da75887994c1b2a7fe670bd.png", + "image_small": "http://i0.hdslb.com/bfs/face/6707c120e00a3445933308fd9b7bd9fad99e9ec4.png", + "level": "普通勋章", + "condition": "单个自制视频总播放数>=1万" + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1675785600000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png", + "nickname_color": "#FB7299" + }, + "fans_detail": null, + "following": 0, + "is_followed": 0, + "user_sailing": null, + "is_contractor": false, + "contract_desc": "" + }, + "content": { + "message": "这款机器背后发热超级严重。。。。。最烫的时候有60-70℃手不敢摸,而发烫后会降频,最低会降到0.6Ghz[笑哭][笑哭]\n现在解决办法已经出来了https://b23.tv/suUd3g7", + "plat": 0, + "device": "", + "members": null, + "jump_url": null, + "max_line": 999 + }, + "replies": null, + "assist": 0, + "folder": { + "has_folded": false, + "is_folded": false, + "rule": "" + }, + "up_action": { + "like": false, + "reply": false + }, + "show_follow": false, + "invisible": false, + "reply_control": {} + } +} +``` + +</details> + +</details> + +## 获取评论区评论总数 + +> https://api.bilibili.com/x/v2/reply/count + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------------- | ------ | -------------------------------------------- | +| type | num | 评论区类型代码 | 必要 | **[类型代码见表](readme.md#评论区类型代码)** | +| oid | num | 目标评论区 id | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----------------------------- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-404:无此项<br />12009:评论主体的type不合法 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 正确时:obj<br />错误时:null | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | -------- | ---- | +| count | num | 评论条数 | | + +**示例:** + +获取视频`av2`的评论区总计评论条数 + +```shell +curl -G 'https://api.bilibili.com/x/v2/reply/count' \ +--data-urlencode 'type=1' \ +--data-urlencode 'oid=2' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "count": 65521 + } +} +``` + +</details> + diff --git a/bb-api-collect/docs/comment/readme.md b/bb-api-collect/docs/comment/readme.md new file mode 100644 index 0000000000..e9ba1a740f --- /dev/null +++ b/bb-api-collect/docs/comment/readme.md @@ -0,0 +1,349 @@ +# 评论区 + +<img src="../../assets/img/comment.svg" width="100" height="100"/> + +评论系统为全站通用,且APP与web端接口共用,以type标明对象类型,以oid指向响应的对象id + +--- + +**继续查看:** + +- [查询类](list.md) +- [操作类](action.md) + +## 评论区类型代码 + +(PS:以下部分内容来源不明,有待验证) + +| 代码 | 评论区类型 | oid 的意义 | +| ---- | ----------------------- | ----------- | +| 1 | 视频稿件 | 稿件 avid | +| 2 | 话题 | 话题 id | +| 4 | 活动 | 活动 id | +| 5 | 小视频 | 小视频 id | +| 6 | 小黑屋封禁信息 | 封禁公示 id | +| 7 | 公告信息 | 公告 id | +| 8 | 直播活动 | 直播间 id | +| 9 | 活动稿件 | (?) | +| 10 | 直播公告 | (?) | +| 11 | 相簿(图片动态) | 相簿 id | +| 12 | 专栏 | 专栏 cvid | +| 13 | 票务 | (?) | +| 14 | 音频 | 音频 auid | +| 15 | 风纪委员会 | 众裁项目 id | +| 16 | 点评 | (?) | +| 17 | 动态(纯文字动态&分享) | 动态 id | +| 18 | 播单 | (?) | +| 19 | 音乐播单 | (?) | +| 20 | 漫画 | (?) | +| 21 | 漫画 | (?) | +| 22 | 漫画 | 漫画 mcid | +| 33 | 课程 | 课程 epid | + +## 评论条目对象 + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ------------------------------- | ------------------ | ------------------------------------------------------------ | +| rpid | num | 评论 rpid | | +| oid | num | 评论区对象 id | | +| type | num | 评论区类型代码 | **类型代码见上表** | +| mid | num | 发送者 mid | | +| root | num | 根评论 rpid | 若为一级评论则为 0<br />大于一级评论则为根评论 id | +| parent | num | 回复父评论 rpid | 若为一级评论则为 0<br />若为二级评论则为根评论 rpid<br />大于二级评论为上一级评 论 rpid | +| dialog | num | 回复对方 rpid | 若为一级评论则为 0<br />若为二级评论则为该评论 rpid<br />大于二级评论为上一级评论 rpid | +| count | num | 二级评论条数 | | +| rcount | num | 回复评论条数 | | +| floor | num | 评论楼层号 | **注:若不支持楼层则无此项** | +| state | num | 评论状态 | 0: 正常<br />17: 被阿瓦隆系统隐藏 (无法被别人看到, 只能自己看到) | +| fansgrade | num | 是否具有粉丝标签 | 0:无<br />1:有 | +| attr | num | 某属性位? | | +| ctime | num | 评论发送时间 | 时间戳 | +| rpid_str | str | 评论rpid | 字串格式 | +| root_str | str | 根评论rpid | 字串格式 | +| parent_str | str | 回复父评论rpid | 字串格式 | +| like | num | 评论获赞数 | | +| action | num | 当前用户操作状态 | 需要登录(Cookie 或 APP) <br />否则恒为 0<br />0:无<br />1:已点赞<br />2:已点踩 | +| member | obj | 评论发送者信息 | | +| content | obj | 评论信息 | | +| replies | 无效时:null<br />有效时:array | 评论回复条目预览 | **仅嵌套一层**<br />否则为 null | +| assist | num | (?) | | +| folder | obj | 折叠信息 | | +| up_action | obj | 评论 UP 主操作信息 | | +| show_follow | bool | (?) | | +| invisible | bool | 评论是否被隐藏 | | +| card_label | obj | 右上角卡片标签信息 | | +| reply_control | obj | 评论提示文案信息 | | + +`评论条目`中的`member`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ----------------------------- | ---------------------- | ------------------------------------------------------------ | +| mid | str | 发送者 mid | | +| uname | str | 发送者昵称 | | +| sex | str | 发送者性别 | 男 女 保密 | +| sign | str | 发送者签名 | | +| avatar | str | 发送者头像 url | | +| rank | str | (?) | | +| DisplayRank | str | (?) | | +| level_info | obj | 发送者等级 | | +| pendant | obj | 发送者头像框信息 | | +| nameplate | obj | 发送者勋章信息 | | +| official_verify | obj | 发送者认证信息 | | +| vip | obj | 发送者会员信息 | | +| fans_detail | 无效时:null<br />有效时:obj | 发送者粉丝标签 | | +| following | num | 是否关注该用户 | 需要登录(Cookie或APP) <br />否则恒为0<br />0:未关注<br />1:已关注 | +| is_followed | num | 是否被该用户关注 | 需要登录(Cookie或APP) <br />否则恒为0<br />0:未关注<br />1:已关注 | +| user_sailing | obj | 发送者评论条目装扮信息 | | +| is_contractor | bool | 是否为合作用户? | | +| contract_desc | str | 合作用户说明? | | + +`member`中的`level_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | -------- | ---- | +| current_level | num | 用户等级 | | +| current_min | num | 0 | | +| current_exp | num | 0 | | +| next_exp | num | 0 | | + +`member`中的`pendant`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------- | ---- | -------------- | ---- | +| pid | num | 头像框 id | | +| name | str | 头像框名称 | | +| image | str | 头像框图片 url | | +| expire | num | 0 | | +| image_enhance | str | 头像框图片 url | | +| image_enhance_frame | str | (?) | | + +`member`中的`nameplate`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ----------------- | ---- | +| nid | num | 勋章 id | | +| name | str | 勋章名称 | | +| image | str | 挂件图片 url 正常 | | +| image_small | str | 勋章图片 url 小 | | +| level | str | 勋章等级 | | +| condition | str | 勋章条件 | | + +`member`中的`official_verify`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---------------------------------------- | +| type | num | 认证类型 | -1:无<br />0:个人认证<br />1:机构认证 | +| desc | str | 认证信息 | 无为空 | + +`member`中的`vip`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------------- | ---- | -------------- | --------------------------------------- | +| vipType | num | 大会员类型 | 0:无<br />1:月会员<br />2:年以上会员 | +| vipDueDate | num | 大会员到期时间 | 毫秒 时间戳 | +| dueRemark | str | (?) | | +| accessStatus | num | (?) | | +| vipStatus | num | 大会员状态 | 0:无<br />1:有 | +| vipStatusWarn | str | (?) | | +| theme_type | num | 会员样式 id | | +| label | obj | 会员铭牌样式 | | +| avatar_subscript | num | (?) | | +| avatar_subscript_url | str | (?) | | +| nickname_color | str | 昵称颜色 | | + +`vip`中的`label`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ------------ | ------------------------------------------------------------ | +| path | str | (?) | | +| text | str | 会员类型文案 | | +| label_theme | str | 会员类型 | vip:大会员<br />annual_vip:年度大会员<br />ten_annual_vip:十年大会员<br />hundred_annual_vip:百年大会员 | +| text_color | str | 文字颜色? | | +| bg_style | num | (?) | | +| bg_color | str | 背景颜色? | | +| border_color | str | 描边颜色? | | + +`member`中的`fans_detail`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ------------ | ---- | +| uid | num | 用户 mid | | +| medal_id | num | 粉丝标签 id | | +| medal_name | str | 粉丝标签名 | | +| score | num | (?) | | +| level | num | 当前标签等级 | | +| intimacy | num | (?) | | +| master_status | num | (?) | | +| is_receive | num | (?) | | + +`member`中的`user_sailing`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ----------------------------- | ------------ | ---- | +| pendant | 无效时:null<br />有效时:obj | 头像框信息 | | +| cardbg | 无效时:null<br />有效时:obj | 评论卡片装扮 | | +| cardbg_with_focus | null | (?) | | + +`user_sailing`中的`pendant`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------- | ---- | -------------- | -------------------------------------- | +| id | num | 头像框 id | | +| name | str | 头像框名称 | | +| image | str | 头像框图片 url | | +| jump_url | str | 空 | | +| type | str | 装扮类型 | suit:一般装扮<br />vip_suit:vip 装扮 | +| image_enhance | str | (?) | | +| image_enhance_frame | str | (?) | | + +`user_sailing`中的`cardbg`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------------------------ | -------------------------------------- | +| id | num | 评论条目装扮 id | | +| name | str | 评论条目装扮名称 | | +| image | str | 评论条目装扮图片 url | | +| jump_url | str | 评论条目装扮商城页面 url | | +| fan | obj | 粉丝专属信息 | | +| type | str | 装扮类型 | suit:一般装扮<br />vip_suit:vip 装扮 | + +`cardbg`中的`fan`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------------------ | ---------------- | +| is_fan | num | 是否为粉丝专属装扮 | 0:否<br />1:是 | +| number | num | 粉丝专属编号 | | +| color | str | 数字颜色 | 颜色码 | +| name | str | 装扮名称 | | +| num_desc | str | 粉丝专属编号 | 字串格式 | + +`评论条目`中的`content`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ----- | ------------------ | ------------------------------------------------------------ | +| message | str | 评论内容 | **重要** | +| plat | num | 评论发送端 | 1:web端<br />2:安卓客户端<br />3:ios 客户端<br />4:wp 客户端 | +| device | str | 评论发送平台设备 | | +| members | array | at 到的用户信息 | | +| emote | obj | 需要渲染的表情转义 | 评论内容无表情则无此项 | +| jump_url | obj | 需要高亮的超链转义 | | +| max_line | num | 6 | 收起最大行数 | +| pictures | array | 评论图片数组 | | + +`content`中的`members`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------------- | -------------------------------- | +| 0 | obj | at到的用户 1 | 基本同`评论条目`中的`member`对象 | +| n | obj | at到的用户 (n+1) | 项数为at到的不同的用户数 | +| …… | obj | …… | …… | + +`content`中的`emote`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ---------------- | -------- | +| {表情转义符} | obj | 表情转义符信息 1 | | +| …… | obj | 表情转义符信息 n | 向下扩展 | + +`emote`中的`{表情转义符}`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------ | -------------------------------------------------------- | +| id | num | 表情 id | | +| package_id | num | 表情包 id | | +| state | num | 0 | | +| type | num | 表情类型 | 1:免费<br />2:会员专属<br />3:购买所得<br />4:颜文字 | +| attr | num | (?) | | +| text | str | 表情转义符 | | +| url | str | 表情图片 url | | +| meta | obj | 属性信息 | | +| mtime | num | 表情创建时间 | 时间戳 | +| jump_title | str | 表情名称 | | + +`{表情转义符}`中的`meta`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ------------ | ---------------- | +| size | num | 表情尺寸信息 | 1:小<br />2:大 | +| alias | str | 简写名 | 无则无此项 | + +`content`中的`jump_url`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | -------------- | -------- | +| {超链转义} | obj | 超链转义信息 1 | | +| …… | obj | 超链转义信息 n | 向下扩展 | + +`jump_url`中的`{超链转义}`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | -------- | ---- | +| title | str | 标题 | | +| state | num | 图标 url | | +| prefixIcon | str | (?) | | +| appUrlSchema | str | (?) | | +| appName | str | (?) | | +| appPackageName | str | (?) | | +| clickReport | str | 上报 id | | + +`content`中的`pictures`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | -------- | -------- | +| img_src | str | 图片地址 | | +| img_width | num | 图片宽度 | | +| img_height | num | 图片高度 | | +| img_size | num | 图片大小 | 单位KB | + +`评论条目`中的`replies`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ------------------------------------------------------------ | +| 0 | obj | 回复条目1 | **为本对象的递归嵌套**<br />**仅可嵌套一层**<br />按照热度顺序排列 | +| 1 | obj | 回复条目2 | | +| 2 | obj | 回复条目3 | 最后一项 | + +`评论条目`中的`folder`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ---------------------- | ---- | +| has_folded | bool | 是否有被折叠的二级评论 | | +| is_folded | bool | 评论是否被折叠 | | +| rule | str | 相关规则页面 url | | + +`评论条目`中的`up_action`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ---------------- | ----------------------- | +| like | bool | 是否UP主觉得很赞 | false:否<br />true:是 | +| reply | bool | 是否被UP主回复 | false:否<br />true:是 | + +`评论条目`中的`card_label`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------------- | ---- | ------------ | ----------------------------- | +| rpid | num | 评论 rpid | | +| text_content | str | 标签文本 | 已知有`妙评` | +| text_color_day | str | 日间文本颜色 | 十六进制颜色值,下同 | +| text_color_night | str | 夜间文本颜色 | | +| label_color_day | str | 日间标签颜色 | | +| label_color_night | str | 夜间标签颜色 | | +| image | str | | 作用不明 | +| type | str | 1 | 作用不明 | +| background | str | 背景图片 url | | +| background_width | num | 背景图片宽度 | | +| background_height | num | 背景图片高度 | | +| jump_url | str | 跳转链接 | | +| effect | num | 0 | 作用不明,可能用于控制动画,下同 | +| effect_start_time | num | 0 | | + +`评论条目`中的`reply_control`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------------- | ---- | -------- | -------------------- | +| max_line | num | 6 | 用于控制折叠状态下的最大显示行数 | +| sub_reply_entry_text | str | 回复提示 | `共 xx 条回复` | +| sub_reply_title_text | str | 回复提示 | `相关回复共有 xx 条` | +| time_desc | str | 时间提示 | `xx 天/小时 前发布` | +| location | str | IP属地 | `IP属地:xx`<br />评论者发送评论时的IP地址属地<br />仅对2022-07-25 11:00及以后发布的评论有效<br />需要登录| +| support_share | bool | 是否可分享 | false:否<br />true:是 | diff --git a/bb-api-collect/docs/creativecenter/opus.md b/bb-api-collect/docs/creativecenter/opus.md new file mode 100644 index 0000000000..75f18fee70 --- /dev/null +++ b/bb-api-collect/docs/creativecenter/opus.md @@ -0,0 +1,110 @@ +# 图文操作 + +## 删除动态 + +> https://api.bilibili.com/x/dynamic/feed/operate/remove + +*请求方法: POST* + +认证方式:Cookie (SESSDATA) + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ------ | ---- | ------ | ---- | +| csrf | string | CSRF Token (即 Cookie 中 bili_jct) | 必要 | | +| platform | string | 平台标识 | 不必要 | 如 `web` | + +**正文参数 (application/json):** + +根对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ------ | -------------- | ------ | ---- | +| dyn_id_str | string | 动态的 opus id | 必要 | | +| dyn_type | number | 动态类型? | 不必要 | | +| rid_str | string | | 不必要 | | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ------ | ------ | ---- | +| code | number | 返回值 | 0: 成功<br />-101: 帐号未登录<br />-111: csrf 校验失败<br />-400: 请求错误<br />4101001: 参数错误<br />4101144: 只能删除自身的动态 | +| message | string | 错误信息 | 成功时为 `0` | +| ttl | number | `1` | | +| data | object | 空对象 | | + +**示例:** + +删除动态 `667831766353969169` + +```shell +curl 'https://api.bilibili.com/x/dynamic/feed/operate/remove' \ +--url-query 'csrf=05fa8d65755655c2893d40d3692d4c70' \ +-H 'content-type: application/json' +--data-raw '{"dyn_id_str":"667831766353969169"}' \ +-b 'SESSDATA=xxxxxx' \ +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": {} +} +``` + +</details> + +## 删除专栏 + +> <https://member.bilibili.com/x/web/article/delete> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------ | ------ | ---- | +| aid | num | 文章cvid | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf校验失败<br />-400:请求错误<br />-404:无此项<br />37104:无权限操作他人专栏 | +| message | str | 错误信息 | 默认为`0` | +| ttl | num | 1 | | + +**示例:** + +```shell +curl 'https://member.bilibili.com/x/web/article/delete' \ + --data-urlencode 'aid=114514' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> diff --git a/bb-api-collect/docs/creativecenter/railgun.md b/bb-api-collect/docs/creativecenter/railgun.md new file mode 100644 index 0000000000..8b171bb68f --- /dev/null +++ b/bb-api-collect/docs/creativecenter/railgun.md @@ -0,0 +1,274 @@ +# 电磁力相关 + +电磁力每周日下午刷新 + +## 获取电磁力等级(web端) + +> https://api.bilibili.com/studio/up-rating/v3/rating/info + +*请求方式:GET* + +认证方式:仅可Cookie(SESSDATA) + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ----------- | ---------------- | +| mid | num | 当前用户mid | | +| level | num | 电磁力等级 | | +| score | num | 电磁力分数 | | +| credit | num | 信用分 | | +| state | num | ? | 一直是2 | + +**示例:** + +```shell +curl 'https://member.bilibili.com/x/web/elec/user' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "mid": ***, + "level": 4, + "score": 326, + "credit": 100, + "state": 2, + "update_date": 1694966400 + } +} +``` + +</details> + +## (失效)获取电磁力详细数值(双端) + +> https://api.bilibili.com/studio/up-rating/rating/summary + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | ---- | +| access_key | str | APP登录Token | APP方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ------- | ----------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ---- | -------------- | ---- | +| date | str | 数据刷新时间 | YYYY-MM-DD | +| level | obj | 电磁力等级 | | +| creative | obj | 创作力 | | +| influence | obj | 影响力 | | +| credit | obj | 信用分 | | + +`data`中的`level` `creative` `influence` `credit`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------- | ---- | +| data | num | 数值 | | +| prev | num | ??? | **作用尚不明确** | +| desc | str | 描述 | | +| date | num | 刷新时间 | 时间戳 | + +**示例:** + +Cookie方式: + +```shell +curl 'https://api.bilibili.com/studio/up-rating/rating/summary' \ +-b 'SESSDATA=xxx' +``` + +APP方式: + +```shell +curl -G 'https://api.bilibili.com/studio/up-rating/rating/summary' \ +--data-urlencode 'access_key=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "date": "2020-07-05", + "level": { + "data": 1, + "prev": 0, + "desc": "正式开启创作之路,希望未来的路上我们携手相伴,创作更多优质内容~", + "date": 1593878400 + }, + "creative": { + "data": 39, + "prev": 39, + "desc": "考察近一年来的创作行为,良好的原创投稿行为和互动数据有助于提升创作力。", + "date": 1593878400 + }, + "influence": { + "data": 54, + "prev": 54, + "desc": "根据近一年活跃粉丝数据进行评估,良好的粉丝活跃度是影响力的基础。", + "date": 1593878400 + }, + "credit": { + "data": 100, + "prev": 100, + "desc": "良好的投稿记录将维持较高的信用分,违反投稿公约的行为将扣除信用分。", + "date": 1594106147 + } + } +} +``` + +</details> + +## 获取电磁力数值历史变化(双端) + +> https://api.bilibili.com/studio/up-rating/rating/history + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | -------------- | +| access_key | str | APP登录Token | APP方式必要 | | +| type | num | 目标数据类型 | 必要 | 类型代码见下表 | + +类型代码`type`: + +| 代码 | 含义 | +| ---- | ------ | +| 1 | 创作力 | +| 2 | 影响力 | +| 3 | 信用分 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ----- | ------------ | -------- | +| date | array | 数据记录时间 | 每周更新 | +| score | array | 电磁力等级 | 每周更新 | + +`data`中的`date`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------------- | -------------- | +| 0 | str | 1周前的日期 | MM-DD | +| n | str | (n+1)周前的日期 | 与数值一一对应 | +| …… | str | …… | …… | +| 7 | str | 8周前的日期 | 最后一条 | + +`data`中的`score`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------------- | -------------- | +| 0 | num | 1周前的数值 | | +| n | num | (n+1)周前的数值 | 与日期一一对应 | +| …… | num | …… | …… | +| 7 | num | 8周前的数值 | 最后一条 | + +**示例:** + +查询创作力的历史变化 + +Cookie方式: + +```shell +curl -G 'https://api.bilibili.com/studio/up-rating/rating/history' \ +--data-urlencode 'type=1' \ +-b 'SESSDATA=xxx' +``` + +APP方式: + +```shell +curl -G 'https://api.bilibili.com/studio/up-rating/rating/history' \ +--data-urlencode 'type=1' \ +--data-urlencode 'access_key=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "date": [ + "05-17", + "05-24", + "05-31", + "06-07", + "06-14", + "06-21", + "06-28", + "07-05" + ], + "score": [ + 48, + 48, + 49, + 49, + 49, + 49, + 49, + 49 + ] + } +} +``` + +</details> diff --git a/bb-api-collect/docs/creativecenter/season.md b/bb-api-collect/docs/creativecenter/season.md new file mode 100644 index 0000000000..8290bde314 --- /dev/null +++ b/bb-api-collect/docs/creativecenter/season.md @@ -0,0 +1,1088 @@ +# 合集管理 + +关于用户空间的合集及视频列表参见 [合集和视频列表信息](../video/collection.md) + +## 获取合集列表 + +> https://member.bilibili.com/x2/creative/web/seasons + +*请求方式: GET* + +认证方式: Cookie (SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | --------- | ----------- | ----------------- | +| pn | num | 页码 | 必要 | 默认为 1 | +| ps | num | 每页数量 | 必要 | 默认为 30 | +| order | str | 排序方式 | 不必要 | 创建时间: ctime<br />修改时间: mtime | +| sort | str | 排序方式 | 不必要 | 创建时间: asc<br />修改时间: desc | +| draft | num | 1 | 不必要 | 作用尚不明确 | + +**JSON回复:** + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | ---- | +| seasons | arr | 合集列表 | | +| tip | obj | 内容 `title` `url` 均为空 | | +| total | num | 合集总数 | | +| play_type | num | 1 | 作用尚不明确 | + +`seasons`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | ---- | +| season | obj | 合集信息 | | +| course | null | | | +| checkin | obj | 审核信息? | | +| seasonStat | obj | 合集统计信息 | | +| sections | obj | 小节列表 | | +| part_episodes | arr | 合集视频列表 | | + +`seasons`数组中的对象中的`season`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | ---- | +| id | num | 合集 ID | | +| title | str | 合集标题 | | +| desc | str | 合集描述 | | +| cover | str | 合集封面 URL | | +| isEnd | num | 是否已完结? | 0: 未完结 | +| mid | num | 合集作者 ID | | +| isAct | num | 是否为活动合集? | 0: 否 | +| is_pay | num | 是否付费? | 0: 否 | +| state | num | 合集状态? | 0: 正常显示<br />-6: 正在审核 | +| partState | num | 合集分段状态? | 0 | +| signState | num | 合集签名状态? | 0 | +| rejectReason | str | 合集拒绝原因? | | +| ctime | num | 创建时间 | | +| mtime | num | 修改时间 | | +| no_section | num | 是否设小节 | 1: 不设小节 | +| forbid | num | 合集是否禁止? | 0: 否 | +| protocol_id | str | 空 | | +| ep_num | num | 0 | | +| season_price | num | 合集价格? | 0: 免费 | +| is_opened | num | 是否公开? | 1: 公开 | +| has_charging_pay | num | 是否充电付费? | 0: 否 | + +`seasons`数组中的对象中的`checkin`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | ---- | +| status | num | 状态? | 0: 正常显示 | +| status_reason | str | 状态原因? | | +| season_status | num | 合集审核状态? | 1: 审核通过 | + +`seasons`数组中的对象中的`seasonStat`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | ---- | +| view | num | 播放量 | | +| danmaku | num | 弹幕数 | | +| reply | num | 评论数 | | +| fav | num | 收藏数 | | +| coin | num | 硬币数 | | +| share | num | 分享数 | | +| nowRank | num | 当前排名? | | +| hisRank | num | 历史最高排名? | | +| like | num | 点赞数 | | +| subscription | num | 订阅数 | | +| vt | num | 0 | | + +`seasons`数组中的对象中的`sections`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | ---- | +| sections | arr | 小节列表 | 套了个娃 | + +`seasons`数组中的对象中的`sections`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | ---- | +| id | num | 小节 ID | | +| type | num | 1 | | +| seasonId | num | 合集 ID | | +| title | str | 小节标题 | | +| order | num | 排序 | | +| state | num | 状态? | 0: 正常 | +| partState | num | 合集分段状态? | 0: 正常 | +| rejectReason | str | 拒绝原因? | | +| ctime | num | 创建时间 | | +| mtime | num | 修改时间 | | +| epCount | num | 视频数量 | | +| cover | str | 封面 URL | | +| has_charging_pay | num | 是否充电付费? | 0: 否 | +| Episodes | null | | | + +`seasons`数组中的对象中的`part_episodes`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | ---- | +| id | num | 合集内视频 ID | | +| title | str | 视频标题 | | +| aid | num | 视频 aid | | +| bvid | str | 视频 bvid | | +| cid | num | 视频 cid | | +| seasonId | num | 合集 ID | | +| sectionId | num | 小节 ID | | +| order | num | 排序编号 | | +| videoTitle | str | 空 | | +| archiveTitle | str | 空 | | +| archiveState | num | 0 | | +| rejectReason | str | 拒绝理由? | | +| state | num | 0 | | +| cover | str | 封面 URL | | +| is_free | num | 是否免费? | 0: 免费 | +| aid_owner | bool | false | | +| charging_pay | num | 充电付费? | 0: 否 | + +**示例:** + +```shell +curl -G 'https://member.bilibili.com/x2/creative/web/seasons' \ +--data-urlencode 'pn=1' \ +--data-urlencode 'ps=30' \ +-b "SESSDATA=xxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "seasons": [ + { + "season": { + "id": 3541247, + "title": "🍥Debian", + "desc": "这里是泽生折腾 Debian GNU/Linux 的珍贵影像记录喵~", + "cover": "https://archive.biliimg.com/bfs/archive/ec51de61b53159c5e2430cf963f5f97e692baeaf.jpg", + "isEnd": 0, + "mid": 645769214, + "isAct": 0, + "is_pay": 0, + "state": 0, + "partState": 0, + "signState": 0, + "rejectReason": "", + "ctime": 1722573640, + "mtime": 1722577206, + "no_section": 1, + "forbid": 0, + "protocol_id": "", + "ep_num": 0, + "season_price": 0, + "is_opened": 1, + "has_charging_pay": 0 + }, + "course": null, + "checkin": { + "status": 0, + "status_reason": "", + "season_status": 1 + }, + "seasonStat": { + "view": 6793, + "danmaku": 21, + "reply": 93, + "fav": 64, + "coin": 26, + "share": 12, + "nowRank": 0, + "hisRank": 0, + "like": 141, + "subscription": 0, + "vt": 0 + }, + "sections": { + "sections": [ + { + "id": 3954033, + "type": 1, + "seasonId": 3541247, + "title": "正片", + "order": 1, + "state": 0, + "partState": 0, + "rejectReason": "", + "ctime": 1722573640, + "mtime": 1722577206, + "epCount": 2, + "cover": "http://i2.hdslb.com/bfs/archive/b76c0b574862f5a8e8eb133f5f33fcbcd602401a.jpg", + "has_charging_pay": 0, + "Episodes": null + } + ] + }, + "part_episodes": [ + { + "id": 77260687, + "title": "Linux小寄巧: 原地卸载内核然后尝试救活!", + "aid": 1906473802, + "bvid": "BV1MU411S7iJ", + "cid": 1625992822, + "seasonId": 3541247, + "sectionId": 3954033, + "order": 1, + "videoTitle": "", + "archiveTitle": "", + "archiveState": 0, + "rejectReason": "", + "state": 0, + "cover": "http://i2.hdslb.com/bfs/archive/b76c0b574862f5a8e8eb133f5f33fcbcd602401a.jpg", + "is_free": 0, + "aid_owner": false, + "charging_pay": 0 + }, + { + "id": 77260688, + "title": "十多年前的电脑运行Debian12的启动过程", + "aid": 1956170305, + "bvid": "BV1Ay411i7Ph", + "cid": 1607067247, + "seasonId": 3541247, + "sectionId": 3954033, + "order": 2, + "videoTitle": "", + "archiveTitle": "", + "archiveState": 0, + "rejectReason": "", + "state": 0, + "cover": "http://i0.hdslb.com/bfs/archive/0bff6624fdfcbf3326fba1837fef093d455c846a.jpg", + "is_free": 0, + "aid_owner": false, + "charging_pay": 0 + } + ] + }, + { + "season": { + "id": 3541327, + "title": "BACollect", + "desc": "", + "cover": "https://archive.biliimg.com/bfs/archive/77906db03b1eefac02613de184afad03f7bc58d7.jpg", + "isEnd": 0, + "mid": 645769214, + "isAct": 0, + "is_pay": 0, + "state": 0, + "partState": 0, + "signState": 0, + "rejectReason": "", + "ctime": 1722574656, + "mtime": 1722574658, + "no_section": 1, + "forbid": 0, + "protocol_id": "", + "ep_num": 0, + "season_price": 0, + "is_opened": 1, + "has_charging_pay": 0 + }, + "course": null, + "checkin": { + "status": 0, + "status_reason": "", + "season_status": 0 + }, + "seasonStat": { + "view": 0, + "danmaku": 0, + "reply": 0, + "fav": 0, + "coin": 0, + "share": 0, + "nowRank": 0, + "hisRank": 0, + "like": 0, + "subscription": 0, + "vt": 0 + }, + "sections": { + "sections": [ + { + "id": 3954127, + "type": 1, + "seasonId": 3541327, + "title": "正片", + "order": 1, + "state": 0, + "partState": 0, + "rejectReason": "", + "ctime": 1722574656, + "mtime": 1722574656, + "epCount": 0, + "cover": "http://static.hdslb.com/images/transparent.gif", + "has_charging_pay": 0, + "Episodes": null + } + ] + }, + "part_episodes": null + } + ], + "tip": { + "title": "", + "url": "" + }, + "total": 2, + "play_type": 1 + } +} +``` + +</details> + +## 创建合集 + +> ttps://member.bilibili.com/x2/creative/web/season/add + +*请求方式: POST* + +认证方式: Cookie (SESSDATA) + +注: 有人工审核 + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| title | str | 合集标题 | 必要 | | +| desc | str | 合集简介 | 不必要 | | +| cover | str | 封面图 | 必要 | 从 [上传封面](upload.md#上传封面) 处获取 | +| season_price | num | 0 | 不必要 | 作用尚不明确 | +| csrf | str | CSRF Token (即 Cookies 中 bili_jct ) | 必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | | +| ttl | num | 1 | | +| data | num | 合集 ID | | + +**示例:** + +```shell +curl -X POST 'https://member.bilibili.com/x2/creative/web/season/add' \ +--data-urlencode 'title=🍥Debian' \ +--data-urlencode 'desc=这里是泽生折腾 Debian GNU/Linux 的珍贵影像记录喵~' \ +--data-urlencode 'cover=https://archive.biliimg.com/bfs/archive/ec51de61b53159c5e2430cf963f5f97e692baeaf.jpg' \ +--data-urlencode 'season_price=0' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx; bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": 3541247 +} +``` + +</details> + +## 添加视频到合集 + +> https://member.bilibili.com/x2/creative/web/season/section/episodes/add + +*请求方式: POST* + +认证方式: Cookie (SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| csrf | str | CSRF Token (即 Cookies 中 bili_jct ) | 必要 | | + +**正文参数 (application/json):** + +根对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| episode | array | 视频列表 | 必要 | | +| section_id | num | 合集小节 ID | 必要 | | + +`episode` 数组中的对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| aid | num | 视频 aid | 必要 | | +| cid | num | 稿件 cid | 必要 | | +| title | str | 合集内单集标题 | 必要 | | +| charging_pay | num | 0 | 不必要 | 作用尚不明确 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | | +| ttl | num | 1 | | + +**示例:** + +假设您已经把请求有效荷载放在 `payload.json` 文件中: + +```json +{ + "sectionId": 3954033, + "episodes": [ + { + "title": "Linux小寄巧: 原地卸载内核然后尝试救活!", + "aid": 1906473802, + "cid": 1625992822, + "charging_pay": 0 + }, + { + "title": "十多年前的电脑运行Debian12的启动过程", + "aid": 1956170305, + "cid": 1607067247, + "charging_pay": 0 + } + ] +} +``` + +```shell +curl -X POST --url 'https://member.bilibili.com/x2/creative/web/season/section/episodes/add' \ +--url-query 'csrf=xxx' \ +-H 'Content-Type: application/json' \ +--data-binary @payload.json \ +-b 'SESSDATA=xxx; bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +## 编辑合集小节 + +> https://member.bilibili.com/x2/creative/web/season/section/edit + +*请求方式: POST* + +认证方式: Cookie (SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| csrf | str | CSRF Token (即 Cookies 中 bili_jct) | 必要 | | + +**正文参数 (application/json):** + +根对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| section | obj | 小节信息 | 必要 | | +| sorts | array | 排序列表 | 必要 | | + +`section` 对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| id | num | 小节 ID | 必要 | | +| seasonId | num | 合集 ID | 必要 | | +| title | str | 小节标题 | 必要 | | +| type | num | 1 | 必要 | | + +`sorts` 数组中的对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| id | num | 合集内视频 ID | 必要 | | +| order | num | 排序位置 | 必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | | +| ttl | num | 1 | | + +**示例:** + +假设您已经把请求有效荷载放在 `payload.json` 文件中: + +```json +{ + "section": { + "id": 3954033, + "type": 1, + "seasonId": 3541247, + "title": "正片" + }, + "sorts": [ + { + "id": 77260687, + "sort": 1 + }, + { + "id": 77260688, + "sort": 2 + } + ] +} +``` + +```shell +curl -X POST --url 'https://member.bilibili.com/x2/creative/web/season/section/edit' \ +--url-query 'csrf=xxx' \ +-H 'Content-Type: application/json' \ +--data-binary @payload.json \ +-b 'SESSDATA=xxx; bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +## 编辑合集信息 + +> https://member.bilibili.com/x2/creative/web/season/edit + +*请求方式: POST* + +认证方式: Cookie (SESSDATA) + +注: 也有人工审核 + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| csrf | str | CSRF Token (即 Cookies 中 bili_jct) | 必要 | | + +**正文参数 (application/json):** + +根对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| season | obj | 合集信息 | 必要 | | +| sorts | array | 排序列表 | 必要 | | + +`season` 对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| id | num | 合集 ID | 必要 | | +| title | str | 合集标题 | 必要 | | +| cover | str | 封面图 | 必要 | 从 [上传封面](upload.md#上传封面) 处获取 | +| desc | str | 合集简介 | 不必要 | | +| season_price | num | 0 | 不必要 | 作用尚不明确 | +| isEnd | num | 是否完结 | 不必要 | 0:未完结<br />1:完结 | + +`sorts` 数组中的对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| id | num | 小节 ID | 必要 | | +| sort | num | 排序位置 | 必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | | +| ttl | num | 1 | | + +**示例:** + +假设您已经把请求有效荷载放在 `payload.json` 文件中: + +```json +{ + "season": { + "cover": "https://archive.biliimg.com/bfs/archive/77906db03b1eefac02613de184afad03f7bc58d7.jpg", + "id": 3541327, + "title": "IWILLBEDEL" + }, + "sorts": [ + { + "id": 3954127, + "sort": 1 + } + ] +} +``` + +```shell +curl -X POST --url 'https://member.bilibili.com/x2/creative/web/season/edit' \ +--url-query 'csrf=xxx' \ +-H 'Content-Type: application/json' \ +--data-binary @payload.json \ +-b 'SESSDATA=xxx; bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +## 删除合集 + +> https://member.bilibili.com/x2/creative/web/season/del + +*请求方式: POST* + +认证方式: Cookie (SESSDATA) + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| id | num | 合集 ID | 必要 | | +| csrf | str | CSRF Token (即 Cookie 中 bili_jct) | 必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | | +| ttl | num | 1 | | + +**示例:** + +删除合集 `id=3541327` + +```shell +curl -X POST 'https://member.bilibili.com/x2/creative/web/season/del' \ +--data-urlencode 'id=3541327' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx; bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +## 获取合集小节中的视频 + +> https://member.bilibili.com/x2/creative/web/season/section + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +可以在给合集排序时使用, 可以获取别人的 + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| id | num | 合集 ID | 必要 | | + +**JSON 回复:** + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | ---- | +| section | obj | 小节信息 | | +| episodes | arr | 小节中的视频 | | + +`data` 对象中的 `section` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | ---- | +| id | num | 小节 ID | | +| type | num | 小节类型 | | +| seasonId | num | 合集 ID | | +| title | str | 小结标题 | | +| order | str | 排序编号? | | +| isEnd | num | 是否已完结? | 0: 未完结 | +| state | num | 合集状态? | 0: 正常显示<br />-6: 正在审核 | +| partState | num | 合集分段状态? | 0 | +| rejectReason | str | 合集拒绝原因? | | +| ctime | num | 创建时间 | | +| mtime | num | 修改时间 | | +| epCount | num | 小节视频总数 | | +| cover | num | 合集封面 | | +| show | num | 是否公开? | 1: 公开 | +| has_charging_pay | num | 是否充电付费? | 0: 否 | +| Episodes | null | | | +| has_pugv_pay | num | 是否 PUGV 付费? | 0: 否 | + +`data` 对象中的 `episodes`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | ---- | +| id | num | 合集内视频 ID | | +| title | str | 视频标题 | | +| aid | num | 视频 aid | | +| bvid | str | 视频 bvid | | +| cid | num | 视频 cid | | +| seasonId | num | 合集 ID | | +| sectionId | num | 小节 ID | | +| order | num | 排序编号 | | +| videoTitle | str | 视频标题 | | +| archiveTitle | str | 看起来也是标题 | | +| archiveState | num | 0 | | +| rejectReason | str | 拒绝理由? | | +| state | num | 0 | | +| cover | str | 封面 URL | | +| is_free | num | 是否免费? | 0: 免费 | +| aid_owner | bool | 是否视频所有者 | true:是所有者 | +| charging_pay | num | 充电付费? | 0: 否 | + + +**示例:** + +获取合集小节 176088 的视频 + +```shell +curl -G --url 'https://member.bilibili.com/x2/creative/web/season/section' \ +--url-query 'id=176088' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +会返回全部的,由于很长,这里只保留三个作为例子 + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "section": { + "id": 176088, + "type": 1, + "seasonId": 152812, + "title": "正片", + "order": 1, + "state": 0, + "partState": 0, + "rejectReason": "", + "ctime": 1643250822, + "mtime": 1739466002, + "epCount": 112, + "cover": "http://i1.hdslb.com/bfs/archive/4439a182b142d92a169609e6e14e7217b3e14e0d.jpg", + "has_charging_pay": 0, + "Episodes": null, + "show": 1, + "has_pugv_pay": 0 + }, + "episodes": [ + { + "id": 109100674, + "title": "「开箱评测」三星Note8 EMR2笔对比公版Wacom笔 套娃笔首选 10寸 RK PX30 Wacom 电子书 天喻墨学 M2 M3", + "aid": 113997323963614, + "bvid": "BV14BNfeSE5c", + "cid": 28376042631, + "seasonId": 152812, + "sectionId": 176088, + "order": 1, + "videoTitle": "「开箱评测」三星Note8 EMR2笔对比公版Wacom笔 套娃笔首选 10寸 RK PX30 Wacom 电子书 天喻墨学 M2 M3", + "archiveTitle": "「开箱评测」三星Note8 EMR2笔对比公版Wacom笔 套娃笔首选 10寸 RK PX30 Wacom 电子书 天喻墨学 M2 M3", + "archiveState": 0, + "rejectReason": "", + "state": 0, + "cover": "", + "is_free": 0, + "aid_owner": true, + "charging_pay": 0, + "member_first": 0, + "pugv_pay": 0 + }, + { + "id": 108733886, + "title": "「开箱评测」拆解 椭圆形的第三方AirTag GRTSZ S2 Tag", + "aid": 113982291576104, + "bvid": "BV1YyNvetEbX", + "cid": 28325121446, + "seasonId": 152812, + "sectionId": 176088, + "order": 2, + "videoTitle": "「开箱评测」拆解 椭圆形的第三方AirTag GRTSZ S2 Tag", + "archiveTitle": "「开箱评测」拆解 椭圆形的第三方AirTag GRTSZ S2 Tag", + "archiveState": 0, + "rejectReason": "", + "state": 0, + "cover": "", + "is_free": 0, + "aid_owner": true, + "charging_pay": 0, + "member_first": 0, + "pugv_pay": 0 + }, + { + "id": 106045797, + "title": "「开箱评测」这帕姆怎么射不出来呢! 星穹铁道 KFC联动 财神帕姆 太可爱了", + "aid": 113892936122993, + "bvid": "BV1ZFFKeTEkr", + "cid": 28087484764, + "seasonId": 152812, + "sectionId": 176088, + "order": 3, + "videoTitle": "「开箱评测」这帕姆怎么射不出来呢! 星穹铁道 KFC联动 财神帕姆 太可爱了", + "archiveTitle": "「开箱评测」这帕姆怎么射不出来呢! 星穹铁道 KFC联动 财神帕姆 太可爱了", + "archiveState": 0, + "rejectReason": "", + "state": 0, + "cover": "", + "is_free": 0, + "aid_owner": true, + "charging_pay": 0, + "member_first": 0, + "pugv_pay": 0 + } + ] + } +} +``` + +</details> + +## 编辑投稿视频合集 + +> https://member.bilibili.com/x2/creative/web/season/switch +*请求方式: POST* + +认证方式:Cookie(SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| t | num | 当前时间 | 非必要 | UNIX 毫秒时间戳 | +| csrf | str | CSRF Token (位于 Cookie 中 bili_jct) | 必要 | | + +**正文参数(application/json):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| aid | num | 视频 ID | 必要 | | +| season_id | num | null | 合集 ID | 必要 | null 表示从合集中移除 | +| section_id | num | null | 小节 ID | 必要 | null 表示从小节中移除 | +| title | str | 视频标题 | 必要 | | +| csrf | str | CSRF Token (位于 Cookie 中 bili_jct) | 非必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----- | +| season_id | num | null | | | +| section_id | num | null | | | +| title | str | 标题 | | +| aid | num | aid | | +| csrf | num | CSRF Token (位于 Cookie 中 bili_jct) | | + +**示例:** + +```shell +curl -X POST "https://member.bilibili.com/x2/creative/web/season/switch" \ +--url-query "csrf=xxxxxxxxxxxx" \ +-H "Content-Type: application/json" \ +--data '{ + "aid": 123456, + "season_id": 654321, + "section_id": 789012, + "title": "新视频标题" +}' \ +-b "SESSDATA=xxxxxxxxxxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "season_id": null, + "section_id": null, + "title": "标题", + "aid": 123, + "csrf": "eqweeqw" +} +``` + +</details> + +## aid反查合集id + +> https://member.bilibili.com/x2/creative/web/season/aid +*请求方式: GET* + +认证方式:Cookie(SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| id | num | 视频 aid | 必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----- | +| code | num | 返回值 | 0: 成功<br />其他: 失败 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + + + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| season | obj | 合集信息 | | + + +`season` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| id | num | 合集 ID | | +| title | str | 合集标题 | | +| cover | str | 合集封面 URL | | +| desc | str | 合集描述 | | +| isEnd | num | 是否已完结 | 0: 未完结<br />1: 已完结 | +| mid | num | 合集作者 ID | | +| isAct | num | 是否为活动合集 | 0: 否<br />1: 是 | +| is_pay | num | 是否付费 | 0: 否<br />1: 是 | +| state | num | 合集状态 | 0: 正常显示<br />-6: 正在审核 | +| partState | num | 合集分段状态 | 0: 正常 | +| signState | num | 合集签名状态 | 0: 正常 | +| rejectReason | str | 合集拒绝原因 | | +| ctime | num | 创建时间 | UNIX 时间戳 | +| mtime | num | 修改时间 | UNIX 时间戳 | +| no_section | num | 是否设小节 | 1: 不设小节 | +| forbid | num | 合集是否禁止 | 0: 否<br />1: 是 | +| protocol_id | str | 协议 ID | | +| ep_num | num | 视频数量 | | +| season_price | num | 合集价格 | 0: 免费 | +| is_opened | num | 是否公开 | 1: 公开<br />0: 不公开 | +| has_charging_pay | num | 是否充电付费 | 0: 否<br />1: 是 | +| has_pugv_pay | num | 是否 PUGV 付费 | 0: 否<br />1: 是 | + +**示例:** + +```shell +curl -G "https://member.bilibili.com/x2/creative/web/season/aid" \ +--data-urlencode "id=123456" \ +-b "SESSDATA=xxxxxxxxxxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "id": 12, + "title": "合集标题", + "desc": "", + "cover": "", + "isEnd": 0, + "mid": 123, + "isAct": 0, + "is_pay": 0, + "state": 0, + "partState": 0, + "signState": 0, + "rejectReason": "", + "ctime": 1667232000, + "mtime": 1667232000, + "no_section": 1, + "forbid": 0, + "protocol_id": "", + "ep_num": 0, + "season_price": 0, + "is_opened": 1, + "has_charging_pay": 0, + "has_pugv_pay": 0 + } +} +``` + +</details> \ No newline at end of file diff --git a/bb-api-collect/docs/creativecenter/statistics&data.md b/bb-api-collect/docs/creativecenter/statistics&data.md new file mode 100644 index 0000000000..bfaef6fb6a --- /dev/null +++ b/bb-api-collect/docs/creativecenter/statistics&data.md @@ -0,0 +1,890 @@ +# 统计与数据 + +统计与数据次日中午12刷新 + +## UP主视频状态数据 + +> https://member.bilibili.com/x/web/index/stat + +*请求方式:GET* + +认证方式:仅可Cookie(SESSDATA) + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | 作用尚不明确 | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ---- | -------------- | ---- | +| inc_coin | num | 新增投币数 | | +| inc_elec | num | 新增充电数 | | +| inc_fav | num | 新增收藏数 | | +| inc_like | num | 新增点赞数 | | +| inc_share | num | 新增分享数 | | +| incr_click | num | 新增播放数 | | +| incr_dm | num | 新增弹幕数 | | +| incr_fans | num | 新增粉丝数 | | +| incr_reply | num | 新增评论数 | | +| total_click | num | 总计播放数 | | +| total_coin | num | 总计投币数 | | +| total_dm | num | 总计弹幕数 | | +| total_elec | num | 总计充电数 | | +| total_fans | num | 总计粉丝数 | | +| total_fav | num | 总计收藏数 | | +| total_like | num | 总计点赞数 | | +| total_reply | num | 总计评论数 | | +| total_share | num | 总计分享数 | | + +**示例:** + +```shell +curl 'https://member.bilibili.com/x/web/index/stat' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "inc_coin": 0, + "inc_elec": 0, + "inc_fav": 0, + "inc_like": 0, + "inc_share": 0, + "incr_click": 0, + "incr_dm": 0, + "incr_fans": 1, + "incr_reply": 0, + "total_click": 9, + "total_coin": 1, + "total_dm": 0, + "total_elec": 0, + "total_fans": 29, + "total_fav": 1, + "total_like": 1, + "total_reply": 0, + "total_share": 0 + } +} +``` + +</details> + +## 新版UP主视频数据比较 + +> https://member.bilibili.com/x/web/data/archive_diagnose/compare + +*请求方式:GET* + +认证方式:仅可Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------ | ------ | -------------- | +| t | num | 时间戳 | 可选 | | +| size | num | 比较最近的N条视频 | 可选,默认5 | 似乎没有最大值,或者最大值很大 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | 作用尚不明确 | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ---------- | ---- | +| list | list | 最近的视频 | | + +`data`中的`list`项: +> [!TIP] +> 这里的数字一般都是百分比,小数点后保留两位,100代表1%,10000代表100% + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ---------- | ---- | +| aid | num | av号 | | +| bvid | str | bv号 | | +| cover | str | 封面url | | +|title| str|标题| +|pubtime|num|发布时间| +|duration|num|视频长度(秒)| +|play|num|播放数|| +|vt|num|未知 +|like|num|点赞数 +|comment|num|评论数 +|dm|num|弹幕数 +|fav|num|收藏数| +|coin|num|投币数 +|share|num|分享数 +|full_play_ratio|num|完播比,用户平均在百分之多少退出 +|play_viewer_rate|num|游客播放数,这个视频有多少是游客播放 +|active_fans_rate|num|粉丝观看率,多少粉丝看了这个视频 +|active_fans_med|num|? +|tm_rate|num|封标点击率 +|tm_rate_med|num|你自己平均封标点击率 +|tm_fan_simi_rate_med|num|同类up粉丝封标点击率 +|tm_viewer_simi_rate_med|num|同类up游客封标点击率 +|tm_fan_rate|num|粉丝封标点击率 +|tm_viewer_rate|num|游客封标点击率 +|tm_pass_rate|num|封标点击率超过n%同类稿件 +|tm_fan_pass_rate|num|粉丝封标点击率超过n%同类稿件 +|tm_viewer_pass_rate|num|游客封标点击率超过n%同类稿件 +|crash_rate|num|3秒退出率 +|crash_rate_med|num|? +|crash_fan_simi_rate_med|num|同类up粉丝3秒退出率 +|crash_viewer_simi_rate_med|num|同类up游客3秒退出率 +|crash_fan_rate|num|粉丝3秒退出率 +|crash_viewer_rate|num|游客3秒退出率 +|interact_rate|num|互动率 +|interact_rate_med|num| +|interact_fan_simi_rate_med|num|同类up粉丝互动率 +|interact_viewer_simi_rate_med|num|同类up游客互动率 +|interact_fan_rate|num|粉丝互动率 +|interact_viewer_rate|num|游客互动率 +|avg_play_time|num|平均播放时间|注意:此字段总是0,可能b站正在写代码,或者和播放量改播放时长有关? +|total_new_attention_cnt|num|涨粉 +|play_trans_fan_rate|num|播转粉率 +|play_trans_fan_rate_med|num|其他up平均播转粉率 + +**示例:** + +```shell +curl 'https://member.bilibili.com/x/web/data/archive_diagnose/compare?size=10' \ +-b 'SESSDATA=xxx' +``` + +## UP主专栏状态数据 + +> https://member.bilibili.com/x/web/data/article + +*请求方式:GET* + +认证方式:仅可Cookie(SESSDATA) + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | 作用尚不明确 | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ---------- | ---- | +| view | num | 总计阅读数 | | +| reply | num | 总计评论数 | | +| like | num | 总计点赞数 | | +| coin | num | 总计投币数 | | +| fav | num | 总计收藏数 | | +| share | num | 总计分享数 | | +| incr_view | num | 新增阅读数 | | +| incr_reply | num | 新增评论数 | | +| incr_like | num | 新增点赞数 | | +| incr_coin | num | 新增投币数 | | +| incr_fav | num | 新增收藏数 | | +| incr_share | num | 新增分享数 | | + +**示例:** + +```shell +curl 'https://member.bilibili.com/x/web/data/article' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "view": 290, + "reply": 17, + "like": 34, + "coin": 9, + "fav": 15, + "share": 7, + "incr_view": 6, + "incr_reply": 0, + "incr_like": 0, + "incr_coin": 0, + "incr_fav": 0, + "incr_share": 0 + } +} +``` + +</details> + +## 视频数据增量趋势 + +> https://member.bilibili.com/x/web/data/pandect + +*请求方式:GET* + +认证方式:仅可Cookie(SESSDATA) + +数据为前30天 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------ | ------ | -------------- | +| type | num | 目标数据类型 | 必要 | 类型代码见下表 | + +类型代码`type`: + +| 代码 | 含义 | +| ---- | ---- | +| 1 | 播放 | +| 2 | 弹幕 | +| 3 | 评论 | +| 4 | 分享 | +| 5 | 投币 | +| 6 | 收藏 | +| 7 | 充电 | +| 8 | 点赞 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | 作用尚不明确 | +| data | array | 趋势列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------------- | -------- | +| 0 | obj | 1天前的数据 | | +| n | obj | (n+1)天前的数据 | | +| …… | obj | …… | …… | +| 29 | obj | 30天前的数据 | 最后一条 | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | -------- | -------------------- | +| date_key | num | 对应时间 | 时间戳 前一天的8:00 | +| total_inc | num | 增加数量 | 意义为数据类型决定 | + +**示例:** + +查询30天前的视频播放增量趋势,可知`2020-04-05`的播放增量为`46`,`2020-04-04`的播放增量为`58` + +```shell +curl -G 'https://member.bilibili.com/x/web/data/pandect' \ +--data-urlencode 'type=1' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [{ + "date_key": 1586044800, + "total_inc": 46 + }, { + "date_key": 1585958400, + "total_inc": 58 + }, { + "date_key": 1585872000, + "total_inc": 81 + }, { + "date_key": 1585785600, + "total_inc": 90 + }, { + "date_key": 1585699200, + "total_inc": 62 + }, { + "date_key": 1585612800, + "total_inc": 70 + }, + ………… + ] +} +``` + +</details> + +## 专栏数据增量趋势 + +> https://member.bilibili.com/x/web/data/article/thirty + +*请求方式:GET* + +认证方式:仅可Cookie(SESSDATA) + +数据为前30天 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------ | ------ | -------------- | +| type | num | 目标数据类型 | 必要 | 类型代码见下表 | + +类型代码`type`: + +| 代码 | 含义 | +| ---- | ---- | +| 1 | 阅读 | +| 2 | 评论 | +| 3 | 分享 | +| 4 | 投币 | +| 5 | 收藏 | +| 6 | 点赞 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | 作用尚不明确 | +| data | array | 趋势列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------------ | -------- | +| 0 | obj | 30天前的数据 | | +| n | obj | (30-n)天前的数据 | | +| …… | obj | …… | …… | +| 29 | obj | 1天前的数据 | 最后一条 | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | -------- | -------------------- | +| date_key | num | 对应时间 | 时间戳 前一天的8:00 | +| total_inc | num | 增加数量 | 意义为数据类型决定 | + +**示例:** + +查询30天前的文章阅读增量趋势,可知`2020-04-05`的阅读增量为`6`,`2020-04-04`的阅读增量为`6` + +```shell +curl -G 'https://member.bilibili.com/x/web/data/article/thirty' \ +--data-urlencode 'type=1' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + ………… + { + "date_key": 1585699200, + "total_inc": 6 + }, { + "date_key": 1585785600, + "total_inc": 6 + }, { + "date_key": 1585872000, + "total_inc": 4 + }, { + "date_key": 1585958400, + "total_inc": 6 + }, { + "date_key": 1586044800, + "total_inc": 6 + }] +} +``` + +</details> + +## 稿件操作来源占比情况 + +> https://member.bilibili.com/x/web/data/survey + +*请求方式:GET* + +认证方式:仅可Cookie(SESSDATA) + +数据为上一天的 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------ | ------ | -------------- | +| type | num | 目标数据类型 | 必要 | 类型代码见下表 | + +类型代码`type`: + +| 代码 | 含义 | +| ---- | ---- | +| 1 | 播放 | +| 2 | 弹幕 | +| 3 | 评论 | +| 4 | 分享 | +| 5 | 投币 | +| 6 | 收藏 | +| 7 | 充电 | +| 8 | 点赞 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | 作用尚不明确 | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ------------ | ------------ | +| {YYYYMMDD} | obj | 上一天的情况 | 字段名为日期 | + +`data`中的`{YYYYMMDD}`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ------ | ------------ | ---- | +| arc_inc | array | 稿件情况 | | +| total_inc | num | 总计增长情况 | | +| type_rank | obj | 分区排名情况 | | + +`{YYYYMMDD}`中的`arc_inc`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---- | +| 0 | obj | 稿件1 | | +| n | obj | 稿件(n+1) | | +| …… | obj | …… | …… | + +`{YYYYMMDD}`中的`arc_inc`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | -------------- | ------------ | +| aid | num | 稿件avid | | +| bvid | str | 稿件bvid | | +| daytime | num | 统计时间 | 时间戳 | +| incr | num | 稿件增长情况数 | | +| interactive | num | 0 | 作用尚不明确 | +| ptime | num | 稿件发布时间 | 时间戳 | +| title | str | 稿件标题 | | + +`{YYYYMMDD}`中的`type_rank`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------- | ---- | +| {分区名} | num | 该排名数 | | +| …… | num | …… | …… | + +**示例:** + +查询我的稿件来源占比情况 + +```shell +curl -G 'https://member.bilibili.com/x/web/data/survey' \ +--data-urlencode 'type=1' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "20200418": { + "arc_inc": [{ + "aid": 94916552, + "bvid": "BV1ZE411K7ux", + "incr": 18, + "title": "【8-bit】影 流 之 主(爱河)", + "daytime": 1587155030, + "ptime": 1583760165, + "interactive": 0 + }, { + "aid": 98948772, + "bvid": "BV1n741127LD", + "incr": 14, + "title": "【特斯拉线圈】组装迷你SSTC", + "daytime": 1587155030, + "ptime": 1585054436, + "interactive": 0 + }, { + "aid": 37294890, + "bvid": "BV1kt411D7yW", + "incr": 9, + "title": "【病毒】彩虹猫可以调速还带有计时器 MEMZ重构升级版", + "daytime": 1587155030, + "ptime": 1543775696, + "interactive": 0 + }, + ………… + ], + "total_inc": 55, + "type_rank": { + "生活": 1392, + "科技": 1597, + "音乐": 1058 + } + } + } +} +``` + +</details> + +## 播放来源占比情况(平台及方式) + +> https://member.bilibili.com/x/web/data/playsource + +*请求方式:GET* + +认证方式:仅可Cookie(SESSDATA) + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | 作用尚不明确 | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | ------------ | ---- | +| page_source | obj | 播放方式情况 | | +| play_proportion | obj | 播放平台情况 | | + +`data`中的`page_source`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ------------------------- | ---- | +| dynamic | num | 通过动态 | | +| other | num | 其他方式 | | +| related_video | num | 通过推荐列表 | | +| search | num | 通过搜索 | | +| space | num | 空间列表播放 | | +| tenma | num | 天马(APP推荐信息流)来源 | | + +`data`中的`play_proportion`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ------------ | ---- | +| android | num | 安卓端 | | +| h5 | num | 移动端h5页面 | | +| ios | num | ios端 | | +| out | num | 站外 | | +| pc | num | 电脑版网页 | | + +**示例:** + +```shell +curl 'https://member.bilibili.com/x/web/data/playsource' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "play_proportion": { + "android": 6060, + "h5": 410, + "ios": 1325, + "out": 0, + "pc": 2137 + }, + "page_source": { + "dynamic": 173, + "other": 1440, + "related_video": 1813, + "search": 1980, + "space": 501, + "tenma": 4087 + } + } +} +``` + +</details> + +## 播放分布情况(粉丝与路人) + +> https://member.bilibili.com/x/web/data/base + +*请求方式:GET* + +认证方式:仅可Cookie(SESSDATA) + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | 作用尚不明确 | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ------------ | ---- | +| period | obj | 提示信息 | | +| viewer_area | obj | 播放地区情况 | | +| viewer_base | obj | 播放数据情况 | | + +`data`中的`period`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ---- | ---- | +| module_one | str | ??? | | +| module_two | str | ??? | | +| module_three | str | ??? | | +| module_four | str | ??? | | + +`data`中的`viewer_area`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ---------------- | ---- | +| fan | obj | 粉丝播放地区情况 | | +| not_fan | obj | 路人播放地区情况 | | + +`viewer_area`中的`fan`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------------ | ---------------- | +| {行政区名} | num | 该地区的粉丝播放量 | 字段名为行政区名 | +| …… | num | …… | …… | + +`viewer_area`中的`not_fan`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------------ | ---------------- | +| {行政区名} | num | 该地区的路人播放量 | 字段名为行政区名 | +| …… | num | …… | …… | + +`data`中的`viewer_base`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ---------------- | ---- | +| fan | obj | 粉丝播放数据情况 | | +| not_fan | obj | 路人播放数据情况 | | + +`viewer_base`中的`fan`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | ------------------ | ---- | +| male | num | 男性粉丝播放数 | | +| female | num | 女性粉丝播放数 | | +| age_one | num | 0-16岁粉丝播放数 | | +| age_two | num | 16-25岁粉丝播放数 | | +| age_three | num | 25-40岁粉丝播放数 | | +| age_four | num | 40+岁粉丝播放数 | | +| plat_pc | num | pc网页端粉丝播放数 | | +| plat_h5 | num | 移动h5端粉丝播放数 | | +| plat_out | num | 站外端粉丝播放数 | | +| plat_ios | num | ios端粉丝播放数 | | +| plat_android | num | 安卓端粉丝播放数 | | +| plat_other_app | num | 其他粉丝播放数 | | + +`viewer_base`中的`not_fan`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | ------------------ | ---- | +| male | num | 男性路人播放数 | | +| female | num | 女性路人播放数 | | +| age_one | num | 0-16岁路人播放数 | | +| age_two | num | 16-25岁路人播放数 | | +| age_three | num | 25-40岁路人播放数 | | +| age_four | num | 40+岁路人播放数 | | +| plat_pc | num | pc网页端路人播放数 | | +| plat_h5 | num | 移动h5端路人播放数 | | +| plat_out | num | 站外端路人播放数 | | +| plat_ios | num | ios端路人播放数 | | +| plat_android | num | 安卓端路人播放数 | | +| plat_other_app | num | 其他路人播放数 | | + +**示例:** + +```shell +curl 'https://member.bilibili.com/x/web/data/base' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "period": { + "module_one": "各维度每日12:00 a.m. 更新前一日数据", + "module_two": "每日12:00 a.m. 更新前一日数据", + "module_three": "每周二12:00 a.m. 更新前一周数据", + "module_four": "各维度每日12:00 a.m. 更新前一日数据" + }, + "viewer_area": { + "fan": { + "上海": 7, + "中国台湾": 2, + "云南": 6, + "内蒙古": 8, + "北京": 14, + "吉林": 4, + "四川": 4, + "天津": 11, + "宁夏": 1, + "安徽": 8, + "山东": 18, + "山西": 10, + "广东": 50, + "广西": 7, + "新疆": 2, + "江苏": 17, + "江西": 6, + "河北": 13, + "河南": 13, + "浙江": 20, + "海南": 1, + "湖北": 13, + "湖南": 13, + "甘肃": 4, + "福建": 10, + "贵州": 4, + "辽宁": 9, + "重庆": 5, + "陕西": 93, + "香港特别行政区": 1, + "黑龙江": 12 + }, + "not_fan": { + "上海": 28, + "中国台湾": 3, + "云南": 22, + "内蒙古": 15, + "北京": 53, + "吉林": 20, + "四川": 60, + "天津": 18, + "宁夏": 7, + "安徽": 43, + "山东": 81, + "山西": 31, + "广东": 176, + "广西": 81, + "新疆": 11, + "江苏": 93, + "江西": 26, + "河北": 50, + "河南": 84, + "浙江": 97, + "海南": 10, + "湖北": 43, + "湖南": 43, + "甘肃": 14, + "福建": 54, + "西藏": 1, + "贵州": 16, + "辽宁": 47, + "重庆": 31, + "陕西": 102, + "青海": 2, + "香港特别行政区": 4, + "黑龙江": 25 + } + }, + "viewer_base": { + "fan": { + "male": 153, + "female": 24, + "age_one": 91, + "age_two": 174, + "age_three": 77, + "age_four": 53, + "plat_pc": 12072, + "plat_h5": 186, + "plat_out": 0, + "plat_ios": 23453, + "plat_android": 87387, + "plat_other_app": 1631 + }, + "not_fan": { + "male": 462, + "female": 72, + "age_one": 425, + "age_two": 445, + "age_three": 360, + "age_four": 188, + "plat_pc": 64760, + "plat_h5": 660, + "plat_out": 1, + "plat_ios": 111259, + "plat_android": 467767, + "plat_other_app": 3408 + } + } + } +} +``` + +</details> diff --git a/bb-api-collect/docs/creativecenter/upload.md b/bb-api-collect/docs/creativecenter/upload.md new file mode 100644 index 0000000000..2dd94daa79 --- /dev/null +++ b/bb-api-collect/docs/creativecenter/upload.md @@ -0,0 +1,1927 @@ +# 投稿 + +## 上传封面 + +> https://member.bilibili.com/x/vu/web/cover/up + +*请求方式: POST* + +认证方式:Cookie(SESSDATA) + +注: 目前看来上传的图片似乎不会自动删除 + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| ts | num | 当前时间 | 不必要 | UNIX 毫秒时间戳 | + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| csrf | str | CSRF Token (位于 Cookie 中 bili_jct) | 必要 | | +| cover | base64 | 视频封面 | 必要 | 经过 base64 编码的图片数据 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----- | +| code | num | 返回值 | 0: 成功<br />-400: 请求错误<br />-111: csrf 校验失败<br />-101: 账号未登录 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| url | str | 封面 URL | | + +**示例:** + +假设已经把需要发送的数据进行编码存放在文件 `./b64` 中: + +```text +csrf=xxxxxxxxxxxx&cover=data%3Aimage%2Fjpeg%3Bbase64%2C%2F9j%2F4AAQSkZJRgABA... +``` + +发送请求: + +```shell +curl -X POST --url "https://member.bilibili.com/x/vu/web/cover/up" \ +--url-query "ts=$(date +%s%3N)" \ +--data-binary @b64 \ +-b "SESSDATA=xxxxxx; bili_jct=xxxxxx" +``` + +JavaScript (Node.js) 请求[示例](https://gist.github.com/SessionHu/5e47a3a1a351ac5486c87e3d63930e7a) + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "url": "https://archive.biliimg.com/bfs/archive/77906db03b1eefac02613de184afad03f7bc58d7.jpg" + } +} +``` + +</details> + +## 获取上传模板列表 + +> https://member.bilibili.com/x/vupre/web/tpls + +*请求方式: GET* + +认证方式:Cookie(SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| t | num | 当前时间 | 非必要 | UNIX 毫秒时间戳 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----- | +| code | num | 返回值 | 0: 成功<br />其他: 失败 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | array | 模板列表 | | + + + +`data` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| tid | num | 模板 ID | | +| name | str | 模板名称 | | +| typeid | num | 分区 ID | | +| title | str | 标题 | | +| tags | str | 标签 | | +| description | str | 描述 | | +| copyright | num | 版权类型 | 1: 自制<br />2: 转载 | +| attribute | num | 属性 | 0 或其他 | +| is_default | num | 是否默认 | 0: 否<br />1: 是 | + +**示例:** + +```shell +curl -G "https://member.bilibili.com/x/vupre/web/tpls" \ +-b "SESSDATA=xxxxxxxxxxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "tid": 12, + "name": "直播录像", + "typeid": 173, + "title": " 标题", + "tags": "可爱", + "description": "描述", + "copyright": 1, + "attribute": 0, + "is_default": 0 + }, + ] +} +``` + +</details> + +## 编辑上传模板 + +> https://member.bilibili.com/x/vupre/web/tpl/update + +*请求方式: POST* + +认证方式:Cookie(SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| t | num | 当前时间 | 非必要 | UNIX 毫秒时间戳 | + +**正文参数(application/json):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| tid | num | 模板 ID | 必要 | | +| name | str | 模板名称 | 非必要 | | +| title | str | 标题 | 非必要 | | +| keywords | str | 标签 | 非必要 | 多个标签用 `,` 分隔 | +| description | str | 描述 | 非必要 | | +| typeid | num | 分区 ID | 非必要 | | +| arctype | str | 版权类型 | 非必要 | "Original": 自制<br />"Copy": 转载 | +| is_default | num | 是否默认 | 非必要 | 0: 否<br />1: 是 | +| csrf | str | CSRF Token (位于 Cookie 中 bili_jct) | 必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----- | +| code | num | 返回值 | 0: 成功<br />其他: 失败 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | + +**示例:** + +```shell +curl -X POST "https://member.bilibili.com/x/vupre/web/tpl/update" \ +--url-query "t=$(date +%s%3N)" \ +-H "Content-Type: application/json" \ +--data '{ + "tid": 12, + "name": "新模板名称", + "title": "新标题", + "keywords": "标签1,标签2", + "description": "新描述", + "typeid": 173, + "arctype": "Original", + "is_default": 1, + "csrf": "xxxxxxxxxxxx" +}' \ +-b "SESSDATA=xxxxxxxxxxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +## 查询话题 + +> https://member.bilibili.com/x/vupre/web/topic/type + +*请求方式: GET* + +认证方式:Cookie(SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | -------- | ------ | ---- | +| type_id | num | 分区 ID | 非必要 | | +| pn | num | 页码 | 必要 | 从 0 开始 | +| ps | num | 每页个数 | 必要 | | +| title | str | 视频标题 | 非必要 | | +| t | num | 当前时间 | 非必要 | UNIX 毫秒时间戳 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----- | +| code | num | 返回值 | 0: 成功<br />其他: 失败 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | array | 话题列表 | | + + +`data` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| topic_id | num | 话题 ID | | +| topic_name | str | 话题名称 | | +| description | str | 话题描述 | | +| mission_id | num | 任务 ID | | +| activity_text | str | 活动文本 | | +| activity_description | str | 活动描述 | | + +**示例:** + +```shell +curl -G "https://member.bilibili.com/x/vupre/web/topic/type" \ +--data-urlencode "pn=0" \ +--data-urlencode "ps=20" \ +-b "SESSDATA=xxxxxxxxxxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "topics": [ + { + "topic_id": 1245317, + "topic_name": "疯狂打游戏", + "description": "疯狂于游戏的世界吧!愿你在这场虚拟的战斗中展现出你非凡的智慧与勇气,让每一个夜晚都充满了激情与荣耀!", + "mission_id": 1742462, + "activity_text": "有奖活动", + "activity_description": "@神魂の魇 发起" + } + ], + "tags": null, + "maxpage": 200, + "request_id": "123" + } +} +``` + +</details> + +## 话题搜索 + +> https://member.bilibili.com/x/vupre/web/topic/search + +*请求方式: GET* + +认证方式:Cookie(SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | -------- | ------ | ---- | +| page_size | num | 每页个数 | 非必要 | | +| offset | num | 个数偏移 | 非必要 | 并非页数 | +| keywords | str | 关键字 | 非必要 | | +| t | num | 当前时间 | 非必要 | UNIX 毫秒时间戳 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----- | +| code | num | 返回值 | 0: 成功<br />其他: 失败 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + + + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| result | obj | 搜索结果 | | + + + +`result` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| has_create_jurisdiction | bool | ? | | +| is_new_topic | bool | 是否为新话题? | | +| tips | str | 提示信息 | | +| page_info | obj | 分页信息 | | +| topics | array | 话题列表 | | + + + +`page_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| has_more | bool | 是否有更多 | | +| offset | num | 偏移量 | | +| page_number | num | 页码 | | + + + +`topics`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| act_protocol | str | ? | | +| activity_sign | str | ? | | +| description | str | 话题描述 | | +| id | num | 话题 ID | | +| mission_id | num | 任务 ID | | +| name | str | 话题名称 | | +| state | num | 状态? | | +| uname | str | ? | | + +**示例:** + +```shell +curl -G "https://member.bilibili.com/x/vupre/web/topic/search" \ +--data-urlencode "page_size=20" \ +--data-urlencode "offset=0" \ +--data-urlencode "keywords=example" \ +-b "SESSDATA=xxxxxxxxxxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "result": { + "topics": [ + { + "id": 1200265, + "name": "巴黎最前线", + "uname": "", + "state": 0, + "description": "巴黎体育盛会前线速递!", + "mission_id": 0, + "activity_sign": "", + "act_protocol": "" + } + ], + "page_info": { + "page_num": 0, + "offset": 1, + "has_more": true + }, + "is_new_topic": false, + "has_create_jurisdiction": true, + "tips": "该话题是UP主活动相关话题,您在话题下的稿件信息可能会被提供给发起话题的UP主,并可能被UP主用于二次创作" + } + } +} +``` + +</details> + +## 标签可用性检查 + +> https://member.bilibili.com/x/vupre/web/topic/tag/check + +*请求方式: GET* + +认证方式:Cookie(SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| tag | str | 需要检查的标签 | 必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----- | +| code | num | 返回值 | 0: 成功<br />其他: 失败 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + + + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| code | num | 标签状态 | 0: 可用<br />其他: 不可用 | +| content | str | 错误返回 | | + +**示例:** + +```shell +curl -G "https://member.bilibili.com/x/vupre/web/topic/tag/check" \ +--data-urlencode "tag=example_tag" \ +-b "SESSDATA=xxxxxxxxxxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "code": 0, + "content": "" + } +} +``` + +```json +{ + "code": 16025, + "message": "tag已经被封印了~", + "ttl": 1, + "data": { + "code": 1, + "content": "服务器错误" + } +} +``` + +</details> + +## 获取简介相关信息 + +> https://member.bilibili.com/x/vupre/web/archive/desc/format + +*请求方式: GET* + +认证方式:Cookie(SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | -------- | ------ | ---- | +| typeid | num | 分区 ID | 必要 | | +| copyright | num | 版权类型 | 必要 | 1:自制<br/>2:转载 | +| t | num | 当前时间 | 非必要 | UNIX 毫秒时间戳 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----- | +| code | num | 返回值 | 0: 成功<br />其他: 失败 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | null | 信息本体 | | + +注:某个时间点后,没有发现 data 为 null 的情况了,过去为 null 时简介上限250字 + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| typeid | num | 分区 ID | | +| id | num | ID | | +| lang | num | 未知 | | +| copyright | num | 版权类型| 1:自制<br/>2:转载 | +| components | str | 简介输入框提示文字 | JSON 字符串 | + +`components` 示例: +`'[{"name":"相关游戏","index":1,"type":"text","required":"1","box":"请输入本视频所涉及的游戏名称,以顿号分隔,例:英雄联盟、塞尔达传说、刺客信条"},{"name":"简介补充","index":2,"type":"textarea","required":"1","box":""}]'` + +**示例:** + +```shell +curl -G "https://member.bilibili.com/x/vupre/web/archive/desc/format" \ +--data-urlencode "typeid=65" \ +--data-urlencode "copyright=1" \ +-b "SESSDATA=xxxxxxxxxxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "typeid": 65, + "id": 1, + "lang": 0, + "copyright": 1, + "components": "[{\"name\":\"相关游戏\",\"index\":1,\"type\":\"text\",\"required\":\"1\",\"box\":\"请输入本视频所涉及的游戏名称,以顿号分隔,例:英雄联盟、塞尔达传说、刺客信条\"},{\"name\":\"简介补充\",\"index\":2,\"type\":\"textarea\",\"required\":\"1\",\"box\":\"\"}]" + } +} +``` + +</details> + +## 获取上传线路 + +> https://member.bilibili.com/preupload?r=probe + +*请求方式: GET* + +认证方式:无 + +**URL参数:** + +无 + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----- | +| OK | num | 返回值 | 1: 成功<br />其他: 失败 | +| lines | array | 上传线路列表 | | +| probe | obj | 未知 | | + +probe 中的对象: +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | -------- | ----- | +| post | float | 未知 | 固定0.1 | + +lines 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | -------- | ----- | +| os | str | 操作系统 | | +| query | str | 查询参数 | | +| probe_url | str | 探测 URL | | + +**示例:** + +```shell +curl -G "https://member.bilibili.com/preupload?r=probe" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "OK": 1, + "lines": [ + { + "os": "upos", + "query": "probe_version=20221109&upcdn=tx&zone=cs", + "probe_url": "//upos-cs-upcdntx.bilivideo.com/OK" + }, + { + "os": "upos", + "query": "probe_version=20221109&upcdn=bldsa&zone=cs", + "probe_url": "//upos-cs-upcdnbldsa.bilivideo.com/OK" + }, + { + "os": "upos", + "query": "probe_version=20221109&upcdn=bda2&zone=cs", + "probe_url": "//upos-cs-upcdnbda2.bilivideo.com/OK" + } + ], + "probe": { + "post": 0.1 + } +} +``` + +</details> + +## 预测稿件类型 + +> https://member.bilibili.com/x/vupre/web/archive/types/predict + +*请求方式: POST* + +认证方式: Cookie(SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| ts | num | 当前时间 | 不必要 | UNIX 毫秒时间戳 | +| csrf | str | CSRF Token (位于 Cookie 中 bili_jct) | 必要 | | + +**正文参数(multipart/form-data):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| filename | str | 视频文件名 | 必要 | 从视频上传接口获取, 无后缀名, 可为空 | +| title | str | 视频标题 | 不必要 || +| upload_id | str | 上传 ID | 不必要 | 如 `616368979_1723455540876_8794` | + +**JSON回复:** + +根对象: + +|字段|类型|内容|备注| +|---|-|-|---| +|code|num|返回值|0: 成功<br />-400: 请求错误<br />-111: csrf 校验失败<br />-101: 账号未登录| +|message|str|错误信息|默认为 0| +|ttl|num|1|| +|data|array|信息本体|| + +`data` 数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| 0 | obj | 视频类型 1 | | +| 1 | obj | 视频类型 2 | | +| …… | obj | …… | | +| n | obj | 视频类型 (n+1) | | + +`data` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| id | num | 子分区 ID | | +| parent | num | 总分区 ID | | +| parent_name | str | 总分区名称 | | +| name | str | 子分区名称 | | +| description | str | 子分区描述 | | +| desc | str | 子分区描述 | 同 `description` | +| intro_original | str | 原创简介说明 | | +| intro_copy | str | 转载简介说明 | | +| notice | str | 注意事项 | | +| copy_right | num | 版权信息? | 0 | +| show | bool | 是否显示? | true | +| rank | num | 排序权重? | | +| max_video_count | num | 最大视频数量? | | +| request_id | str | 空 | | +| human_type | obj\|null | 新分区ID,好像除第一个之外都是null | + +`human_type` 参数 +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| id | num | 新分区id | 可在 [获取新分区ID](#获取新分区ID) 找到对应名称 | + +**示例:** + +```shell +curl -X POST --url 'https://member.bilibili.com/x/vupre/web/archive/types/predict' \ +--url-query 'csrf=d51eadf05ba3bc6c5f76def7fbcc0185' \ +--data-urlencode 'filename=' \ +-b 'SESSDATA=xxx; bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "id": 122, + "parent": 36, + "parent_name": "知识", + "name": "野生技能协会", + "description": "技能展示或技能教学分享类视频", + "desc": "技能展示或技能教学分享类视频", + "intro_original": "可对视频内容进行补充说明,并对所使用的视频素材进行标明。\n如是系列,也可附带上期视频地址。\n请勿加入涉政或具较大争议性的文字简介,否则将做打回处理。", + "intro_copy": "转载稿件需标明出处,请注明原作者、原作者频道名或原作者投稿地址。\n可对相关内容进行补充说明。\n请勿加入涉政或具较大争议性的文字简介,否则将做打回处理。\n如是系列,也可附带上期视频地址。", + "notice": "清晰明了表明内容亮点的标题会更受观众欢迎哟!", + "copy_right": 0, + "show": true, + "rank": 75, + "max_video_count": 100, + "request_id": "" + }, + { + "id": 21, + "parent": 160, + "parent_name": "生活", + "name": "日常", + "description": "一般日常向的生活类视频", + "desc": "一般日常向的生活类视频", + "intro_original": "能够选择自制的必须是up主个人或工作室自己制作剪辑的视频,除此之外的搬运视频字幕制作,对于视频进行加速、慢放等简易二次创作,在视频中添加前后贴片或者打水印等行为均不被认作自制", + "intro_copy": "转载需写明请注明转载作品详细信息原作者、原标题及出处(需为该视频最原始出处,如所标注明显为非原始出处的话会被打回)", + "notice": "", + "copy_right": 0, + "show": true, + "rank": 4, + "max_video_count": 50, + "request_id": "" + }, + { + "id": 242, + "parent": 5, + "parent_name": "娱乐", + "name": "娱乐粉丝创作", + "description": "粉丝向创作视频", + "desc": "粉丝向创作视频", + "intro_original": "", + "intro_copy": "", + "notice": "清晰明了表明内容亮点的标题会更受观众欢迎哟!", + "copy_right": 0, + "show": true, + "rank": 40, + "max_video_count": 50, + "request_id": "" + }, + { + "id": 65, + "parent": 4, + "parent_name": "游戏", + "name": "网络游戏", + "description": "多人在线游戏为主要内容的相关视频", + "desc": "多人在线游戏为主要内容的相关视频", + "intro_original": "建议在简介和TAG中添加正确的游戏名,以便在分区和搜索中得到更好的展示。\n录制他人直播(包括授权转载、授权录制)不属于自制内容,请选转载。", + "intro_copy": "建议在简介和TAG中添加正确的游戏名。\n搬运转载内容请添加原作者、原链接地址信息。录制他人直播内容请添加原主播信息、直播时间。\n未添加正确转载、录播信息的稿件可能被打回。", + "notice": "【UP主/节目名】+《游戏名》+主要标题+期号", + "copy_right": 0, + "show": true, + "rank": 30, + "max_video_count": 50, + "request_id": "" + }, + { + "id": 138, + "parent": 160, + "parent_name": "生活", + "name": "搞笑", + "description": "搞笑挑战、剪辑、表演、配音以及各类日常沙雕视频", + "desc": "搞笑挑战、剪辑、表演、配音以及各类日常沙雕视频", + "intro_original": "能够选择自制的必须是up主个人或工作室自己制作剪辑的视频,除此之外的搬运视频字幕制作,对于视频进行加速、慢放等简易二次创作,在视频中添加前后贴片或者打水印等行为均不被认作自制", + "intro_copy": "转载需写明请注明转载作品详细信息原作者、原标题及出处(需为该视频最原始出处,如所标注明显为非原始出处的话会被打回)", + "notice": "", + "copy_right": 0, + "show": true, + "rank": 30, + "max_video_count": 50, + "request_id": "" + } + ] +} +``` + +</details> + +## 预测稿件标签 + +> https://member.bilibili.com/x/vupre/web/tag/recommend + +*请求方式: GET* + +认证方式: Cookie(SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| upload_id | str | 同 [预测稿件类型](#预测稿件类型) 的 `upload_id` | 不必要 | | +| subtype_id | int | 子分区 ID | 不必要 | | +| title | str | 视频标题 | 不必要 | | +| filename | str | 同 [预测稿件类型](#预测稿件类型) 的 `filename` | 不必要 | | +| description | str | 视频简介 | 不必要 | | +| cover_url | str | 视频封面 URL | 不必要 | 不含 `https:` 或 `http:` 字串 | +| t | int | 当前 UNIX 毫秒时间戳 | 不必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | int | 返回值 | 0: 成功<br />-101: 账号未登录 | +| data | array | 标签信息 | | +| message | str | 错误信息 | 默认为 0 | +| request_id | str | 请求 ID | | + +`data` 数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| 0 | obj | 标签 1 | | +| 1 | obj | 标签 2 | | +| …… | obj | …… | | +| n | obj | 标签 (n+1) | | + +`data` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| tag | str | 标签名称 | | +| checked | int | 0 | | +| request_id | str | 请求 ID | 同根对象 | + +**示例:** + +```shell +curl -G 'https://member.bilibili.com/x/vupre/web/tag/recommend' \ +--url-query 'subtype_id=122' \ +--url-query 'title=Telnet手打HTTP' \ +--url-query 'description=测试用 Telnet 手打 HTTP/1.x 协议访问本地服务器, 无 SSL/TLS 支持' +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": [ + { + "tag": "学习", + "checked": 0, + "request_id": "TAG_1723543336295_3371" + }, + { + "tag": "编程", + "checked": 0, + "request_id": "" + }, + { + "tag": "课程", + "checked": 0, + "request_id": "" + }, + { + "tag": "学习心得", + "checked": 0, + "request_id": "" + }, + { + "tag": "经验分享", + "checked": 0, + "request_id": "" + } + ], + "message": "0", + "request_id": "TAG_1723543336295_3371" +} +``` + +</details> + +## 投递视频稿件(Web) + +> https://member.bilibili.com/x/vu/web/add/v3 + +*请求方式: POST* + +认证方式:Cookie(SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| ts | num | 当前时间 | 不必要 | UNIX 毫秒时间戳 | +| csrf | str | CSRF Token (位于 Cookie 中 bili_jct) | 必要 | | + +**正文参数(application/json):** + +根对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| videos | array | 视频信息 | 必要 | 若为分 P 视频, 请注意数组元素顺序 | +| cover | str | 视频封面 URL | 非必要 | 如果不传会自动取封面,参见[上传视频封面](#上传视频封面) | +| cover43 | str | 视频封面 URL (比例为 4:3) | 非必要 | 可为空 | +| title | str | 视频标题 | 必要 | 最多 80 字 | +| copyright | num | 1: 自制<br />2: 转载 | 必要 | | +| tid | num | 分区 ID | 必要 | Web端此参数已无法手动设置,参数值为从[预测稿件类型](#预测稿件类型)中获取第一个固定id | +| human_type2 | num | 新分区ID | 非必要| 从 [新分区ID](#获取新分区ID) 获取 | +| tag | str | 视频标签 | 必要 | 多个标签用 `,` 分隔, 最多 10 个 | +| desc_format_id | num | 简介格式 ID? | 必要 | 9999: 纯文本 | +| desc | str | 视频简介 | 非必要 | 最多 2000 字 | +| desc_v2 | str | 视频简介额外信息 | 非必要 | 比如有艾特操作时传递,见备注 | +| recreate | num | 是否允许二创 | 必要 | -1: 允许(默认)<br />1: 不允许 | +| dynamic | str | 粉丝动态 | 必要 | | +| interactive | num | 互动视频? | 必要 | 0: 否 | +| act_reserve_create | num | 活动预约? | 必要 | 0: 否 | +| no_disturbance | num | 是否推送到动态| 必要 | 0:不推送,1:推送| +| no_reprint | num | 是否允许转载 | 必要 | 1: 允许<br />0: 不允许 | +| subtitle | obj | 字幕信息 | 必要 | | +| dolby | num | 杜比音效 | 必要 | 0: 否(默认)<br />1: 是 | +| lossless_music | num | 无损音乐 | 必要 | 0: 否(默认)<br />1: 是 | +| up_selection_reply | bool | 精选评论 | 必要 | | +| up_close_reply | bool | 关闭评论 | 必要 | | +| up_close_danmu | bool | 关闭弹幕 | 必要 | | +| web_os | num | 平台类型? | 必要 | 3 | +| is_only_self | 可见性 | 非必要 | 0:公开<br/>1:仅自己可见 | +| topic_id | 话题id | 非必要 | 可从[查询话题](./upload.md#查询话题)等相关接口获取 | +| mission_id | 任务id | 非必要 | 可从[查询话题](./upload.md#查询话题)等相关接口获取 | +| is_360 | num | 是否全景 | 非必要 | -1:非全景<br/>1:全景 | +| neutral_mark | str | 创作者声明 | 非必要 | | + +`videos` 数组中的对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| filename | str | 视频文件名 | 必要 | 从视频上传接口获取, 无后缀名 | +| title | str | 分 P 标题 | 必要 | | +| desc | str | 分 P 简介 | 必要 | | +| cid | num | 分 P cid | 必要 | 从视频上传接口获取, 即 `biz_id` | + +`subtitle` 对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| open | num | 是否启用字幕投稿 | 必要 | 0: 启用(默认)<br />1: 不启用 | +| lan | str | 字幕投稿语言 | 必要 | 可为空 | + +**desc_v2举例:** + +```js +{ + // 如果两者不一致,可能导致后续在web修改出现错误 + "desc": "前面@陈睿 后面", + "desc_v2": [ // 纯文字type是1,艾特用户type是2,biz_id为用户uid + { + "biz_id": "", + "raw_text": "前面", + "type": 1 + }, + { + "biz_id": "208259", // uid + "raw_text": "陈睿", // 用户名 + "type": 2 + }, + { + "biz_id": "", + "raw_text": " 后面", + "type": 1 + } + ] +} +``` + +**示例:** + +假设已经把需要发送的数据存放在文件 `./data.json` 中: + +```json +{ + "videos": [ + { + "filename": "n240728ad33h52yqhxbtw51cb06sq9gx", + "title": "Telnet手打HTTP", + "desc": "", + "cid": 500001629877726 + } + ], + "cover": "https://archive.biliimg.com/bfs/archive/85447ea20431ef799382c403c84b4bfb82a41053.jpg", + "cover43": "", + "title": "Telnet手打HTTP", + "copyright": 1, + "tid": 122, + "tag": "telnet,socket,tcp,linux,http", + "desc_format_id": 9999, + "desc": "测试用 Telnet 手打 HTTP/1.x 协议访问本地服务器, 无 SSL/TLS 支持", + "recreate": -1, + "dynamic": "for testing", + "interactive": 0, + "act_reserve_create": 0, + "no_disturbance": 0, + "no_reprint": 1, + "subtitle": { + "open": 0, + "lan": "" + }, + "dolby": 0, + "lossless_music": 0, + "up_selection_reply": false, + "up_close_reply": false, + "up_close_danmu": false, + "web_os": 3, + "csrf": "xxxxxxxxxxxxxxxxxxxxxxxx" +} +``` + +发送请求: + +```shell +curl -X POST --url "https://member.bilibili.com/x/vu/web/add/v3" \ +--url-query "ts=$(date +%s%3N)" \ +--url-query "csrf=xxxxxxxxxxxxxxxxxxxxxxxx" \ +-H "Content-Type: application/json; charset=utf-8" \ +--data @data.json \ +-b "SESSDATA=xxxxxx; bili_jct=xxxxxxxxxxxxxxxxxxxxxxxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "aid": 112861976201494, + "bvid": "BV181vnexEmB" + } +} +``` + +</details> + +## 编辑视频稿件(Web) + +> https://member.bilibili.com/x/vu/web/edit + +*请求方式: POST* + +认证方式:Cookie(SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| t | num | 当前时间 | 非必要 | UNIX 毫秒时间戳 | +| csrf | str | CSRF Token (位于 Cookie 中 bili_jct) | 必要 | | + +**正文参数(application/json):** + +绝大部分参数与上传一致,部分参数只有不对编辑生效 + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| aid | num | 视频 ID | 必要 | | +| videos | array | 视频信息 | 必要 | 若为分 P 视频, 请注意数组元素顺序 | +| title | str | 视频标题 | 必要 | 最多 80 字 | +| cover | str | 视频封面 URL | 非必要 | 如果不传会自动取封面,参见[上传视频封面](#上传视频封面) | +| cover43 | str | 视频封面 URL (比例为 4:3) | 非必要 | 可为空 | +| copyright | num | 1: 自制<br />2: 转载 | 必要 | | +| tid | num | 分区 ID | 必要 | | +| tag | str | 视频标签 | 必要 | 多个标签用 `,` 分隔, 最多 10 个 | +| desc_format_id | num | 简介格式 ID? | 必要 | 9999: 纯文本 | +| desc | str | 视频简介 | 非必要 | 最多 2000 字 | +| desc_v2 | str | 视频简介额外信息 | 非必要 | 比如有艾特操作时传递,见上传视频 | +| recreate | num | 是否允许二创 | 必要 | -1: 允许(默认)<br />1: 不允许 | +| dynamic | str | 粉丝动态 | 必要 | | +| interactive | num | 互动视频? | 必要 | 0: 否 | +| act_reserve_create | num | 活动预约? | 必要 | 0: 否 | +| no_disturbance | num | 是否推送到动态 | 必要 | 0:不推送<br />1:推送 | +| no_reprint | num | 是否允许转载 | 必要 | 1: 允许<br />0: 不允许 | +| subtitle | obj | 字幕信息 | 必要 | | +| web_os | num | 操作系统 | 必要 | 1: Web | +| mission_id | num | 任务 ID | 非必要 | 0: 无 | +| csrf | str | CSRF Token (位于 Cookie 中 bili_jct) | 必要 | | +| new_web_edit | num | 未知 | 非必要 | 未知 | +| is_360 | num | 是否全景 | 非必要 | -1:非全景<br/>1:全景 | +| is_only_self | 可见性 | 非必要 | 0:公开<br/>1:仅自己可见 | + + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----- | +| code | num | 返回值 | 0: 成功<br />其他: 失败 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "aid": 123456, + "bvid": "BV1xx411c7mD" + } +} +``` + +</details> + +## 获取新分区ID + +> https://member.bilibili.com/x/vupre/web/archive/human/type2/list + +*请求方式: GET* + +认证方式:Cookie(SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| t | num | 当前时间 | 非必要 | UNIX 毫秒时间戳 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----- | +| code | num | 返回值 | 0: 成功<br />其他: 失败 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| type_list | array | 信息本体 | | + +`type_list` 对象: + +| 参数名 | 类型 | 内容 | 备注 | +| ------ | ---- | -------- | ---- | +| id | num | 分区ID | | +| name | str | 分区名 | | + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "type_list": [ + { + "id": 1001, + "name": "影视" + }, + { + "id": 1002, + "name": "娱乐" + }, + { + "id": 1003, + "name": "音乐" + }, + { + "id": 1004, + "name": "舞蹈" + }, + { + "id": 1005, + "name": "动画" + }, + { + "id": 1006, + "name": "绘画" + }, + { + "id": 1007, + "name": "鬼畜" + }, + { + "id": 1008, + "name": "游戏" + }, + { + "id": 1009, + "name": "资讯" + }, + { + "id": 1010, + "name": "知识" + }, + { + "id": 1011, + "name": "人工智能" + }, + { + "id": 1012, + "name": "科技数码" + }, + { + "id": 1013, + "name": "汽车" + }, + { + "id": 1014, + "name": "时尚美妆" + }, + { + "id": 1015, + "name": "家装房产" + }, + { + "id": 1016, + "name": "户外潮流" + }, + { + "id": 1017, + "name": "健身" + }, + { + "id": 1018, + "name": "体育运动" + }, + { + "id": 1019, + "name": "手工" + }, + { + "id": 1020, + "name": "美食" + }, + { + "id": 1021, + "name": "小剧场" + }, + { + "id": 1022, + "name": "旅游出行" + }, + { + "id": 1023, + "name": "三农" + }, + { + "id": 1024, + "name": "动物" + }, + { + "id": 1025, + "name": "亲子" + }, + { + "id": 1026, + "name": "健康" + }, + { + "id": 1027, + "name": "情感" + }, + { + "id": 1029, + "name": "vlog" + }, + { + "id": 1030, + "name": "生活兴趣" + }, + { + "id": 1031, + "name": "生活经验" + } + ] + } +} +``` + +</details> + +## 上传视频文件 + +注: 目前看来上传的视频文件似乎不会自动删除, 而且似乎不是视频也可以上传的样子, 但是下载认证字段有效期只有 5 天 + +### 上传流程 + +整个上传流程较为复杂, 详细参见[Demo](#Demo) + +1. `GET` `preupload` 接口, [获取上传元数据](#获取上传元数据-预上传) + +2. `POST` 第 1 步得到的地址, [上传视频元数据](#上传视频元数据) + +3. `PUT` 第 1 步得到的地址, [分片上传视频文件](#分片上传视频文件) + +4. `POST` 第 1 步得到的地址, [结束上传视频文件](#结束上传视频文件) + +5. `GET` 第 1 步得到的地址, [下载已上传的视频文件](#下载已上传的视频文件) , 确认上传成功 (可选) + +### 上传接口 + +#### 获取上传元数据 (预上传) + +> https://member.bilibili.com/preupload + +*请求方式: GET* + +认证方式:Cookie(SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| name | str | 文件名 | 必要 | 会影响返回的上传地址 | +| r | str | 上传区域? | 必要 | upos | +| profile | str | 上传配置? | 必要 | 普通视频: ugcfx/bup<br />提交反馈: feedback/bup | +| probe_version | num | 上传版本? | 不必要 | 20221109 | +| upcdn | str | 上传 CDN? | 不必要 | txa | +| zone | str | 上传区域? | 不必要 | cs | +| ssl | num | 是否使用 SSL? | 不必要 | 0 | +| version | str | 上传版本? | 不必要 | 2.14.0.0 | +| build | str | 上传版本? | 不必要 | 2140000 | +| size | num | 文件大小 | 不必要 | 视频文件大小, 单位 字节 | +| webVersion | str | 上传版本? | 不必要 | 2.13.0 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----- | +| OK | num | 1 | | +| auth | str | 上传凭证 | 作为后面请求中请求头, 有效期 5 天 | +| biz_id | num | 业务 ID? | | +| chunk_retry | num | 重试次数? | | +| chunk_retry_delay | num | 重试延迟? | | +| chunk_size | num | 分块大小 | 后面要用 | +| endpoint | str | 上传节点 | 后面要用 | +| endpoints | array | 上传节点列表 | | +| expose_params | null | | | +| put_query | str | 上传参数? | | +| threads | num | 上传线程数 | | +| timeout | num | 超时时间? | | +| uip | str | 你的 IP | | +| upos_uri | str | 上传地址 | 后面要用 | + +`endpoints` 数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ----- | +| 0 | str | 上传节点1 | | +| …… | str | …… | | +| n | str | 上传节点n | | + +**示例:** + +假设视频文件名为 `2024-07-28_15-37-50.mkv`, 视频大小为 `305333744` 字节 + +```shell +curl -G "https://member.bilibili.com/preupload" \ +--data-urlencode "name=2024-07-28_15-37-50.mkv" \ +--data-urlencode "r=upos" \ +--data-urlencode "profile=ugcfx/bup" \ +-b "SESSDATA=xxxxxxxxxxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "OK": 1, + "auth": "ak=1494471752&cdn=%2F%2Fupos-cs-upcdntxa.bilivideo.com&os=upos&sign=b6c5cc520a281200906aea97e190b098×tamp=1722155211.324&uid=616368979&uip=108.181.24.77&uport=52096&use_dqp=0", + "biz_id": 500001630152509, + "chunk_retry": 10, + "chunk_retry_delay": 3, + "chunk_size": 10485760, + "endpoint": "//upos-cs-upcdntxa.bilivideo.com", + "endpoints": [ + "//upos-cs-upcdntxa.bilivideo.com", + "//upos-cs-upcdnalia.bilivideo.com" + ], + "expose_params": null, + "put_query": "os=upos&profile=ugcfx%2Fbup", + "threads": 3, + "timeout": 1200, + "uip": "108.181.24.77", + "upos_uri": "upos://ugcfx2lf/n240728ad1p51if4g3ke4s3o95sznogy.mkv" +} +``` + +</details> + +#### 上传视频元数据 + +> URL 拼接格式: `"https"` + [上一个接口](#获取上传元数据-预上传)的`endpoint` + 上一个接口的`upos_uri`去掉协议名 +> JavaScript 模板字符串: `https:${preupload.endpoint}/${endpoint.upos_uri.replace("upos://", "")}` + +*请求方式: POST* + +认证方式:请求头 `X-Upos-Auth` 为上一接口得到的 `auth` + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| uploads | str | 留空 | 必要 | 留空 | +| output | str | 输出格式 | 不必要 | 默认为 json(推荐), 留空为 xml | +| profile | str | 上传配置? | 必要 | 与上一个接口保持相同 | +| filesize | num | 文件大小 | 必要 | 视频文件大小, 单位 字节<br />feedback/bup 不必要 | +| partsize | num | 分块大小 | 必要 | 上一个接口返回, 且后面要用<br />feedback/bup 不必要 | +| biz_id | num | 业务 ID? | 必要 | 上一个接口返回, 且后面要用<br />feedback/bup 不必要 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----- | +| OK | num | 1 | | +| bucket | str | 空间名? | | +| key | str | 文件名? | | +| upload_id | str | 上传 ID | 后面要用 | + +**示例:** + +假设上一接口返回的 +`auth` 为 `ak=1494471752&cdn=%2F%2Fupos-cs-upcdntxa.bilivideo.com&os=upos&sign=4004b35628e982bc90b59cec86f8c441×tamp=1722173443.298&uid=616368979&uip=104.28.153.18&uport=44282&use_dqp=0`, +`biz_id` 为`500001630454700`, +`endpoint` 为 `//upos-cs-upcdntxa.bilivideo.com`, +`upos_uri` 为 `upos://ugcfx2lf/n240728adhejliqv0kqyg2s5n6huv501.mkv`, +`chunk_size` 为 `10485760`. +视频文件大小为 `305333744` 字节. + +```shell +curl -X POST --url "https://upos-cs-upcdntxa.bilivideo.com/ugcfx2lf/n240728adhejliqv0kqyg2s5n6huv501.mkv` \ +--url-query "uploads=" \ +--url-query "output=json" \ +--url-query "profile=ugcfx/bup" \ +--url-query "filesize=305333744" \ +--url-query "partsize=10485760" \ +--url-query "biz_id=500001630454700" \ +-H "X-Upos-Auth: ak=1494471752&cdn=%2F%2Fupos-cs-upcdntxa.bilivideo.com&os=upos&sign=4004b35628e982bc90b59cec86f8c441×tamp=1722173443.298&uid=616368979&uip=104.28.153.18&uport=44282&use_dqp=0" \ +-b "SESSDATA=xxxxxxxxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "OK": 1, + "bucket": "ugcfx2lf", + "key": "/n240728adhejliqv0kqyg2s5n6huv501.mkv", + "upload_id": "26c674b4-0dce-45f5-a9cd-a199d9c982bf" +} +``` + +</details> + +#### 分片上传视频文件 + +> URL 同 [上一个接口](#上传视频元数据) + +*请求方式: PUT* + +认证方式:请求头 `X-Upos-Auth` 为上上一接口得到的 `auth` + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| partNumber | num | 分块序号 | 必要 | 从 1 开始 | +| uploadId | str | 上传 ID | 必要 | 上一个接口返回 | +| chunk | num | 分块序号 | 必要 | 从 0 开始 | +| chunks | num | 分块总数 | 必要 | 自行计算: 文件大小除以分块大小并向上取整 | +| size | num | 该分块大小 | 必要 | 该实际上传字节数 | +| start | num | 该分块开始位置 | 必要 | 已实际上传字节数 | +| end | num | 该分块结束位置 | 必要 | 该分块上传结束后实际上传总字节数 | +| total | num | 总大小 | 必要 | 视频文件大小, 单位 字节 | + +**正文参数(application/octet-stream):** + +视频文件在该分块的字节流 + +**纯文本回复:** + +```text +MULTIPART_PUT_SUCCESS +``` + +**示例:** + +假设上上一接口返回的 +`auth` 为 `ak=1494471752&cdn=%2F%2Fupos-cs-upcdntxa.bilivideo.com&os=upos&sign=911dd5b995895805d785aa607b4153b6×tamp=1722212776.333&uid=616368979&uip=108.181.24.77&uport=36044&use_dqp=0`, +`endpoint` 为 `//upos-cs-upcdntxa.bilivideo.com`, +`upos_uri` 为 `upos://ugcfx2lf/n240729ad7gxi43yaoml312h2nbt2pnf.xz`, +`chunk_size` 为 `10485760`. + +上一接口返回的 +`upload_id` 为 `8130090a-16f7-4fe6-8a29-198f5abce913`. + +视频文件名为 `20240724-remove-linux-then-install.tar.xz`, 文件大小为 `278255704` 字节. + +假设您要上传的分块序号为 `1`, +该分块大小为 `10485760`, +该分块开始位置为 `0`, +该分块结束位置为 `10485760`, +该分块实际上传字节数为 `10485760`, +您已将文件分块存放至 `part01.tar.xz`, `part02.tar.xz`, ..., `part27.tar.xz`. + +```shell +curl -X PUT --url "https://upos-cs-upcdntxa.bilivideo.com/ugcfx2lf/n240729ad7gxi43yaoml312h2nbt2pnf.xz" \ +--url-query "partNumber=1" \ +--url-query "uploadId=8130090a-16f7-4fe6-8a29-198f5abce913" \ +--url-query "chunk=0" \ +--url-query "chunks=27" \ +--url-query "size=10485760" \ +--url-query "start=0" \ +--url-query "end=10485760" \ +--url-query "total=278255704" \ +-H "X-Upos-Auth: ak=1494471752&cdn=%2F%2Fupos-cs-upcdntxa.bilivideo.com&os=upos&sign=911dd5b995895805d785aa607b4153b6×tamp=1722212776.333&uid=616368979&uip=108.181.24.77&uport=36044&use_dqp=0" \ +-H "Content-Type: application/octet-stream" \ +--data-binary @part01.tar.xz \ +-b "SESSDATA=xxxxxxxxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```text +MULTIPART_PUT_SUCCESS +``` + +</details> + +#### 结束上传视频文件 + +> URL 同 [上一个接口](#分片上传视频文件) + +*请求方式: POST* + +认证方式:请求头 `X-Upos-Auth` 为上上上一接口得到的 `auth` + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| output | str | 输出格式 | 不必要 | 默认为 json(推荐), 留空为 xml | +| name | str | 文件名 | 必要 | 视频文件名 | +| profile | str | 上传配置? | 必要 | 与上一个接口相同, 普通视频: ugcfx/bup | +| uploadId | str | 上传 ID | 必要 | 与上一个接口相同 | +| biz_id | num | 业务 ID? | 必要 | 与上上一个接口相同 | + +**正文参数(application/json):** + +根对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---- | ------ | ---- | +| parts | array | 各分块信息 | 必要 | 按实际上传顺序而不是分块序号顺序 | + +`parts` 数组: + +| 项 | 类型 | 内容 | 必要性 | 备注 | +| --- | ---- | ---- | ------ | ---- | +| 0 | obj | 分块信息1 | 必要 | 按实际上传顺序而不是分块序号顺序 | +| 1 | obj | 分块信息2 | 必要 | | +| …… | obj | …… | | | +| n | obj | 分块信息n | 必要 | | + +`parts` 数组中的对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---- | ------ | ---- | +| partNumber | num | 分块序号 | 必要 | 从 1 开始 | +| eTag | str | `etag` | 必要 | | + +**JSON回复:** + +与 [上上一个接口](#上传视频元数据) 相同 + +**示例:** + +假设上上上一接口返回的 +`auth` 为 `ak=1494471752&cdn=%2F%2Fupos-cs-upcdntxa.bilivideo.com&os=upos&sign=911dd5b995895805d785aa607b4153b6×tamp=1722212776.333&uid=616368979&uip=108.181.24.77&uport=36044&use_dqp=0`, +`endpoint` 为 `//upos-cs-upcdntxa.bilivideo.com`, +`upos_uri` 为 `upos://ugcfx2lf/n240729ad7gxi43yaoml312h2nbt2pnf.xz`, +`biz_id` 为 `500001630826789`. + +上上一接口返回的 +`upload_id` 为 `8130090a-16f7-4fe6-8a29-198f5abce913`. + +视频文件名为 `20240724-remove-linux-then-install.tar.xz`, 文件大小为 `278255704` 字节. + +假设您已经全部上传完毕, 共上传 `27` 个分块, 本次请求上传的的内容存放在 `body.json` 文件中. + +```shell +curl -X PUT --url "https://upos-cs-upcdntxa.bilivideo.com/ugcfx2lf/n240729ad7gxi43yaoml312h2nbt2pnf.xz" \ +--url-query "output=json" \ +--url-query "name=20240724-remove-linux-then-install.tar.xz" \ +--url-query "profile=ugcfx%2Fbup" \ +--url-query "uploadId=8130090a-16f7-4fe6-8a29-198f5abce913" \ +--url-query "biz_id=500001630826789" \ +-H "X-Upos-Auth: ak=1494471752&cdn=%2F%2Fupos-cs-upcdntxa.bilivideo.com&os=upos&sign=911dd5b995895805d785aa607b4153b6×tamp=1722212776.333&uid=616368979&uip=108.181.24.77&uport=36044&use_dqp=0" \ +-H "Content-Type: application/json" \ +--data-binary @body.json \ +-b "SESSDATA=xxxxxxxxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "OK": 1, + "location": "ugcfx2lf/n240729ad7gxi43yaoml312h2nbt2pnf.xz", + "bucket": "ugcfx2lf", + "key": "/n240729ad7gxi43yaoml312h2nbt2pnf.xz" +} +``` + +</details> + +#### 下载已上传的视频文件 + +> URL 同 [上一个接口](#结束上传视频文件) + +*请求方式: GET* + +认证方式:请求头 `X-Upos-Auth` 为上上上上一接口得到的 `auth` + +注: 由于 `X-Upos-Auth` 有效期只有 5 天, 过期请求将返回 HTTP 403 如下 + +```http +HTTP/1.1 403 Forbidden +Bili-Trace-Id: 3e3f2db61366adbf +Server: upos@hcsgw@jscs-bvc-hcsgw-public-02 +X-Bili-Trace-Id: 0d8ca1af6d3510253e3f2db61366adbf +X-Upos-Auth: AUTH_TS_GT_5DAY AUTH=ak=1494471752&cdn=%2F%2Fupos-cs-upcdntxa.bilivideo.com&os=upos&sign=911dd5b995895805d785aa607b4153b6×tamp=1722212776.333&uid=616368979&uip=108.181.24.77&uport=36044&use_dqp=0 Now=1722662669 DURATION=449893 +Content-Length: 0 +Connection: keep-alive +Date: Sat, 03 Aug 2024 05:24:29 GMT +EO-LOG-UUID: 4296647794590631154 +EO-Cache-Status: MISS +``` + +**字节流回复:** + +视频文件字节流 + +**示例:** + +假设请求上一接口时的 URL 为 `https://upos-cs-upcdntxa.bilivideo.com/ugcfx2lf/n240729ad7gxi43yaoml312h2nbt2pnf.xz`, +请求头的 `X-Upos-Auth` 为 `ak=1494471752&cdn=%2F%2Fupos-cs-upcdntxa.bilivideo.com&os=upos&sign=911dd5b995895805d785aa607b4153b6×tamp=1722212776.333&uid=616368979&uip=108.181.24.77&uport=36044&use_dqp=0`, +您想要下载到运行目录下的 `file.tar.xz` 文件 + +```shell +curl -G "https://upos-cs-upcdntxa.bilivideo.com/ugcfx2lf/n240729ad7gxi43yaoml312h2nbt2pnf.xz" \ +-H "X-Upos-Auth: ak=1494471752&cdn=%2F%2Fupos-cs-upcdntxa.bilivideo.com&os=upos&sign=911dd5b995895805d785aa607b4153b6×tamp=1722212776.333&uid=616368979&uip=108.181.24.77&uport=36044&use_dqp=0" \ +--output file.tar.xz +``` + +<details> +<summary>查看检查示例:</summary> + +```text + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed +100 265M 100 265M 0 0 9493k 0 0:00:28 0:00:28 --:--:-- 10.3M +$ sha512sum file.tar.xz +abfbedf1ac4f251c81103beb4d5406af1e0b64b9d54e99bfc77d2a8a9c4913a9fd2f1751828ace8aac036f6385609d99e251437b07a0491caca2ad7069a57003 file.tar.xz +$ sha512sum ~/Documents/video-proj/20240724-remove-linux-then-install.tar.xz +abfbedf1ac4f251c81103beb4d5406af1e0b64b9d54e99bfc77d2a8a9c4913a9fd2f1751828ace8aac036f6385609d99e251437b07a0491caca2ad7069a57003 /home/sess/Documents/video-proj/20240724-remove-linux-then-install.tar.xz +``` + +</details> + +### Demo + +#### Java + +注: 需要 Gson 依赖, Java 8+, 单线程上传, 无异常处理, 仅供参考 + +```java +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; + +/** + * A demo class for uploading videos to Bilibili. + * + * @author SessX6cf + */ +public class BiliVideoUploader { + + private static String SESSDATA; + private static File VIDEO_FILE; + + public static void main(String[] args) throws IOException { + long ts = System.currentTimeMillis(); + if (args.length < 2) { + System.out.println("Usage: java BiliVideoUploader <video_file> <sessdata>"); + return; + } else { + VIDEO_FILE = new File(args[0]); + if (!VIDEO_FILE.isFile()) { + System.out.println("It is not a file!"); + return; + } else if (!VIDEO_FILE.canRead()) { + System.out.println("Cannot read the file!"); + return; + } else if (VIDEO_FILE.isDirectory()) { + System.out.println("You can play a directory?!"); + return; + } + SESSDATA = args[1]; + } + // step 1: preupload video + System.out.println("step 1: preupload video"); + JsonObject preuploadVideo = preuploadVideo(); + // step 2: post video meta + System.out.println("step 2: post video meta"); + JsonObject postVideoMeta = postVideoMeta(preuploadVideo); + // step 3: upload video + System.out.println("step 3: upload video"); + int chunks = uploadVideo(preuploadVideo, postVideoMeta); + // step 4: end upload + System.out.println("step 4: end upload"); + endupload(preuploadVideo, postVideoMeta, chunks); + // finished + System.out.println("finished (" + (System.currentTimeMillis() - ts) + "ms)"); + } + + private static String querypart(String key, String value) throws IOException { + return key + "=" + URLEncoder.encode(value, "UTF-8"); + } + + private static HttpURLConnection conn(String url, String method) throws IOException { + HttpURLConnection conn; + try { + conn = (HttpURLConnection) new URI(url).toURL().openConnection(); + } catch (java.net.URISyntaxException e) { + throw new IOException(e); + } + conn.setRequestMethod(method); + // conn.setRequestProperty("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0"); + if (url.contains("bilibili.com")) conn.setRequestProperty("Cookie", "SESSDATA=" + SESSDATA); + return conn; + } + + private static byte[] inputStreamToString(HttpURLConnection conn) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + InputStream in; + in = conn.getInputStream(); + int b; + while ((b = in.read()) != -1) { + baos.write(b); + } + in.close(); + return baos.toByteArray(); + } + + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); + + private static JsonObject preuploadVideo() throws IOException { + StringJoiner url = new StringJoiner("&", "https://member.bilibili.com/preupload?", ""); + url.add(querypart("name", VIDEO_FILE.getName())); + // url.add(querypart("size", String.valueOf(VIDEO_FILE.length()))); + url.add(querypart("r", "upos")); + url.add(querypart("profile", "ugcfx/bup")); + HttpURLConnection conn = conn(url.toString(), "GET"); + System.out.println("GET " + url.toString()); + String response = new String(inputStreamToString(conn), StandardCharsets.UTF_8); + try { + JsonObject json = GSON.fromJson(response, JsonObject.class); + System.out.println(GSON.toJson(json)); + return json; + } catch (JsonSyntaxException e) { + System.out.println(response); + throw e; + } + } + + private static JsonObject postVideoMeta(JsonObject preuploadVideo) throws IOException { + String schemeandhost = "https:" + preuploadVideo.get("endpoint").getAsString(); + String path = preuploadVideo.get("upos_uri").getAsString().replaceFirst("upos:/", ""); + StringJoiner url = new StringJoiner("&", schemeandhost + path + "?", ""); + url.add(querypart("uploads", "")); // WARNING: this is not a typo, it's required, or 404 + url.add(querypart("output", "json")); + url.add(querypart("profile", "ugcfx/bup")); + url.add(querypart("filesize", String.valueOf(VIDEO_FILE.length()))); + url.add(querypart("partsize", preuploadVideo.get("chunk_size").getAsString())); + url.add(querypart("biz_id", preuploadVideo.get("biz_id").getAsString())); + HttpURLConnection conn = conn(url.toString(), "POST"); + conn.setRequestProperty("X-Upos-Auth", preuploadVideo.get("auth").getAsString()); // 403 without it + System.out.println("POST " + url.toString()); + String response = new String(inputStreamToString(conn), StandardCharsets.UTF_8); + try { + JsonObject json = GSON.fromJson(response, JsonObject.class); + System.out.println(GSON.toJson(json)); + return json; + } catch (JsonSyntaxException e) { + System.out.println(response); + throw e; + } + } + + private static int uploadVideo(JsonObject preuploadVideo, JsonObject postVideoMeta) throws IOException { + long startts = System.currentTimeMillis() - 1; + String schemeandhost = "https:" + preuploadVideo.get("endpoint").getAsString(); + String path = preuploadVideo.get("upos_uri").getAsString().replaceFirst("upos:/", ""); + String urlp = schemeandhost + path + "?"; + long length = VIDEO_FILE.length(); + byte[] buffer = new byte[preuploadVideo.get("chunk_size").getAsInt()]; + int size = 0; + int chunks = (int) Math.ceil(length / (double) buffer.length); + InputStream in = new FileInputStream(VIDEO_FILE); + for (int chunk = 0; chunk < chunks; chunk++) { + System.out.println("speed: " + (chunk * buffer.length) / (System.currentTimeMillis() - startts) + "bytes/s"); + System.out.println("chunk: " + (chunk + 1) + "/" + chunks); + size = in.read(buffer, 0, buffer.length); + if (size == -1) { + break; + } + StringJoiner url = new StringJoiner("&", urlp, ""); + url.add(querypart("partNumber", String.valueOf(chunk + 1))); + url.add(querypart("uploadId", postVideoMeta.get("upload_id").getAsString())); + url.add(querypart("chunk", String.valueOf(chunk))); + url.add(querypart("chunks", String.valueOf(chunks))); + url.add(querypart("size", String.valueOf(size))); + url.add(querypart("start", String.valueOf(chunk * buffer.length))); + url.add(querypart("end", String.valueOf((chunk) * buffer.length + size))); + url.add(querypart("total", String.valueOf(length))); + HttpURLConnection conn = conn(url.toString(), "PUT"); + conn.setRequestProperty("X-Upos-Auth", preuploadVideo.get("auth").getAsString()); + conn.setRequestProperty("Content-Type", "application/octet-stream"); + conn.setRequestProperty("Content-Length", String.valueOf(size)); + conn.setDoOutput(true); + conn.getOutputStream().write(buffer, 0, size); + System.out.println("PUT " + url.toString()); + String response = new String(inputStreamToString(conn), StandardCharsets.UTF_8); + System.out.println(response); + } + in.close(); + return chunks; + } + + private static void endupload(JsonObject preuploadVideo, JsonObject postVideoMeta, int chunks) throws IOException { + String schemeandhost = "https:" + preuploadVideo.get("endpoint").getAsString(); + String path = preuploadVideo.get("upos_uri").getAsString().replaceFirst("upos:/", ""); + StringJoiner url = new StringJoiner("&", schemeandhost + path + "?", ""); + url.add(querypart("output", "json")); + url.add(querypart("name", VIDEO_FILE.getName())); + url.add(querypart("profile", "ugcfx/bup")); + url.add(querypart("uploadId", postVideoMeta.get("upload_id").getAsString())); + url.add(querypart("biz_id", preuploadVideo.get("biz_id").getAsString())); + JsonArray parts = new JsonArray(); + for (int i = 1; i <= chunks; i++) { + JsonObject part = new JsonObject(); + part.addProperty("partNumber", i); + part.addProperty("eTag", "etag"); + parts.add(part); + } + JsonObject body = new JsonObject(); + body.add("parts", parts); + HttpURLConnection conn = conn(url.toString(), "POST"); + conn.setRequestProperty("X-Upos-Auth", preuploadVideo.get("auth").getAsString()); + conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); + conn.setDoOutput(true); + conn.getOutputStream().write(body.toString().getBytes(StandardCharsets.UTF_8)); + System.out.println("POST " + url.toString()); + String response = new String(inputStreamToString(conn), StandardCharsets.UTF_8); + try { + JsonObject json = GSON.fromJson(response, JsonObject.class); + System.out.println(GSON.toJson(json)); + } catch (JsonSyntaxException e) { + System.out.println(response); + throw e; + } + } + +} +``` diff --git a/bb-api-collect/docs/creativecenter/videos.md b/bb-api-collect/docs/creativecenter/videos.md new file mode 100644 index 0000000000..6a800fdecd --- /dev/null +++ b/bb-api-collect/docs/creativecenter/videos.md @@ -0,0 +1,555 @@ +# 视频相关杂项 + +## 获取稿件列表 + +> https://member.bilibili.com/x2/creative/web/archives/sp + +*请求方式: GET* + +认证方式: Cookie (SESSDATA) + +注: 该接口返回内容大多为无实际意义的空值, 具体内容建议通过常规接口获取 + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | --------- | ----------- | ----------------- | +| pn | num | 页码 | 必要 | 默认为 1 | +| ps | num | 每页数量 | 必要 | 默认为 10, 留空为 100 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------------ | ---- | +| class | null | 作用尚不明确 | | +| arc_audits | array | 稿件列表 | | +| page | obj | 分页信息 | | +| play_type | num | 1 | | + +`arc_audits` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| - | - | - | - | +| Archive | obj | 稿件信息 | | +| Videos | null | | | +| stat | obj | 稿件统计信息 | | +| state_panel | num | 0 | | +| parent_tname | str | 空 | | +| typename | str | 空 | | +| open_appeal | num | 0 | | +| activity | null | | | +| season_add_state | num | 是否可加入合集 | 0: 可以<br />1: 不可以 | + +`Archive` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| - | - | - | - | +| aid | num | av 号 | | +| bvid | str | bv 号 | | +| mid | num | 0 | | +| tid | num | 0 | | +| tp_info | null | | | +| title | str | 稿件标题 | | +| author | str | 空 | | +| cover | str | 封面图 | 位于 bfs 需要自行拼接 URL | +| reject_reason | str | 空 | | +| reject_reason_url | str | 空 | | +| tag | str | 空 | | +| duration | num | 0 | | +| copyright | num | 0 | | +| no_reprint | num | 0 | | +| ugcpay | num | 0 | | +| order_id | num | 0 | | +| order_name | str | 空 | | +| adorder_id | num | 0 | | +| adorder_name | str | 空 | | +| adorder_no | str | 空 | | +| online_time | num | 0 | | +| new_adorder_info | null | | | +| desc | str | 稿件简介 | | +| mission_id | num | 0 | | +| mission_name | str | 空 | | +| attribute | num | 0 | | +| state | num | 0 | | +| state_desc | str | 空 | | +| state_panel | num | 0 | | +| source | str | 空 | | +| desc_format_id | num | 0 | | +| attrs | null | | | +| porder | null | | | +| dynamic | str | 空 | | +| poi_object | null | | | +| dtime | num | 0 | | +| ptime | num | 0 | | +| ctime | num | 0 | | +| ugcpay_info | null | | | +| staffs | null | | | +| vote | null | | | +| activity | null | | | +| interactive | num | 0 | | +| hl | null | | | +| no_background | num | 0 | | +| dynamic_video | num | 0 | | +| no_public | num | 0 | | +| is_360 | num | 0 | | +| is_dolby | num | 0 | | +| lossless_music | num | 0 | | +| bs_editor | num | 0 | | +| up_from | num | 0 | | +| desc_v2 | null | | | +| dynamic_v2 | null | | | +| topic_id | num | 0 | | +| topic_name | str | 空 | | +| topic_stat | num | 0 | | +| premiere | num | 0 | | +| is_ugcpay_v2 | num | 0 | | +| recreate | null | | | +| charging_pay | num | 0 | | +| neutral_mark | str | 空 | | +| preview | null | | | +| upower_level | null | | | +| cover43 | str | 空 | | +| had_passed | bool | false | | +| is_staff | num | 0 | | +| is_pugv | num | 0 | | +| upower_mode | num | 0 | | +| upower_unit_price | num | 0 | | + +`stat` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| - | - | - | - | +| aid | num | av 号 | | +| view | num | 播放量 | | +| danmaku | num | 弹幕数 | | +| reply | num | 评论数 | | +| favorite | num | 收藏数 | | +| coin | num | 硬币数 | | +| share | num | 分享数 | | +| now_rank | num | 0 | 当前排名 | +| his_rank | num | 0 | 历史最高排名 | +| like | num | 点赞数 | | +| dislike | num | 点踩数 | 恒为 0 | +| vt | num | 0 | | +| vv | num | 播放量 | | + +**示例:** + +```shell +curl -G "https://member.bilibili.com/x2/creative/web/archives/sp" \ +--data-urlencode "pn=1" \ +--data-urlencode "ps=3" \ +-b "SESSDATA=xxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "class": null, + "arc_audits": [ + { + "Archive": { + "aid": 1906473802, + "bvid": "BV1MU411S7iJ", + "mid": 0, + "tid": 0, + "tp_info": null, + "title": "Linux小寄巧: 原地卸载内核然后尝试救活!", + "author": "", + "cover": "/bfs/archive/b76c0b574862f5a8e8eb133f5f33fcbcd602401a.jpg", + "reject_reason": "", + "reject_reason_url": "", + "tag": "", + "duration": 0, + "copyright": 0, + "no_reprint": 0, + "ugcpay": 0, + "order_id": 0, + "order_name": "", + "adorder_id": 0, + "adorder_name": "", + "adorder_no": "", + "online_time": 0, + "new_adorder_info": null, + "desc": "", + "mission_id": 0, + "mission_name": "", + "attribute": 0, + "state": 0, + "state_desc": "", + "state_panel": 0, + "source": "", + "desc_format_id": 0, + "attrs": null, + "porder": null, + "dynamic": "", + "poi_object": null, + "dtime": 0, + "ptime": 0, + "ctime": 0, + "ugcpay_info": null, + "staffs": null, + "vote": null, + "activity": null, + "interactive": 0, + "hl": null, + "no_background": 0, + "dynamic_video": 0, + "no_public": 0, + "is_360": 0, + "is_dolby": 0, + "lossless_music": 0, + "bs_editor": 0, + "up_from": 0, + "desc_v2": null, + "dynamic_v2": null, + "topic_id": 0, + "topic_name": "", + "topic_stat": 0, + "premiere": 0, + "is_ugcpay_v2": 0, + "recreate": null, + "political_media": 0, + "political_editable": 0, + "charging_pay": 0, + "neutral_mark": "", + "preview": null, + "upower_level": null, + "cover43": "", + "had_passed": false, + "is_staff": 0, + "is_pugv": 0, + "upower_mode": 0, + "upower_unit_price": 0 + }, + "Videos": null, + "stat": { + "aid": 1906473802, + "view": 4036, + "danmaku": 8, + "reply": 56, + "favorite": 53, + "coin": 12, + "share": 8, + "now_rank": 0, + "his_rank": 0, + "like": 99, + "dislike": 0, + "vt": 0, + "vv": 4036 + }, + "state_panel": 0, + "parent_tname": "", + "typename": "", + "open_appeal": 0, + "activity": null, + "season_add_state": 0 + }, + { + "Archive": { + "aid": 1956170305, + "bvid": "BV1Ay411i7Ph", + "mid": 0, + "tid": 0, + "tp_info": null, + "title": "十多年前的电脑运行Debian12的启动过程", + "author": "", + "cover": "/bfs/archive/0bff6624fdfcbf3326fba1837fef093d455c846a.jpg", + "reject_reason": "", + "reject_reason_url": "", + "tag": "", + "duration": 0, + "copyright": 0, + "no_reprint": 0, + "ugcpay": 0, + "order_id": 0, + "order_name": "", + "adorder_id": 0, + "adorder_name": "", + "adorder_no": "", + "online_time": 0, + "new_adorder_info": null, + "desc": "", + "mission_id": 0, + "mission_name": "", + "attribute": 0, + "state": 0, + "state_desc": "", + "state_panel": 0, + "source": "", + "desc_format_id": 0, + "attrs": null, + "porder": null, + "dynamic": "", + "poi_object": null, + "dtime": 0, + "ptime": 0, + "ctime": 0, + "ugcpay_info": null, + "staffs": null, + "vote": null, + "activity": null, + "interactive": 0, + "hl": null, + "no_background": 0, + "dynamic_video": 0, + "no_public": 0, + "is_360": 0, + "is_dolby": 0, + "lossless_music": 0, + "bs_editor": 0, + "up_from": 0, + "desc_v2": null, + "dynamic_v2": null, + "topic_id": 0, + "topic_name": "", + "topic_stat": 0, + "premiere": 0, + "is_ugcpay_v2": 0, + "recreate": null, + "political_media": 0, + "political_editable": 0, + "charging_pay": 0, + "neutral_mark": "", + "preview": null, + "upower_level": null, + "cover43": "", + "had_passed": false, + "is_staff": 0, + "is_pugv": 0, + "upower_mode": 0, + "upower_unit_price": 0 + }, + "Videos": null, + "stat": { + "aid": 1956170305, + "view": 2747, + "danmaku": 13, + "reply": 37, + "favorite": 11, + "coin": 14, + "share": 4, + "now_rank": 0, + "his_rank": 0, + "like": 42, + "dislike": 0, + "vt": 0, + "vv": 2747 + }, + "state_panel": 0, + "parent_tname": "", + "typename": "", + "open_appeal": 0, + "activity": null, + "season_add_state": 0 + }, + { + "Archive": { + "aid": 910326709, + "bvid": "BV1GM4y1a7Vn", + "mid": 0, + "tid": 0, + "tp_info": null, + "title": "Minecraft终末之诗,但是谷歌翻译20遍", + "author": "", + "cover": "/bfs/archive/09b7f2542f3e66973ec7de1a3c806cdd45b95426.jpg", + "reject_reason": "", + "reject_reason_url": "", + "tag": "", + "duration": 0, + "copyright": 0, + "no_reprint": 0, + "ugcpay": 0, + "order_id": 0, + "order_name": "", + "adorder_id": 0, + "adorder_name": "", + "adorder_no": "", + "online_time": 0, + "new_adorder_info": null, + "desc": "原内容来源:Minecraft Wiki\n使用的工具:Google Translate\n视频仅供娱乐,请勿当真", + "mission_id": 0, + "mission_name": "", + "attribute": 0, + "state": 0, + "state_desc": "", + "state_panel": 0, + "source": "", + "desc_format_id": 0, + "attrs": null, + "porder": null, + "dynamic": "", + "poi_object": null, + "dtime": 0, + "ptime": 0, + "ctime": 0, + "ugcpay_info": null, + "staffs": null, + "vote": null, + "activity": null, + "interactive": 0, + "hl": null, + "no_background": 0, + "dynamic_video": 0, + "no_public": 0, + "is_360": 0, + "is_dolby": 0, + "lossless_music": 0, + "bs_editor": 0, + "up_from": 0, + "desc_v2": null, + "dynamic_v2": null, + "topic_id": 0, + "topic_name": "", + "topic_stat": 0, + "premiere": 0, + "is_ugcpay_v2": 0, + "recreate": null, + "political_media": 0, + "political_editable": 0, + "charging_pay": 0, + "neutral_mark": "", + "preview": null, + "upower_level": null, + "cover43": "", + "had_passed": false, + "is_staff": 0, + "is_pugv": 0, + "upower_mode": 0, + "upower_unit_price": 0 + }, + "Videos": null, + "stat": { + "aid": 910326709, + "view": 533, + "danmaku": 6, + "reply": 4, + "favorite": 15, + "coin": 13, + "share": 4, + "now_rank": 0, + "his_rank": 0, + "like": 29, + "dislike": 0, + "vt": 0, + "vv": 533 + }, + "state_panel": 0, + "parent_tname": "", + "typename": "", + "open_appeal": 0, + "activity": null, + "season_add_state": 0 + } + ], + "page": { + "pn": 1, + "ps": 3, + "count": 32 + }, + "play_type": 1 + } +} +``` + +</details> + +## 视频基础信息 + +> https://member.bilibili.com/x/web/archive/videos + +*请求方式: GET* + +认证方式: Cookie (SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---- | ---- | ---- | ---- | ---- | +| aid | num | av 号 | 必要 | | + +**JSON回复:** + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| archive | obj | 稿件信息 | | +| videos | array | 视频信息 | | + +`archive` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| aid | num | av 号 | | +| bvid | str | bvid | | +| title | str | 标题 | | + +`videos` 数组: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | -- | --- | +| cid | num | 分P cid | | +| index | num | 分P 序号 | | +| title | str | 分P 标题 | | +| duration | num | 0 | | + +**示例:** + +```shell +curl -G "https://member.bilibili.com/x/web/archive/videos" \ +--data-urlencode "aid=1906473802" \ +-b "SESSDATA=xxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "archive": { + "aid": 1906473802, + "bvid": "BV1MU411S7iJ", + "title": "Linux小寄巧: 原地卸载内核然后尝试救活!" + }, + "videos": [ + { + "cid": 1625992822, + "index": 1, + "title": "Linux小寄巧: 原地卸载内核然后尝试救活!", + "duration": 0 + } + ] + } +} +``` + +</details> diff --git a/bb-api-collect/docs/customerservice/msg.md b/bb-api-collect/docs/customerservice/msg.md new file mode 100644 index 0000000000..06b5645e06 --- /dev/null +++ b/bb-api-collect/docs/customerservice/msg.md @@ -0,0 +1,115 @@ +# 客服消息 + +## 心跳 + +> https://customerservice.bilibili.com/x/custom/session_svr/v1/heart_beat + +*请求方式: GET* + +认证方式: Cookie (SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| shop_id | num | 0 | 非必要 | | +| shop_father_id | num | 0 | 非必要 | | +| build | num | 客户端版本 | 非必要 | web: 0 | +| mobi_app | str | 客户端类型 | 非必要 | 如 `web` | + +**JSON回复:** + +|字段|类型|内容|备注| +|-|-|-|-| +|code|num|返回值|0: 成功| +|msg|str|`ok`|失败时不存在| +|message|str|错误信息|成功时为 `ok`| +|ttl|num|1|| + +**示例:** + +```shell +curl -G "https://customerservice.bilibili.com/x/custom/session_svr/v1/heart_beat" \ +-b "SESSDATA=xxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "ok", + "message": "ok", + "ttl": 1 +} +``` + +</details> + +## 上传文件 + +> https://customerservice.bilibili.com/x/custom/msg_svr/v1/upload + +*请求方式: POST* + +认证方式: Cookie (SESSDATA) + +注: 上传的文件 15 分钟内有效, 过期后下载会返回 HTTP 403 + +**正文参数 (multipart/form-data):** + +|参数名|类型|内容|必要性|备注| +|-|-|-|-|-| +|file|file|文件内容|必要|| +|filename|str|文件名|必要|| +|mid|num|用户 mid|必要|| +|csrf|str|CSRF Token (位于 Cookie 中 bili_jct)|必要|| + +**JSON回复:** + +根对象: + +|字段|类型|内容|备注| +|-|-|-|-| +|code|num|返回值|0: 成功<br />1000011: 仅支持上传300M内的文件<br />1200201: 获取用户信息失败| +|message|str|错误信息|成功时为 `ok`| +|ttl|num|1|| +|data|obj|上传结果|| + +`data` 对象: + +|字段|类型|内容|备注| +|-|-|-|-| +|key|str|文件名|| +|url|str|文件 URL|注意转义| + +**示例:** + +上传文件 `./headers/xx-out.xcf`, 文件名 `ihavenoname` + +```shell +curl -X POST "https://customerservice.bilibili.com/x/custom/msg_svr/v1/upload" \ +-F 'file=@./headers/xx-out.xcf' \ +-F 'filename=ihavenoname' \ +-F 'mid=1070915568' \ +-F 'csrf=xxx' \ +-b 'SESSDATA=xxx; bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "ok", + "ttl": 1, + "data": { + "key": "1a0c88d240852155a111e4cc6893be39.xcf", + "url": "https://jssz-boss.hdslb.com/customer-video-upload/1a0c88d240852155a111e4cc6893be39.xcf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=f9TxwsagojnE1DWM%2F20240803%2Fjssz%2Fs3%2Faws4_request&X-Amz-Date=20240803T115447Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=cef962c8e503c6ff564fd485bdef1079df1b4a7e38f4fbd9c21a5667207f406e" + } +} +``` + +</details> diff --git a/bb-api-collect/docs/danmaku/action.md b/bb-api-collect/docs/danmaku/action.md new file mode 100644 index 0000000000..95e34c49e5 --- /dev/null +++ b/bb-api-collect/docs/danmaku/action.md @@ -0,0 +1,828 @@ +# 弹幕操作 + +## 发送视频弹幕 + +> https://api.bilibili.com/x/v2/dm/post + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或APP + +此接口与漫画弹幕相同 + +`mode=6`的逆向弹幕与`mode=8`的代码弹幕不可发送 + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --- | --- | --- | --- | --- | +| web_location | str | 普通视频: 1315873 | 不必要 | | +| csrf | str | CSRF Token (即 Cookie 中 bili_jct) | Cookie 方式必要 | | +| w_rid | str | Wbi 签名 | 必要 | 参见 [Wbi 签名](../misc/sign/wbi.md) | +| wts | str | UNIX 秒级时间戳 | 必要 | 参见 [Wbi 签名](../misc/sign/wbi.md) | + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------- | ---- | ------------------------- | --------------- | ------------------------------------------------------------ | +| 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 />9:BAS弹幕(`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回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-102:账号被封停<br />-111:csrf校验失败<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 />36712:level 1用户发送弹幕的最大长度为20<br />36713:稿件未付费<br />36714:弹幕发送时间不合法<br />36715:当日操作数量超过上限<br />36718:目前您不是大会员,无法使用会员权益 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---------- | ------------------ | -------------------------------- | +| 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,普通弹幕,游动弹幕) + +```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' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code":0, + "message":"0", + "ttl":1, + "data":{ + "action":"", + "dmid":32161968826613767, + "dmid_str":"32161968826613767", + "visible":true + } +} +``` + +</details> + +## 发送互动弹幕 + +> https://api.bilibili.com/x/v2/dm/command/post + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或APP + +2020-09-25 B站更新了互动弹幕功能,包括UP主头像弹幕、关联视频弹幕、视频内嵌引导关注按钮三大功能 + +详情见: + +[【客户端更新】6.10版本更新!UP主支持发布关联视频弹幕]( https://www.bilibili.com/read/cv7728299 ) + + [引导关注卡片]( https://www.bilibili.com/blackboard/activity-c8a0iDRQy.html ) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | ------------------------------------------------------------ | +| access_key | str | APP登录Token | APP方式必要 | | +| type | num | 互动弹幕类型 | 必要 | 1:UP主头像弹幕<br />2:关联视频弹幕<br />5:视频内嵌引导关注按钮 | +| aid | num | 稿件avid | 必要 | | +| cid | num | 视频cid | 必要 | | +| progress | num | 弹幕出现在视频内的时间 | 非必要 | 单位为毫秒<br />默认为0 | +| plat | num | 平台标识 | 必要 | 1:web端<br />2:安卓端<br />8:视频管理页面 | +| data | str | json序列 | 必要 | | +| dmid | num | 修改互动弹幕的弹幕id | 非必要 | 注:修改弹幕`plat`必须为8 | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +`data`参数json序列: + +类型为【UP主头像弹幕】时: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| msg | str | 弹幕内容 | | + +类型为【关联视频弹幕】时: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | ---- | +| msg | str | 弹幕内容 | | +| bvid | str | 关联视频的bvid | | + +类型为【视频内嵌引导关注按钮】时: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------- | --------------- | +| duration | num | 持续时间 | 单位为毫秒 | +| posX | num | X坐标 | 区间:[118-549] | +| posY | num | Y坐标 | 区间:[82-293] | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----------------------------- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-102:账号被封停<br />-111:csrf校验失败<br />-400:请求错误<br />-404:无此项<br />-500:服务器错误<br />36711:该视频禁止发送弹幕<br />79026:发送失败,请勿填写当前稿件bvid<br />79024:发送失败,请输入正确的bvid<br />79036:该指令弹幕超出限制<br />79037:关注弹幕坐标溢出 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 正确时:obj<br />错误时:null | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ---------------------- | ------------------------------------------------------------ | +| command | str | 指令? | UP主头像弹幕:#UP#<br />关联视频弹幕:#LINK#<br />视频内嵌引导关注按钮:#ATTENTION# | +| content | str | 弹幕内容 | | +| extra | str | 弹幕数据 | json序列 | +| id | num | 弹幕dmid | | +| idStr | str | 弹幕dmid | 字串形式 | +| mid | num | 用户mid | | +| oid | num | 视频cid | | +| progress | num | 弹幕出现在视频内的时间 | | +| type | num | 互动弹幕类型 | 1:UP主头像弹幕<br />2:关联视频弹幕<br />5:视频内嵌引导关注按钮 | + +`extra`序列数据: + +类型为【UP主头像弹幕】时: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---- | +| icon | str | UP主头像url | | + +类型为【关联视频弹幕】时: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | -------------- | ---- | +| aid | num | 关联视频的avid | | +| title | str | 关联视频的标题 | | +| bvid | str | 关联视频的bvid | | + +类型为【视频内嵌引导关注按钮】时: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------------ | ------------------------------------------ | +| duration | num | 持续时间 | 单位为毫秒 | +| posX | num | X坐标 | 区间:[118-549] | +| posY | num | Y坐标 | 区间:[82-293] | +| icon | str | 按钮图片url | 不应该是关注按钮吗,但这个是圆形的 | +| type | num | 关注按钮类型 | 0:仅关注<br />1:仅三联<br />2:关注+三联 | + +**示例:** + +为视频`av201947622`(cid为`230709860`)的5000ms位置发送一条UP主头像弹幕`test` + +```shell +curl 'https://api.bilibili.com/x/v2/dm/command/post' \ +--data-urlencode 'type=1' \ +--data-urlencode 'aid=201947622' \ +--data-urlencode 'cid=230709860' \ +--data-urlencode 'progress=5000' \ +--data-urlencode 'plat=1' \ +--data-urlencode 'data={"msg":"test"}' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "id": 39053842117558279, + "oid": 230709860, + "mid": 293793435, + "type": 1, + "command": "#UP#", + "content": "test", + "extra": "{\"icon\":\"http://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg\"}", + "idStr": "39053842117558279" + } +} +``` + +</details> + +为视频`av201947622`(cid为`230709860`)的5000ms位置发送一条发送关联视频弹幕`测试1234`关联视频为`BV1kz4y1X7XP` + +```shell +curl 'https://api.bilibili.com/x/v2/dm/command/post' \ +--data-urlencode 'type=2' \ +--data-urlencode 'aid=201947622' \ +--data-urlencode 'cid=230709860' \ +--data-urlencode 'progress=5000' \ +--data-urlencode 'plat=1' \ +--data-urlencode 'data={"bvid":"BV1kz4y1X7XP","msg":"测试1234"}' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "id": 39054383689236483, + "oid": 230709860, + "mid": 293793435, + "type": 2, + "command": "#LINK#", + "content": "测试1234", + "progress": 11925, + "extra": "{\"aid\":583785685,\"title\":\"【cmd】访问api 命令行也能上B站\",\"bvid\":\"BV1kz4y1X7XP\"}", + "idStr": "39054383689236483" + } +} +``` + +</details> + + +为视频`av201947622`(cid为`230709860`)的5000ms位置发送视频内嵌引导关注按钮,X坐标为118,Y坐标为82,持续时间为5000ms + +```shell +curl 'https://api.bilibili.com/x/v2/dm/command/post' \ +--data-urlencode 'type=5' \ +--data-urlencode 'aid=201947622' \ +--data-urlencode 'cid=230709860' \ +--data-urlencode 'progress=5000' \ +--data-urlencode 'plat=1' \ +--data-urlencode 'data={"duration":5000,"posX":118,"posY":82}' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "id": 39055158405496839, + "oid": 230709860, + "mid": 293793435, + "type": 5, + "command": "#ATTENTION#", + "progress": 5000, + "extra": "{\"duration\":5000,\"posX\":118,\"posY\":82}", + "idStr": "39055158405496839" + } +} +``` + +</details> + +## 发送打分弹幕 + +> https://api.bilibili.com/x/v2/dm/command/grade/post + +*请求方式: POST* + +认证方式: Cookie (SESSDATA) + +<!--{ + "gh": [220] +}--> + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---- | ------ | ---- | +| aid | num | 稿件 aid | 必要 | | +| cid | num | 分 P cid | 必要 | | +| progress | num | 播放进度 | 必要 | 单位为毫秒 | +| grade_id | num | 打分 id | 必要 | | +| grade_score | num | 分数 | 偶数, 最大 10 | +| polaris_app_id | num | 100 | 不必要 | +| polaris_platfrom | num | 5 | 不必要 | | +| spmid | str | 333.788.0.0 | 不必要 | | +| from_spmid | str | 来源 spmid | 不必要 | | +| csrf | str | CSRF Token (即 Cookie 中的 bili_jct) | 必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | num | 返回值 | 0: 成功 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| dmid | num | 弹幕dmid | | +| dmid_str | str | 弹幕dmid | 字串形式 | +| visible | bool | 是否可见 | | +| action | str | 动作 | `"grade:"` + (请求的分数 / 2) | + +**示例:** + +```shell +curl -X POST 'https://api.bilibili.com/x/v2/dm/command/grade/post' \ +--data-urlencode 'aid=112861976201494' \ +--data-urlencode 'cid=500001629877726' \ +--data-urlencode 'progress=32000' \ +--data-urlencode 'grade_id=3651137' \ +--data-urlencode 'grade_score=10' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "dmid": 1651556419721443584, + "dmidStr": "1651556419721443584", + "visible": true, + "action": "grade:5" + } +} +``` + +</details> + +## 撤回弹幕 + +> https://api.bilibili.com/x/dm/recall + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或APP + +仅能撤回自己两分钟内的弹幕,且每天只有3次机会 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | ---- | +| access_key | str | APP登录Token | APP方式必要 | | +| dmid | num | 弹幕dmid | 必要 | | +| cid | num | 视频cid | 必要 | | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-102:账号被封停<br />-111:csrf校验失败<br />-400:请求错误<br />-404:无此项<br />36301:撤回失败,弹幕发送已过2分钟<br />36302:撤回失败,弹幕已经被删除或撤回<br />36303:撤回失败,今天撤回的机会已经用完<br />36304:撤回失败,服务器出错 | +| message | str | 错误信息 | 成功后显示剩余次数 | +| ttl | num | 1 | | + +**示例:** + +撤回`cid=168901231`下的弹幕`32310301474947077`的弹幕 + +```shell +curl 'https://api.bilibili.com/x/dm/recall' \ +--data-urlencode 'cid=168901231' \ +--data-urlencode 'dmid=32310301474947077' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "撤回成功,你还有3次撤回机会" +} +``` + +</details> + +## 购买高级弹幕发送权限 + +> https://api.bilibili.com/x/dm/adv/buy + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或APP + +购买一次需要2硬币,同时向up主发送请求 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | ---- | +| access_key | str | APP登录Token | APP方式必要 | | +| mode | str | sp | 必要 | | +| cid | num | 视频cid | 必要 | | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-102:账号被封停<br />-111:csrf校验失败<br />-107:硬币不足<br />-400:请求错误<br />36007:不允许购买<br />36009:正在确认中<br />36010:已购买 | +| message | str | 返回信息 | | +| ttl | num | 1 | | + +示例: + +购买视频cid为`168901231`的高级弹幕发送权限 + +```shell +curl 'https://api.bilibili.com/x/dm/adv/buy' \ +--data-urlencode 'cid=168901231' \ +--data-urlencode 'mode=sp' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code":0, + "message":"已成功购买" +} +``` + +</details> + +## 检测高级弹幕发送权限 + +> https://api.bilibili.com/x/dm/adv/state + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | ---- | +| access_key | str | APP登录Token | APP方式必要 | | +| mode | str | sp | 必要 | | +| cid | num | 视频cid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----------------------------- | ---------------- | -------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />--400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 有效时:obj<br />无效时:null | 有效时:信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ---------------- | ------------------------------------------ | +| coins | num | 需要支付的硬币数 | | +| confirm | num | 是否同意 | 1:同意<br />2:未同意<br />未购买时无此项 | +| accept | bool | 是否允许申请 | true:允许<br />false:不允许 | +| hasBuy | bool | 是否已购买 | true:已购买<br />未购买时无此项 | + +**示例:** + +查询视频cid为`168901231`的视频高级弹幕权限购买状态 + +当前状态为已购买且同意 + +```shell +curl -G 'https://api.bilibili.com/x/dm/adv/state' \ +--data-urlencode 'cid=168901231' \ +--data-urlencode 'mode=sp' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "coins": 2, + "confirm": 1, + "accept": true, + "hasBuy": true + } +} +``` + +</details> + +## 点赞弹幕 + +> https://api.bilibili.com/x/v2/dm/thumbup/add + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或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 | 平台标识 | 非必要 | web_player:web 播放器<br />android:安卓端 | +| csrf | str | CSRF Token(位于 Cookie) | Cookie 方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|------------------------------------------------------------------------------------------------------------------------------------| +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf 校验失败<br />-400:请求错误<br />36106:该弹幕已被删除<br/>36805:该视频禁止点赞弹幕<br/>65004:取消赞失败 未点赞过<br />65006:已赞过 | +| message | str | 错误信息 | 默认为0 | +| tll | num | 1 | | + +**示例** + +为`cid=145928946`下的弹幕`35600074482384899`点赞 + +```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' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code":0, + "message":"0", + "ttl":1 +} +``` + +</details> + +## 举报弹幕 + +> https://api.bilibili.com/x/dm/report/add + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或APP + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | ------------------ | +| access_key | str | APP登录Token | APP方式必要 | | +| cid | num | 视频cid | 必要 | | +| dmid | num | 弹幕dmid | 必要 | | +| reason | num | 举报类型 | 必要 | **类型代码见下表** | +| content | str | 其他举报备注 | 非必要 | `reason=11`时有效 | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +举报类型`reason`: + +| 代码 | 含义 | +| ---- | ---------- | +| 1 | 违法违禁 | +| 2 | 色情低俗 | +| 3 | 赌博诈骗 | +| 4 | 人身攻击 | +| 5 | 侵犯隐私 | +| 6 | 垃圾广告 | +| 7 | 引战 | +| 8 | 剧透 | +| 9 | 恶意刷屏 | +| 10 | 视频无关 | +| 11 | 其他 | +| 12 | 青少年不良 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf 校验失败<br />-400:请求错误<br />36201:举报弹幕不存在<br />36203:举报原因类型错误<br />36204:已举报 | +| message | str | 错误信息 | 默认为空 | +| tll | num | 1 | 举报失败时 | + +**示例** + +举报`cid=145928946`下的弹幕`35600074482384899`,理由是`引战` + +```shell +curl 'https://api.bilibili.com/x/dm/report/add' \ +--data-urlencode 'cid=145928946' \ +--data-urlencode 'dmid=35600074482384899' \ +--data-urlencode 'reason=7' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code":0, + "message":"" +} +``` + +</details> + +## 保护&删除弹幕 + +> https://api.bilibili.com/x/v2/dm/edit/state + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) 或APP + +注:只能操作自己的稿件或有骑士权限的稿件 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | --------------------------------------------- | +| access_key | str | APP登录Token | APP方式必要 | | +| type | num | 弹幕类选择 | 必要 | 1:视频弹幕 | +| oid | num | 视频cid | 必要 | | +| dmids | nums | 弹幕dmid | 必要 | 多个id之间用`,`分隔 | +| state | num | 操作代码 | 必要 | 1:删除弹幕<br />2:弹幕保护<br />3:取消保护 | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf 校验失败<br />-400:请求错误<br />-403:访问权限不足 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例** + +删除`cid=145928946`下的弹幕`35600074482384899`、`39067304918515717`、`39082777041174531` + +```shell +curl 'https://api.bilibili.com/x/v2/dm/edit/state' \ +--data-urlencode 'type=1' \ +--data-urlencode 'oid=145928946' \ +--data-urlencode 'dmids=35600074482384899,39067304918515717,39082777041174531' \ +--data-urlencode 'state=1' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code":0, + "message":"0", + "ttl":1 +} +``` + +</details> + +## 修改字幕池 + +> https://api.bilibili.com/x/v2/dm/edit/pool + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) 或APP + +注:只能操作自己的稿件或有骑士权限的稿件 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | -------------------------------- | +| access_key | str | APP登录Token | APP方式必要 | | +| type | num | 弹幕类选择 | 必要 | 1:视频弹幕 | +| oid | num | 视频cid | 必要 | | +| dmids | nums | 弹幕dmid | 必要 | 多个id之间用`,`分隔 | +| pool | num | 操作代码 | 必要 | 0:移出字幕池<br />1:移入字幕池 | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf 校验失败<br />-400:请求错误<br />-403:访问权限不足 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例** + +将`cid=145928946`下的弹幕`35600074482384899`、`39067304918515717`、`39082777041174531`移入字幕池 + +```shell +curl 'https://api.bilibili.com/x/v2/dm/edit/state' \ +--data-urlencode 'type=1' \ +--data-urlencode 'oid=145928946' \ +--data-urlencode 'pool=1' \ +--data-urlencode 'dmids=35600074482384899,39067304918515717,39082777041174531' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code":0, + "message":"0", + "ttl":1 +} +``` + +</details> diff --git a/bb-api-collect/docs/danmaku/buzzword.md b/bb-api-collect/docs/danmaku/buzzword.md new file mode 100644 index 0000000000..5f6535640c --- /dev/null +++ b/bb-api-collect/docs/danmaku/buzzword.md @@ -0,0 +1,508 @@ +# 名词解释 + +该功能用于解释和科普 B 站弹幕、评论等的专有名词及梗,展示其出处,并推荐相关站内内容 + +可使用页面 https://www.bilibili.com/blackboard/activity-joFQ0txEQd.html?type_id=4 查看名词列表 + +可使用页面 https://www.bilibili.com/blackboard/activity-WroMZNunfa.html?id=1 查看名词解释详情 + +## 拉取名词解释列表 + +> https://api.bilibili.com/x/v2/dm/buzzword/list + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | -------- | ------ | ---------------------------------------------- | +| type_id | num | 名词类型 | 必要 | 如:4代表“哔哩哔哩热词图鉴”<br />5代表“语言类” | +| pn | num | 页码 | 非必要 | 默认为1 | +| ps | num | 每页项数 | 非必要 | 默认为20 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | -------- | ---- | +| type | obj | 类型信息 | | +| buzzwords | array | 词语列表 | | +| page | obj | 页面信息 | | + +`data`中的`type`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | -------- | ------ | +| id | num | 类型 id | | +| name | str | 类型名称 | | +| name_pinyin | obj | 拼音信息 | 见副表 | + +`data`中的`buzzwords`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | obj | 名词条目 1 | | +| n | obj | 名词条目(n+1) | | +| …… | obj | …… | …… | + +`buzzwords`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ------------ | ----------------------------------------- | +| id | num | 名词 id | 用于[查询名词解释详情](#查询名词解释详情) | +| name | str | 名词 | | +| name_pinyin | obj | 拼音信息 | 见副表 | +| picture | str | 名词图片 url | | + +`data`中的`page`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | -------- | ---- | +| num | num | 当前页码 | | +| size | num | 每页项数 | | +| total | num | 总计项数 | | +| cnt | num | (?) | | + +副表:拼音`name_pinyin`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | -------- | ---- | +| 对应单个汉字 1 | str | 拼音字串 | | +| 对应单个汉字 n | str | 拼音字串 | | +| …… | str | …… | …… | + +**示例:** + +拉取对应`哔哩哔哩热词图鉴`的名词列表,以20项为一页拉取第1页 + +```bash +curl -G 'https://api.bilibili.com/x/v2/dm/buzzword/list' \ +--data-urlencode 'type_id=4' \ +--data-urlencode 'ps=10' \ +--data-urlencode 'pn=1' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "type": { + "id": 4, + "name": "哔哩哔哩热词图鉴", + "name_pinyin": { + "哔": "bì", + "哩": "lī", + "图": "tú", + "热": "rè", + "词": "cí", + "鉴": "jiàn" + }, + "level": 0 + }, + "buzzwords": [ + { + "id": 145, + "name": "麦乐鸡侠", + "name_pinyin": { + "乐": "lè", + "侠": "xiá", + "鸡": "jī", + "麦": "mài" + }, + "picture": "https://i0.hdslb.com/bfs/archive/1cdec1ff86733a38c1a9ff824dde6d4121955aee.png" + }, + { + "id": 146, + "name": "金钱豹", + "name_pinyin": { + "豹": "bào", + "金": "jīn", + "钱": "qián" + }, + "picture": "https://i0.hdslb.com/bfs/archive/3d492f4c01da7d15073d3175871e14ed56f0f78a.png" + }, + { + "id": 11, + "name": "通辽可汗", + "name_pinyin": { + "可": "kě", + "汗": "hàn", + "辽": "liáo", + "通": "tōng" + }, + "picture": "https://i0.hdslb.com/bfs/archive/ca332fb5f9da48497298cf26fe07b1f061e53a0b.jpg" + }, + { + "id": 123, + "name": "资本马桶搋", + "name_pinyin": { + "搋": "chuāi", + "本": "běn", + "桶": "tǒng", + "资": "zī", + "马": "mǎ" + }, + "picture": "https://i0.hdslb.com/bfs/archive/aaf33dced1941af0946f37c62f4b48fcaba9c9a2.jpg" + }, + { + "id": 133, + "name": "马了顶大", + "name_pinyin": { + "了": "le", + "大": "dà", + "顶": "dǐng", + "马": "mǎ" + }, + "picture": "https://i0.hdslb.com/bfs/archive/9653bd7f8d2c804aceb8043ebd5c8360a93e26c0.png" + }, + { + "id": 9, + "name": "退钱", + "name_pinyin": { + "退": "tuì", + "钱": "qián" + }, + "picture": "https://i0.hdslb.com/bfs/archive/2540db0bc94792b1f5be75e19aa05d33666e3036.jpg" + }, + { + "id": 141, + "name": "森林冰火人", + "name_pinyin": { + "人": "rén", + "冰": "bīng", + "林": "lín", + "森": "sēn", + "火": "huǒ" + }, + "picture": "https://i0.hdslb.com/bfs/archive/bc5ca101313d4db223c395d64779e76eb3482d60.jpg" + }, + { + "id": 22, + "name": "学霸题", + "name_pinyin": { + "学": "xué", + "霸": "bà", + "题": "tí" + }, + "picture": "https://i0.hdslb.com/bfs/archive/a67a0a57ec48beb8c8dcc9f26c7bb66cd0ed5da7.jpg" + }, + { + "id": 10, + "name": "张三", + "name_pinyin": { + "三": "sān", + "张": "zhāng" + }, + "picture": "https://i0.hdslb.com/bfs/archive/f4dac6fdc5c58639b79ae87385e9b9f7eae3b263.png" + }, + { + "id": 5, + "name": "饮茶先啦", + "name_pinyin": { + "先": "xiān", + "啦": "la", + "茶": "chá", + "饮": "yǐn" + }, + "picture": "https://i0.hdslb.com/bfs/archive/4c90ad207f0041e2dccd586827028aea50c2dc7d.jpg" + } + ], + "page": { + "num": 1, + "size": 10, + "total": 143, + "cnt": 0 + } + } +} +``` + +</details> + +## 查询名词解释详情 + +> https://api.bilibili.com/x/v2/dm/buzzword/detail + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------ | ------ | -------------------------------- | +| id | num | 名词id | 必要 | 如:1代表“kksk”<br />2代表“打脸” | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | --------------------------------- | -------- | --------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-404:不存在该名词 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 有数据时:obj<br />无数据时:null | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ------------------------------- | -------------------- | ----------------------------- | +| id | num | 名词id | | +| name | str | 名词 | | +| description | str | 名词解释 | | +| picture | str | 名词图片 url | | +| types | array | 父分类列表 | 该名词可能隶属多个父分类 | +| related_words | array | 近义词/相关词 | | +| uppers | 有数据:array<br />无数据:null | 相关 UP 列表 | 该名词(梗)出处 | +| related_ugc | 有数据:array<br />无数据:null | 相关 ucg 视频列表 | 该名词(梗)出处 | +| related_ogv | 有数据:array<br />无数据:null | 相关 pgc 视频列表 | 该名词(梗)出处 | +| guides | obj | 推荐创作信息 | | +| related_buzzwords | array | 推荐名词列表 | | +| topic | obj | 关联话题信息 | | +| show_dynamic | bool | 是否展示话题动态聚合 | `true`展示<br />`false`不展示 | + +`data`中的`types`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---- | +| 0 | obj | 父分类 1 | | +| n | obj | 父分类(n+1) | | +| …… | obj | …… | …… | + +`types`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | -------- | ---- | +| id | num | 类型 id | | +| name | str | 类型名称 | | +| name_pinyin | null | | | +| level | num | 权重? | | + +`data`中的`related_words`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------------- | ---- | +| 0 | str | 近义词/相关词1 | | +| n | str | 近义词/相关词(n+1) | | +| …… | str | …… | …… | + +`data`中的`uppers`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | ---- | +| 0 | obj | 相关 UP 1 | | +| n | obj | 相关 UP(n+1) | | +| …… | obj | …… | …… | + +`uppers`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------- | ------------------------------------------------------------ | +| id | num | UP 主 mid | | +| recommend | str | | | +| name | str | UP 主昵称 | | +| face | str | UP 主头像 url | | +| official | obj | UP 主认证信息 | | +| followed | bool | 是否关注 | 需要登录(Cookie 或 APP)<br />`true`已关注<br />`false`未关注 | +| fans_count | num | 粉丝数 | | + +`data`中的`related_ugc`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------------- | ---- | +| 0 | obj | 相关 ucg 视频 1 | | +| n | obj | 相关 ucg 视频(n+1) | | +| …… | obj | …… | …… | + +`related_ugc`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------------ | -------- | +| aid | num | 稿件 avid | | +| cid | num | 视频 cid | | +| name | str | 视频标题 | | +| link | str | 空 | | +| play | num | 播放数 | | +| danmaku | num | 弹幕数 | | +| duration | num | 视频时长 | 单位为秒 | +| cover | str | 视频封面 url | | + +`data`中的`related_ogv`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------------- | ---- | +| 0 | obj | 相关 pgc 视频 1 | | +| n | obj | 相关 pgc 视频(n+1) | | +| …… | obj | …… | …… | + +`related_ogv`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ------------ | ------------------------------------- | +| season_id | num | 剧集 ssid | | +| name | str | 剧集标题 | | +| play | num | 播放数 | | +| followed | num | 追剧/番数 | | +| is_followed | bool | 是否追剧/番 | `true`已追剧/番<br />`false`未追剧/番 | +| new_ep | str | 最新一集信息 | | +| cover | str | 剧集封面 url | | +| episodes | null | | | +| follow_info | obj | | | + +`data`中的`guides`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ----- | ---------------- | ---- | +| description | str | 创作推介文案 | | +| contribute_tags | array | 创作跳转按钮信息 | | + +`guides`中的`contribute_tags`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------------- | ---- | +| 0 | obj | 创作跳转按钮 1 | | +| n | obj | 创作跳转按钮(n+1) | | +| …… | obj | …… | …… | + +`contribute_tags`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | -------- | -------------------------- | +| title | str | 按钮文案 | | +| link | str | 跳转 uri | 跳转至必剪或客户端创作入口 | + +`data`中的`related_buzzwords`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | obj | 推荐名词 1 | | +| n | obj | 推荐名词(n+1) | | +| …… | obj | …… | …… | + +`related_buzzwords`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ------- | ----------------------------------------- | +| id | num | 名词 id | 用于[查询名词解释详情](#查询名词解释详情) | +| name | str | 名词 | | +| name_pinyin | null | | | +| picture | str | 空 | | + +`data`中的`topic`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------ | ---- | +| topic_id | num | 关联话题id | | +| topic_name | str | 关联话题名称 | | + +**示例:** + +查询名词`kksk`的详情 + +```bash +curl -G 'https://api.bilibili.com/x/v2/dm/buzzword/detail' \ +--data-urlencode 'id=1' +``` + +<details> +<summary>查看响应示例:</summary> + + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "id": 1, + "name": "kksk", + "description": "该梗是日语“ここすき”罗马音的字母缩写,翻译为喜欢这里。一般作为赞扬认可的弹幕出现在视频画面中。由于在2017年随着以《恶魔人》为BGM和语音剪辑素材的《美洲豹人》系列作品的传播,让这个梗快速的通过弹幕流行开,并频繁出现在各类稿件经典画面中。", + "picture": "https://i0.hdslb.com/bfs/archive/c269c9ca1b5eb730ee1d77aadd28e3165eaa4d6d.png", + "types": [ + { + "id": 4, + "name": "哔哩哔哩热词图鉴", + "name_pinyin": null, + "level": 0 + }, + { + "id": 5, + "name": "语言类", + "name_pinyin": null, + "level": 0 + }, + { + "id": 9, + "name": "空耳", + "name_pinyin": null, + "level": 0 + } + ], + "related_words": [ + "恶魔人", + "美洲豹人", + "喜欢这里" + ], + "uppers": [ + { + "id": 488450, + "recommend": "", + "name": "PXN1", + "face": "http://i2.hdslb.com/bfs/face/96dd8cc4f2922bd81e5a938f6ad02b3e3041debe.jpg", + "official": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "followed": false, + "fans_count": 1416 + } + ], + "related_ugc": [ + { + "aid": 30056798, + "cid": 52388183, + "name": "恶 魔 人", + "link": "", + "play": 3434500, + "danmaku": 8292, + "duration": 188, + "cover": "http://i0.hdslb.com/bfs/archive/f0433d2dacf4b3397a9390ab982cefd138dbf8c8.jpg" + } + ], + "related_ogv": null, + "guides": { + "description": "使用同款热梗素材创作你的专属作品吧!添加热梗主题#kksk是什么梗#参与投稿,优质稿件会优先展示在哔哩哔哩热词图鉴相关推荐中哦!", + "contribute_tags": [ + { + "title": "拍同款", + "link": "bilibili://uper/appTraffic?appScheme=bcut%3A%2F%2Fstudio%2Fmaterial_editor%2F%3Ftab_id%3D1%26sub_id%3D90160%26third_id%3D150281&appName=com.bilibili.studio&appID=1299589486" + } + ] + }, + "related_buzzwords": null, + "topic": { + "topic_id": 7642, + "topic_name": "kksk是什么梗" + }, + "show_dynamic": false + } +} +``` + +</details> diff --git a/bb-api-collect/docs/danmaku/config.md b/bb-api-collect/docs/danmaku/config.md new file mode 100644 index 0000000000..9cd760f345 --- /dev/null +++ b/bb-api-collect/docs/danmaku/config.md @@ -0,0 +1,71 @@ +# 弹幕个人配置修改 + +## 修改弹幕个人配置(web端) + +> https://api.bilibili.com/x/v2/dm/web/config + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或APP + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------ | ------ | ------------------------ | -------------- | ------------------------------------------------------------ | +| access_key | str | APP登录Token | APP方式必要 | | +| dm_switch | bool | 弹幕开关 | 非必要 | true:开启<br />false:关闭 | +| blockscroll | bool | 屏蔽类型-滚动 | 非必要 | true:不屏蔽<br />false:屏蔽 | +| blocktop | bool | 屏蔽类型-顶部 | 非必要 | 同上 | +| blockbottom | bool | 屏蔽类型-底部 | 非必要 | 同上 | +| blockcolor | bool | 屏蔽类型-彩色 | 非必要 | 同上 | +| blockspecial | bool | 屏蔽类型-特殊 | 非必要 | 同上 | +| ai_switch | bool | 是否打开智能云屏蔽 | 非必要 | true:开启<br />false:关闭 | +| ai_level | num | 智能云屏蔽等级 | 非必要 | 区间:[0-10]<br />0为默认等级(3级) | +| preventshade | bool | 防挡弹幕(底部15%) | 非必要 | true:开启<br />false:关闭 | +| dmask | bool | 智能防挡弹幕(人像蒙版) | 非必要 | 同上 | +| opacity | num | 弹幕不透明度 | 非必要 | 区间:[0-1] | +| dmarea | num | 弹幕显示区域 | 非必要 | 100:不重叠<br />75:3/4屏<br />50:半瓶<br />25:1/4屏<br />0:不限 | +| speedplus | num | 弹幕速度 | 非必要 | 区间:[0.4-1.6] | +| fontsize | num | 字体大小 | 非必要 | 区间:[0.4-1.6] | +| screensync | bool | 跟随屏幕缩放比例 | 非必要 | true:开启<br />false:关闭 | +| speedsync | bool | 根据播放倍速调整速度 | 非必要 | 同上 | +| fontfamily | str | 字体类型 | 非必要 | 未启用 | +| bold | bool | 粗体 | 非必要 | 未启用 | +| fontborder | num | 描边类型 | 非必要 | 0:重墨<br />1:描边<br />2:45°投影 | +| drawType | string | 渲染类型 | 非必要 | 未启用 | +| ts | num | 当前时间戳 | 非必要 | | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf校验失败<br />-400:请求错误<br />23004:数据没有修改 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +关闭弹幕 + +```shell +curl 'https://api.bilibili.com/x/v2/dm/web/config' \ +--data-urlencode 'dm_switch=false' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code":0, + "message":"0", + "ttl":1 +} +``` + +</details> \ No newline at end of file diff --git a/bb-api-collect/docs/danmaku/danmaku_proto.md b/bb-api-collect/docs/danmaku/danmaku_proto.md new file mode 100644 index 0000000000..b21bd3218c --- /dev/null +++ b/bb-api-collect/docs/danmaku/danmaku_proto.md @@ -0,0 +1,115 @@ +# protobuf弹幕 + +2020年5月23日,哔哩哔哩网页端及移动端启用了新的默认弹幕 API,网页端弹幕显示的上限变为原弹幕池上限的两倍。 + +新的 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)中获取 + +**注:仅获取 6min 的整数倍时间内的弹幕,6min 内最多弹幕数为 6000 条(如第一包中弹幕`progress`值域为0-360000)** + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------- | ---- | --------- | ------ | ---------------------------- | +| 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) + +- [protogen.marcgravell](https://protogen.marcgravell.com/): 在线编译 protogen 工具, 无需再安装本地编译器(生成文件需加后缀`_pb2.py`才可使用) + +- [protobuf pip](https://pypi.org/project/protobuf/): 可一键安装的 Python 的 protogen 解析库 + +消息`DmSegMobileReply`: + +| 名称 | 类型 | 含义 | 备注 | +| ----- | -------------------- | -------- | ---- | +| elems | repeated DanmakuElem | 弹幕条目 | | + +消息`DanmakuElem`: + +| 名称 | 类型 | 含义 | 备注 | +| --------- | ------ | ------------------ | ------------------------------------------------------------ | +| id | int64 | 弹幕 dmid | 唯一 可用于操作参数 | +| progress | int32 | 视频内弹幕出现时间 | 毫秒 | +| mode | int32 | 弹幕类型 | 1 2 3:普通弹幕<br />4:底部弹幕<br />5:顶部弹幕<br />6:逆向弹幕<br />7:高级弹幕<br />8:代码弹幕<br />9:BAS 弹幕(仅限于特殊弹幕专包) | +| 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 + +**注:以下[proto定义](../grpc_api/bilibili/community/service/dm/v1/dm.proto)需要编译,`bilibili.community.service.dm.v1.dm_pb2`并非通过 pypi 安装** + +```python +import requests +import google.protobuf.text_format as text_format +import bilibili.community.service.dm.v1.dm_pb2 as Danmaku + +url = 'https://api.bilibili.com/x/v2/dm/web/seg.so' +params = { + 'type': 1, # 弹幕类型 + 'oid': 1176840, # cid + 'pid': 810872, # avid + 'segment_index': 1 # 弹幕分段 +} +resp = requests.get(url, params) +data = resp.content + +danmaku_seg = Danmaku.DmSegMobileReply() +danmaku_seg.ParseFromString(data) + +print(text_format.MessageToString(danmaku_seg.elems[0], as_utf8=True)) +``` + +输出: + +``` +id: 711923911 +progress: 47880 +mode: 1 +fontsize: 18 +color: 10092288 +midHash: "59417e95" +content: "世界第一电击公主殿下,遇到你是我一生最美好的风景!吾炮赛高,永生不离!唯我超电磁炮永世长存! " +ctime: 1418799826 +weight: 6 +idStr: "711923911" +attr: 1 +``` + diff --git a/bb-api-collect/docs/danmaku/danmaku_view_proto.md b/bb-api-collect/docs/danmaku/danmaku_view_proto.md new file mode 100644 index 0000000000..4c761e3496 --- /dev/null +++ b/bb-api-collect/docs/danmaku/danmaku_view_proto.md @@ -0,0 +1,288 @@ +# 弹幕元数据 + +2020-09-25 B站更新了互动弹幕功能,包括UP主头像弹幕、关联视频弹幕、视频内嵌引导关注按钮三大功能 + +详情见: + +- [【客户端更新】6.10版本更新!UP主支持发布关联视频弹幕]( https://www.bilibili.com/read/cv7728299 ) +- [引导关注卡片](https://www.bilibili.com/blackboard/activity-c8a0iDRQy.html ) + +## 获取弹幕个人配置与互动弹幕及BAS(代码)弹幕专包(web端) + +> https://api.bilibili.com/x/v2/dm/web/view + +*请求方式:GET* + +认证方式:仅可Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ----------- | +| type | num | 弹幕类 | 必要 | 1:视频弹幕 | +| oid | num | 视频cid | 必要 | | +| pid | num | 稿件avid | 非必要 | | + +**proto回复:** + +消息`DmWebViewReply`: + +| 名称 | 类型 | 含义 | 备注 | +| ---------- | -------------------- | ---------------------- | ---------------------------- | +| state | int32 | 弹幕开放状态 | 0:开放弹幕<br />1:禁止弹幕 | +| text | string | ? | | +| textSide | string | ? | | +| dmSge | DmSegConfig | 分段弹幕包信息? | | +| flag | DanmakuFlagConfig | ? | | +| specialDms | repeated string | BAS(代码)弹幕专包url | | +| checkBox | bool | ? | | +| count | int64 | 实际弹幕总数 | 具有1500-6000不等的上限 | +| commandDms | repeated CommandDm | 互动弹幕条目 | | +| dmSetting | DanmuWebPlayerConfig | 弹幕个人配置 | 仅登录后存在 | + +消息`dmSge`: + +| 名称 | 类型 | 含义 | 备注 | +| -------- | ----- | ------------ | ---------- | +| pageSize | int64 | 分段时间? | 单位为毫秒 | +| total | int64 | 最大分页数? | | + +消息`flag`: + +| 名称 | 类型 | 含义 | 备注 | +| --------- | ------ | ---- | ---- | +| recFlag | int32 | ? | | +| recText | string | ? | | +| recSwitch | int32 | ? | | + +消息`commandDms`: + +| 名称 | 类型 | 含义 | 备注 | +| -------- | ------ | ------------ | ------------------------------------------------------------ | +| id | int64 | 弹幕dmid | | +| oid | int64 | 视频cid | | +| mid | int64 | 发送者mid | | +| command | string | 弹幕指令 | `#UP#`:UP主头像弹幕<br />`#LINK#`:关联视频弹幕<br />`#ATTENTION#`:视频内嵌引导关注按钮 | +| content | string | 弹幕文字 | | +| progress | int32 | 弹幕出现时间 | 单位为毫秒 | +| ctime | string | 创建时间? | 此项为空 | +| mtime | string | 修改时间? | 此项为空 | +| extra | string | 弹幕负载数据 | json序列字串 | +| idStr | string | 弹幕dmid | 字串形式 | + +`extra`json序列: + +类型为【UP主头像弹幕】时: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---- | +| icon | str | UP主头像url | | + +类型为【关联视频弹幕】时: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ------------------- | ---- | +| aid | num | 关联视频的avid | | +| title | str | 关联视频的标题 | | +| icon | str | 关联视频按钮图片url | | +| bvid | str | 关联视频的bvid | | + +类型为【视频内嵌引导关注按钮】时: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------------ | ------------------------------------------ | +| duration | num | 持续时间 | 单位为毫秒 | +| posX | num | X坐标 | 区间:[118-549] | +| posY | num | Y坐标 | 区间:[82-293] | +| icon | str | 按钮图片url | 不应该是关注按钮吗,但这个是圆形的 | +| type | num | 关注按钮类型 | 0:仅关注<br />1:仅三连<br />2:关注+三连 | + +消息`dmSetting`: + +| 名称 | 类型 | 含义 | 备注 | +| ------------ | ------ | ------------------------ | ------------------------------------------------------------ | +| dmSwitch | bool | 弹幕开关 | true:开启<br />false:关闭 | +| aiSwitch | bool | 智能云屏蔽 | 同上 | +| aiLevel | int32 | 智能云屏蔽级别 | 区间:[1-10] | +| blocktop | bool | 屏蔽类型-顶部 | true:不屏蔽<br />false:屏蔽 | +| blockscroll | bool | 屏蔽类型-滚动 | 同上 | +| blockbottom | bool | 屏蔽类型-底部 | 同上 | +| blockcolor | bool | 屏蔽类型-彩色 | 同上 | +| blockspecial | bool | 屏蔽类型-特殊 | 同上 | +| preventshade | bool | 防挡弹幕(底部15%) | true:开启<br />false:关闭 | +| dmask | bool | 智能防挡弹幕(人像蒙版) | 同上 | +| opacity | float | 弹幕不透明度 | 区间:[0-1] | +| dmarea | int32 | 弹幕显示区域 | 100:不重叠<br />75:3/4屏<br />50:半瓶<br />25:1/4屏<br />0:不限 | +| speedplus | float | 弹幕速度 | 区间:[0.4-1.6] | +| fontsize | float | 字体大小 | 区间:[0.4-1.6] | +| screensync | bool | 跟随屏幕缩放比例 | | +| speedsync | bool | 根据播放倍速调整速度 | | +| fontfamily | string | 字体类型? | 未启用 | +| bold | bool | 粗体? | 未启用 | +| fontborder | int32 | 描边类型 | 0:重墨<br />1:描边<br />2:45°投影 | +| drawType | string | 渲染类型? | 未启用 | + +protobuf结构体: + +**web_dmview.proto** + +```protobuf +syntax = "proto3"; + +//分段弹幕包信息? +message DmSegConfig { + int64 pageSize = 1; //分段时间? + int64 total = 2; //最大分页数? +} + +// +message DanmakuFlagConfig { + int32 recFlag = 1; // + string recText = 2; // + int32 recSwitch = 3; // +} + +// 互动弹幕条目 +message CommandDm { + int64 id = 1; //弹幕dmid + int64 oid = 2; //视频cid + int64 mid = 3; //发送者mid + string command = 4; //弹幕指令 + string content = 5; //弹幕文字 + int32 progress = 6; //弹幕出现时间 + string ctime = 7; // + string mtime = 8; // + string extra = 9; //弹幕负载数据 + string idStr = 10; //弹幕dmid(字串形式) +} + +//弹幕个人配置 +message DanmuWebPlayerConfig{ + bool dmSwitch=1; //弹幕开关 + bool aiSwitch=2; //智能云屏蔽 + int32 aiLevel=3; //智能云屏蔽级别 + bool blocktop=4; //屏蔽类型-顶部 + bool blockscroll=5; //屏蔽类型-滚动 + bool blockbottom=6; //屏蔽类型-底部 + bool blockcolor=7; //屏蔽类型-彩色 + bool blockspecial=8; //屏蔽类型-特殊 + bool preventshade=9; //防挡弹幕(底部15%) + bool dmask=10; //智能防挡弹幕(人像蒙版) + float opacity=11; //弹幕不透明度 + int32 dmarea=12; //弹幕显示区域 + float speedplus=13; //弹幕速度 + float fontsize=14; //字体大小 + bool screensync=15; //跟随屏幕缩放比例 + bool speedsync=16; //根据播放倍速调整速度 + string fontfamily=17; //字体类型? + bool bold=18; //粗体? + int32 fontborder=19; //描边类型 + string drawType=20; //渲染类型? +} + +message DmWebViewReply { + int32 state = 1; //弹幕开放状态 + string text = 2; // + string textSide = 3; // + DmSegConfig dmSge = 4; //分段弹幕包信息? + DanmakuFlagConfig flag = 5; // + repeated string specialDms = 6; //BAS(代码)弹幕专包url + bool checkBox = 7; // + int64 count = 8; //实际弹幕总数 + repeated CommandDm commandDms = 9; //互动弹幕条目 + DanmuWebPlayerConfig dmSetting = 10; //弹幕个人配置 +} +``` + +**示例:** + +获取视频`av797164471(cid=236871317)`的弹幕元数据 + +```shell +curl -G 'https://api.bilibili.com/x/v2/dm/web/view' \ +--data-urlencode 'type=1' \ +--data-urlencode 'oid=236871317' \ +--data-urlencode 'pid=797164471' \ +-b 'SESSDATA=xxx' \ +-o 'danmaku_view.bin' +``` + +响应正文为protubuf二进制数据 + +## 实例 + +### 获取互动弹幕 + +获取并显示视频`av797164471(cid=236871317)`的所有互动弹幕 + +```python +import web_dmview_pb2 +import requests + +AVID = 797164471 +CID = 236871317 +url = f'https://api.bilibili.com/x/v2/dm/web/view?type=1&oid={CID}&pid={AVID}' + +data = requests.get(url) +target = web_dmview_pb2.DmWebViewReply() +target.ParseFromString(data.content) + +print(f'互动弹幕数={len(target.commandDms)}') +for i in target.commandDms: + print(f'''\ +---弹幕ID={i.id} +---视频cid={i.oid} +---发送者mid={i.mid} +---弹幕指令={i.command} +---弹幕文字={i.content} +---弹幕出现时间={i.progress} +---弹幕负载数据={i.extra} +---弹幕ID(字串)={i.idStr}''' +) +``` + +输出为: + +``` +互动弹幕数=1 +---弹幕ID=38469676112019463 +---视频cid=236871317 +---发送者mid=501183549 +---弹幕指令=#UP# +---弹幕文字=这个视频没有恰饭!别紧张! +---弹幕出现时间=157818 +---弹幕负载数据={"icon":"https://i1.hdslb.com/bfs/face/559abe31f561f71f3106d8ee7b2065cac50c1235.jpg"} +---弹幕ID(字串)=38469676112019463 +``` + +### 获取BAS(代码)弹幕专包 + +BAS弹幕(`pool=2` `mode=9`)只能从此包获取,代码弹幕(`pool=2` `mode=8`)也能从此包获取 + +获取并显示视频`av2(cid=62131)`的所有BAS(代码)弹幕专包 + +```python +import web_dmview_pb2 +import requests + +AVID = 2 +CID = 62131 +url = f'https://api.bilibili.com/x/v2/dm/web/view?type=1&oid={CID}&pid={AVID}' + +data = requests.get(url) +target = web_dmview_pb2.DmWebViewReply() +target.ParseFromString(data.content) + +print(f'特殊弹幕包数={len(target.specialDms)}') +for i in target.specialDms: + print(f'特殊弹幕包url={i}') +``` + +输出为: + +``` +特殊弹幕包数=1 +特殊弹幕包url=https://i0.hdslb.com/bfs/dm/b0d5f08c12be59292aa0d4e09b6dd8e54c2ba886.bin +``` + +使用[普通分段包弹幕](danmaku_proto.md#获取实时弹幕)的proto结构体反序列化此bin数据 diff --git a/bb-api-collect/docs/danmaku/danmaku_xml.md b/bb-api-collect/docs/danmaku/danmaku_xml.md new file mode 100644 index 0000000000..a5ea9ca4bc --- /dev/null +++ b/bb-api-collect/docs/danmaku/danmaku_xml.md @@ -0,0 +1,145 @@ +# xml弹幕 + +实时弹幕池容量有限(根据视频类型500-8000条不等),占满后再发送会使实时弹幕池底部的弹幕压入历史弹幕池(类似于堆栈) + +## 获取实时弹幕1 + +> https://api.bilibili.com/x/v1/dm/list.so + +*请求方式:GET* + +**使用deflate压缩,注意解码** + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------- | ------ | ---- | +| oid | num | 视频cid | 必要 | | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/v1/dm/list.so' \ +--data-urlencode 'oid=144541892' \ +--compressed -o 'danmaku.xml' +``` + +## 获取实时弹幕2 + +> https://comment.bilibili.com/{cid}.xml + +*请求方式:GET* + +效果与前者相同 + +**使用deflate压缩,注意解码** + +**url路径:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------- | ------ | ---- | +| cid | num | 视频cid | 必要 | | + +**示例:** + +```shell +curl 'https://comment.bilibili.com/144541892.xml' +--compressed -o 'danmaku.xml' +``` + +**xml回复:** + +<details> +<summary>查看响应示例:</summary> + +```xml +<?xml version="1.0" encoding="UTF-8"?> +<i> + <chatserver>chat.bilibili.com</chatserver> + <chatid>144541892</chatid> + <mission>0</mission> + <maxlimit>1500</maxlimit> + <state>0</state> + <real_name>0</real_name> + <source>e-r</source> + <d p="490.19100,1,25,16777215,1584268892,0,a16fe0dd,29950852386521095">从结尾回来看这里,更感动了!</d> + <d p="18.77300,1,25,16777215,1584268920,0,4fe08d3,29950867226492933">咦三体居然还有动画</d> + <d p="52.88400,1,25,16777215,1584268954,0,4fe08d3,29950885214289927">哈哈哈哈开心</d> + <d p="25.51600,1,25,16777215,1584268957,0,e4b18b37,29950886612566021">红岸么</d> + <d p="144.45200,1,25,16777215,1584269076,0,e4b18b37,29950948716576775">我就是想看我的世界里水滴长啥样</d> + <d p="112.64100,1,25,16777215,1584269109,0,96606007,29950966302244871">有手指?</d> + <d p="222.84000,1,25,16777215,1584269154,0,e4b18b37,29950989809745923">侦测到在途的聚变打击</d> + <d p="284.77800,1,25,16777215,1584269216,0,e4b18b37,29951022237483011">都是虫子</d> + <d p="398.00500,1,25,16777215,1584269329,0,e4b18b37,29951081615196163">ocean</d> + <d p="432.17900,1,25,16777215,1584269363,0,e4b18b37,29951099571535943">村民,哼~</d> + <d p="467.41900,1,25,16777215,1584269399,0,e4b18b37,29951118364639237">黄河之水天上来</d> + <d p="6.71900,1,25,16777215,1584269422,0,70ba16f4,29951130398621699">镇站之宝</d> + <d p="313.08600,1,25,16777215,1584269425,0,e531c9dc,29951131798994947">这水</d> + <d p="587.87900,1,25,16777215,1584269519,0,e4b18b37,29951181142360071">海的那边是什么</d> + <d p="618.05000,1,25,16777215,1584269549,0,e4b18b37,29951196901933061">折跃门准备完毕</d> + ………… +<i> +``` + +</details> + +## 弹幕格式 + +### xml格式结构 + +- 标签 i + + - 标签 chatserver:chat.bilibili.com + - 标签 chatid:视频cid + - 标签 mission:0 + - 标签 maxlimit:实时弹幕池最大容量 + - 标签 state:弹幕状态(0:正常 1:弹幕已关闭) + - 标签 real_name:0 + - 标签 source:e-r + + - 标签 d (带有属性 p):弹幕内容 + +### 属性 p + +字符串内每项用逗号`,`分隔 + +| 项 | 含义 | 类型 | 备注 | +| ---- | ------------------ | ------ | ------------------------------------------------------------ | +| 0 | 视频内弹幕出现时间 | float | 秒 | +| 1 | 弹幕类型 | int32 | 1 2 3:普通弹幕<br />4:底部弹幕<br />5:顶部弹幕<br />6:逆向弹幕<br />7:高级弹幕<br />8:代码弹幕<br />9:BAS弹幕(`pool`必须为2) | +| 2 | 弹幕字号 | int32 | 18:小<br />25:标准<br />36:大 | +| 3 | 弹幕颜色 | int32 | 十进制RGB888值 | +| 4 | 弹幕发送时间 | int32 | 时间戳 | +| 5 | 弹幕池类型 | int32 | 0: 普通池<br />1: 字幕池<br />2: 特殊池 (代码/BAS弹幕)<br />3: 互动池?| +| 6 | 发送者mid的HASH | string | 用于屏蔽用户和查看用户发送的所有弹幕 也可反查用户id | +| 7 | 弹幕dmid | int64 | 唯一 可用于操作参数 | +| 8 | 弹幕的屏蔽等级 | int32 | 0-10,低于用户设定等级的弹幕将被屏蔽<br />(新增,下方样例未包含) | + +```xml +<d p="490.19100,1,25,16777215,1584268892,0,a16fe0dd,29950852386521095">从结尾回来看这里,更感动了!</d> +``` + +弹幕内容为:“从结尾回来看这里,更感动了!” + +参数为:视频内出现的时间是490.19100秒,类型是普通弹幕,字号为标准,颜色为白色(#FFFFFF),发送时间是2020/3/15 18:41:32......... + +### web版标准颜色 + +弹幕的颜色属性使用**十进制RGB888**值 + +| 颜色 | HEX(RGB888) | DEC(RGB888) | +| -------------------------------------- | ----------------------------------------- | ------------------------------------------- | +| <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> | diff --git a/bb-api-collect/docs/danmaku/history.md b/bb-api-collect/docs/danmaku/history.md new file mode 100644 index 0000000000..a20f15acdb --- /dev/null +++ b/bb-api-collect/docs/danmaku/history.md @@ -0,0 +1,240 @@ +# 历史弹幕 + +**注:历史弹幕的xml接口已经失效,现已改为protobuf接口** + +## 查询历史弹幕日期 + +> https://api.bilibili.com/x/v2/dm/history/index + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**注:查询历史弹幕需要登录** + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------ | ------ | ------- | +| type | num | 1 | 必要 | | +| oid | num | 视频cid | 必要 | | +| month | str | 查询目标年月 | 必要 | YYYY-MM | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------------------------------- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 有弹幕:array<br />无弹幕:null | 日期列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------------- | ---------- | +| 0 | str | 存在弹幕的日期1 | YYYY-MM-DD | +| n | str | 存在弹幕的日期(n+1) | YYYY-MM-DD | +| …… | str | …… | …… | + +**示例:** + +查询了cid为144541892的视频位于2020年1月中有历史弹幕记录的日期 + +```shell +curl -G 'https://api.bilibili.com/x/v2/dm/history/index' \ +--data-urlencode 'type=1' \ +--data-urlencode 'oid=144541892' \ +--data-urlencode 'month=2020-01' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + "2020-01-21", + "2020-01-22", + "2020-01-23", + "2020-01-24", + "2020-01-25", + "2020-01-26", + "2020-01-27", + "2020-01-28", + "2020-01-29", + "2020-01-30", + "2020-01-31" + ] +} +``` + +</details> + +返回结果的 `data` 项说明这些日期有弹幕发送。若查询的月份中视频无弹幕,则 `data` 项为 `null` + +```shell +curl -G 'https://api.bilibili.com/x/v2/dm/history/index' \ +--data-urlencode 'type=1' \ +--data-urlencode 'oid=144541892' \ +--data-urlencode 'month=2019-12' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": null +} +``` + +</details> + +## 获取历史弹幕protobuf接口 + +> https://api.bilibili.com/x/v2/dm/web/history/seg.so + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ----------- | +| type | num | 弹幕类 | 必要 | 1:视频弹幕 | +| oid | num | 视频cid | 必要 | | +| date | str | 弹幕日期 | 必要 | YYYY-MM-DD | + +**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) + +获取视频`av84271171(cid=144541892)`2020-01-21的历史弹幕 + +**注:proto定义需要编译** + +```python +import requests +import google.protobuf.text_format as text_format +import bilibili.community.service.dm.v1_pb2 as Danmaku + +url = 'https://api.bilibili.com/x/v2/dm/web/history/seg.so' +params = { + 'type':1, #弹幕类型 + 'oid':144541892, #cid + 'date':'2020-01-21' #弹幕日期 +} +cookies = { + 'SESSDATA':'xxx' +} +resp = requests.get(url,params,cookies=cookies) +data = resp.content + +danmaku_seg = Danmaku.DmSegMobileReply() +danmaku_seg.ParseFromString(data) + +print(text_format.MessageToString(danmaku_seg.elems[0],as_utf8=True)) +``` + +输出: + +``` +id: 27532611677585408 +progress: 300507 +mode: 1 +fontsize: 25 +color: 16777215 +midHash: "2a28d4a6" +content: "章北海的老爹" +ctime: 1579621359 +idStr: "27532611677585408" +``` + +## 获取历史弹幕xml接口 + +<details> +<summary>查看折叠内容:</summary> + +> https://api.bilibili.com/x/v2/dm/history + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**注:查询历史弹幕需要登录** + +结果为[标准xml格式弹幕](danmaku_xml.md#弹幕格式) + +**使用deflate压缩,注意解码** + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---------- | +| type | num | 1 | 必要 | | +| oid | num | 视频cid | 必要 | | +| date | str | 弹幕日期 | 必要 | YYYY-MM-DD | + +**示例:** + +获取视频`av84271171(cid=144541892)`2020-01-21的历史弹幕 + +```shell +curl -G 'https://api.bilibili.com/x/v2/dm/history' \ +--data-urlencode 'type=1' \ +--data-urlencode 'oid=144541892' \ +--data-urlencode 'date=2020-01-21' \ +-b 'SESSDATA=xxx' \ +--compressed -o 'danmaku.xml' +``` + +<details> +<summary>查看响应示例:</summary> + +```xml +<?xml version="1.0" encoding="UTF-8"?> +<i> + <chatserver>chat.bilibili.com</chatserver> + <chatid>144541892</chatid> + <mission>0</mission> + <maxlimit>1500</maxlimit> + <state>0</state> + <real_name>0</real_name> + <d p="473.43400,1,25,15138834,1579622380,0,ec16f2d,27532609919123456">敬礼</d> + <d p="3.10200,1,25,16777215,1579622362,0,a2bd7474,27532609920696320">悄默声的更新啊怎么</d> + <d p="17.52300,1,25,16777215,1579622357,0,972c932b,27532609906016258">久等了</d> + <d p="40.81800,1,25,16777215,1579622343,0,bbca6701,27532609906540546">不都是乱纪元才浸泡</d> + <d p="243.39800,1,25,15138834,1579622336,0,77b00ed9,27532609924890624">已阅,狗屁不通。大字报在地上搞搞就行,别弄到天上去</d> + <d p="559.80000,1,25,16777215,1579622334,0,9affc7f5,27532609909686274">CSSC。。。</d> + <d p="398.29700,1,25,16777215,1579622331,0,18d4707,27532609926463488">看到了个寂寞</d> + <d p="34.81000,1,25,38979,1579622327,0,319d7700,27532609926987776">有耳朵了!</d> + <d p="18.65700,1,25,16777215,1579622321,0,bbca6701,27532609912307714">雪天不用浸泡吧</d> + <d p="305.99800,1,25,16777215,1579622316,0,878c315b,27532609928560640">未来史学派</d> + <d p="7.86200,1,25,16777215,1579622309,0,c5136613,27532609913880578">浸泡!!!!!!!</d> + <d p="368.95600,1,25,16777215,1579622302,0,18d4707,27532609914404866">章召忠</d> + <d p="25.19800,1,25,16777215,1579622286,0,4dab6898,27532609931706368">mi24av</d> + <d p="41.10100,1,25,16777215,1579622274,0,33d31036,27532609932230656">泪奔</d> + <d p="627.69800,1,25,16777215,1579622264,0,d79a826a,27532609933279232">组建太空军</d> + <d p="310.58900,1,25,16777215,1579622243,0,18d4707,27532609918074882">是未来史学派?</d> + <d p="723.34800,1,25,16777215,1579622239,0,844fa9e7,27532609919123458">刘培强还行</d> + ………… +<i> +``` + +</details> + +</details> diff --git a/bb-api-collect/docs/danmaku/snapshot.md b/bb-api-collect/docs/danmaku/snapshot.md new file mode 100644 index 0000000000..69f098b5d3 --- /dev/null +++ b/bb-api-collect/docs/danmaku/snapshot.md @@ -0,0 +1,88 @@ +# 弹幕快照 + +## 获取弹幕快照 + +> https://api.bilibili.com/x/v2/dm/ajax + +*请求方式:GET* + +最近产生的几条弹幕内容,**最多20条** + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | -------- | ------------------ | ------ | ---- | +| aid | num或str | 稿件avid或稿件bvid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | --------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-404:无视频 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | array | 预览列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | -------- | +| 0 | str | 预览内容1 | | +| n | str | 预览内容(n+1) | | +| …… | str | …… | …… | +| 19 | str | 预览内容20 | 最后一条 | + +**示例:** + +获取视频`av43337021`/`BV1rb411m7gE`的弹幕快照,总计20条 + +avid方式: + +```shell +curl -G 'https://api.bilibili.com/x/v2/dm/ajax' \ +--data-urlencode 'aid=43337021' +``` + +bvid方式: + +```shell +curl -G 'https://api.bilibili.com/x/v2/dm/ajax' \ +--data-urlencode 'aid=BV1rb411m7gE' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + "漫画比动漫好看而且血腥", + "666", + "金木小天使", + "太喜欢了", + "每天一遍防止抑郁", + "我还记得土豆那时候还有的看", + "把在给我摸摸~", + "突然泪目", + "感谢野生字幕君", + "993-7", + "刚刚出的时候小学看,现在高二了", + "原版op有这么长吗?搞笑,肯定做了剪辑,op会给你放全歌?", + "让你看个op 3 : 5 4 秒?", + "说原版不原版的都是弱智", + "樱花", + "请打开洗脑循环食用,请打开洗脑循环食用,请打开洗脑循环食用,请打开洗脑循环食用,请打开洗脑循环食用,", + "再来亿遍", + "错的不是我,而是这个世界。", + "吃货的第一季的最后一季足以让他封神!", + "+" + ] +} +``` + +</details> diff --git a/bb-api-collect/docs/danmaku/thumbup.md b/bb-api-collect/docs/danmaku/thumbup.md new file mode 100644 index 0000000000..0d59ff941a --- /dev/null +++ b/bb-api-collect/docs/danmaku/thumbup.md @@ -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 1P(cid=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> diff --git a/bb-api-collect/docs/danmaku/webmask.md b/bb-api-collect/docs/danmaku/webmask.md new file mode 100644 index 0000000000..ab0fff82b2 --- /dev/null +++ b/bb-api-collect/docs/danmaku/webmask.md @@ -0,0 +1,80 @@ +# 智能防挡弹幕 + +B 站部分视频提供“智能防挡弹幕”功能,其原理是提供了一个 webmask 二进制文件,其中保存了视频中各个位置的 svg 格式蒙版。 + +首先需要获取 webmask 资源的地址。 + +## 获取 webmask 资源地址 + +通过 [web 播放器资源接口](../video/player.md) 获取 webmask 二进制文件的地址。 + + +## webmask 资源 + +获取的 url 没有权鉴,不需要后面的参数也可以获取。 + +示例: + +```shell +curl -G https://upos-sz-staticcos-cmask.bilivideo.com/cmaskboss/825851971_30_0.webmask >> 825851971_30_0.webmask +``` + +下载后是二进制文件。 + + +## webmask 二进制读取 + +参考:[andrewvy/webmask-renderer](https://github.com/andrewvy/webmask-renderer) + +name | offset | length | type | desc +--- | ------ | ------ | ---- | ---- +mask | 0 | 4 | char | 'MASK' 文件头 +version| 4 | 4 | int | 是1 +vU | 8 | 4 | ? | 不知道是干什么的 +Ly | 12 | 4 | int | 后续数据的段数 +time_1 | 16 | 8 | long | 第一段对应视频开始时间 +offset_1 | 24 | 8 | long | 第一段蒙版信息开始处对应二进制偏移 +...|...|...|...|... +time_{Ly} |16+(Ly-1)*16| 8 | long | 第 `Ly` 段对应视频开始时间 +offset_{Ly} |24+(Ly-1)*16| 8 | long | 第 `Ly` 段蒙版信息开始处对应二进制偏移 +segments_1| 由前面offset_1提供 | 由 `offset_2-offset_1` 计算得到 | binary | 蒙版信息块,使用 gzip 压缩 +...|...|...|...|... + + +蒙版信息块是经过 gzip 压缩文本得到的二进制。解压缩后得到一个字节串。 + +前 16 字节是两个 long,记为 `left` 和 `right`,暂时不清楚其作用。`left` 似乎和平均每张蒙版的时间有关。`right` 总是 `i*10000`,`i` 是从 0 开始数的数据段次序。 + +后面是各个 svg 文本直接拼起来,可以直接通过 svg 格式头 `data:image/svg+xml;base64,` 分开。 + + +Python 示例: +```python +from struct import unpack +import gzip + +f = open('你的 webmask', 'rb') +buf = f.read() +_Ly = buf[12:16] +Ly = unpack('>i', _Ly)[0] # 大端序 int + +times = [] +offsets = [] +for idx in range(Ly): + op = 16 + idx * 16 # 个人习惯,我算偏移时喜欢用 `op` 和 `ed` 作为开始和结束的名字。 + time = unpack('>q', buf[op: op+8])[0] + offset = unpack('>q', buf[op+8: op+16])[0] + times.append(time) + offsets.append(offset) + +frames = [] +for idx in range(Ly): + op = offsets[idx] + if idx == Ly - 1: ed = len(buf) + else: ed = offsets[idx+1] + ba = buf[op: ed] + bad = gzip.decompress(ba) + badl = bad.split(b'data:image/svg+xml;base64,') + # badl[0]是16字节,`left` 和 `right` + frames.append(badl[1: ]) +``` diff --git a/bb-api-collect/docs/dynamic/action.md b/bb-api-collect/docs/dynamic/action.md new file mode 100644 index 0000000000..aa55d2b5db --- /dev/null +++ b/bb-api-collect/docs/dynamic/action.md @@ -0,0 +1,351 @@ +# 动态操作 + +## 点赞动态 + +> https://api.bilibili.com/x/dynamic/feed/dyn/thumb + +*请求方法: POST* + +认证方式: Cookie (SESSDATA) + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ------ | ------ | ------ | ---- | +| csrf | string | CSRF Token (即 Cookie 中 bili_jct) | 必要 | | + +**正文参数 (application/json):** + +根对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ------ | -------- | ------ | ---- | +| dyn_id_str | string | 动态 id | 必要 | | +| up | number | 点赞状态 | 必要 | 0: 切换<br />1: 点赞<br />2: 取消点赞 | +| spmid | string | `333.1369.0.0` | 不必要 | | +| from_spmid | string | `333.999.0.0` | 不必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ------ | ---- | ---- | +| code | number | 返回值 | 0: 成功<br />-101: 账号未登录<br />-111: csrf 校验失败<br />4100001: 参数错误 | +| message | string | 错误消息 | 成功时为 `0` | +| ttl | number | `1` | | +| data | object | 空对象 | | + +**示例:** + +点赞动态 `1057955152016703512` + +```shell +curl -X POST 'https://api.bilibili.com/x/dynamic/feed/dyn/thumb' \ + --url-query 'csrf=xxx' \ + -b 'SESSDATA=xxxxx' \ + -H 'content-type: application/json' \ + --data-raw '{"dyn_id_str":"1057955152016703512","up":1}' +``` +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": {} +} +``` + +</details> + +## 点赞动态 (旧版) + +> https://api.vc.bilibili.com/dynamic_like/v1/dynamic_like/thumb + +*请求方法: POST* + +认证方式: Cookie (SESSDATA) + +**正文参数 (application/x-www-form-urlencoded):** + +根对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ------ | -------- | ------ | ---- | +| dynamic_id | string | 动态 id | 必要 | | +| up | number | 点赞状态 | 必要 | 0: 切换<br />1: 点赞<br />2: 取消点赞 | +| csrf | string | CSRF Token (即 Cookie 中 bili_jct) | 必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ------ | ---- | ---- | +| code | number | 返回值 | 0: 成功<br />-101: 账号未登录<br />-111: csrf 校验失败<br />4100001: 参数错误 | +| message | string | 错误消息 | 成功时为 `0` | +| ttl | number | `1` | | +| data | object | 空对象 | | + +**示例:** + +点赞动态 `1060771233257226247` + +```shell +curl -X POST 'https://api.vc.bilibili.com/dynamic_like/v1/dynamic_like/thumb' \ --data-urlencode 'csrf=xxxxxx' \ + --data-urlencode 'dynamic_id=1060771233257226247' \ + --data-urlencode 'up=1' \ + -b 'SESSDATA=xxx' +``` +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": {} +} +``` + +</details> + +## 删除动态 + +参见 [创作中心 -> 图文操作 -> 删除动态](../creativecenter/opus.md#删除动态) + +## 删除动态 (旧版) + +> <https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/rm_dynamic> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数(multipart/form-data):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------ | ------ | ---- | +| dynamic_id | num | 动态id | 必要 | | +| csrf_token | str | csrf | 必要 | | +| csrf | str | csrf | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />500404:已经删除过该动态<br />500406:动态不是自己的 | +| msg | str | 错误信息 | 成功时为空文本 | +| message | str | 错误信息 | 同`msg` | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ---- | ---------------- | +| \_gt\_ | num | 0 | **作用尚不明确** | + +**示例:** + +删除动态`dynamic_id=588320531406678918` + +```shell +curl 'https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/rm_dynamic' \ + --data-urlencode 'dynamic_id=588320531406678918' \ + --data-urlencode 'csrf_token=xxx' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "", + "message": "", + "data": { + "_gt_": 0 + } +} +``` + +</details> + +## 删除定时发布动态 + +> <https://api.vc.bilibili.com/dynamic_draft/v1/dynamic_draft/rm_draft> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------ | ---- | +| draft_id | num | 定时发布动态id | 必要 | | +| csrf_token | str | csrf | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------ | +| code | num | 返回值 | 0:成功<br />4120015:系统异常 | +| message | str | 错误信息 | | +| ttl | num | 1 | | +| data | obj | 数据本体 | 空对象,即`{}` | + +**示例:** + +删除定时发布动态`draft_id=755409289278914611` + +```shell +curl 'https://api.vc.bilibili.com/dynamic_draft/v1/dynamic_draft/rm_draft' \ + --data-urlencode 'draft_id=755409289278914611' \ + --data-urlencode 'csrf=xxxx' + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": {} +} +``` + +</details> + +## 设置置顶动态 + +> https://api.bilibili.com/x/dynamic/feed/space/set_top + +**请求方法: POST** + +认证方式: Cookie (SESSDATA) + +鉴权方式: Cookie 中 `buvid3` 不为空 + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ------ | ------ | ------ | ---- | +| csrf | string | CSRF Token (即 Cookie 中 bili_jct) | 必要 | | + +**正文参数 (application/json):** + +根对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ------ | -------- | ------ | ---- | +| dyn_str | string | 动态 id | 必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ------ | ---- | ---- | +| code | number | 返回值 | 0: 成功<br />-101: 账号未登录<br />-111: csrf 校验失败<br />4100001: 参数错误 | +| message | string | 错误消息 | 成功时为 `0` | +| ttl | number | `1` | | +| data | object | 空对象 | | + +**示例:** + + +置顶动态 `1063487284684259332` + +```shell +curl -X POST 'https://api.bilibili.com/x/dynamic/feed/space/set_top' \ + --url-query 'csrf=xxx' \ + -b 'SESSDATA=xxxxx; buvid3=aaa' \ + -H 'content-type: application/json' \ + --data-raw '{"dyn_str":"1063487284684259332"}' +``` +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": {} +} +``` + +</details> + +## 取消置顶动态 + +> https://api.bilibili.com/x/dynamic/feed/space/rm_top + +**请求方法: POST** + +认证方式: Cookie (SESSDATA) + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ------ | ------ | ------ | ---- | +| csrf | string | CSRF Token (即 Cookie 中 bili_jct) | 必要 | | + +**正文参数 (application/json):** + +根对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ------ | -------- | ------ | ---- | +| dyn_str | string | 动态 id | 必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ------ | ---- | ---- | +| code | number | 返回值 | 0: 成功<br />-101: 账号未登录<br />-111: csrf 校验失败<br />4100001: 参数错误 | +| message | string | 错误消息 | 成功时为 `0` | +| ttl | number | `1` | | +| data | object | 空对象 | | + +**示例:** + + +取消置顶动态 `1063487284684259332` + +```shell +curl -X POST 'https://api.bilibili.com/x/dynamic/feed/space/rm_top' \ + --url-query 'csrf=xxx' \ + -b 'SESSDATA=xxxxx' \ + -H 'content-type: application/json' \ + --data-raw '{"dyn_str":"1063487284684259332"}' +``` +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": {} +} +``` + +</details> diff --git a/bb-api-collect/docs/dynamic/all.md b/bb-api-collect/docs/dynamic/all.md new file mode 100644 index 0000000000..8c69ddfaa4 --- /dev/null +++ b/bb-api-collect/docs/dynamic/all.md @@ -0,0 +1,7770 @@ +# 获取动态列表 + +## 获取全部动态列表 + +> https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/all + +*请求方式: GET* + +认证方式: Cookie (SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 必要性 | 内容 | 备注 | +| --- | --- | --- | --- | --- | +| timezone_offset | str | 非必要 | `-480` | 新版无 | +| type | str | 非必要 | 分类 | 新版无, `all`:全部(默认)<br/>`video`:视频投稿<br/>`pgc`:追番追剧<br/>`article`:专栏 | +| host_mid | num | 非必要 | UP主UID | 仅新版, 如 `293793435` | +| offset | num | 非必要 | 分页偏移量 | 默认为空, 翻页时使用 | +| update_baseline | str | 非必要 | 更新基线 | 获取新动态时使用 | +| page | num | 非必要 | 页数 | 无效参数 | +| platform | str | 非必要 | 平台 | 仅新版, 如 `web` | +| features | str | 非必要 | 功能开关? | 旧版 `itemOpusStyle,listOnlyfans`<br />新版 `itemOpusStyle,listOnlyfans,opusBigCover,onlyfansVote,decorationCard,onlyfansAssetsV2,forwardListHidden,ugcDelete` | +| web_location | str | 非必要 | 333.1365 | 仅新版存在 | + +**JSON回复:** + +根: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 响应码 | 0:成功<br/>-101:账号未登录 | +| message | str | | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| has_more | bool | 是否有更多数据 | | +| items | array | 数据数组 | | +| offset | str | 偏移量 | 等于`items`中最后一条记录的id<br/>获取下一页时使用 | +| update_baseline | str | 更新基线 | 等于`items`中第一条记录的id | +| update_num | num | 本次获取获取到了多少条新动态 | 在更新基线以上的动态条数 | + +`data.items[n]`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| basic | obj | | | +| id_str | str | 动态id | | +| modules | obj | 动态信息 | | +| type | str | 动态类型 | [动态类型](./dynamic_enum.md#动态类型) | +| visible | bool | 是否显示 | `true`:正常显示<br/>`false`:折叠动态 | +| orig | obj | 原动态信息 | 仅动态类型为`DYNAMIC_TYPE_FORWARD`的情况下存在 | + +`data.items[n].basic`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| comment_id_str | str | 见 [动态类型](./dynamic_enum.md#动态类型) | +| comment_type | num | | 见 [动态类型](./dynamic_enum.md#动态类型) | +| like_icon | obj | | 见下 | +| rid_str | str | | 见 [动态类型](./dynamic_enum.md#动态类型) | + +`data.items[n].basic.like_icon`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| action_url | str | `空串` | | +| end_url | str | `空串` | | +| id | num | `0` | | +| start_url | str | `空串` | | + +`data.items[n].modules`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| module_author | obj | UP主信息 | 参见 [MODULE_TYPE_AUTHOR](../opus/features.md#module-type-author) 中的 `module_author` 对象 | +| module_dynamic | obj | 动态内容信息 | | +| module_more | obj | 动态右上角三点菜单 | 参见 [module_more](../opus/features.md#module-more) 中的 `module_more` 对象 | +| module_stat | obj | 动态统计数据 | 参见 [MODULE_TYPE_STAT](../opus/features.md#module-type-stat) 中的 `module_stat` 对象 | +| module_interaction | obj | 热度评论 | | +| module_fold | obj | 动态折叠信息 | | +| module_dispute | obj | 争议小黄条 | | +| module_tag | obj | 置顶信息 | | + +`data.items[n].modules.module_dynamic`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| additional | obj | 相关内容卡片信息 | | +| desc | obj | 动态文字内容 |其他动态时为null | +| major | obj | 动态主体对象 |转发动态时为null | +| topic | obj | 话题信息 | 无时为 null, 参见 [MODULE_TYPE_TOPIC](../opus/features.md#module-type-topic) | + +`data.items[n].modules.module_dynamic.additional`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| common | obj | 一般类型 | `ADDITIONAL_TYPE_COMMON`类型独有 | +| type | str | 卡片类型 | [相关内容卡片类型](./dynamic_enum.md#相关内容卡片类型) | +| reserve | obj | 预约信息 | `ADDITIONAL_TYPE_RESERVE`类型独有 | +| goods | obj | 商品内容 | `ADDITIONAL_TYPE_GOODS`类型独有 | +| vote | obj | 投票信息 | `ADDITIONAL_TYPE_VOTE`类型独有 | +| ugc | obj | 视频信息 | `ADDITIONAL_TYPE_UGC`类型独有 | +| match | object | 比赛信息? | `ADDITIONAL_TYPE_MATCH`类型独有, 参见 [MODULE_TYPE_CONTENT](../opus/features.md#module-type-content) 的 `module_content.paragraphs[].link_card.match` | +| upower_lottery | object | 充电专属抽奖信息 | `ADDITIONAL_TYPE_UPOWER_LOTTERY`类型独有, 参见 [MODULE_TYPE_CONTENT](../opus/features.md#module-type-content) 的 `module_content.paragraphs[].link_card.upower_lottery` | + +`data.items[n].modules.module_dynamic.additional.common`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| button | obj | 按钮内容 | | +| cover | str | 左侧封面图 | | +| desc1 | str | 描述1 | | +| desc2 | str | 描述2 | | +| head_text | str | 卡片头文本 | | +| id_str | str | 相关id | | +| jump_url | str | 跳转URL | | +| style | num | `1` | | +| sub_type | str | 子类型 | `game`<br/>`decoration`<br/>`ogv` | +| title | str | 卡片标题 | | + +`data.items[n].modules.module_dynamic.additional.common.button`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| jump_style | obj | 跳转类型 | `game`和`decoration`类型特有 | +| jump_url | str | 跳转URL | | +| type | num | | 1:`game`和`decoration`类型<br/>2:`ogv`类型 | +| check | obj | | `ogv`类型特有 | +| status | num | `1` | | +| uncheck | obj | | `ogv`类型特有 | + +`data.items[n].modules.module_dynamic.additional.common.button.jump_style`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| icon_url | str | `空串` | | +| text | str | 按钮显示文案 | game:`进入`<br/>decoration:`去看看` | + +`data.items[n].modules.module_dynamic.additional.common.button.check`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| icon_url | str | 按钮图片URL | | +| text | str | 按钮显示文案 | `ogv`:已追剧 | + +`data.items[n].modules.module_dynamic.additional.common.button.uncheck`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| icon_url | str | 按钮图片URL | | +| text | str | 按钮显示文案 | `ogv`:追剧 | + +`data.items[n].modules.module_dynamic.additional.reserve`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| button | obj | 按钮信息 | | +| desc1 | obj | 预约时间 | | +| desc2 | obj | 预约观看量 | | +| jump_url | str | 跳转URL | | +| reserve_total | num | 预约人数 | | +| rid | num | | | +| state | num | `0` | | +| stype | num | `1` `2` | | +| title | str | 预约标题 | | +| up_mid | num | 预约发起人UID | | +| desc3 | obj | 预约有奖信息 | | + +`data.items[n].modules.module_dynamic.additional.reserve.button`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| check | obj | 已预约状态显示内容 | | +| status | num | 预约状态 | 1:未预约,使用`uncheck`<br/>2:已预约,使用`check` | +| type | num | 类型 | 1:视频预约,使用`jump_style`<br/>2:直播预约,使用`check`和`uncheck` | +| uncheck | obj | 未预约状态显示内容 | | +| jump_style | obj | 跳转按钮 | | +| jump_url | str | 跳转URL | | + +`data.items[n].modules.module_dynamic.additional.reserve.button.check`对象" + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| icon_url | str | `空串` | | +| text | str | 按钮显示文案 | `已预约` | + +`data.items[n].modules.module_dynamic.additional.reserve.button.uncheck`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| icon_url | str | 显示图标URL | | +| text | str | 按钮显示文案 | | +| toast | str | 预约成功显示提示文案 | | +| disable | num | 是否不可预约 | 1:是 | + +`data.items[n].modules.module_dynamic.additional.reserve.button.jump_style`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| icon_url | str | `空串` | | +| text | str | 按钮显示文案 | `去观看` | + +`data.items[n].modules.module_dynamic.additional.reserve.desc1`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| style | num | 类型 | 0:`视频预约` `11-05 20:00 直播` `预计今天 17:05发布`<br/>1:`直播中` | +| text | str | 显示文案 | | + +`data.items[n].modules.module_dynamic.additional.reserve.desc2`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| style | num | `0` | | +| text | str | 显示文案 | `2人预约`<br/>`743观看`<br/>`1.0万人看过`<br/>`2151人气` | +| visible | bool | 是否显示 | true:显示文案<br/>false:显示已结束 | + +`data.items[n].modules.module_dynamic.additional.reserve.desc3`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| jump_url | str | 开奖信息跳转URL | | +| style | num | `1` | | +| text | str | 奖品信息显示文案 | | + +`data.items[n].modules.module_dynamic.additional.goods`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| head_icon | str | `空串` | | +| head_text | str | 卡片头显示文案 | | +| items | array | 商品信息列表 | | +| jump_url | str | `空串` | | + +`data.items[n].modules.module_dynamic.additional.goods.items`数组中的: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| brief | str | 商品副标题 | | +| cover | str | 商品封面 | | +| id | str | 商品ID | | +| jump_desc | str | 跳转按钮显示文案 | | +| jump_url | str | 跳转URL | | +| name | str | 商品名称 | | +| price | str | 商品价格 | | + +`data.items[n].modules.module_dynamic.additional.vote`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| choice_cnt | num | `1` | | +| default_share | num | 是否默认勾选`同时分享至动态` | 1:勾选 | +| desc | str | 投票标题 | | +| end_time | num | 剩余时间 | 单位:秒 | +| join_num | num | 已参与人数 | | +| status | num | `1` | | +| type | null | `null` | | +| uid | num | 发起人UID | | +| vote_id | num | 投票ID | | + +`data.items[n].modules.module_dynamic.additional.ugc`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cover | str | 封面 | | +| desc_second | str | 播放量与弹幕数 | | +| duration | str | 视频长度 | | +| head_text | str | `空串` | | +| id_str | str | 视频AV号 | | +| jump_url | str | 视频跳转URL | | +| multi_line | bool | `true` | | +| title | str | 视频标题 | | + +`data.items[n].modules.module_dynamic.desc`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| rich_text_nodes | array | 富文本节点列表 | [富文本节点类型](../opus/rich_text_nodes.md#富文本节点类型) | +| text | str | 动态的文字内容 | | + +`data.items[n].modules.module_dynamic.major`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| type | str | 动态主体类型 | [动态主体类型](./dynamic_enum.md#动态主体类型) | +| ugc_season | obj | 合集信息 | `MAJOR_TYPE_UGC_SEASON` | +| article | obj | 专栏类型 | `MAJOR_TYPE_ARTICLE` | +| draw | obj | 带图动态 | `MAJOR_TYPE_DRAW` | +| archive | obj | 视频信息 | `MAJOR_TYPE_ARCHIVE` | +| live_rcmd | obj | 直播状态 | `MAJOR_TYPE_LIVE_RCMD` | +| common | obj | 一般类型 | `MAJOR_TYPE_COMMON` | +| pgc | obj | 剧集信息 | `MAJOR_TYPE_PGC` | +| courses | obj | 课程信息 | `MAJOR_TYPE_COURSES` | +| music | obj | 音频信息 | `MAJOR_TYPE_MUSIC` | +| opus | obj | 图文动态 | `MAJOR_TYPE_OPUS` | +| live | obj | | | +| none | obj | 动态失效 | `MAJOR_TYPE_NONE` | +| upower_common | obj | 充电相关 | `MAJOR_TYPE_UPOWER_COMMON` | + +`data.items[].modules.module_dynamic.major.upower_common` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| background | object | 背景 | | +| button | object | 按钮 | | +| icon | object | 图标 | | +| jump_url | string | 跳转 URL | | +| rid | string | 关联 id | | +| title | string | 标题 | | +| title_prefix | string | 标题前缀 | | +| type | number | 类型 | | +| up_mid | number | UP 主 mid (UID) | | +| upower_action_state | number | 充电操作状态? | | +| upower_level | number | 充电级别? | | + +`data.items[].modules.module_dynamic.major.upower_common.background` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| dark_src | string | 深色背景 | | +| light_src | string | 浅色背景 | | + +`data.items[].modules.module_dynamic.major.upower_common.button` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| jump_style | object | 跳转样式 | | +| jump_url | string | 跳转 URL | | +| type | number | 类型 | | + +`data.items[].modules.module_dynamic.major.upower_common.button.jump_style` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| text | string | 文本 | | + +`data.items[].modules.module_dynamic.major.upower_common.icon` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| dark_src | string | 深色图标 URL | | +| light_src | string | 浅色图标 URL | | + +<!-- Generated by json-apidoc-gen @ 2025-07-20T07:08:06.175919645Z --> + +`data.items[n].modules.module_dynamic.major.ugc_season`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| aid | num | 视频AV号 | | +| badge | obj | 角标信息 | | +| cover | str | 视频封面 | | +| desc | str | 视频简介 | | +| disable_preview | num | `0` | | +| duration_text | str | 时长 | | +| jump_url | str | 跳转URL | | +| stat | obj | 统计信息 | | +| title | str | 视频标题 | | + +`data.items[n].modules.module_dynamic.major.ugc_season.badge`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| bg_color | str | 背景颜色 | | +| color | str | 字体颜色 | | +| text | str | 角标文案 | | + +`data.items[n].modules.module_dynamic.major.ugc_season.stat`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| danmaku | str | 弹幕数 | | +| play | str | 播放数 | | + +`data.items[n].modules.module_dynamic.major.article`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| covers | array | 封面图数组 | 最多三张 | +| desc | str | 文章摘要 | | +| id | num | 文章CV号 | | +| jump_url | str | 文章跳转地址 | | +| label | str | 文章阅读量 | | +| title | str | 文章标题 | | + +`data.items[n].modules.module_dynamic.major.draw`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| id | num | 对应相簿id | | +| items | array | 图片信息列表 | | + +`data.items[n].modules.module_dynamic.major.draw.items[o]`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| height | num | 图片高度 | | +| size | num | 图片大小 | 单位KB | +| src | str | 图片URL | | +| tags | array | | | +| width | num | 图片宽度 | | + +`data.items[n].modules.module_dynamic.major.archive`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| aid | str | 视频AV号 | | +| badge | obj | 角标信息 | | +| bvid | str | 视频BVID | | +| cover | str | 视频封面 | | +| desc | str | 视频简介 | | +| disable_preview | num | `0` | | +| duration_text | str | 视频长度 | | +| jump_url | str | 跳转URL | | +| stat | obj | 统计信息 | | +| title | str | 视频标题 | | +| type | num | `1` | | + +`data.items[n].modules.module_dynamic.major.archive.badge`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| bg_color | str | 背景颜色 | | +| color | str | 字体颜色 | | +| text | str | 角标文案 | | + +`data.items[n].modules.module_dynamic.major.archive.stat`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| danmaku | str | 弹幕数 | | +| play | str | 播放数 | | + +`data.items[n].modules.module_dynamic.major.live_rcmd`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| content | str | 直播间内容JSON | | +| reserve_type | num | `0` | | + +`data.items[n].modules.module_dynamic.major.common`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| badge | obj | 角标信息 | | +| biz_type | num | `0` | | +| cover | str | 左侧图片封面 | | +| desc | str | 右侧描述信息 | | +| id | str | | | +| jump_url | str | 跳转地址 | | +| label | str | `空串` | | +| sketch_id | str | | | +| style | num | `1` | | +| title | str | 右侧标题 | | + +`data.items[n].modules.module_dynamic.major.common.badge`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| bg_color | str | 背景色 | | +| color | str | 前景色 | | +| text | str | 文本 | | + +`data.items[n].modules.module_dynamic.major.pgc`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| badge | obj | 角标信息 | | +| cover | str | 视频封面 | | +| epid | num | 分集EpId | | +| jump_url | str | 跳转URL | | +| season_id | num | 剧集SeasonId | | +| stat | obj | 统计信息 | | +| sub_type | num | 剧集类型 | 1:番剧<br/>2:电影<br/>3:纪录片<br/>4:国创<br/>5:电视剧<br/>6:漫画<br/>7:综艺 | +| title | str | 视频标题 | | +| type | num | `2` | | + +`data.items[n].modules.module_dynamic.major.pgc.badge`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| bg_color | str | 背景颜色 | | +| color | str | 字体颜色 | | +| text | str | 角标文案 | | + +`data.items[n].modules.module_dynamic.major.pgc.stat`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| danmaku | str | 弹幕数 | | +| play | str | 播放数 | | + +`data.items[n].modules.module_dynamic.major.courses`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| badge | obj | 角标信息 | | +| cover | str | 封面图URL | | +| desc | str | 更新状态描述 | | +| id | num | 课程id | | +| jump_url | str | 跳转URL | | +| sub_title | str | 课程副标题 | | +| title | str | 课程标题 | | + +`data.items[n].modules.module_dynamic.major.courses.badge`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| bg_color | str | 背景颜色 | | +| color | str | 字体颜色 | | +| text | str | 角标文案 | | + +`data.items[n].modules.module_dynamic.major.music`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cover | str | 音频封面 | | +| id | num | 音频AUID | | +| jump_url | str | 跳转URL | | +| label | str | 音频分类 | | +| title | str | 音频标题 | | + +`data.items[n].modules.module_dynamic.major.opus`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| fold_action | array | 展开收起 | | +| jump_url | str | 跳转URL | | +| pics | array | 图片信息 | | +| summary | obj | 动态内容 | | +| title | str | 动态标题 | 没有标题时为null | + +`data.items[n].modules.module_dynamic.major.opus.summary`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| rich_text_nodes | array | 富文本节点列表 | 和`desc`对象中的`rich_text_nodes`数组结构一样 | +| text | str | 评论内容 | | + +`data.items[n].modules.module_dynamic.major.live`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| badge | obj | 角标信息 | | +| cover | str | 直播封面 | | +| desc_first | str | 直播主分区名称 | | +| desc_second | str | 观看人数 | | +| id | num | 直播间id | | +| jump_url | str | 直播间跳转URL | | +| live_state | num | 直播状态 | 0:直播结束<br/>1:正在直播 | +| reserve_type | num | `0` | | +| title | str | 直播间标题 | | + +`data.items[n].modules.module_dynamic.major.live.badge`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| bg_color | str | 背景颜色 | | +| color | str | 字体颜色 | | +| text | str | 角标文案 | | + +`data.items[n].modules.module_dynamic.major.none`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| tips | str | 动态失效显示文案 | deprecated? | + +`data.items[n].modules.module_interaction`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| items | array | 信息列表 | | + +`data.items[n].modules.module_interaction.items`数组中的: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| desc | obj | 点赞/评论信息 | | +| type | num | 类型 | 0:点赞信息<br/>1:评论信息 | + +`data.items[n].modules.module_interaction.items[o].desc`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| rich_text_nodes | array | 富文本节点列表 | [富文本节点类型](../opus/rich_text_nodes.md#富文本节点类型) | +| text | str | 评论内容 | | + +`data.items[n].modules.module_fold`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| ids | array | 被折叠的动态id列表 | | +| statement | str | 显示文案 | 例:展开x条相关动态 | +| type | num | `1` | | +| users | array | `空数组` | | + +`data.items[n].modules.module_dispute`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| desc | str | | | +| jump_url | str | | | +| title | str | 提醒文案 | 例:视频内含有危险行为,请勿模仿 | + +`data.items[n].modules.module_tag`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| text | str | '置顶' | 置顶动态出现这个对象,否则没有 | + +**示例:** + +```shell +curl -L -X GET 'https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/all?type=all' \ +-H 'Cookie: SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "has_more": true, + "items": [ + { + "basic": { + "comment_id_str": "112981396619958", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "112981396619958" + }, + "id_str": "966887968322093078", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i2.hdslb.com/bfs/face/b1c15dd8814d79e648008815517aa5ef50a2fb9c.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "3546730050096047" + }, + "face": "https://i2.hdslb.com/bfs/face/b1c15dd8814d79e648008815517aa5ef50a2fb9c.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/3546730050096047/dynamic", + "label": "", + "mid": 3546730050096047, + "name": "青岛LUCIFER", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "刚刚", + "pub_ts": 1723959548, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 0, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 0 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "112981396619958", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1oeWNebEv2", + "cover": "http://i2.hdslb.com/bfs/archive/0e3d26d90eb0642d90c7552e63ce690e2fe7f8ce.jpg", + "desc": "给老板娘贴睫毛贴了半天,老登眼皮总动,夹睫毛疼了还骂我,不开心哈哈哈。", + "disable_preview": 0, + "duration_text": "00:16", + "jump_url": "//www.bilibili.com/video/BV1oeWNebEv2/", + "stat": { + "danmaku": "0", + "play": "0" + }, + "title": "老板娘今天是可爱鬼呀!", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 0, + "forbidden": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 0, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + { + "basic": { + "comment_id_str": "1756441068", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "1756441068" + }, + "id_str": "966873782060843027", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/726060100f7b80f3ab17889aa9fb8f380a53b9da.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 3, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "266765166" + }, + "face": "https://i0.hdslb.com/bfs/face/726060100f7b80f3ab17889aa9fb8f380a53b9da.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/266765166/dynamic", + "label": "", + "mid": 266765166, + "name": "漫士沉思录", + "official_verify": { + "desc": "", + "type": 0 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "55分钟前", + "pub_ts": 1723956245, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 0, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 0 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "1756441068", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1d4421Z7nW", + "cover": "http://i1.hdslb.com/bfs/archive/df067c178714da9b511f10bde11e1bc75ea676d9.jpg", + "desc": "使用3b1b开发的manim引擎制作", + "disable_preview": 0, + "duration_text": "14:25", + "jump_url": "//www.bilibili.com/video/BV1d4421Z7nW/", + "stat": { + "danmaku": "217", + "play": "1.4万" + }, + "title": "【漫士科普】如何最简单且本质地理解欧拉公式?", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 142, + "forbidden": false + }, + "forward": { + "count": 6, + "forbidden": false + }, + "like": { + "count": 1959, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + { + "basic": { + "comment_id_str": "325833790", + "comment_type": 11, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "325833790" + }, + "id_str": "966831498138222598", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/1fd5b43d5f619e6df8c8adcf13c962a3e80ee971.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/garb/item/fe1267f786bf69f1471aff715f8d38ec0e486df5.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 4, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "layers": [ + { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/1fd5b43d5f619e6df8c8adcf13c962a3e80ee971.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + { + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_animation": { + "webp_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/garb/item/0aa9fd33133ed3fd9f11c857cc6ca848d6804113.webp" + }, + "src_type": 1 + } + }, + "res_type": 4 + }, + "visible": true + } + ] + }, + { + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 4, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + } + ], + "mid": "233114659" + }, + "decorate": { + "card_url": "https://i0.hdslb.com/bfs/garb/bb140043341137b879e957d09b649ce7c3257820.png", + "fan": { + "color": "#903AC2", + "color_format": { + "colors": [ + "#903AC2FF", + "#903AC2FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": true, + "num_prefix": "NO.", + "num_str": "000001", + "number": 1 + }, + "id": 1706163888001, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=1706163888001\u0026isdiy=0\u0026part=card\u0026from=post\u0026f_source=garb\u0026vmid=233114659\u0026native.theme=1\u0026navhide=1", + "name": "龙腾啾跃-动态卡片粉丝", + "type": 3 + }, + "face": "https://i1.hdslb.com/bfs/face/1fd5b43d5f619e6df8c8adcf13c962a3e80ee971.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/233114659/dynamic", + "label": "", + "mid": 233114659, + "name": "碧蓝航线", + "official_verify": { + "desc": "", + "type": 1 + }, + "pendant": { + "expire": 0, + "image": "https://i1.hdslb.com/bfs/garb/item/fe1267f786bf69f1471aff715f8d38ec0e486df5.png", + "image_enhance": "https://i1.hdslb.com/bfs/garb/item/0aa9fd33133ed3fd9f11c857cc6ca848d6804113.webp", + "image_enhance_frame": "https://i1.hdslb.com/bfs/garb/item/3052b412defbbc7704e887fefde8de539e8027c5.png", + "n_pid": 1987, + "name": "碧蓝航线2020", + "pid": 1987 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "3小时前", + "pub_ts": 1723946400, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1729526400000, + "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": { + "common": { + "button": { + "jump_style": { + "icon_url": "", + "text": "进入" + }, + "jump_url": "https://www.biligame.com/detail?id=97\u0026sourceFrom=1005", + "type": 1 + }, + "cover": "https://i0.hdslb.com/bfs/game/b141a7690c226a0eae66518c713d3af62613b21d.png", + "desc1": "养成", + "desc2": "指挥官,欢迎回港", + "head_text": "相关游戏", + "id_str": "97", + "jump_url": "https://www.biligame.com/detail?id=97\u0026sourceFrom=1005", + "style": 1, + "sub_type": "game", + "title": "碧蓝航线" + }, + "type": "ADDITIONAL_TYPE_COMMON" + }, + "desc": { + "rich_text_nodes": [ + { + "jump_url": "//search.bilibili.com/all?keyword=%E7%A2%A7%E8%93%9D%E8%88%AA%E7%BA%BF", + "orig_text": "#碧蓝航线#", + "text": "#碧蓝航线#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "orig_text": " ", + "text": " ", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%E7%A2%A7%E8%93%9D%E8%88%AA%E7%BA%BF%E6%BC%AB%E5%B1%95", + "orig_text": "#碧蓝航线漫展#", + "text": "#碧蓝航线漫展#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "orig_text": " ", + "text": " ", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=2024%E6%B8%AF%E5%8C%BA%E7%9B%9B%E5%A4%8F%E6%B8%85%E5%87%89%E8%8A%82", + "orig_text": "#2024港区盛夏清凉节#", + "text": "#2024港区盛夏清凉节#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "orig_text": "\n◆ 「港区盛夏清凉节」长沙站·街区快闪 DAY1 现场直击!◆ \n\n城市街巷,专属惊喜,\n绘就绚丽夏日!\n和少女们一同记录这场特别邂逅吧!\n\n◆ 互动游戏开放时间:2024年8月17日~8月18日,每日10:00~12:00及14:00~19:00\n◆ 街区快闪体验地址:湖南省长沙市开福区潮宗街历史文化街区\n◆ 参与方式:无需预约,前往现场即可参与体验~\n◆ 体验须知:\n※8月17日~8月18日期间,指挥官可前往潮宗街历史文化街区现场参与体验。\n※指挥官关注《碧蓝航线》官方B站账号后,可参与互动游戏,集章兑换周边礼品哟!\n※兑换周边每日数量有限,兑完即止。\n※天气炎热,请指挥官做好防暑准备,出行注意安全哟。", + "text": "\n◆ 「港区盛夏清凉节」长沙站·街区快闪 DAY1 现场直击!◆ \n\n城市街巷,专属惊喜,\n绘就绚丽夏日!\n和少女们一同记录这场特别邂逅吧!\n\n◆ 互动游戏开放时间:2024年8月17日~8月18日,每日10:00~12:00及14:00~19:00\n◆ 街区快闪体验地址:湖南省长沙市开福区潮宗街历史文化街区\n◆ 参与方式:无需预约,前往现场即可参与体验~\n◆ 体验须知:\n※8月17日~8月18日期间,指挥官可前往潮宗街历史文化街区现场参与体验。\n※指挥官关注《碧蓝航线》官方B站账号后,可参与互动游戏,集章兑换周边礼品哟!\n※兑换周边每日数量有限,兑完即止。\n※天气炎热,请指挥官做好防暑准备,出行注意安全哟。", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "#碧蓝航线# #碧蓝航线漫展# #2024港区盛夏清凉节#\n◆ 「港区盛夏清凉节」长沙站·街区快闪 DAY1 现场直击!◆ \n\n城市街巷,专属惊喜,\n绘就绚丽夏日!\n和少女们一同记录这场特别邂逅吧!\n\n◆ 互动游戏开放时间:2024年8月17日~8月18日,每日10:00~12:00及14:00~19:00\n◆ 街区快闪体验地址:湖南省长沙市开福区潮宗街历史文化街区\n◆ 参与方式:无需预约,前往现场即可参与体验~\n◆ 体验须知:\n※8月17日~8月18日期间,指挥官可前往潮宗街历史文化街区现场参与体验。\n※指挥官关注《碧蓝航线》官方B站账号后,可参与互动游戏,集章兑换周边礼品哟!\n※兑换周边每日数量有限,兑完即止。\n※天气炎热,请指挥官做好防暑准备,出行注意安全哟。" + }, + "major": { + "draw": { + "id": 325833790, + "items": [ + { + "height": 4000, + "size": 16103.947, + "src": "http://i0.hdslb.com/bfs/new_dyn/31b32e6dcf2f1a6328552f0fa666302d233114659.jpg", + "tags": [], + "width": 6000 + }, + { + "height": 3905, + "size": 16620.71, + "src": "http://i0.hdslb.com/bfs/new_dyn/e507c60207f486824708a5850d07d1bb233114659.jpg", + "tags": [], + "width": 5858 + }, + { + "height": 4000, + "size": 16195.393, + "src": "http://i0.hdslb.com/bfs/new_dyn/7a7ef9513bb32edc3de887d787a4df43233114659.jpg", + "tags": [], + "width": 6000 + }, + { + "height": 4672, + "size": 11758.82, + "src": "http://i0.hdslb.com/bfs/new_dyn/a21461b944e10306e68672df3e92c1b9233114659.jpg", + "tags": [], + "width": 7008 + }, + { + "height": 4672, + "size": 3962.4902, + "src": "http://i0.hdslb.com/bfs/new_dyn/b2c4baa47b4999cabb9c8c338c2da36c233114659.jpg", + "tags": [], + "width": 7008 + }, + { + "height": 4672, + "size": 11276.51, + "src": "http://i0.hdslb.com/bfs/new_dyn/8cf06e142fce875d2c3b83961abbc668233114659.jpg", + "tags": [], + "width": 7008 + }, + { + "height": 3735, + "size": 13969.533, + "src": "http://i0.hdslb.com/bfs/new_dyn/c56cd277f281ba8cc4a395dbe5d9fa54233114659.jpg", + "tags": [], + "width": 5603 + }, + { + "height": 3106, + "size": 12942.339, + "src": "http://i0.hdslb.com/bfs/new_dyn/9049a5c39ebafdd1cb488b26da4f99da233114659.jpg", + "tags": [], + "width": 4659 + }, + { + "height": 3802, + "size": 18643.953, + "src": "http://i0.hdslb.com/bfs/new_dyn/564e469ba092d2381b23547da37ca3c0233114659.jpg", + "tags": [], + "width": 5703 + } + ] + }, + "type": "MAJOR_TYPE_DRAW" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 151, + "forbidden": false + }, + "forward": { + "count": 31, + "forbidden": false + }, + "like": { + "count": 2827, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_DRAW", + "visible": true + }, + { + "basic": { + "comment_id_str": "37231101", + "comment_type": 12, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "37231101" + }, + "id_str": "966827503780888593", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/978ea07f22e54c2e62f01def8e815b59adacc5d0.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 4, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "407045223" + }, + "decorate": { + "card_url": "https://i0.hdslb.com/bfs/vip/a9e3d993c7a15e88ce0bf714a142f7d2b44121e2.png", + "fan": { + "color": "", + "color_format": null, + "is_fan": false, + "num_prefix": "", + "num_str": "", + "number": 0 + }, + "id": 28, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=28\u0026isdiy=0\u0026part=card\u0026from=post\u0026f_source=garb\u0026vmid=407045223\u0026native.theme=1\u0026navhide=1", + "name": "2233娘", + "type": 1 + }, + "face": "https://i0.hdslb.com/bfs/face/978ea07f22e54c2e62f01def8e815b59adacc5d0.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/407045223/dynamic", + "label": "", + "mid": 407045223, + "name": "二次元的中科院物理所", + "official_verify": { + "desc": "", + "type": 1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了文章", + "pub_location_text": "", + "pub_time": "3小时前", + "pub_ts": 1723945470, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1745769600000, + "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": null, + "major": { + "article": { + "covers": [ + "https://i0.hdslb.com/bfs/article/f59f635a3784c49eb174da7d589c4e75407045223.jpg" + ], + "desc": "西游记中,孙悟空为了保护师傅,在地上画了一个圈,由此便可限制住妖怪。今天小编带大家布置法术场地,只需在上面画出图案,便可控制水滴的行动!实验器材火柴、蜡烛、空易拉罐、所标杯、细竹签实验步骤安全提示:本实验有明火,请小朋友在家长的陪同下完成,或在空旷的地方进行,避免着火,注意安全。第一步:首先布置施法场地,通过蜡烛将易拉罐底部附着满炭黑。注意此步骤中应保持易拉罐内含一定水分,否则会产生烫伤等风险!第二步:向施法场地滴入水滴,观察场地效果。可以看到水滴在场地内不收约束,自由滑行第三步:当用细竹签等在场地中画出", + "id": 37231101, + "jump_url": "//www.bilibili.com/read/cv37231101/", + "label": "12万阅读", + "title": "带你在家里学会孙悟空的“画地为牢” 丨正经玩" + }, + "type": "MAJOR_TYPE_ARTICLE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 9, + "forbidden": false + }, + "forward": { + "count": 2, + "forbidden": false + }, + "like": { + "count": 583, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_ARTICLE", + "visible": true + }, + { + "basic": { + "comment_id_str": "1306462278", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "1306462278" + }, + "id_str": "966792134707380227", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_animation": { + "webp_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/7efb679569b2faeff38fa08f6f992fa1ada5e948.webp" + }, + "src_type": 1 + } + }, + "res_type": 4 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/0dcf03aa499a64524fe25871d26d95f49f880928.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 3, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "686127" + }, + "face": "https://i0.hdslb.com/bfs/face/7efb679569b2faeff38fa08f6f992fa1ada5e948.webp", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/686127/dynamic", + "label": "", + "mid": 686127, + "name": "籽岷", + "official_verify": { + "desc": "", + "type": 0 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/0dcf03aa499a64524fe25871d26d95f49f880928.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/0dcf03aa499a64524fe25871d26d95f49f880928.png", + "image_enhance_frame": "", + "n_pid": 2066, + "name": "百年大会员", + "pid": 2066 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "6小时前", + "pub_ts": 1723937235, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 4845196800000, + "label": { + "bg_color": "#FB7299", + "bg_style": 1, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/c16005a5b39164b3536cbd45618a5edd597a1c51.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/Pzrd8zmpQD.png", + "label_theme": "hundred_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": null, + "major": { + "archive": { + "aid": "1306462278", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV14M4m1175k", + "cover": "http://i1.hdslb.com/bfs/archive/7f8060fe1669b1a0a980844bb90e8150a859499c.jpg", + "desc": "https://www.curseforge.com/minecraft/mc-mods/desert-behemoths-sandworms/", + "disable_preview": 0, + "duration_text": "04:24", + "jump_url": "//www.bilibili.com/video/BV14M4m1175k/", + "stat": { + "danmaku": "297", + "play": "10.1万" + }, + "title": "我的世界 巨大沙虫", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_interaction": { + "items": [ + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "bili_49990770610:", + "rid": "3546583341730698", + "text": "bili_49990770610:", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "emoji": { + "icon_url": "https://i0.hdslb.com/bfs/emote/1597302b98827463f5b75c7cac1f29ea6ce572c4.png", + "size": 1, + "text": "[给心心]", + "type": 1 + }, + "orig_text": "[给心心]", + "text": "[给心心]", + "type": "RICH_TEXT_NODE_TYPE_EMOJI" + } + ], + "text": "[给心心]" + }, + "type": 1 + } + ] + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 248, + "forbidden": false + }, + "forward": { + "count": 10, + "forbidden": false + }, + "like": { + "count": 10276, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + { + "basic": { + "comment_id_str": "325813964", + "comment_type": 11, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "325813964" + }, + "id_str": "966695334756483089", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/4f8f3f1f2d47f0dad84f66aa57acd4409ea46361.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 1, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "layers": [ + { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + { + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_animation": { + "webp_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/fe0b83b53e2342b16646f6e7a9370d8a867decdb.webp" + }, + "src_type": 1 + } + }, + "res_type": 4 + }, + "visible": true + } + ] + }, + { + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 1, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + } + ], + "mid": "293793435" + }, + "decorate": { + "card_url": "https://i0.hdslb.com/bfs/garb/item/c0cf2235089ed314d92f30efa855c9b5611fa2cd.png", + "fan": { + "color": "#07b6d5", + "color_format": { + "colors": [ + "#07b6d5FF", + "#07b6d5FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": true, + "num_prefix": "NO.", + "num_str": "005638", + "number": 5638 + }, + "id": 2513, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=2513\u0026isdiy=0\u0026part=card\u0026from=post\u0026f_source=garb\u0026vmid=293793435\u0026native.theme=1\u0026navhide=1", + "name": "初音未来粉丝专属", + "type": 3 + }, + "face": "https://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/293793435/dynamic", + "label": "", + "mid": 293793435, + "name": "社会易姐QwQ", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/4f8f3f1f2d47f0dad84f66aa57acd4409ea46361.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/fe0b83b53e2342b16646f6e7a9370d8a867decdb.webp", + "image_enhance_frame": "https://i0.hdslb.com/bfs/garb/item/127c507ec8448be30cf5f79500ecc6ef2fd32f2c.png", + "n_pid": 2511, + "name": "初音未来13周年", + "pid": 2511 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "12小时前", + "pub_ts": 1723914697, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1739116800000, + "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": "非常好冰箱贴,爱来自硬先生😋😋", + "text": "非常好冰箱贴,爱来自硬先生😋😋", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@硬核拆解 ", + "rid": "427494870", + "text": "@硬核拆解 ", + "type": "RICH_TEXT_NODE_TYPE_AT" + } + ], + "text": "非常好冰箱贴,爱来自硬先生😋😋@硬核拆解 " + }, + "major": { + "draw": { + "id": 325813964, + "items": [ + { + "height": 1277, + "size": 98.36, + "src": "http://i0.hdslb.com/bfs/new_dyn/60d92e9e0d89a5394a2da69aba6f9710293793435.jpg", + "tags": [], + "width": 958 + }, + { + "height": 1080, + "size": 905.82, + "src": "http://i0.hdslb.com/bfs/new_dyn/0f9bff1938d824ce206a569d539455df293793435.jpg", + "tags": [], + "width": 1440 + }, + { + "height": 1080, + "size": 693.59, + "src": "http://i0.hdslb.com/bfs/new_dyn/ab3332061b793361ec08901ace1782db293793435.jpg", + "tags": [], + "width": 1440 + }, + { + "height": 1080, + "size": 988.15, + "src": "http://i0.hdslb.com/bfs/new_dyn/8e62512db6d04b381dae3814adb95d5e293793435.jpg", + "tags": [], + "width": 1440 + } + ] + }, + "type": "MAJOR_TYPE_DRAW" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 0, + "forbidden": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 11, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_DRAW", + "visible": true + }, + { + "basic": { + "comment_id_str": "966692349750018048", + "comment_type": 17, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "966692349750018048" + }, + "id_str": "966692349750018048", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/78cdc5ba930ab171ebfe1ecc848cabcd4b0e0974.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/garb/open/aafcb0ea3a0bc237634240f98bf93b3b6ac2d337.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 3, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "36081646" + }, + "decorate": { + "card_url": "https://i0.hdslb.com/bfs/garb/item/684f6dc32decd32fe9db901b81b83b9a1fe39574.png", + "fan": { + "color": "", + "color_format": null, + "is_fan": false, + "num_prefix": "", + "num_str": "", + "number": 0 + }, + "id": 49922, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=49922\u0026isdiy=0\u0026part=card\u0026from=post\u0026f_source=garb\u0026vmid=36081646\u0026native.theme=1\u0026navhide=1", + "name": "古色花香洛天依", + "type": 1 + }, + "face": "https://i1.hdslb.com/bfs/face/78cdc5ba930ab171ebfe1ecc848cabcd4b0e0974.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/36081646/dynamic", + "label": "", + "mid": 36081646, + "name": "洛天依", + "official_verify": { + "desc": "", + "type": 0 + }, + "pendant": { + "expire": 0, + "image": "https://i1.hdslb.com/bfs/garb/open/aafcb0ea3a0bc237634240f98bf93b3b6ac2d337.png", + "image_enhance": "https://i1.hdslb.com/bfs/garb/open/aafcb0ea3a0bc237634240f98bf93b3b6ac2d337.png", + "image_enhance_frame": "", + "n_pid": 1720437918001, + "name": "洛天依心律共鸣头像框", + "pid": -1843967695 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "12小时前", + "pub_ts": 1723914002, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1764777600000, + "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": "恭喜", + "text": "恭喜", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@从一到无穷大Infinity", + "rid": "697565874", + "text": "@从一到无穷大Infinity", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": "@qwq啊啊啊啊啊噜", + "rid": "189799722", + "text": "@qwq啊啊啊啊啊噜", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": "@有时名字不能取太长", + "rid": "3546388151405126", + "text": "@有时名字不能取太长", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": "等5位同学中奖,已私信通知,详情请点击抽奖查看。", + "text": "等5位同学中奖,已私信通知,详情请点击抽奖查看。", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "恭喜@从一到无穷大Infinity@qwq啊啊啊啊啊噜@有时名字不能取太长等5位同学中奖,已私信通知,详情请点击抽奖查看。" + }, + "major": null, + "topic": null + }, + "module_interaction": { + "items": [ + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "明ちゃん王:", + "rid": "1280664625", + "text": "明ちゃん王:", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": "哇,非常不错呢,跟天依挺搭配的", + "text": "哇,非常不错呢,跟天依挺搭配的", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "emoji": { + "icon_url": "https://i0.hdslb.com/bfs/emote/63c9d1a31c0da745b61cdb35e0ecb28635675db2.png", + "size": 1, + "text": "[星星眼]", + "type": 1 + }, + "orig_text": "[星星眼]", + "text": "[星星眼]", + "type": "RICH_TEXT_NODE_TYPE_EMOJI" + } + ], + "text": "哇,非常不错呢,跟天依挺搭配的[星星眼]" + }, + "type": 1 + } + ] + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 88, + "forbidden": false + }, + "forward": { + "count": 12, + "forbidden": false + }, + "like": { + "count": 3088, + "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": "939874290505875465", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/78cdc5ba930ab171ebfe1ecc848cabcd4b0e0974.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/garb/open/aafcb0ea3a0bc237634240f98bf93b3b6ac2d337.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 3, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "36081646" + }, + "decorate": { + "card_url": "https://i0.hdslb.com/bfs/garb/item/684f6dc32decd32fe9db901b81b83b9a1fe39574.png", + "fan": { + "color": "", + "color_format": null, + "is_fan": false, + "num_prefix": "", + "num_str": "", + "number": 0 + }, + "id": 49922, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=49922\u0026isdiy=0\u0026part=card\u0026from=post\u0026f_source=garb\u0026vmid=36081646\u0026native.theme=1\u0026navhide=1", + "name": "古色花香洛天依", + "type": 1 + }, + "face": "https://i1.hdslb.com/bfs/face/78cdc5ba930ab171ebfe1ecc848cabcd4b0e0974.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/36081646/dynamic", + "label": "", + "mid": 36081646, + "name": "洛天依", + "official_verify": { + "desc": "", + "type": 0 + }, + "pendant": { + "expire": 0, + "image": "https://i1.hdslb.com/bfs/garb/open/aafcb0ea3a0bc237634240f98bf93b3b6ac2d337.png", + "image_enhance": "https://i1.hdslb.com/bfs/garb/open/aafcb0ea3a0bc237634240f98bf93b3b6ac2d337.png", + "image_enhance_frame": "", + "n_pid": 1720437918001, + "name": "洛天依心律共鸣头像框", + "pid": -1843967695 + }, + "pub_action": "", + "pub_time": "", + "pub_ts": 1717669936, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1764777600000, + "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": { + "goods": { + "head_icon": "", + "head_text": "UP主的推荐", + "items": [ + { + "brief": "", + "cover": "https://i0.hdslb.com/bfs/mall/mall/ef/9d/2cb00b3649bcb232f62b3169be95407d.png", + "id": "901140704120020992", + "jump_desc": "去看看", + "jump_url": "https://mall.bilibili.com/neul-next/detailuniversal/detail.html?isMerchant=1\u0026page=detailuniversal_detail\u0026saleType=0\u0026itemsId=10406556\u0026loadingShow=1\u0026noTitleBar=1\u0026msource=cps_Mdynamic_36081646\u0026from=\u0026contentId=\u0026track_id=__BGMT__", + "name": "天羽川 洛天依 短袖水手服纯色裙长短袜套装", + "price": "¥49" + } + ], + "jump_url": "" + }, + "type": "ADDITIONAL_TYPE_GOODS" + }, + "desc": { + "rich_text_nodes": [ + { + "orig_text": "​互动抽奖", + "rid": "301330", + "text": "​互动抽奖", + "type": "RICH_TEXT_NODE_TYPE_LOTTERY" + }, + { + "orig_text": "洛天依X", + "text": "洛天依X", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@天羽川JK ", + "rid": "394187581", + "text": "@天羽川JK ", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": "联名水手服\u0026长短袜套装 新品预售即将开启啦!\n转发关注天依,揪5位小伙伴送出联名款长短袜1双~", + "text": "联名水手服\u0026长短袜套装 新品预售即将开启啦!\n转发关注天依,揪5位小伙伴送出联名款长短袜1双~", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "emoji": { + "icon_url": "http://i0.hdslb.com/bfs/emote/9826fb4f77944387767a37552143fbec40159fa5.png", + "size": 2, + "text": "[洛天依_礼物]", + "type": 3 + }, + "orig_text": "[洛天依_礼物]", + "text": "[洛天依_礼物]", + "type": "RICH_TEXT_NODE_TYPE_EMOJI" + }, + { + "orig_text": "\n\n❀联名服饰\n-洛天依联名款水手服\n-洛天依还原款长短袜\n\n❀预售时间\n6月8日20:00 起\n\n日常\u0026cos皆宜,大家有没有发现结合了天依的哪些元素呀?", + "text": "\n\n❀联名服饰\n-洛天依联名款水手服\n-洛天依还原款长短袜\n\n❀预售时间\n6月8日20:00 起\n\n日常\u0026cos皆宜,大家有没有发现结合了天依的哪些元素呀?", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "emoji": { + "icon_url": "https://i0.hdslb.com/bfs/emote/8034b3cb55370d19b1683eb38e7747c5c6c5dba6.png", + "size": 2, + "text": "[洛天依蝶变_星星眼]", + "type": 3 + }, + "orig_text": "[洛天依蝶变_星星眼]", + "text": "[洛天依蝶变_星星眼]", + "type": "RICH_TEXT_NODE_TYPE_EMOJI" + }, + { + "orig_text": "\n", + "text": "\n", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "​互动抽奖洛天依X@天羽川JK 联名水手服\u0026长短袜套装 新品预售即将开启啦!\n转发关注天依,揪5位小伙伴送出联名款长短袜1双~[洛天依_礼物]\n\n❀联名服饰\n-洛天依联名款水手服\n-洛天依还原款长短袜\n\n❀预售时间\n6月8日20:00 起\n\n日常\u0026cos皆宜,大家有没有发现结合了天依的哪些元素呀?[洛天依蝶变_星星眼]\n" + }, + "major": { + "draw": { + "id": 318324614, + "items": [ + { + "height": 1280, + "size": 662.59, + "src": "http://i0.hdslb.com/bfs/new_dyn/1f23b61786eadb8c3e3f4c137730715036081646.jpg", + "tags": [], + "width": 904 + }, + { + "height": 1280, + "size": 614.83, + "src": "http://i0.hdslb.com/bfs/new_dyn/7d679216308bb7c65aeba38b4eafdd8936081646.jpg", + "tags": [], + "width": 904 + } + ] + }, + "type": "MAJOR_TYPE_DRAW" + }, + "topic": { + "id": 1156147, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1156147\u0026topic_name=%E5%A4%A9%E4%BE%9D%E7%9A%84%E5%91%A8%E8%BE%B9", + "name": "天依的周边" + } + } + }, + "type": "DYNAMIC_TYPE_DRAW", + "visible": true + }, + "type": "DYNAMIC_TYPE_FORWARD", + "visible": true + }, + { + "basic": { + "comment_id_str": "325807840", + "comment_type": 11, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "325807840" + }, + "id_str": "966677390370537527", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/2b9ee4a9c99f1006f3c800c1317f7850ad6f3d0d.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 4, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "485703766" + }, + "face": "https://i1.hdslb.com/bfs/face/2b9ee4a9c99f1006f3c800c1317f7850ad6f3d0d.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/485703766/dynamic", + "label": "", + "mid": 485703766, + "name": "英伟达GeForce", + "official_verify": { + "desc": "", + "type": 1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "13小时前", + "pub_ts": 1723910520, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 2000563200000, + "label": { + "bg_color": "#FB7299", + "bg_style": 1, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/adb599797dd171e2d3d6d012f448b49679258344.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/sGu57N6pgK.png", + "label_theme": "ten_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": "直面天命,还有 2 天!\nRTX. ON!\n\n投稿来自于:Bilibili", + "text": "直面天命,还有 2 天!\nRTX. ON!\n\n投稿来自于:Bilibili", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@祗殁", + "rid": "12299496", + "text": "@祗殁", + "type": "RICH_TEXT_NODE_TYPE_AT" + } + ], + "text": "直面天命,还有 2 天!\nRTX. ON!\n\n投稿来自于:Bilibili@祗殁" + }, + "major": { + "draw": { + "id": 325807840, + "items": [ + { + "height": 1073, + "size": 66.29785, + "src": "https://i0.hdslb.com/bfs/new_dyn/b47b271135c7c496923d76c6b794e596485703766.png", + "tags": [], + "width": 1213 + } + ] + }, + "type": "MAJOR_TYPE_DRAW" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 105, + "forbidden": false + }, + "forward": { + "count": 7, + "forbidden": false + }, + "like": { + "count": 872, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_DRAW", + "visible": true + }, + { + "basic": { + "comment_id_str": "1606450518", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "1606450518" + }, + "id_str": "966647978674618373", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/bb23fb77a033759a145f8eda7b5e3a15386f637c.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 3, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "1503187" + }, + "decorate": { + "card_url": "https://i0.hdslb.com/bfs/archive/e495de36cab75f9a610fb6f2d0ba29a87b794cc6.png", + "fan": { + "color": "#BFC8D2", + "color_format": { + "colors": [ + "#B8C7D0FF", + "#A2A7B0FF" + ], + "end_point": "100,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": true, + "num_prefix": "NO.", + "num_str": "002484", + "number": 2484 + }, + "id": 66898, + "jump_url": "https://www.bilibili.com/h5/mall/digital-card/home?act_id=108\u0026from=post\u0026f_source=garb\u0026-Abrowser=live\u0026hybrid_set_header=2\u0026navhide=1\u0026anchor_task=1", + "name": "BLG 信念干杯勋章", + "type": 3 + }, + "face": "https://i1.hdslb.com/bfs/face/bb23fb77a033759a145f8eda7b5e3a15386f637c.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/1503187/dynamic", + "label": "", + "mid": 1503187, + "name": "和谐号舰长", + "official_verify": { + "desc": "", + "type": 0 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "昨天 22:07", + "pub_ts": 1723903670, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1732204800000, + "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": null, + "major": { + "archive": { + "aid": "1606450518", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV152421Z7bV", + "cover": "http://i1.hdslb.com/bfs/archive/e87786447779ff1a4fb2d941a3321f9750a65300.jpg", + "desc": "多来点这样的更新,太快乐了", + "disable_preview": 0, + "duration_text": "03:39", + "jump_url": "//www.bilibili.com/video/BV152421Z7bV/", + "stat": { + "danmaku": "406", + "play": "6.6万" + }, + "title": "官方:矿车怎么就不能是飞船?", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_interaction": { + "items": [ + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "吉吉国民开水儿:", + "rid": "43514654", + "text": "吉吉国民开水儿:", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": "致敬传奇宰人航空大师张泰玩", + "text": "致敬传奇宰人航空大师张泰玩", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "致敬传奇宰人航空大师张泰玩" + }, + "type": 1 + } + ] + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 218, + "forbidden": false + }, + "forward": { + "count": 15, + "forbidden": false + }, + "like": { + "count": 5694, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + { + "basic": { + "comment_id_str": "1506427569", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "1506427569" + }, + "id_str": "966629209415876628", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/978ea07f22e54c2e62f01def8e815b59adacc5d0.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 4, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "407045223" + }, + "decorate": { + "card_url": "https://i0.hdslb.com/bfs/vip/a9e3d993c7a15e88ce0bf714a142f7d2b44121e2.png", + "fan": { + "color": "", + "color_format": null, + "is_fan": false, + "num_prefix": "", + "num_str": "", + "number": 0 + }, + "id": 28, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=28\u0026isdiy=0\u0026part=card\u0026from=post\u0026f_source=garb\u0026vmid=407045223\u0026native.theme=1\u0026navhide=1", + "name": "2233娘", + "type": 1 + }, + "face": "https://i0.hdslb.com/bfs/face/978ea07f22e54c2e62f01def8e815b59adacc5d0.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/407045223/dynamic", + "label": "", + "mid": 407045223, + "name": "二次元的中科院物理所", + "official_verify": { + "desc": "", + "type": 1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "昨天 20:55", + "pub_ts": 1723899301, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1745769600000, + "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": "光是什么?光是我们看到的五彩斑斓的世界,光是自然界能量的来源,光是一种电磁波。我们利用光可以做些什么?如何收集太阳的能量?如何产生光?让我们在本集课程中寻找这些问题的答案~ 错过直播的小伙伴可以来这里补课~", + "text": "光是什么?光是我们看到的五彩斑斓的世界,光是自然界能量的来源,光是一种电磁波。我们利用光可以做些什么?如何收集太阳的能量?如何产生光?让我们在本集课程中寻找这些问题的答案~ 错过直播的小伙伴可以来这里补课~", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "光是什么?光是我们看到的五彩斑斓的世界,光是自然界能量的来源,光是一种电磁波。我们利用光可以做些什么?如何收集太阳的能量?如何产生光?让我们在本集课程中寻找这些问题的答案~ 错过直播的小伙伴可以来这里补课~" + }, + "major": { + "archive": { + "aid": "1506427569", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1uS42197b5", + "cover": "http://i1.hdslb.com/bfs/archive/e13db3349cdc91a00041be9730bbbe42c3e8df55.jpg", + "desc": "光是什么?光是我们看到的五彩斑斓的世界,光是自然界能量的来源,光是一种电磁波。我们利用光可以做些什么?如何收集太阳的能量?如何产生光?让我们在本集课程中寻找这些问题的答案~", + "disable_preview": 0, + "duration_text": "44:45", + "jump_url": "//www.bilibili.com/video/BV1uS42197b5/", + "stat": { + "danmaku": "1", + "play": "3364" + }, + "title": "光照下多姿多彩的世界——光化学和我们的生活【中国科学院科学公开课S06E15】", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": { + "id": 1073121, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1073121\u0026topic_name=%E4%B8%AD%E5%9B%BD%E7%A7%91%E5%AD%A6%E9%99%A2%E7%A7%91%E5%AD%A6%E5%85%AC%E5%BC%80%E8%AF%BE", + "name": "中国科学院科学公开课" + } + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 3, + "forbidden": false + }, + "forward": { + "count": 2, + "forbidden": false + }, + "like": { + "count": 741, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + { + "basic": { + "comment_id_str": "325765582", + "comment_type": 11, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "325765582" + }, + "id_str": "966583356402696224", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/c1733474892caa45952b2c09a89323157df7129a.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 3, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "946974" + }, + "face": "https://i0.hdslb.com/bfs/face/c1733474892caa45952b2c09a89323157df7129a.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/946974/dynamic", + "label": "", + "mid": 946974, + "name": "影视飓风", + "official_verify": { + "desc": "", + "type": 0 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "昨天 17:57", + "pub_ts": 1723888625, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1975248000000, + "label": { + "bg_color": "#FB7299", + "bg_style": 1, + "border_color": "", + "img_label_uri_hans": "https://i0.hdslb.com/bfs/activity-plat/static/20220608/e369244d0b14644f5e1a06431e22a4d5/wltavwHAkL.gif", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/802418ff03911645648b63aa193ba67997b5a0bc.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/8u7iRTPE7N.png", + "label_theme": "ten_annual_vip", + "path": "", + "text": "十年大会员", + "text_color": "#FFFFFF", + "use_img_label": true + }, + "nickname_color": "#FB7299", + "status": 1, + "theme_type": 0, + "type": 2 + } + }, + "module_dynamic": { + "additional": { + "reserve": { + "button": { + "check": { + "icon_url": "", + "text": "已预约" + }, + "status": 1, + "type": 2, + "uncheck": { + "icon_url": "https://i0.hdslb.com/bfs/album/1d6af68e116985828780dd843ef435ccd6307e63.png", + "text": "预约" + } + }, + "desc1": { + "style": 0, + "text": "今天 20:00 直播" + }, + "desc2": { + "style": 0, + "text": "4153人预约", + "visible": true + }, + "jump_url": "", + "reserve_total": 4153, + "rid": 4003487, + "state": 0, + "stype": 2, + "title": "直播预约:飓风商店夏促来了!", + "up_mid": 946974 + }, + "type": "ADDITIONAL_TYPE_RESERVE" + }, + "desc": { + "rich_text_nodes": [ + { + "orig_text": "飓风商店夏季活动来啦!\n8月18日周日晚20:00,直播间每15分钟天选抽送【热升华键帽】!\n\n👇新品看这边\n呼声超高的mini托特挂件、防泼水拎包、新版车贴,首发好价!\n👇福利看这边\n经典热销款全场9折,夏秋两季可穿,硬件同享折扣!\n\n总之,记得预约!", + "text": "飓风商店夏季活动来啦!\n8月18日周日晚20:00,直播间每15分钟天选抽送【热升华键帽】!\n\n👇新品看这边\n呼声超高的mini托特挂件、防泼水拎包、新版车贴,首发好价!\n👇福利看这边\n经典热销款全场9折,夏秋两季可穿,硬件同享折扣!\n\n总之,记得预约!", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "飓风商店夏季活动来啦!\n8月18日周日晚20:00,直播间每15分钟天选抽送【热升华键帽】!\n\n👇新品看这边\n呼声超高的mini托特挂件、防泼水拎包、新版车贴,首发好价!\n👇福利看这边\n经典热销款全场9折,夏秋两季可穿,硬件同享折扣!\n\n总之,记得预约!" + }, + "major": { + "draw": { + "id": 325765582, + "items": [ + { + "height": 9829, + "size": 5198.785, + "src": "http://i0.hdslb.com/bfs/new_dyn/9d690134c84c03f6bacf83cf4d21bd73946974.jpg", + "tags": [], + "width": 2251 + } + ] + }, + "type": "MAJOR_TYPE_DRAW" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 3104, + "forbidden": false + }, + "forward": { + "count": 154, + "forbidden": false + }, + "like": { + "count": 4703, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_DRAW", + "visible": true + }, + { + "basic": { + "comment_id_str": "325753910", + "comment_type": 11, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "325753910" + }, + "id_str": "966552037496979456", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_animation": { + "webp_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/7efb679569b2faeff38fa08f6f992fa1ada5e948.webp" + }, + "src_type": 1 + } + }, + "res_type": 4 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/0dcf03aa499a64524fe25871d26d95f49f880928.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 3, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "686127" + }, + "face": "https://i0.hdslb.com/bfs/face/7efb679569b2faeff38fa08f6f992fa1ada5e948.webp", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/686127/dynamic", + "label": "", + "mid": 686127, + "name": "籽岷", + "official_verify": { + "desc": "", + "type": 0 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/0dcf03aa499a64524fe25871d26d95f49f880928.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/0dcf03aa499a64524fe25871d26d95f49f880928.png", + "image_enhance_frame": "", + "n_pid": 2066, + "name": "百年大会员", + "pid": 2066 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "昨天 15:55", + "pub_ts": 1723881333, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 4845196800000, + "label": { + "bg_color": "#FB7299", + "bg_style": 1, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/c16005a5b39164b3536cbd45618a5edd597a1c51.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/Pzrd8zmpQD.png", + "label_theme": "hundred_annual_vip", + "path": "", + "text": "百年大会员", + "text_color": "#FFFFFF", + "use_img_label": true + }, + "nickname_color": "#FB7299", + "status": 1, + "theme_type": 0, + "type": 2 + } + }, + "module_dynamic": { + "additional": { + "type": "ADDITIONAL_TYPE_UPOWER_LOTTERY", + "upower_lottery": { + "button": { + "jump_style": { + "icon_url": "", + "text": "6元充电" + }, + "jump_url": "https://www.bilibili.com/h5/upower/index?mid=686127\u0026default_level=10\u0026levels=10\u0026navhide=1\u0026lotteryId=313280\u0026businessId=966552037496979456\u0026prePage=lotteryCard", + "type": 1 + }, + "desc": { + "jump_url": "https://www.bilibili.com/h5/lottery/result?business_id=966552037496979456\u0026business_type=12", + "style": 1, + "text": "【籽岷定制手偶】*10份" + }, + "hint": { + "style": 0, + "text": "加入当前UP主的「6元档包月充电」即可参与" + }, + "jump_url": "https://www.bilibili.com/h5/lottery/result?business_id=966552037496979456\u0026business_type=12", + "rid": 313280, + "state": 0, + "title": "石粒专属抽奖", + "up_mid": 686127, + "upower_action_state": 2, + "upower_level": 10 + } + }, + "desc": { + "rich_text_nodes": [ + { + "emoji": { + "icon_url": "https://i0.hdslb.com/bfs/garb/ebeae1235fa9397e6e5598ce1e5e2955bb345a8b.png", + "size": 2, + "text": "[UPOWER_686127_闪亮登场]", + "type": 11 + }, + "orig_text": "[UPOWER_686127_闪亮登场]", + "text": "[UPOWER_686127_闪亮登场]", + "type": "RICH_TEXT_NODE_TYPE_EMOJI" + }, + { + "orig_text": "今天给大家奉上一波新福利,抽10人(籽岷定制手偶)~\n感谢一直为我包月充电的观众们~\n活动开奖时间为8月21日23点59分,大家快来抽奖吧~", + "text": "今天给大家奉上一波新福利,抽10人(籽岷定制手偶)~\n感谢一直为我包月充电的观众们~\n活动开奖时间为8月21日23点59分,大家快来抽奖吧~", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "[UPOWER_686127_闪亮登场]今天给大家奉上一波新福利,抽10人(籽岷定制手偶)~\n感谢一直为我包月充电的观众们~\n活动开奖时间为8月21日23点59分,大家快来抽奖吧~" + }, + "major": { + "draw": { + "id": 325753910, + "items": [ + { + "height": 800, + "size": 596.8096, + "src": "http://i0.hdslb.com/bfs/new_dyn/1b03b7888b105765d985f3093e5d6e4a686127.png", + "tags": [], + "width": 800 + }, + { + "height": 800, + "size": 393.75098, + "src": "http://i0.hdslb.com/bfs/new_dyn/b69ee39531bf8864471ec9fbc7de4402686127.png", + "tags": [], + "width": 800 + }, + { + "height": 800, + "size": 364.8711, + "src": "http://i0.hdslb.com/bfs/new_dyn/0c3fb5268abe60023b0053902bccde66686127.png", + "tags": [], + "width": 800 + }, + { + "height": 800, + "size": 198.65234, + "src": "http://i0.hdslb.com/bfs/new_dyn/693a40f83d2ac6a4952c9541365e1265686127.png", + "tags": [], + "width": 800 + } + ] + }, + "type": "MAJOR_TYPE_DRAW" + }, + "topic": { + "id": 1006239, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1006239\u0026topic_name=%E7%B1%BD%E5%B2%B7%E5%93%81%E9%89%B4%E5%9B%A2", + "name": "籽岷品鉴团" + } + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 28, + "forbidden": false + }, + "forward": { + "count": 2, + "forbidden": false + }, + "like": { + "count": 2686, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_DRAW", + "visible": true + }, + { + "basic": { + "comment_id_str": "1456450441", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "1456450441" + }, + "id_str": "966513421411418114", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/94183796acd85f2e80f3dca740bc1c3d5cae6410.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 1, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "3493131246897478" + }, + "face": "https://i1.hdslb.com/bfs/face/94183796acd85f2e80f3dca740bc1c3d5cae6410.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/3493131246897478/dynamic", + "label": "", + "mid": 3493131246897478, + "name": "电解碳酸钠", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "昨天 13:25", + "pub_ts": 1723872342, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1744732800000, + "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": "给脚专用的“按键” 我觉得他不应该这么贵", + "text": "给脚专用的“按键” 我觉得他不应该这么贵", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "给脚专用的“按键” 我觉得他不应该这么贵" + }, + "major": { + "archive": { + "aid": "1456450441", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1Yi421a7FC", + "cover": "http://i1.hdslb.com/bfs/archive/b56700e0a1d28ecff2ff135a7cc51e9b09cace79.jpg", + "desc": "用到的配件:\n·带有热插拔轴体功能的任何全新\u0026二手键盘 只要功能正常即可\n·追求极致性价比的 可以直接买剪线键盘进行改造\n·TFS-1脚踏脚踩开关(我买的3.2一个)\n要注意这些脚踏开关有可能是3线 分为常闭和常开\n对于这个型号的开关 我接的是红线+白线 为踩下触发\n·焊油(推荐针管式单手操作)", + "disable_preview": 0, + "duration_text": "06:01", + "jump_url": "//www.bilibili.com/video/BV1Yi421a7FC/", + "stat": { + "danmaku": "149", + "play": "2.7万" + }, + "title": "商家别看!脚踩键盘DIY超值方案?市场售价凭啥那么贵!", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 161, + "forbidden": false + }, + "forward": { + "count": 17, + "forbidden": false + }, + "like": { + "count": 2699, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + { + "basic": { + "comment_id_str": "966495069003579398", + "comment_type": 17, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "966495069003579398" + }, + "id_str": "966495069003579398", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/c1733474892caa45952b2c09a89323157df7129a.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 3, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "946974" + }, + "face": "https://i0.hdslb.com/bfs/face/c1733474892caa45952b2c09a89323157df7129a.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/946974/dynamic", + "label": "", + "mid": 946974, + "name": "影视飓风", + "official_verify": { + "desc": "", + "type": 0 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "昨天 12:14", + "pub_ts": 1723868069, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1975248000000, + "label": { + "bg_color": "#FB7299", + "bg_style": 1, + "border_color": "", + "img_label_uri_hans": "https://i0.hdslb.com/bfs/activity-plat/static/20220608/e369244d0b14644f5e1a06431e22a4d5/wltavwHAkL.gif", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/802418ff03911645648b63aa193ba67997b5a0bc.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/8u7iRTPE7N.png", + "label_theme": "ten_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": "周末啦,希望大家喜欢这期科普分享!我们的官网也加上了电影节的科普和信息汇总,欢迎大家取用~", + "text": "周末啦,希望大家喜欢这期科普分享!我们的官网也加上了电影节的科普和信息汇总,欢迎大家取用~", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "周末啦,希望大家喜欢这期科普分享!我们的官网也加上了电影节的科普和信息汇总,欢迎大家取用~" + }, + "major": null, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 101, + "forbidden": false + }, + "forward": { + "count": 7, + "forbidden": false + }, + "like": { + "count": 5247, + "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": "966197633939931139", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/c1733474892caa45952b2c09a89323157df7129a.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 3, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "946974" + }, + "face": "https://i0.hdslb.com/bfs/face/c1733474892caa45952b2c09a89323157df7129a.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/946974/dynamic", + "label": "", + "mid": 946974, + "name": "影视飓风", + "official_verify": { + "desc": "", + "type": 0 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_time": "", + "pub_ts": 1723798817, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1975248000000, + "label": { + "bg_color": "#FB7299", + "bg_style": 1, + "border_color": "", + "img_label_uri_hans": "https://i0.hdslb.com/bfs/activity-plat/static/20220608/e369244d0b14644f5e1a06431e22a4d5/wltavwHAkL.gif", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/802418ff03911645648b63aa193ba67997b5a0bc.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/8u7iRTPE7N.png", + "label_theme": "ten_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": "挺久没有更新的看懂电影系列!", + "text": "挺久没有更新的看懂电影系列!", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "挺久没有更新的看懂电影系列!" + }, + "major": { + "archive": { + "aid": "1506437840", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV13S42197ja", + "cover": "http://i1.hdslb.com/bfs/archive/50d4705b2d804a76f3c19af269dd7804479aa94e.jpg", + "desc": "国内外总共有3000多个大大小小的电影节。那么,短片可以参加电影节吗?什么时候投递获奖概率才大一些?这次我们想和你分享一些投递和参加电影节的门道。我们还整理了一份有关电影节的科普文档,可以来我们的官网看看:https://filmfestival.ysjf.com/。\n如果你喜欢这期视频,请多多支持我们,并将视频分享给其他朋友一起看看!", + "disable_preview": 0, + "duration_text": "10:55", + "jump_url": "//www.bilibili.com/video/BV13S42197ja/", + "stat": { + "danmaku": "2067", + "play": "64.1万" + }, + "title": "全世界3000多个电影节,都在办些啥?", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "type": "DYNAMIC_TYPE_FORWARD", + "visible": true + }, + { + "basic": { + "comment_id_str": "37185041", + "comment_type": 12, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "37185041" + }, + "id_str": "966484129969340422", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/978ea07f22e54c2e62f01def8e815b59adacc5d0.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 4, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "407045223" + }, + "decorate": { + "card_url": "https://i0.hdslb.com/bfs/vip/a9e3d993c7a15e88ce0bf714a142f7d2b44121e2.png", + "fan": { + "color": "", + "color_format": null, + "is_fan": false, + "num_prefix": "", + "num_str": "", + "number": 0 + }, + "id": 28, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=28\u0026isdiy=0\u0026part=card\u0026from=post\u0026f_source=garb\u0026vmid=407045223\u0026native.theme=1\u0026navhide=1", + "name": "2233娘", + "type": 1 + }, + "face": "https://i0.hdslb.com/bfs/face/978ea07f22e54c2e62f01def8e815b59adacc5d0.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/407045223/dynamic", + "label": "", + "mid": 407045223, + "name": "二次元的中科院物理所", + "official_verify": { + "desc": "", + "type": 1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了文章", + "pub_location_text": "", + "pub_time": "昨天 11:32", + "pub_ts": 1723865522, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1745769600000, + "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": null, + "major": { + "article": { + "covers": [ + "https://i0.hdslb.com/bfs/article/708ab38ac38df8fe7851a63c0258fa64407045223.jpg" + ], + "desc": "经历过密码解锁和手势解锁后 真感慨指纹解锁是天才的创造 可惜遇到湿手油手经常失效 甚至擦干了还是这样 这是为什么呢问答导航Q1 鸡蛋在母鸡体内有气室吗?Q2 为什么弹簧是螺旋型的?Q3 闪电为什么总是自上而下,有没有自下而上的闪电呢?Q4 当一束光使电子发生了能级跃迁,原先的光子去哪儿了,消失了吗?Q5 为什么有茶叶的水在转时茶叶会趋向中间而不是两边呢?Q6 为什么塑料相比于其它物质,更容易起静电?Q7 为什么会有空集?空集的存在有什么物理意义? Q8 为什么有纹理的木擦了木蜡油之后会纹理变深,更容易被看", + "id": 37185041, + "jump_url": "//www.bilibili.com/read/cv37185041/", + "label": "16.3万阅读", + "title": "手指沾水擦干但是指纹识别还是失败,这是什么原因?| No.422" + }, + "type": "MAJOR_TYPE_ARTICLE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 23, + "forbidden": false + }, + "forward": { + "count": 7, + "forbidden": false + }, + "like": { + "count": 727, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_ARTICLE", + "visible": true + }, + { + "basic": { + "comment_id_str": "966475883631083553", + "comment_type": 17, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "966475883631083553" + }, + "id_str": "966475883631083553", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/1fd5b43d5f619e6df8c8adcf13c962a3e80ee971.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/garb/item/fe1267f786bf69f1471aff715f8d38ec0e486df5.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 4, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "layers": [ + { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/1fd5b43d5f619e6df8c8adcf13c962a3e80ee971.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + { + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_animation": { + "webp_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/garb/item/0aa9fd33133ed3fd9f11c857cc6ca848d6804113.webp" + }, + "src_type": 1 + } + }, + "res_type": 4 + }, + "visible": true + } + ] + }, + { + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 4, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + } + ], + "mid": "233114659" + }, + "decorate": { + "card_url": "https://i0.hdslb.com/bfs/garb/bb140043341137b879e957d09b649ce7c3257820.png", + "fan": { + "color": "#903AC2", + "color_format": { + "colors": [ + "#903AC2FF", + "#903AC2FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": true, + "num_prefix": "NO.", + "num_str": "000001", + "number": 1 + }, + "id": 1706163888001, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=1706163888001\u0026isdiy=0\u0026part=card\u0026from=post\u0026f_source=garb\u0026vmid=233114659\u0026native.theme=1\u0026navhide=1", + "name": "龙腾啾跃-动态卡片粉丝", + "type": 3 + }, + "face": "https://i1.hdslb.com/bfs/face/1fd5b43d5f619e6df8c8adcf13c962a3e80ee971.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/233114659/dynamic", + "label": "", + "mid": 233114659, + "name": "碧蓝航线", + "official_verify": { + "desc": "", + "type": 1 + }, + "pendant": { + "expire": 0, + "image": "https://i1.hdslb.com/bfs/garb/item/fe1267f786bf69f1471aff715f8d38ec0e486df5.png", + "image_enhance": "https://i1.hdslb.com/bfs/garb/item/0aa9fd33133ed3fd9f11c857cc6ca848d6804113.webp", + "image_enhance_frame": "https://i1.hdslb.com/bfs/garb/item/3052b412defbbc7704e887fefde8de539e8027c5.png", + "n_pid": 1987, + "name": "碧蓝航线2020", + "pid": 1987 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "昨天 11:00", + "pub_ts": 1723863602, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1729526400000, + "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": "恭喜", + "text": "恭喜", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@两百斤的橘猫猫0w0", + "rid": "8391364", + "text": "@两百斤的橘猫猫0w0", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": "@一位隐身的Z23厨", + "rid": "382382091", + "text": "@一位隐身的Z23厨", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": "@默涛默随波", + "rid": "230373473", + "text": "@默涛默随波", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": "等8位同学中奖,已私信通知,详情请点击抽奖查看。", + "text": "等8位同学中奖,已私信通知,详情请点击抽奖查看。", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "恭喜@两百斤的橘猫猫0w0@一位隐身的Z23厨@默涛默随波等8位同学中奖,已私信通知,详情请点击抽奖查看。" + }, + "major": null, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 227, + "forbidden": false + }, + "forward": { + "count": 20, + "forbidden": false + }, + "like": { + "count": 3126, + "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": "963893770559946786", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/1fd5b43d5f619e6df8c8adcf13c962a3e80ee971.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/garb/item/fe1267f786bf69f1471aff715f8d38ec0e486df5.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 4, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "layers": [ + { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/1fd5b43d5f619e6df8c8adcf13c962a3e80ee971.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + { + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_animation": { + "webp_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/garb/item/0aa9fd33133ed3fd9f11c857cc6ca848d6804113.webp" + }, + "src_type": 1 + } + }, + "res_type": 4 + }, + "visible": true + } + ] + }, + { + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 4, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + } + ], + "mid": "233114659" + }, + "decorate": { + "card_url": "https://i0.hdslb.com/bfs/garb/bb140043341137b879e957d09b649ce7c3257820.png", + "fan": { + "color": "#903AC2", + "color_format": { + "colors": [ + "#903AC2FF", + "#903AC2FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": true, + "num_prefix": "NO.", + "num_str": "000001", + "number": 1 + }, + "id": 1706163888001, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=1706163888001\u0026isdiy=0\u0026part=card\u0026from=post\u0026f_source=garb\u0026vmid=233114659\u0026native.theme=1\u0026navhide=1", + "name": "龙腾啾跃-动态卡片粉丝", + "type": 3 + }, + "face": "https://i1.hdslb.com/bfs/face/1fd5b43d5f619e6df8c8adcf13c962a3e80ee971.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/233114659/dynamic", + "label": "", + "mid": 233114659, + "name": "碧蓝航线", + "official_verify": { + "desc": "", + "type": 1 + }, + "pendant": { + "expire": 0, + "image": "https://i1.hdslb.com/bfs/garb/item/fe1267f786bf69f1471aff715f8d38ec0e486df5.png", + "image_enhance": "https://i1.hdslb.com/bfs/garb/item/0aa9fd33133ed3fd9f11c857cc6ca848d6804113.webp", + "image_enhance_frame": "https://i1.hdslb.com/bfs/garb/item/3052b412defbbc7704e887fefde8de539e8027c5.png", + "n_pid": 1987, + "name": "碧蓝航线2020", + "pid": 1987 + }, + "pub_action": "", + "pub_time": "", + "pub_ts": 1723262407, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1729526400000, + "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": { + "common": { + "button": { + "jump_style": { + "icon_url": "", + "text": "进入" + }, + "jump_url": "https://www.biligame.com/detail?id=97\u0026sourceFrom=1005", + "type": 1 + }, + "cover": "https://i0.hdslb.com/bfs/game/b141a7690c226a0eae66518c713d3af62613b21d.png", + "desc1": "养成", + "desc2": "指挥官,欢迎回港", + "head_text": "相关游戏", + "id_str": "97", + "jump_url": "https://www.biligame.com/detail?id=97\u0026sourceFrom=1005", + "style": 1, + "sub_type": "game", + "title": "碧蓝航线" + }, + "type": "ADDITIONAL_TYPE_COMMON" + }, + "desc": { + "rich_text_nodes": [ + { + "jump_url": "//search.bilibili.com/all?keyword=%E7%A2%A7%E8%93%9D%E8%88%AA%E7%BA%BF", + "orig_text": "#碧蓝航线#", + "text": "#碧蓝航线#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "orig_text": " ", + "text": " ", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "互动抽奖", + "rid": "312103", + "text": "互动抽奖", + "type": "RICH_TEXT_NODE_TYPE_LOTTERY" + }, + { + "orig_text": " \n兰夜放灯祈相守,\n纤手弄糕思今宵。\n\n关注", + "text": " \n兰夜放灯祈相守,\n纤手弄糕思今宵。\n\n关注", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@碧蓝航线", + "rid": "233114659", + "text": "@碧蓝航线", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": " 并转发该内容,我们将于8月17日抽取3位指挥官送出【JUUs时间 花园Q版手办】,抽取5位指挥官送出【心智魔方-系列浴球(随机一款)】。\n\n金风玉露,值此良宵,愿与君共度~", + "text": " 并转发该内容,我们将于8月17日抽取3位指挥官送出【JUUs时间 花园Q版手办】,抽取5位指挥官送出【心智魔方-系列浴球(随机一款)】。\n\n金风玉露,值此良宵,愿与君共度~", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "#碧蓝航线# 互动抽奖 \n兰夜放灯祈相守,\n纤手弄糕思今宵。\n\n关注@碧蓝航线 并转发该内容,我们将于8月17日抽取3位指挥官送出【JUUs时间 花园Q版手办】,抽取5位指挥官送出【心智魔方-系列浴球(随机一款)】。\n\n金风玉露,值此良宵,愿与君共度~" + }, + "major": { + "draw": { + "id": 324938558, + "items": [ + { + "height": 3038, + "size": 2025.2646, + "src": "http://i0.hdslb.com/bfs/new_dyn/b0068d1603aee2849ca46a58642fa99e233114659.jpg", + "tags": [], + "width": 5400 + }, + { + "height": 5063, + "size": 7377.1143, + "src": "http://i0.hdslb.com/bfs/new_dyn/c047aafcf90a48b578a63c3e1b86c1de233114659.jpg", + "tags": [], + "width": 9000 + } + ] + }, + "type": "MAJOR_TYPE_DRAW" + }, + "topic": null + } + }, + "type": "DYNAMIC_TYPE_DRAW", + "visible": true + }, + "type": "DYNAMIC_TYPE_FORWARD", + "visible": true + }, + { + "basic": { + "comment_id_str": "1456253104", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "1456253104" + }, + "id_str": "966374603744083976", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_animation": { + "webp_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/7efb679569b2faeff38fa08f6f992fa1ada5e948.webp" + }, + "src_type": 1 + } + }, + "res_type": 4 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/0dcf03aa499a64524fe25871d26d95f49f880928.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 3, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "686127" + }, + "face": "https://i0.hdslb.com/bfs/face/7efb679569b2faeff38fa08f6f992fa1ada5e948.webp", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/686127/dynamic", + "label": "", + "mid": 686127, + "name": "籽岷", + "official_verify": { + "desc": "", + "type": 0 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/0dcf03aa499a64524fe25871d26d95f49f880928.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/0dcf03aa499a64524fe25871d26d95f49f880928.png", + "image_enhance_frame": "", + "n_pid": 2066, + "name": "百年大会员", + "pid": 2066 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "昨天 04:27", + "pub_ts": 1723840021, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 4845196800000, + "label": { + "bg_color": "#FB7299", + "bg_style": 1, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/c16005a5b39164b3536cbd45618a5edd597a1c51.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/Pzrd8zmpQD.png", + "label_theme": "hundred_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": null, + "major": { + "archive": { + "aid": "1456253104", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1ai421h7nT", + "cover": "http://i1.hdslb.com/bfs/archive/0245f30593e2963b883cd5953881034ad033fbd5.jpg", + "desc": "https://www.minecraft.net/en-us/article/minecraft-snapshot-24w33a", + "disable_preview": 0, + "duration_text": "16:22", + "jump_url": "//www.bilibili.com/video/BV1ai421h7nT/", + "stat": { + "danmaku": "2149", + "play": "24.5万" + }, + "title": "收纳袋、红石、矿车大改 我的世界新版本介绍 1.21.2 24w33a", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": { + "id": 1028161, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1028161\u0026topic_name=%E6%95%B4%E7%82%B9%E7%94%B5%E5%AD%90%E6%A6%A8%E8%8F%9C", + "name": "整点电子榨菜" + } + }, + "module_interaction": { + "items": [ + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "名字永远是个谜:", + "rid": "2022349482", + "text": "名字永远是个谜:", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": "我们轨道交通圈有福了啊啊啊啊啊啊啊!", + "text": "我们轨道交通圈有福了啊啊啊啊啊啊啊!", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "我们轨道交通圈有福了啊啊啊啊啊啊啊!" + }, + "type": 1 + } + ] + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 921, + "forbidden": false + }, + "forward": { + "count": 51, + "forbidden": false + }, + "like": { + "count": 23138, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + { + "basic": { + "comment_id_str": "325694432", + "comment_type": 11, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "325694432" + }, + "id_str": "966306597269667840", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/2b9ee4a9c99f1006f3c800c1317f7850ad6f3d0d.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 4, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "485703766" + }, + "face": "https://i1.hdslb.com/bfs/face/2b9ee4a9c99f1006f3c800c1317f7850ad6f3d0d.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/485703766/dynamic", + "label": "", + "mid": 485703766, + "name": "英伟达GeForce", + "official_verify": { + "desc": "", + "type": 1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "昨天 00:03", + "pub_ts": 1723824187, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 2000563200000, + "label": { + "bg_color": "#FB7299", + "bg_style": 1, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/adb599797dd171e2d3d6d012f448b49679258344.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/sGu57N6pgK.png", + "label_theme": "ten_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": "直面天命,还有 3 天!\nRTX. ON!\n\n投稿来自于:Bilibili", + "text": "直面天命,还有 3 天!\nRTX. ON!\n\n投稿来自于:Bilibili", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@祗殁 ", + "rid": "12299496", + "text": "@祗殁 ", + "type": "RICH_TEXT_NODE_TYPE_AT" + } + ], + "text": "直面天命,还有 3 天!\nRTX. ON!\n\n投稿来自于:Bilibili@祗殁 " + }, + "major": { + "draw": { + "id": 325694432, + "items": [ + { + "height": 1280, + "size": 59.246094, + "src": "http://i0.hdslb.com/bfs/new_dyn/2e42c52d5e1383fe443f0984a41a9624485703766.jpg", + "tags": [], + "width": 1282 + } + ] + }, + "type": "MAJOR_TYPE_DRAW" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 115, + "forbidden": false + }, + "forward": { + "count": 3, + "forbidden": false + }, + "like": { + "count": 876, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_DRAW", + "visible": true + }, + { + "basic": { + "comment_id_str": "325690655", + "comment_type": 11, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "325690655" + }, + "id_str": "966298866306515029", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/1fd5b43d5f619e6df8c8adcf13c962a3e80ee971.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/garb/item/fe1267f786bf69f1471aff715f8d38ec0e486df5.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 4, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "layers": [ + { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/1fd5b43d5f619e6df8c8adcf13c962a3e80ee971.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + { + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_animation": { + "webp_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/garb/item/0aa9fd33133ed3fd9f11c857cc6ca848d6804113.webp" + }, + "src_type": 1 + } + }, + "res_type": 4 + }, + "visible": true + } + ] + }, + { + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 4, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + } + ], + "mid": "233114659" + }, + "decorate": { + "card_url": "https://i0.hdslb.com/bfs/garb/bb140043341137b879e957d09b649ce7c3257820.png", + "fan": { + "color": "#903AC2", + "color_format": { + "colors": [ + "#903AC2FF", + "#903AC2FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": true, + "num_prefix": "NO.", + "num_str": "000001", + "number": 1 + }, + "id": 1706163888001, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=1706163888001\u0026isdiy=0\u0026part=card\u0026from=post\u0026f_source=garb\u0026vmid=233114659\u0026native.theme=1\u0026navhide=1", + "name": "龙腾啾跃-动态卡片粉丝", + "type": 3 + }, + "face": "https://i1.hdslb.com/bfs/face/1fd5b43d5f619e6df8c8adcf13c962a3e80ee971.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/233114659/dynamic", + "label": "", + "mid": 233114659, + "name": "碧蓝航线", + "official_verify": { + "desc": "", + "type": 1 + }, + "pendant": { + "expire": 0, + "image": "https://i1.hdslb.com/bfs/garb/item/fe1267f786bf69f1471aff715f8d38ec0e486df5.png", + "image_enhance": "https://i1.hdslb.com/bfs/garb/item/0aa9fd33133ed3fd9f11c857cc6ca848d6804113.webp", + "image_enhance_frame": "https://i1.hdslb.com/bfs/garb/item/3052b412defbbc7704e887fefde8de539e8027c5.png", + "n_pid": 1987, + "name": "碧蓝航线2020", + "pid": 1987 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "2天前", + "pub_ts": 1723822387, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1729526400000, + "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": { + "common": { + "button": { + "jump_style": { + "icon_url": "", + "text": "进入" + }, + "jump_url": "https://www.biligame.com/detail?id=97\u0026sourceFrom=1005", + "type": 1 + }, + "cover": "https://i0.hdslb.com/bfs/game/b141a7690c226a0eae66518c713d3af62613b21d.png", + "desc1": "养成", + "desc2": "指挥官,欢迎回港", + "head_text": "相关游戏", + "id_str": "97", + "jump_url": "https://www.biligame.com/detail?id=97\u0026sourceFrom=1005", + "style": 1, + "sub_type": "game", + "title": "碧蓝航线" + }, + "type": "ADDITIONAL_TYPE_COMMON" + }, + "desc": { + "rich_text_nodes": [ + { + "jump_url": "//search.bilibili.com/all?keyword=%E7%A2%A7%E8%93%9D%E8%88%AA%E7%BA%BF", + "orig_text": "#碧蓝航线#", + "text": "#碧蓝航线#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "orig_text": " ", + "text": " ", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%E7%A2%A7%E8%93%9D%E8%88%AA%E7%BA%BF%E6%BC%AB%E5%B1%95", + "orig_text": "#碧蓝航线漫展#", + "text": "#碧蓝航线漫展#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "orig_text": " ", + "text": " ", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=2024%E6%B8%AF%E5%8C%BA%E7%9B%9B%E5%A4%8F%E6%B8%85%E5%87%89%E8%8A%82", + "orig_text": "#2024港区盛夏清凉节#", + "text": "#2024港区盛夏清凉节#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "orig_text": "\n◆ 「港区盛夏清凉节」长沙站·街区快闪 到达!◆ \n\n碧蓝夏日,映照专属的街景~\n街区快闪即将开启,\n与少女们一同踏上这场特别的城市漫步之旅吧!\n\n◆ 互动游戏开放时间:2024年8月17日~8月18日,每日10:00~12:00及14:00~19:00\n◆ 街区快闪体验地址:湖南省长沙市开福区潮宗街历史文化街区\n◆ 参与方式:无需预约,前往现场即可参与体验~\n◆ 体验须知:\n※8月17日~8月18日期间,指挥官可前往潮宗街历史文化街区现场参与体验。\n※指挥官关注《碧蓝航线》官方B站账号后,可参与互动游戏,集章兑换周边礼品哟!\n※兑换周边每日数量有限,兑完即止。\n※天气炎热,请指挥官做好防暑准备,出行注意安全哟。", + "text": "\n◆ 「港区盛夏清凉节」长沙站·街区快闪 到达!◆ \n\n碧蓝夏日,映照专属的街景~\n街区快闪即将开启,\n与少女们一同踏上这场特别的城市漫步之旅吧!\n\n◆ 互动游戏开放时间:2024年8月17日~8月18日,每日10:00~12:00及14:00~19:00\n◆ 街区快闪体验地址:湖南省长沙市开福区潮宗街历史文化街区\n◆ 参与方式:无需预约,前往现场即可参与体验~\n◆ 体验须知:\n※8月17日~8月18日期间,指挥官可前往潮宗街历史文化街区现场参与体验。\n※指挥官关注《碧蓝航线》官方B站账号后,可参与互动游戏,集章兑换周边礼品哟!\n※兑换周边每日数量有限,兑完即止。\n※天气炎热,请指挥官做好防暑准备,出行注意安全哟。", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "#碧蓝航线# #碧蓝航线漫展# #2024港区盛夏清凉节#\n◆ 「港区盛夏清凉节」长沙站·街区快闪 到达!◆ \n\n碧蓝夏日,映照专属的街景~\n街区快闪即将开启,\n与少女们一同踏上这场特别的城市漫步之旅吧!\n\n◆ 互动游戏开放时间:2024年8月17日~8月18日,每日10:00~12:00及14:00~19:00\n◆ 街区快闪体验地址:湖南省长沙市开福区潮宗街历史文化街区\n◆ 参与方式:无需预约,前往现场即可参与体验~\n◆ 体验须知:\n※8月17日~8月18日期间,指挥官可前往潮宗街历史文化街区现场参与体验。\n※指挥官关注《碧蓝航线》官方B站账号后,可参与互动游戏,集章兑换周边礼品哟!\n※兑换周边每日数量有限,兑完即止。\n※天气炎热,请指挥官做好防暑准备,出行注意安全哟。" + }, + "major": { + "draw": { + "id": 325690655, + "items": [ + { + "height": 6000, + "size": 2737.6729, + "src": "http://i0.hdslb.com/bfs/new_dyn/722dc5e7eba3c3f6861b294f6bf3020c233114659.jpg", + "tags": [], + "width": 4000 + }, + { + "height": 4000, + "size": 4852.4023, + "src": "http://i0.hdslb.com/bfs/new_dyn/b04110f894184880666ee8b204000846233114659.jpg", + "tags": [], + "width": 6000 + }, + { + "height": 4000, + "size": 3941.9678, + "src": "http://i0.hdslb.com/bfs/new_dyn/8ce3c1e6f2d33a47d42f35193b9e5f55233114659.jpg", + "tags": [], + "width": 6000 + }, + { + "height": 4000, + "size": 4461.9707, + "src": "http://i0.hdslb.com/bfs/new_dyn/ab9a5bf2215f88fed6026d67d98ec901233114659.jpg", + "tags": [], + "width": 6000 + }, + { + "height": 4000, + "size": 3137.0205, + "src": "http://i0.hdslb.com/bfs/new_dyn/18e62cf8ebc7c07b99e042ac4cdeeaaa233114659.jpg", + "tags": [], + "width": 6000 + }, + { + "height": 4000, + "size": 9561.615, + "src": "http://i0.hdslb.com/bfs/new_dyn/1036f447fcbec195e717e2a5b3091a73233114659.jpg", + "tags": [], + "width": 6000 + } + ] + }, + "type": "MAJOR_TYPE_DRAW" + }, + "topic": null + }, + "module_interaction": { + "items": [ + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "豌豆羹:", + "rid": "3493280973064560", + "text": "豌豆羹:", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": "大帝皮肤加彩蛋!", + "text": "大帝皮肤加彩蛋!", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "大帝皮肤加彩蛋!" + }, + "type": 1 + } + ] + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 446, + "forbidden": false + }, + "forward": { + "count": 47, + "forbidden": false + }, + "like": { + "count": 4352, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_DRAW", + "visible": true + }, + { + "basic": { + "comment_id_str": "966281785469042740", + "comment_type": 17, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "966281785469042740" + }, + "id_str": "966281785469042740", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/21426275f3d3149b96b88783275205ba574c09e3.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 3, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "178429408" + }, + "face": "https://i1.hdslb.com/bfs/face/21426275f3d3149b96b88783275205ba574c09e3.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/178429408/dynamic", + "label": "", + "mid": 178429408, + "name": "老弟一号", + "official_verify": { + "desc": "", + "type": 0 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "2天前", + "pub_ts": 1723818410, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1728576000000, + "label": { + "bg_color": "#FB7299", + "bg_style": 1, + "border_color": "", + "img_label_uri_hans": "https://i0.hdslb.com/bfs/activity-plat/static/20220608/e369244d0b14644f5e1a06431e22a4d5/0DFy9BHgwE.gif", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/8d7e624d13d3e134251e4174a7318c19a8edbd71.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/uckjAv3Npy.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": "不管怎么样,我先把香槟开了", + "text": "不管怎么样,我先把香槟开了", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "emoji": { + "icon_url": "https://i0.hdslb.com/bfs/emote/bf7e00ecab02171f8461ee8cf439c73db9797748.png", + "size": 1, + "text": "[脱单doge]", + "type": 1 + }, + "orig_text": "[脱单doge]", + "text": "[脱单doge]", + "type": "RICH_TEXT_NODE_TYPE_EMOJI" + }, + { + "orig_text": "要是褒姒,直播抽一百个爵柏电源", + "text": "要是褒姒,直播抽一百个爵柏电源", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "不管怎么样,我先把香槟开了[脱单doge]要是褒姒,直播抽一百个爵柏电源" + }, + "major": null, + "topic": null + }, + "module_interaction": { + "items": [ + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "芊芊老猫的日常:", + "rid": "1284100140", + "text": "芊芊老猫的日常:", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": "还是好人多啊", + "text": "还是好人多啊", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "emoji": { + "icon_url": "https://i0.hdslb.com/bfs/emote/4683fd9ffc925fa6423110979d7dcac5eda297f4.png", + "size": 1, + "text": "[OK]", + "type": 1 + }, + "orig_text": "[OK]", + "text": "[OK]", + "type": "RICH_TEXT_NODE_TYPE_EMOJI" + } + ], + "text": "还是好人多啊[OK]" + }, + "type": 1 + } + ] + }, + "module_more": { + "three_point_items": [ + { + "label": "取消关注", + "type": "THREE_POINT_FOLLOWING" + }, + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "module_stat": { + "comment": { + "count": 156, + "forbidden": false + }, + "forward": { + "count": 1, + "forbidden": false + }, + "like": { + "count": 1367, + "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": "966274874613956608", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i2.hdslb.com/bfs/face/4c9095a6fc7d6ef7bf97ee1c65767f537763c60c.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 4, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "652239032" + }, + "face": "https://i2.hdslb.com/bfs/face/4c9095a6fc7d6ef7bf97ee1c65767f537763c60c.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/652239032/dynamic", + "label": "", + "mid": 652239032, + "name": "IGN中国", + "official_verify": { + "desc": "", + "type": 1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_time": "", + "pub_ts": 1723816801, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 0, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 0 + } + }, + "module_dynamic": { + "additional": null, + "desc": { + "rich_text_nodes": [ + { + "orig_text": "《黑神话:悟空》绝对可以说是一座中国游戏行业的里程碑,它所呈现的优秀品质对得起这四年来它背负的所有期待,这是真正意义上放在全球市场也是极具竞争力的国产游戏,而游戏科学也将在此役之后毫无疑问成为全球顶尖ARPG游戏开发商之一。", + "text": "《黑神话:悟空》绝对可以说是一座中国游戏行业的里程碑,它所呈现的优秀品质对得起这四年来它背负的所有期待,这是真正意义上放在全球市场也是极具竞争力的国产游戏,而游戏科学也将在此役之后毫无疑问成为全球顶尖ARPG游戏开发商之一。", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "《黑神话:悟空》绝对可以说是一座中国游戏行业的里程碑,它所呈现的优秀品质对得起这四年来它背负的所有期待,这是真正意义上放在全球市场也是极具竞争力的国产游戏,而游戏科学也将在此役之后毫无疑问成为全球顶尖ARPG游戏开发商之一。" + }, + "major": { + "archive": { + "aid": "1456400345", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1Ti421a7dv", + "cover": "http://i2.hdslb.com/bfs/archive/fd87a4e75738b0de1388df60f5e4ce5011b1367a.jpg", + "desc": "《黑神话:悟空》绝对可以说是一座中国游戏行业的里程碑,它所呈现的优秀品质对得起这四年来它背负的所有期待,这是真正意义上放在全球市场也是极具竞争力的国产游戏,我相信它会成为今年年度游戏的有力竞争者,而游戏科学也将在此役之后毫无疑问成为全球顶尖ARPG游戏开发商之一。", + "disable_preview": 0, + "duration_text": "10:00", + "jump_url": "//www.bilibili.com/video/BV1Ti421a7dv/", + "stat": { + "danmaku": "4.6万", + "play": "595.1万" + }, + "title": "【IGN】10分,《黑神话:悟空》评测:踏平坎坷成大道", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "type": "DYNAMIC_TYPE_FORWARD", + "visible": true + } + ], + "offset": "966281785469042740", + "update_baseline": "966888011247648768", + "update_num": 5 + } +} +``` + +</details> + +## 检测是否有新动态 + +> https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/all/update + +*请求方式:GET* + +认证方式: Cookie (SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| - | - | - | - | - | +| type | str | 动态类型 | 不必要 | 默认为 `all` | +| update_baseline | id | 更新基线 | 必要 | 用于检测是否有新动态, 默认为上次请求 [获取全部动态列表](#获取全部动态列表) 返回的 `update_baseline`, 实测填 `0` 也可正常获取 | +| web_location | str | 333.1365 | 不必要 | | + +**JSON回复:** + +根: + +| 字段 | 类型 | 内容 | 备注 | +| - | - | - | - | +| code | num | 返回值 | 0: 成功<br />-101: 账号未登录<br />-400: 请求错误 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` : + +| 字段 | 类型 | 内容 | 备注 | +| - | - | - | - | +| update_num | num | 有新动态的数量 | | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/all/update' \ +--data-urlencode 'update_baseline=114514' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "update_num": 9 + } +} +``` + +</details> diff --git a/bb-api-collect/docs/dynamic/atlist.md b/bb-api-collect/docs/dynamic/atlist.md new file mode 100644 index 0000000000..a73734f0bb --- /dev/null +++ b/bb-api-collect/docs/dynamic/atlist.md @@ -0,0 +1,238 @@ +# 根据关键字搜索用户 (at别人时的填充列表) + +**注意关键字不一定顺序匹配,如最后示例** + +> https://api.bilibili.com/x/polymer/web-dynamic/v1/mention/search + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | ---------- | ------ | ---------------------------------- | +| keyword | str | 搜索关键字 | 非必要 | 若无此项,则返回所有关注用户的信息 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录 | +| message | str | 错误信息 | 成功时为 `0` | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ----- | -------- | ---------------------------------------------- | +| groups | array | 用户分组 | 根据是否关注该用户来分组,未找到用户时为空数组 | + +`groups`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---- | +| 0 | obj | 分组1 | | +| n | obj | 分组(n+1) | | +| …… | obj | …… | …… | + +`groups`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | ---------------- | ------------------------ | +| group_name | str | 分组名称 | `我的关注`或`其他` | +| group_type | num | 分组类型 | 2:我的关注<br />4:其他 | +| items | array | 搜索到的用户信息 | 按照认证状态与粉丝数排序 | + +`items`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---- | +| 0 | obj | 用户1 | | +| n | obj | 用户(n+1) | | +| …… | obj | …… | …… | + +`items`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------------- | ---- | ------------ | ---------------------------------------- | +| face | str | 用户头像url | | +| fans | num | 用户粉丝数 | | +| name | str | 用户昵称 | | +| official_verify_type | num | 用户认证状态 | -1:无<br />0:个人认证<br />1:机构认证 | +| uid | str | 用户mid | | + +**示例:** + +搜索关键字为`社会易`的用户 + +```shell +curl -G 'https://api.bilibili.com/x/polymer/web-dynamic/v1/mention/search' \ +--data-urlencode 'keyword=社会易' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "groups": [ + { + "group_name": "我的关注", + "group_type": 2, + "items": [ + { + "face": "https://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg", + "fans": 3613, + "name": "社会易姐QwQ", + "official_verify_type": -1, + "uid": "293793435" + } + ] + }, + { + "group_name": "其他", + "group_type": 4, + "items": [ + { + "face": "https://i0.hdslb.com/bfs/face/dbc456bdec5e7a4806c9d0311d95ebcc6be674cf.jpg", + "fans": 23464, + "name": "社会易老师", + "official_verify_type": -1, + "uid": "484031754" + }, + { + "face": "https://i1.hdslb.com/bfs/face/5497859a550a017d0a51c640d232c539c2f48991.jpg", + "fans": 11, + "name": "栄禧貿易株式会社", + "official_verify_type": -1, + "uid": "4991467" + }, + { + "face": "https://i2.hdslb.com/bfs/face/311cecf9298158b8a5f47ed3e641328ab5c0cfcd.jpg", + "fans": 10, + "name": "社会李易儒", + "official_verify_type": -1, + "uid": "442101413" + }, + { + "face": "https://i2.hdslb.com/bfs/face/2dad05e4748b5e91e1ec5d3c5d4f0904a5bcdaf0.jpg", + "fans": 8, + "name": "日本国立貿易株式会社", + "official_verify_type": -1, + "uid": "3546589855484501" + }, + { + "face": "http://i0.hdslb.com/bfs/face/2ae12d7f71173baa8e00c4cfe97acb5a3de31566.jpg", + "fans": 6, + "name": "社会小伙肖子易", + "official_verify_type": -1, + "uid": "250129011" + }, + { + "face": "https://i2.hdslb.com/bfs/face/1ebb0d4aa8e2c4b532f82983503ec38b62a1820f.jpg", + "fans": 4, + "name": "社会主义接班人小易", + "official_verify_type": -1, + "uid": "486568790" + }, + { + "face": "http://i0.hdslb.com/bfs/face/dccb52f3c15ba1bb99aac3c86e9825842cc95295.jpg", + "fans": 2, + "name": "社会你易易", + "official_verify_type": -1, + "uid": "497214639" + }, + { + "face": "https://i1.hdslb.com/bfs/face/1902cc0b07ab4a5de6110f5adb2691cbf7051f2b.jpg", + "fans": 1, + "name": "社会打工不容易", + "official_verify_type": -1, + "uid": "3546742186314202" + }, + { + "face": "https://i0.hdslb.com/bfs/face/19ee1b5975969a47ba085cd1f628d86a479b9950.jpg", + "fans": 0, + "name": "社会交易", + "official_verify_type": -1, + "uid": "3493291412687622" + }, + { + "face": "https://i0.hdslb.com/bfs/face/de6afbda484e114b7cedeb621c3cbbaef7800988.jpg", + "fans": 0, + "name": "不谦易会社恐", + "official_verify_type": -1, + "uid": "1602175830" + }, + { + "face": "http://i0.hdslb.com/bfs/face/member/noface.jpg", + "fans": 8, + "name": "社会易总", + "official_verify_type": -1, + "uid": "155817540" + }, + { + "face": "https://i0.hdslb.com/bfs/face/member/noface.jpg", + "fans": 0, + "name": "社会存在与社会易逝", + "official_verify_type": -1, + "uid": "3546578331634371" + }, + { + "face": "http://i0.hdslb.com/bfs/face/member/noface.jpg", + "fans": 0, + "name": "社会易姐QAQ", + "official_verify_type": -1, + "uid": "1983403996" + }, + { + "face": "http://i1.hdslb.com/bfs/face/510cde8f4e3eb27aa50177d619a4200bb501797b.jpg", + "fans": 0, + "name": "社会易大佬人狠话不多", + "official_verify_type": -1, + "uid": "408471763" + }, + { + "face": "http://i1.hdslb.com/bfs/face/7324adb53362527a1bf5f20141a6ae4307011ea7.jpg", + "fans": 0, + "name": "社会易轩", + "official_verify_type": -1, + "uid": "384672256" + }, + { + "face": "http://i0.hdslb.com/bfs/face/member/noface.jpg", + "fans": 0, + "name": "社会易哥", + "official_verify_type": -1, + "uid": "284984452" + }, + { + "face": "http://i0.hdslb.com/bfs/face/member/noface.jpg", + "fans": 0, + "name": "社会易姐", + "official_verify_type": -1, + "uid": "249112673" + }, + { + "face": "http://i0.hdslb.com/bfs/face/member/noface.jpg", + "fans": 0, + "name": "社会易大佬", + "official_verify_type": -1, + "uid": "167967213" + } + ] + } + ] + } +} +``` + +</details> \ No newline at end of file diff --git a/bb-api-collect/docs/dynamic/banner.md b/bb-api-collect/docs/dynamic/banner.md new file mode 100644 index 0000000000..2df8329e4e --- /dev/null +++ b/bb-api-collect/docs/dynamic/banner.md @@ -0,0 +1,132 @@ +# 首页公告栏 + +## 动态首页公告栏 (新版) + +> https://api.bilibili.com/x/dynamic/feed/dyn/banner + +*请求方法: GET* + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---- | ------ | ---- | +| platform | number | 平台? | 不必要 | 默认为 `1`, 留空无 | +| position | string | 位置? | 不必要 | 默认为 `web动态`, 留空无 | +| web_location | string | `333.1365` | 不必要 | | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | number | 返回值 | 0: 成功 | +| data | object | 数据本体 | | +| message | string | 错误信息 | 成功时为 `0` | +| ttl | number | `1` | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| banners | object[] | 横幅们 | 套了个娃 | + +`data.banners[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| banner_id | number | 横幅 id | 旧版接口无 | +| end_time | number | 结束时间 | UNIX 秒级时间戳 | +| img_url | string | 图片 URL | | +| link | string | 跳转链接 | | +| platform | number | 平台 | 与请求参数对应 | +| position | string | 位置 | 与请求参数对应 | +| start_time | number | 开始时间 | UNIX 秒级时间戳 | +| title | string | 标题 | | +| weight | number | 权重 | | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/dynamic/feed/dyn/banner?platform=1&position=web动态&web_location=333.1365' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "banners": [ + { + "banner_id": 20, + "end_time": 2056204800, + "img_url": "https://i0.hdslb.com/bfs/vc/9c699f2acbcad00197e92c401b835d2c6aba8a55.png", + "link": "https://www.bilibili.com/blackboard/activity-5zJxM3spoS.html", + "platform": 1, + "position": "web动态", + "start_time": 1582862523, + "title": "点击进入", + "weight": 1 + } + ] + }, + "message": "0", + "ttl": 1 +} +``` +</details> + +<!-- Generated by json-apidoc-gen @ 2025-05-01T00:21:48.81113265Z --> + +## 动态首页公告栏 (旧版) + +> https://api.vc.bilibili.com/banner_svr/v1/banner_svr/show + + +*请求方法: GET* + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---- | ------ | ---- | +| platform | number | 平台? | 不必要 | 默认为 `1` | +| position | string | 位置? | 不必要 | 默认为 `web动态` | + +**JSON 回复:** + +与 [动态首页公告栏 (新版)](#动态首页公告栏-新版) 相同, 除了少了个 `data.banners[].banner_id` + +**示例:** + +```shell +curl 'https://api.vc.bilibili.com/banner_svr/v1/banner_svr/show' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "banners": [ + { + "img_url": "https://i0.hdslb.com/bfs/vc/9c699f2acbcad00197e92c401b835d2c6aba8a55.png", + "title": "点击进入", + "link": "https://www.bilibili.com/blackboard/activity-5zJxM3spoS.html", + "platform": 1, + "weight": 1, + "position": "web动态", + "start_time": 1582862523, + "end_time": 2056204800 + } + ] + } +} +``` + +</details> diff --git a/bb-api-collect/docs/dynamic/basicInfo.md b/bb-api-collect/docs/dynamic/basicInfo.md new file mode 100644 index 0000000000..b4b836a304 --- /dev/null +++ b/bb-api-collect/docs/dynamic/basicInfo.md @@ -0,0 +1,1581 @@ +# 动态基本信息 + +## 动态转发列表 + +> https://api.vc.bilibili.com/dynamic_repost/v1/dynamic_repost/repost_detail + +请求方式:GET + +==Attention: 转发列表总计超过550部分继续获取可能被限制。== + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| :--------: | :--: | :----: | :----: | :--: | +| dynamic_id | id | 动态id | 必要 | | +| offset | - | - | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | -------- | +| code | num | 返回值 | 0:成功 | +| data | obj | 信息本体 | | +| message | str | 错误信息 | 默认为空 | +| msg | num | 空 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------------- | ------------ | +| has_more | bool | 是否还有下一页 | 每页最多20条 | +| total | int | 总计包含 | 不超过20条 | +| _gt_ | num | 0 | 作用尚不明确 | + +`data`中的`items`对象: + +由于参数过多,这里不一一列举,请自行参阅其他文件理解。 + +**示例:** + +获取`哔哩哔哩弹幕网`的动态id为`669016644742283288`动态 + +```shell +curl -G 'https://api.vc.bilibili.com/dynamic_repost/v1/dynamic_repost/repost_detail' \ +--data-urlencode 'dynamic_id=669016644742283288' +``` + +<details> +<summary>查看响应示例</summary> + +```json +{ + "code": 0, + "msg": "", + "message": "", + "data": { + "has_more": 0, + "total": 3, + "items": [ + { + "desc": { + "uid": 478909651, + "type": 1, + "rid": 669023160171702063, + "acl": 0, + "view": 0, + "repost": 0, + "like": 0, + "is_liked": 0, + "dynamic_id": 669023160201379864, + "timestamp": 1654607493, + "pre_dy_id": 669016644742283288, + "orig_dy_id": 669007814298959974, + "orig_type": 2, + "user_profile": { + "info": { + "uid": 478909651, + "uname": "-牛马之玉", + "face": "http://i0.hdslb.com/bfs/face/member/noface.jpg", + "face_nft": 0 + }, + "card": { + "official_verify": { + "type": -1, + "desc": "" + } + }, + "vip": { + "vipType": 0, + "vipDueDate": 0, + "vipStatus": 0, + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "rank": "10000", + "sign": "", + "level_info": { + "current_level": 2 + } + }, + "uid_type": 1, + "stype": 0, + "r_type": 1, + "inner_id": 0, + "status": 1, + "dynamic_id_str": "669023160201379864", + "pre_dy_id_str": "669016644742283288", + "orig_dy_id_str": "669007814298959974", + "rid_str": "669023160171702063", + "origin": { + "uid": 392836434, + "type": 2, + "rid": 196658860, + "acl": 1024, + "view": 46111, + "repost": 1446, + "like": 0, + "dynamic_id": 669007814298959974, + "timestamp": 1654603920, + "pre_dy_id": 0, + "orig_dy_id": 0, + "uid_type": 1, + "stype": 0, + "r_type": 0, + "inner_id": 0, + "status": 1, + "dynamic_id_str": "669007814298959974", + "pre_dy_id_str": "0", + "orig_dy_id_str": "0", + "rid_str": "196658860" + }, + "previous": { + "uid": 9617619, + "type": 1, + "rid": 669016644698939384, + "acl": 1024, + "view": 1381, + "repost": 3, + "like": 0, + "dynamic_id": 669016644742283288, + "timestamp": 1654605976, + "pre_dy_id": 669007814298959974, + "orig_dy_id": 669007814298959974, + "uid_type": 1, + "stype": 0, + "r_type": 1, + "inner_id": 0, + "status": 1, + "dynamic_id_str": "669016644742283288", + "pre_dy_id_str": "669007814298959974", + "orig_dy_id_str": "669007814298959974", + "rid_str": "669016644698939384" + } + }, + "card": "{ \"user\": { \"uid\": 478909651, \"uname\": \"-牛马之玉\", \"face\": \"http:\\/\\/i0.hdslb.com\\/bfs\\/face\\/member\\/noface.jpg\" }, \"item\": { \"rp_id\": 669023160171702063, \"uid\": 478909651, \"content\": \"\\/\\/@哔哩哔哩直播:6月8日KPL首届夏季赛火热开赛,明星主播花式解说!开赛首日直播间礼品...\", \"ctrl\": \"[{\\\"location\\\":2,\\\"length\\\":7,\\\"data\\\":\\\"9617619\\\",\\\"type\\\":1}]\", \"orig_dy_id\": 669007814298959974, \"pre_dy_id\": 669016644742283288, \"timestamp\": 0, \"at_uids\": [ 9617619 ], \"orig_type\": 2 }, \"origin\": \"{\\\"item\\\":{\\\"at_control\\\":\\\"[{\\\\\\\"location\\\\\\\":0,\\\\\\\"length\\\\\\\":4,\\\\\\\"data\\\\\\\":\\\\\\\"4\\\\\\\",\\\\\\\"type\\\\\\\":2}]\\\",\\\"category\\\":\\\"daily\\\",\\\"description\\\":\\\"互动抽奖 【上B站,看KPL】\\\\r\\\\nKPL首届夏季赛即将来袭,6月8日15:00B站55官方直播间等你来看!你最期待哪场对决呢?更有多位明星主播陪你观赛,趣味吐槽花式解说开赛首日~\\\\r\\\\n\\\\r\\\\n55直播间马超-无双飞将皮肤助力金撒不停,赛事全程天选好礼每局掉落,观赛还能领取游戏内道具!APP端参与直播间【热议】讨论,更有机会获超多奖励。\\\\r\\\\n\\\\r\\\\nKPL赛事征稿开赛日同步上线,带#KPL激励计划#话题投稿,瓜分30万奖金~\\\\r\\\\n战火将燃,谁将勇夺开门红,让我们拭目以待! [打call]\\\\n\\\\n直播间TP:https:\\\\\\/\\\\\\/live.bilibili.com\\\\\\/55 \\\\n赛事预测:https:\\\\\\/\\\\\\/www.bilibili.com\\\\\\/v\\\\\\/game\\\\\\/match\\\\\\/competition?spm_id_from=444.42.0.0 \\\\n更多比赛:https:\\\\\\/\\\\\\/www.bilibili.com\\\\\\/v\\\\\\/game\\\\\\/match\\\\\\/schedule?mid=0&gid=0&tid=0&time=1639785600000&spm_id_from=444.42.0.0\\\",\\\"id\\\":196658860,\\\"is_fav\\\":0,\\\"pictures\\\":[{\\\"img_height\\\":6758,\\\"img_size\\\":4693.3251953125,\\\"img_src\\\":\\\"https:\\\\\\/\\\\\\/i0.hdslb.com\\\\\\/bfs\\\\\\/album\\\\\\/d4fd33fe00c80938daf6f14641f15901bc4a0d17.jpg\\\",\\\"img_tags\\\":null,\\\"img_width\\\":1080}],\\\"pictures_count\\\":1,\\\"reply\\\":128,\\\"role\\\":[],\\\"settings\\\":{\\\"copy_forbidden\\\":\\\"0\\\"},\\\"source\\\":[],\\\"title\\\":\\\"\\\",\\\"upload_time\\\":1654603920},\\\"user\\\":{\\\"head_url\\\":\\\"http:\\\\\\/\\\\\\/i0.hdslb.com\\\\\\/bfs\\\\\\/face\\\\\\/50de7906e50260c0e596d54ca51687e58ed7a9ba.jpg\\\",\\\"name\\\":\\\"哔哩哔哩王者荣耀赛事\\\",\\\"uid\\\":392836434,\\\"vip\\\":{\\\"avatar_subscript\\\":1,\\\"due_date\\\":1661097600000,\\\"label\\\":{\\\"label_theme\\\":\\\"annual_vip\\\",\\\"path\\\":\\\"\\\",\\\"text\\\":\\\"年度大会员\\\"},\\\"nickname_color\\\":\\\"#FB7299\\\",\\\"status\\\":1,\\\"theme_type\\\":0,\\\"type\\\":2,\\\"vip_pay_type\\\":0}}}\", \"origin_extension\": { \"lott\": \"{\\\"lottery_id\\\":96074}\" }, \"origin_extend_json\": \"{\\\"ctrl\\\":[{\\\"data\\\":\\\"4\\\",\\\"length\\\":4,\\\"location\\\":0,\\\"type\\\":2}],\\\"from\\\":{\\\"emoji_type\\\":1,\\\"from\\\":\\\"create.dynamic.web\\\",\\\"verify\\\":{\\\"aegis_enable\\\":true,\\\"asw\\\":{},\\\"cc\\\":{},\\\"csw\\\":{},\\\"dc\\\":{},\\\"gc\\\":{},\\\"ra\\\":{},\\\"sp\\\":{},\\\"sw\\\":{},\\\"ur\\\":{},\\\"verify_first\\\":true}},\\\"like_icon\\\":{\\\"action\\\":\\\"\\\",\\\"action_url\\\":\\\"\\\",\\\"end\\\":\\\"\\\",\\\"end_url\\\":\\\"\\\",\\\"start\\\":\\\"\\\",\\\"start_url\\\":\\\"\\\"},\\\"lott\\\":{\\\"lottery_id\\\":96074},\\\"topic\\\":{\\\"is_attach_topic\\\":1}}\", \"origin_user\": { \"info\": { \"uid\": 392836434, \"uname\": \"哔哩哔哩王者荣耀赛事\", \"face\": \"http:\\/\\/i0.hdslb.com\\/bfs\\/face\\/50de7906e50260c0e596d54ca51687e58ed7a9ba.jpg\", \"face_nft\": 0 }, \"card\": { \"official_verify\": { \"type\": 1, \"desc\": \"哔哩哔哩王者荣耀赛事官方帐号\" } }, \"vip\": { \"vipType\": 2, \"vipDueDate\": 1661097600000, \"vipStatus\": 1, \"themeType\": 0, \"label\": { \"path\": \"\", \"text\": \"年度大会员\", \"label_theme\": \"annual_vip\", \"text_color\": \"#FFFFFF\", \"bg_style\": 1, \"bg_color\": \"#FB7299\", \"border_color\": \"\" }, \"avatar_subscript\": 1, \"nickname_color\": \"#FB7299\", \"role\": 3, \"avatar_subscript_url\": \"http:\\/\\/i0.hdslb.com\\/bfs\\/vip\\/icon_Certification_big_member_22_3x.png\" }, \"pendant\": { \"pid\": 0, \"name\": \"\", \"image\": \"\", \"expire\": 0, \"image_enhance\": \"\", \"image_enhance_frame\": \"\" }, \"rank\": \"10000\", \"sign\": \"哔哩哔哩王者荣耀赛事官方账号\", \"level_info\": { \"current_level\": 6 } } }", + "extend_json": "{\"\":{\"at_mids\":[{\"at_type\":2,\"mid_list\":[9617619]}],\"content\":\"\\/\\/@哔哩哔哩直播:6月8日KPL首届夏季赛火热开赛,明星主播花式解说!开赛首日直播间礼品...\",\"data_type\":2,\"need_send_msg\":true,\"publisher\":478909651},\"ctrl\":[{\"data\":\"9617619\",\"length\":7,\"location\":2,\"type\":1}],\"from\":{\"emoji_type\":1,\"from\":\"create.fast_repost\",\"verify\":{\"aegis_enable\":true,\"asw\":{},\"cc\":{},\"csw\":{},\"dc\":{},\"gc\":{},\"ra\":{},\"sp\":{},\"sw\":{},\"ur\":{}}},\"like_icon\":{\"action\":\"\",\"action_url\":\"\",\"end\":\"\",\"end_url\":\"\",\"start\":\"\",\"start_url\":\"\"}}", + "display": { + "origin": { + "emoji_info": { + "emoji_details": [ + { + "emoji_name": "[打call]", + "id": 510, + "package_id": 1, + "state": 0, + "type": 1, + "attr": 0, + "text": "[打call]", + "url": "http://i0.hdslb.com/bfs/emote/431432c43da3ee5aab5b0e4f8931953e649e9975.png", + "meta": { + "size": 1 + }, + "mtime": 1648834168 + } + ] + }, + "relation": { + "status": 1, + "is_follow": 0, + "is_followed": 0 + } + }, + "relation": { + "status": 1, + "is_follow": 0, + "is_followed": 0 + } + } + }, + { + "desc": { + "uid": 37906788, + "type": 1, + "rid": 669022472968542526, + "acl": 0, + "view": 0, + "repost": 0, + "like": 0, + "is_liked": 0, + "dynamic_id": 669022473022341136, + "timestamp": 1654607333, + "pre_dy_id": 669016644742283288, + "orig_dy_id": 669007814298959974, + "orig_type": 2, + "user_profile": { + "info": { + "uid": 37906788, + "uname": "整天就想吃桃子", + "face": "http://i0.hdslb.com/bfs/face/388f29bb0e426d625378b99eec690775467ebb00.jpg", + "face_nft": 0 + }, + "card": { + "official_verify": { + "type": -1, + "desc": "" + } + }, + "vip": { + "vipType": 2, + "vipDueDate": 1712073600000, + "vipStatus": 1, + "themeType": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299", + "role": 3, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "rank": "10000", + "sign": "", + "level_info": { + "current_level": 5 + } + }, + "uid_type": 1, + "stype": 0, + "r_type": 1, + "inner_id": 0, + "status": 1, + "dynamic_id_str": "669022473022341136", + "pre_dy_id_str": "669016644742283288", + "orig_dy_id_str": "669007814298959974", + "rid_str": "669022472968542526", + "origin": { + "uid": 392836434, + "type": 2, + "rid": 196658860, + "acl": 1024, + "view": 46111, + "repost": 1446, + "like": 0, + "dynamic_id": 669007814298959974, + "timestamp": 1654603920, + "pre_dy_id": 0, + "orig_dy_id": 0, + "uid_type": 1, + "stype": 0, + "r_type": 0, + "inner_id": 0, + "status": 1, + "dynamic_id_str": "669007814298959974", + "pre_dy_id_str": "0", + "orig_dy_id_str": "0", + "rid_str": "196658860" + }, + "previous": { + "uid": 9617619, + "type": 1, + "rid": 669016644698939384, + "acl": 1024, + "view": 1381, + "repost": 3, + "like": 0, + "dynamic_id": 669016644742283288, + "timestamp": 1654605976, + "pre_dy_id": 669007814298959974, + "orig_dy_id": 669007814298959974, + "uid_type": 1, + "stype": 0, + "r_type": 1, + "inner_id": 0, + "status": 1, + "dynamic_id_str": "669016644742283288", + "pre_dy_id_str": "669007814298959974", + "orig_dy_id_str": "669007814298959974", + "rid_str": "669016644698939384" + } + }, + "card": "{ \"user\": { \"uid\": 37906788, \"uname\": \"整天就想吃桃子\", \"face\": \"http:\\/\\/i0.hdslb.com\\/bfs\\/face\\/388f29bb0e426d625378b99eec690775467ebb00.jpg\" }, \"item\": { \"rp_id\": 669022472968542526, \"uid\": 37906788, \"content\": \"\\/\\/@哔哩哔哩直播:6月8日KPL首届夏季赛火热开赛,明星主播花式解说!开赛首日直播间礼品不定时掉...\", \"ctrl\": \"[{\\\"location\\\":2,\\\"length\\\":7,\\\"data\\\":\\\"9617619\\\",\\\"type\\\":1}]\", \"orig_dy_id\": 669007814298959974, \"pre_dy_id\": 669016644742283288, \"timestamp\": 0, \"at_uids\": [ 9617619 ], \"orig_type\": 2 }, \"origin\": \"{\\\"item\\\":{\\\"at_control\\\":\\\"[{\\\\\\\"location\\\\\\\":0,\\\\\\\"length\\\\\\\":4,\\\\\\\"data\\\\\\\":\\\\\\\"4\\\\\\\",\\\\\\\"type\\\\\\\":2}]\\\",\\\"category\\\":\\\"daily\\\",\\\"description\\\":\\\"互动抽奖 【上B站,看KPL】\\\\r\\\\nKPL首届夏季赛即将来袭,6月8日15:00B站55官方直播间等你来看!你最期待哪场对决呢?更有多位明星主播陪你观赛,趣味吐槽花式解说开赛首日~\\\\r\\\\n\\\\r\\\\n55直播间马超-无双飞将皮肤助力金撒不停,赛事全程天选好礼每局掉落,观赛还能领取游戏内道具!APP端参与直播间【热议】讨论,更有机会获超多奖励。\\\\r\\\\n\\\\r\\\\nKPL赛事征稿开赛日同步上线,带#KPL激励计划#话题投稿,瓜分30万奖金~\\\\r\\\\n战火将燃,谁将勇夺开门红,让我们拭目以待! [打call]\\\\n\\\\n直播间TP:https:\\\\\\/\\\\\\/live.bilibili.com\\\\\\/55 \\\\n赛事预测:https:\\\\\\/\\\\\\/www.bilibili.com\\\\\\/v\\\\\\/game\\\\\\/match\\\\\\/competition?spm_id_from=444.42.0.0 \\\\n更多比赛:https:\\\\\\/\\\\\\/www.bilibili.com\\\\\\/v\\\\\\/game\\\\\\/match\\\\\\/schedule?mid=0&gid=0&tid=0&time=1639785600000&spm_id_from=444.42.0.0\\\",\\\"id\\\":196658860,\\\"is_fav\\\":0,\\\"pictures\\\":[{\\\"img_height\\\":6758,\\\"img_size\\\":4693.3251953125,\\\"img_src\\\":\\\"https:\\\\\\/\\\\\\/i0.hdslb.com\\\\\\/bfs\\\\\\/album\\\\\\/d4fd33fe00c80938daf6f14641f15901bc4a0d17.jpg\\\",\\\"img_tags\\\":null,\\\"img_width\\\":1080}],\\\"pictures_count\\\":1,\\\"reply\\\":128,\\\"role\\\":[],\\\"settings\\\":{\\\"copy_forbidden\\\":\\\"0\\\"},\\\"source\\\":[],\\\"title\\\":\\\"\\\",\\\"upload_time\\\":1654603920},\\\"user\\\":{\\\"head_url\\\":\\\"http:\\\\\\/\\\\\\/i0.hdslb.com\\\\\\/bfs\\\\\\/face\\\\\\/50de7906e50260c0e596d54ca51687e58ed7a9ba.jpg\\\",\\\"name\\\":\\\"哔哩哔哩王者荣耀赛事\\\",\\\"uid\\\":392836434,\\\"vip\\\":{\\\"avatar_subscript\\\":1,\\\"due_date\\\":1661097600000,\\\"label\\\":{\\\"label_theme\\\":\\\"annual_vip\\\",\\\"path\\\":\\\"\\\",\\\"text\\\":\\\"年度大会员\\\"},\\\"nickname_color\\\":\\\"#FB7299\\\",\\\"status\\\":1,\\\"theme_type\\\":0,\\\"type\\\":2,\\\"vip_pay_type\\\":0}}}\", \"origin_extension\": { \"lott\": \"{\\\"lottery_id\\\":96074}\" }, \"origin_extend_json\": \"{\\\"ctrl\\\":[{\\\"data\\\":\\\"4\\\",\\\"length\\\":4,\\\"location\\\":0,\\\"type\\\":2}],\\\"from\\\":{\\\"emoji_type\\\":1,\\\"from\\\":\\\"create.dynamic.web\\\",\\\"verify\\\":{\\\"aegis_enable\\\":true,\\\"asw\\\":{},\\\"cc\\\":{},\\\"csw\\\":{},\\\"dc\\\":{},\\\"gc\\\":{},\\\"ra\\\":{},\\\"sp\\\":{},\\\"sw\\\":{},\\\"ur\\\":{},\\\"verify_first\\\":true}},\\\"like_icon\\\":{\\\"action\\\":\\\"\\\",\\\"action_url\\\":\\\"\\\",\\\"end\\\":\\\"\\\",\\\"end_url\\\":\\\"\\\",\\\"start\\\":\\\"\\\",\\\"start_url\\\":\\\"\\\"},\\\"lott\\\":{\\\"lottery_id\\\":96074},\\\"topic\\\":{\\\"is_attach_topic\\\":1}}\", \"origin_user\": { \"info\": { \"uid\": 392836434, \"uname\": \"哔哩哔哩王者荣耀赛事\", \"face\": \"http:\\/\\/i0.hdslb.com\\/bfs\\/face\\/50de7906e50260c0e596d54ca51687e58ed7a9ba.jpg\", \"face_nft\": 0 }, \"card\": { \"official_verify\": { \"type\": 1, \"desc\": \"哔哩哔哩王者荣耀赛事官方帐号\" } }, \"vip\": { \"vipType\": 2, \"vipDueDate\": 1661097600000, \"vipStatus\": 1, \"themeType\": 0, \"label\": { \"path\": \"\", \"text\": \"年度大会员\", \"label_theme\": \"annual_vip\", \"text_color\": \"#FFFFFF\", \"bg_style\": 1, \"bg_color\": \"#FB7299\", \"border_color\": \"\" }, \"avatar_subscript\": 1, \"nickname_color\": \"#FB7299\", \"role\": 3, \"avatar_subscript_url\": \"http:\\/\\/i0.hdslb.com\\/bfs\\/vip\\/icon_Certification_big_member_22_3x.png\" }, \"pendant\": { \"pid\": 0, \"name\": \"\", \"image\": \"\", \"expire\": 0, \"image_enhance\": \"\", \"image_enhance_frame\": \"\" }, \"rank\": \"10000\", \"sign\": \"哔哩哔哩王者荣耀赛事官方账号\", \"level_info\": { \"current_level\": 6 } } }", + "extend_json": "{\"\":{\"at_mids\":[{\"at_type\":2,\"mid_list\":[9617619]}],\"content\":\"\\/\\/@哔哩哔哩直播:6月8日KPL首届夏季赛火热开赛,明星主播花式解说!开赛首日直播间礼品不定时掉...\",\"data_type\":2,\"need_send_msg\":true,\"publisher\":37906788},\"ctrl\":[{\"data\":\"9617619\",\"length\":7,\"location\":2,\"type\":1}],\"from\":{\"emoji_type\":1,\"from\":\"create.fast_repost\",\"verify\":{\"aegis_enable\":true,\"asw\":{},\"cc\":{},\"csw\":{},\"dc\":{},\"gc\":{},\"ra\":{},\"sp\":{},\"sw\":{},\"ur\":{}}},\"like_icon\":{\"action\":\"\",\"action_url\":\"\",\"end\":\"\",\"end_url\":\"\",\"start\":\"\",\"start_url\":\"\"}}", + "display": { + "origin": { + "emoji_info": { + "emoji_details": [ + { + "emoji_name": "[打call]", + "id": 510, + "package_id": 1, + "state": 0, + "type": 1, + "attr": 0, + "text": "[打call]", + "url": "http://i0.hdslb.com/bfs/emote/431432c43da3ee5aab5b0e4f8931953e649e9975.png", + "meta": { + "size": 1 + }, + "mtime": 1648834168 + } + ] + }, + "relation": { + "status": 1, + "is_follow": 0, + "is_followed": 0 + } + }, + "relation": { + "status": 1, + "is_follow": 0, + "is_followed": 0 + } + } + }, + { + "desc": { + "uid": 586724890, + "type": 1, + "rid": 669019754258423810, + "acl": 0, + "view": 0, + "repost": 0, + "like": 0, + "is_liked": 0, + "dynamic_id": 669019754292314181, + "timestamp": 1654606700, + "pre_dy_id": 669016644742283288, + "orig_dy_id": 669007814298959974, + "orig_type": 2, + "user_profile": { + "info": { + "uid": 586724890, + "uname": "雪羽枭白", + "face": "http://i1.hdslb.com/bfs/face/a270f0df9a621d6d7f05a0ff94c64bad5fcb6964.jpg", + "face_nft": 0 + }, + "card": { + "official_verify": { + "type": -1, + "desc": "" + } + }, + "vip": { + "vipType": 0, + "vipDueDate": 0, + "vipStatus": 0, + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "rank": "10000", + "sign": "芜湖,起飞~", + "level_info": { + "current_level": 4 + } + }, + "uid_type": 1, + "stype": 0, + "r_type": 1, + "inner_id": 0, + "status": 1, + "dynamic_id_str": "669019754292314181", + "pre_dy_id_str": "669016644742283288", + "orig_dy_id_str": "669007814298959974", + "rid_str": "669019754258423810", + "origin": { + "uid": 392836434, + "type": 2, + "rid": 196658860, + "acl": 1024, + "view": 46111, + "repost": 1446, + "like": 0, + "dynamic_id": 669007814298959974, + "timestamp": 1654603920, + "pre_dy_id": 0, + "orig_dy_id": 0, + "uid_type": 1, + "stype": 0, + "r_type": 0, + "inner_id": 0, + "status": 1, + "dynamic_id_str": "669007814298959974", + "pre_dy_id_str": "0", + "orig_dy_id_str": "0", + "rid_str": "196658860" + }, + "previous": { + "uid": 9617619, + "type": 1, + "rid": 669016644698939384, + "acl": 1024, + "view": 1381, + "repost": 3, + "like": 0, + "dynamic_id": 669016644742283288, + "timestamp": 1654605976, + "pre_dy_id": 669007814298959974, + "orig_dy_id": 669007814298959974, + "uid_type": 1, + "stype": 0, + "r_type": 1, + "inner_id": 0, + "status": 1, + "dynamic_id_str": "669016644742283288", + "pre_dy_id_str": "669007814298959974", + "orig_dy_id_str": "669007814298959974", + "rid_str": "669016644698939384" + } + }, + "card": "{ \"user\": { \"uid\": 586724890, \"uname\": \"雪羽枭白\", \"face\": \"http:\\/\\/i1.hdslb.com\\/bfs\\/face\\/a270f0df9a621d6d7f05a0ff94c64bad5fcb6964.jpg\" }, \"item\": { \"rp_id\": 669019754258423810, \"uid\": 586724890, \"content\": \"\\/\\/@哔哩哔哩直播:6月8日KPL首届夏季赛火热开赛,明星主播花式解说!开赛首日直播间礼品不定时掉落,记得好好蹲守哦~明天15点,2022KPL夏季赛我们不见不散>>>网页链接\", \"ctrl\": \"[{\\\"location\\\":2,\\\"length\\\":7,\\\"data\\\":\\\"9617619\\\",\\\"type\\\":1}]\", \"orig_dy_id\": 669007814298959974, \"pre_dy_id\": 669016644742283288, \"timestamp\": 0, \"at_uids\": [ 9617619 ], \"orig_type\": 2 }, \"origin\": \"{\\\"item\\\":{\\\"at_control\\\":\\\"[{\\\\\\\"location\\\\\\\":0,\\\\\\\"length\\\\\\\":4,\\\\\\\"data\\\\\\\":\\\\\\\"4\\\\\\\",\\\\\\\"type\\\\\\\":2}]\\\",\\\"category\\\":\\\"daily\\\",\\\"description\\\":\\\"互动抽奖 【上B站,看KPL】\\\\r\\\\nKPL首届夏季赛即将来袭,6月8日15:00B站55官方直播间等你来看!你最期待哪场对决呢?更有多位明星主播陪你观赛,趣味吐槽花式解说开赛首日~\\\\r\\\\n\\\\r\\\\n55直播间马超-无双飞将皮肤助力金撒不停,赛事全程天选好礼每局掉落,观赛还能领取游戏内道具!APP端参与直播间【热议】讨论,更有机会获超多奖励。\\\\r\\\\n\\\\r\\\\nKPL赛事征稿开赛日同步上线,带#KPL激励计划#话题投稿,瓜分30万奖金~\\\\r\\\\n战火将燃,谁将勇夺开门红,让我们拭目以待! [打call]\\\\n\\\\n直播间TP:https:\\\\\\/\\\\\\/live.bilibili.com\\\\\\/55 \\\\n赛事预测:https:\\\\\\/\\\\\\/www.bilibili.com\\\\\\/v\\\\\\/game\\\\\\/match\\\\\\/competition?spm_id_from=444.42.0.0 \\\\n更多比赛:https:\\\\\\/\\\\\\/www.bilibili.com\\\\\\/v\\\\\\/game\\\\\\/match\\\\\\/schedule?mid=0&gid=0&tid=0&time=1639785600000&spm_id_from=444.42.0.0\\\",\\\"id\\\":196658860,\\\"is_fav\\\":0,\\\"pictures\\\":[{\\\"img_height\\\":6758,\\\"img_size\\\":4693.3251953125,\\\"img_src\\\":\\\"https:\\\\\\/\\\\\\/i0.hdslb.com\\\\\\/bfs\\\\\\/album\\\\\\/d4fd33fe00c80938daf6f14641f15901bc4a0d17.jpg\\\",\\\"img_tags\\\":null,\\\"img_width\\\":1080}],\\\"pictures_count\\\":1,\\\"reply\\\":128,\\\"role\\\":[],\\\"settings\\\":{\\\"copy_forbidden\\\":\\\"0\\\"},\\\"source\\\":[],\\\"title\\\":\\\"\\\",\\\"upload_time\\\":1654603920},\\\"user\\\":{\\\"head_url\\\":\\\"http:\\\\\\/\\\\\\/i0.hdslb.com\\\\\\/bfs\\\\\\/face\\\\\\/50de7906e50260c0e596d54ca51687e58ed7a9ba.jpg\\\",\\\"name\\\":\\\"哔哩哔哩王者荣耀赛事\\\",\\\"uid\\\":392836434,\\\"vip\\\":{\\\"avatar_subscript\\\":1,\\\"due_date\\\":1661097600000,\\\"label\\\":{\\\"label_theme\\\":\\\"annual_vip\\\",\\\"path\\\":\\\"\\\",\\\"text\\\":\\\"年度大会员\\\"},\\\"nickname_color\\\":\\\"#FB7299\\\",\\\"status\\\":1,\\\"theme_type\\\":0,\\\"type\\\":2,\\\"vip_pay_type\\\":0}}}\", \"origin_extension\": { \"lott\": \"{\\\"lottery_id\\\":96074}\" }, \"origin_extend_json\": \"{\\\"ctrl\\\":[{\\\"data\\\":\\\"4\\\",\\\"length\\\":4,\\\"location\\\":0,\\\"type\\\":2}],\\\"from\\\":{\\\"emoji_type\\\":1,\\\"from\\\":\\\"create.dynamic.web\\\",\\\"verify\\\":{\\\"aegis_enable\\\":true,\\\"asw\\\":{},\\\"cc\\\":{},\\\"csw\\\":{},\\\"dc\\\":{},\\\"gc\\\":{},\\\"ra\\\":{},\\\"sp\\\":{},\\\"sw\\\":{},\\\"ur\\\":{},\\\"verify_first\\\":true}},\\\"like_icon\\\":{\\\"action\\\":\\\"\\\",\\\"action_url\\\":\\\"\\\",\\\"end\\\":\\\"\\\",\\\"end_url\\\":\\\"\\\",\\\"start\\\":\\\"\\\",\\\"start_url\\\":\\\"\\\"},\\\"lott\\\":{\\\"lottery_id\\\":96074},\\\"topic\\\":{\\\"is_attach_topic\\\":1}}\", \"origin_user\": { \"info\": { \"uid\": 392836434, \"uname\": \"哔哩哔哩王者荣耀赛事\", \"face\": \"http:\\/\\/i0.hdslb.com\\/bfs\\/face\\/50de7906e50260c0e596d54ca51687e58ed7a9ba.jpg\", \"face_nft\": 0 }, \"card\": { \"official_verify\": { \"type\": 1, \"desc\": \"哔哩哔哩王者荣耀赛事官方帐号\" } }, \"vip\": { \"vipType\": 2, \"vipDueDate\": 1661097600000, \"vipStatus\": 1, \"themeType\": 0, \"label\": { \"path\": \"\", \"text\": \"年度大会员\", \"label_theme\": \"annual_vip\", \"text_color\": \"#FFFFFF\", \"bg_style\": 1, \"bg_color\": \"#FB7299\", \"border_color\": \"\" }, \"avatar_subscript\": 1, \"nickname_color\": \"#FB7299\", \"role\": 3, \"avatar_subscript_url\": \"http:\\/\\/i0.hdslb.com\\/bfs\\/vip\\/icon_Certification_big_member_22_3x.png\" }, \"pendant\": { \"pid\": 0, \"name\": \"\", \"image\": \"\", \"expire\": 0, \"image_enhance\": \"\", \"image_enhance_frame\": \"\" }, \"rank\": \"10000\", \"sign\": \"哔哩哔哩王者荣耀赛事官方账号\", \"level_info\": { \"current_level\": 6 } } }", + "extend_json": "{\"\":{\"at_mids\":[{\"at_type\":2,\"mid_list\":[9617619]}],\"content\":\"\\/\\/@哔哩哔哩直播:6月8日KPL首届夏季赛火热开赛,明星主播花式解说!开赛首日直播间礼品不定时掉落,记得好好蹲守哦~明天15点,2022KPL夏季赛我们不见不散>>>网页链接\",\"data_type\":2,\"need_send_msg\":true,\"publisher\":586724890},\"ctrl\":[{\"data\":\"9617619\",\"length\":7,\"location\":2,\"type\":1}],\"from\":{\"emoji_type\":1,\"from\":\"create.dynamic.web\",\"verify\":{\"aegis_enable\":true,\"asw\":{},\"cc\":{},\"csw\":{},\"dc\":{},\"gc\":{},\"ra\":{},\"sp\":{},\"sw\":{},\"ur\":{}}},\"like_icon\":{\"action\":\"\",\"action_url\":\"\",\"end\":\"\",\"end_url\":\"\",\"start\":\"\",\"start_url\":\"\"}}", + "display": { + "origin": { + "emoji_info": { + "emoji_details": [ + { + "emoji_name": "[打call]", + "id": 510, + "package_id": 1, + "state": 0, + "type": 1, + "attr": 0, + "text": "[打call]", + "url": "http://i0.hdslb.com/bfs/emote/431432c43da3ee5aab5b0e4f8931953e649e9975.png", + "meta": { + "size": 1 + }, + "mtime": 1648834168 + } + ] + }, + "relation": { + "status": 1, + "is_follow": 0, + "is_followed": 0 + } + }, + "relation": { + "status": 1, + "is_follow": 0, + "is_followed": 0 + } + } + } + ], + "_gt_": 0 + } +} +``` +</details> + + +## 动态点赞列表 + +> https://api.vc.bilibili.com/dynamic_like/v1/dynamic_like/spec_item_likes + +请求方式:GET + +==Attention: 点赞列表总计超过25K部分继续获取可能被限制。== + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----------- | ---- | ------ | ------- | ---- | +|dynamic_id|int64 | 动态id | 必须 | | +|pn|int64 | 页码 | 非必须 | | +|ps|int64 | 每页数量 | 非必须 |该值不得大于20 | + +**json回复:** +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | -------- | +| code | num | 返回值 | 0:成功 | +| data | obj | 信息本体 | | +| message | str | 错误信息 | 默认为空 | +| msg | num | 空 | | + +`data`对象: + +| 字段 | 类型 | 用途 | 备注 | +| -------- | ---- | -------------- | ------------ | +|item_likes|list |点赞信息列表主体 | | +| has_more | bool | 是否还有下一页 | 每页最多20条 | +| total_count | int | 总计点赞数 | | +| _gt_ | num | 0 | 作用尚不明确 | + +`data`中的`item_likes`对象: + +由于参数过多,这里不一一列举,请自行参阅其他文件理解。 + +**示例:** + +获取`哔哩哔哩弹幕网`的动态id为`669016644742283288`动态 +```shell +curl -G 'https://api.vc.bilibili.com/dynamic_like/v1/dynamic_like/spec_item_likes' \ +--data-urlencode 'dynamic_id=669016644742283288' +``` + +<details> +<summary>查看响应示例</summary> + +```json +{ + "code": 0, + "msg": "", + "message": "", + "data": { + "item_likes": [ + { + "uid": 660169578, + "time": 1654946013, + "face_url": "http://i0.hdslb.com/bfs/face/346ce28e99cc0a7d9cc05b0c0951957445cbcb61.jpg", + "uname": "空蓝奇观", + "user_info": { + "uid": 660169578, + "uname": "空蓝奇观", + "face": "http://i0.hdslb.com/bfs/face/346ce28e99cc0a7d9cc05b0c0951957445cbcb61.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1656604800000, + "vipStatus": 1, + "themeType": 0, + "label": { + "path": "", + "text": "大会员", + "label_theme": "vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "nickname_color": "", + "role": 1, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "sign": "。。。", + "level_info": { + "current_level": 4 + } + }, + "attend": 0 + }, + { + "uid": 522318130, + "time": 1654901839, + "face_url": "http://i1.hdslb.com/bfs/face/3159660d82bf0ffc878265cd11f7bb55122848a8.jpg", + "uname": "114514号饼干机器人", + "user_info": { + "uid": 522318130, + "uname": "114514号饼干机器人", + "face": "http://i1.hdslb.com/bfs/face/3159660d82bf0ffc878265cd11f7bb55122848a8.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1655740800000, + "vipStatus": 1, + "themeType": 0, + "label": { + "path": "", + "text": "大会员", + "label_theme": "vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "nickname_color": "", + "role": 1, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "sign": "", + "level_info": { + "current_level": 4 + } + }, + "attend": 0 + }, + { + "uid": 473098535, + "time": 1654874055, + "face_url": "http://i2.hdslb.com/bfs/face/ae37c4c8a7512322186eaf1c1cb170362c604215.jpg", + "uname": "花式送人头的感觉", + "user_info": { + "uid": 473098535, + "uname": "花式送人头的感觉", + "face": "http://i2.hdslb.com/bfs/face/ae37c4c8a7512322186eaf1c1cb170362c604215.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1626451200000, + "vipStatus": 0, + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 32446, + "name": "EDG战队", + "image": "http://i2.hdslb.com/bfs/garb/item/422c8bd354989845bd9ed64bd00cfa1048e92580.png", + "expire": 0, + "image_enhance": "http://i2.hdslb.com/bfs/garb/item/422c8bd354989845bd9ed64bd00cfa1048e92580.png", + "image_enhance_frame": "" + }, + "sign": "", + "level_info": { + "current_level": 4 + } + }, + "attend": 0 + }, + { + "uid": 297957406, + "time": 1654870870, + "face_url": "http://i1.hdslb.com/bfs/face/c28b431177fa6faffc4b928b9506a7057f002f73.jpg", + "uname": "冷水ensq", + "user_info": { + "uid": 297957406, + "uname": "冷水ensq", + "face": "http://i1.hdslb.com/bfs/face/c28b431177fa6faffc4b928b9506a7057f002f73.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1657036800000, + "vipStatus": 1, + "themeType": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299", + "role": 3, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "sign": "这个人很神秘,只写了这么点东西", + "level_info": { + "current_level": 5 + } + }, + "attend": 0 + }, + { + "uid": 384080149, + "time": 1654869742, + "face_url": "http://i1.hdslb.com/bfs/face/74efb9ca3fc68679cb3ddbf331ceffc246f13929.jpg", + "uname": "嵇獬", + "user_info": { + "uid": 384080149, + "uname": "嵇獬", + "face": "http://i1.hdslb.com/bfs/face/74efb9ca3fc68679cb3ddbf331ceffc246f13929.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1583942400000, + "vipStatus": 0, + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "sign": "这个人很懒,也不知道写什么\n我会一直做自己", + "level_info": { + "current_level": 5 + } + }, + "attend": 0 + }, + { + "uid": 666484726, + "time": 1654867375, + "face_url": "http://i1.hdslb.com/bfs/face/8e7c02c5d98d8ee52d0643227aed59b4fca1420d.jpg", + "uname": "未未成年累月", + "user_info": { + "uid": 666484726, + "uname": "未未成年累月", + "face": "http://i1.hdslb.com/bfs/face/8e7c02c5d98d8ee52d0643227aed59b4fca1420d.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1626624000000, + "vipStatus": 0, + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "sign": "", + "level_info": { + "current_level": 3 + } + }, + "attend": 0 + }, + { + "uid": 298557818, + "time": 1654865058, + "face_url": "http://i2.hdslb.com/bfs/face/b3bea3c029e4a35788625228a8ffbcec6c00eaea.jpg", + "uname": "爱吃星河的饼干", + "user_info": { + "uid": 298557818, + "uname": "爱吃星河的饼干", + "face": "http://i2.hdslb.com/bfs/face/b3bea3c029e4a35788625228a8ffbcec6c00eaea.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1603209600000, + "vipStatus": 0, + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "sign": "规矩,既是束缚,也是保护。", + "level_info": { + "current_level": 5 + } + }, + "attend": 0 + }, + { + "uid": 431901641, + "time": 1654845296, + "face_url": "http://i2.hdslb.com/bfs/face/88bf1a1c0cbbdf39032fa766e0b2324716b5315e.jpg", + "uname": "水粉墨殇", + "user_info": { + "uid": 431901641, + "uname": "水粉墨殇", + "face": "http://i2.hdslb.com/bfs/face/88bf1a1c0cbbdf39032fa766e0b2324716b5315e.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1655740800000, + "vipStatus": 1, + "themeType": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299", + "role": 3, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png" + }, + "pendant": { + "pid": 5305, + "name": "明日方舟音律系列", + "image": "http://i2.hdslb.com/bfs/garb/item/615a1653281141ddf64cbb98c792ddaee78f7f40.png", + "expire": 0, + "image_enhance": "http://i2.hdslb.com/bfs/garb/item/516ecdf2d495a62f1bac31497c831b711823140c.webp", + "image_enhance_frame": "http://i2.hdslb.com/bfs/garb/item/c0751afbf950373c260254d02768eabf30ff3906.png" + }, + "sign": "", + "level_info": { + "current_level": 5 + } + }, + "attend": 0 + }, + { + "uid": 670417135, + "time": 1654833667, + "face_url": "http://i1.hdslb.com/bfs/face/f8fddf339016be034736c45714b52fbb148d5252.jpg", + "uname": "阿布不喜欢我", + "user_info": { + "uid": 670417135, + "uname": "阿布不喜欢我", + "face": "http://i1.hdslb.com/bfs/face/f8fddf339016be034736c45714b52fbb148d5252.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1626451200000, + "vipStatus": 0, + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "sign": "", + "level_info": { + "current_level": 4 + } + }, + "attend": 0 + }, + { + "uid": 339203848, + "time": 1654798783, + "face_url": "http://i1.hdslb.com/bfs/face/6bead07c483681db51d519aed8b8d00de265e8ae.jpg", + "uname": "XD君233", + "user_info": { + "uid": 339203848, + "uname": "XD君233", + "face": "http://i1.hdslb.com/bfs/face/6bead07c483681db51d519aed8b8d00de265e8ae.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1620748800000, + "vipStatus": 0, + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "sign": "大爱火柴人,我的世界和一些求生枪战游戏", + "level_info": { + "current_level": 5 + } + }, + "attend": 0 + }, + { + "uid": 199624899, + "time": 1654792330, + "face_url": "http://i0.hdslb.com/bfs/face/59526a5bfbe6985a0741ddaacffaee3c90c5e34a.jpg", + "uname": "猛Pink", + "user_info": { + "uid": 199624899, + "uname": "猛Pink", + "face": "http://i0.hdslb.com/bfs/face/59526a5bfbe6985a0741ddaacffaee3c90c5e34a.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1598112000000, + "vipStatus": 0, + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "sign": "这个人很神秘,什么都看不了=●ω●=", + "level_info": { + "current_level": 5 + } + }, + "attend": 0 + }, + { + "uid": 451151619, + "time": 1654791995, + "face_url": "http://i0.hdslb.com/bfs/face/9322b5a5802b5c831b2382afed073f5290be6e38.jpg", + "uname": "七城关", + "user_info": { + "uid": 451151619, + "uname": "七城关", + "face": "http://i0.hdslb.com/bfs/face/9322b5a5802b5c831b2382afed073f5290be6e38.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1655827200000, + "vipStatus": 1, + "themeType": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299", + "role": 3, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png" + }, + "pendant": { + "pid": 6249, + "name": "星座系列:处女座", + "image": "http://i0.hdslb.com/bfs/garb/item/cd82b1c35fe0ea221c4fd56525893bc58ec53300.png", + "expire": 0, + "image_enhance": "http://i0.hdslb.com/bfs/garb/item/cd82b1c35fe0ea221c4fd56525893bc58ec53300.png", + "image_enhance_frame": "" + }, + "sign": "强迫症", + "level_info": { + "current_level": 5 + } + }, + "attend": 0 + }, + { + "uid": 375385022, + "time": 1654785903, + "face_url": "http://i2.hdslb.com/bfs/face/fbdfa7917e8f874382f4b42fcccd9c7296461cb9.jpg", + "uname": "想变成魔法少女的笙绘", + "user_info": { + "uid": 375385022, + "uname": "想变成魔法少女的笙绘", + "face": "http://i2.hdslb.com/bfs/face/fbdfa7917e8f874382f4b42fcccd9c7296461cb9.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1643472000000, + "vipStatus": 0, + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "sign": "希望自己的原创作品可以成为自活过的证明", + "level_info": { + "current_level": 5 + } + }, + "attend": 0 + }, + { + "uid": 291506521, + "time": 1654782383, + "face_url": "http://i1.hdslb.com/bfs/face/887f13f658cfbee23e3e200fe61755f1a8d5823c.jpg", + "uname": "星が落ちた日", + "user_info": { + "uid": 291506521, + "uname": "星が落ちた日", + "face": "http://i1.hdslb.com/bfs/face/887f13f658cfbee23e3e200fe61755f1a8d5823c.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1673884800000, + "vipStatus": 1, + "themeType": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299", + "role": 3, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png" + }, + "pendant": { + "pid": 4104, + "name": "良辰美景·不问天", + "image": "http://i1.hdslb.com/bfs/garb/item/4dbf08aae75f9479a21db2bb289229b8d71631e1.png", + "expire": 0, + "image_enhance": "http://i1.hdslb.com/bfs/garb/item/253bf41272ddef301c1f6a0361abd49d772bfafc.webp", + "image_enhance_frame": "http://i1.hdslb.com/bfs/garb/item/c4934a1ffdb3865fe79b319de439af3973b53ec9.png" + }, + "sign": "一时摸鱼一时爽,一直摸鱼一直爽!", + "level_info": { + "current_level": 5 + } + }, + "attend": 0 + }, + { + "uid": 179333519, + "time": 1654780391, + "face_url": "http://i2.hdslb.com/bfs/face/89a58c10bf500fb7c9530ba8f28f73208c510d22.jpg", + "uname": "纳眉兹www", + "user_info": { + "uid": 179333519, + "uname": "纳眉兹www", + "face": "http://i2.hdslb.com/bfs/face/89a58c10bf500fb7c9530ba8f28f73208c510d22.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1646496000000, + "vipStatus": 0, + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "sign": "人生", + "level_info": { + "current_level": 4 + } + }, + "attend": 0 + }, + { + "uid": 497821251, + "time": 1654780363, + "face_url": "http://i0.hdslb.com/bfs/face/a7bf301db14cb7fa094dba5f68d13faa7c5798d2.jpg", + "uname": "不器用な・ジョゼ", + "user_info": { + "uid": 497821251, + "uname": "不器用な・ジョゼ", + "face": "http://i0.hdslb.com/bfs/face/a7bf301db14cb7fa094dba5f68d13faa7c5798d2.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1683216000000, + "vipStatus": 1, + "themeType": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299", + "role": 3, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png" + }, + "pendant": { + "pid": 299, + "name": "梦塔·雪谜城", + "image": "http://i0.hdslb.com/bfs/face/c93e1eeb77b1bb0753eff243d49c006bf18d69c5.png", + "expire": 0, + "image_enhance": "http://i0.hdslb.com/bfs/face/c93e1eeb77b1bb0753eff243d49c006bf18d69c5.png", + "image_enhance_frame": "" + }, + "sign": "・花无凋零之日,爱无传达之时,爱情亘古不变,紫罗兰永世长存\n・人活着就是为了樱岛麻衣\nキャ━━━━(゚∀゚)━━━━!!", + "level_info": { + "current_level": 5 + } + }, + "attend": 0 + }, + { + "uid": 1054063538, + "time": 1654779485, + "face_url": "http://i2.hdslb.com/bfs/face/bc60a7b5c3b5fd624043050a3ab15e2c4c871803.jpg", + "uname": "贪吃的ZZ", + "user_info": { + "uid": 1054063538, + "uname": "贪吃的ZZ", + "face": "http://i2.hdslb.com/bfs/face/bc60a7b5c3b5fd624043050a3ab15e2c4c871803.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 0, + "vipDueDate": 0, + "vipStatus": 0, + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "sign": "(ฅ>ω<*ฅ)", + "level_info": { + "current_level": 3 + } + }, + "attend": 0 + }, + { + "uid": 305663999, + "time": 1654777857, + "face_url": "http://i2.hdslb.com/bfs/face/3a2b2f84990ec182af8380ef97db8256c6ecec25.jpg", + "uname": "qw夕颜", + "user_info": { + "uid": 305663999, + "uname": "qw夕颜", + "face": "http://i2.hdslb.com/bfs/face/3a2b2f84990ec182af8380ef97db8256c6ecec25.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 0, + "vipDueDate": 0, + "vipStatus": 0, + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "sign": "", + "level_info": { + "current_level": 4 + } + }, + "attend": 0 + }, + { + "uid": 436616802, + "time": 1654776381, + "face_url": "http://i0.hdslb.com/bfs/face/e1ddfcdac95b39217e4710f3605005abfecb53a1.jpg", + "uname": "桐影映江边", + "user_info": { + "uid": 436616802, + "uname": "桐影映江边", + "face": "http://i0.hdslb.com/bfs/face/e1ddfcdac95b39217e4710f3605005abfecb53a1.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1664208000000, + "vipStatus": 1, + "themeType": 0, + "label": { + "path": "", + "text": "大会员", + "label_theme": "vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "nickname_color": "", + "role": 1, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png" + }, + "pendant": { + "pid": 1990, + "name": "明日方舟", + "image": "http://i0.hdslb.com/bfs/garb/item/0c8e7d627a35c378b757f39419889ef1fcc0ed9b.png", + "expire": 0, + "image_enhance": "http://i0.hdslb.com/bfs/garb/item/1815c81da71069ea3db4553cad7d233f782da2f2.webp", + "image_enhance_frame": "http://i0.hdslb.com/bfs/garb/item/ed2b4ef1da228c0b937753542b33af8f04d1d70c.png" + }, + "sign": "追寻着你的身影,从迷失的世界起航,直到深海的尽头~", + "level_info": { + "current_level": 4 + } + }, + "attend": 0 + }, + { + "uid": 266536964, + "time": 1654775142, + "face_url": "http://i2.hdslb.com/bfs/face/b15e60d6e5403075f212d5bd3d30dc0fb3016088.jpg", + "uname": "君九j", + "user_info": { + "uid": 266536964, + "uname": "君九j", + "face": "http://i2.hdslb.com/bfs/face/b15e60d6e5403075f212d5bd3d30dc0fb3016088.jpg", + "rank": "10000", + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1683648000000, + "vipStatus": 1, + "themeType": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299", + "role": 3, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png" + }, + "pendant": { + "pid": 1293, + "name": "碧蓝航线", + "image": "http://i2.hdslb.com/bfs/face/2508daec59b2aaada2784f26f9c1c28069f28e43.png", + "expire": 0, + "image_enhance": "http://i2.hdslb.com/bfs/face/2508daec59b2aaada2784f26f9c1c28069f28e43.png", + "image_enhance_frame": "" + }, + "sign": "", + "level_info": { + "current_level": 5 + } + }, + "attend": 0 + } + ], + "has_more": 1, + "total_count": 2367, + "_gt_": 0 + } +} +``` + +</details> + +## 获取草稿列表 + +> https://api.vc.bilibili.com/dynamic_draft/v1/dynamic_draft/get_drafts + +请求方式:GET + +认证方式:Cookie(SESSDATA) + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------- | +| code | num | 返回值 | 0:成功 | +| data | obj | 信息本体 | | +| message | str | 错误信息 | 正常为"0" | +| ttl | num | 1 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ----- | -------- | ---- | +| drafts | array | 草稿列表 | | + +`drafts`列表的每一项: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | -------------------- | ------------------------------------------------------------ | +| draft_id | str | 草稿id | | +| publish_time | num | 定时发送的秒级时间戳 | | +| type | num | 动态类型 | 请参考[获取特定动态卡片信息](get_dynamic_detail.md) | +| uid | num | 自己的mid | | +| user_profile | obj | 自己的用户信息 | 请参考[用户基本信息](../user/info.md) | +| request | str | 动态内容 | 该项为json转成str,内容请参考[发表纯文本动态](publish.md#发表纯文本动态) | diff --git a/bb-api-collect/docs/dynamic/card_info.md b/bb-api-collect/docs/dynamic/card_info.md new file mode 100644 index 0000000000..89dcc31e54 --- /dev/null +++ b/bb-api-collect/docs/dynamic/card_info.md @@ -0,0 +1,604 @@ +# 动态卡片信息字段 + +不同动态内容卡片的具体信息。包含在 [获取特定动态卡片信息](get_dynamic_detail.md#获取特定动态卡片信息) 等 API 的 JSON 回复中 + +以card字段的形式出现,内容为一个可被解析为Json对象的字符串。 + +不同类型的动态内容拥有不同的字段。 + +注: 本处 `type` 一般不包含在 `card` 字符串代表的对象内 + +**** + +## 转发动态 (type=1) + +需注意账号转发视频投稿,其他用户的动态以及分享收藏夹等均为转发类内容,并不属于type=4300的收藏类动态等。 + +在type=1的转发类动态中,解析出的对象包含以下内容: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| user | obj | 转发者用户信息 | 包含用户名,用户id和头像 | +| item | obj | 转发相关信息 | `content`字段为转发附言 | | +| origin | str | 被转发动态信息 | 即本文档所描述的动态详细信息字段。<br/>动态类型为`item`对象的`orig_type`字段 | +| origin_extend_json | str | 被转发动态补充信息 | | +| origin_user | obj | 被转发用户信息 | | +| activity_infos | obj | 被转发动态参与的活动 | | + +<details> +<summary>查看字段内容示例:</summary> + +```json +{ + "user": { + "uid": 1704629193, + "uname": "钢板狗的狐", + "face": "https://i0.hdslb.com/bfs/face/443bfd128429f84c0d81c20c4354ea5007f7480c.jpg" + }, + "item": { + "rp_id": 587236631985408400, + "uid": 1704629193, + "content": "#阅机无数#这是什么本子", + "ctrl": "", + "orig_dy_id": 587058081595689300, + "pre_dy_id": 587058081595689300, + "timestamp": 1635565083, + "reply": 0, + "orig_type": 8 + }, + "origin": "{\"aid\":933765713,\"attribute\":0,\"cid\":433047365,\"copyright\":1,\"ctime\":1635523511,\"desc\":\"-\",\"dimension\":{\"height\":1920,\"rotate\":0,\"width\":1080},\"duration\":200,\"dynamic\":\"\",\"first_frame\":\"https:\\/\\/i2.hdslb.com\\/bfs\\/storyff\\/n211029a2nf13h6fhybt231isumtaj9x_firsti.jpg\",\"jump_url\":\"bilibili:\\/\\/video\\/933765713\\/?page=1&player_preload=null&player_width=1080&player_height=1920&player_rotate=0\",\"owner\":{\"face\":\"https:\\/\\/i0.hdslb.com\\/bfs\\/face\\/e4c06054bc9d6c564637f70a7565a6a2d24ee521.jpg\",\"mid\":492755628,\"name\":\"Leojdj\"},\"pic\":\"https:\\/\\/i2.hdslb.com\\/bfs\\/archive\\/8b3bd4387d4041389ba7f02ce813b17f96a7f1e2.jpg\",\"player_info\":null,\"pubdate\":1635523511,\"rights\":{\"autoplay\":1,\"bp\":0,\"download\":0,\"elec\":0,\"hd5\":0,\"is_cooperation\":0,\"movie\":0,\"no_background\":0,\"no_reprint\":1,\"pay\":0,\"ugc_pay\":0,\"ugc_pay_preview\":0},\"short_link\":\"https:\\/\\/b23.tv\\/BV16T4y1R7H9\",\"short_link_v2\":\"https:\\/\\/b23.tv\\/BV16T4y1R7H9\",\"stat\":{\"aid\":933765713,\"coin\":0,\"danmaku\":0,\"dislike\":0,\"favorite\":1,\"his_rank\":0,\"like\":2,\"now_rank\":0,\"reply\":2,\"share\":1,\"view\":70},\"state\":0,\"tid\":95,\"title\":\"试图安装Windows10\",\"tname\":\"数码\",\"up_from_v2\":9,\"videos\":1}", + "origin_extend_json": "{\"\":{\"ogv\":{\"ogv_id\":0}},\"dispute\":{\"content\":\"\"},\"from\":{\"from\":\"\"},\"like_icon\":{\"action\":\"\",\"action_url\":\"\",\"end\":\"\",\"end_url\":\"\",\"start\":\"\",\"start_url\":\"\"},\"topic\":{\"is_attach_topic\":1}}", + "origin_user": { + "info": { + "uid": 492755628, + "uname": "Leojdj", + "face": "https://i0.hdslb.com/bfs/face/e4c06054bc9d6c564637f70a7565a6a2d24ee521.jpg" + }, + "card": { + "official_verify": { + "type": -1, + "desc": "" + } + }, + "vip": { + "vipType": 0, + "vipDueDate": 0, + "vipStatus": 0, + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "rank": "10000", + "sign": "", + "level_info": { + "current_level": 3 + } + }, + "activity_infos": { + "details": [ + { + "type": 1, + "detail": "{\"is_show\":1,\"topic_id\":10511051,\"topic_link\":\"https:\\/\\/member.bilibili.com\\/york\\/punch-card?navhide=1\",\"topic_name\":\"打卡挑战\"}" + } + ] + } +} +``` + +</details> + +## 图片动态 (type=2) + +在type=2的图片动态中,解析出的对象包含以下内容: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| item | obj | 图片动态内容 | `description`字段为文字内容<br/>`pictures`字段图片 | | +| user | obj | 发布者用户信息 | 包含用户名,用户id和头像 | + + +<details> +<summary>查看字段内容示例:</summary> + +```json +{ + "item": { + "at_control": "", + "category": "daily", + "description": "#阅机无数#已知这个笔记本的品牌为Dell,隶属于灵越系列,主打外观的设计,目测应该是4代酷睿之前的型号,CPU应该是低压i5/i3,不知道能否找出具体型号", + "id": 172408258, + "is_fav": 0, + "pictures": [ + { + "img_height": 2400, + "img_size": 1425.97998046875, + "img_src": "https://i0.hdslb.com/bfs/album/3716f26eeede4d77874f3eeacd49b0e2e597fcc3.jpg", + "img_tags": null, + "img_width": 1080 + } + ], + "pictures_count": 1, + "reply": 2, + "role": [], + "settings": { + "copy_forbidden": "0" + }, + "source": [], + "title": "", + "upload_time": 1635433727 + }, + "user": { + "head_url": "https://i1.hdslb.com/bfs/face/98f88e00306ac92d30bae013f8295d26bd018093.jpg", + "name": "LostCity失落之城", + "uid": 169216498, + "vip": { + "avatar_subscript": 0, + "due_date": 0, + "label": { + "label_theme": "", + "path": "", + "text": "" + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 0, + "vip_pay_type": 0 + } + } +} +``` + +</details> + +## 文字动态 (type=4) + +在type=4的文字动态中,解析出的对象包含以下内容: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| item | obj | 文字动态内容 | `description`字段为文字内容 | | +| user | obj | 发布者用户信息 | 包含用户名,用户id和头像 | + + +<details> +<summary>查看字段内容示例:</summary> + +```json +{ + "user": { + "uid": 403417570, + "uname": "杯子人一君羊", + "face": "https://i1.hdslb.com/bfs/face/cf0772f2e4d76f75ca4c230d9ab1b50012a8bbfa.jpg" + }, + "item": { + "rp_id": 586612173803463700, + "uid": 403417570, + "content": "#阅机无数# 文字题\nthinkpad 09-15年\n触控笔\nenergy star\ncore i5\n[藏狐]", + "ctrl": "", + "orig_dy_id": 0, + "pre_dy_id": 0, + "timestamp": 1635419690, + "reply": 2 + } +} +``` + +</details> + +## 视频投稿动态 (type=8) + +在type=8的视频投稿动态中,解析出的对象包含以下内容: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| aid | num | 视频avid | | +| attribute | num | `0` | [可能已弃用](https://shakaianee.top/archives/9/) | +| cid | num | 视频cid | | +| copyright | num | 原创信息 | 1为原创,2为转载 | +| desc | str | 视频简介 | | +| dimension | obj |视频1p分辨率| | +| duration | num | 视频时长 | 单位秒 | +| dynamic | str | 动态文字内容 | | +| first_frame | str | 视频第一帧图片 | 图片链接 | +| jump_url | str | 视频跳转链接 | | +| mission_id | num | 稿件参与的活动id | | +| owner | obj | 动态作者信息 | 即up主 | +| pic | str | 视频封面 | | +| player_info | ? | 可能是播放器信息 | | +| pubdate | num | 发布时间 | 时间戳 | +| rights | obj | 联合投稿,是否付费等信息 | 可能用来代替原`attribute`字段 | +| stat | obj | 视频数据 | 点赞投币等 | +| state | num | 视频状态 | 详情见**属性数据文档** | +| tid | num | 视频分区编号 | | +| title | str | 视频标题 | | +| tname | str | 视频分区名称 | | +| video | num | 视频数| | + + + +<details> +<summary>查看字段内容示例:</summary> + +```json +{ + "aid": 506318410, + "attribute": 0, + "cid": 432711595, + "copyright": 1, + "ctime": 1635403080, + "desc": "我看谁敢欺负天依依?都别动啊,放那儿让我来!\n好久不写萌歌歌了,耐心心看到结尾,有天依依激萌嚎叫(不\n\n作曲曲/编曲曲/混音音:iKz @Signal-E | 作词词:叫叫与壶壶\n唱歌歌:洛天依 | 调校校:Creuzer\n曲绘绘:pelokio & 贝贝web & 壶芬奇\nPVV:AYWC八毛 @Signal-E\n制作人:iKz\n\n蛀牙牙版:BV1FR4y1n7rt", + "dimension": { + "height": 1080, + "rotate": 0, + "width": 1920 + }, + "duration": 265, + "dynamic": "我看谁敢欺负天依依?都别动啊,放那儿让我来!\n好久不写萌歌歌了,耐心心看到结尾,有洛天依激萌嚎叫(不", + "first_frame": "https://i1.hdslb.com/bfs/storyff/n211029a21oldgobzh2ob1uf3tqav4yy_firsti.jpg", + "jump_url": "bilibili://video/506318410/?page=1&player_preload=null&player_width=1920&player_height=1080&player_rotate=0", + "mission_id": 122069, + "owner": { + "face": "https://i1.hdslb.com/bfs/face/4935c75aecf986c3c129400882ee9c5ceeeec4b5.jpg", + "mid": 25681, + "name": "iKz_茶壶" + }, + "pic": "https://i0.hdslb.com/bfs/archive/06749bfe8b9505b00bd572950615912fecadb513.jpg", + "player_info": null, + "pubdate": 1635501604, + "rights": { + "autoplay": 1, + "bp": 0, + "download": 0, + "elec": 0, + "hd5": 1, + "is_cooperation": 1, + "movie": 0, + "no_background": 0, + "no_reprint": 1, + "pay": 0, + "ugc_pay": 0, + "ugc_pay_preview": 0 + }, + "short_link": "https://b23.tv/BV13u411o7Ht", + "short_link_v2": "https://b23.tv/BV13u411o7Ht", + "stat": { + "aid": 506318410, + "coin": 5490, + "danmaku": 486, + "dislike": 0, + "favorite": 6017, + "his_rank": 0, + "like": 8526, + "now_rank": 0, + "reply": 597, + "share": 568, + "view": 44737 + }, + "state": 0, + "tid": 30, + "title": "【超萌萌洛天依!万圣节原创】嘤嘤大作战【iKz-茶壶壶】", + "tname": "VOCALOID·UTAU", + "videos": 1 +} +``` + +</details> + +## 小视频 (type=16) + +## 戏剧? (type=32) + +## 专栏投稿动态 (type=64) + +在type=64的专栏投稿动态中,解析出的对象包含以下内容: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| id | num | 专栏的id,即cv号 | | +| category | obj | 分类号和分类名称 | | +| categories | obj | 分类信息 | | +| title | str | 专栏标题 | | +| summary | str | 专栏简介 | | +| banner_url | str | 头图链接 | | +| template_id | num | 模板信息 | | +| state | num | 专栏状态 | | +| author | obj | 作者信息 | 包含了头像挂件和勋章等 | +| reprint | num | 可能是转载 | | +| image_urls | obj | 图片链接 | | +| publish_time | num | 发布时间 | 时间戳,应该指专栏 | +| ctime | num | 发布时间 | 时间戳,应该指动态 | +| stats | obj | 专栏数据,点赞之类 | 有点踩字段,但并未实装此功能 | +| words | num | 字数 | | +| origin_image_urls | obj | 源图片地址 | | +| list | ? | 可能为文集 | | +| is_like | bool | 是否点赞 | | +| media | obj | 番剧电影相关内容 | 影评的分数,是否有剧透等 | +| apply_time | ? | ? | | +| check_time | ? | ? | | +| original | num | 是否原创 | | +| act_id | num | ? | | +| dispute | ? | 可能为是否争议内容 | | +| authenMark | ? | ? | | +| cover_avid | num | 相关视频id | 例如笔记专栏的原视频 | +| top_video_info | ? | ? | | +| type | num | 可能是专栏类别 | | + +<details> +<summary>查看字段内容示例:</summary> + +```json +{ + "id": 12457797, + "category": { + "id": 42, + "parent_id": 41, + "name": "全部笔记" + }, + "categories": [ + { + "id": 41, + "parent_id": 0, + "name": "笔记" + }, + { + "id": 42, + "parent_id": 41, + "name": "全部笔记" + } + ], + "title": "【编曲教程】弦乐如何编写?二十分钟学会弦乐基础写法~", + "summary": "点击进入查看全文", + "banner_url": "https://i0.hdslb.com/bfs/archive/9c0f743f0d79bf3f73ea196eced55a9211ef363f.jpg", + "template_id": 4, + "state": 0, + "author": { + "mid": 310236726, + "name": "珞林ltyxh", + "face": "https://i0.hdslb.com/bfs/face/8c4aebb01b3cc34154168be51241b0345f110aeb.webp", + "pendant": { + "pid": 2155, + "name": "洛天依8th生日纪念", + "image": "https://i0.hdslb.com/bfs/garb/item/e98718ae0d09e48bc85df969820b88241bc06883.png", + "expire": 0 + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "nameplate": { + "nid": 4, + "name": "青铜殿堂", + "image": "https://i0.hdslb.com/bfs/face/2879cd5fb8518f7c6da75887994c1b2a7fe670bd.png", + "image_small": "https://i2.hdslb.com/bfs/face/6707c120e00a3445933308fd9b7bd9fad99e9ec4.png", + "level": "普通勋章", + "condition": "单个自制视频总播放数>=1万" + }, + "vip": { + "type": 2, + "status": 1, + "due_date": 0, + "vip_pay_type": 0, + "theme_type": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299" + } + }, + "reprint": 0, + "image_urls": [ + "https://i0.hdslb.com/bfs/article/banner/6daa4ac60ddec2456bb720dbb4979b07dd705e8a.png" + ], + "publish_time": 1627921161, + "ctime": 1627921161, + "stats": { + "view": 107, + "favorite": 5, + "like": 11, + "dislike": 0, + "reply": 1, + "share": 0, + "coin": 1, + "dynamic": 0 + }, + "words": 225, + "origin_image_urls": [ + "https://i0.hdslb.com/bfs/article/banner/6daa4ac60ddec2456bb720dbb4979b07dd705e8a.png" + ], + "list": null, + "is_like": false, + "media": { + "score": 0, + "media_id": 0, + "title": "", + "cover": "", + "area": "", + "type_id": 0, + "type_name": "", + "spoiler": 0, + "season_id": 0 + }, + "apply_time": "", + "check_time": "", + "original": 1, + "act_id": 0, + "dispute": null, + "authenMark": null, + "cover_avid": 57337301, + "top_video_info": null, + "type": 2 +} +``` + +</details> + +## 音频投稿动态 (type=256) + +在type=256的音频投稿动态中,解析出的对象包含以下内容: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| id | num | 投稿编号 | 即au号 | +| upId | num | 音乐人id | 与用户uid不同 | +| title | str | 音频标题 | | +| upper | str | 上传者名称 | | +| cover | str | 封面图链接 | | +| author | str | 作者名称 | | +| ctime | num | 上传时间 | 时间戳的后面加了三个0 | +| playCnt | num | 播放量 | | +| intro | str | 音频介绍 | | +| schema | str | 跳转链接 | 似乎并不只是url | +| typeInfo | str | 分区信息 | | +| upperAvatar | str | 上传者的头像链接 | | + +<details> +<summary>查看字段内容示例:</summary> + +```json +{ + "id": 2562895, + "upId": 482834, + "title": "[蓝猫原创伴奏]无衣", + "upper": "NBluecat", + "cover": "https://i0.hdslb.com/bfs/music/1e7c4d04bd405159b66893d4cb68977ddf784b42.jpg", + "author": "NBluecat", + "ctime": 1632115270000, + "replyCnt": 1, + "playCnt": 252, + "intro": "_(:з」∠)_这是无衣的伴奏,非常简单", + "schema": "bilibili://music/detail/2562895?name=%5B%E8%93%9D%E7%8C%AB%E5%8E%9F%E5%88%9B%E4%BC%B4%E5%A5%8F%5D%E6%97%A0%E8%A1%A3&uperName=&cover_url=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Fmusic%2F1e7c4d04bd405159b66893d4cb68977ddf784b42.jpg&upperId=&author=NBluecat", + "typeInfo": "音乐 · 纯音乐/演奏", + "upperAvatar": "https://i2.hdslb.com/bfs/face/d5bf3c9f179803134172ff1c6090ba6b999651c6.jpg" +} +``` + +</details> + +## 番剧 (type=512) + +## ??? (type=1000) + +## ??? (type=1001) + +## ??? (type=1024) + +## H5 活动动态 (type=2048) + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| rid | number | 动态 id | | +| sketch | object | 动态卡片内容 | | +| user | object | 用户信息 | | +| vest | object | 动态正文内容 | | + +`sketch` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| cover_url | string | 封面 URL | | +| desc_text | string | 描述文本 | | +| sketch_id | number | 卡片 id | 即动态 id | +| target_url | string | 目标 URL | | +| text | string | 文本? | 空? | +| title | string | 标题 | | + +`user` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| face | string | 头像 URL | | +| uid | number | mid (UID) | | +| uname | string | 用户名 | | + +`vest` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| content | string | 内容 | | +| uid | number | 用户 mid (UID) | | + +**示例:** + +<details> +<summary>查看示例:</summary> + +```json +{ + "rid": 1093384350151475200, + "sketch": { + "cover_url": "https://i0.hdslb.com/bfs/game/65e4fa4b3cf2d177148328e2ff76535500bc563c.png", + "desc_text": "分享了一条动态", + "sketch_id": 1093755435448533000, + "target_url": "https://space.bilibili.com/645769214", + "text": "", + "title": "你好,世界" + }, + "user": { + "face": "https://i2.hdslb.com/bfs/face/77906db03b1eefac02613de184afad03f7bc58d7.jpg", + "uid": 645769214, + "uname": "Session小胡" + }, + "vest": { + "content": "[笑哭]", + "uid": 645769214 + } +} +``` +</details> + +<!-- Generated by json-apidoc-gen @ 2025-07-26T01:40:56.464495209Z --> + +## 漫画分享 (type=2049) + +## PGC 番剧 (type=4097) + +## 电影 (type=4098) + +## 电视剧 (type=4099) + +## 国创动漫 (type=4100) + +## 纪录片 (type=4101) + +## 直播 (type=4200) + +## 直播 (type=4201) + +## 收藏夹 (type=4300) + +## 付费课程 (type=4302) + +## 付费课程 (type=4303) + +## 直播 (type=4308) + +## 合集 (type=4310) + +## ??? (type=4311) + +## ??? (type=268435455) diff --git a/bb-api-collect/docs/dynamic/content.md b/bb-api-collect/docs/dynamic/content.md new file mode 100644 index 0000000000..5164f4bd8b --- /dev/null +++ b/bb-api-collect/docs/dynamic/content.md @@ -0,0 +1,1034 @@ +# 动态信息 + +## 获取正在直播的已关注者 + +> https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/w_live_users + +*请求方式:GET* + +认证方式:Cookie(SESSDSTA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---------- | ------ | -------- | +| size | num | 每页显示数 | 非必要 | 默认为10 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功 | +| data | obj | 信息本体 | | +| message | str | 错误信息 | 默认为0 | +| msg | num | 空 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----- | ---------- | ------------ | +| count | num | 直播者数量 | | +| group | str | "default" | 作用尚不明确 | +| items | array | 直播者列表 | | +| _gt_ | num | 0 | 作用尚不明确 | + +`data`中的`items`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | obj | 第一位直播者 | | +| n | obj | 第(n+1)位直播者 | | +| …… | obj | …… | …… | + +`data`中的`items`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ---------- | ---- | +| face | str | 直播者头像 | | +| link | str | 直播链接 | | +| title | str | 直播标题 | | +| uid | num | 直播者id | | +| uname | str | 直播者昵称 | | + +**示例:** + +```shell +curl -G 'https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/w_live_users' \ +--data-urlencode 'size=10' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "", + "message": "", + "data": { + "count": 4, + "group": "default", + "items": [ + { + "uid": 430774867, + "uname": "AIofficial", + "face": "https://i0.hdslb.com/bfs/face/f9a65c15bd1e9871419e6566aeee891eef420c5b.jpg", + "link": "https://live.bilibili.com/21412734", + "title": "【罚站AI】换装24小时AI直播间唱聊~" + }, + { + "uid": 456664753, + "uname": "央视新闻", + "face": "https://i1.hdslb.com/bfs/face/5a6808606bf1f7a2390b77e14df8d0d1d04680d9.jpg", + "link": "https://live.bilibili.com/21686237", + "title": "8.19中国医师节 一起“医”路同行" + }, + { + "uid": 5755666, + "uname": "可爱的大枣子", + "face": "https://i1.hdslb.com/bfs/face/248428206eca5b9ca34514dc2df54d456fbecb9e.jpg", + "link": "https://live.bilibili.com/2116488", + "title": "早上好" + }, + { + "uid": 290515513, + "uname": "地球频道", + "face": "https://i1.hdslb.com/bfs/face/33b60973ae3608beb27189947b02ccc2164a96d5.jpg", + "link": "https://live.bilibili.com/9196015", + "title": "【直播】从太空看地球" + } + ], + "_gt_": 0 + } +} +``` + +</details> + +## 获取发布新动态的已关注者 + +> https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/w_dyn_uplist + +*请求方式:GET* + +认证方式:Cookie(SESSDSTA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------------- | ---- | ------------------ | ------ | ---------------- | +| teenagers_mode | num | 是否开启青少年模式 | 非必要 | 否:0<br />是:1 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------- | +| code | num | 返回值 | 0:成功<br />-6:未登录 | +| data | obj | 信息本体 | | +| message | str | 错误信息 | 默认为0 | +| msg | num | 空 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------------- | ----- | ---------- | ------------ | +| button_statement | str | 空 | 作用尚不明确 | +| items | array | 更新者列表 | | +| _gt_ | num | 0 | 作用尚不明确 | + +`data`中的`items`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | obj | 第一位更新者 | | +| n | obj | 第(n+1)位更新者 | | +| …… | obj | …… | …… | + +**示例:** + +```shell +curl -G 'https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/w_dyn_uplist' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "", + "message": "", + "data": { + "button_statement": "", + "items": [{ + "user_profile": { + "info": { + "uid": 332704117, + "uname": "白上吹雪Official", + "face": "https://i1.hdslb.com/bfs/face/26298b21c4a059d95ee9d009bbdf1dca94da951f.jpg" + }, + "card": { + "official_verify": { + "type": 0, + "desc": "bilibili 知名UP主、直播签约主播" + } + }, + "vip": { + "vipType": 2, + "vipDueDate": 1634832000000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "" + }, + "rank": "10000", + "sign": "hololive一期生,虚拟白发狐狸白上吹雪是也(^・ω・^§)ノ 画师:凪白みと 协力:白上吹雪字幕组 商务合作请私信", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 282994, + "uname": "泠鸢yousa", + "face": "https://i2.hdslb.com/bfs/face/28f95c383f2805dbed32e93007c91ccfda28775f.jpg" + }, + "card": { + "official_verify": { + "type": 0, + "desc": "bilibili 2019百大UP主、直播签约主播" + } + }, + "vip": { + "vipType": 2, + "vipDueDate": 1649001600000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 301, + "name": "实验品家庭", + "image": "https://i1.hdslb.com/bfs/face/6fbee28f782926612eb1ad71d6c8aa7264206fe9.png", + "expire": 0, + "image_enhance": "https://i1.hdslb.com/bfs/face/6fbee28f782926612eb1ad71d6c8aa7264206fe9.png" + }, + "rank": "10000", + "sign": "虚拟艺人团体VirtuaReal Star成员,微博&网易云等搜:泠鸢yousa ", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 13765857, + "uname": "LShang001", + "face": "https://i2.hdslb.com/bfs/face/4bc59f57e6d31fcf868d7e935f643a043dd6b99f.jpg" + }, + "card": { + "official_verify": { + "type": -1, + "desc": "" + } + }, + "vip": { + "vipType": 1, + "vipDueDate": 1599926400000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "" + }, + "rank": "10000", + "sign": "Excelsior", + "level_info": { + "current_level": 5, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 410527811, + "uname": "WhatOnEarth一探究竟", + "face": "https://i0.hdslb.com/bfs/face/0ef3c74f61c4f5f0ef70ddbf3f1f0ebfed18a1b8.jpg" + }, + "card": { + "official_verify": { + "type": 0, + "desc": "bilibili 知名科普UP主" + } + }, + "vip": { + "vipType": 1, + "vipDueDate": 1599494400000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "" + }, + "rank": "10000", + "sign": "硬核人文科普,精彩社会案例,尽在WOE。", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 519253600, + "uname": "火柴人AlanBecker", + "face": "https://i1.hdslb.com/bfs/face/75e1219501e9ca3e82cad2c4a466fb4b5c7d0557.jpg" + }, + "card": { + "official_verify": { + "type": 0, + "desc": "Alan Becker官方帐号,动画UP主" + } + }, + "vip": { + "vipType": 1, + "vipDueDate": 1594137600000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "" + }, + "rank": "10000", + "sign": "Alan Becker官方频道", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 293793435, + "uname": "社会易姐QwQ", + "face": "https://i1.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg" + }, + "card": { + "official_verify": { + "type": -1, + "desc": "" + } + }, + "vip": { + "vipType": 2, + "vipDueDate": 1612454400000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "" + }, + "rank": "10000", + "sign": "高中技术宅一枚,爱好MC&电子&8-bit音乐&数码&编程,资深猿厨,粉丝群:1136462265", + "level_info": { + "current_level": 5, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 5755666, + "uname": "可爱的大枣子", + "face": "https://i1.hdslb.com/bfs/face/248428206eca5b9ca34514dc2df54d456fbecb9e.jpg" + }, + "card": { + "official_verify": { + "type": -1, + "desc": "" + } + }, + "vip": { + "vipType": 2, + "vipDueDate": 1645286400000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "" + }, + "rank": "10000", + "sign": "檐外清风惊落一池桃花染", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 51270387, + "uname": "挽竹Killer", + "face": "https://i2.hdslb.com/bfs/face/3a9f7b01c8b7d235fa2fa8d761b94520fb82bd20.jpg" + }, + "card": { + "official_verify": { + "type": -1, + "desc": "" + } + }, + "vip": { + "vipType": 1, + "vipDueDate": 1613404800000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "" + }, + "rank": "10000", + "sign": "(15w粉女装直播嗷)粉丝群:872444546", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 4409391, + "uname": "估读", + "face": "https://i0.hdslb.com/bfs/face/f0d6b44b38eff3ce023b354f692cdb5ae0013772.jpg" + }, + "card": { + "official_verify": { + "type": -1, + "desc": "" + } + }, + "vip": { + "vipType": 1, + "vipDueDate": 1578412800000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "" + }, + "rank": "10000", + "sign": "关注一下这只硬核up吧~ 脑洞能开,双手能做,立志把硬核内容做得易于食用ヾ(✿゚▽゚)ノ 粉丝群971392670。微博ID“估读酱”", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 70547713, + "uname": "Dr丶寻一", + "face": "https://i1.hdslb.com/bfs/face/fb2f66c64b1de4da329b8ccdbe4cc2db19bab488.jpg" + }, + "card": { + "official_verify": { + "type": -1, + "desc": "" + } + }, + "vip": { + "vipType": 1, + "vipDueDate": 1598025600000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 2360, + "name": "#EveOneCat", + "image": "https://i1.hdslb.com/bfs/garb/item/3a6053f073f979a776e02e088dd7dd7694c5b1f3.png", + "expire": 0, + "image_enhance": "https://i1.hdslb.com/bfs/garb/item/6c7f2ccb92627b11101dfbb616524845cac8f216.webp" + }, + "rank": "10000", + "sign": "准备开黑乐谱的坑,有时还会弄点其他的红石音乐。有什么好的黑乐谱可以私信我下载链接,只要是我电脑上的fl能够成功导入,看实际情况施工。", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 591856754, + "uname": "卢正义的雕刻时光", + "face": "https://i0.hdslb.com/bfs/face/5acc7be5c21c1dc7a4d0ebe8d741e60555971029.jpg" + }, + "card": { + "official_verify": { + "type": 0, + "desc": "bilibili 知名UP主" + } + }, + "vip": { + "vipType": 2, + "vipDueDate": 1624377600000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "" + }, + "rank": "10000", + "sign": "我是卢正义,年方二十有七\n初来贵站,还望各位多多关照\n商务合作⭐ JOJOMONO\n木品咨询⭐ lym11336699\n", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 361818130, + "uname": "是田小浪呀", + "face": "https://i1.hdslb.com/bfs/face/917d7f539e24860a52ccca2e8dbf8d6d6ca0e66b.jpg" + }, + "card": { + "official_verify": { + "type": -1, + "desc": "" + } + }, + "vip": { + "vipType": 0, + "vipDueDate": 0, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "" + }, + "rank": "10000", + "sign": "", + "level_info": { + "current_level": 3, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 108572682, + "uname": "月下玄月", + "face": "https://i1.hdslb.com/bfs/face/9cb69b21cd23fce7545c441415db17f2d57af159.jpg" + }, + "card": { + "official_verify": { + "type": 0, + "desc": "bilibili 知名UP主" + } + }, + "vip": { + "vipType": 2, + "vipDueDate": 1619712000000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "" + }, + "rank": "10000", + "sign": "QQ1群:701762419;QQ2群:1062508843", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 7450650, + "uname": "超果果mc", + "face": "https://i2.hdslb.com/bfs/face/0202ae8b377d750fe3fbeff4f9b8219b48071ee5.jpg" + }, + "card": { + "official_verify": { + "type": 0, + "desc": "bilibili 知名游戏UP主、直播签约主播" + } + }, + "vip": { + "vipType": 2, + "vipDueDate": 1645113600000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "" + }, + "rank": "10000", + "sign": "希望做出大家看了都会开心的视频 微博@超果果mc 商业合作加qq:169113409", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 4958429, + "uname": "Mukyo木西", + "face": "https://i0.hdslb.com/bfs/face/15c9b8360e524332a61b998360dd4958e0d1fd31.jpg" + }, + "card": { + "official_verify": { + "type": -1, + "desc": "" + } + }, + "vip": { + "vipType": 1, + "vipDueDate": 1582992000000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "" + }, + "rank": "10000", + "sign": "各个音乐平台搜 Mukyo木西。微博@Mukyo木西就是狗狗。", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 26321770, + "uname": "和猫住の", + "face": "https://i2.hdslb.com/bfs/face/a0f1e2e8fa05317c12064b7026a20900bdb25b5a.jpg" + }, + "card": { + "official_verify": { + "type": 0, + "desc": "bilibili 知名UP主" + } + }, + "vip": { + "vipType": 2, + "vipDueDate": 1627488000000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 303, + "name": "喂,看见耳朵啦", + "image": "https://i1.hdslb.com/bfs/face/09f3180cb0a4a0a479045fe4fad705f9b92a82d2.png", + "expire": 0, + "image_enhance": "https://i1.hdslb.com/bfs/face/09f3180cb0a4a0a479045fe4fad705f9b92a82d2.png" + }, + "rank": "10000", + "sign": "年轻人的猫咪救援领养平台,微博/公众号:和猫住 客服v:公众号和猫住菜单“联系我”", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 37556366, + "uname": "NickZhuOfficial", + "face": "https://i0.hdslb.com/bfs/face/e3a45f58368a70c5277af394bb40e32156ca2a23.jpg" + }, + "card": { + "official_verify": { + "type": -1, + "desc": "" + } + }, + "vip": { + "vipType": 0, + "vipDueDate": 0, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 2248, + "name": "搞笑专属头像挂件", + "image": "https://i2.hdslb.com/bfs/garb/item/bab219d170a1662c26beede8944c6afbc6bc2bb4.png", + "expire": 0, + "image_enhance": "https://i2.hdslb.com/bfs/garb/item/bab219d170a1662c26beede8944c6afbc6bc2bb4.png" + }, + "rank": "10000", + "sign": "鬼畜人", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 438345816, + "uname": "盲人母亲曹世美", + "face": "https://i2.hdslb.com/bfs/face/61111e0fa1ce0e8224b7aa48cc8b4dddc2ec6046.jpg" + }, + "card": { + "official_verify": { + "type": 0, + "desc": "bilibili 知名UP主" + } + }, + "vip": { + "vipType": 0, + "vipDueDate": 0, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "" + }, + "rank": "10000", + "sign": "来自贵州纳雍大山深处的一家三口,父亲腿脚残疾,母亲看不见,还有一个脑瘫儿子,盲人母亲就这样用她一双手撑起了一个家想了解v:llj104890", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 486633990, + "uname": "我是江无情", + "face": "https://i1.hdslb.com/bfs/face/bf667a09070a9345c881ec8e3e6844d8ecb043ca.jpg" + }, + "card": { + "official_verify": { + "type": 0, + "desc": "bilibili 知名科普UP主" + } + }, + "vip": { + "vipType": 2, + "vipDueDate": 1617379200000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "" + }, + "rank": "10000", + "sign": "一个做视频的,商务请私信微博:我是江无情", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 1 + }, + { + "user_profile": { + "info": { + "uid": 13337125, + "uname": "GoldenEggs", + "face": "https://i0.hdslb.com/bfs/face/11a78303bf3c69a1bf34cab25bb219eeee47961e.jpg" + }, + "card": { + "official_verify": { + "type": 0, + "desc": "bilibili 知名游戏UP主" + } + }, + "vip": { + "vipType": 2, + "vipDueDate": 1649865600000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "" + }, + "rank": "10000", + "sign": "脑洞区up主,常借助Minecraft平台实现一些好玩的想法 // 创意交流群:871449268/合作QQ:1558854197", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": "0" + } + }, + "has_update": 0 + }], + "_gt_": 0 + } +} +``` + +</details> \ No newline at end of file diff --git a/bb-api-collect/docs/dynamic/detail.md b/bb-api-collect/docs/dynamic/detail.md new file mode 100644 index 0000000000..2018cea18e --- /dev/null +++ b/bb-api-collect/docs/dynamic/detail.md @@ -0,0 +1,2327 @@ +# 获取动态详情 + +## 动态详情 + +> https://api.bilibili.com/x/polymer/web-dynamic/v1/detail +> https://api.bilibili.com/x/polymer/web-dynamic/desktop/v1/detail + +*请求方式: GET* + +认证方式: Cookie (SESSDATA) (非必要) + +鉴权方式: Cookie (User-Agent) (必要), [Wbi 签名](../misc/sign/wbi.md) (非必要) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --- | --- | --- | --- | --- | +| id | num | 动态 ID | 必要 | | +| timezone_offset | num | -480 | 非必要 | | +| platform | str | 平台 | 非必要 | `web` | +| gaia_source | str | 来源 | 非必要 | `main_web` | +| features | str | 功能 | 必要 | `itemOpusStyle,opusBigCover,onlyfansVote,endFooterHidden,decorationCard,onlyfansAssetsV2,ugcDelete,onlyfansQaCard,commentsNewVersion`, 参见 [图文 功能模块](../opus/features.md) | +| web_location | str | `333.1368` | 非必要 | | +| x-bili-device-req-json | obj | 设备信息? | 非必要 | `{"platform":"web","device":"pc"}` | +| x-bili-web-req-json | obj | 请求信息? | 非必要 | `{"spm_id":"333.1368"}` | +| w_rid | str | Wbi 签名 | 不必要 | 参见 [Wbi 签名](../misc/sign/wbi.md) | +| wts | num | UNIX 秒级时间戳 | 不必要 | 参见 [Wbi 签名](../misc/sign/wbi.md) | + +**JSON回复:** + +根对象: + +| 字段名 | 类型 | 内容 | 备注 | +|---------|-----|------|--------------------------| +| code | num | 响应码 | 0: 成功<br/>-352: 风控校验失败<br />500: 服务器错误<br />4101139: 4101139 | +| message | str | | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段名 | 类型 | 内容 | 备注 | +|------|-----|-----|-----| +| item | obj | | | + +`data.item`对象: + +参照 [获取动态列表](./all.md#获取动态列表) + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/polymer/web-dynamic/v1/detail' \ + -A 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0' \ + -b 'SESSDATA=xxxxxx' \ + --url-query 'id=967717348014293017' \ + --url-query 'w_rid=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \ + --url-query 'wts=1724986186' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "item": { + "basic": { + "comment_id_str": "326122895", + "comment_type": 11, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "326122895" + }, + "id_str": "967717348014293017", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i2.hdslb.com/bfs/face/77906db03b1eefac02613de184afad03f7bc58d7.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "645769214" + }, + "decorate": { + "card_url": "https://i0.hdslb.com/bfs/vip/a9e3d993c7a15e88ce0bf714a142f7d2b44121e2.png", + "fan": { + "color": "", + "color_format": null, + "is_fan": false, + "num_prefix": "", + "num_str": "", + "number": 0 + }, + "id": 28, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=28&isdiy=0&part=card&from=post&f_source=garb&vmid=645769214&native.theme=1&navhide=1", + "name": "2233娘", + "type": 1 + }, + "face": "https://i2.hdslb.com/bfs/face/77906db03b1eefac02613de184afad03f7bc58d7.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/645769214/dynamic", + "label": "", + "mid": 645769214, + "name": "Session小胡", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "2024年08月20日 19:17", + "pub_ts": 1724152653, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1665158400000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": null, + "desc": { + "rich_text_nodes": [ + { + "orig_text": "今天因为Linux被骂, 决定放弃支持 Windows. 而且明天要开始军训了, 将停更若干时间, 遂发此动态, 望不知.", + "text": "今天因为Linux被骂, 决定放弃支持 Windows. 而且明天要开始军训了, 将停更若干时间, 遂发此动态, 望不知.", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "今天因为Linux被骂, 决定放弃支持 Windows. 而且明天要开始军训了, 将停更若干时间, 遂发此动态, 望不知." + }, + "major": { + "draw": { + "id": 326122895, + "items": [ + { + "height": 1080, + "size": 1005.29, + "src": "http://i0.hdslb.com/bfs/new_dyn/0f6f939334104ddc347566514fa4bfa7645769214.jpg", + "tags": [], + "width": 1440 + } + ] + }, + "type": "MAJOR_TYPE_DRAW" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "删除", + "modal": { + "cancel": "取消", + "confirm": "确认删除", + "content": "动态删除后将无法恢复,请谨慎操作", + "title": "要删除动态吗?" + }, + "params": { + "dyn_id_str": "967717348014293017", + "dyn_type": 2, + "rid_str": "326122895" + }, + "type": "THREE_POINT_DELETE" + } + ] + }, + "module_stat": { + "comment": { + "count": 34, + "forbidden": false + }, + "forward": { + "count": 2, + "forbidden": false + }, + "like": { + "count": 65, + "forbidden": false, + "status": true + } + } + }, + "type": "DYNAMIC_TYPE_DRAW", + "visible": true + } + } +} +``` + +</details> + +## 动态赞与转发列表 + +> https://api.bilibili.com/x/polymer/web-dynamic/v1/detail/reaction + +*请求方式: GET* + +认证方式: Cookie (SESSDATA) + +注: 登录任意账号即可, 若不登录则返回数为 0 + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --- | --- | --- | --- | --- | +| id | num | 动态 id | 必要 | | +| offset | obj | 偏移量 | 非必要 | 用于翻页, 即响应的 `data.offset` | +| web_location | str | 333.1369 | 非必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0: 成功 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| has_more | bool | 是否有更多 | | +| items | array | 赞与转发列表 | | +| offset | str | 偏移量 | 套了一层字符串的 JSON 对象, 用于下次请求 | +| total | num | 总数 | | + +`data` 对象中的 `items` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| action | str | 操作类型 | 赞了/转发了 | +| attend | num | 参与数 | 1: 对方仅关注了发送者<br />2: 发送者关注了对方 | +| desc | str | 描述 | | +| face | str | 头像 URL | | +| mid | num | 用户 mid | | +| name | str | 用户名 | | + +**示例:** + +获取动态 `967717348014293017` 的赞与转发列表 + +```shell +curl -G 'https://api.bilibili.com/x/polymer/web-dynamic/v1/detail/reaction' \ +--url-query 'id=967717348014293017' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "has_more": true, + "items": [ + { + "action": "赞了", + "attend": 2, + "desc": "", + "face": "https://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg", + "mid": "293793435", + "name": "社会易姐QwQ" + }, + { + "action": "转发了", + "attend": 2, + "desc": "", + "face": "https://i1.hdslb.com/bfs/face/a8c0d532c19085ff14385abb51450d9c32afe93f.jpg", + "mid": "662407339", + "name": "XhuOffice" + }, + { + "action": "赞了", + "attend": 2, + "desc": "", + "face": "https://i1.hdslb.com/bfs/face/a8c0d532c19085ff14385abb51450d9c32afe93f.jpg", + "mid": "662407339", + "name": "XhuOffice" + }, + { + "action": "转发了", + "attend": 2, + "desc": "", + "face": "https://i1.hdslb.com/bfs/face/2c506dcf0b6507041b0bfafea7505cb1badf6ccd.jpg", + "mid": "616368979", + "name": "淡紫玲儿" + }, + { + "action": "赞了", + "attend": 2, + "desc": "", + "face": "https://i1.hdslb.com/bfs/face/2c506dcf0b6507041b0bfafea7505cb1badf6ccd.jpg", + "mid": "616368979", + "name": "淡紫玲儿" + }, + { + "action": "赞了", + "attend": 2, + "desc": "", + "face": "https://i2.hdslb.com/bfs/face/77906db03b1eefac02613de184afad03f7bc58d7.jpg", + "mid": "645769214", + "name": "Session小胡" + }, + { + "action": "赞了", + "attend": 0, + "desc": "共同关注了3个Up主", + "face": "https://i0.hdslb.com/bfs/face/2ac46bacfdedebf9aecf6415b95dd58636b1e22a.jpg", + "mid": "340463550", + "name": "折耳喵之心" + }, + { + "action": "赞了", + "attend": 0, + "desc": "", + "face": "https://i1.hdslb.com/bfs/face/ec855a27a42e174521399d7508cece6c0c02c6ff.jpg", + "mid": "628114249", + "name": "at白日梦想家" + }, + { + "action": "赞了", + "attend": 0, + "desc": "共同关注了3个Up主", + "face": "https://i1.hdslb.com/bfs/face/81362ba3f99b2702b9746ca7fe67ffc76d3a97c4.jpg", + "mid": "198175", + "name": "傲娇金发黑丝双马尾" + }, + { + "action": "赞了", + "attend": 0, + "desc": "", + "face": "https://i2.hdslb.com/bfs/face/df1c9bc7d79c84b7227486a944d7a748093fbb31.jpg", + "mid": "1007349302", + "name": "用户9420594" + }, + { + "action": "赞了", + "attend": 0, + "desc": "", + "face": "https://i0.hdslb.com/bfs/face/f17befd18cab5e157844ab986bd6c60d58d74738.jpg", + "mid": "1180456113", + "name": "人工智能小冰_yoyo" + }, + { + "action": "赞了", + "attend": 0, + "desc": "共同关注了2个Up主", + "face": "https://i0.hdslb.com/bfs/face/f1b0ebdf19c2f4b768c5a3e57cbd50e404ad9549.jpg", + "mid": "273008643", + "name": "LV1渡劫失败降到" + }, + { + "action": "赞了", + "attend": 0, + "desc": "", + "face": "https://i0.hdslb.com/bfs/face/a7732df2624c6a0b6e5856ceb27f3c96598a2fd4.jpg", + "mid": "452290620", + "name": "评论永远比视频精彩" + }, + { + "action": "赞了", + "attend": 0, + "desc": "", + "face": "https://i0.hdslb.com/bfs/face/cc2ea9088f066b33f24d39434d23aa68cb8ab761.png", + "mid": "91671246", + "name": "樱樱之雪" + }, + { + "action": "赞了", + "attend": 0, + "desc": "共同关注了3个Up主", + "face": "http://i1.hdslb.com/bfs/face/d20eae4d6339cef2267b36c1c262ae6466395b64.jpg", + "mid": "340632388", + "name": "天神永恒hb" + }, + { + "action": "赞了", + "attend": 0, + "desc": "共同关注了21个Up主", + "face": "https://i0.hdslb.com/bfs/face/368b2a33eed5dc146bd9ab8bf62bc9667653a350.jpg", + "mid": "38120922", + "name": "vgwik" + }, + { + "action": "赞了", + "attend": 0, + "desc": "共同关注了2个Up主", + "face": "https://i2.hdslb.com/bfs/face/efbd8bb841ea6340f39854b82d9741f47cb3351e.jpg", + "mid": "691494413", + "name": "熬夜肝不好" + }, + { + "action": "赞了", + "attend": 0, + "desc": "", + "face": "https://i1.hdslb.com/bfs/face/c46fe783ac7a5291dac4773744b3d35d7cebd77f.jpg", + "mid": "1486540726", + "name": "o_90" + }, + { + "action": "赞了", + "attend": 0, + "desc": "", + "face": "https://i1.hdslb.com/bfs/face/fece6f971d14fddbddcede65a42edc63d01884d4.jpg", + "mid": "34474963", + "name": "Neko_vecter" + }, + { + "action": "赞了", + "attend": 0, + "desc": "共同关注了8个Up主", + "face": "https://i0.hdslb.com/bfs/face/e1d66345bdb6f8c75b782ed5c4b93440860c894d.jpg", + "mid": "88466370", + "name": "没有钱的首富" + }, + { + "action": "赞了", + "attend": 0, + "desc": "共同关注了15个Up主", + "face": "https://i0.hdslb.com/bfs/face/f8a6e77e5839e64a7448ddeb7112af86eb47aa48.jpg", + "mid": "14625981", + "name": "龙凌洛" + }, + { + "action": "赞了", + "attend": 0, + "desc": "", + "face": "https://i2.hdslb.com/bfs/face/18c0bb87fbc8f9fde0d7f92ab88917e517e53df1.jpg", + "mid": "36708269", + "name": "alcoholmole" + }, + { + "action": "赞了", + "attend": 0, + "desc": "", + "face": "https://i0.hdslb.com/bfs/face/39f0e0ec39e6828b01afc28ad001471d1efa8c66.jpg", + "mid": "52874964", + "name": "黑暗战师" + }, + { + "action": "赞了", + "attend": 1, + "desc": "对方关注了你", + "face": "https://i0.hdslb.com/bfs/face/07d73f7d01c8e8cfb9173d8fe6e40a0c8cb5713d.jpg", + "mid": "702368712", + "name": "-御帝哥哥-" + }, + { + "action": "赞了", + "attend": 0, + "desc": "共同关注了22个Up主", + "face": "http://i0.hdslb.com/bfs/face/member/noface.jpg", + "mid": "398095475", + "name": "meipeter" + }, + { + "action": "赞了", + "attend": 0, + "desc": "", + "face": "https://i1.hdslb.com/bfs/face/a4a1566d7218307839345a079651bf58a69a028f.jpg", + "mid": "101358808", + "name": "香香软软的小阿芙" + } + ], + "offset": "{\"page\":2,\"like\":101358808,\"repost\":-1}", + "total": 65 + } +} +``` + +</details> + +## 动态抽奖详情 + +> https://api.vc.bilibili.com/lottery_svr/v1/lottery_svr/lottery_notice + +*请求方法: GET* + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | ---- | -------- | ------ | ---- | +| business_id | num | 动态 id | 必要 | | +| bussiness_type | num | 业务类型? | 必要 | 1: 动态抽奖 | +| csrf | str | CSRF Token (即 Cookie 中 bili_jct 字段) | 不必要 | | +| web_location | str | 333.1330 | 不必要 | | + +<details> +<summary>旧版参数:</summary> + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | ---- | -------- | ------ | ---- | +| dynamic_id | num | 动态 id | 必要 | | + +</details> + +**JSON回复:** + +根对象: + +| 字段名 | 类型 | 内容 | 备注 | +| - | - | - | - | +| code | num | 返回值 | 0: 成功<br />-9999: 服务系统错误 | +| message | str | 错误信息 | 无则为空串 | +| msg | str | 错误信息 | 无则为空串 | +| data | obj | 信息本体 | 错误时为空对象 | + +`data`对象: + +| 字段名 | 类型 | 内容 | 备注 | +| - | - | - | - | +| lottery_id | num | 抽奖 id | | +| sender_uid | num | 发送者 mid | | +| business_type | num | 业务类型 | 1: 动态抽奖 | +| business_id | num | 业务 id | 可能与请求参数不同 | +| status | num | 抽奖状态 | 0: 未开奖<br />2: 已开奖 | +| lottery_time | num | 开奖时间 | UNIX 秒级时间戳 | +| lottery_at_num | num | at 人数? | | +| lottery_feed_limit | num | 转发限制? | | +| need_post | num | 是否需要发布? | | +| pay_status | num | 支付状态? | | +| first_prize | num | 一等奖数量 | | +| second_prize | num | 二等奖数量 | | +| third_prize | num | 三等奖数量 | | +| ts | num | 发布时间 | UNIX 秒级时间戳 | +| participants | num | 参与人数 | | +| has_charge_right | bool | 是否有充值权? | | +| participated | bool | 是否参与过? | | +| followed | bool | 是否关注过 | | +| reposted | bool | 是否转发过 | | +| lottery_detail_url | str | 抽奖详情页 URL? | | +| first_prize_cmt | str | 一等奖奖品名称 | | +| third_prize_cmt | str | 三等奖奖品名称 | | +| first_prize_pic | str | 一等奖奖品图片 URL | | +| second_prize_pic | str | 二等奖奖品图片 URL | | +| third_prize_pic | str | 三等奖奖品图片 URL | | +| vip_batch_sign | str | ? | | +| prize_type_first | obj | 一等奖奖品类型 | | +| prize_type_second | obj | 二等奖奖品类型 | 无则不存在 | +| prize_type_third | obj | 三等奖奖品类型 | 无则不存在 | +| lottery_result | obj | 抽奖结果 | 无则不存在 | + +`data`对象中的`prize_type_first`对象: + +| 字段名 | 类型 | 内容 | 备注 | +| - | - | - | - | +| type | num | 奖品类型? | 0 | +| value | obj | 奖品价值? | | + +`prize_type_first`对象中的`value`对象: + +| 字段名 | 类型 | 内容 | 备注 | +| - | - | - | - | +| stype | num | 子奖品类型? | 0 | + +`data`对象中的`prize_type_second`对象: + +与 `prize_type_first` 格式相同 + +`data`对象中的`prize_type_third`对象: + +与 `prize_type_first` 格式相同 + +`data`对象中的`lottery_result`对象: + +| 字段名 | 类型 | 内容 | 备注 | +| - | - | - | - | +| first_prize_result | array | 一等奖结果 | | +| second_prize_result | array | 二等奖结果 | 无则不存在 | +| third_prize_result | array | 三等奖结果 | 无则不存在 | + +`lottery_result`对象中的`first_prize_result`数组: + +| 项名 | 类型 | 内容 | 备注 | +| - | - | - | - | +| uid | num | 中奖者 mid | | +| name | str | 中奖者名称 | | +| face | str | 中奖者头像 URL | | +| hongbao_money | num | 奖品金额? | | + +`lottery_result`对象中的`second_prize_result`数组: + +与 `first_prize_result` 格式相同 + +`lottery_result`对象中的`third_prize_result`数组: + +与 `first_prize_result` 格式相同 + +**示例:** + +```shell +curl -G 'https://api.vc.bilibili.com/lottery_svr/v1/lottery_svr/lottery_notice' \ +--url-query 'business_id=969916293954142214' \ +--url-query 'business_type=1' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "lottery_id": 314834, + "sender_uid": 36081646, + "business_type": 1, + "business_id": 969916293954142214, + "status": 2, + "lottery_time": 1724860800, + "lottery_at_num": 0, + "lottery_feed_limit": 1, + "need_post": 0, + "pay_status": 0, + "first_prize": 1, + "second_prize": 0, + "third_prize": 0, + "ts": 1724922650, + "participants": 9230, + "has_charge_right": false, + "participated": false, + "followed": false, + "reposted": false, + "lottery_detail_url": "", + "first_prize_cmt": "S档门票", + "third_prize_cmt": "", + "first_prize_pic": "", + "second_prize_pic": "", + "third_prize_pic": "", + "vip_batch_sign": "", + "prize_type_first": { + "type": 0, + "value": { + "stype": 0 + } + }, + "lottery_result": { + "first_prize_result": [ + { + "uid": 1014634854, + "name": "lty世界第一吃货殿下", + "face": "https://i0.hdslb.com/bfs/face/c746083b15f6761ea75c602661123e68784c6b1c.jpg", + "hongbao_money": 0 + } + ] + } + }, + "message": "", + "msg": "" +} +``` + +</details> + +## 动态转发列表 + +> https://api.bilibili.com/x/polymer/web-dynamic/v1/detail/forward + +*请求方法: GET* + +鉴权方式: `User-Agent` 为有效浏览器等 + +<!-- #1343 --> + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | ---- | -------- | ------ | ---- | +| id | number | 动态 id | 必要 | | +| offset | string | 偏移 | 不必要 | 来自上一次请求的 `data.offset` | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | number | 返回值 | 0: 成功<br />4101001: 参数错误<br />-352: 风控校验失败 | +| data | object | 数据本体 | | +| message | string | 错误信息 | 成功时为 `0` | +| ttl | number | `1` | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| has_more | boolean | 是否有更多数据 | | +| items | object[] | 转发列表 | | +| offset | string | 下一页偏移 | 用于下一次请求 | +| total | number | 总数 | | + +`data.items[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| desc | object | 描述 | | +| id_str | string | 进行转发的动态 id | | +| pub_time | string | 发布时间 | | +| user | object | 用户 | | + +`data.items[].desc` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| rich_text_nodes | object[] | 富文本节点 | 参见 [富文本节点](../opus/rich_text_nodesmd) | +| text | string | 纯文本 | | + +`data.items[].user` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| face | string | 头像 URL | | +| face_nft | boolean | 是否为 NFT 头像 | | +| mid | number | 用户 mid (UID) | | +| name | string | 用户名 | | +| official | object | 认证信息 | | +| pendant | object | 装扮信息 | | +| vip | object | 大会员信息 | | + +`data.items[].user.official` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| desc | string | | | +| role | number | | | +| title | string | | | +| type | number | | | + +`data.items[].user.pendant` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| expire | number | | | +| image | string | | | +| image_enhance | string | | | +| image_enhance_frame | string | | | +| n_pid | number | | | +| name | string | | | +| pid | number | | | + +`data.items[].user.vip` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| avatar_icon | object | | | +| avatar_subscript | number | | | +| avatar_subscript_url | string | | | +| due_date | number | | | +| label | object | | | +| nickname_color | string | | | +| role | number | | | +| status | number | | | +| theme_type | number | | | +| tv_due_date | number | | | +| tv_vip_pay_type | number | | | +| tv_vip_status | number | | | +| type | number | | | +| vip_pay_type | number | | | + +`data.items[].user.vip.avatar_icon` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| icon_resource | object | | | + +`data.items[].user.vip.avatar_icon.icon_resource` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | + +`data.items[].user.vip.label` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| bg_color | string | | | +| bg_style | number | | | +| border_color | string | | | +| img_label_uri_hans | string | | | +| img_label_uri_hans_static | string | | | +| img_label_uri_hant | string | | | +| img_label_uri_hant_static | string | | | +| label_theme | string | | | +| path | string | | | +| text | string | | | +| text_color | string | | | +| use_img_label | boolean | | | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/polymer/web-dynamic/v1/detail/forward' \ +--url-query 'id=1091904489085993012' \ +-A 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "has_more": true, + "items": [ + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "恭喜恭喜​//", + "text": "恭喜恭喜​//", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@英伟达GeForce", + "rid": "485703766", + "text": "@英伟达GeForce", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注", + "text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@英伟达GeForce ", + "rid": "485703766", + "text": "@英伟达GeForce ", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": " 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "text": " 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E8%A3%82%E5%8F%98%E5%A4%A9%E5%9C%B0s1%23", + "orig_text": "#裂变天地s1#", + "text": "#裂变天地s1#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23CS2%23", + "orig_text": "#CS2#", + "text": "#CS2#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23TYLOO%23", + "orig_text": "#TYLOO#", + "text": "#TYLOO#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E4%B8%AD%E5%9B%BD%E5%A4%A9%E7%A6%84%E5%88%9B%E5%8E%86%E5%8F%B2%E5%A4%BA%E5%86%A0%23", + "orig_text": "#中国天禄创历史夺冠#", + "text": "#中国天禄创历史夺冠#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + } + ], + "text": "恭喜恭喜​//@英伟达GeForce:热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n#裂变天地s1##CS2##TYLOO##中国天禄创历史夺冠#" + }, + "id_str": "1092279955170000920", + "pub_time": "1分钟前", + "user": { + "face": "https://i2.hdslb.com/bfs/face/c831cf26f1012338306a178d70a436a7ac2d79fb.jpg", + "face_nft": false, + "mid": 58964126, + "name": "see_ka", + "official": { + "desc": "", + "role": 0, + "title": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "vip": { + "avatar_icon": { + "icon_resource": {} + }, + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1699977600000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "role": 0, + "status": 0, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 1, + "vip_pay_type": 0 + } + } + }, + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "转发动态//", + "text": "转发动态//", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@英伟达GeForce", + "rid": "485703766", + "text": "@英伟达GeForce", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E8%A3%82%E5%8F%98%E5%A4%A9%E5%9C%B0s1%23", + "orig_text": "#裂变天地s1#", + "text": "#裂变天地s1#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23CS2%23", + "orig_text": "#CS2#", + "text": "#CS2#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23TYLOO%23", + "orig_text": "#TYLOO#", + "text": "#TYLOO#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E4%B8%AD%E5%9B%BD%E5%A4%A9%E7%A6%84%E5%88%9B%E5%8E%86%E5%8F%B2%E5%A4%BA%E5%86%A0%23", + "orig_text": "#中国天禄创历史夺冠#", + "text": "#中国天禄创历史夺冠#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + } + ], + "text": "转发动态//@英伟达GeForce:热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n#裂变天地s1##CS2##TYLOO##中国天禄创历史夺冠#" + }, + "id_str": "1092279895003758596", + "pub_time": "1分钟前", + "user": { + "face": "https://i2.hdslb.com/bfs/face/d62d4f1d1e8e74a5bc3befd1367c0e0cace13390.jpg", + "face_nft": false, + "mid": 3546652805696378, + "name": "小大宙", + "official": { + "desc": "", + "role": 0, + "title": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "vip": { + "avatar_icon": { + "icon_resource": {} + }, + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 0, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "role": 0, + "status": 0, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 0, + "vip_pay_type": 0 + } + } + }, + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "许愿幸运呀嘿嘿,加油加油", + "text": "许愿幸运呀嘿嘿,加油加油", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "emoji": { + "icon_url": "https://i0.hdslb.com/bfs/garb/c2cb4128fd28a727b4aec120e26adc4adf0f4e75.png", + "size": 2, + "text": "[Akie秋绘七周年_阳光可爱]", + "type": 3 + }, + "orig_text": "[Akie秋绘七周年_阳光可爱]", + "text": "[Akie秋绘七周年_阳光可爱]", + "type": "RICH_TEXT_NODE_TYPE_EMOJI" + }, + { + "emoji": { + "icon_url": "https://i0.hdslb.com/bfs/garb/c2cb4128fd28a727b4aec120e26adc4adf0f4e75.png", + "size": 2, + "text": "[Akie秋绘七周年_阳光可爱]", + "type": 3 + }, + "orig_text": "[Akie秋绘七周年_阳光可爱]", + "text": "[Akie秋绘七周年_阳光可爱]", + "type": "RICH_TEXT_NODE_TYPE_EMOJI" + }, + { + "orig_text": "​//", + "text": "​//", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@英伟达GeForce", + "rid": "485703766", + "text": "@英伟达GeForce", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注", + "text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@英伟达GeForce ", + "rid": "485703766", + "text": "@英伟达GeForce ", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": " 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "text": " 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E8%A3%82%E5%8F%98%E5%A4%A9%E5%9C%B0s1%23", + "orig_text": "#裂变天地s1#", + "text": "#裂变天地s1#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23CS2%23", + "orig_text": "#CS2#", + "text": "#CS2#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23TYLOO%23", + "orig_text": "#TYLOO#", + "text": "#TYLOO#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E4%B8%AD%E5%9B%BD%E5%A4%A9%E7%A6%84%E5%88%9B%E5%8E%86%E5%8F%B2%E5%A4%BA%E5%86%A0%23", + "orig_text": "#中国天禄创历史夺冠#", + "text": "#中国天禄创历史夺冠#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + } + ], + "text": "许愿幸运呀嘿嘿,加油加油[Akie秋绘七周年_阳光可爱][Akie秋绘七周年_阳光可爱]​//@英伟达GeForce:热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n#裂变天地s1##CS2##TYLOO##中国天禄创历史夺冠#" + }, + "id_str": "1092279663073427464", + "pub_time": "2分钟前", + "user": { + "face": "https://i2.hdslb.com/bfs/face/2286199120c79b81bd77f1c21849288a656e52d3.webp", + "face_nft": false, + "mid": 1627169000, + "name": "咚咚咚巴拉嘎嘎", + "official": { + "desc": "", + "role": 0, + "title": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "vip": { + "avatar_icon": { + "icon_resource": {} + }, + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 0, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "role": 0, + "status": 0, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 0, + "vip_pay_type": 0 + } + } + }, + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "转发动态//", + "text": "转发动态//", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@英伟达GeForce", + "rid": "485703766", + "text": "@英伟达GeForce", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E8%A3%82%E5%8F%98%E5%A4%A9%E5%9C%B0s1%23", + "orig_text": "#裂变天地s1#", + "text": "#裂变天地s1#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23CS2%23", + "orig_text": "#CS2#", + "text": "#CS2#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23TYLOO%23", + "orig_text": "#TYLOO#", + "text": "#TYLOO#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E4%B8%AD%E5%9B%BD%E5%A4%A9%E7%A6%84%E5%88%9B%E5%8E%86%E5%8F%B2%E5%A4%BA%E5%86%A0%23", + "orig_text": "#中国天禄创历史夺冠#", + "text": "#中国天禄创历史夺冠#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + } + ], + "text": "转发动态//@英伟达GeForce:热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n#裂变天地s1##CS2##TYLOO##中国天禄创历史夺冠#" + }, + "id_str": "1092278962995855364", + "pub_time": "5分钟前", + "user": { + "face": "https://i0.hdslb.com/bfs/face/b829e7e3a9e7b1dc8e2fb0486ddcd60e61ca9bca.jpg", + "face_nft": false, + "mid": 3493274574654105, + "name": "雷冬冬加油呀", + "official": { + "desc": "", + "role": 0, + "title": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "vip": { + "avatar_icon": { + "icon_resource": {} + }, + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 0, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "role": 0, + "status": 0, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 0, + "vip_pay_type": 0 + } + } + }, + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "转发动态//", + "text": "转发动态//", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@英伟达GeForce", + "rid": "485703766", + "text": "@英伟达GeForce", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E8%A3%82%E5%8F%98%E5%A4%A9%E5%9C%B0s1%23", + "orig_text": "#裂变天地s1#", + "text": "#裂变天地s1#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23CS2%23", + "orig_text": "#CS2#", + "text": "#CS2#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23TYLOO%23", + "orig_text": "#TYLOO#", + "text": "#TYLOO#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E4%B8%AD%E5%9B%BD%E5%A4%A9%E7%A6%84%E5%88%9B%E5%8E%86%E5%8F%B2%E5%A4%BA%E5%86%A0%23", + "orig_text": "#中国天禄创历史夺冠#", + "text": "#中国天禄创历史夺冠#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + } + ], + "text": "转发动态//@英伟达GeForce:热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n#裂变天地s1##CS2##TYLOO##中国天禄创历史夺冠#" + }, + "id_str": "1092278920047230984", + "pub_time": "5分钟前", + "user": { + "face": "https://i1.hdslb.com/bfs/face/97630265e04024f6ae169ffc513480821058fe10.jpg", + "face_nft": false, + "mid": 612768016, + "name": "宇宙尽头是被窝", + "official": { + "desc": "", + "role": 0, + "title": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "vip": { + "avatar_icon": { + "icon_resource": {} + }, + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 0, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "role": 0, + "status": 0, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 0, + "vip_pay_type": 0 + } + } + }, + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "转发动态//", + "text": "转发动态//", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@英伟达GeForce", + "rid": "485703766", + "text": "@英伟达GeForce", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E8%A3%82%E5%8F%98%E5%A4%A9%E5%9C%B0s1%23", + "orig_text": "#裂变天地s1#", + "text": "#裂变天地s1#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23CS2%23", + "orig_text": "#CS2#", + "text": "#CS2#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23TYLOO%23", + "orig_text": "#TYLOO#", + "text": "#TYLOO#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E4%B8%AD%E5%9B%BD%E5%A4%A9%E7%A6%84%E5%88%9B%E5%8E%86%E5%8F%B2%E5%A4%BA%E5%86%A0%23", + "orig_text": "#中国天禄创历史夺冠#", + "text": "#中国天禄创历史夺冠#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + } + ], + "text": "转发动态//@英伟达GeForce:热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n#裂变天地s1##CS2##TYLOO##中国天禄创历史夺冠#" + }, + "id_str": "1092278580747960353", + "pub_time": "6分钟前", + "user": { + "face": "https://i0.hdslb.com/bfs/face/a5ae348d6ab686e17ab0e2acd5a0d12f4908f55f.jpg", + "face_nft": false, + "mid": 1603962291, + "name": "天堂尿壶_全神贯注", + "official": { + "desc": "", + "role": 0, + "title": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "vip": { + "avatar_icon": { + "icon_resource": {} + }, + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 0, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "role": 0, + "status": 0, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 0, + "vip_pay_type": 0 + } + } + }, + { + "desc": { + "rich_text_nodes": [ + { + "jump_url": "https://b23.tv/7cYpOev", + "orig_text": "https://b23.tv/7cYpOev", + "text": "网页链接", + "type": "RICH_TEXT_NODE_TYPE_WEB" + }, + { + "orig_text": "\ncncs", + "text": "\ncncs", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "emoji": { + "icon_url": "https://i0.hdslb.com/bfs/garb/55b2580bd5c24f87d3910ef8bd7bd70bb6bc22de.png", + "size": 2, + "text": "[青春烟火静态表情包_比心心]", + "type": 3 + }, + "orig_text": "[青春烟火静态表情包_比心心]", + "text": "[青春烟火静态表情包_比心心]", + "type": "RICH_TEXT_NODE_TYPE_EMOJI" + }, + { + "emoji": { + "icon_url": "https://i0.hdslb.com/bfs/garb/55b2580bd5c24f87d3910ef8bd7bd70bb6bc22de.png", + "size": 2, + "text": "[青春烟火静态表情包_比心心]", + "type": 3 + }, + "orig_text": "[青春烟火静态表情包_比心心]", + "text": "[青春烟火静态表情包_比心心]", + "type": "RICH_TEXT_NODE_TYPE_EMOJI" + }, + { + "orig_text": "​//", + "text": "​//", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@英伟达GeForce", + "rid": "485703766", + "text": "@英伟达GeForce", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注", + "text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@英伟达GeForce ", + "rid": "485703766", + "text": "@英伟达GeForce ", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": " 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "text": " 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E8%A3%82%E5%8F%98%E5%A4%A9%E5%9C%B0s1%23", + "orig_text": "#裂变天地s1#", + "text": "#裂变天地s1#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23CS2%23", + "orig_text": "#CS2#", + "text": "#CS2#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23TYLOO%23", + "orig_text": "#TYLOO#", + "text": "#TYLOO#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E4%B8%AD%E5%9B%BD%E5%A4%A9%E7%A6%84%E5%88%9B%E5%8E%86%E5%8F%B2%E5%A4%BA%E5%86%A0%23", + "orig_text": "#中国天禄创历史夺冠#", + "text": "#中国天禄创历史夺冠#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + } + ], + "text": "https://b23.tv/7cYpOev\ncncs[青春烟火静态表情包_比心心][青春烟火静态表情包_比心心]​//@英伟达GeForce:热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n#裂变天地s1##CS2##TYLOO##中国天禄创历史夺冠#" + }, + "id_str": "1092278374586384390", + "pub_time": "7分钟前", + "user": { + "face": "https://i0.hdslb.com/bfs/baselabs/ad8743f86fbf3c0afe80505ef2fcf7c567d99cd5.png", + "face_nft": true, + "mid": 3546570991601673, + "name": "敷料", + "official": { + "desc": "", + "role": 0, + "title": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/open/e9857ee50a657bf8bc004296d1486522489f9ce9.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/open/e9857ee50a657bf8bc004296d1486522489f9ce9.png", + "image_enhance_frame": "", + "n_pid": 1733371830001, + "name": "元大头像挂件", + "pid": -1794957583 + }, + "vip": { + "avatar_icon": { + "icon_resource": {} + }, + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1724774400000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "role": 0, + "status": 0, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 1, + "vip_pay_type": 0 + } + } + }, + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "//", + "text": "//", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@英伟达GeForce", + "rid": "485703766", + "text": "@英伟达GeForce", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注", + "text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@英伟达GeForce", + "rid": "485703766", + "text": "@英伟达GeForce", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": " 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "text": " 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E8%A3%82%E5%8F%98%E5%A4%A9%E5%9C%B0s1%23", + "orig_text": "#裂变天地s1#", + "text": "#裂变天地s1#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23CS2%23", + "orig_text": "#CS2#", + "text": "#CS2#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23TYLOO%23", + "orig_text": "#TYLOO#", + "text": "#TYLOO#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E4%B8%AD%E5%9B%BD%E5%A4%A9%E7%A6%84%E5%88%9B%E5%8E%86%E5%8F%B2%E5%A4%BA%E5%86%A0%23", + "orig_text": "#中国天禄创历史夺冠#", + "text": "#中国天禄创历史夺冠#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + } + ], + "text": "//@英伟达GeForce:热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n#裂变天地s1##CS2##TYLOO##中国天禄创历史夺冠#" + }, + "id_str": "1092277777626824725", + "pub_time": "9分钟前", + "user": { + "face": "https://i0.hdslb.com/bfs/face/3283cc839ebb4f745891ef2b3eb52b608dc6287e.jpg", + "face_nft": false, + "mid": 241814478, + "name": "巧克力糖三角", + "official": { + "desc": "", + "role": 0, + "title": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1756569600000, + "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": "http://i0.hdslb.com/bfs/vip/label_annual.png", + "text": "年度大会员", + "text_color": "#FFFFFF", + "use_img_label": true + }, + "nickname_color": "#FB7299", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + } + }, + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "转发动态//", + "text": "转发动态//", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@英伟达GeForce", + "rid": "485703766", + "text": "@英伟达GeForce", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注", + "text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@英伟达GeForce", + "rid": "485703766", + "text": "@英伟达GeForce", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": " 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "text": " 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E8%A3%82%E5%8F%98%E5%A4%A9%E5%9C%B0s1%23", + "orig_text": "#裂变天地s1#", + "text": "#裂变天地s1#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23CS2%23", + "orig_text": "#CS2#", + "text": "#CS2#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23TYLOO%23", + "orig_text": "#TYLOO#", + "text": "#TYLOO#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E4%B8%AD%E5%9B%BD%E5%A4%A9%E7%A6%84%E5%88%9B%E5%8E%86%E5%8F%B2%E5%A4%BA%E5%86%A0%23", + "orig_text": "#中国天禄创历史夺冠#", + "text": "#中国天禄创历史夺冠#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + } + ], + "text": "转发动态//@英伟达GeForce:热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n#裂变天地s1##CS2##TYLOO##中国天禄创历史夺冠#" + }, + "id_str": "1092277631582208005", + "pub_time": "10分钟前", + "user": { + "face": "https://i2.hdslb.com/bfs/face/44b28a33ee43080ba8ce3b004f61c6f6a8f84ae2.jpg", + "face_nft": false, + "mid": 385330502, + "name": "LunariaFox", + "official": { + "desc": "", + "role": 0, + "title": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "vip": { + "avatar_icon": { + "icon_resource": {} + }, + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1671292800000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "role": 0, + "status": 0, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 1, + "vip_pay_type": 0 + } + } + }, + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "转发动态//", + "text": "转发动态//", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@英伟达GeForce", + "rid": "485703766", + "text": "@英伟达GeForce", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "text": ":热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E8%A3%82%E5%8F%98%E5%A4%A9%E5%9C%B0s1%23", + "orig_text": "#裂变天地s1#", + "text": "#裂变天地s1#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23CS2%23", + "orig_text": "#CS2#", + "text": "#CS2#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23TYLOO%23", + "orig_text": "#TYLOO#", + "text": "#TYLOO#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%23%E4%B8%AD%E5%9B%BD%E5%A4%A9%E7%A6%84%E5%88%9B%E5%8E%86%E5%8F%B2%E5%A4%BA%E5%86%A0%23", + "orig_text": "#中国天禄创历史夺冠#", + "text": "#中国天禄创历史夺冠#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + } + ], + "text": "转发动态//@英伟达GeForce:热爱从未褪色,拼搏终有回响!\n恭喜 TYLOO 站上了世界冠军的领奖台!\n这就是 GEFORCE,这就是 CS:GO,这就是 TYLOO!\n关注@英伟达GeForce 并转发该条动态内容,我们将抽选 3 位小伙伴获得【100元京东E卡】一张!\n#裂变天地s1##CS2##TYLOO##中国天禄创历史夺冠#" + }, + "id_str": "1092276742539706437", + "pub_time": "13分钟前", + "user": { + "face": "https://i0.hdslb.com/bfs/face/3485b31e66a5edcc35da91daccf92d8374b75109.jpg", + "face_nft": false, + "mid": 261738771, + "name": "ak青旗沽酒", + "official": { + "desc": "", + "role": 0, + "title": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "vip": { + "avatar_icon": { + "icon_resource": {} + }, + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1721318400000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "role": 0, + "status": 0, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 1, + "vip_pay_type": 0 + } + } + } + ], + "offset": "1092276742539706437", + "total": 1290 + }, + "message": "0", + "ttl": 1 +} +``` +</details> + +<!-- Generated by json-apidoc-gen @ 2025-07-22T03:25:21.567940914Z --> + +## 获取动态中图片 + +> https://api.bilibili.com/x/polymer/web-dynamic/v1/detail/pic + +*请求方法: GET* + +<!-- #1303 --> + +**URL 参数:** + +| 字段 | 类型 | 内容 | 必要性 | 备注 | +| ---- | ------ | ------- | ------ | ---- | +| id | number | 动态 id | 必要 | | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | number | 返回值 | | +| data | object[] | 数据本体 | | +| message | string | 错误信息 | 成功时为 `0` | +| ttl | number | `1` | | + +`data[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| height | number | 图片高度 | | +| size | number | 图片大小 | k | +| src | string | 图片 URL | | +| width | number | 图片宽度 | | + +**示例:** + +```shell +-curl -G 'https://api.bilibili.com/x/polymer/web-dynamic/v1/detail/pic' \ +--url-query 'id=1092404028147499014' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": [ + { + "height": 20112, + "size": 9609.4560546875, + "src": "http://i0.hdslb.com/bfs/new_dyn/b3ca19b4a65c2f847fa91d925495eb3f36081646.jpg", + "width": 4167 + }, + { + "height": 21146, + "size": 6948.43359375, + "src": "http://i0.hdslb.com/bfs/new_dyn/60b1549d91ce580a8499f63368b283fc36081646.jpg", + "width": 4167 + }, + { + "height": 29531, + "size": 10990.845703125, + "src": "http://i0.hdslb.com/bfs/new_dyn/598a158fff8a5814fe85ae0f9212b1cf36081646.jpg", + "width": 4167 + } + ], + "message": "0", + "ttl": 1 +} +``` +</details> + +<!-- Generated by json-apidoc-gen @ 2025-07-23T01:44:31.058550428Z --> + +## 获取转发动态信息 + +> https://api.bilibili.com/x/polymer/web-dynamic/v1/detail/forward/item + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +**URL 参数:** + +| 字段 | 类型 | 内容 | 必要性 | 备注 | +| ---- | ------ | ------ | ---- | ---- | +| id | number | 动态 id | 必要 | | +| timezone_offset | number | 时区偏移 | 非必要 | `(new Date).getTimezoneOffset()` | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | number | 返回值 | 0: 成功<br />500: 加载错误,请稍后再试<br />4101105: 请求数据发生错误, 请刷新或稍后重试 | +| data | object | 数据本体 | | +| message | string | 错误信息 | 成功时为 `0` | +| ttl | number | `1` | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| item | object | 动态信息 | 套了个娃 | + +`data.item` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| desc | object | 动态内容 | | +| id_str | string | 动态 id 字符串 | | +| pub_time | string | 发布时间 | | +| user | object | 发布用户信息 | | + +`data.item.desc` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| rich_text_nodes | object[] | 富文本节点 | 参见 [富文本节点](../opus/rich_text_node.md) | +| text | string | 纯文本内容 | | + +`data.item.user` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| face | string | 头像 URL | | +| face_nft | boolean | | | +| mid | number | 用户 mid (UID) | | +| name | string | 用户名 | | +| official | object | 认证信息 | | +| pendant | object | 装扮信息 | | +| vip | object | 大会员信息 | | + +`data.item.user.official` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| desc | string | | | +| role | number | | | +| title | string | | | +| type | number | | | + +`data.item.user.pendant` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| expire | number | | | +| image | string | | | +| image_enhance | string | | | +| image_enhance_frame | string | | | +| n_pid | number | | | +| name | string | | | +| pid | number | | | + +`data.item.user.vip` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| avatar_icon | object | | | +| avatar_subscript | number | | | +| avatar_subscript_url | string | | | +| due_date | number | | | +| label | object | | | +| nickname_color | string | | | +| role | number | | | +| status | number | | | +| theme_type | number | | | +| tv_due_date | number | | | +| tv_vip_pay_type | number | | | +| tv_vip_status | number | | | +| type | number | | | +| vip_pay_type | number | | | + +`data.item.user.vip.avatar_icon` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| icon_resource | object | | | +| icon_type | number | | | + +`data.item.user.vip.avatar_icon.icon_resource` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | + +`data.item.user.vip.label` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| bg_color | string | | | +| bg_style | number | | | +| border_color | string | | | +| img_label_uri_hans | string | | | +| img_label_uri_hans_static | string | | | +| img_label_uri_hant | string | | | +| img_label_uri_hant_static | string | | | +| label_theme | string | | | +| path | string | | | +| text | string | | | +| text_color | string | | | +| use_img_label | boolean | | | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/polymer/web-dynamic/v1/detail/forward/item' \ +--url-query 'id=1100082020923473952' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "item": { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "分享视频", + "text": "分享视频", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "分享视频" + }, + "id_str": "1074491510557245446", + "pub_time": "06月04日", + "user": { + "face": "https://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg", + "face_nft": false, + "mid": 293793435, + "name": "社会易姐QwQ", + "official": { + "desc": "", + "role": 0, + "title": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/4f8f3f1f2d47f0dad84f66aa57acd4409ea46361.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/fe0b83b53e2342b16646f6e7a9370d8a867decdb.webp", + "image_enhance_frame": "https://i0.hdslb.com/bfs/garb/item/127c507ec8448be30cf5f79500ecc6ef2fd32f2c.png", + "n_pid": 2511, + "name": "初音未来13周年", + "pid": 2511 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1770825600000, + "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": "http://i0.hdslb.com/bfs/vip/label_annual.png", + "text": "年度大会员", + "text_color": "#FFFFFF", + "use_img_label": true + }, + "nickname_color": "#FB7299", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 1640793600, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + } + } + }, + "message": "0", + "ttl": 1 +} +``` +</details> + +<!-- Generated by json-apidoc-gen @ 2025-08-12T08:52:29.430524983Z --> diff --git a/bb-api-collect/docs/dynamic/dynamic_enum.md b/bb-api-collect/docs/dynamic/dynamic_enum.md new file mode 100644 index 0000000000..6e2fa5bba6 --- /dev/null +++ b/bb-api-collect/docs/dynamic/dynamic_enum.md @@ -0,0 +1,240 @@ +# 动态类型对照 + +## 动态类型 + +| 类型 | 说明 | comment_id_str | comment_type |rid_str| 示例 | +| --- | --- | --- | --- | --- | --- | +| DYNAMIC_TYPE_NONE | 无效动态 |||| [716510857084796964](https://t.bilibili.com/716510857084796964) | +| DYNAMIC_TYPE_FORWARD | 动态转发 |动态本身id|17||| +| DYNAMIC_TYPE_AV | 投稿视频 |视频AV号| 1 |视频AV号|| +| DYNAMIC_TYPE_PGC | 剧集(番剧、电影、纪录片) |剧集分集AV号| 1 |剧集分集EP号|| +| DYNAMIC_TYPE_COURSES | ||| || +| DYNAMIC_TYPE_WORD | 纯文字动态 |动态本身id|17|| [718377531474968613](https://t.bilibili.com/718377531474968613) | +| DYNAMIC_TYPE_DRAW | 带图动态 |相簿id|11|相簿id| [718384798557536290](https://t.bilibili.com/718384798557536290) | +| DYNAMIC_TYPE_ARTICLE | 投稿专栏 |专栏cv号|12|专栏cv号| [718372214316990512](https://t.bilibili.com/718372214316990512) | +| DYNAMIC_TYPE_MUSIC | 音乐 | 音频au号 | 14 | 音频au号 | [128788657410273954](https://t.bilibili.com/128788657410273954) | +| DYNAMIC_TYPE_COMMON_SQUARE | 装扮<br/>剧集点评<br/>普通分享 ||17|| [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 | 直播间分享 |动态本身id||直播间id| [216042859353895488](https://t.bilibili.com/216042859353895488) | +| DYNAMIC_TYPE_MEDIALIST | 收藏夹 |收藏夹ml号|19|收藏夹ml号| [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 | 直播开播 |动态本身id|17|live_id| [718371505648435205](https://t.bilibili.com/718371505648435205) | +| DYNAMIC_TYPE_BANNER | ||| || +| DYNAMIC_TYPE_UGC_SEASON | 合集更新 |视频AV号|1|视频AV号| [718390979031203873](https://t.bilibili.com/718390979031203873) | +| DYNAMIC_TYPE_SUBSCRIPTION_NEW | ||| || + +## 富文本节点类型 + +参见 [图文富文本节点类型](../opus/rich_text_nodes.md#富文本节点类型) + +## 作者类型 + +| 类型 | 说明 | 示例 | +|------------------------|------|-----| +| 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_TYPE_UPOWER_LOTTERY | 充电专属抽奖 | | + +## + +| 类型 | 说明 | 示例 | +|-------------------------------|-----|-----| +| 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 | | | +| MAJOR_TYPE_UPOWER_COMMON | 充电相关 | [1087983622038749191](https://t.bilibili.com/1087983622038749191) | + +## + +| 类型 | 说明 | 示例 | +|-----------------|-----|-----| +| 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 | | | diff --git a/bb-api-collect/docs/dynamic/get_dynamic_detail.md b/bb-api-collect/docs/dynamic/get_dynamic_detail.md new file mode 100644 index 0000000000..245712216c --- /dev/null +++ b/bb-api-collect/docs/dynamic/get_dynamic_detail.md @@ -0,0 +1,538 @@ +# 特定动态卡片信息 + +## 获取特定动态卡片信息 + +> https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/get_dynamic_detail + +*请求方法: GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------ | ---- | ---------- | ------ | -------- | +| dynamic_id | id | 动态id | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | number | 返回值 | 0: 成功<br />4128001: 请求数据发生错误,请刷新或稍后重试 | +| data | object | 信息本体 | 失败时为 `null` | +| message | string | 错误信息 | 成功时为 `0` | +| ttl | number | `1` | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----- | ---------- | ------------ | +| card | object | 动态卡片内容 | 当动态不存在/删除时不返回此项 | + +`data`中的`card`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---- | +| activity_infos | obj | 该条动态参与的活动 |当此条动态没有参与任何活动时不显示此项 | +| card | str | 动态详细信息 | 会跟随此动态类型不同发生一定的变化,评论数、点赞数等相关信息参考`desc`字段, 详细可见 [动态详细信息字段](card_info.md) | +| desc | obj | 动态相关信息 | 会跟随此动态类型不同发生一定的变化,详细信息(例如动态描述等)参考`card`字段 | +| display | obj | 动态部分的可操作项 | 会随着动态类型发生变化,主要用于显示动态 | +| extend_json | str | 动态扩展项 | 会随着动态类型发生变化 | + +**示例:** + +获取`哔哩哔哩弹幕网`的动态id为`507420325550127049`动态 + +```shell +curl -G 'https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/get_dynamic_detail' \ +--data-urlencode 'dynamic_id=507420325550127049' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "card": { + "desc": { + "uid": 8047632, + "type": 8, + "rid": 204774719, + "acl": 0, + "view": 0, + "repost": 0, + "comment": 0, + "like": 0, + "is_liked": 0, + "dynamic_id": 507420325550127040, + "timestamp": 1616981401, + "pre_dy_id": 0, + "orig_dy_id": 0, + "orig_type": 0, + "user_profile": { + "info": { + "uid": 8047632, + "uname": "哔哩哔哩弹幕网", + "face": "https://i0.hdslb.com/bfs/face/0c84b9f4ad546d3f20324809d45fc439a2a8ddab.jpg" + }, + "card": { + "official_verify": { + "type": -1 + } + }, + "vip": { + "vipType": 2, + "vipDueDate": 1924963200000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "http://i0.hdslb.com/bfs/vip/label_annual.png", + "text": "十年大会员", + "label_theme": "ten_annual_vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299", + "role": 7, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "rank": "10000", + "sign": "哔哩哔哩 干杯 ( ゜- ゜)つロ", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": "" + } + }, + "spec_type": 0, + "uid_type": 1, + "stype": 0, + "r_type": 1, + "inner_id": 0, + "status": 1, + "dynamic_id_str": "507420325550127049", + "pre_dy_id_str": "0", + "orig_dy_id_str": "0", + "rid_str": "204774719", + "origin": null, + "bvid": "BV1Dh411S7sS", + "previous": null + }, + "card": "{\"aid\":204774719,\"cid\":316514988,\"ctime\":1616981401,\"desc\":\"2021年3月29日9:30(北京时间),B站在中国香港港交所成功挂牌二次上市。欢迎来到bilibili这座乐园,和超过2亿中国年轻人一起表达自我、拥抱世界。\",\"dimension\":{\"height\":1080,\"rotate\":0,\"width\":1920},\"duration\":290,\"dynamic\":\"\",\"first_frame\":\"\",\"jump_url\":\"bilibili://video/204774719/?page=1\\u0026player_width=1920\\u0026player_height=1080\\u0026player_rotate=0\",\"owner\":{\"face\":\"https://i0.hdslb.com/bfs/face/0c84b9f4ad546d3f20324809d45fc439a2a8ddab.jpg\",\"mid\":8047632,\"name\":\"哔哩哔哩弹幕网\"},\"pic\":\"http://i0.hdslb.com/bfs/archive/bcbcac6560268ef9cbe59fbf759ac28adf5e0432.jpg\",\"pubdate\":1616981400,\"short_link_v2\":\"\",\"stat\":{\"aid\":204774719,\"coin\":9016,\"danmaku\":742,\"dislike\":0,\"favorite\":5463,\"like\":32802,\"reply\":1603,\"share\":2517,\"view\":278278},\"state\":0,\"tid\":207,\"title\":\"欢迎来到2亿年轻人的乐园——bilibili 回香港上市啦!\",\"tname\":\"财经商业\",\"videos\":1}", + "extend_json": "{\"from\":{\"from\":\"\",\"emoji_type\":1},\"ctrl\":null,\"lott\":null}", + "display": { + "origin": null, + "usr_action_txt": "投稿了视频", + "relation": null, + "live_info": null, + "emoji_info": null, + "highlight": null + } + } + } +} +``` + +</details> + +## 最近更新UP主列表 + +> https://api.bilibili.com/x/polymer/web-dynamic/v1/portal + +*请求方式:GET* + +*认证方式:Cookie(SESSDATA) 和 Access_Token* + +**json回复:** + +*根对象* + +| 字段 | 类型 | 内容 | 备注 | +| ------- | --- | ---- | ---- | +| code | num | 返回值 | 0:成功 | +| data | obj | 信息本体 | | +| message | str | 错误信息 | 默认为0 | +| ttl | int | 1 | 默认为1 | + +`data`对象 + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | ---------- | --- | +| live_users | null | 不明 | | +| my_info | obj | 个人关注的一些信息 | | +| up_list | array | 最近更新的up主列表 | | + +`my_info`对象 + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | --- | ----------- | ---- | +| dyns | int | 个人动态 | | +| face | str | 头像 | 图像地址 | +| face_nft | int | 不明 | | +| follower | int | 粉丝数量 | | +| following | int | 我的关注 | | +| level_info | obj | 本人等级内容 | | +| mid | int | 账户mid | | +| name | str | 账户名称 | | +| offcial | obj | 认证信息 | | +| space_bg | str | 账户个人中心的背景横幅 | 图像地址 | +| vip | obj | vip信息 | | + +`my_info`中的`level_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | --- | ---- | ---------- | +| current_level | num | 当前等级 | 0-6级 | +| current_min | num | 0 | | +| current_exp | num | 0 | | +| next_exp | num | 0 | | + +`my_info`中的`Official`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | --- | ---- | ------------------------------------- | +| role | num | 认证类型 | 见[用户认证类型一览](../user/official_role.md) | +| title | str | 认证信息 | 无为空 | +| desc | str | 认证备注 | 无为空 | +| type | num | 是否认证 | -1:无<br />0:认证 | + +`my_info`中的`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 | 电视大会员支付类型 | | + +`vip`中的`label`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------------- | ---- | -------- | ---------------------------------------------------------------------------------------------------------------------------- | +| path | str | 空 | 作用尚不明确 | +| text | str | 会员类型文案 | `大会员` `年度大会员` `十年大会员` `百年大会员` `最强绿鲤鱼` | +| label_theme | str | 会员标签 | vip:大会员<br />annual_vip:年度大会员<br />ten_annual_vip:十年大会员<br />hundred_annual_vip:百年大会员<br/>fools_day_hundred_annual_vip:最强绿鲤鱼 | +| text_color | str | 会员标签 | | +| bg_style | num | 1 | | +| bg_color | str | 会员标签背景颜色 | 颜色码,一般为`#FB7299`,曾用于愚人节改变大会员配色 | +| border_color | str | 会员标签边框颜色 | 未使用 | +| use_img_label | bool | `true` | | +| img_label_uri_hans | str | `空串` | | +| img_label_uri_hant | str | `空串` | | +| img_label_uri_hans_static | str | 大会员牌子图片 | 简体版 | +| img_label_uri_hant_static | str | 大会员牌子图片 | 繁体版 | + +`data`中的`up_list`数组对象 + +| 字段 | 属性 | 内容 | 备注 | +| ----------------- | ---- | --------- | --- | +| face | str | UP主头像 | | +| has_update | bool | 最近更新是否更新? | | +| is_reserve_recall | bool | 不明 | | +| mid | int | UP主mid | | +| uname | str | up主昵称 | | + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "live_users": null, + "my_info": { + "dyns": 67, + "face": "http://i0.hdslb.com/bfs/face/44253f4e588d72d4c10dde495752142b588455af.jpg", + "face_nft": 0, + "follower": 15, + "following": 77, + "level_info": { + "current_exp": 23846, + "current_level": 5, + "current_min": 10800, + "level_up": -62135596800, + "next_exp": 28800 + }, + "mid": 108534711, + "name": "CiaoMyTime", + "official": { + "desc": "", + "role": 0, + "title": "", + "type": -1 + }, + "space_bg": "http://i1.hdslb.com/bfs/space/aea2dd7b8894ce31d578d4fad6a7188c7b49cb2f.jpg", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1670256000000, + "label": { + "bg_color": "#FB7299", + "bg_style": 1, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/3788b674c69072f1ee252b79a31ecc8c43af3039.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/jwXBWRVwa5.png", + "label_theme": "vip", + "path": "", + "text": "大会员", + "text_color": "#FFFFFF", + "use_img_label": true + }, + "nickname_color": "", + "role": 1, + "status": 1, + "theme_type": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 1, + "vip_pay_type": 0 + } + }, + "up_list": [ + { + "face": "https://i2.hdslb.com/bfs/face/09a47992c9cb08f81effede594ddf014f83047fe.jpg", + "has_update": true, + "is_reserve_recall": false, + "mid": 15135791, + "uname": "东北大学张引" + }, + { + "face": "https://i1.hdslb.com/bfs/face/a83b296101bb36a6f1dacb8fdfa74a57a2c29445.jpg", + "has_update": true, + "is_reserve_recall": false, + "mid": 1856528671, + "uname": "陆鳐LuLu" + }, + { + "face": "https://i0.hdslb.com/bfs/face/60ec600cc9d84c74c8220ab41ce49bacfdc0895c.jpg", + "has_update": true, + "is_reserve_recall": false, + "mid": 39180492, + "uname": "蒸気火鸡" + }, + { + "face": "https://i0.hdslb.com/bfs/face/986a9f29848d17b39a99e41557d56dcd1091a3a9.jpg", + "has_update": true, + "is_reserve_recall": false, + "mid": 2142762, + "uname": "老戴在此" + }, + { + "face": "https://i1.hdslb.com/bfs/face/475f3c05ea494a26f5dd91b277f48b136ae63021.jpg", + "has_update": true, + "is_reserve_recall": false, + "mid": 431313625, + "uname": "小蓝和他的朋友日常号" + }, + { + "face": "https://i1.hdslb.com/bfs/face/bafb36d5726f8062e578474095abb0e906fec163.jpg", + "has_update": true, + "is_reserve_recall": false, + "mid": 233114659, + "uname": "碧蓝航线" + }, + { + "face": "https://i0.hdslb.com/bfs/face/39d23f3c5dd2c96fc35db5c2a98f4a8ff73a2d46.jpg", + "has_update": true, + "is_reserve_recall": false, + "mid": 27534330, + "uname": "崩坏3第一偶像爱酱" + }, + { + "face": "http://i2.hdslb.com/bfs/face/f119348814f30c6bbbcc60bd63c12b8215d19d2f.jpg", + "has_update": true, + "is_reserve_recall": false, + "mid": 524704055, + "uname": "大庆赶海" + }, + { + "face": "https://i0.hdslb.com/bfs/face/c4340d477356ba108098ba9a566e7ce4a54e0936.jpg", + "has_update": true, + "is_reserve_recall": false, + "mid": 194326389, + "uname": "兮子cc" + }, + { + "face": "https://i2.hdslb.com/bfs/face/0455b74f73d6a83eef2d6dfbdb4ae2beda42a3ce.jpg", + "has_update": true, + "is_reserve_recall": false, + "mid": 476833439, + "uname": "盾之勇者成名录" + }, + { + "face": "https://i0.hdslb.com/bfs/face/7c6cdd77937d4bbd2171241fe530e18c0c5bc58e.jpg", + "has_update": true, + "is_reserve_recall": false, + "mid": 492840942, + "uname": "云视听小电视-TV" + }, + { + "face": "https://i0.hdslb.com/bfs/face/b14881845b777d925876f24cb46b1dc1ad5a0e27.jpg", + "has_update": true, + "is_reserve_recall": false, + "mid": 1636034895, + "uname": "绝区零" + }, + { + "face": "http://i1.hdslb.com/bfs/face/3b933fe3c47976dd29f30e3a4f7f2bdfd99e8b08.jpg", + "has_update": true, + "is_reserve_recall": false, + "mid": 603028270, + "uname": "乃木坂46官方" + }, + { + "face": "https://i2.hdslb.com/bfs/face/76ec72b2a530f2f24209c98b5690ef7b536040cf.jpg", + "has_update": true, + "is_reserve_recall": false, + "mid": 5992670, + "uname": "云之幻" + }, + { + "face": "https://i1.hdslb.com/bfs/face/9ca9ea42fa75d9a651b354a95e8e39f48d8c30d2.jpg", + "has_update": true, + "is_reserve_recall": false, + "mid": 299359111, + "uname": "月圆之夜" + }, + { + "face": "https://i1.hdslb.com/bfs/face/c8c0adce728125167fe44371d451b3dc19a84506.jpg", + "has_update": false, + "is_reserve_recall": false, + "mid": 79983517, + "uname": "一唐老狮一" + }, + { + "face": "https://i0.hdslb.com/bfs/face/68b4b212d9738c40d8a6a77beb65a6dd4415f81b.jpg", + "has_update": false, + "is_reserve_recall": false, + "mid": 1861940979, + "uname": "保卫萝卜" + }, + { + "face": "https://i2.hdslb.com/bfs/face/85bab2a17646ccf442d28549e7216fd65c6adeb7.jpg", + "has_update": false, + "is_reserve_recall": false, + "mid": 2162, + "uname": "GPBeta" + }, + { + "face": "https://i1.hdslb.com/bfs/face/7a41310afc08381ad0451bee8ea07f15fcc411bd.jpg", + "has_update": false, + "is_reserve_recall": false, + "mid": 508963009, + "uname": "HiiroVTuber" + }, + { + "face": "https://i1.hdslb.com/bfs/face/b085d34fd9d2cd44641ab648cc96e7a3068eb811.jpg", + "has_update": false, + "is_reserve_recall": false, + "mid": 396848107, + "uname": "不愧是姐姐大人" + }, + { + "face": "https://i0.hdslb.com/bfs/face/3f1496f48a5eb840a974fef0fd7db7a3f225fbe7.jpg", + "has_update": false, + "is_reserve_recall": false, + "mid": 80304, + "uname": "亚食人" + }, + { + "face": "https://i2.hdslb.com/bfs/face/a7716fec14658ef7365b538fdce0d86eb6123ed4.jpg", + "has_update": false, + "is_reserve_recall": false, + "mid": 401742377, + "uname": "原神" + }, + { + "face": "https://i0.hdslb.com/bfs/face/81d5201d6095e3802f14094a6906d1a114bc74c7.jpg", + "has_update": false, + "is_reserve_recall": false, + "mid": 11131476, + "uname": "绫人太太啊" + }, + { + "face": "https://i0.hdslb.com/bfs/face/7d72e58d0ad1b401e4c59960c4b1795efbc57c3a.jpg", + "has_update": false, + "is_reserve_recall": false, + "mid": 409524162, + "uname": "一线码农聊技术" + }, + { + "face": "https://i0.hdslb.com/bfs/face/5634900a3167310fcd0c6b1102ffc308c68aedd1.jpg", + "has_update": false, + "is_reserve_recall": false, + "mid": 260054391, + "uname": "CHeems的日常" + }, + { + "face": "https://i2.hdslb.com/bfs/face/81a4c852925b873f42c4971c836a67ea9dd2ef41.jpg", + "has_update": false, + "is_reserve_recall": false, + "mid": 361469957, + "uname": "软件工艺师" + }, + { + "face": "https://i2.hdslb.com/bfs/face/99e9eb37657f67f547b546b72592d70ab8ce1a4b.jpg", + "has_update": false, + "is_reserve_recall": false, + "mid": 41059757, + "uname": "刻刻帝TokisakiKuru" + }, + { + "face": "https://i1.hdslb.com/bfs/face/affbd5780e44ec1340f60c5283e81cbee2d9a21a.jpg", + "has_update": false, + "is_reserve_recall": false, + "mid": 156785512, + "uname": "Swety_Core" + }, + { + "face": "http://i0.hdslb.com/bfs/face/f576c8bd9eb4ec7f7776880581bea2d6c53d1b65.jpg", + "has_update": false, + "is_reserve_recall": false, + "mid": 298683153, + "uname": "猫和老鼠官方手游" + }, + { + "face": "https://i1.hdslb.com/bfs/face/5161d6bd003c24065c0d0ab2ae2ce7f37f0f607b.jpg", + "has_update": false, + "is_reserve_recall": false, + "mid": 159440647, + "uname": "Uki----" + } + ] + } +} +``` + +</details> diff --git a/bb-api-collect/docs/dynamic/nav.md b/bb-api-collect/docs/dynamic/nav.md new file mode 100644 index 0000000000..85a2c243c6 --- /dev/null +++ b/bb-api-collect/docs/dynamic/nav.md @@ -0,0 +1,1167 @@ +# 获取导航栏动态 + +## 获取导航栏动态列表 + +> https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/nav + +*请求方式: GET* + +认证方式:Cookie(SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------------- | ---- | ---------- | ------ | ----------------------- | +| update_baseline | num | 更新基线 | 非必要 | 获取新动态时使用 | +| offset | num | 分页偏移量 | 非必要 | 翻页时使用 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | -------------------------- | +| code | num | 返回值 | 0: 成功 <br />-101: 未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ----- | ---------------------------- | -------------------------------------------------- | +| has_more | bool | 是否有更多数据 | | +| items | array | 数据数组 | | +| offset | str | 偏移量 | 等于`items`中最后一条记录的id<br/>获取下一页时使用 | +| update_baseline | str | 更新基线 | 等于`items`中第一条记录的id_str | +| update_num | num | 本次获取获取到了多少条新动态 | 在更新基线以上的动态条数 | + +`data`对象中`items`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------- | ---------------------------- | +| author | obj | UP主 | 参考 [MODULE_TYPE_AUTHOR](../opus/features.md#module-type-author) | +| cover | str | 封面URL | | +| id_str | str | 动态id | | +| pub_time | str | 发布时间 | 文字表述的相对时间 | +| rid | num | 关联id | 视频即aid | +| title | str | 标题 | | +| type | num | 动态类型 | 8: 视频 | +| visible | bool | 是否可见 | true:可见<br/>false:不可见 | + +**示例:** + +获取导航栏动态列表 + +```shell +curl "https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/nav" \ + -b "SESSDATA=xxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "has_more": true, + "items": [ + { + "author": { + "face": "https://i1.hdslb.com/bfs/face/2b9ee4a9c99f1006f3c800c1317f7850ad6f3d0d.jpg", + "jump_url": "//space.bilibili.com/485703766/dynamic", + "mid": 485703766, + "name": "英伟达GeForce", + "official": { + "desc": "", + "role": 3, + "title": "英伟达GeForce官方账号", + "type": 1 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 2000563200000, + "label": { + "bg_color": "#FB7299", + "bg_style": 1, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/adb599797dd171e2d3d6d012f448b49679258344.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/sGu57N6pgK.png", + "label_theme": "ten_annual_vip", + "path": "", + "text": "十年大会员", + "text_color": "#FFFFFF", + "use_img_label": true + }, + "nickname_color": "#FB7299", + "role": 7, + "status": 1, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 1 + } + }, + "cover": "http://i2.hdslb.com/bfs/archive/d38b239af580eb199b4bbe55d2388cb603f6e917.jpg", + "id_str": "954636836111646759", + "jump_url": "//www.bilibili.com/video/BV181421k7bu/", + "pub_time": "1小时前", + "rid": 1556082150, + "title": "《异环》首曝丨即将支持 NVIDIA DLSS & 光线追踪技术", + "type": 8, + "visible": true + }, + { + "author": { + "face": "https://i1.hdslb.com/bfs/face/7cabb9c9576b4be8d52004d8a3a5450e5e062070.jpg", + "jump_url": "//space.bilibili.com/403748305/dynamic", + "mid": 403748305, + "name": "BML制作指挥部", + "official": { + "desc": "", + "role": 3, + "title": "Bilibili Macro Link官方账号", + "type": 1 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1750176000000, + "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", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "cover": "http://i2.hdslb.com/bfs/archive/a220f26856924287c9dc4fa59c67ff38a2fcd20c.jpg", + "id_str": "954616624230433048", + "jump_url": "//www.bilibili.com/video/BV1RW421R7pE/", + "pub_time": "2小时前", + "rid": 1856122369, + "title": "【夏色祭×可波】《カタオモイ》请感受这份传达给你的心意【BML2024单品】", + "type": 8, + "visible": true + }, + { + "author": { + "face": "https://i1.hdslb.com/bfs/face/7cabb9c9576b4be8d52004d8a3a5450e5e062070.jpg", + "jump_url": "//space.bilibili.com/403748305/dynamic", + "mid": 403748305, + "name": "BML制作指挥部", + "official": { + "desc": "", + "role": 3, + "title": "Bilibili Macro Link官方账号", + "type": 1 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1750176000000, + "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", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "cover": "http://i1.hdslb.com/bfs/archive/1b7e4eaf6696038bb96ff38c6d13a6b3778d6a7c.jpg", + "id_str": "954616624230432996", + "jump_url": "//www.bilibili.com/video/BV15Z421u7MX/", + "pub_time": "2小时前", + "rid": 1156047704, + "title": "Ready for my show!中日16位实力舞见高燃开场《唱》【BML2024单品】", + "type": 8, + "visible": true + }, + { + "author": { + "face": "https://i1.hdslb.com/bfs/face/7cabb9c9576b4be8d52004d8a3a5450e5e062070.jpg", + "jump_url": "//space.bilibili.com/403748305/dynamic", + "mid": 403748305, + "name": "BML制作指挥部", + "official": { + "desc": "", + "role": 3, + "title": "Bilibili Macro Link官方账号", + "type": 1 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1750176000000, + "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", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "cover": "http://i1.hdslb.com/bfs/archive/5f22e930d0683b5e8d7a81f75b48fdb0c3a0f2e7.jpg", + "id_str": "954616624229384275", + "jump_url": "//www.bilibili.com/video/BV1hz421q7xP/", + "pub_time": "2小时前", + "rid": 1356132445, + "title": "阿梓×尔东和小明倾情演出《暁の車》带你重温高达经典旋律【BML2024单品】", + "type": 8, + "visible": true + }, + { + "author": { + "face": "https://i1.hdslb.com/bfs/face/7cabb9c9576b4be8d52004d8a3a5450e5e062070.jpg", + "jump_url": "//space.bilibili.com/403748305/dynamic", + "mid": 403748305, + "name": "BML制作指挥部", + "official": { + "desc": "", + "role": 3, + "title": "Bilibili Macro Link官方账号", + "type": 1 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1750176000000, + "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", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "cover": "http://i2.hdslb.com/bfs/archive/04b46154e833ea1349c3302f9b9c188a45b016e9.jpg", + "id_str": "954616624228335667", + "jump_url": "//www.bilibili.com/video/BV1LS421R7sr/", + "pub_time": "2小时前", + "rid": 1506089543, + "title": "【Vox Akuma】声之恶魔低音爵士,深情演绎世界名曲【BML2024单品】", + "type": 8, + "visible": true + }, + { + "author": { + "face": "https://i1.hdslb.com/bfs/face/7cabb9c9576b4be8d52004d8a3a5450e5e062070.jpg", + "jump_url": "//space.bilibili.com/403748305/dynamic", + "mid": 403748305, + "name": "BML制作指挥部", + "official": { + "desc": "", + "role": 3, + "title": "Bilibili Macro Link官方账号", + "type": 1 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1750176000000, + "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", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "cover": "http://i0.hdslb.com/bfs/archive/819d73ca191235e89a03c62889073d526b552fc2.jpg", + "id_str": "954616624033300612", + "jump_url": "//www.bilibili.com/video/BV1qM4m127wD/", + "pub_time": "2小时前", + "rid": 1306194854, + "title": "【RAB】全 部 逮 捕!萝 莉 控 的 末 日【BML2024单品】", + "type": 8, + "visible": true + }, + { + "author": { + "face": "https://i1.hdslb.com/bfs/face/7cabb9c9576b4be8d52004d8a3a5450e5e062070.jpg", + "jump_url": "//space.bilibili.com/403748305/dynamic", + "mid": 403748305, + "name": "BML制作指挥部", + "official": { + "desc": "", + "role": 3, + "title": "Bilibili Macro Link官方账号", + "type": 1 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1750176000000, + "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", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "cover": "http://i2.hdslb.com/bfs/archive/01dd21a65db17705479ee4ee550a79856847264e.jpg", + "id_str": "954616624020717623", + "jump_url": "//www.bilibili.com/video/BV1rZ421K7yT/", + "pub_time": "2小时前", + "rid": 1156076206, + "title": "【可波×夏色祭】对你一见钟情啦!《5201314》开启绝赞告白【BML2024单品】", + "type": 8, + "visible": true + }, + { + "author": { + "face": "https://i1.hdslb.com/bfs/face/7cabb9c9576b4be8d52004d8a3a5450e5e062070.jpg", + "jump_url": "//space.bilibili.com/403748305/dynamic", + "mid": 403748305, + "name": "BML制作指挥部", + "official": { + "desc": "", + "role": 3, + "title": "Bilibili Macro Link官方账号", + "type": 1 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1750176000000, + "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", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "cover": "http://i1.hdslb.com/bfs/archive/d79b28afc3273d5edb211d03ddc70c45999d57f7.jpg", + "fold": { + "ids": [ + "954616624019669009" + ], + "statement": "展开1条相关动态", + "type": 3, + "users": [] + }, + "id_str": "954616624019669032", + "jump_url": "//www.bilibili.com/video/BV1oE421c7XV/", + "pub_time": "2小时前", + "rid": 1656233700, + "title": "【洛天依】来自2024的《霜雪千年》还记否这一曲喜悲霜雪【BML2024单品】", + "type": 8, + "visible": true + }, + { + "author": { + "face": "https://i1.hdslb.com/bfs/face/93b809e050e639c9d8e8e379da96a4c2216ae755.jpg", + "jump_url": "//space.bilibili.com/36081646/dynamic", + "mid": 36081646, + "name": "洛天依", + "official": { + "desc": "", + "role": 2, + "title": "2023年度原创音乐、洛天依官方账号", + "type": 0 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1764777600000, + "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", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "cover": "http://i1.hdslb.com/bfs/archive/d79b28afc3273d5edb211d03ddc70c45999d57f7.jpg", + "id_str": "954616624019669009", + "jump_url": "//www.bilibili.com/video/BV1oE421c7XV/", + "pub_time": "2小时前", + "rid": 1656233700, + "title": "【洛天依】来自2024的《霜雪千年》还记否这一曲喜悲霜雪【BML2024单品】", + "type": 8, + "visible": false + }, + { + "author": { + "face": "https://i1.hdslb.com/bfs/face/7cabb9c9576b4be8d52004d8a3a5450e5e062070.jpg", + "jump_url": "//space.bilibili.com/403748305/dynamic", + "mid": 403748305, + "name": "BML制作指挥部", + "official": { + "desc": "", + "role": 3, + "title": "Bilibili Macro Link官方账号", + "type": 1 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1750176000000, + "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", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "cover": "http://i1.hdslb.com/bfs/archive/cbbbb6e35c7680261a8a1fb3f582e04de14cbb50.jpg", + "id_str": "954616624002891844", + "jump_url": "//www.bilibili.com/video/BV1Fb421H7YQ/", + "pub_time": "2小时前", + "rid": 1806140865, + "title": "【ChiliChill】《我的悲伤是水做的》,描绘雨天的淡蓝色心情【BML2024单品】", + "type": 8, + "visible": true + }, + { + "author": { + "face": "https://i1.hdslb.com/bfs/face/7cabb9c9576b4be8d52004d8a3a5450e5e062070.jpg", + "jump_url": "//space.bilibili.com/403748305/dynamic", + "mid": 403748305, + "name": "BML制作指挥部", + "official": { + "desc": "", + "role": 3, + "title": "Bilibili Macro Link官方账号", + "type": 1 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1750176000000, + "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", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "cover": "http://i1.hdslb.com/bfs/archive/b1f8744db9bad8a4a89bd9fa3fab0d128b347edb.jpg", + "id_str": "954616623998697505", + "jump_url": "//www.bilibili.com/video/BV12m421g759/", + "pub_time": "2小时前", + "rid": 1606234911, + "title": "成为挣脱《Cage》的小鸟,露米Lumi深情吟唱人类希望之歌【BML2024单品】", + "type": 8, + "visible": true + }, + { + "author": { + "face": "https://i1.hdslb.com/bfs/face/7cabb9c9576b4be8d52004d8a3a5450e5e062070.jpg", + "jump_url": "//space.bilibili.com/403748305/dynamic", + "mid": 403748305, + "name": "BML制作指挥部", + "official": { + "desc": "", + "role": 3, + "title": "Bilibili Macro Link官方账号", + "type": 1 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1750176000000, + "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", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "cover": "http://i2.hdslb.com/bfs/archive/52e82dc68f3cbbb598d27437c33e996718e07924.jpg", + "id_str": "954616623995552002", + "jump_url": "//www.bilibili.com/video/BV181421k74U/", + "pub_time": "2小时前", + "rid": 1556081716, + "title": "型月组曲优雅串烧《若能看到明月》🌙🌙🌙【BML2024单品】", + "type": 8, + "visible": true + }, + { + "author": { + "face": "https://i1.hdslb.com/bfs/face/7cabb9c9576b4be8d52004d8a3a5450e5e062070.jpg", + "jump_url": "//space.bilibili.com/403748305/dynamic", + "mid": 403748305, + "name": "BML制作指挥部", + "official": { + "desc": "", + "role": 3, + "title": "Bilibili Macro Link官方账号", + "type": 1 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1750176000000, + "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", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "cover": "http://i0.hdslb.com/bfs/archive/8558fe6746c43182b25f6a590f47b9673d47ba67.jpg", + "id_str": "954616623994503209", + "jump_url": "//www.bilibili.com/video/BV1jW421d7ce/", + "pub_time": "2小时前", + "rid": 1856192192, + "title": "Finana Ryugu超甜演绎童年回忆《プレパレード》最清纯的恋爱预演~【BML2024单品】", + "type": 8, + "visible": true + }, + { + "author": { + "face": "https://i1.hdslb.com/bfs/face/7cabb9c9576b4be8d52004d8a3a5450e5e062070.jpg", + "jump_url": "//space.bilibili.com/403748305/dynamic", + "mid": 403748305, + "name": "BML制作指挥部", + "official": { + "desc": "", + "role": 3, + "title": "Bilibili Macro Link官方账号", + "type": 1 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1750176000000, + "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", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "cover": "http://i2.hdslb.com/bfs/archive/1ebd8cbd38eb9db9451df9978b20bee445d8fea0.jpg", + "id_str": "954616623993454708", + "jump_url": "//www.bilibili.com/video/BV1cw4m1Y7Zs/", + "pub_time": "2小时前", + "rid": 1106145687, + "title": "元气补给站《MORE!JUMP!MORE!》在BML舞台起跳!【BML2024单品】", + "type": 8, + "visible": true + }, + { + "author": { + "face": "https://i1.hdslb.com/bfs/face/7cabb9c9576b4be8d52004d8a3a5450e5e062070.jpg", + "jump_url": "//space.bilibili.com/403748305/dynamic", + "mid": 403748305, + "name": "BML制作指挥部", + "official": { + "desc": "", + "role": 3, + "title": "Bilibili Macro Link官方账号", + "type": 1 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1750176000000, + "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", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "cover": "http://i1.hdslb.com/bfs/archive/bc1de2b7e27a5385e3e913fc552b86b744b49fb8.jpg", + "id_str": "954616623990308904", + "jump_url": "//www.bilibili.com/video/BV1QH4y1w7hC/", + "pub_time": "2小时前", + "rid": 1056107813, + "title": "【星瞳】华丽演绎《迷宮バタフライ》🦋一曲重温童年之梦【BML2024单品】", + "type": 8, + "visible": true + }, + { + "author": { + "face": "https://i1.hdslb.com/bfs/face/7cabb9c9576b4be8d52004d8a3a5450e5e062070.jpg", + "jump_url": "//space.bilibili.com/403748305/dynamic", + "mid": 403748305, + "name": "BML制作指挥部", + "official": { + "desc": "", + "role": 3, + "title": "Bilibili Macro Link官方账号", + "type": 1 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1750176000000, + "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", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "cover": "http://i0.hdslb.com/bfs/archive/63617f9210ab2e996f75e8e2fb46c5dc73aeed35.jpg", + "id_str": "954616623980871832", + "jump_url": "//www.bilibili.com/video/BV1L1421b7XJ/", + "pub_time": "2小时前", + "rid": 1556117158, + "title": "奏响《葬送的破阵曲》,按捺不住战斗的心了!【BML2024单品】", + "type": 8, + "visible": true + }, + { + "author": { + "face": "https://i1.hdslb.com/bfs/face/7cabb9c9576b4be8d52004d8a3a5450e5e062070.jpg", + "jump_url": "//space.bilibili.com/403748305/dynamic", + "mid": 403748305, + "name": "BML制作指挥部", + "official": { + "desc": "", + "role": 3, + "title": "Bilibili Macro Link官方账号", + "type": 1 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1750176000000, + "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", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "cover": "http://i0.hdslb.com/bfs/archive/c3c470e309acef1d8c8f2ce79ed753f9bca50879.jpg", + "id_str": "954616623979823254", + "jump_url": "//www.bilibili.com/video/BV1uy411B7Ca/", + "pub_time": "2小时前", + "rid": 1956028036, + "title": "【猫MEME】转生成只能用MEME讲话的平凡上班族【BML2024单品】", + "type": 8, + "visible": true + }, + { + "author": { + "face": "https://i0.hdslb.com/bfs/face/978ea07f22e54c2e62f01def8e815b59adacc5d0.jpg", + "jump_url": "//space.bilibili.com/407045223/dynamic", + "mid": 407045223, + "name": "二次元的中科院物理所", + "official": { + "desc": "", + "role": 6, + "title": "中国科学院物理研究所官方账号", + "type": 1 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1745769600000, + "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", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 1626364800, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "cover": "http://i1.hdslb.com/bfs/archive/056db2ac79801d853bebcd41c247788d8ccdb795.jpg", + "id_str": "954609313946533894", + "jump_url": "//www.bilibili.com/video/BV1Wz421q7n5/", + "pub_time": "3小时前", + "rid": 1356075945, + "title": "暑期不失约!第六季《科学公开课》震撼来袭!", + "type": 8, + "visible": true + }, + { + "author": { + "face": "https://i0.hdslb.com/bfs/face/7efb679569b2faeff38fa08f6f992fa1ada5e948.webp", + "jump_url": "//space.bilibili.com/686127/dynamic", + "mid": 686127, + "name": "籽岷", + "official": { + "desc": "", + "role": 1, + "title": "2023百大UP主、知名游戏UP主", + "type": 0 + }, + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 4845196800000, + "label": { + "bg_color": "#FB7299", + "bg_style": 1, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/c16005a5b39164b3536cbd45618a5edd597a1c51.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/Pzrd8zmpQD.png", + "label_theme": "hundred_annual_vip", + "path": "", + "text": "百年大会员", + "text_color": "#FFFFFF", + "use_img_label": true + }, + "nickname_color": "#FB7299", + "role": 15, + "status": 1, + "theme_type": 0, + "tv_due_date": 1692288000, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 1 + } + }, + "cover": "http://i1.hdslb.com/bfs/archive/170237c4589a086afd7d62823765de1cc7306555.jpg", + "id_str": "954478850029387784", + "jump_url": "//www.bilibili.com/video/BV1Jz421q7JH/", + "pub_time": "11小时前", + "rid": 1356097140, + "title": "我的世界 冷门原版生物娘化 材质包", + "type": 8, + "visible": true + }, + { + "author": { + "face": "https://i0.hdslb.com/bfs/face/22e6b4f3c9199b6f4397f0d8df916872d677557b.jpg", + "jump_url": "//space.bilibili.com/625267185/dynamic", + "mid": 625267185, + "name": "零度解说", + "official": { + "desc": "", + "role": 0, + "title": "", + "type": -1 + }, + "vip": { + "avatar_icon": { + "icon_resource": {} + }, + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 0, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "role": 0, + "status": 0, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 0, + "vip_pay_type": 0 + } + }, + "cover": "http://i0.hdslb.com/bfs/archive/6f0397b546ba4da15fcd9a2e06cbcc1f68e5545c.jpg", + "id_str": "954376956212674594", + "jump_url": "//www.bilibili.com/video/BV141421b7sf/", + "pub_time": "昨天 20:30", + "rid": 1556122058, + "title": "快速提升上网速度!免费又好用,适用 Windows 10 /11,非常简单!!(2024) | 零度解说", + "type": 8, + "visible": true + } + ], + "offset": "954376956212674594", + "update_baseline": "954659517801431040", + "update_num": 0 + } +} +``` + +</details> diff --git a/bb-api-collect/docs/dynamic/publish.md b/bb-api-collect/docs/dynamic/publish.md new file mode 100644 index 0000000000..a86dbab5d7 --- /dev/null +++ b/bb-api-collect/docs/dynamic/publish.md @@ -0,0 +1,555 @@ +# 发布动态 + +## 为图片动态上传图片 + +> https://api.bilibili.com/x/dynamic/feed/draw/upload_bfs + +*请求方法: POST* + +认证方式: Cookie (SESSDATA) + +注意: 非日常类型像素宽高必须大于 420 + +**正文参数 (multipart/form-data):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | --------------------- | ------ | ---- | +| file_up | file | 需要上传的图片文件 | 必要 | 格式仅支持 `jpg` `png` `gif` | +| category | string | 图片类型 | 不必要 | daily: 日常 (动态) (默认)<br />draw: 绘画 (画友)<br />cos: 摄影 (COSPLAY) | +| biz | string | | 不必要 | `new_dyn` | +| csrf | string | CSRF Token (即 Cookie 中 bili_jct) | 必要 | | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---- | +| code | number | 返回值 | 0: 成功<br />4100001: 参数错误<br />-101: 账号未登录 | +| message | string | 错误信息 | 默认为 `0` | +| data | object | 信息本体 | 成功时为有效信息 | +| ttl | number | `1` | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | -------------- | ---- | +| image_url | string | 已上传图片 URL | | +| image_width | number | 已上传图片宽度 | 像素 | +| image_height | number | 已上传图片高度 | 像素 | +| img_size | number | 已上传图片大小 | k | + +**示例:** + +上传图片 `test.png` 类型为 `日常` + +```shell +curl 'https://api.bilibili.com/x/dynamic/feed/draw/upload_bfs' \ +-F 'file_up=@test.png' \ +-F 'category=daily' \ +-F 'csrf=xxxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "image_url": "http://i0.hdslb.com/bfs/new_dyn/8ad5640045a114b62580614cb512bbc32095498218.png", + "image_width": 73, + "image_height": 71, + "img_size": 6.261 + } +} +``` + +</details> + +## 创建投票 + +> https://api.vc.bilibili.com/vote_svr/v1/vote_svr/create_vote + +*请求方法: POST* + +认证方式: Cookie (SESSDATA) + +注意: `options` 最少两个, 下标 `n` 从 `0` 开始 + +**正文参数 (multipart/form-data):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------------------------- | ---- | ---- | ------ | ---- | +| info[title] | string | 投票标题 | 必要 | | +| info[desc] | string | 投票描述 | 非必要 | 可为空 | +| info[type] | number | 投票类型 | 必要 | 0: 文字投票<br />1: 图片投票 | +| info[choice_cnt] | number | 最多选几项 | 必要 | | +| info[duration] | number | 投票持续秒数 | 必要 | 常用:<br/>三天: 259200<br/>七天: 604800<br/>三十天: 2592000 | +| info[options]\[ n ][desc] | string | 第 n 项选项文字内容 | 必要 | | +| info[options]\[ n ][img_url] | strin | 第 n 项选项投票图片 | 非必要 || +| csrf | string | CSRF Token (即 Cookie 中 bili_jct) | 非必要 | | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | -------------------------------- | +| code | number | 返回值 | 0:成功 <br />5100001: 参数错误 | +| msg | string | 错误信息 | 成功为空 | +| message | string | 错误信息 | 跟上面那个一模一样 | +| data | object | 信息本体 | 仅在正确时既`code=0`时为有效信息 | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | -------------- | ---- | +| vote_id | number | 投票 id | | +| \_gt\_ | number | 0 | | + +**示例:** + +创建一个标题为 `是否自愿开学` 持续七天的纯文本投票 + +```shell +curl -X POST 'https://api.vc.bilibili.com/vote_svr/v1/vote_svr/create_vote' \ +--data-urlencode 'info[title]=是否自愿开学' \ +--data-urlencode 'info[desc]=问卷调查:自愿开学' \ +--data-urlencode 'info[type]=0' \ +--data-urlencode 'info[choice_cnt]=1' \ +--data-urlencode 'info[duration]=604800' \ +--data-urlencode 'info[options][0][desc]=自愿' \ +--data-urlencode 'info[options][1][desc]=不自愿' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "", + "message": "", + "data": { + "vote_id": 4947171, + "_gt_": 0 + } +} +``` + +</details> + +## 发表纯文本动态 + +> https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/create + +*请求方法: POST* + +认证方式: Cookie (SESSDATA) + +**正文参数 (multipart/form-data):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --- | --- | --- | --- | --- | +| dynamic_id | number | 0 | 必要 | | +| type | number | 4 | 必要 | | +| rid | number | 0 | 必要 | | +| content | string | 动态内容 | 必要 | | +| up_choose_comment | number | 0 | 非必要 | | +| up_close_comment | number | 0 | 非必要 | | +| extension | json | 位置信息 | 非必要 | | +| at_uids | string | 动态中 at 到的用户的 uid | 非必要 | 使用逗号`,`分隔 | +| ctrl | array | 特殊格式控制 (如 at 别人时的蓝字体和链接) | 非必要 | | +| csrf_token | string | CSRF Token (即 Cookie 中 bili_jct) | 非必要 | | +| csrf | string | CSRF Token (即 Cookie 中 bili_jct) | 非必要 | | + +`extension` 参数值: + +```jsonc +{ + "emoji_type": 1, + "lbs_cfg": { + "title": "**市", + "poi": "156330200", + "show_title": "**市", + "type": 1, + "address": "**市", + "location": { + "lng": //显示的经度数值, + "lat": //显示的纬度数值 + }, + "distance": 0 + }, + "flag_cfg": {}, + "from_cfg": { + "location": { + "lat": //用户实际纬度数值, + "lng": //用户实际经度数值 + } + } +} +``` + +`ctrl` 数组中的对象: + +| 参数名 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| location | number | 从全文第几个字开始变蓝 | | +| type | number | 1 | 可能 1 代表链接到用户 mid | +| length | number | 这一段变蓝多少字 | | +| data | string | 链接目标 | 被 at 人的 mid | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | number | 返回值 | 0: 成功 | +| message | string | 错误信息 | 成功为空 | +| data | object | 数据本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| result | number | 0 | | +| errmsg | string | 像是服务器日志一样的东西 | | +| dynamic_id | number | 动态 id | | +| create_result | number | 1 | | +| dynamic_id_str | string | 动态 id | 字符串格式 | +| \_gt_ | number | 0 | | + +**示例:** + +<details> +<summary>纯文本:</summary> + +```bash +curl 'https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/create' \ + --data-urlencode 'dynamic_id=0' \ + --data-urlencode 'type=4' \ + --data-urlencode 'rid=0' \ + --data-urlencode 'content=Hello Bug~' \ + --data-urlencode 'up_choose_comment=0' \ + --data-urlencode 'up_close_comment=0' \ + --data-urlencode 'extension={"emoji_type":1,"from":{"emoji_type":1},"flag_cfg":{}}' \ + --data-urlencode 'at_uids=' \ + --data-urlencode 'ctrl=[]' \ + --data-urlencode 'csrf_token=de2731532b4ab96bc8536da948932668' \ + --data-urlencode 'csrf=de2731532b4ab96bc8536da948932668' \ + -b 'SESSDATA=******' +``` + +```json +{ + "code": 0, + "msg": "", + "message": "", + "data": { + "result": 0, + "errmsg": "; Create dynamic:588320531406678918, res:0, result:1; Push create kafka:0; Push create databus:0; Register comment result:0; Add outbox result:1", + "dynamic_id": 588320531406678918, + "create_result": 1, + "dynamic_id_str": "588320531406678918", + "_gt_": 0 + } +} +``` + +</details> + +<details> +<summary>at 两个人:</summary> + +动态正文 +``` +[热词系列_神仙UP]@暮光小猿wzt @社会易姐QwQ +``` + +at_uids +``` +15858903,293793435 +``` + +ctrl +```json +[ + { "location": 11, "type": 1, "length": 9, "data": "15858903" }, + { "location": 20, "type": 1, "length": 9, "data": "293793435" } +] +``` + +命令 +```bash +curl 'https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/create' \ + --data-urlencode 'dynamic_id': '0' \ + --data-urlencode 'type': '4' \ + --data-urlencode 'rid': '0' \ + --data-urlencode 'content': '[热词系列_神仙UP]@暮光小猿wzt @社会易姐QwQ ' \ + --data-urlencode 'up_choose_comment': '0' \ + --data-urlencode 'up_close_comment': '0' \ + --data-urlencode 'extension': '{"emoji_type":1,"from":{"emoji_type":1},"flag_cfg":{}}' \ + --data-urlencode 'at_uids': '15858903,293793435' \ + --data-urlencode 'ctrl': '[{"location":11,"type":1,"length":9,"data":"15858903"},{"location":20,"type":1,"length":9,"data":"293793435"}]' \ + --data-urlencode 'csrf_token': 'de2731532b4ab96bc8536da948932668' \ + --data-urlencode 'csrf': 'de2731532b4ab96bc8536da948932668' \ + -b 'SESSDATA=******' +``` + +</details> + +## 发表复杂动态 + +> https://api.bilibili.com/x/dynamic/feed/create/dyn + +*请求方法:POST* + +认证方式:Cookie (SESSDATA) + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------ | ------ | ---- | +| csrf | string | CSRF Token (即 Cookie 中 bili_jct) | 必要 | | + +**正文参数 (application/json):** + +根对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --- | --- | --- | --- | --- | +| dyn_req | object | 请求本体 | 必要 | | + +`dyn_req` 对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --- | --- | --- | --- | --- | +| attach_card | object | 特殊卡片 | 非必要 | 如直播预约等 | +| content | object | 动态内容 | 非必要 | | +| meta | object | 元信息 | 非必要 | 大概是来源信息 | +| scene | number | 动态类型? | 必要 | 纯文本: 1 (实际同 2)<br/>带图: 2<br />4: 转发 | +| pics | object[] | 携带图片 | 非必要 | 最多九个 | +| topic | object | 话题 | 非必要 | | +| option | object | 互动设置 | 非必要 | 没有此项时默认开启评论区 | +| upload_id | string | 客户端生成的 | 非必要 | 内容为`发送人mid`+`当前秒级时间戳`+`四位随机整数`,中间用`_`隔开 | + +`dyn_req.meta` 对象: + +大概是来源信息, 示例见下 + +```json +{ + "app_meta": { + "from": "create.dynamic.web", + "mobi_app": "web" + } +} +``` + +`dyn_req.content` 对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ----- | -------------------- | ------ | ---- | +| contents | object[] | 动态组件对象有序数组 | 必要 | | + +`dyn_req.content.contents[]` 对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---- | ------ | ---- | +| raw_text | string | 文本 | 必要 | | +| type | number | 组件类型 id | 不必要 | 参见 [富文本节点类型](../opus/rich_text_nodes.md) | +| biz_id | string | 动态组件的内容id转字符串 | 不必要 | 参见 [富文本节点类型](../opus/rich_text_nodes.md) | + +`dyn_req.topic` 对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------- | ---- | ------- | ------ | -------------------------- | +| from_source | string | 来源id? | 不必要 | 网页版直接选为 `dyn.web.list` | +| from_topic_id | number | 0 | 不必要 | | +| id | number | 话题id | 必要 | | +| name | string | 话题名 | 不必要 | | + +`dyn_req.pics[]` 对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ----- | ---------------- | ------ | ------------------------------------------------------------ | +| img_height | number | 图高 | 非必要 | 这个东西会直接原封不动传到前端,比如你都写 0 在网页上就看不见了, 但是还会加载 | +| img_width | number | 图宽 | 非必要 | 同上 | +| img_size | float | 图片文件大小(KB) | 非必要 | | +| img_src | string | 图片 URL | 必要 | | + +`dyn_req.option` 对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----------------- | ---- | ------------ | ------ | --------------- | +| up_choose_comment | number | 精选评论flag | 非必要 | 1: 开启 | +| close_comment | number | 关闭评论flag | 非必要 | 同上, 上二选一 | + +`dyn_req.topic` 对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------- | ---- | ------------ | ------ | -------- | +| from_source | string | `dyn.web.list` | 非必要 | 作用不明 | +| from_topic_id | number | 0 | 非必要 | 作用不明 | +| id | number | 话题id | 必要 | | +| name | string | 话题名 | 非必要 | | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | number | 返回值 | 0: 成功<br />-101: 账号未登录<br />4126021: 你没有绑定手机,无法发布动态 | +| message | string | 错误信息 | 成功为空 | +| data | object | 数据本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| result | number | 0 | | +| message | string | 错误信息 | | +| dyn_id | number | 动态 id | | +| dyn_id_str | string | 动态 id | 字符串格式 | +| dyn_type | number | 动态类型 | 1: 转发<br />2: 图文 | +| share_window | object | 分享提示 | 当 Cookie 不存在 `buvid3` 时存在 | + +`data.share_window` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| main_title | string | `分享后会获得更多曝光,快去分享吧` | | + +**示例:** + +<details> +<summary>Cookie 带 `buvid3`:</summary> + +动态正文 +``` +Test礼堂丁真,鉴定为一眼丁真 +``` + +带两张一样的图: + +http://i0.hdslb.com/bfs/new_dyn/322acd0fa92cfa59c0ad70e95ab95476470310172.png + +然后关闭评论区 + +命令 + +```bash +curl -X POST 'https://api.bilibili.com/x/dynamic/feed/create/dyn?csrf=xxxxx' \ +-b 'buvid3=114514;SESSDATA=xxxxx;' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "dyn_req": { + "content": { + "contents": [ + { + "raw_text": "Test", + "type": 1, + "biz_id": "" + }, + { + "raw_text": "礼堂丁真,鉴定为一眼丁真", + "type": 2, + "biz_id": "1463028352" + } + ] + }, + "pics": [ + { + "img_src": "http://i0.hdslb.com/bfs/new_dyn/322acd0fa92cfa59c0ad70e95ab95476470310172.png", + "img_width": 1368, + "img_height": 1500, + "img_size": 662.6005859375 + }, + { + "img_src": "http://i0.hdslb.com/bfs/new_dyn/322acd0fa92cfa59c0ad70e95ab95476470310172.png", + "img_width": 1368, + "img_height": 1500, + "img_size": 662.6005859375 + } + ], + "option": { + "close_comment": 1 + }, + "scene": 2 + } +}' +``` + +响应: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "dyn_id": 755402172521250838, + "dyn_id_str": "755402172521250838", + "dyn_type": 2, + "dyn_rid": 221621773 + } +} +``` + +</details> + +## 立即发布定时动态 + +> https://api.vc.bilibili.com/dynamic_draft/v1/dynamic_draft/publish_now + +*请求方法: POST* + +认证方式: Cookie (SESSDATA) + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------------------ | ------ | ---- | +| draft_id | file | 定时动态(草稿)id | 必要 | | +| csrf | string | CSRF Token(即 Cookie 中 bili_jct) | 必要 | | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------ | +| code | number | 返回值 | 0: 成功 | +| data | object | 信息本体 | 正常为空对象 | +| message | string | 错误消息 | 正常为 `0` | +| ttl | number | 1 | | + +<details> +<summary>查看示例</summary> + + +```bash +curl -X POST 'https://api.vc.bilibili.com/dynamic_draft/v1/dynamic_draft/publish_now' \ +--header 'Content-Type: application/x-www-form-urlencoded' \ +--data-urlencode 'draft_id=755409289278914611' \ +--data-urlencode 'csrf=xxx' +-b 'SESSDATA=xxxx;' +``` + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": {} +} +``` + +</details> diff --git a/bb-api-collect/docs/dynamic/space.md b/bb-api-collect/docs/dynamic/space.md new file mode 100644 index 0000000000..a83f3a0b4d --- /dev/null +++ b/bb-api-collect/docs/dynamic/space.md @@ -0,0 +1,4473 @@ +# 用户空间动态 + +## 获取用户空间动态 + +> https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space +> +> https://api.bilibili.com/x/polymer/web-dynamic/desktop/v1/feed/space + +*请求方法: GET* + +鉴权方式: +* 未登录: 请求标头 `User-Agent` 字段, `Cookie` 需含 `buvid3`; WBI 签名, `dm_img` 系列风控 +* 已登录: 请求标头 `Cookie` 含有效 `SESSDATA` + +注: 该接口现在有一些奇奇怪怪的校验, 存在一定运气成分, 参见 [#686](https://github.com/SocialSisterYi/bilibili-API-collect/issues/686), 所以建议您还是登录吧~ + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|-----------------|--------|--------|-----| - | +| offset | string | 分页偏移量 | 不必要 | | +| host_mid | string | 被查询用户 UID (mid) |必要| | +| timezone_offset | number | 时区偏移| 不必要| 默认 `-480` | +| platform | string | 平台 | 不必要 | 如 `web` | +| features | string | 功能 | 不必要 | 留空为空, 默认为 `itemOpusStyle,listOnlyfans,opusBigCover,onlyfansVote,forwardListHidden,decorationCard,commentsNewVersion,onlyfansAssetsV2,ugcDelete,onlyfansQaCard`, 参见 [功能模块](../opus/features.md#features) | +| web_location | string | `333.1387` | 不必要 | | +| dm_img_switch | number | `0` | 不必要 | 仅登录时存在 | +| dm_img_list | object[] | `dm_img` 系列风控 | 不必要 | 仅未登录时存在 | +| dm_img_str | string | `dm_img` 系列风控 | 不必要 | 仅未登录时存在 | +| dm_cover_img_str | string | `dm_img` 系列风控 | 不必要 | 仅未登录时存在 | +| dm_img_inter | object | `dm_img` 系列风控 | 不必要 | 仅未登录时存在 | +| x-bili-device-req-json | object | `{"platform":"web","device":"pc"}` | 不必要 | | +| x-bili-web-req-json | object | `{"spm_id":"333.1387"}` | 不必要 | | +| w_rid | string | WBI 签名 | 不必要 | 参见 [WBI 签名](../misc/sign/wbi.md) | +| wts | number | UNIX 秒级时间戳 | 不必要 | 参见 [WBI 签名](../misc/sign/wbi.md) | + +**JSON 回复:** + +可参考 [获取动态列表](./all.md#获取动态列表) + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space?host_mid=2095498218&features=itemOpusStyle,listOnlyfans,opusBigCover,onlyfansVote,forwardListHidden,decorationCard,commentsNewVersion,onlyfansAssetsV2,ugcDelete,onlyfansQaCard' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>点击查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "has_more": true, + "items": [ + { + "basic": { + "comment_id_str": "349795473", + "comment_type": 11, + "jump_url": "//www.bilibili.com/opus/1063487284684259332", + "like_icon": { + "action_url": "https://i0.hdslb.com/bfs/garb/item/cb34de5fbca6b8507adf7364ae785822b74df1f9.bin", + "end_url": "", + "id": 68554, + "start_url": "" + }, + "rid_str": "349795473" + }, + "id_str": "1063487284684259332", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "2095498218" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "fan": { + "color": "#a465e5", + "color_format": { + "colors": [ + "#a465e5FF", + "#a465e5FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "坠落·空", + "num_desc": "002272", + "number": 2272 + }, + "id": 68557, + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "item_id": 68557, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=68557&isdiy=0&part=card&from=post&f_source=garb&vmid=2095498218&native.theme=1&navhide=1", + "name": "坠落·空粉丝" + }, + "face": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/2095498218/dynamic", + "label": "", + "mid": 2095498218, + "name": "次元壁小宋", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance_frame": "", + "n_pid": 68553, + "name": "坠落·空", + "pid": 68553 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "27分钟前", + "pub_ts": 1746450829, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1683129600000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "opus": { + "fold_action": [ + "展开", + "收起" + ], + "jump_url": "//www.bilibili.com/opus/1063487284684259332", + "pics": [ + { + "height": 512, + "live_url": null, + "size": 9.783203125, + "url": "http://i0.hdslb.com/bfs/new_dyn/8bc3298efe55f2fc3949678538ed5fa52095498218.png", + "width": 512 + } + ], + "summary": { + "rich_text_nodes": [ + { + "orig_text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean a augue eget sapien ultricies tristique. Integer rutrum convallis elit et vestibulum. Proin porta magna id congue lobortis. Vestibulum et arcu vestibulum, dignissim est ultrices, laoreet lectus. Nam sed sem vehicula, iaculis lorem ac, tempor arcu. Aliquam nec porta sapien. Nam convallis iaculis urna, et varius dolor. Sed non pellentesque enim. Praesent molestie efficitur rutrum. Nunc sit amet tempus nisl, at sodales augue. Nunc eu risus quis eros euismod rhoncus quis at purus. Aliquam vulputate magna non enim dapibus vestibulum. Sed pellentesque leo eget imperdiet viverra. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae;\n\nUt porta non ex quis porta. Proin maximus, diam eget commodo tempus, justo libero ultricies ante, feugiat elementum sem ante sit amet magna. Donec auctor arcu sed ligula imperdiet, eget iaculis nunc mollis.", + "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean a augue eget sapien ultricies tristique. Integer rutrum convallis elit et vestibulum. Proin porta magna id congue lobortis. Vestibulum et arcu vestibulum, dignissim est ultrices, laoreet lectus. Nam sed sem vehicula, iaculis lorem ac, tempor arcu. Aliquam nec porta sapien. Nam convallis iaculis urna, et varius dolor. Sed non pellentesque enim. Praesent molestie efficitur rutrum. Nunc sit amet tempus nisl, at sodales augue. Nunc eu risus quis eros euismod rhoncus quis at purus. Aliquam vulputate magna non enim dapibus vestibulum. Sed pellentesque leo eget imperdiet viverra. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae;\n\nUt porta non ex quis porta. Proin maximus, diam eget commodo tempus, justo libero ultricies ante, feugiat elementum sem ante sit amet magna. Donec auctor arcu sed ligula imperdiet, eget iaculis nunc mollis.", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean a augue eget sapien ultricies tristique. Integer rutrum convallis elit et vestibulum. Proin porta magna id congue lobortis. Vestibulum et arcu vestibulum, dignissim est ultrices, laoreet lectus. Nam sed sem vehicula, iaculis lorem ac, tempor arcu. Aliquam nec porta sapien. Nam convallis iaculis urna, et varius dolor. Sed non pellentesque enim. Praesent molestie efficitur rutrum. Nunc sit amet tempus nisl, at sodales augue. Nunc eu risus quis eros euismod rhoncus quis at purus. Aliquam vulputate magna non enim dapibus vestibulum. Sed pellentesque leo eget imperdiet viverra. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae;\n\nUt porta non ex quis porta. Proin maximus, diam eget commodo tempus, justo libero ultricies ante, feugiat elementum sem ante sit amet magna. Donec auctor arcu sed ligula imperdiet, eget iaculis nunc mollis." + }, + "title": "Lorem ipsum dolor si" + }, + "type": "MAJOR_TYPE_OPUS" + }, + "topic": null + }, + "module_interaction": { + "items": [ + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "RPG_Teng_Lin", + "rid": "357413690", + "text": "RPG_Teng_Lin", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": " 赞了", + "text": " 赞了", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "" + }, + "type": 0 + } + ] + }, + "module_more": { + "three_point_items": [ + { + "label": "取消置顶", + "params": { + "dynamic_id": "1063487284684259332", + "status": true + }, + "type": "THREE_POINT_TOP" + }, + { + "label": "删除", + "modal": { + "cancel": "取消", + "confirm": "确认删除", + "content": "动态删除后将无法恢复,请谨慎操作", + "title": "要删除动态吗?" + }, + "params": { + "dyn_id_str": "1063487284684259332", + "dyn_type": 2, + "rid_str": "349795473" + }, + "type": "THREE_POINT_DELETE" + } + ] + }, + "module_stat": { + "comment": { + "count": 0, + "forbidden": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 1, + "forbidden": false, + "status": false + } + }, + "module_tag": { + "text": "置顶" + } + }, + "type": "DYNAMIC_TYPE_DRAW", + "visible": true + }, + { + "basic": { + "comment_id_str": "114443295918557", + "comment_type": 1, + "like_icon": { + "action_url": "https://i0.hdslb.com/bfs/garb/item/cb34de5fbca6b8507adf7364ae785822b74df1f9.bin", + "end_url": "", + "id": 68554, + "start_url": "" + }, + "rid_str": "114443295918557" + }, + "id_str": "1062695803784527872", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "2095498218" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "fan": { + "color": "#a465e5", + "color_format": { + "colors": [ + "#a465e5FF", + "#a465e5FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "坠落·空", + "num_desc": "002272", + "number": 2272 + }, + "id": 68557, + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "item_id": 68557, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=68557&isdiy=0&part=card&from=post&f_source=garb&vmid=2095498218&native.theme=1&navhide=1", + "name": "坠落·空粉丝" + }, + "face": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/2095498218/dynamic", + "label": "", + "mid": 2095498218, + "name": "次元壁小宋", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance_frame": "", + "n_pid": 68553, + "name": "坠落·空", + "pid": 68553 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2天前", + "pub_ts": 1746266548, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1683129600000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "114443295918557", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1HUVnz7EX1", + "cover": "http://i1.hdslb.com/bfs/archive/515f60c051c83f98922f78de95a072feebc8f041.jpg", + "desc": "-", + "disable_preview": 0, + "duration_text": "05:14", + "jump_url": "//www.bilibili.com/video/BV1HUVnz7EX1/", + "stat": { + "danmaku": "1", + "play": "26" + }, + "title": "来自阿洛娜的权威", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_interaction": { + "items": [ + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "长安不见-雪", + "rid": "3546712641636719", + "text": "长安不见-雪", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": "、", + "text": "、", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "旋转的M2", + "rid": "3493264944531941", + "text": "旋转的M2", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": " 赞了", + "text": " 赞了", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "" + }, + "type": 0 + } + ] + }, + "module_more": { + "three_point_items": [ + { + "label": "置顶", + "params": { + "dynamic_id": "1062695803784527872", + "status": false + }, + "type": "THREE_POINT_TOP" + }, + { + "label": "删除", + "modal": { + "cancel": "取消", + "confirm": "确认删除", + "content": "视频删除后将无法恢复,请谨慎操作", + "title": "删除动态会同时删除视频稿件" + }, + "params": { + "dyn_id_str": "1062695803784527872", + "dyn_type": 8, + "rid_str": "114443295918557" + }, + "type": "THREE_POINT_DELETE" + } + ] + }, + "module_stat": { + "comment": { + "count": 1, + "forbidden": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 4, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + { + "basic": { + "comment_id_str": "114402862959003", + "comment_type": 1, + "like_icon": { + "action_url": "https://i0.hdslb.com/bfs/garb/item/cb34de5fbca6b8507adf7364ae785822b74df1f9.bin", + "end_url": "", + "id": 68554, + "start_url": "" + }, + "rid_str": "114402862959003" + }, + "id_str": "1060045976462426117", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "2095498218" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "fan": { + "color": "#a465e5", + "color_format": { + "colors": [ + "#a465e5FF", + "#a465e5FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "坠落·空", + "num_desc": "002272", + "number": 2272 + }, + "id": 68557, + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "item_id": 68557, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=68557&isdiy=0&part=card&from=post&f_source=garb&vmid=2095498218&native.theme=1&navhide=1", + "name": "坠落·空粉丝" + }, + "face": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/2095498218/dynamic", + "label": "", + "mid": 2095498218, + "name": "次元壁小宋", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance_frame": "", + "n_pid": 68553, + "name": "坠落·空", + "pid": 68553 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "04月26日", + "pub_ts": 1745649587, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1683129600000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "114402862959003", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1ovLXzPEFq", + "cover": "http://i0.hdslb.com/bfs/archive/b361f14b56080cb17ed5ff24d0b629945c0c150d.jpg", + "desc": "-", + "disable_preview": 0, + "duration_text": "02:42", + "jump_url": "//www.bilibili.com/video/BV1ovLXzPEFq/", + "stat": { + "danmaku": "0", + "play": "199" + }, + "title": "终于把星野酱带回家了૮₍˃̶ꇴ˂̶₎ა", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_interaction": { + "items": [ + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "蔚蓝绪山", + "rid": "3493074818828658", + "text": "蔚蓝绪山", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": "、", + "text": "、", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "蚕茧自缠萦", + "rid": "291098307", + "text": "蚕茧自缠萦", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": " 赞了", + "text": " 赞了", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "" + }, + "type": 0 + } + ] + }, + "module_more": { + "three_point_items": [ + { + "label": "置顶", + "params": { + "dynamic_id": "1060045976462426117", + "status": false + }, + "type": "THREE_POINT_TOP" + }, + { + "label": "删除", + "modal": { + "cancel": "取消", + "confirm": "确认删除", + "content": "视频删除后将无法恢复,请谨慎操作", + "title": "删除动态会同时删除视频稿件" + }, + "params": { + "dyn_id_str": "1060045976462426117", + "dyn_type": 8, + "rid_str": "114402862959003" + }, + "type": "THREE_POINT_DELETE" + } + ] + }, + "module_stat": { + "comment": { + "count": 8, + "forbidden": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 9, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + { + "basic": { + "comment_id_str": "114398483975404", + "comment_type": 1, + "like_icon": { + "action_url": "https://i0.hdslb.com/bfs/garb/item/cb34de5fbca6b8507adf7364ae785822b74df1f9.bin", + "end_url": "", + "id": 68554, + "start_url": "" + }, + "rid_str": "114398483975404" + }, + "id_str": "1059758291001802840", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "2095498218" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "fan": { + "color": "#a465e5", + "color_format": { + "colors": [ + "#a465e5FF", + "#a465e5FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "坠落·空", + "num_desc": "002272", + "number": 2272 + }, + "id": 68557, + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "item_id": 68557, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=68557&isdiy=0&part=card&from=post&f_source=garb&vmid=2095498218&native.theme=1&navhide=1", + "name": "坠落·空粉丝" + }, + "face": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/2095498218/dynamic", + "label": "", + "mid": 2095498218, + "name": "次元壁小宋", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance_frame": "", + "n_pid": 68553, + "name": "坠落·空", + "pid": 68553 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "04月25日", + "pub_ts": 1745582605, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1683129600000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "114398483975404", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1KXLEz9EV8", + "cover": "http://i2.hdslb.com/bfs/archive/915817adaf0c1618ecf28d06d03eb8be8f6c89ff.jpg", + "desc": "-", + "disable_preview": 0, + "duration_text": "00:14", + "jump_url": "//www.bilibili.com/video/BV1KXLEz9EV8/", + "stat": { + "danmaku": "0", + "play": "205" + }, + "title": "玩了一年多codm,这个什么玩意……", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_interaction": { + "items": [ + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "长安不见-雪", + "rid": "3546712641636719", + "text": "长安不见-雪", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": "、", + "text": "、", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "坤坤丨宝宝", + "rid": "510272506", + "text": "坤坤丨宝宝", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": " 赞了", + "text": " 赞了", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "" + }, + "type": 0 + } + ] + }, + "module_more": { + "three_point_items": [ + { + "label": "置顶", + "params": { + "dynamic_id": "1059758291001802840", + "status": false + }, + "type": "THREE_POINT_TOP" + }, + { + "label": "删除", + "modal": { + "cancel": "取消", + "confirm": "确认删除", + "content": "视频删除后将无法恢复,请谨慎操作", + "title": "删除动态会同时删除视频稿件" + }, + "params": { + "dyn_id_str": "1059758291001802840", + "dyn_type": 8, + "rid_str": "114398483975404" + }, + "type": "THREE_POINT_DELETE" + } + ] + }, + "module_stat": { + "comment": { + "count": 1, + "forbidden": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 6, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + { + "basic": { + "comment_id_str": "114392746165578", + "comment_type": 1, + "like_icon": { + "action_url": "https://i0.hdslb.com/bfs/garb/item/cb34de5fbca6b8507adf7364ae785822b74df1f9.bin", + "end_url": "", + "id": 68554, + "start_url": "" + }, + "rid_str": "114392746165578" + }, + "id_str": "1059382215079624725", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "2095498218" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "fan": { + "color": "#a465e5", + "color_format": { + "colors": [ + "#a465e5FF", + "#a465e5FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "坠落·空", + "num_desc": "002272", + "number": 2272 + }, + "id": 68557, + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "item_id": 68557, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=68557&isdiy=0&part=card&from=post&f_source=garb&vmid=2095498218&native.theme=1&navhide=1", + "name": "坠落·空粉丝" + }, + "face": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/2095498218/dynamic", + "label": "", + "mid": 2095498218, + "name": "次元壁小宋", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance_frame": "", + "n_pid": 68553, + "name": "坠落·空", + "pid": 68553 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "04月24日", + "pub_ts": 1745495043, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1683129600000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "114392746165578", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1oZLgz7EeX", + "cover": "http://i1.hdslb.com/bfs/archive/f62117a5e67f2775c892123d1ebe9e23d3523ca8.jpg", + "desc": "-", + "disable_preview": 0, + "duration_text": "12:25", + "jump_url": "//www.bilibili.com/video/BV1oZLgz7EeX/", + "stat": { + "danmaku": "0", + "play": "335" + }, + "title": "什么才是叫作史上最绝望的死法,……(这爆率正常吗)", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_interaction": { + "items": [ + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "菌哥电影", + "rid": "628092353", + "text": "菌哥电影", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": "、", + "text": "、", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "是轻甄不是饭团酱", + "rid": "646061108", + "text": "是轻甄不是饭团酱", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": " 赞了", + "text": " 赞了", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "" + }, + "type": 0 + } + ] + }, + "module_more": { + "three_point_items": [ + { + "label": "置顶", + "params": { + "dynamic_id": "1059382215079624725", + "status": false + }, + "type": "THREE_POINT_TOP" + }, + { + "label": "删除", + "modal": { + "cancel": "取消", + "confirm": "确认删除", + "content": "视频删除后将无法恢复,请谨慎操作", + "title": "删除动态会同时删除视频稿件" + }, + "params": { + "dyn_id_str": "1059382215079624725", + "dyn_type": 8, + "rid_str": "114392746165578" + }, + "type": "THREE_POINT_DELETE" + } + ] + }, + "module_stat": { + "comment": { + "count": 8, + "forbidden": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 18, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + { + "basic": { + "comment_id_str": "114291361449486", + "comment_type": 1, + "like_icon": { + "action_url": "https://i0.hdslb.com/bfs/garb/item/cb34de5fbca6b8507adf7364ae785822b74df1f9.bin", + "end_url": "", + "id": 68554, + "start_url": "" + }, + "rid_str": "114291361449486" + }, + "id_str": "1052737677322878980", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "2095498218" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "fan": { + "color": "#a465e5", + "color_format": { + "colors": [ + "#a465e5FF", + "#a465e5FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "坠落·空", + "num_desc": "002272", + "number": 2272 + }, + "id": 68557, + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "item_id": 68557, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=68557&isdiy=0&part=card&from=post&f_source=garb&vmid=2095498218&native.theme=1&navhide=1", + "name": "坠落·空粉丝" + }, + "face": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/2095498218/dynamic", + "label": "", + "mid": 2095498218, + "name": "次元壁小宋", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance_frame": "", + "n_pid": 68553, + "name": "坠落·空", + "pid": 68553 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "04月06日", + "pub_ts": 1743947991, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1683129600000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "114291361449486", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV15tR6YEEGN", + "cover": "http://i1.hdslb.com/bfs/archive/f53a964d2438e44db579a2ff373b49e57ea9c752.jpg", + "desc": "-", + "disable_preview": 0, + "duration_text": "10:26", + "jump_url": "//www.bilibili.com/video/BV15tR6YEEGN/", + "stat": { + "danmaku": "0", + "play": "152" + }, + "title": "有这一款游戏,爆率逆天没有别的(封神)", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_interaction": { + "items": [ + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "长安不见-雪", + "rid": "3546712641636719", + "text": "长安不见-雪", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": " 赞了", + "text": " 赞了", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "" + }, + "type": 0 + } + ] + }, + "module_more": { + "three_point_items": [ + { + "label": "置顶", + "params": { + "dynamic_id": "1052737677322878980", + "status": false + }, + "type": "THREE_POINT_TOP" + }, + { + "label": "删除", + "modal": { + "cancel": "取消", + "confirm": "确认删除", + "content": "视频删除后将无法恢复,请谨慎操作", + "title": "删除动态会同时删除视频稿件" + }, + "params": { + "dyn_id_str": "1052737677322878980", + "dyn_type": 8, + "rid_str": "114291361449486" + }, + "type": "THREE_POINT_DELETE" + } + ] + }, + "module_stat": { + "comment": { + "count": 4, + "forbidden": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 3, + "forbidden": false, + "status": true + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + { + "basic": { + "comment_id_str": "1050478468672782345", + "comment_type": 17, + "like_icon": { + "action_url": "https://i0.hdslb.com/bfs/garb/item/cb34de5fbca6b8507adf7364ae785822b74df1f9.bin", + "end_url": "", + "id": 68554, + "start_url": "" + }, + "rid_str": "1050478468672782345" + }, + "id_str": "1050478468672782345", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "2095498218" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "fan": { + "color": "#a465e5", + "color_format": { + "colors": [ + "#a465e5FF", + "#a465e5FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "坠落·空", + "num_desc": "002272", + "number": 2272 + }, + "id": 68557, + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "item_id": 68557, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=68557&isdiy=0&part=card&from=post&f_source=garb&vmid=2095498218&native.theme=1&navhide=1", + "name": "坠落·空粉丝" + }, + "face": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/2095498218/dynamic", + "label": "", + "mid": 2095498218, + "name": "次元壁小宋", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance_frame": "", + "n_pid": 68553, + "name": "坠落·空", + "pid": 68553 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "03月31日", + "pub_ts": 1743421978, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1683129600000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": null, + "desc": { + "rich_text_nodes": [ + { + "orig_text": "我昨晚也有Bug,打航天基地的爆破第二局后我的,趴下滑铲不知道咋回事就点不了跳跃键也点不了然后就只能点开火键和操作键,投掷物能丢以外其他啥也干不了,只能跟人机样送一整局就输了", + "text": "我昨晚也有Bug,打航天基地的爆破第二局后我的,趴下滑铲不知道咋回事就点不了跳跃键也点不了然后就只能点开火键和操作键,投掷物能丢以外其他啥也干不了,只能跟人机样送一整局就输了", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "emoji": { + "icon_url": "https://i0.hdslb.com/bfs/emote/493b36cbadea2356f09933b39e49c5a2f8f625b8.png", + "size": 2, + "text": "[坠落·空_自闭]", + "type": 3 + }, + "orig_text": "[坠落·空_自闭]", + "text": "[坠落·空_自闭]", + "type": "RICH_TEXT_NODE_TYPE_EMOJI" + }, + { + "emoji": { + "icon_url": "https://i0.hdslb.com/bfs/emote/86c614f2d21263387fa7ef168450ccd69cce9a0b.png", + "size": 2, + "text": "[坠落·空_哭泣]", + "type": 3 + }, + "orig_text": "[坠落·空_哭泣]", + "text": "[坠落·空_哭泣]", + "type": "RICH_TEXT_NODE_TYPE_EMOJI" + } + ], + "text": "我昨晚也有Bug,打航天基地的爆破第二局后我的,趴下滑铲不知道咋回事就点不了跳跃键也点不了然后就只能点开火键和操作键,投掷物能丢以外其他啥也干不了,只能跟人机样送一整局就输了[坠落·空_自闭][坠落·空_哭泣]" + }, + "major": null, + "topic": null + }, + "module_interaction": { + "items": [ + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "长安不见-雪", + "rid": "3546712641636719", + "text": "长安不见-雪", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": " 赞了", + "text": " 赞了", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "" + }, + "type": 0 + } + ] + }, + "module_more": { + "three_point_items": [ + { + "label": "置顶", + "params": { + "dynamic_id": "1050478468672782345", + "status": false + }, + "type": "THREE_POINT_TOP" + }, + { + "label": "删除", + "modal": { + "cancel": "取消", + "confirm": "确认删除", + "content": "动态删除后将无法恢复,请谨慎操作", + "title": "要删除动态吗?" + }, + "params": { + "dyn_id_str": "1050478468672782345", + "dyn_type": 1, + "rid_str": "1050478468672782345" + }, + "type": "THREE_POINT_DELETE" + } + ] + }, + "module_stat": { + "comment": { + "count": 0, + "forbidden": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 1, + "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": "1049725573770772488", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i2.hdslb.com/bfs/face/ad1944a6564f065fae1b5d7ee963d08c900fe8d3.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "289949153" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/vip/e2ffa1d1d491fe0464338ed3921327ef5e4b42c5.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/vip/a9e3d993c7a15e88ce0bf714a142f7d2b44121e2.png", + "fan": {}, + "id": 28, + "image_enhance": "https://i0.hdslb.com/bfs/vip/a9e3d993c7a15e88ce0bf714a142f7d2b44121e2.png", + "item_id": 28, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=28&isdiy=0&part=card&from=post&f_source=garb&vmid=289949153&native.theme=1&navhide=1", + "name": "2233娘" + }, + "face": "https://i2.hdslb.com/bfs/face/ad1944a6564f065fae1b5d7ee963d08c900fe8d3.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/289949153/dynamic", + "label": "", + "mid": 289949153, + "name": "谁是fufu", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_time": "", + "pub_ts": 1743246681, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1743350400000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "114245391947434", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1vmZAYDEcT", + "cover": "http://i0.hdslb.com/bfs/archive/d3ccb1bd474d55cc4415e073d21f1c8a3d12c22d.jpg", + "desc": "-", + "disable_preview": 0, + "duration_text": "02:43", + "jump_url": "//www.bilibili.com/video/BV1vmZAYDEcT/", + "stat": { + "danmaku": "49", + "play": "6.5万" + }, + "title": "上号成为人机了!是BUG还是分身?", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": { + "id": 1061343, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1061343&topic_name=%E4%BD%BF%E5%91%BD%E5%8F%AC%E5%94%A4%E6%89%8B%E6%B8%B8%E8%AE%B0%E5%BD%95", + "name": "使命召唤手游记录" + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "type": "DYNAMIC_TYPE_FORWARD", + "visible": true + }, + { + "basic": { + "comment_id_str": "1049490226780569608", + "comment_type": 17, + "like_icon": { + "action_url": "https://i0.hdslb.com/bfs/garb/item/cb34de5fbca6b8507adf7364ae785822b74df1f9.bin", + "end_url": "", + "id": 68554, + "start_url": "" + }, + "rid_str": "1049490226780569608" + }, + "id_str": "1049490226780569608", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "2095498218" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "fan": { + "color": "#a465e5", + "color_format": { + "colors": [ + "#a465e5FF", + "#a465e5FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "坠落·空", + "num_desc": "002272", + "number": 2272 + }, + "id": 68557, + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "item_id": 68557, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=68557&isdiy=0&part=card&from=post&f_source=garb&vmid=2095498218&native.theme=1&navhide=1", + "name": "坠落·空粉丝" + }, + "face": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/2095498218/dynamic", + "label": "", + "mid": 2095498218, + "name": "次元壁小宋", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance_frame": "", + "n_pid": 68553, + "name": "坠落·空", + "pid": 68553 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "03月29日", + "pub_ts": 1743191885, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1683129600000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": null, + "desc": { + "rich_text_nodes": [ + { + "orig_text": "回复 ", + "text": "回复 ", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "@狂热的地幔", + "rid": "1333987156", + "text": "@狂热的地幔", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": " :我试过玩上一个月删了,然后现在我又想玩不知道为什么玩几天又想删", + "text": " :我试过玩上一个月删了,然后现在我又想玩不知道为什么玩几天又想删", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "emoji": { + "icon_url": "https://i0.hdslb.com/bfs/emote/c3043ba94babf824dea03ce500d0e73763bf4f40.png", + "size": 1, + "text": "[笑哭]", + "type": 1 + }, + "orig_text": "[笑哭]", + "text": "[笑哭]", + "type": "RICH_TEXT_NODE_TYPE_EMOJI" + } + ], + "text": "回复 @狂热的地幔 :我试过玩上一个月删了,然后现在我又想玩不知道为什么玩几天又想删[笑哭]" + }, + "major": null, + "topic": null + }, + "module_interaction": { + "items": [ + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "长安不见-雪", + "rid": "3546712641636719", + "text": "长安不见-雪", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": " 赞了", + "text": " 赞了", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "" + }, + "type": 0 + } + ] + }, + "module_more": { + "three_point_items": [ + { + "label": "置顶", + "params": { + "dynamic_id": "1049490226780569608", + "status": false + }, + "type": "THREE_POINT_TOP" + }, + { + "label": "删除", + "modal": { + "cancel": "取消", + "confirm": "确认删除", + "content": "动态删除后将无法恢复,请谨慎操作", + "title": "要删除动态吗?" + }, + "params": { + "dyn_id_str": "1049490226780569608", + "dyn_type": 1, + "rid_str": "1049490226780569608" + }, + "type": "THREE_POINT_DELETE" + } + ] + }, + "module_stat": { + "comment": { + "count": 0, + "forbidden": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 1, + "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": "1049336535656169477", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/929fb162c6eb9f81b55b67b3016364a3d00fb437.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 3, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "497979931" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/vip/40b8bef91ed10dd8c2b9302d85db76c5f1f3c292.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/vip/99f54078df2412394140aa5df4422bc0a1ca3d3e.png", + "fan": {}, + "id": 5, + "image_enhance": "https://i0.hdslb.com/bfs/vip/99f54078df2412394140aa5df4422bc0a1ca3d3e.png", + "item_id": 5, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=5&isdiy=0&part=card&from=post&f_source=garb&vmid=497979931&native.theme=1&navhide=1", + "name": "33娘" + }, + "face": "https://i1.hdslb.com/bfs/face/929fb162c6eb9f81b55b67b3016364a3d00fb437.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/497979931/dynamic", + "label": "", + "mid": 497979931, + "name": "冰林L", + "official_verify": { + "desc": "", + "type": 0 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_time": "", + "pub_ts": 1743156101, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1745856000000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "114239469520401", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1E7oXYhEhp", + "cover": "http://i2.hdslb.com/bfs/archive/db15a6d18cdf6cef3cb41b9d9f11847b5c950bc4.jpg", + "desc": "我知道MC不是我生活的全部,但我希望他能陪我更久一点,未来我可能会去尝试做一些MC动画,或者其他的游戏。", + "disable_preview": 0, + "duration_text": "02:39", + "jump_url": "//www.bilibili.com/video/BV1E7oXYhEhp/", + "stat": { + "danmaku": "548", + "play": "31.2万" + }, + "title": "做MC视频10年了,为什么MC越来越无聊了…", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "type": "DYNAMIC_TYPE_FORWARD", + "visible": true + }, + { + "basic": { + "comment_id_str": "1046005002557980674", + "comment_type": 17, + "like_icon": { + "action_url": "https://i0.hdslb.com/bfs/garb/item/cb34de5fbca6b8507adf7364ae785822b74df1f9.bin", + "end_url": "", + "id": 68554, + "start_url": "" + }, + "rid_str": "1046376087871815681" + }, + "id_str": "1046005002557980674", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "2095498218" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "fan": { + "color": "#a465e5", + "color_format": { + "colors": [ + "#a465e5FF", + "#a465e5FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "坠落·空", + "num_desc": "002272", + "number": 2272 + }, + "id": 68557, + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "item_id": 68557, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=68557&isdiy=0&part=card&from=post&f_source=garb&vmid=2095498218&native.theme=1&navhide=1", + "name": "坠落·空粉丝" + }, + "face": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/2095498218/dynamic", + "label": "", + "mid": 2095498218, + "name": "次元壁小宋", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance_frame": "", + "n_pid": 68553, + "name": "坠落·空", + "pid": 68553 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "03月19日", + "pub_ts": 1742380418, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1683129600000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": null, + "desc": { + "rich_text_nodes": [ + { + "jump_url": "//search.bilibili.com/all?keyword=bilibili%E4%B8%AA%E6%80%A7%E8%A3%85%E6%89%AE", + "orig_text": "#bilibili个性装扮#", + "text": "#bilibili个性装扮#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "orig_text": " 我正在使用“坠落·空”头像挂件,你也来试试~", + "text": " 我正在使用“坠落·空”头像挂件,你也来试试~", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "#bilibili个性装扮# 我正在使用“坠落·空”头像挂件,你也来试试~" + }, + "major": { + "common": { + "badge": { + "bg_color": "#FB7299", + "color": "#ffffff", + "text": "装扮" + }, + "biz_id": 0, + "biz_type": 231, + "cover": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "desc": "挂件", + "id": "1046376087871815681", + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?f_source=dynamic&from=share&isdiy=0&item_id=68595&native.theme=1&navhide=1&part=pendant&q=953008717620250319183338&vmid=2095498218", + "label": "", + "sketch_id": "1046376087871815680", + "style": 1, + "title": "坠落·空" + }, + "type": "MAJOR_TYPE_COMMON" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "置顶", + "params": { + "dynamic_id": "1046005002557980674", + "status": false + }, + "type": "THREE_POINT_TOP" + }, + { + "label": "删除", + "modal": { + "cancel": "取消", + "confirm": "确认删除", + "content": "动态删除后将无法恢复,请谨慎操作", + "title": "要删除动态吗?" + }, + "params": { + "dyn_id_str": "1046005002557980674", + "dyn_type": 2048, + "rid_str": "1046376087871815681" + }, + "type": "THREE_POINT_DELETE" + } + ] + }, + "module_stat": { + "comment": { + "count": 0, + "forbidden": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 1, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_COMMON_SQUARE", + "visible": true + }, + { + "basic": { + "comment_id_str": "1044401021238902802", + "comment_type": 17, + "like_icon": { + "action_url": "https://i0.hdslb.com/bfs/garb/item/cb34de5fbca6b8507adf7364ae785822b74df1f9.bin", + "end_url": "", + "id": 68554, + "start_url": "" + }, + "rid_str": "1044401021238902802" + }, + "id_str": "1044401021238902802", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "2095498218" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "fan": { + "color": "#a465e5", + "color_format": { + "colors": [ + "#a465e5FF", + "#a465e5FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "坠落·空", + "num_desc": "002272", + "number": 2272 + }, + "id": 68557, + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "item_id": 68557, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=68557&isdiy=0&part=card&from=post&f_source=garb&vmid=2095498218&native.theme=1&navhide=1", + "name": "坠落·空粉丝" + }, + "face": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/2095498218/dynamic", + "label": "", + "mid": 2095498218, + "name": "次元壁小宋", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance_frame": "", + "n_pid": 68553, + "name": "坠落·空", + "pid": 68553 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "03月15日", + "pub_ts": 1742006962, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1683129600000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": null, + "desc": { + "rich_text_nodes": [ + { + "orig_text": "我参与了投票", + "text": "我参与了投票", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "​视频类型", + "rid": "14746295", + "text": "​视频类型", + "type": "RICH_TEXT_NODE_TYPE_VOTE" + }, + { + "orig_text": "我投给了我想看抽象的2D动画", + "text": "我投给了我想看抽象的2D动画", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "我参与了投票​视频类型我投给了我想看抽象的2D动画" + }, + "major": null, + "topic": null + }, + "module_interaction": { + "items": [ + { + "desc": { + "rich_text_nodes": [ + { + "orig_text": "长安不见-雪", + "rid": "3546712641636719", + "text": "长安不见-雪", + "type": "RICH_TEXT_NODE_TYPE_AT" + }, + { + "orig_text": " 赞了", + "text": " 赞了", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "" + }, + "type": 0 + } + ] + }, + "module_more": { + "three_point_items": [ + { + "label": "置顶", + "params": { + "dynamic_id": "1044401021238902802", + "status": false + }, + "type": "THREE_POINT_TOP" + }, + { + "label": "删除", + "modal": { + "cancel": "取消", + "confirm": "确认删除", + "content": "动态删除后将无法恢复,请谨慎操作", + "title": "要删除动态吗?" + }, + "params": { + "dyn_id_str": "1044401021238902802", + "dyn_type": 1, + "rid_str": "1044401021238902802" + }, + "type": "THREE_POINT_DELETE" + } + ] + }, + "module_stat": { + "comment": { + "count": 0, + "forbidden": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 1, + "forbidden": false, + "status": false + } + } + }, + "orig": { + "basic": { + "comment_id_str": "", + "comment_type": 0, + "jump_url": "//www.bilibili.com/opus/1044394265267929093", + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "" + }, + "id_str": "1044394265267929093", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/4e08982dd07abbdf86f35a68483424b743f07730.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/5bb7bef5107e448892ab54539298d50eb678de05.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 3, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "1142084989" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/archive/7e0eed18747150fa233ba6994489b9096f1d9fe8.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/archive/7e0eed18747150fa233ba6994489b9096f1d9fe8.png", + "fan": { + "color": "#BFC8D2", + "color_format": { + "colors": [ + "#B8C7D0FF", + "#A2A7B0FF" + ], + "end_point": "100,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "XXXX", + "num_desc": "047769", + "number": 47769 + }, + "id": 66945, + "image_enhance": "https://i0.hdslb.com/bfs/archive/7e0eed18747150fa233ba6994489b9096f1d9fe8.png", + "item_id": 66945, + "jump_url": "https://www.bilibili.com/h5/mall/digital-card/home?act_id=101116&from=post&f_source=garb&-Abrowser=live&hybrid_set_header=2&navhide=1&anchor_task=1", + "name": "初音未来三连快乐勋章" + }, + "face": "https://i1.hdslb.com/bfs/face/4e08982dd07abbdf86f35a68483424b743f07730.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/1142084989/dynamic", + "label": "", + "mid": 1142084989, + "name": "不抽象的真菌零_Jack", + "official_verify": { + "desc": "", + "type": 0 + }, + "pendant": { + "expire": 0, + "image": "https://i1.hdslb.com/bfs/face/5bb7bef5107e448892ab54539298d50eb678de05.png", + "image_enhance": "https://i1.hdslb.com/bfs/face/5bb7bef5107e448892ab54539298d50eb678de05.png", + "image_enhance_frame": "", + "n_pid": 294, + "name": "茶啊二中", + "pid": 294 + }, + "pub_action": "", + "pub_time": "", + "pub_ts": 1742005389, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1751558400000, + "label": { + "bg_color": "#FB7299", + "bg_style": 1, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/3788b674c69072f1ee252b79a31ecc8c43af3039.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/jwXBWRVwa5.png", + "label_theme": "vip", + "path": "", + "text": "大会员", + "text_color": "#FFFFFF", + "use_img_label": true + }, + "nickname_color": "#FB7299", + "status": 1, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": { + "type": "ADDITIONAL_TYPE_VOTE", + "vote": { + "button": { + "jump_style": { + "text": "参与" + }, + "type": 1 + }, + "choice_cnt": 1, + "default_share": 1, + "desc": "153人参与", + "end_time": 1742091752, + "join_num": 153, + "status": 4, + "title": "视频类型", + "type": null, + "uid": 1142084989, + "vote_id": 14746295 + } + }, + "desc": null, + "major": { + "opus": { + "fold_action": [ + "展开", + "收起" + ], + "jump_url": "//www.bilibili.com/opus/1044394265267929093", + "pics": [], + "summary": { + "rich_text_nodes": [ + { + "orig_text": "投票", + "text": "投票", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "​视频类型", + "rid": "14746295", + "text": "​视频类型", + "type": "RICH_TEXT_NODE_TYPE_VOTE" + } + ], + "text": "投票​视频类型" + }, + "title": null + }, + "type": "MAJOR_TYPE_OPUS" + }, + "topic": null + } + }, + "type": "DYNAMIC_TYPE_WORD", + "visible": true + }, + "type": "DYNAMIC_TYPE_FORWARD", + "visible": true + }, + { + "basic": { + "comment_id_str": "1044400750626603011", + "comment_type": 17, + "like_icon": { + "action_url": "https://i0.hdslb.com/bfs/garb/item/cb34de5fbca6b8507adf7364ae785822b74df1f9.bin", + "end_url": "", + "id": 68554, + "start_url": "" + }, + "rid_str": "1044400750626603011" + }, + "id_str": "1044400750626603011", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "2095498218" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "fan": { + "color": "#a465e5", + "color_format": { + "colors": [ + "#a465e5FF", + "#a465e5FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "坠落·空", + "num_desc": "002272", + "number": 2272 + }, + "id": 68557, + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "item_id": 68557, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=68557&isdiy=0&part=card&from=post&f_source=garb&vmid=2095498218&native.theme=1&navhide=1", + "name": "坠落·空粉丝" + }, + "face": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/2095498218/dynamic", + "label": "", + "mid": 2095498218, + "name": "次元壁小宋", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance_frame": "", + "n_pid": 68553, + "name": "坠落·空", + "pid": 68553 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "03月15日", + "pub_ts": 1742006899, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1683129600000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": null, + "desc": { + "rich_text_nodes": [ + { + "orig_text": "我参与了投票", + "text": "我参与了投票", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "​你们的头像是", + "rid": "14514807", + "text": "​你们的头像是", + "type": "RICH_TEXT_NODE_TYPE_VOTE" + }, + { + "orig_text": "我投给了女性", + "text": "我投给了女性", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "我参与了投票​你们的头像是我投给了女性" + }, + "major": null, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "置顶", + "params": { + "dynamic_id": "1044400750626603011", + "status": false + }, + "type": "THREE_POINT_TOP" + }, + { + "label": "删除", + "modal": { + "cancel": "取消", + "confirm": "确认删除", + "content": "动态删除后将无法恢复,请谨慎操作", + "title": "要删除动态吗?" + }, + "params": { + "dyn_id_str": "1044400750626603011", + "dyn_type": 1, + "rid_str": "1044400750626603011" + }, + "type": "THREE_POINT_DELETE" + } + ] + }, + "module_stat": { + "comment": { + "count": 0, + "forbidden": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 0, + "forbidden": false, + "status": false + } + } + }, + "orig": { + "basic": { + "comment_id_str": "", + "comment_type": 0, + "jump_url": "//www.bilibili.com/opus/1034151558512640008", + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "" + }, + "id_str": "1034151558512640008", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/3c35c94e5c9fc5aad09052078339ec9faf1aad87.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "1403650486" + }, + "face": "https://i1.hdslb.com/bfs/face/3c35c94e5c9fc5aad09052078339ec9faf1aad87.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/1403650486/dynamic", + "label": "", + "mid": 1403650486, + "name": "小邓Channel", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "", + "pub_time": "", + "pub_ts": 1739620573, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1711382400000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": { + "type": "ADDITIONAL_TYPE_VOTE", + "vote": { + "button": { + "jump_style": { + "text": "参与" + }, + "type": 1 + }, + "choice_cnt": 1, + "default_share": 1, + "desc": "1135人参与", + "end_time": 1742039701, + "join_num": 1135, + "status": 4, + "title": "你们的头像是", + "type": null, + "uid": 1403650486, + "vote_id": 14514807 + } + }, + "desc": null, + "major": { + "opus": { + "fold_action": [ + "展开", + "收起" + ], + "jump_url": "//www.bilibili.com/opus/1034151558512640008", + "pics": [], + "summary": { + "rich_text_nodes": [ + { + "orig_text": "我发起了一个投票", + "text": "我发起了一个投票", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "​你们的头像是", + "rid": "14514807", + "text": "​你们的头像是", + "type": "RICH_TEXT_NODE_TYPE_VOTE" + } + ], + "text": "我发起了一个投票​你们的头像是" + }, + "title": null + }, + "type": "MAJOR_TYPE_OPUS" + }, + "topic": null + } + }, + "type": "DYNAMIC_TYPE_WORD", + "visible": true + }, + "type": "DYNAMIC_TYPE_FORWARD", + "visible": true + }, + { + "basic": { + "comment_id_str": "1044400681921806345", + "comment_type": 17, + "like_icon": { + "action_url": "https://i0.hdslb.com/bfs/garb/item/cb34de5fbca6b8507adf7364ae785822b74df1f9.bin", + "end_url": "", + "id": 68554, + "start_url": "" + }, + "rid_str": "1044400681921806345" + }, + "id_str": "1044400681921806345", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "2095498218" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "fan": { + "color": "#a465e5", + "color_format": { + "colors": [ + "#a465e5FF", + "#a465e5FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "坠落·空", + "num_desc": "002272", + "number": 2272 + }, + "id": 68557, + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/5f6f72f12f56a8217913f29ef991171c897ab443.png", + "item_id": 68557, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=68557&isdiy=0&part=card&from=post&f_source=garb&vmid=2095498218&native.theme=1&navhide=1", + "name": "坠落·空粉丝" + }, + "face": "https://i0.hdslb.com/bfs/face/3f77a9eeb6aa503bd5e0353865d6d737e4ff69c1.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/2095498218/dynamic", + "label": "", + "mid": 2095498218, + "name": "次元壁小宋", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/640b9ee5a12d77bb7431cfc9c815dd25c05f9915.png", + "image_enhance_frame": "", + "n_pid": 68553, + "name": "坠落·空", + "pid": 68553 + }, + "pub_action": "", + "pub_location_text": "", + "pub_time": "03月15日", + "pub_ts": 1742006883, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1683129600000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": null, + "desc": { + "rich_text_nodes": [ + { + "orig_text": "我参与了投票", + "text": "我参与了投票", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "​你们露过声吗?", + "rid": "14689974", + "text": "​你们露过声吗?", + "type": "RICH_TEXT_NODE_TYPE_VOTE" + }, + { + "orig_text": "我投给了没露过", + "text": "我投给了没露过", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "我参与了投票​你们露过声吗?我投给了没露过" + }, + "major": null, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "置顶", + "params": { + "dynamic_id": "1044400681921806345", + "status": false + }, + "type": "THREE_POINT_TOP" + }, + { + "label": "删除", + "modal": { + "cancel": "取消", + "confirm": "确认删除", + "content": "动态删除后将无法恢复,请谨慎操作", + "title": "要删除动态吗?" + }, + "params": { + "dyn_id_str": "1044400681921806345", + "dyn_type": 1, + "rid_str": "1044400681921806345" + }, + "type": "THREE_POINT_DELETE" + } + ] + }, + "module_stat": { + "comment": { + "count": 0, + "forbidden": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 0, + "forbidden": false, + "status": false + } + } + }, + "orig": { + "basic": { + "comment_id_str": "", + "comment_type": 0, + "jump_url": "//www.bilibili.com/opus/1041900177728733184", + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "" + }, + "id_str": "1041900177728733184", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i2.hdslb.com/bfs/face/70af6734f5e92c4345c592b099200b9519fdac23.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "3546855879215762" + }, + "face": "https://i2.hdslb.com/bfs/face/70af6734f5e92c4345c592b099200b9519fdac23.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/3546855879215762/dynamic", + "label": "", + "mid": 3546855879215762, + "name": "爱玩休闲区的樱梦雪", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "", + "pub_time": "", + "pub_ts": 1741424689, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 0, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 0 + } + }, + "module_dynamic": { + "additional": { + "type": "ADDITIONAL_TYPE_VOTE", + "vote": { + "button": { + "jump_style": { + "text": "参与" + }, + "type": 1 + }, + "choice_cnt": 1, + "default_share": 1, + "desc": "818人参与", + "end_time": 1743239041, + "join_num": 818, + "status": 4, + "title": "你们露过声吗?", + "type": null, + "uid": 3546855879215762, + "vote_id": 14689974 + } + }, + "desc": null, + "major": { + "opus": { + "fold_action": [ + "展开", + "收起" + ], + "jump_url": "//www.bilibili.com/opus/1041900177728733184", + "pics": [], + "summary": { + "rich_text_nodes": [ + { + "orig_text": "我发起了一个投票", + "text": "我发起了一个投票", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "orig_text": "​你们露过声吗?", + "rid": "14689974", + "text": "​你们露过声吗?", + "type": "RICH_TEXT_NODE_TYPE_VOTE" + } + ], + "text": "我发起了一个投票​你们露过声吗?" + }, + "title": null + }, + "type": "MAJOR_TYPE_OPUS" + }, + "topic": null + } + }, + "type": "DYNAMIC_TYPE_WORD", + "visible": true + }, + "type": "DYNAMIC_TYPE_FORWARD", + "visible": true + } + ], + "offset": "1044400681921806345", + "update_baseline": "", + "update_num": 0 + } +} +``` + +</details> + +## 设置置顶动态 + +参见 [设置置顶动态](action.md#设置置顶动态) + +## 取消置顶动态 + +参见 [取消置顶动态](action.md#取消置顶动态) diff --git a/bb-api-collect/docs/dynamic/topic.md b/bb-api-collect/docs/dynamic/topic.md new file mode 100644 index 0000000000..d553635d76 --- /dev/null +++ b/bb-api-collect/docs/dynamic/topic.md @@ -0,0 +1,5736 @@ +# 话题 + +## 获取话题下动态列表 + +> https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/topic +> https://app.bilibili.com/x/topic/web/details/cards + +*请求方法: GET* + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---- | ------ | ---- | +| topic_id | number | 话题 ID | 必要 | | +| sort_by | number | 排序方式 | 不必要 | 见回复 `data.topic_card_list.topic_sort_by_conf` 对象 | +| offset | string | 偏移量 | 不必要 | 上一次请求回复的 `data.topic_card_list.offset` | +| page_size | number | 每页数量 | 不必要 | 默认为 `20` | +| source | string | 来源 | 不必要 | 如 `Web` (接口 1) `H5` (接口 2) | +| features | string | 功能模块 | 不必要 | 仅接口 1, 如 `itemOpusStyle,listOnlyfans,opusBigCover,onlyfansVote,decorationCard`, 参见 [功能模块](../opus/features.md) | +| web_location | string | `333.1036` | 不必要 | 仅接口 2 | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | number | 返回值 | 0: 成功 | +| data | object | 数据本体 | | +| message | string | 错误信息 | 成功时为 `0` | +| ttl | number | `1` | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| related_topics | object | 相关话题? | 空对象 | +| topic_card_list | object | 话题卡片列表 | | + +`data.topic_card_list` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| has_more | boolean | 是否有更多 | | +| items | object[] | 动态列表 | 套了个娃 | +| offset | string | 偏移量 | | +| topic_sort_by_conf | object | 排序方式配置 | | + +`data.topic_card_list.items[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| dynamic_card_item | object | 动态 | 基本同 [获取全部动态列表](all.md#获取全部动态列表) 的 `data.items[]` 对象 | +| topic_type | string | 话题类型? | 目前所见似乎只有 `"DYNAMIC"` | + +`data.topic_card_list.topic_sort_by_conf` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| all_sort_by | object[] | 全部排序方式 | | +| default_sort_by | number | 默认排序方式 | | +| show_sort_by | number | 展示的排序方式 | | + +`data.topic_card_list.topic_sort_by_conf.all_sort_by[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| sort_by | number | 排序方式 | | +| sort_name | string | 排序名称 | | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/topic?topic_id=34958&sort_by=0&offset=&page_size=20&source=Web&features=itemOpusStyle%2ClistOnlyfans%2CopusBigCover%2ConlyfansVote%2CdecorationCard' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "related_topics": {}, + "topic_card_list": { + "has_more": true, + "items": [ + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "114687152757937", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "114687152757937" + }, + "id_str": "1078676238928707587", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/38f6660463a00c412c5cd1917f91bbd8119ee7bc.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 4, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "1310515966" + }, + "face": "https://i1.hdslb.com/bfs/face/38f6660463a00c412c5cd1917f91bbd8119ee7bc.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/1310515966/dynamic", + "label": "", + "mid": 1310515966, + "name": "声优音画", + "official_verify": { + "desc": "", + "type": 1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "06月15日", + "pub_ts": 1749987283, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 0, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 0 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "114687152757937", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1hCMtzKEyP", + "cover": "http://i2.hdslb.com/bfs/archive/5994a570d9a12a89bcb50258455ff1302efdb97b.jpg", + "desc": "“把妹王”火麟飞携金句杀疯全场,少年意气燃爆童年DNA!\n出镜配音演员:鞠月斌@配音演员鞠月斌", + "disable_preview": 0, + "duration_text": "00:43", + "jump_url": "//www.bilibili.com/video/BV1hCMtzKEyP/", + "stat": { + "danmaku": "69", + "play": "39.3万" + }, + "title": "声优音画|《超兽武装》经典热血回归!", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 328, + "forbidden": false + }, + "forward": { + "count": 6, + "forbidden": false + }, + "like": { + "count": 40598, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "473683637", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "473683637" + }, + "id_str": "712669283716431894", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i2.hdslb.com/bfs/face/eba2897173640343e5f9294f365ee0eb2082f525.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 1, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "387122516" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/garb/open/86e89e72b134283bf72e66c8e7c6e49b2d26d9e3.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/garb/open/86e89e72b134283bf72e66c8e7c6e49b2d26d9e3.png", + "fan": { + "color": "#BFC8D2", + "color_format": { + "colors": [ + "#B8C7D0FF", + "#A2A7B0FF" + ], + "end_point": "100,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "XXXX", + "num_desc": "008059", + "number": 8059 + }, + "id": 69432, + "image_enhance": "https://i0.hdslb.com/bfs/garb/open/86e89e72b134283bf72e66c8e7c6e49b2d26d9e3.png", + "item_id": 69432, + "jump_url": "https://www.bilibili.com/h5/mall/digital-card/home?act_id=102704&from=post&f_source=garb&-Abrowser=live&hybrid_set_header=2&navhide=1&anchor_task=1", + "name": "名侦探柯南30周年" + }, + "face": "https://i2.hdslb.com/bfs/face/eba2897173640343e5f9294f365ee0eb2082f525.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/387122516/dynamic", + "label": "", + "mid": 387122516, + "name": "橙子面包酱_", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2022年10月03日", + "pub_ts": 1664769648, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1755273600000, + "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": "http://i0.hdslb.com/bfs/vip/label_annual.png", + "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": "来啦~", + "text": "来啦~", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "来啦~" + }, + "major": { + "archive": { + "aid": "473683637", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1BT411K7Gv", + "cover": "http://i1.hdslb.com/bfs/archive/d9ac37b09af57553b5d313eef60040a133c730d8.jpg", + "desc": "如果再给我一次机会,我一定会早点拍视频,呜呜呜呜拍到凌晨真的太困了dT-Tb\n这首歌很多人点,我也很喜欢!!!(感觉自己没唱好•᷄ࡇ•᷅)", + "disable_preview": 0, + "duration_text": "04:30", + "jump_url": "//www.bilibili.com/video/BV1BT411K7Gv/", + "stat": { + "danmaku": "463", + "play": "53.9万" + }, + "title": "趁17岁唱一首本兮的《未成年》!!!", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 1365, + "forbidden": false + }, + "forward": { + "count": 241, + "forbidden": false + }, + "like": { + "count": 28628, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "113231091795405", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "113231091795405" + }, + "id_str": "983253769442557958", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i2.hdslb.com/bfs/face/e84fa744dd3cefd073c446fc7737ff3b2482e3a7.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 3, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "2170934" + }, + "face": "https://i2.hdslb.com/bfs/face/e84fa744dd3cefd073c446fc7737ff3b2482e3a7.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/2170934/dynamic", + "label": "", + "mid": 2170934, + "name": "明月庄主", + "official_verify": { + "desc": "", + "type": 0 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2024年10月01日", + "pub_ts": 1727770008, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1925308800000, + "label": { + "bg_color": "#FB7299", + "bg_style": 1, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/adb599797dd171e2d3d6d012f448b49679258344.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/sGu57N6pgK.png", + "label_theme": "ten_annual_vip", + "path": "http://i0.hdslb.com/bfs/vip/label_annual.png", + "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": "这个MC存档10岁了!明月庄主单机生存开档十周年。存档发布", + "text": "这个MC存档10岁了!明月庄主单机生存开档十周年。存档发布", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "这个MC存档10岁了!明月庄主单机生存开档十周年。存档发布" + }, + "major": { + "archive": { + "aid": "113231091795405", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1RyxYeGEqC", + "cover": "http://i0.hdslb.com/bfs/archive/d91bd52665bbc354a57bb6470a56504373092adf.jpg", + "desc": "这个MC存档10岁了!明月庄主单机生存开档十周年。存档发布\n\n百度网盘:明月庄主的原版单机生存.优化过1.21.1.7z\n链接:https://pan.baidu.com/s/1eKocLGQyo7sVyysEK1t4lA?pwd=moon \n提取码:moon \n我用夸克网盘分享了「明月庄主的原版单机生存.优化过1.21.1.7z」\n链接:https://pan.quark.cn/s/f47bc9c695b7", + "disable_preview": 0, + "duration_text": "09:21", + "jump_url": "//www.bilibili.com/video/BV1RyxYeGEqC/", + "stat": { + "danmaku": "455", + "play": "9.6万" + }, + "title": "这个MC存档10岁了!明月庄主单机生存开档十周年。存档发布", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 883, + "forbidden": false + }, + "forward": { + "count": 33, + "forbidden": false + }, + "like": { + "count": 8656, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "812023623", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "812023623" + }, + "id_str": "666777038344945689", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "http://i0.hdslb.com/bfs/face/010e6ac40fef4d6560d5d716128b499ea5edf729.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "36776949" + }, + "face": "http://i0.hdslb.com/bfs/face/010e6ac40fef4d6560d5d716128b499ea5edf729.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/36776949/dynamic", + "label": "", + "mid": 36776949, + "name": "柚子爱好者", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2022年06月01日", + "pub_ts": 1654084527, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1617552000000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "812023623", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1N34y177uz", + "cover": "http://i1.hdslb.com/bfs/archive/b0ac9129e78b7cc4cc95d685c38b076dc0cdcf8e.jpg", + "desc": "最美好的六一礼物", + "disable_preview": 0, + "duration_text": "02:08", + "jump_url": "//www.bilibili.com/video/BV1N34y177uz/", + "stat": { + "danmaku": "240", + "play": "11.3万" + }, + "title": "最美好的六一礼物", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 359, + "forbidden": false + }, + "forward": { + "count": 26, + "forbidden": false + }, + "like": { + "count": 9186, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "687206432", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "687206432" + }, + "id_str": "696709872294559798", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i2.hdslb.com/bfs/face/eba2897173640343e5f9294f365ee0eb2082f525.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 1, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "387122516" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/garb/open/86e89e72b134283bf72e66c8e7c6e49b2d26d9e3.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/garb/open/86e89e72b134283bf72e66c8e7c6e49b2d26d9e3.png", + "fan": { + "color": "#BFC8D2", + "color_format": { + "colors": [ + "#B8C7D0FF", + "#A2A7B0FF" + ], + "end_point": "100,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "XXXX", + "num_desc": "008059", + "number": 8059 + }, + "id": 69432, + "image_enhance": "https://i0.hdslb.com/bfs/garb/open/86e89e72b134283bf72e66c8e7c6e49b2d26d9e3.png", + "item_id": 69432, + "jump_url": "https://www.bilibili.com/h5/mall/digital-card/home?act_id=102704&from=post&f_source=garb&-Abrowser=live&hybrid_set_header=2&navhide=1&anchor_task=1", + "name": "名侦探柯南30周年" + }, + "face": "https://i2.hdslb.com/bfs/face/eba2897173640343e5f9294f365ee0eb2082f525.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/387122516/dynamic", + "label": "", + "mid": 387122516, + "name": "橙子面包酱_", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2022年08月21日", + "pub_ts": 1661053808, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1755273600000, + "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": "http://i0.hdslb.com/bfs/vip/label_annual.png", + "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": "♥(。→v←。)♥本兮本兮本兮", + "text": "♥(。→v←。)♥本兮本兮本兮", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "♥(。→v←。)♥本兮本兮本兮" + }, + "major": { + "archive": { + "aid": "687206432", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1FU4y1k75W", + "cover": "http://i0.hdslb.com/bfs/archive/1890a9b9362d57fe8da5aaf7c52c90b5317e821a.jpg", + "desc": "好多人点这首歌,但是我真的驾驭不了wwww˃ʍ˂\n唱错了几句(ᇂ_ᇂ|||)", + "disable_preview": 0, + "duration_text": "02:55", + "jump_url": "//www.bilibili.com/video/BV1FU4y1k75W/", + "stat": { + "danmaku": "125", + "play": "11万" + }, + "title": "【爷青回系列】《你在看孤独的风景》cover本兮", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 477, + "forbidden": false + }, + "forward": { + "count": 34, + "forbidden": false + }, + "like": { + "count": 5837, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "452289087", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "452289087" + }, + "id_str": "875680820193394744", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i2.hdslb.com/bfs/face/9780c885127ddf5ae48b1f98c43e63b97c89ac14.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "7062857" + }, + "face": "https://i2.hdslb.com/bfs/face/9780c885127ddf5ae48b1f98c43e63b97c89ac14.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/7062857/dynamic", + "label": "", + "mid": 7062857, + "name": "星际靓仔", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2023年12月16日", + "pub_ts": 1702723729, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1747670400000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "452289087", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1vj411p784", + "cover": "http://i1.hdslb.com/bfs/archive/3e50d9370c40bd5ea31ecf84419e02c913e895fa.jpg", + "desc": "非常感谢@君龙-金君龙 老师的音频授权!这首男版的《只凝视着你》燃爆了!好声音值得被更多人听到!\n歌手简介:金君龙,曾用名君龙,出生于吉林省延边,中国朝鲜族歌手、音乐制作人、阿里郎组合主唱。(以上内容来自百度百科)", + "disable_preview": 0, + "duration_text": "04:28", + "jump_url": "//www.bilibili.com/video/BV1vj411p784/", + "stat": { + "danmaku": "529", + "play": "20.3万" + }, + "title": "恐怖如斯!男歌手竟原调翻唱灌篮高手片尾曲《只凝视着你》!", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 508, + "forbidden": false + }, + "forward": { + "count": 23, + "forbidden": false + }, + "like": { + "count": 6151, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "684664595", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "684664595" + }, + "id_str": "668133732620697639", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i2.hdslb.com/bfs/face/eba2897173640343e5f9294f365ee0eb2082f525.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 1, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "387122516" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/garb/open/86e89e72b134283bf72e66c8e7c6e49b2d26d9e3.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/garb/open/86e89e72b134283bf72e66c8e7c6e49b2d26d9e3.png", + "fan": { + "color": "#BFC8D2", + "color_format": { + "colors": [ + "#B8C7D0FF", + "#A2A7B0FF" + ], + "end_point": "100,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "XXXX", + "num_desc": "008059", + "number": 8059 + }, + "id": 69432, + "image_enhance": "https://i0.hdslb.com/bfs/garb/open/86e89e72b134283bf72e66c8e7c6e49b2d26d9e3.png", + "item_id": 69432, + "jump_url": "https://www.bilibili.com/h5/mall/digital-card/home?act_id=102704&from=post&f_source=garb&-Abrowser=live&hybrid_set_header=2&navhide=1&anchor_task=1", + "name": "名侦探柯南30周年" + }, + "face": "https://i2.hdslb.com/bfs/face/eba2897173640343e5f9294f365ee0eb2082f525.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/387122516/dynamic", + "label": "", + "mid": 387122516, + "name": "橙子面包酱_", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2022年06月05日", + "pub_ts": 1654400407, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1755273600000, + "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": "http://i0.hdslb.com/bfs/vip/label_annual.png", + "text": "年度大会员", + "text_color": "#FFFFFF", + "use_img_label": true + }, + "nickname_color": "#FB7299", + "status": 1, + "theme_type": 0, + "type": 2 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "684664595", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV15U4y117XE", + "cover": "http://i1.hdslb.com/bfs/archive/abb1dbb1b3b194be1f44ee049a065387bef5560b.jpg", + "desc": "-", + "disable_preview": 0, + "duration_text": "02:05", + "jump_url": "//www.bilibili.com/video/BV15U4y117XE/", + "stat": { + "danmaku": "56", + "play": "9.6万" + }, + "title": "当然很《爱你》啦!!!今天是王心凌女孩~", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 290, + "forbidden": false + }, + "forward": { + "count": 17, + "forbidden": false + }, + "like": { + "count": 5214, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "703146337", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "703146337" + }, + "id_str": "838814083642818565", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/1d89b423a12ba86987c5c4d4098b285bea645b1c.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 1, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "44044545" + }, + "face": "https://i0.hdslb.com/bfs/face/1d89b423a12ba86987c5c4d4098b285bea645b1c.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/44044545/dynamic", + "label": "", + "mid": 44044545, + "name": "双马尾钳子", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2023年09月08日", + "pub_ts": 1694140023, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1775750400000, + "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": "http://i0.hdslb.com/bfs/vip/label_annual.png", + "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": "雾草我做了四天(咳咳)(吐血)", + "text": "雾草我做了四天(咳咳)(吐血)", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "雾草我做了四天(咳咳)(吐血)" + }, + "major": { + "archive": { + "aid": "703146337", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1gm4y1K7rE", + "cover": "http://i1.hdslb.com/bfs/archive/04aadffdc48e010905a0ca2be4167dc4d5300022.jpg", + "desc": "BGM:BV1hT411L7fk\n剧情梗概:\n威廉和鲍勃本来是一对神界情侣,鲍勃为了保护威廉被乌鸦打落凡间转世为人,威廉为了追寻鲍勃,化身入树中,历经千辛万苦终于也转世为人。然而此时的两人已不认得对方,仅靠缘分结为情侣,却处处互相折磨,在痛苦中越陷越深,最后两人双双放手成全对方,各自踏上了新的人生之路。\n\n内含大量游戏贴图替换,剧情为恶搞,请勿当真!(不会真有人当真吧)", + "disable_preview": 0, + "duration_text": "04:25", + "jump_url": "//www.bilibili.com/video/BV1gm4y1K7rE/", + "stat": { + "danmaku": "193", + "play": "6.8万" + }, + "title": "【锈湖】用仙剑奇侠传三的方式打开锈湖", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 200, + "forbidden": false + }, + "forward": { + "count": 21, + "forbidden": false + }, + "like": { + "count": 5565, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "511956063", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "511956063" + }, + "id_str": "664837929337618438", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/04345e01722540db8dce258f8a0051e1a6dba029.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "19954576" + }, + "face": "https://i1.hdslb.com/bfs/face/04345e01722540db8dce258f8a0051e1a6dba029.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/19954576/dynamic", + "label": "", + "mid": 19954576, + "name": "克里斯不关门_", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2022年05月27日", + "pub_ts": 1653633043, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 0, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 0 + } + }, + "module_dynamic": { + "additional": null, + "desc": { + "rich_text_nodes": [ + { + "orig_text": "王心凌男孩因为一条十年前表演《爱你》的视频 人生第一次被采访了 而且还是央视网…来听听看我的小作文发挥的咋样吧哈哈~还没看过原视频的欢迎来我的主页看看哟~ P.S. 感谢大家之前的热情回应,当年节目的完整版会在这周晚点发,记得关注我才不会错过更新哦 感恩! <3", + "text": "王心凌男孩因为一条十年前表演《爱你》的视频 人生第一次被采访了 而且还是央视网…来听听看我的小作文发挥的咋样吧哈哈~还没看过原视频的欢迎来我的主页看看哟~ P.S. 感谢大家之前的热情回应,当年节目的完整版会在这周晚点发,记得关注我才不会错过更新哦 感恩! <3", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "王心凌男孩因为一条十年前表演《爱你》的视频 人生第一次被采访了 而且还是央视网…来听听看我的小作文发挥的咋样吧哈哈~还没看过原视频的欢迎来我的主页看看哟~ P.S. 感谢大家之前的热情回应,当年节目的完整版会在这周晚点发,记得关注我才不会错过更新哦 感恩! <3" + }, + "major": { + "archive": { + "aid": "511956063", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1zg411o7Sn", + "cover": "http://i0.hdslb.com/bfs/archive/f9969e889d36042a4addfbe6cffc2b1ccf57efc2.jpg", + "desc": "王心凌男孩因为一条十年前表演《爱你》的视频 人生第一次被采访了 而且还是央视网…来听听看我的小作文发挥的咋样吧哈哈~还没看过原视频的欢迎来我的主页看看哟~ P.S. 感谢大家之前的热情回应,当年节目的完整版会在这周晚点发,记得关注我才不会错过更新哦 感恩! <3", + "disable_preview": 0, + "duration_text": "03:16", + "jump_url": "//www.bilibili.com/video/BV1zg411o7Sn/", + "stat": { + "danmaku": "59", + "play": "5.7万" + }, + "title": "王心凌男孩你好 我是央视网记者 可以问你几个问题吗?", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 136, + "forbidden": false + }, + "forward": { + "count": 9, + "forbidden": false + }, + "like": { + "count": 3696, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "526638349", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "526638349" + }, + "id_str": "778087296460128312", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "http://i0.hdslb.com/bfs/face/dbe9074fda0c174a851d0d79e1bd27ddaa18c9e5.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "419805517" + }, + "face": "http://i0.hdslb.com/bfs/face/dbe9074fda0c174a851d0d79e1bd27ddaa18c9e5.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/419805517/dynamic", + "label": "", + "mid": 419805517, + "name": "精分小阿夺", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2023年03月28日", + "pub_ts": 1680000966, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 0, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 0 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "526638349", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1xM411g7uZ", + "cover": "http://i2.hdslb.com/bfs/archive/ea2e6054e898241debf1fe991b5e36ab562a11df.jpg", + "desc": "-", + "disable_preview": 0, + "duration_text": "00:47", + "jump_url": "//www.bilibili.com/video/BV1xM411g7uZ/", + "stat": { + "danmaku": "55", + "play": "4.7万" + }, + "title": "有哪些动漫曾带给你“爷青回”的瞬间?", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 45, + "forbidden": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 3410, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "726866951", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "726866951" + }, + "id_str": "663496718409531463", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/675aa52717ee9e5aad48e8bd8dd2e1f259b3200c.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 1, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "77060623" + }, + "face": "https://i1.hdslb.com/bfs/face/675aa52717ee9e5aad48e8bd8dd2e1f259b3200c.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/77060623/dynamic", + "label": "", + "mid": 77060623, + "name": "pH一sH_肨虎花", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2022年05月23日", + "pub_ts": 1653320768, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1799596800000, + "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": "http://i0.hdslb.com/bfs/vip/label_annual.png", + "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": "午夜偷袭!", + "text": "午夜偷袭!", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "午夜偷袭!" + }, + "major": { + "archive": { + "aid": "726866951", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1iS4y1z7oC", + "cover": "http://i0.hdslb.com/bfs/archive/8b6fe643251147bc3a1791d028c56aa1c2ac6984.jpg", + "desc": "听到甜心教主的《爱你》真的忍不住了,忍着伤痛画了这一笔,希望能够得到你的三连!", + "disable_preview": 0, + "duration_text": "03:52", + "jump_url": "//www.bilibili.com/video/BV1iS4y1z7oC/", + "stat": { + "danmaku": "310", + "play": "3.3万" + }, + "title": "这一笔,爷青回!王心凌《梦的光点》", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 211, + "forbidden": false + }, + "forward": { + "count": 3, + "forbidden": false + }, + "like": { + "count": 2485, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "114820430961589", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "114820430961589" + }, + "id_str": "1087411287614291971", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/20843b2d7edf0d096bd09ff767065ebcec6fb3ad.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "3546766148372797" + }, + "face": "https://i1.hdslb.com/bfs/face/20843b2d7edf0d096bd09ff767065ebcec6fb3ad.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/3546766148372797/dynamic", + "label": "", + "mid": 3546766148372797, + "name": "柿杂乱", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "07月09日", + "pub_ts": 1752021070, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 0, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 0 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "114820430961589", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1XMGszTE8s", + "cover": "http://i0.hdslb.com/bfs/archive/ae8caade776af7e197d8b172f18004916d1f2eb8.jpg", + "desc": "这个视频抠图剪辑找素材花了好几天时间,期间运气太非酋抽卡一直不出彩,被迫开了个新号,感谢你对这个系列的支持。", + "disable_preview": 0, + "duration_text": "00:33", + "jump_url": "//www.bilibili.com/video/BV1XMGszTE8s/", + "stat": { + "danmaku": "39", + "play": "1.7万" + }, + "title": "【SCP×BA】SCP蔚蓝档案合作组织。希望这个也能火。", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 223, + "forbidden": false + }, + "forward": { + "count": 2, + "forbidden": false + }, + "like": { + "count": 2092, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "946166332", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "946166332" + }, + "id_str": "738695406850932758", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/2e591a702d42f753fdfb847825274ef745675e51.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/488870931b1bba66da36d22848f0720480d3d79a.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 1, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "layers": [ + { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/2e591a702d42f753fdfb847825274ef745675e51.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + { + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_animation": { + "webp_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/5974f17f9d96a88bafba2f6d18d647a486e88312.webp" + }, + "src_type": 1 + } + }, + "res_type": 4 + }, + "visible": true + } + ] + }, + { + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 1, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + } + ], + "mid": "2518014" + }, + "face": "https://i0.hdslb.com/bfs/face/2e591a702d42f753fdfb847825274ef745675e51.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/2518014/dynamic", + "label": "", + "mid": 2518014, + "name": "熊木柚子", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/488870931b1bba66da36d22848f0720480d3d79a.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/5974f17f9d96a88bafba2f6d18d647a486e88312.webp", + "image_enhance_frame": "https://i0.hdslb.com/bfs/garb/item/4316a3910bb0bd6f2f1c267a3e9187f0b9fe5bd0.png", + "n_pid": 32257, + "name": "EveOneCat2", + "pid": 32257 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2022年12月12日", + "pub_ts": 1670829327, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1786550400000, + "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": "http://i0.hdslb.com/bfs/vip/label_annual.png", + "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": "彩虹岛里得到的第一件稀有武器就是“黑发狐妖可爱魔杖”", + "text": "彩虹岛里得到的第一件稀有武器就是“黑发狐妖可爱魔杖”", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "彩虹岛里得到的第一件稀有武器就是“黑发狐妖可爱魔杖”" + }, + "major": { + "archive": { + "aid": "946166332", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1iW4y1M7y2", + "cover": "http://i2.hdslb.com/bfs/archive/f49ae764cbee2f4bcda09334f1a2c64488597b76.jpg", + "desc": "彩虹岛游戏音乐翻奏\n作曲:ESti\n演奏乐器:长笛", + "disable_preview": 0, + "duration_text": "02:20", + "jump_url": "//www.bilibili.com/video/BV1iW4y1M7y2/", + "stat": { + "danmaku": "50", + "play": "4.5万" + }, + "title": "【彩虹岛】山岳地带bgm——《shanghai runner》", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 302, + "forbidden": false + }, + "forward": { + "count": 10, + "forbidden": false + }, + "like": { + "count": 2893, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "274780128", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "274780128" + }, + "id_str": "830237944487870470", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i2.hdslb.com/bfs/face/0e66175c1933add3de8c7ff2612912b0ed0eabcb.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "1832864498" + }, + "face": "https://i2.hdslb.com/bfs/face/0e66175c1933add3de8c7ff2612912b0ed0eabcb.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/1832864498/dynamic", + "label": "", + "mid": 1832864498, + "name": "桃之夭夭之桃", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2023年08月16日", + "pub_ts": 1692143235, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 0, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 0 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "274780128", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1tF411y73f", + "cover": "http://i2.hdslb.com/bfs/archive/ca224c68033c77cd028aa8c748cc544e0c3db746.jpg", + "desc": "最近真的很忙,忙着生病,忙着工作,忙着搬家,所以抓紧时间更新一下。", + "disable_preview": 0, + "duration_text": "02:20", + "jump_url": "//www.bilibili.com/video/BV1tF411y73f/", + "stat": { + "danmaku": "108", + "play": "3.4万" + }, + "title": "你不开心就来看我视频咯!Just forget me please!", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 152, + "forbidden": false + }, + "forward": { + "count": 2, + "forbidden": false + }, + "like": { + "count": 1221, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "404110312", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "404110312" + }, + "id_str": "823361087690768450", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/007e6c54bc86b40950b2d213973cd732f47163ce.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 4, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "16836724" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/garb/item/ceb7d1827f13103f0d499f62b1ffa8af5f05c143.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/garb/item/ceb7d1827f13103f0d499f62b1ffa8af5f05c143.png", + "fan": { + "color": "#942b32", + "color_format": { + "colors": [ + "#942b32FF", + "#942b32FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "刺客信条15周年", + "num_desc": "000001", + "number": 1 + }, + "id": 38456, + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/ceb7d1827f13103f0d499f62b1ffa8af5f05c143.png", + "item_id": 38456, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=38456&isdiy=0&part=card&from=post&f_source=garb&vmid=16836724&native.theme=1&navhide=1", + "name": "刺客信条15周年粉丝专属" + }, + "face": "https://i1.hdslb.com/bfs/face/007e6c54bc86b40950b2d213973cd732f47163ce.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/16836724/dynamic", + "label": "", + "mid": 16836724, + "name": "UBISOFT育碧", + "official_verify": { + "desc": "", + "type": 1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2023年07月28日", + "pub_ts": 1690542092, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1755792000000, + "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": "http://i0.hdslb.com/bfs/vip/label_annual.png", + "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": "每个人都是如王子一般的主角,这段名为人生的冒险,就是一场终将胜利的横版闯关。\n《波斯王子》系列历经34年沉浮,如今", + "text": "每个人都是如王子一般的主角,这段名为人生的冒险,就是一场终将胜利的横版闯关。\n《波斯王子》系列历经34年沉浮,如今", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "jump_url": "//search.bilibili.com/all?keyword=%E6%B3%A2%E6%96%AF%E7%8E%8B%E5%AD%90%EF%BC%9A%E5%A4%B1%E8%90%BD%E7%9A%84%E7%8E%8B%E5%86%A0", + "orig_text": "#波斯王子:失落的王冠#", + "text": "#波斯王子:失落的王冠#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + { + "orig_text": "回归系列原点,以横版闯关游戏的姿态归来!想知道《波斯王子》系列是如何走到今天的吗?点击视频进入这场人生的“横版闯关”吧", + "text": "回归系列原点,以横版闯关游戏的姿态归来!想知道《波斯王子》系列是如何走到今天的吗?点击视频进入这场人生的“横版闯关”吧", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + }, + { + "emoji": { + "icon_url": "https://i0.hdslb.com/bfs/emote/431432c43da3ee5aab5b0e4f8931953e649e9975.png", + "size": 1, + "text": "[打call]", + "type": 1 + }, + "orig_text": "[打call]", + "text": "[打call]", + "type": "RICH_TEXT_NODE_TYPE_EMOJI" + } + ], + "text": "每个人都是如王子一般的主角,这段名为人生的冒险,就是一场终将胜利的横版闯关。\n《波斯王子》系列历经34年沉浮,如今#波斯王子:失落的王冠#回归系列原点,以横版闯关游戏的姿态归来!想知道《波斯王子》系列是如何走到今天的吗?点击视频进入这场人生的“横版闯关”吧[打call]" + }, + "major": { + "archive": { + "aid": "404110312", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV17V41157hA", + "cover": "http://i2.hdslb.com/bfs/archive/9c275f2eb0f3c6b051e5c1abbda1db8201dc7b0f.jpg", + "desc": "时之神力,逆转乾坤;波斯舞台,王子归来!《波斯王子:失落的王冠》的传奇冒险将于2024年1月18日开启!", + "disable_preview": 0, + "duration_text": "05:13", + "jump_url": "//www.bilibili.com/video/BV17V41157hA/", + "stat": { + "danmaku": "25", + "play": "4.6万" + }, + "title": "波斯最强体操运动员是谁?", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 92, + "forbidden": false + }, + "forward": { + "count": 5, + "forbidden": false + }, + "like": { + "count": 1350, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "606448624", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "606448624" + }, + "id_str": "741290237143023616", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/2e591a702d42f753fdfb847825274ef745675e51.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/488870931b1bba66da36d22848f0720480d3d79a.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 1, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "layers": [ + { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/2e591a702d42f753fdfb847825274ef745675e51.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + { + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_animation": { + "webp_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/5974f17f9d96a88bafba2f6d18d647a486e88312.webp" + }, + "src_type": 1 + } + }, + "res_type": 4 + }, + "visible": true + } + ] + }, + { + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 1, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + } + ], + "mid": "2518014" + }, + "face": "https://i0.hdslb.com/bfs/face/2e591a702d42f753fdfb847825274ef745675e51.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/2518014/dynamic", + "label": "", + "mid": 2518014, + "name": "熊木柚子", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/488870931b1bba66da36d22848f0720480d3d79a.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/5974f17f9d96a88bafba2f6d18d647a486e88312.webp", + "image_enhance_frame": "https://i0.hdslb.com/bfs/garb/item/4316a3910bb0bd6f2f1c267a3e9187f0b9fe5bd0.png", + "n_pid": 32257, + "name": "EveOneCat2", + "pid": 32257 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2022年12月19日", + "pub_ts": 1671433483, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1786550400000, + "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": "http://i0.hdslb.com/bfs/vip/label_annual.png", + "text": "年度大会员", + "text_color": "#FFFFFF", + "use_img_label": true + }, + "nickname_color": "#FB7299", + "status": 1, + "theme_type": 0, + "type": 2 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "606448624", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1J84y147af", + "cover": "http://i2.hdslb.com/bfs/archive/81ea384080b7598ed4a4ac7bc3cd68341932b042.jpg", + "desc": "-", + "disable_preview": 0, + "duration_text": "02:19", + "jump_url": "//www.bilibili.com/video/BV1J84y147af/", + "stat": { + "danmaku": "17", + "play": "1.4万" + }, + "title": "【彩虹岛】Merry Christmas 尖叫雪地BGM——《snowfield雪地回音》", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 214, + "forbidden": false + }, + "forward": { + "count": 5, + "forbidden": false + }, + "like": { + "count": 994, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "772580225", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "772580225" + }, + "id_str": "700423623235600425", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i2.hdslb.com/bfs/face/eba2897173640343e5f9294f365ee0eb2082f525.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 1, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "387122516" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/garb/open/86e89e72b134283bf72e66c8e7c6e49b2d26d9e3.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/garb/open/86e89e72b134283bf72e66c8e7c6e49b2d26d9e3.png", + "fan": { + "color": "#BFC8D2", + "color_format": { + "colors": [ + "#B8C7D0FF", + "#A2A7B0FF" + ], + "end_point": "100,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "XXXX", + "num_desc": "008059", + "number": 8059 + }, + "id": 69432, + "image_enhance": "https://i0.hdslb.com/bfs/garb/open/86e89e72b134283bf72e66c8e7c6e49b2d26d9e3.png", + "item_id": 69432, + "jump_url": "https://www.bilibili.com/h5/mall/digital-card/home?act_id=102704&from=post&f_source=garb&-Abrowser=live&hybrid_set_header=2&navhide=1&anchor_task=1", + "name": "名侦探柯南30周年" + }, + "face": "https://i2.hdslb.com/bfs/face/eba2897173640343e5f9294f365ee0eb2082f525.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/387122516/dynamic", + "label": "", + "mid": 387122516, + "name": "橙子面包酱_", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2022年08月31日", + "pub_ts": 1661918483, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1755273600000, + "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": "http://i0.hdslb.com/bfs/vip/label_annual.png", + "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": "上学去了˃ʍ˂", + "text": "上学去了˃ʍ˂", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "上学去了˃ʍ˂" + }, + "major": { + "archive": { + "aid": "772580225", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1o14y1W7AZ", + "cover": "http://i2.hdslb.com/bfs/archive/fdf552056a23e3118c15b68f4acf3e62ae9a043d.jpg", + "desc": "开头有点夹子,对不起>人<!!!", + "disable_preview": 0, + "duration_text": "02:43", + "jump_url": "//www.bilibili.com/video/BV1o14y1W7AZ/", + "stat": { + "danmaku": "30", + "play": "1.7万" + }, + "title": "【爷青回系列】《某个心跳》cover本兮", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 159, + "forbidden": false + }, + "forward": { + "count": 6, + "forbidden": false + }, + "like": { + "count": 1222, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "360051457", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "360051457" + }, + "id_str": "809870209103953945", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/991b66faf44236cdacacda526b9ab33f1445b10e.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/garb/item/488870931b1bba66da36d22848f0720480d3d79a.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 1, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "layers": [ + { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/face/991b66faf44236cdacacda526b9ab33f1445b10e.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + { + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_animation": { + "webp_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i1.hdslb.com/bfs/garb/item/5974f17f9d96a88bafba2f6d18d647a486e88312.webp" + }, + "src_type": 1 + } + }, + "res_type": 4 + }, + "visible": true + } + ] + }, + { + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 1, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + } + ], + "mid": "73276978" + }, + "face": "https://i1.hdslb.com/bfs/face/991b66faf44236cdacacda526b9ab33f1445b10e.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/73276978/dynamic", + "label": "", + "mid": 73276978, + "name": "醉樱履冰", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i1.hdslb.com/bfs/garb/item/488870931b1bba66da36d22848f0720480d3d79a.png", + "image_enhance": "https://i1.hdslb.com/bfs/garb/item/5974f17f9d96a88bafba2f6d18d647a486e88312.webp", + "image_enhance_frame": "https://i1.hdslb.com/bfs/garb/item/4316a3910bb0bd6f2f1c267a3e9187f0b9fe5bd0.png", + "n_pid": 32257, + "name": "EveOneCat2", + "pid": 32257 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2023年06月22日", + "pub_ts": 1687401002, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1767542400000, + "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": "http://i0.hdslb.com/bfs/vip/label_annual.png", + "text": "年度大会员", + "text_color": "#FFFFFF", + "use_img_label": true + }, + "nickname_color": "#FB7299", + "status": 1, + "theme_type": 0, + "type": 2 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "360051457", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1ZX4y1W7zd", + "cover": "http://i2.hdslb.com/bfs/archive/627de932421b996ef8782c35ad17c816a1a9e7b8.jpg", + "desc": "回放:BV1tN411r7oU\n【逍遥散人】直播间:https://live.bilibili.com/1017\n【逍遥散人】主页:https://space.bilibili.com/168598", + "disable_preview": 0, + "duration_text": "20:16", + "jump_url": "//www.bilibili.com/video/BV1ZX4y1W7zd/", + "stat": { + "danmaku": "165", + "play": "5.6万" + }, + "title": "【逍遥散人】散人看11年前自己的实况《幽灵诡计》", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 80, + "forbidden": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 1339, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "897064867", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "897064867" + }, + "id_str": "666670390017261601", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i2.hdslb.com/bfs/face/c93eb41c2b7c1a1741f4ef6126bc78a5332014df.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.8000000000000002, + "axis_y": 0.8000000000000002, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "rgb(255,255,255)", + "border": "2px solid rgba(255,255,255,1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 3, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "48421904" + }, + "decoration_card": { + "big_card_url": "https://i0.hdslb.com/bfs/vip/e2ffa1d1d491fe0464338ed3921327ef5e4b42c5.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/vip/a9e3d993c7a15e88ce0bf714a142f7d2b44121e2.png", + "fan": {}, + "id": 28, + "image_enhance": "https://i0.hdslb.com/bfs/vip/a9e3d993c7a15e88ce0bf714a142f7d2b44121e2.png", + "item_id": 28, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=28&isdiy=0&part=card&from=post&f_source=garb&vmid=48421904&native.theme=1&navhide=1", + "name": "2233娘" + }, + "face": "https://i2.hdslb.com/bfs/face/c93eb41c2b7c1a1741f4ef6126bc78a5332014df.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/48421904/dynamic", + "label": "", + "mid": 48421904, + "name": "贾逸可", + "official_verify": { + "desc": "", + "type": 0 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2022年06月01日", + "pub_ts": 1654059696, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1746288000000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 1 + } + }, + "module_dynamic": { + "additional": null, + "desc": { + "rich_text_nodes": [ + { + "orig_text": "一转眼十年啦,当时我还没有入驻B站,十年前你听过这首《红白机》(游戏机之歌)吗?\n我是既能模仿华语乐坛歌手翻唱,也能原创的贾逸可。祝大家儿童节快乐!\n", + "text": "一转眼十年啦,当时我还没有入驻B站,十年前你听过这首《红白机》(游戏机之歌)吗?\n我是既能模仿华语乐坛歌手翻唱,也能原创的贾逸可。祝大家儿童节快乐!\n", + "type": "RICH_TEXT_NODE_TYPE_TEXT" + } + ], + "text": "一转眼十年啦,当时我还没有入驻B站,十年前你听过这首《红白机》(游戏机之歌)吗?\n我是既能模仿华语乐坛歌手翻唱,也能原创的贾逸可。祝大家儿童节快乐!\n" + }, + "major": { + "archive": { + "aid": "897064867", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1aA4y1d7fQ", + "cover": "http://i1.hdslb.com/bfs/archive/5a20992eb2a886998afdd82a08b975c0e7ea2dbf.jpg", + "desc": "一转眼十年啦,当时我还没有入驻B站,十年前你听过这首《红白机》(游戏机之歌)吗?\n我是既能模仿华语乐坛歌手翻唱,也能原创的贾逸可。祝大家儿童节快乐!\n用这首歌送给我们的童年~一起爷青回,华语乐坛系列:\n【常玉(周董点赞原创)】BV1st4y1s7Kk\n【爱你】BV1gF41157J8\n【热爱105°C的你】BV1qw411Z7Zy\n【孤勇者】BV1AM4y1P7De\n【有何不可】BV1WL411T7vD\n【达拉崩吧】BV1rY411j73X\n【本操纲目】BV1PY411A7sJ\n【萨日朗】BV16L4y1", + "disable_preview": 0, + "duration_text": "03:32", + "jump_url": "//www.bilibili.com/video/BV1aA4y1d7fQ/", + "stat": { + "danmaku": "129", + "play": "2万" + }, + "title": "⚡️爷青回!原创游戏机之歌《红白机》⚡️", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 109, + "forbidden": false + }, + "forward": { + "count": 11, + "forbidden": false + }, + "like": { + "count": 1867, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + }, + { + "dynamic_card_item": { + "basic": { + "comment_id_str": "792152742", + "comment_type": 1, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "792152742" + }, + "id_str": "874962963680722993", + "modules": { + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/3bb211c6aa7a9adc08d22d30b3c818c5040797c1.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "1621845192" + }, + "face": "https://i0.hdslb.com/bfs/face/3bb211c6aa7a9adc08d22d30b3c818c5040797c1.jpg", + "face_nft": false, + "following": null, + "jump_url": "//space.bilibili.com/1621845192/dynamic", + "label": "", + "mid": 1621845192, + "name": "太阳嘟嘟小姐姐", + "official_verify": { + "desc": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_action": "投稿了视频", + "pub_location_text": "", + "pub_time": "2023年12月14日", + "pub_ts": 1702556590, + "type": "AUTHOR_TYPE_NORMAL", + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 0, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "status": 0, + "theme_type": 0, + "type": 0 + } + }, + "module_dynamic": { + "additional": null, + "desc": null, + "major": { + "archive": { + "aid": "792152742", + "badge": { + "bg_color": "#FB7299", + "color": "#FFFFFF", + "icon_url": null, + "text": "投稿视频" + }, + "bvid": "BV1ZC4y1X7zu", + "cover": "http://i2.hdslb.com/bfs/archive/edbfc6fa5a168714789678bbea3aab74d8af7e9c.jpg", + "desc": "-", + "disable_preview": 0, + "duration_text": "00:13", + "jump_url": "//www.bilibili.com/video/BV1ZC4y1X7zu/", + "stat": { + "danmaku": "5", + "play": "1.5万" + }, + "title": "仿青儿仿得我要心脏骤停了!大家都说太像了,把我高兴得做梦都要笑醒!呜呜呜太喜欢了!", + "type": 1 + }, + "type": "MAJOR_TYPE_ARCHIVE" + }, + "topic": null + }, + "module_more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + }, + { + "label": "与话题无关", + "type": "THREE_POINT_TOPIC_IRRELEVANT" + } + ] + }, + "module_stat": { + "comment": { + "count": 41, + "forbidden": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 1223, + "forbidden": false, + "status": false + } + } + }, + "type": "DYNAMIC_TYPE_AV", + "visible": true + }, + "topic_type": "DYNAMIC" + } + ], + "offset": "heat_2922347_20_20", + "topic_sort_by_conf": { + "all_sort_by": [ + { + "sort_by": 2, + "sort_name": "热门" + }, + { + "sort_by": 3, + "sort_name": "最新" + } + ], + "default_sort_by": 2, + "show_sort_by": 2 + } + } + }, + "message": "0", + "ttl": 1 +} +``` +</details> + +<!-- Generated by json-apidoc-gen @ 2025-07-25T01:56:48.912698186Z --> + +## ~~获取包含置顶及热门的动态列表~~ + +> ~~https://api.vc.bilibili.com/topic_svr/v1/topic_svr/fetch_dynamics~~ + +该接口已失效, 参见 [#852](https://github.com/SocialSisterYi/bilibili-API-collect/issues/852), 历史文档见 [此处](https://github.com/SocialSisterYi/bilibili-API-collect/blob/e99f64c9b5c2bbd156e95ca254620378a22697f7/docs/dynamic/tag_dynamics.md#%E8%8E%B7%E5%8F%96%E5%8C%85%E5%90%AB%E7%BD%AE%E9%A1%B6%E5%8F%8A%E7%83%AD%E9%97%A8%E7%9A%84%E5%8A%A8%E6%80%81%E5%88%97%E8%A1%A8) + +## ~~获取历史动态列表~~ + +> ~~https://api.vc.bilibili.com/topic_svr/v1/topic_svr/topic_history~~ + +该接口已失效, 参见 [#852](https://github.com/SocialSisterYi/bilibili-API-collect/issues/852), 历史文档见 [此处](https://github.com/SocialSisterYi/bilibili-API-collect/blob/e99f64c9b5c2bbd156e95ca254620378a22697f7/docs/dynamic/tag_dynamics.md#%E8%8E%B7%E5%8F%96%E5%8E%86%E5%8F%B2%E5%8A%A8%E6%80%81%E5%88%97%E8%A1%A80) + +## 搜索发布话题 + +> https://app.bilibili.com/x/topic/pub/search +> https://api.bilibili.com/x/topic/pub/search + +*请求方法: GET* + +注: 该接口可能存在传入页面大小与返回数量不匹配的问题, 可能与访问权限有关 + +<!--{ + "from": { + "url": "https://t.bilibili.com/" + "selector": ".bili-topic-search__input__inner" + } +}--> + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --- | --- | --- | --- | --- | +| keywords | str | 关键词 | 不必要 | | +| content | str | 空 | 不必要 | | +| upload_id | str | 上传 id? | 不必要 | 页面刷新第一次请求时为空, 后均非空<br />似乎为固定值, 格式: `${your_mid}_${login_or_last_refresh_or_cookie_ts}_${dig4}`, 如 `616368979_1722652786_2534` | +| page_size | int | 页大小 | 不必要 | 默认为 20 | +| page_num | int | 1 | 不必要 | 不用于翻页 | +| offset | int | 偏移 | 不必要 | 可从响应 `data.page_info.offset` 中获取 | +| web_location | str | 333.1365 | 不必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0: 成功<br />-400: 请求错误 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| new_topic | obj | 新建话题? | | +| has_create_jurisdiction | bool | false | 是否有创建权限? | +| topic_items | array | 话题列表 | | +| request_id | str | 请求 id | | +| page_info | obj | 页信息 | | + +`data` 中的 `new_topic` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| name | str | 请求参数中的 `keywords` | | + +`data` 中的 `topic_items` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| id | num | 话题 id | | +| name | str | 话题名 | | +| view | num | 浏览数 | | +| discuss | num | 讨论数 | | +| stat_desc | str | 状态描述 | | +| description | str | 话题描述 | | +| show_interact_data | bool | false | 是否显示互动数据? | + +`data` 中的 `page_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| offset | num | 下次请求可用的偏移 | 请求参数中的 `offset` + `page_size` | +| has_more | bool | 是否有更多数据 | 当没有更多时可能不存在该字段 | + +**示例:** + +注: 该示例就是解释开头所注的问题的一个示例 + +```shell +curl -G 'https://app.bilibili.com/x/topic/pub/search' \ +--url-query 'keywords=2233' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "new_topic": { + "name": "2233" + }, + "has_create_jurisdiction": false, + "topic_items": [ + { + "id": 1101122, + "name": "2233异世集", + "view": 2502, + "discuss": 11, + "stat_desc": "2502浏览·11讨论", + "description": "分享数字周边", + "show_interact_data": false + }, + { + "id": 1050671, + "name": "2233生日倒计时", + "view": 21149, + "discuss": 130, + "stat_desc": "2.1万浏览·130讨论", + "description": "2233生日倒计时", + "show_interact_data": false + }, + { + "id": 1057129, + "name": "2233手办可可爱爱", + "view": 836, + "discuss": 14, + "stat_desc": "836浏览·14讨论", + "description": "喜欢2233,", + "show_interact_data": false + } + ], + "request_id": "1$0$1723796266$7f515d4e26b7bd5007fb8ca4b066bf0b", + "page_info": { + "offset": 4, + "has_more": true + } + } +} +``` + +</details> + +## 推荐搜索话题? + +> https://app.bilibili.com/x/topic/pub/rcmd/search +> https://api.bilibili.com/x/topic/pub/rcmd/search + +*请求方法: GET* + +注: 该接口好像啥也不返回, 但是网页端会请求该接口 + +<!--{ + "from": { + "url": "https://t.bilibili.com/" + }, + "gh": [1083] +}--> + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --- | --- | --- | --- | --- | +| keywords | str | 空 | 不必要 | | +| upload_id | str | 上传 id? | 不必要 | 同上 | +| web_location | str | 333.1365 | 不必要 | 有时请求不带该参数 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0: 成功 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | str | 数据本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | -- | --- | +| topic_items | unknown[] | 空? | 可能与 [推荐话题](#推荐话题) 相同? | +| request_id | str | 请求 id | 当传入 `keywords` 时不为空| + +**示例:** + +```shell +curl -G 'https://app.bilibili.com/x/topic/pub/rcmd/search' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "topic_items": [], + "request_id": "" + } +} +``` + +</details> + +## 推荐话题 + +> https://app.bilibili.com/x/topic/web/dynamic/rcmd + +*请求方法: GET* + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------ | ------ | ---------- | ------ | ---- | +| source | string | 来源 | 不必要 | 如 `Web` | +| page_size | number | 获取数量 | 不必要 | 默认为 `9`, 留空为 `6`, 最大为 `26`, 最小为 `1` | +| web_location | string | `333.1365` | 不必要 | | + + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | num | 返回值 | 0: 成功 | +| message | str | 错误信息 | 成功时为 `0` | +| ttl | num | `1` | | +| data | str | 数据本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| topic_items | object[] | 话题列表 | 套了个娃 | + +`data.topic_items[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| discuss | number | 讨论数 | | +| dynamics | number | 动态数 | | +| id | number | 话题 id | | +| jump_url | string | 跳转 URL | | +| name | string | 话题名 | | +| show_interact_data | boolean | 是否显示互动数据? | | +| view | number | 浏览数 | | + +**示例:** + +```shell +curl -G 'https://app.bilibili.com/x/topic/web/dynamic/rcmd?page_size=9' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "topic_items": [ + { + "discuss": 147, + "dynamics": 20, + "id": 1305890, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1305890", + "name": "燕云河西凉州篇预测", + "show_interact_data": false, + "view": 261060 + }, + { + "discuss": 554, + "dynamics": 24, + "id": 1305885, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1305885", + "name": "真人版驯龙高手新预告", + "show_interact_data": false, + "view": 472265 + }, + { + "discuss": 24358, + "dynamics": 57, + "id": 1305877, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1305877", + "name": "国米4-3巴萨", + "show_interact_data": false, + "view": 4851673 + }, + { + "discuss": 201, + "dynamics": 24, + "id": 1305933, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1305933", + "name": "公积金住房贷款利率下调0.25%", + "show_interact_data": false, + "view": 111704 + }, + { + "discuss": 20201, + "dynamics": 70, + "id": 1305920, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1305920", + "name": "印度巴基斯坦交火", + "show_interact_data": false, + "view": 12102634 + }, + { + "discuss": 2497, + "dynamics": 37, + "id": 1305940, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1305940", + "name": "降准降息释放什么信号", + "show_interact_data": false, + "view": 475373 + }, + { + "discuss": 11970, + "dynamics": 51, + "id": 1305886, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1305886", + "name": "淮水竹亭值得一看吗", + "show_interact_data": false, + "view": 3171863 + }, + { + "discuss": 860, + "dynamics": 38, + "id": 1305904, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1305904", + "name": "GTA6全新预告", + "show_interact_data": false, + "view": 202393 + }, + { + "discuss": 576, + "dynamics": 23, + "id": 1305830, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1305830", + "name": "默茨正式当选德国新任总理", + "show_interact_data": false, + "view": 280448 + } + ] + }, + "message": "0", + "ttl": 1 +} +``` +</details> + +<!-- Generated by json-apidoc-gen @ 2025-05-08T06:56:53.249280549Z --> + +## 检查话题是否存在 + +> https://api.bilibili.com/x/topic/pub/is_existed + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +<!-- #1357 --> + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---- | ------ | ---- | +| topic | string | 话题名 | 必要 | 大小写敏感 | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | number | 返回值 | 0: 成功 | +| data | object | 数据本体 | | +| message | string | 错误信息 | 成功时为 `0` | +| ttl | number | `1` | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| already_existed | boolean | 是否已经存在 | | +| synonym_topic | object | 类似话题 | | + +`data.synonym_topic` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| topic_items | object[] | 话题列表 | | + +`data.synonym_topic.topic_items[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| description | string | 话题描述 | | +| discuss | number | 讨论数 | | +| dynamics | number | 动态数 | | +| id | number | 话题 id | | +| jump_url | string | 跳转 URL | | +| name | string | 话题名 | | +| show_interact_data | boolean | 显示互动数据? | | +| view | number | 浏览数 | | + +**示例:** + +```shell +-curl -G 'https://api.bilibili.com/x/topic/pub/is_existed' \ +--url-query 'topic=BW2025' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "already_existed": true, + "synonym_topic": { + "topic_items": [ + { + "description": "Ave Mujica、大石昌良、宫野真守、虹咲学园 学园偶像同好会、偶像大师闪耀色彩、Machico、茅原实里、RAISE A SUILEN、TOGENASHI TOGEARI、yama等参演嘉宾信息已解禁🎶7月11日至13日,在国家会展中心(上海)虹馆EH与大家见面~", + "discuss": 44910, + "dynamics": 5183, + "id": 1297553, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1297553", + "name": "BML2025", + "show_interact_data": false, + "view": 35386975 + }, + { + "description": "心火燎原,2025季中冠军赛即将到来。", + "discuss": 48373, + "dynamics": 523, + "id": 1313369, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1313369", + "name": "2025MSI", + "show_interact_data": false, + "view": 15264132 + }, + { + "description": "简中版《命运-冠位指定》将于2025年8月8日-8月10日在杭州举办FES2025九周年纪念展。", + "discuss": 1421, + "dynamics": 121, + "id": 1315085, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1315085", + "name": "FGOFES2025", + "show_interact_data": false, + "view": 927806 + } + ] + } + }, + "message": "0", + "ttl": 1 +} +``` +</details> + +<!-- Generated by json-apidoc-gen @ 2025-07-26T02:37:34.536597611Z --> + +## 获取指定话题详细信息 + +> https://app.bilibili.com/x/topic/web/details/top + +*请求方法: GET* + +<!-- #1360 --> + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---- | ------ | ---- | +| topic_id | number | 话题 id | 必要 | | +| source | string | 来源 | 不必要 | 如 `Web` `H5` | +| web_location | string | `333.1036` | 不必要 | 当 `source` 为 `H5` 时 | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | number | 返回值 | 0: 成功 | +| data | object | 数据本体 | | +| message | string | 错误信息 | 成功时为 `0` | +| ttl | number | `1` | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| click_area_card | object | 点击区域卡片? | | +| functional_card | object | 功能卡片 | | +| top_details | object | 话题详情 | | + +`data.click_area_card` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | + +`data.functional_card` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| traffic_card | object | 引流卡片 | | + +`data.functional_card.traffic_card` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| benefit_point | string | 奖励点 | | +| card_desc | string | 卡片描述 | | +| icon_url | string | 图标 URL | | +| jump_title | string | 跳转标题 | | +| jump_url | string | 跳转 URL | | +| name | string | 名称 | | + +`data.top_details` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| close_pub_layer_entry | boolean | 是否关闭发布层入口? | | +| has_create_jurisdiction | boolean | 是否有创建权限? | | +| operation_content | object | 操作内容? | | +| topic_creator | object | 话题创建者 | | +| topic_item | object | 话题详情 | | +| word_color | number | 话题字体颜色? | | + +`data.top_details.operation_content` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | + +`data.top_details.topic_creator` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| face | string | 头像 URL | | +| name | string | 昵称 | | +| uid | number | mid (UID) | | + +`data.top_details.topic_item` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| back_color | string | 背景色 | | +| ctime | number | 创建时间 | | +| description | string | 话题描述 | | +| discuss | number | 讨论数 | | +| dynamics | number | 动态数 | | +| fav | number | 收藏数 | | +| id | number | 话题 id | | +| jump_url | string | 跳转 URL | | +| like | number | 点赞数 | | +| name | string | 话题名 | | +| share | number | 分享数 | | +| share_pic | string | 分享图片 URL | 似乎就是话题的图标 | +| share_url | string | 分享的 URL | | +| show_interact_data | boolean | 显示互动数据? | | +| view | number | 浏览数 | | + +**示例:** + +```shell +curl -G 'https://app.bilibili.com/x/topic/web/details/top' \ +--url-query 'topic_id=1314000' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "click_area_card": {}, + "functional_card": { + "traffic_card": { + "benefit_point": "投稿4K视频瓜分千万流量&奖金", + "card_desc": "2025-10-01 00:00截止", + "icon_url": "https://i0.hdslb.com/bfs/activity-plat/static/20211019/4c5b6134e2def772efe20dabcca1f6e1/vGqnSBjy8N.png", + "jump_title": "立即参与", + "jump_url": "https://www.bilibili.com/blackboard/era/4Kchaoqingpc.html", + "name": "眼见帧实·B站超高清视频计划" + } + }, + "top_details": { + "close_pub_layer_entry": false, + "has_create_jurisdiction": false, + "operation_content": {}, + "topic_creator": { + "face": "https://i0.hdslb.com/bfs/face/9da46bf581938ff29c2143f186b3f66409c11bf6.jpg", + "name": "赛博星人科技汪", + "uid": 394205865 + }, + "topic_item": { + "back_color": "#6188FF", + "ctime": 1750734201, + "description": "来B站,分享你的超高清视频!2025.6.30-9.30期间,参与“眼见帧实·B站超高清视频计划”活动,投稿超清视频,可以分享超清开箱、超清vlog、超清科普、超清美食、超清风光大片等内容!丰厚奖金&礼物等你来拿~", + "discuss": 435100, + "dynamics": 7902, + "fav": 15, + "id": 1314000, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1314000", + "like": 19, + "name": "B站超高清视频计划", + "share": 7, + "share_pic": "http://i0.hdslb.com/bfs/vc/7701fba940e721ceb756cc73694ebb8f510fe0cc.png", + "share_url": "https://m.bilibili.com/topic-detail?topic_id=1314000", + "show_interact_data": true, + "view": 90735677 + }, + "word_color": 0 + } + }, + "message": "0", + "ttl": 1 +} +``` +</details> + +<!-- Generated by json-apidoc-gen @ 2025-07-26T03:17:14.502472328Z --> diff --git a/bb-api-collect/docs/electric/Bcoin.md b/bb-api-collect/docs/electric/Bcoin.md new file mode 100644 index 0000000000..970d1bc31a --- /dev/null +++ b/bb-api-collect/docs/electric/Bcoin.md @@ -0,0 +1,323 @@ +# B币方式充电 + +<img src="../../assets/img/battery-100.png" width="100" height="100"/> + +**注**:以前充电是电池的概念,1B币折合10电池,一般地充电10电池可获得1经验 + +**目前(2020/12/02后)则是贝壳的概念,1B币折合1贝壳、1经验(如果存在小数点,则经验值向下取整,即2.5B币获得2经验)** + +## 新版本B币充电 + +> https://api.bilibili.com/x/ugcpay/web/v2/trade/elec/pay/quick + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------------------ | ------ | ------------------------------------------------- | +| bp_num | num | 贝壳数量 | 必要 | 必须在2-9999之间 | +| is_bp_remains_prior | bool | 是否优先扣除B币余额 | 必要 | [true,false],B币充电请选择true | +| up_mid | num | 充电对象用户mid | 必要 | | +| otype | str | 充电来源 | 必要 | up:空间充电<br />archive:视频充电 | +| oid | num | 充电来源代码 | 必要 | 空间充电:充电对象用户mid<br />视频充电:稿件avid | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功(并不代表充电成功) <br />-101:账号未登录<br />-111:csrf校验失败<br />-400:请求错误<br />-500:服务器错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ----------- | ------------------------------------------------ | +| mid | num | 本用户mid | | +| up_mid | num | 目标用户mid | | +| order_no | str | 留言token | 用于添加充电留言 | +| bp_num | str | 充电贝壳数 | | +| exp | num | 获得经验数 | | +| status | num | 返回结果 | 4:成功<br />-2:低于20电池下限<br />-4:B币不足 | +| msg | str | 错误信息 | 默认为空 | + +**示例:** + +以空间的方式向用户`mid=293793435`充了2贝壳,得到2经验,留言token为`BPRG5CEC3VUPOOANA540` + +此时`data`.`status`=`4` + +~~自己给自己冲QAQ~~ + +```shell +curl 'https://api.bilibili.com/x/ugcpay/web/v2/trade/elec/pay/quick' \ +--data-urlencode 'bp_num=2' \ +--data-urlencode 'is_bp_remains_prior=true' \ +--data-urlencode 'up_mid=293793435' \ +--data-urlencode 'otype=up' \ +--data-urlencode 'oid=293793435' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "mid": 293793435, + "up_mid": 293793435, + "order_no": "BPRG5CEC3VUPOOANA540", + "bp_num": 2, + "exp": "2", + "status": 4, + "msg": "" + } +} +``` + +</details> + +当所充电贝壳数小于2时,充电不会成功 + +此时`data`.`status`=`-2` + +```shell +curl 'https://api.bilibili.com/x/ugcpay/web/v2/trade/elec/pay/quick' \ +--data-urlencode 'bp_num=1' \ +--data-urlencode 'is_bp_remains_prior=true' \ +--data-urlencode 'otype=up' \ +--data-urlencode 'oid=293793435' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "mid": 0, + "up_mid": 0, + "order_no": "", + "bp_num": "0", + "exp": 0, + "status": -2, + "msg": "elec raw order create failed: 88201" + } +} +``` + +</details> + +当所充贝壳数折合的B币数不足时,充电也不会成功 + +此时`data`.`status`=`-4` + +```shell +curl 'https://api.bilibili.com/x/ugcpay/web/v2/trade/elec/pay/quick' \ +--data-urlencode 'bp_num=99' \ +--data-urlencode 'is_bp_remains_prior=true' \ +--data-urlencode 'up_mid=293793435' \ +--data-urlencode 'otype=up' \ +--data-urlencode 'oid=293793435' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "mid": 0, + "up_mid": 0, + "order_no": "", + "bp_num": "0", + "exp": 0, + "status": -4, + "msg": "bp.to.battery http failed, invalid args, errNo=800409904: B 币余额不足" + } +} +``` + +</details> + + +## 老版本B币充电 + +老版本目前已过期,调用接口成功后(code返回0),data.status会返回0,且B币不会消耗,贝壳也不会增加。以下是历史信息: + +<details> +<summary>查看折叠内容</summary> + +> https://api.bilibili.com/x/ugcpay/trade/elec/pay/quick + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------------------ | ------ | ------------------------------------------------- | +| elec_num | num | 充电电池数量 | 必要 | 必须在2-9999之间 | +| up_mid | num | 充电对象用户mid | 必要 | | +| otype | str | 充电来源 | 必要 | up:空间充电<br />archive:视频充电 | +| oid | num | 充电来源代码 | 必要 | 空间充电:充电对象用户mid<br />视频充电:稿件avid | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功(并不代表充电成功) <br />-101:账号未登录<br />-111:csrf校验失败<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ----------- | ------------------------------------------------ | +| mid | num | 本用户mid | | +| up_mid | num | 目标用户mid | | +| order_no | str | 留言token | 用于添加充电留言 | +| elec_num | num | 充电电池数 | | +| exp | num | 获得经验数 | | +| status | num | 返回结果 | 4:成功<br />-2:低于20电池下限<br />-4:B币不足 | +| msg | str | 错误信息 | 默认为空 | + +**示例:** + +以空间的方式向用户`mid=293793435`充了20电池,得到2经验,留言token为`BPRG5CEC3VUPOOANA540` + +此时`data`.`status`=`4` + +~~再次自己冲自己QAQ~~ + +```shell +curl 'https://api.bilibili.com/x/ugcpay/trade/elec/pay/quick' \ +--data-urlencode 'elec_num=20' \ +--data-urlencode 'up_mid=293793435' \ +--data-urlencode 'otype=up' \ +--data-urlencode 'oid=293793435' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "mid": 293793435, + "up_mid": 293793435, + "order_no": "BPRG5CEC3VUPOOANA540", + "elec_num": 20, + "exp": 2, + "status": 4, + "msg": "" + } +} +``` + +</details> + +当所充电池数小于2时,充电不会成功 + +此时`data`.`status`=`-2` + +```shell +curl 'https://api.bilibili.com/x/ugcpay/trade/elec/pay/quick' \ +--data-urlencode 'elec_num=1' \ +--data-urlencode 'up_mid=293793435' \ +--data-urlencode 'otype=up' \ +--data-urlencode 'oid=293793435' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "mid": 0, + "up_mid": 0, + "order_no": "", + "elec_num": 0, + "exp": 0, + "status": -2, + "msg": "elec raw order create failed: 88201" + } +} +``` + +</details> + +当所充电池数折合的B币数不足时,充电也不会成功 + +此时`data`.`status`=`-4` + +```shell +curl 'https://api.bilibili.com/x/ugcpay/trade/elec/pay/quick' \ +--data-urlencode 'elec_num=999' \ +--data-urlencode 'up_mid=293793435' \ +--data-urlencode 'otype=up' \ +--data-urlencode 'oid=293793435' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "mid": 0, + "up_mid": 0, + "order_no": "", + "elec_num": 0, + "exp": 0, + "status": -4, + "msg": "bp.to.battery http failed, invalid args, errNo=800409904: B 币余额不足" + } +} +``` + +</details> +</details> diff --git a/bb-api-collect/docs/electric/WeChat&Alipay.md b/bb-api-collect/docs/electric/WeChat&Alipay.md new file mode 100644 index 0000000000..2d2e193974 --- /dev/null +++ b/bb-api-collect/docs/electric/WeChat&Alipay.md @@ -0,0 +1,198 @@ +# 微信&支付宝方式充电 + +<img src="../../assets/img/battery-100.png" width="100" height="100"/> + +操作流程: + +1. 申请充电二维码及扫码秘钥,秘钥临时保存备用 +2. 使用`qr_code_url`中的值生成二维码 +3. 用支付宝或微信扫描 +4. 以扫码秘钥作为参数轮询检查扫码支付结果 + +## 申请充电二维码及扫码秘钥 + +> https://api.bilibili.com/x/ugcpay/web/v2/trade/elec/pay/qr_code/create + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +秘钥有效时间为10分钟 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------------- | ---- | ------------------------ | ------ | ------------------------------------------------------------ | +| bp_num | num | 充电B币数量 | 必要 | 必须在2-9999之间 | +| is_bp_remains_prior | bool | 是否优先扣除B币 | 必要 | true:是<br />false:否<br />在B币不足时剩余的部分利用支付平台支付 | +| up_mid | num | 充电对象用户mid | 必要 | | +| otype | str | 充电来源 | 必要 | up:空间充电<br />archive:视频充电 | +| oid | num | 充电来源代码 | 必要 | 空间充电:充电对象用户mid<br />视频充电:稿件avid | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf校验失败<br />-400:请求错误<br />-500:服务器错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ------------------ | -------- | +| qr_code_url | str | 支付二维码生成内容 | 存在转义 | +| qr_token | str | 扫码秘钥 | | +| exp | num | 获得经验数 | | + +**示例:** + +申请空间的方式向用户23215368充电10电池且不使用B币的支付二维码 + +```shell +curl 'https://api.bilibili.com/x/ugcpay/trade/elec/pay/qr_code/create' \ +--data-urlencode 'elec_num=10' \ +--data-urlencode 'up_mid=23215368' \ +--data-urlencode 'is_bp_remains_prior=false' \ +--data-urlencode 'otype=up' \ +--data-urlencode 'oid=23215368' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "qr_code_url": "https://api.bilibili.com/x/ugcpay/trade/elec/pay/qr_code/gateway?mid=293793435&token=c1cb1d95d2194ba58df6bb0f24ae1aaa", + "qr_token": "c1cb1d95d2194ba58df6bb0f24ae1aaa", + "exp": 1 + } +} +``` + +</details> + +## 检查扫码支付结果 + +> https://api.bilibili.com/x/ugcpay/trade/elec/pay/order/status + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | -------- | ------ | ---- | +| qr_token | str | 扫码秘钥 | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ----------- | ------------------------------------------------------------ | +| qr_token | str | 扫码秘钥 | | +| order_no | str | 留言token | 未成功则无此项<br />用于添加充电留言 | +| mid | num | 当前用户mid | | +| status | num | 状态值 | 若秘钥错误则无此项<br />1:已支付<br />2:未扫描<br />3:未确认 | + +**示例:** + +当申请到的支付二维码未被扫描时,`data`.`status`的值为`2` + +```shell +curl -G 'https://api.bilibili.com/x/ugcpay/trade/elec/pay/order/status' \ +--data-urlencode 'qr_token=c7cbdc47fc424cd18f2146db653597b8' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "qr_token": "c7cbdc47fc424cd18f2146db653597b8", + "mid": 293793435, + "status": 2 + } +} +``` + +</details> + +当申请到的支付二维码已扫描但未确认时,`data`.`status`的值为`3` + +```shell +curl -G 'https://api.bilibili.com/x/ugcpay/trade/elec/pay/order/status' \ +--data-urlencode 'qr_token=c7cbdc47fc424cd18f2146db653597b8' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "qr_token": "c7cbdc47fc424cd18f2146db653597b8", + "mid": 293793435, + "status": 3 + } +} +``` + +</details> + +成功支付后,`data`.`status`的值为`1`,且`data`.`order_no`存在留言token + +```shell +curl -G 'https://api.bilibili.com/x/ugcpay/trade/elec/pay/order/status' \ +--data-urlencode 'qr_token=c7cbdc47fc424cd18f2146db653597b8' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "qr_token": "bd649c836c524550bfe22a369334fc05", + "order_no": "BPTD36U3KP82I31RSSLG", + "mid": 293793435, + "status": 1 + } +} +``` + +</details> diff --git a/bb-api-collect/docs/electric/charge_list.md b/bb-api-collect/docs/electric/charge_list.md new file mode 100644 index 0000000000..6bd2cdd2d1 --- /dev/null +++ b/bb-api-collect/docs/electric/charge_list.md @@ -0,0 +1,542 @@ +# 充电列表 + +## 获取空间充电公示列表 + +> <https://api.bilibili.com/x/ugcpay-rank/elec/month/up> + +*请求方式:GET* + +本接口需要在请求标头中提供有效的浏览器 UA,如 `Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36` + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| up_mid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />88214:up主未开通充电 | +| message | str | 错误信息 | | +| ttl | num | 0 | | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----- | ---------------- | --------------- | +| count | num | 本月充电人数 | | +| list | array | 本月充电用户列表 | | +| total_count | num | 总计充电次数 | | +| total | num | 总计充电次数 | 同`total_count` | +| special_day | num | 0 | 作用尚不明确 | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---------------- | +| 0 | obj | 充电用户1 | | +| n | obj | 充电用户(n+1) | 按照充电排名排列 | +| …… | obj | …… | …… | + +`data`中的`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ---------------- | ---------------- | +| uname | str | 充电用户昵称 | | +| avatar | str | 充电用户头像url | | +| mid | num | 充电对象mid | | +| pay_mid | num | 充电用户mid | | +| rank | num | 充电用户排名 | 取决于充电的多少 | +| trend_type | num | 0 | 作用尚不明确 | +| vip_info | obj | 充电用户会员信息 | | +| message | str | 充电留言 | 无为空 | +| msg_hidden | num | 0 | 作用尚不明确 | + +`list`数组中的对象中的`vip_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | -------------- | ----- | +| vipDueMsec | num | 大会员过期时间 | 恒为0 | +| vipStatus | num | 大会员状态 | 包月充电时恒为0<br />自定义充电:<br />0:无<br />1:有 | +| vipType | num | 大会员类型 | 包月充电时恒为0<br />自定义充电:<br />0:无<br />1:月大会员<br />2:年度及以上大会员 | + +**示例:** + +查询用户`mid=53456`的充电公示列表 + +```shell +curl -G 'https://api.bilibili.com/x/ugcpay-rank/elec/month/up' \ + -A 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36' \ + --data-urlencode 'up_mid=53456' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "", + "ttl": 0, + "data": { + "count": 8521, + "list": [ + { + "uname": "云梦澡堂", + "avatar": "https://i1.hdslb.com/bfs/face/6589df5fdac0f80593f6a86e4d88dc08e25df3d2.jpg", + "mid": 53456, + "pay_mid": 1555775947, + "rank": 1, + "trend_type": 0, + "vip_info": { "vipDueMsec": 0, "vipStatus": 0, "vipType": 0 }, + "message": "", + "message_hidden": 0 + }, + { + "uname": "在下小天子", + "avatar": "https://i1.hdslb.com/bfs/face/a3bfbe6186889bb50dcd87c1156d07a70227a25b.jpg", + "mid": 53456, + "pay_mid": 508630801, + "rank": 2, + "trend_type": 0, + "vip_info": { "vipDueMsec": 0, "vipStatus": 0, "vipType": 0 }, + "message": "", + "message_hidden": 0 + } + ], + "total_count": 41919, + "total": 41919, + "special_day": 0 + } +} +``` + +</details> + +## 获取视频充电鸣谢名单 + +> <https://api.bilibili.com/x/web-interface/elec/show> + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------ | ------------ | ------------------ | +| mid | num | 目标用户mid | 必要 | | +| aid | num | 目标稿件avid | 必要(可选) | avid与bvid任选一个 | +| bvid | str | 目标稿件bvid | 必要(可选) | avid与bvid任选一个 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-404:无视频<br />62001:不需要展示充电信息 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ----- | ---------------- | ------------ | +| show_info | obj | 展示选项 | | +| av_count | num | 目标视频充电人数 | | +| count | num | 本月充电人数 | | +| total_count | num | 总计充电人数 | | +| special_day | num | 0 | 作用尚不明确 | +| display_num | num | 0 | 作用尚不明确 | +| cnt_priv_type | num | 0 | 作用尚不明确 | +| list | array | 本月充电用户列表 | | + +`data`中的`show_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------------------ | ---------------- | +| show | bool | 是否展示视频充电鸣谢名单 | | +| state | num | 充电功能开启状态 | -1:未开通充电功能<br />1:已开通自定义充电<br />2:已开通包月、自定义充电<br />3:已开通包月高档、自定义充电 | +| title | str | 充电按钮显示文字 | 空字符串或 `充电` 或 `充电中` | +| jump_url | str | 跳转url | | +| icon | str | 充电图标 | | +| high_level | obj | 充电专属视频信息 | | +| with_qa_id | num | 充电问答id | | + +`show_info`中的`high_level`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | ------------------------------ | ---------------- | +| privilege_type | num | 解锁视频所需最低定价档位的代码 | 见[充电档位代码与定价](../electric/monthly.md#充电档位代码privilege_type与定价) | +| title | str | 提示标题 | `该视频为「{充电档位名称}」专属视频` | +| sub_title | str | 提示子标题 | `开通「{充电档位定价}元档包月充电」即可观看` | +| show_button | bool | 是否显示按钮 | | +| button_text | str | 按钮文本 | `去开通` | +| jump_url | obj | 跳转url信息 | 详细信息有待补充 | +| intro | str | 充电介绍语 | | +| open | bool | (?) | | +| new | bool | (?) | | +| question_text | str | (?) | | +| qa_detail_link | str | (?) | | + +`high_level`中的`jump_url`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | ----------------------- | ---- | +| up_link | str | UP主包月充电购买页面url | | +| paywall_link | str | 视频试看后的提示页面url | | +| previewbar_link | str | 视频预览页面url | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---------------- | +| 0 | obj | 充电用户1 | | +| n | obj | 充电用户(n+1) | 按照充电排名排列 | +| …… | obj | …… | …… | + +`data`中的`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ---------------- | ---------------- | +| mid | num | 充电对象mid | | +| pay_mid | num | 充电用户mid | | +| rank | num | 充电用户排名 | 取决于充电的多少 | +| uname | str | 充电用户昵称 | | +| avatar | str | 充电用户头像url | | +| message | str | 充电留言 | 无为空 | +| msg_deleted | num | 0 | 作用尚不明确 | +| vip_info | obj | 充电用户会员信息 | | +| trend_type | num | 0 | 作用尚不明确 | + +`data`中的`list`数组中的`vip_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | -------------- | ----- | +| vipType | num | 大会员类型 | 包月充电时恒为0<br />自定义充电:<br />0:无<br />1:月大会员<br />2:年度及以上大会员 | +| vipDueMsec | num | 大会员过期时间 | 恒为0 | +| vipStatus | num | 大会员状态 | 包月充电时恒为0<br />自定义充电:<br />0:无<br />1:有 | + +**示例:** + +获取视频`av967773538`/` BV1up4y1y77i `,用户`mid=53456`的视频充电鸣谢名单 + +avid方式: + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/elec/show' \ + --data-urlencode 'mid=53456' \ + --data-urlencode 'aid=967773538' +``` + +bvid方式: + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/elec/show' \ + --data-urlencode 'mid=53456' \ + --data-urlencode 'bvid=BV1up4y1y77i' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "show_info": { + "show": true, + "state": 2, + "title": "充电", + "jump_url": "https://www.bilibili.com/h5/upower/index?mid=53456&navhide=1&prePage=video&oid=967773538", + "icon": "https://i0.hdslb.com/bfs/garb/item/33e2e72d9a0c855f036b4cb55448f44af67a0635.png", + "high_level": { + "privilege_type": 0, + "title": "", + "sub_title": "", + "show_button": false, + "button_text": "", + "jump_url": { "up_link": "", "paywall_link": "", "previewbar_link": "" }, + "intro": "", + "open": false, + "new": false + } + }, + "av_count": 0, + "count": 0, + "total_count": 41919, + "special_day": 0, + "display_num": 0, + "cnt_priv_type": 0, + "list": [ + { + "mid": 53456, + "pay_mid": 1555775947, + "rank": 1, + "uname": "云梦澡堂", + "avatar": "https://i1.hdslb.com/bfs/face/6589df5fdac0f80593f6a86e4d88dc08e25df3d2.jpg", + "message": "", + "msg_deleted": 0, + "vip_info": { "vipType": 0, "vipDueMsec": 0, "vipStatus": 0 }, + "trend_type": 0 + }, + { + "mid": 53456, + "pay_mid": 508630801, + "rank": 2, + "uname": "在下小天子", + "avatar": "https://i1.hdslb.com/bfs/face/a3bfbe6186889bb50dcd87c1156d07a70227a25b.jpg", + "message": "", + "msg_deleted": 0, + "vip_info": { "vipType": 0, "vipDueMsec": 0, "vipStatus": 0 }, + "trend_type": 0 + } + ] + } +} +``` + +</details> + +## 查询我收到的充电列表 + +> <https://pay.bilibili.com/bk/brokerage/listForCustomerRechargeRecord> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----------- | ---- | -------- | ------ | ------------------- | +| currentPage | num | 页数 | 必要 | | +| pageSize | num | 分页大小 | 必要 | 取值范围\[1,50\] | +| customerId | num | (?) | 必要 | 目前为固定值:10026 | +| beginTime | str | 开始日期 | 非必要 | yyyy-MM-dd | +| endTime | str | 结束日期 | 非必要 | yyyy-MM-dd | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功<br />800501007:user not login<br />800501008:内部错误<br />800501011:请求参数有误 | +| errno | num | | | +| msg | str | | | +| showMsg | str | | | +| data | obj | 信息本体 | | +| success | bool | | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ----- | ------------ | ---- | +| page | obj | 分页信息 | | +| result | array | 充电信息本体 | | +| config | array | (?) | | + +`page`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ------------ | ---- | +| currentPage | num | 当前页数 | | +| pageSize | num | 当前分页大小 | | +| totalCount | num | 记录总数 | | +| totalPage | num | 总页数 | | + +`result`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ---- | ---------------- | ------------------- | +| mid | num | 充电人mid | | +| name | str | 充电人昵称 | | +| avatar | str | 充电人头像 | | +| originalThirdCoin | num | 原始B币数 | | +| brokerage | num | 实际收到的贝壳数 | | +| remark | str | 充电渠道 | Web/安卓/iOS | +| ctime | str | 充电时间 | yyyy-MM-dd HH:mm:ss | + +`config`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ---- | ---- | ---------- | +| mid | null | | 总是为null | +| name | null | | 总是为null | +| avatar | null | | 总是为null | +| originalThirdCoin | null | | 总是为null | +| brokerage | null | | 总是为null | +| remark | null | | 总是为null | +| ctime | null | | 总是为null | + +**示例:** + +```shell +curl -G 'https://pay.bilibili.com/bk/brokerage/listForCustomerRechargeRecord' \ + --data-urlencode 'currentPage=1' \ + --data-urlencode 'pageSize=2' \ + --data-urlencode 'customerId=10026' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "errno": 0, + "msg": "SUCCESS", + "showMsg": "交易成功", + "data": { + "page": { + "currentPage": 1, + "pageSize": 2, + "totalCount": 311, + "totalPage": 156 + }, + "result": [ + { + "mid": 2233, + "name": "2233", + "avatar": "http://i2.hdslb.com/bfs/face/f42b7f47c80648d2ee1231f2435b527c60302289.jpg", + "originalThirdCoin": 2, + "brokerage": 1.34, + "remark": "Web", + "ctime": "2022-04-12 17:34:47" + }, + { + "mid": 2233, + "name": "2233", + "avatar": "http://i0.hdslb.com/bfs/face/member/noface.jpg", + "originalThirdCoin": 2, + "brokerage": 0.68, + "remark": "iOS", + "ctime": "2022-04-10 03:41:10" + } + ], + "config": [ + { + "mid": null, + "name": null, + "avatar": null, + "originalThirdCoin": null, + "brokerage": null, + "remark": null, + "ctime": null + } + ] + }, + "success": true +} +``` + +</details> + +## 查询历史充电数据 + +> <https://member.bilibili.com/x/h5/elec/rank/recent> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | -------- | ------ | ---------------- | +| pn | num | 页数 | 非必要 | | +| ps | num | 分页大小 | 非必要 | 取值范围\[1,20\] | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ----- | ------------ | ---- | +| list | array | 充电信息本体 | | +| pager | obj | 分页信息 | | + +`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ---------- | ------------------- | +| aid | num | 0 | | +| bvid | str | 空 | | +| elec_num | num | 充电电池数 | | +| title | str | 空 | | +| uname | str | 空 | | +| avatar | str | 空 | | +| ctime | str | 充电时间 | yyyy-MM-dd HH:mm:ss | + +`pager`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ------------ | ---- | +| current | num | 当前页数 | | +| size | num | 当前分页大小 | | +| total | num | 记录总数 | | + +**示例:** + +```shell +curl -G 'https://member.bilibili.com/x/h5/elec/rank/recent' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "aid": 0, + "bvid": "", + "elec_num": 50, + "title": "", + "uname": "", + "avatar": "", + "ctime": "2020-04-02 03:12:22" + }, + { + "aid": 0, + "bvid": "", + "elec_num": 20, + "title": "", + "uname": "", + "avatar": "", + "ctime": "2020-04-02 03:12:00" + } + ], + "pager": { + "current": 1, + "size": 20, + "total": 38 + } + } +} +``` + +</details> diff --git a/bb-api-collect/docs/electric/charge_msg.md b/bb-api-collect/docs/electric/charge_msg.md new file mode 100644 index 0000000000..534fe9f684 --- /dev/null +++ b/bb-api-collect/docs/electric/charge_msg.md @@ -0,0 +1,298 @@ +# 充电留言 + +## 发送充电留言 + +> https://api.bilibili.com/x/ugcpay/trade/elec/message + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------------------ | ------ | ---- | +| order_id | str | 留言token | 必要 | | +| message | str | 留言内容 | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功 <br />-101:账号未登录<br />-111:csrf校验失败<br />-400:请求错误<br />88203:不能重复留言 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +为留言token为`BPRG5CEC3VUPOOANA540`的充电操作,添加了内容为`支持一下大佬`的留言 + +```shell +curl 'https://api.bilibili.com/x/ugcpay/trade/elec/message' \ + --data-urlencode 'order_id=BPRG5CEC3VUPOOANA540' \ + --data-urlencode 'message=支持一下大佬' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +## 查询我收到的充电留言 + +> https://member.bilibili.com/x/web/elec/remark/list + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | --------- | ------ | ---------------- | +| begin | str | 起始日期 | 非必要 | 默认2016-01-01 | +| end | str | 结束日期 | 非必要 | 默认2050-01-01 | +| pn | str | 页数 | 非必要 | | +| ps | str | 分页大小 | 非必要 | 取值范围\[1,12\] | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录 | +| msg | str | 错误信息 | 成功时为`0` | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ----- | -------- | ---- | +| list | array | 信息本体 | | +| pager | obj | 分页信息 | | + +`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ---------------------- | ---- | +| aid | num | | | +| bvid | str | | | +| id | num | 留言记录id | | +| mid | num | 0 | | +| reply_mid | num | 0 | | +| elec_num | num | 0 | | +| state | num | UP是否已经回复这条留言 | 0:未回复<br />1:已回复 | +| msg | str | 留言信息 | | +| aname | str | 空 | | +| uname | str | 空 | | +| avator | str | 空 | | +| reply_name | str | 空 | | +| reply_avator | str | 空 | | +| reply_msg | str | 空 | | +| ctime | num | 留言时间 | 毫秒级时间戳 | +| reply_time | num | 0 | | + +`pager`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ------------ | ---- | +| current | num | 当前页数 | | +| size | num | 当前分页大小 | | +| total | num | 记录总数 | | + +**示例:** + +```shell +curl 'https://member.bilibili.com/x/web/elec/remark/list?begin=2016-01-01&end=2050-01-01&pn=1&ps=10' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "aid": 0, + "bvid": "", + "id": 6715018, + "mid": 0, + "reply_mid": 0, + "elec_num": 0, + "state": 0, + "msg": "加油", + "aname": "", + "uname": "", + "avator": "", + "reply_name": "", + "reply_avator": "", + "reply_msg": "", + "ctime": 1650665119000, + "reply_time": 0 + } + ], + "pager": { + "current": 1, + "size": 10, + "total": 448 + } + } +} +``` + +</details> + +## 查询充电留言详情 + +> https://member.bilibili.com/x/web/elec/remark/detail + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| id | num | 留言id | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-400:请求错误 | +| message | str | 错误信息 | 成功时为 `0` | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ---------------------- | ---- | +| aid | num | | | +| bvid | str | | | +| id | num | 留言id | | +| mid | num | 留言者mid(充电用户) | | +| reply_mid | num | UP主mid | | +| elec_num | num | 0 | | +| state | num | UP是否已经回复这条留言 | 0:未回复<br />1:已回复 | +| msg | str | 留言内容 | | +| aname | str | 空 | | +| uname | str | 留言者用户名 | | +| avator | str | 留言者头像 | | +| reply_name | str | UP主用户名 | | +| reply_avator | str | UP主头像 | | +| reply_msg | str | 回复内容 | | +| ctime | num | 留言时间 | 毫秒级时间戳 | +| reply_time | num | 回复时间 | 毫秒级时间戳 | + +**示例:** + +```shell +curl 'https://member.bilibili.com/x/web/elec/remark/detail?id=6507563' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "aid": 0, + "bvid": "", + "id": 6507563, + "mid": 19978396, + "reply_mid": 2062760, + "elec_num": 0, + "state": 1, + "msg": "感谢搬运", + "aname": "", + "uname": "HANSOOOOOL", + "avator": "http://i1.hdslb.com/bfs/face/5c22af0261b8b3f9a54b6e0038e35430e9ed9cfd.jpg", + "reply_name": "一把近战都不给六花", + "reply_avator": "http://i2.hdslb.com/bfs/face/1804b716084908d4992bdd35827d0c2d7222fe97.jpg", + "reply_msg": "( ̄3 ̄)", + "ctime": 1646726966000, + "reply_time": 1646811946000 + } +} +``` + +</details> + +## 回复充电留言 + +> https://member.bilibili.com/x/web/elec/remark/reply + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| csrf | str | csrf | 必要 | | +| id | num | 留言id | 必要 | | +| msg | str | 回复信息 | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf 校验失败<br />-400:请求错误<br />20004:充电服务异常 | +| message | str | 错误信息 | | +| ttl | num | 1 | | +| data | num | 数据本体 | 1:成功<br />2:失败 | + +**示例:** + +```shell +curl 'https://member.bilibili.com/x/web/elec/remark/reply' \ + -b 'SESSDATA=xxx' \ + --data-urlencode 'csrf=xxx' \ + --data-urlencode 'id=6258929' \ + --data-urlencode 'msg=( ̄3 ̄)' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": 1 +} +``` + +</details> diff --git a/bb-api-collect/docs/electric/monthly.md b/bb-api-collect/docs/electric/monthly.md new file mode 100644 index 0000000000..21dc3efd81 --- /dev/null +++ b/bb-api-collect/docs/electric/monthly.md @@ -0,0 +1,746 @@ +# 包月充电 + +<img src="../../assets/img/battery-100.png" width="100" height="100"/> + +## 常量说明 + +### 充电档位代码(`privilege_type`)与定价 + +| 代码 | 定价(单位:元人民币) | +| :--: | :--------------------: | +| 10 | 6 | +| 20 | 30 | +| 30 | 50 | +| 40 | 88 | +| 50 | 128 | +| 60 | 288 | +| 70 | 588 | +| 80 | 998 | +| 100 | 18 | +| 110 | 238 | +| 130 | 68 | + +## 获取包月充电列表 + +> <https://api.live.bilibili.com/xlive/revenue/v1/guard/getChargeRecord> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ------------------------ | +| page | num | 页码 | 必要 | | +| type | num | 充电状态 | 必要 | 1:使用中<br />2:已过期 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-400:请求错误<br />25100004:参数错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | ---------------- | ---------------- | +| list | 有内容时:array<br />无内容时:null | 包月充电UP主列表 | 最多10个 | +| page | num | 当前页数 | | +| page_size | num | 当前分页大小 | 一般为10 | +| total_page | num | 总页数 | | +| total_num | num | 用户总数 | | +| is_more | num | 是否有更多用户 | 0:否<br />1:是 | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---------------- | +| 0 | obj | 用户1 | | +| n | obj | 用户(n+1) | | +| …… | obj | …… | …… | + +数组`list`中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------------- | ----- | ------------------------ | ---------- | +| up_uid | num | 充电UP主mid | | +| user_name | str | 充电UP主昵称 | | +| user_face | str | 充电UP主头像url | | +| item | array | 充电详情 | | +| start | num | 开始充电时间 | 秒级时间戳 | +| high_level_state | num | 是否可对UP主进行高档充电 | | +| elec_reply_state | num | 是否可对UP主进行专属问答 | 0:否<br />1:是<br />2:状态未知 | + +数组`list`中的对象中的`item`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | -------- | +| 0 | obj | 充电档位1 | | +| n | obj | 充电档位(n+1) | | +| …… | obj | …… | …… | + +数组`item`中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | --------------------------------------------- | ---------------- | ---------------- | +| privilege_type | num | 充电档位代码 | 详见[充电档位代码与定价](#充电档位代码privilege_type与定价) | +| icon | str | 充电图标 | | +| name | str | 充电档位名称 | | +| expire_time | num | 该档位过期时间 | 秒级时间戳 | +| renew | 开启自动续费时:obj<br />关闭自动续费时:null | 充电自动续费详情 | | +| start_time | num | 该档位生效时间 | 秒级时间戳 | +| renew_list | 开启自动续费时:array<br />关闭自动续费时:null | 充电自动续费列表 | | + +`renew`对象、`renew_list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ---- | ------------ | ------------------------------------------------- | +| uid | num | 自己的mid | | +| ruid | num | UP主的mid | | +| goods_id | num | 充电类型 | 172:一个月<br />173:连续包月<br />174:连续包年 | +| status | num | 充电状态 | 1 | +| next_execute_time | num | 下次续费时间 | 秒级时间戳 | +| signed_time | num | 签约时间 | 秒级时间戳 | +| signed_price | num | 下次续费金额 | 单位为千分之一元人民币 | +| pay_channel | num | 签约平台 | 2:微信支付<br />4:支付宝 | +| period | num | 下次充电天数 | | +| mobile_app | str | 充电渠道 | 可为`android`等 | + +**示例:** + +获取自己正在使用的包月充电的列表 + +```shell +curl 'https://api.live.bilibili.com/xlive/revenue/v1/guard/getChargeRecord' \ + --data-urlencode 'page=1' \ + --data-urlencode 'type=1' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "up_uid": 2233, + "user_name": "2233", + "user_face": "https://i0.hdslb.com/bfs/face/noface.jpg", + "item": [ + { + "privilege_type": 10, + "icon": "https://s1.hdslb.com/bfs/templar/york-static/lightning_icon@2x.png", + "name": "为TA充电", + "expire_time": 1703519999, + "renew": { + "uid": 425503913, + "ruid": 2233, + "goods_id": 174, + "status": 1, + "next_execute_time": 1703174400, + "signed_time": 1671618921, + "signed_price": 36000, + "pay_channel": 2, + "period": 366, + "mobile_app": "android" + }, + "start_time": 1671618921, + "renew_list": [ + { + "uid": 425503913, + "ruid": 2233, + "goods_id": 174, + "status": 1, + "next_execute_time": 1703174400, + "signed_time": 1671618921, + "signed_price": 36000, + "pay_channel": 2, + "period": 366, + "mobile_app": "android" + } + ] + } + ], + "start": 1669183804, + "high_level_state": 1, + "elec_reply_state": 1 + }, + { + "up_uid": 293793435, + "user_name": "社会易姐QwQ", + "user_face": "https://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg", + "item": [ + { + "privilege_type": 10, + "icon": "https://s1.hdslb.com/bfs/templar/york-static/lightning_icon@2x.png", + "name": "为TA充电", + "expire_time": 1681401599, + "renew": { + "uid": 425503913, + "ruid": 293793435, + "goods_id": 173, + "status": 1, + "next_execute_time": 1680364800, + "signed_time": 1677760921, + "signed_price": 5000, + "pay_channel": 4, + "period": 31, + "mobile_app": "android" + }, + "start_time": 1677760921, + "renew_list": [ + { + "uid": 425503913, + "ruid": 293793435, + "goods_id": 173, + "status": 1, + "next_execute_time": 1680364800, + "signed_time": 1677760921, + "signed_price": 5000, + "pay_channel": 4, + "period": 31, + "mobile_app": "android" + } + ] + } + ], + "start": 1676033795, + "high_level_state": 1, + "elec_reply_state": 1 + } + ], + "page": 1, + "page_size": 10, + "total_page": 3, + "total_num": 22, + "is_more": 1 + } +} +``` + +</details> + +表示自己从2022-11-23 14:10:04开始给“2233”包月充电,并且在2022-12-21 18:35:21在微信开通了连续包年充电,在2023-12-22 00:00:00的时候会自动续费36元,并继续充电366天; + +自己从2023-02-10 20:56:35开始给“社会易姐QwQ”包月充电,并且在2023-03-02 20:42:01在支付宝开通了连续包月充电,在2023-04-02 00:00:00的时候会自动续费5元,并继续充电31天。 + +## UP主包月充电详情 + +> <https://api.bilibili.com/x/upower/item/detail> + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| up_mid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------ | ---- | -------------------------- | ------------------------------ | +| upower_rank | obj | 充电详情 | | +| item | obj | 充电欢迎语信息 | | +| user_card | obj | UP主信息 | | +| upower_level | num | UP主开通的充电等级 | 1:非高档充电<br />2:高档充电 | +| elec_reply_state | num | 是否可对UP主进行专属问答 | | +| voucher_state | obj | 包月充电券信息 | **详细信息有待补充** | +| upower_right_count | obj | 不同充电档位下的充电权益数 | | +| only_contain_medal | bool | 享有的权益仅为粉丝勋章 | | +| privilege_type | num | 当前给该UP主包月充电的档位 | 见[充电档位代码与定价](#充电档位代码privilege_type与定价),若从未给该UP主包月充电过则为0 | + +`data`中的`upower_rank`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | ---------------- | ------------ | +| total | num | 充电用户总数 | | +| total_desc | str | 充电总数文字说明 | 示例:“1+” | +| list | array | 充电用户列表 | 最多展示30个 | + +`upower_rank`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | -------------------------- | +| 0 | obj | 用户1 | | +| n | obj | 用户(n+1) | 按照最初充电时间排序(?) | +| …… | obj | …… | …… | + +`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | --------------- | ---- | +| rank | num | 充电用户索引 | | +| mid | num | 充电用户mid | | +| nickname | str | 充电用户昵称 | | +| avatar | str | 充电用户头像url | | + +`data`中的`item`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | ---------------- | ---- | +| intro_video_aid | str | 充电介绍视频AV号 | | +| welcomes | str | 充电介绍语 | | + +`data`中的`user_card`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ----------- | ---- | +| avatar | str | UP主头像url | | +| nickname | str | UP主昵称 | | + +`data`中的`upower_right_count`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | -------------------- | ---- | +| {充电档位代码} | num | 该档位下的充电权益数 | | + +**示例:** + +获取`mid=1265680561`的包月充电详情 + +```shell +curl 'https://api.bilibili.com/x/upower/item/detail' \ + --data-urlencode 'up_mid=1265680561' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "upower_rank": { + "total": 5082, + "total_desc": "5000+", + "list": [ + { + "rank": 1, + "mid": 1476475459, + "nickname": "一只屑椒", + "avatar": "https://i1.hdslb.com/bfs/face/dc721da215f4651e0472d566b146ee8fdf198dbe.jpg" + }, + { + "rank": 2, + "mid": 275365317, + "nickname": "-陪我去看海吧i", + "avatar": "https://i0.hdslb.com/bfs/face/dd7547b13020e7f47549ad7908fd3fc58efadefc.jpg" + }, + { + "rank": 3, + "mid": 401909111, + "nickname": "Vege5able", + "avatar": "https://i2.hdslb.com/bfs/face/46b1fdc94c7851ec0c47817adeec13e3225da559.jpg" + } + ] + }, + "item": { + "intro_video_aid": "", + "welcomes": "哈喽b站的小伙伴们,我的充电计划升级啦! 感兴趣就多多支持我吧~(゜-゜)つロ" + }, + "user_card": { + "avatar": "https://i1.hdslb.com/bfs/face/5ddddba98f0265265662a8f7d5383e528a98412b.jpg", + "nickname": "永雏塔菲" + }, + "upower_level": 1, + "elec_reply_state": 1, + "voucher_state": { + "voucher_order_id": "95843e812210c455d1ea6e4714bf105a00", + "user_voucher_state": 2, + "vip_action": 0, + "voucher_name": "包月充电券(6元档)", + "validate_price": 0, + "validate_level": 0, + "activity": "", + "common_time": 0, + "high_level_time": 0, + "specify_up": 0, + "specify_level": 0 + }, + "upower_right_count": { + "10": 3 + }, + "only_contain_medal": false, + "privilege_type": 0 + } +} +``` + +</details> + +## 与UP主的包月充电关系 + +> <https://api.bilibili.com/x/upower/charge/follow/info> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| up_mid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------ | ---- | ------------------------------ | ------------------------------------------- | +| days | num | 已保持多少天包月充电状态 | | +| up_card | obj | UP主信息 | | +| user_card | obj | 自己的信息 | | +| remain_days | num | 剩余天数 | 未处于包月充电状态为-1 | +| remain_less_1day | num | 剩余的天数是否小于1天 | 0:否<br />1:是<br />未处于包月充电状态为0 | +| upower_rank | obj | 充电详情 | | +| upower_icon | str | 充电图标url | 仅在处于包月充电状态时有内容 | +| upower_right_count | obj | 当前自己享有该UP主的充电权益数 | | +| only_contain_medal | bool | 享有的权益仅为粉丝勋章 | | +| privilege_type | num | 当前给该UP主包月充电的档位代码 | 见[充电档位代码与定价](#充电档位代码privilege_type与定价),若未处于包月充电状态为0 | +| challenge_info | obj | 充电挑战信息 | **详细信息有待补充** | + +`data`中的`up_card`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | ------------ | ---- | +| mid | num | UP主mid | | +| nickname | str | UP主昵称 | | +| official_title | str | UP主认证信息 | | +| avatar | str | UP主头像url | | + +`data`中的`user_card`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ----------- | ---- | +| avatar | str | 用户头像url | | +| nickname | str | 用户昵称 | | + +`data`中的`upower_rank`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | ---------------- | ----------- | +| total | num | 充电用户总数 | | +| total_desc | str | 充电总数文字说明 | 示例:“1+” | +| list | array | 充电用户列表 | 最多展示6个 | + +`upower_rank`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---------------- | +| 0 | obj | 用户1 | | +| n | obj | 用户(n+1) | 按照充电时间排序 | +| …… | obj | …… | …… | + +数组`list`中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | --------------- | ---- | +| rank | num | 充电用户索引 | | +| mid | num | 充电用户mid | | +| nickname | str | 充电用户昵称 | | +| avatar | str | 充电用户头像url | | + +**示例:** + +获取与`mid=293793435`的包月充电关系 + +```shell +curl 'https://api.bilibili.com/x/upower/charge/follow/info' \ + --data-urlencode 'up_mid=293793435' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "days": 17, + "up_card": { + "mid": 293793435, + "nickname": "社会易姐QwQ", + "official_title": "", + "avatar": "https://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg" + }, + "user_card": { + "avatar": "https://i2.hdslb.com/bfs/face/540ed71e2fb2ddd8967c21b392026c34fc15673e.jpg", + "nickname": "晨叶梦春" + }, + "remain_days": 15, + "remain_less_1day": 0, + "upower_rank": { + "total": 1, + "total_desc": "1+", + "list": [ + { + "rank": 1, + "mid": 425503913, + "nickname": "晨叶梦春", + "avatar": "https://i2.hdslb.com/bfs/face/540ed71e2fb2ddd8967c21b392026c34fc15673e.jpg" + } + ] + }, + "upower_icon": "https://i0.hdslb.com/bfs/garb/item/33e2e72d9a0c855f036b4cb55448f44af67a0635.png", + "upower_right_count": 2, + "only_contain_medal": false, + "privilege_type": 10, + "challenge_info": { + "challenge_id": "", + "description": "", + "challenge_type": 0, + "remaining_days": 0, + "end_time": "", + "progress": 0, + "targets": [], + "state": 0, + "end_time_unix": 0, + "pub_dyn": 0, + "dyn_content": "" + } + } +} +``` + +</details> + +表示自己已保持17天对“社会易姐QwQ”的包月充电,剩余15天过期。 + +## 包月充电用户排名 + +> <https://api.bilibili.com/x/upower/up/member/rank/v2> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------------- | ---- | ------------ | ------ | --------- | +| up_mid | num | 目标用户mid | 必要 | | +| ps | num | 每页项数 | 必要 | 最大为101 | +| pn | num | 页码 | 必要 | | +| privilege_type | num | 充电档位代码 | 非必要 | 见[充电档位代码与定价](#充电档位代码privilege_type与定价),默认为可以显示排名的档位中**最高定价**的档位 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ----- | ------------------------------ | -------- | +| up_info | obj | UP主信息 | | +| rank_info | array | 当前档位的充电用户排名 | | +| user_info | obj | 自己在该档位下与UP主的充电关系 | | +| member_total | num | 当前档位的充电用户总数 | | +| privilege_type | num | 当前充电档位代码 | 见[充电档位代码与定价](#充电档位代码privilege_type与定价) | +| is_charge | bool | 自己是否给该UP主包月充电过 | 无论档位 | +| tabs | array | 可显示排名的充电档位代码列表 | | +| level_info | array | 可显示排名的充电档位信息 | | + +`data`中的`up_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | -------------------- | ---------------------------------------- | +| mid | num | UP主mid | | +| nickname | str | UP主昵称 | | +| avatar | str | UP主头像url | | +| type | num | UP主认证类型 | -1:无<br />0:UP主认证<br />1:机构认证 | +| title | str | UP主认证文字 | | +| upower_state | num | UP主充电功能开启状态 | 0:未开通充电功能<br />1:已开通自定义充电<br />2:已开通包月、自定义充电<br />3:已开通包月高档、自定义充电 | + +`data`中的`rank_info`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---------------- | +| 0 | obj | 用户1 | | +| n | obj | 用户(n+1) | 按照充电排名排列 | +| …… | obj | …… | …… | + +`rank_info`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ---------------- | ----- | +| mid | num | 充电用户mid | | +| nickname | str | 充电用户昵称 | | +| avatar | str | 充电用户头像url | | +| rank | num | 充电用户排名 | | +| day | num | 包月充电天数 | | +| expire_at | num | 包月充电过期时间 | 恒为0 | +| remain_days | num | 剩余天数 | 恒为0 | + +`data`中的`user_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ---------------- | ------------------------------- | +| mid | num | 用户mid | | +| nickname | str | 用户昵称 | | +| avatar | str | 用户头像url | | +| rank | num | 包月充电排名 | 不在该充电档位用户列表里为-1 | +| day | num | 包月充电天数 | | +| expire_at | num | 包月充电过期时间 | 秒级时间戳,若从未给UP主在该档位下包月充电过为0 | +| remain_days | num | 剩余天数 | 若该档位充电状态已失效为0 | + +`data`中的`tabs`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---------------- | +| 0 | num | 档位代码1 | | +| n | num | 档位代码(n+1) | | +| …… | num | …… | …… | + +`data`中的`level_info`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---------------- | +| 0 | obj | 档位1 | | +| n | obj | 档位(n+1) | | +| …… | obj | …… | …… | + +`level_info`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | -------------------- | ---------------------- | +| privilege_type | num | 当前充电档位代码 | 见[充电档位代码与定价](#充电档位代码privilege_type与定价) | +| name | str | 档位名称 | | +| price | num | 档位价格 | 单位为百分之一元人民币 | +| member_total | num | 当前档位的用户总数 | | + +**示例:** + +获取给`mid=686127`包月充电的用户排名 + +```shell +curl 'https://api.bilibili.com/x/upower/up/member/rank/v2' \ + --data-urlencode 'up_mid=686127' \ + --data-urlencode 'ps=3' \ + --data-urlencode 'pn=1' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "up_info": { + "mid": 686127, + "nickname": "籽岷", + "avatar": "https://i0.hdslb.com/bfs/face/7efb679569b2faeff38fa08f6f992fa1ada5e948.webp", + "type": 0, + "title": "2024百大UP主、知名游戏UP主", + "upower_state": 3 + }, + "rank_info": [ + { + "mid": 187012867, + "nickname": "是我灬不配", + "avatar": "https://i1.hdslb.com/bfs/face/ad4d2ce0705fd766a0ade315f5a6a5984ce479f4.jpg", + "rank": 1, + "day": 682, + "expire_at": 0, + "remain_days": 0 + }, + { + "mid": 20135495, + "nickname": "和平时一样鸽", + "avatar": "https://i2.hdslb.com/bfs/face/0eef725964105f39b1f000a59f232d9094017544.jpg", + "rank": 2, + "day": 620, + "expire_at": 0, + "remain_days": 0 + }, + { + "mid": 490065730, + "nickname": "乔治Y-GYhaha", + "avatar": "https://i1.hdslb.com/bfs/face/e1753e1e43d7a7df5333c5a2f4d3ec1d0334ebe6.jpg", + "rank": 3, + "day": 527, + "expire_at": 0, + "remain_days": 0 + } + ], + "user_info": { + "mid": 425503913, + "nickname": "晨叶梦春", + "avatar": "https://i2.hdslb.com/bfs/face/540ed71e2fb2ddd8967c21b392026c34fc15673e.jpg", + "rank": -1, + "day": 0, + "expire_at": 0, + "remain_days": 0 + }, + "member_total": 46881, + "privilege_type": 50, + "is_charge": false, + "tabs": [50, 10], + "level_info": [ + { + "privilege_type": 50, + "name": "审稿", + "price": 12800, + "member_total": 1082 + }, + { + "privilege_type": 10, + "name": "石粒", + "price": 600, + "member_total": 46158 + } + ] + } +} +``` + +</details> diff --git a/bb-api-collect/docs/emoji/action.md b/bb-api-collect/docs/emoji/action.md new file mode 100644 index 0000000000..d5bc0bd227 --- /dev/null +++ b/bb-api-collect/docs/emoji/action.md @@ -0,0 +1,105 @@ +# 表情操作 + +## 添加表情包 + +> https://api.bilibili.com/x/emote/package/add + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +只能添加有会员权限或已购买的表情包 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | ------ | -------------------------------- | +| package_id | num | 表情包id | 必要 | | +| business | str | 使用场景 | 必要 | reply:评论区<br />dynamic:动态 | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf校验失败<br />-400:请求错误<br />-403:访问权限不足 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +添加id为`25`的表情包,使用场景为评论区 + +```shell +curl 'https://api.bilibili.com/x/emote/package/add' \ +--data-urlencode 'package_id=25' \ +--data-urlencode 'business=reply' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +## 移除表情包 + +> https://api.bilibili.com/x/emote/package/remove + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | ------ | -------------------------------- | +| package_id | num | 表情包id | 必要 | | +| business | str | 使用场景 | 必要 | reply:评论区<br />dynamic:动态 | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf校验失败<br />-400:请求错误<br />-403:访问权限不足 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +移除id为`25`的表情包,使用场景为评论区 + +```shell +curl 'https://api.bilibili.com/x/emote/package/remove' \ +--data-urlencode 'package_id=25' \ +--data-urlencode 'business=reply' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> diff --git a/bb-api-collect/docs/emoji/list.md b/bb-api-collect/docs/emoji/list.md new file mode 100644 index 0000000000..14359828cb --- /dev/null +++ b/bb-api-collect/docs/emoji/list.md @@ -0,0 +1,639 @@ +# 表情列表 + +## 获取我的表情列表 + +> https://api.bilibili.com/x/emote/user/panel/web + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +使用登录(Cookie)进行会员专属及已购买表情包的分发,否则全为免费表情包 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | -------- | ------ | -------------------------------- | +| business | str | 使用场景 | 必要 | reply:评论区<br />dynamic:动态 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ----- | ------ | ---- | +| packages | array | 表情包 | | + +`data`中的`packages`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | -------------- | +| 0 | obj | 表情包1 | **详情见附表** | +| n | obj | 表情包(n+1) | **详情见附表** | +| …… | obj | …… | …… | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/emote/user/panel/web' \ +--data-urlencode 'business=reply' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "packages": [ + { + "id": 1, + "text": "小黄脸", + "url": "http://i0.hdslb.com/bfs/emote/81edf17314cea3b48674312b4364df44d5c01f17.png", + "mtime": 1591604235, + "type": 1, + "attr": 66, + "meta": { + "size": 1, + "item_id": 958 + }, + "emote": [ + { + "id": 2126, + "package_id": 1, + "text": "[视频卫星]", + "url": "http://i0.hdslb.com/bfs/emote/dce6fc7d6dfeafff01241924db60f8251cca5307.png", + "mtime": 1590986882, + "type": 1, + "attr": 0, + "meta": { + "size": 1 + }, + "flags": {} + }, + { + "id": 1901, + "package_id": 1, + "text": "[加油武汉]", + "url": "http://i0.hdslb.com/bfs/emote/eb966aaa5b690d3f9308a9f936f5b5a72a7f956b.png", + "mtime": 1580024058, + "type": 1, + "attr": 0, + "meta": { + "size": 1 + }, + "flags": {} + }, + { + "id": 1906, + "package_id": 1, + "text": "[口罩]", + "url": "http://i0.hdslb.com/bfs/emote/3ad2f66b151496d2a5fb0a8ea75f32265d778dd3.png", + "mtime": 1581309529, + "type": 1, + "attr": 0, + "meta": { + "size": 1 + }, + "flags": {} + }, + { + "id": 1, + "package_id": 1, + "text": "[微笑]", + "url": "http://i0.hdslb.com/bfs/emote/685612eadc33f6bc233776c6241813385844f182.png", + "mtime": 1582182040, + "type": 1, + "attr": 0, + "meta": { + "size": 1 + }, + "flags": {} + }, + { + "id": 1958, + "package_id": 1, + "text": "[笑]", + "url": "http://i0.hdslb.com/bfs/emote/81edf17314cea3b48674312b4364df44d5c01f17.png", + "mtime": 1582184940, + "type": 1, + "attr": 0, + "meta": { + "size": 1 + }, + "flags": {} + }, + ………… + }, + { + "id": 53, + "text": "热词系列一", + "url": "http://i0.hdslb.com/bfs/emote/bacd6e17997348873ef89e5f1bcbbda877a1606a.png", + "mtime": 1592205524, + "type": 1, + "attr": 2, + "meta": { + "size": 2, + "item_id": 1039 + }, + "emote": [ + { + "id": 1937, + "package_id": 53, + "text": "[热词系列_知识增加]", + "url": "http://i0.hdslb.com/bfs/emote/142409b595982b8210b2958f3d340f3b47942645.png", + "mtime": 1585202919, + "type": 1, + "attr": 2, + "meta": { + "size": 2, + "alias": "知识增加" + }, + "flags": {} + }, + { + "id": 2147, + "package_id": 53, + "text": "[热词系列_希望没事]", + "url": "http://i0.hdslb.com/bfs/emote/6c0d2e6c486d1ba5afd6204a96e102652464a01d.png", + "mtime": 1591689594, + "type": 1, + "attr": 2, + "meta": { + "size": 2, + "alias": "希望没事" + }, + "flags": {} + }, + { + "id": 2083, + "package_id": 53, + "text": "[热词系列_泪目]", + "url": "http://i0.hdslb.com/bfs/emote/bba3703ab90b7d16fe9dbcb85ed949db687f8331.png", + "mtime": 1588910215, + "type": 1, + "attr": 2, + "meta": { + "size": 2, + "alias": "泪目" + }, + "flags": {} + }, + { + "id": 2082, + "package_id": 53, + "text": "[热词系列_保护]", + "url": "http://i0.hdslb.com/bfs/emote/55f8f6445ca7c3170cdfc5b16036abf639ce9b57.png", + "mtime": 1588910215, + "type": 1, + "attr": 2, + "meta": { + "size": 2, + "alias": "保护" + }, + "flags": {} + }, + ………… + }, + ………… + ] + } +} +``` + +</details> + +## 获取指定的表情包明细 + +> https://api.bilibili.com/x/emote/package + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | -------- | ------ | -------------------------------- | +| business | str | 使用场景 | 必要 | reply:评论区<br />dynamic:动态 | +| ids | nums | 表情包id | 必要 | id之间以`,`隔开 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----------------------------- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 有效时:obj<br />无效时:null | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ----- | ------ | ---- | +| packages | array | 表情包 | | + +`data`中的`packages`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | -------------- | +| 0 | obj | 表情包1 | **详情见附表** | +| n | obj | 表情包(n+1) | **详情见附表** | +| …… | obj | …… | …… | + +**示例:** + +获取表情包id为`93`的表情包明细 + +```shell +curl -G 'https://api.bilibili.com/x/emote/package' \ +--data-urlencode 'ids=93' \ +--data-urlencode 'business=reply' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "packages": [ + { + "id": 93, + "text": "泠鸢yousa", + "url": "http://i0.hdslb.com/bfs/emote/5fa6082e098402d16d58c68e441ae76e40befd2c.png", + "mtime": 1592213522, + "type": 3, + "attr": 28, + "meta": { + "size": 2, + "item_id": 1907, + "item_url": "https://www.bilibili.com/h5/mall/suit/detail?navhide=1&stahide=0&id=1911" + }, + "emote": [ + { + "id": 2086, + "package_id": 93, + "text": "[泠鸢yousa_awsl]", + "url": "http://i0.hdslb.com/bfs/emote/7663b729161bd4556c2ec318c07791000743eb56.png", + "mtime": 1589776042, + "type": 3, + "attr": 0, + "meta": { + "size": 2, + "alias": "awsl" + }, + "flags": {} + }, + { + "id": 2087, + "package_id": 93, + "text": "[泠鸢yousa_打call]", + "url": "http://i0.hdslb.com/bfs/emote/718e9495846db4172eb87d2f7f02015a34d35ea2.png", + "mtime": 1589776042, + "type": 3, + "attr": 0, + "meta": { + "size": 2, + "alias": "打call" + }, + "flags": {} + }, + { + "id": 2088, + "package_id": 93, + "text": "[泠鸢yousa_沉默]", + "url": "http://i0.hdslb.com/bfs/emote/5e967cf1669743ed92e9a8ff3e5de6d90ca63d3d.png", + "mtime": 1589776042, + "type": 3, + "attr": 0, + "meta": { + "size": 2, + "alias": "沉默" + }, + "flags": {} + }, + { + "id": 2089, + "package_id": 93, + "text": "[泠鸢yousa_大哭]", + "url": "http://i0.hdslb.com/bfs/emote/3f757b147b9b1e201470eae7dac9cc0360172569.png", + "mtime": 1589776042, + "type": 3, + "attr": 0, + "meta": { + "size": 2, + "alias": "大哭" + }, + "flags": {} + }, + { + "id": 2090, + "package_id": 93, + "text": "[泠鸢yousa_干杯]", + "url": "http://i0.hdslb.com/bfs/emote/5cf5e14101be845233a222ab1bbdc21c63af04c3.png", + "mtime": 1590401422, + "type": 3, + "attr": 0, + "meta": { + "size": 2, + "alias": "干杯" + }, + "flags": {} + }, + { + "id": 2091, + "package_id": 93, + "text": "[泠鸢yousa_好人卡]", + "url": "http://i0.hdslb.com/bfs/emote/e3907b3bb20b18e7ecb11cd86829c9a4ce5b1b2f.png", + "mtime": 1589776042, + "type": 3, + "attr": 0, + "meta": { + "size": 2, + "alias": "好人卡" + }, + "flags": {} + }, + { + "id": 2092, + "package_id": 93, + "text": "[泠鸢yousa_加大力度]", + "url": "http://i0.hdslb.com/bfs/emote/a0393a2d4b522f07a319dfd2e91754a3cdff2c48.png", + "mtime": 1589776042, + "type": 3, + "attr": 0, + "meta": { + "size": 2, + "alias": "加大力度" + }, + "flags": {} + }, + { + "id": 2093, + "package_id": 93, + "text": "[泠鸢yousa_滑稽]", + "url": "http://i0.hdslb.com/bfs/emote/a8057c0e0579b93c16010a270e261fd0a64034af.png", + "mtime": 1589776042, + "type": 3, + "attr": 0, + "meta": { + "size": 2, + "alias": "滑稽" + }, + "flags": {} + }, + { + "id": 2094, + "package_id": 93, + "text": "[泠鸢yousa_请吃桃]", + "url": "http://i0.hdslb.com/bfs/emote/e92276d9d8c28f85f7dbcc0fbbb6ecb3345ce33e.png", + "mtime": 1589776042, + "type": 3, + "attr": 0, + "meta": { + "size": 2, + "alias": "请吃桃" + }, + "flags": {} + }, + { + "id": 2095, + "package_id": 93, + "text": "[泠鸢yousa_惊讶]", + "url": "http://i0.hdslb.com/bfs/emote/9fdc2c5b4b970aded56fe2f326bd4d00e849339d.png", + "mtime": 1589776042, + "type": 3, + "attr": 0, + "meta": { + "size": 2, + "alias": "惊讶" + }, + "flags": {} + }, + { + "id": 2096, + "package_id": 93, + "text": "[泠鸢yousa_生气]", + "url": "http://i0.hdslb.com/bfs/emote/9e6ba9ff34101e04d3e321cad486f845f892050e.png", + "mtime": 1589776042, + "type": 3, + "attr": 0, + "meta": { + "size": 2, + "alias": "生气" + }, + "flags": {} + }, + { + "id": 2097, + "package_id": 93, + "text": "[泠鸢yousa_贴贴]", + "url": "http://i0.hdslb.com/bfs/emote/dbc177d314231add509501ffc6bc7655fca2c10f.png", + "mtime": 1589776042, + "type": 3, + "attr": 0, + "meta": { + "size": 2, + "alias": "贴贴" + }, + "flags": {} + }, + { + "id": 2098, + "package_id": 93, + "text": "[泠鸢yousa_头晕]", + "url": "http://i0.hdslb.com/bfs/emote/49830c1c8a1652f7ee9cb854ac7dbf8e378cdcd6.png", + "mtime": 1589776042, + "type": 3, + "attr": 0, + "meta": { + "size": 2, + "alias": "头晕" + }, + "flags": {} + }, + { + "id": 2099, + "package_id": 93, + "text": "[泠鸢yousa_问号]", + "url": "http://i0.hdslb.com/bfs/emote/ab7a543233eff83138c3221c86a762ab36bab7bc.png", + "mtime": 1589776042, + "type": 3, + "attr": 0, + "meta": { + "size": 2, + "alias": "问号" + }, + "flags": {} + }, + { + "id": 2100, + "package_id": 93, + "text": "[泠鸢yousa_真棒]", + "url": "http://i0.hdslb.com/bfs/emote/02ea49543a3ac52feee185c156ab08fb2bfdd89e.png", + "mtime": 1589776042, + "type": 3, + "attr": 0, + "meta": { + "size": 2, + "alias": "真棒" + }, + "flags": {} + } + ], + "flags": { + "added": true + } + } + ] + } +} +``` + +</details> + +## 获取所有表情包列表 + +> https://api.bilibili.com/x/emote/setting/panel + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | -------- | ------ | -------------------------------- | +| business | str | 使用场景 | 必要 | reply:评论区<br />dynamic:动态 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------- | ----- | ---------------- | ---- | +| user_panel_packages | array | 用户拥有的表情包 | | +| all_packages | array | 所有表情包 | | +| mall | obj | 商城页面 | | + +`data`对象中的`user_panel_packages`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------------- | -------------- | +| 0 | obj | 用户拥有的表情包1 | **详情见附表** | +| n | obj | 用户拥有的表情包(n+1) | **详情见附表** | +| …… | obj | …… | …… | + +`data`对象中的`all_packages`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | -------------- | +| 0 | obj | 所有表情包1 | **详情见附表** | +| n | obj | 所有表情包(n+1) | **详情见附表** | +| …… | obj | …… | …… | + +`data`对象中的`mall`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ----------- | ---- | +| title | str | 商城名称 | | +| url | str | 商城页面url | | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/emote/setting/panel' \ +--data-urlencode 'business=reply' \ +-b 'SESSDATA=xxx' +``` + +**限于篇幅,代码块示例略** + +## 附表-表情包对象 + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ----- | ----------------- | -------------------------------------------------------- | +| id | num | 表情包id | | +| text | str | 表情包名称 | | +| url | str | 表情包标志图片url | | +| mtime | num | 创建时间 | 时间戳 | +| type | num | 表情包类型 | 1:普通<br />2:会员专属<br />3:购买所得<br />4:颜文字 | +| attr | num | ??? | **作用尚不明确** | +| meta | obj | 属性信息 | | +| emote | array | 表情列表 | | +| flags | obj | 是否添加标志 | | + +`表情包对象`中的`flags`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ---------- | ------------------------------------------------------------ | +| added | bool | 是否已添加 | true:已添加<br />false:未添加<br />需要登录(SESSDATA)<br />否则恒为false | + +`表情包对象`中的`meta`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | --------------- | ---------------- | +| size | num | 表情尺寸信息 | 1:小<br />2:大 | +| item_id | num | 购买物品id | | +| item_url | num | 购买物品页面url | 无则无此项 | + +`表情包对象`中的`emote`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---- | +| 0 | obj | 表情1 | | +| n | obj | 表情(n+1) | | +| …… | obj | …… | …… | + +`emote`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ----------- | -------------------------------------------------------- | +| id | num | 表情id | | +| package_id | num | 表情包id | | +| text | str | 表情转义符 | 颜文字时为该字串 | +| url | str | 表情图片url | 颜文字时为该字串 | +| mtime | num | 创建时间 | 时间戳 | +| type | num | 表情类型 | 1:普通<br />2:会员专属<br />3:购买所得<br />4:颜文字 | +| attr | num | ??? | **作用尚不明确** | +| meta | obj | 属性信息 | | +| flags | obj | 禁用标志 | 无则为空 | + +`emote`数组中的对象中的`flags`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ---------- | ------------------------------------------------------ | +| no_access | bool | 是否为禁用 | true:禁用<br />需要登录(SESSDATA)<br />否则恒为true | + +`emote`数组中的对象中的`meta`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ------------ | ---------------- | +| size | num | 表情尺寸信息 | 1:小<br />2:大 | +| alias | str | 简写名 | 无则无此项 | diff --git a/bb-api-collect/docs/fav/action.md b/bb-api-collect/docs/fav/action.md new file mode 100644 index 0000000000..1672164a19 --- /dev/null +++ b/bb-api-collect/docs/fav/action.md @@ -0,0 +1,472 @@ +# 收藏夹操作 + +## 管理收藏夹 + +### 新建收藏夹 + +> https://api.bilibili.com/x/v3/fav/folder/add + +*请求方式:POST* + +认证方式:APP或Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | ------------------------ | -------------- | ------------------------------------ | +| title | str | 收藏夹标题 | 必要 | | +| intro | str | 收藏夹简介 | 非必要 | 默认为空 | +| privacy | num | 是否公开 | 非必要 | 默认为公开<br />0:公开<br />1:私密 | +| cover | str | 封面图url | 非必要 | 封面会被审核 | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功<br />-102:账号被封停 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +略.... + +详见[获取收藏夹元数据](info.md#获取收藏夹元数据)中的`data`对象 + +**示例:** + +创建一个叫`test`,简介是`2333`,封面`https://i0.hdslb.com/bfs/space/cb1c3ef50e22b6096fde67febe863494caefebad.png`,的公开收藏夹: + +```shell +curl 'https://api.bilibili.com/x/v3/fav/folder/add' \ +--data-urlencode 'title=test' \ +--data-urlencode 'intro=2333' \ +--data-urlencode 'privacy=0' \ +--data-urlencode 'cover=https://i0.hdslb.com/bfs/space/cb1c3ef50e22b6096fde67febe863494caefebad.png' \ +--data-urlencode 'csrf=xxxx' \ +-b 'SESSDATA=xxxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "id": 1182306172, + "fid": 11823061, + "mid": 470310172, + "attr": 6, + "title": "test", + "cover": "https://i0.hdslb.com/bfs/space/cb1c3ef50e22b6096fde67febe863494caefebad.png", + "upper": { + "mid": 0, + "name": "", + "face": "", + "followed": false, + "vip_type": 0, + "vip_statue": 0 + }, + "cover_type": 0, + "cnt_info": { + "collect": 0, + "play": 0, + "thumb_up": 0, + "share": 0 + }, + "type": 0, + "intro": "2333", + "ctime": 0, + "mtime": 0, + "state": 0, + "fav_state": 0, + "like_state": 0, + "media_count": 0 + } +} +``` + +</details> + +### 修改收藏夹 + +> https://api.bilibili.com/x/v3/fav/folder/edit + +*请求方式:POST* + +认证方式:APP或Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------------------ | -------------- | ------------------------------------------ | +| media_id | num | 目标收藏夹mdid | 必要 | | +| title | str | 修改收藏夹标题 | 必要 | | +| intro | str | 修改收藏夹简介 | 非必要 | | +| privacy | num | 是否公开 | 非必要 | 默认为公开<br /><br />0:公开<br />1:私密 | +| cover | str | 封面图url | 非必要 | 封面会被审核 | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功<br />-102:账号被封停 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +略.... + +详见[获取收藏夹元数据](info.md#获取收藏夹元数据)中的`data`对象 + +**示例:** + +修改id为`1182306172`的名字为`test`,简介为`2333`,封面为`https://i0.hdslb.com/bfs/space/cb1c3ef50e22b6096fde67febe863494caefebad.png`,公开收藏夹: + +```shell +curl 'https://api.bilibili.com/x/v3/fav/folder/edit' \ +--data-urlencode 'media_id=1182306172' \ +--data-urlencode 'title=test' \ +--data-urlencode 'intro=2333' \ +--data-urlencode 'privacy=0' \ +--data-urlencode 'cover=https://i0.hdslb.com/bfs/space/cb1c3ef50e22b6096fde67febe863494caefebad.png' \ +--data-urlencode 'csrf=xxxx' \ +-b 'SESSDATA=xxxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "id": 1182306172, + "fid": 11823061, + "mid": 470310172, + "attr": 6, + "title": "test", + "cover": "https://i0.hdslb.com/bfs/space/cb1c3ef50e22b6096fde67febe863494caefebad.png", + "upper": { + "mid": 0, + "name": "", + "face": "", + "followed": false, + "vip_type": 0, + "vip_statue": 0 + }, + "cover_type": 0, + "cnt_info": { + "collect": 0, + "play": 0, + "thumb_up": 0, + "share": 0 + }, + "type": 0, + "intro": "2333", + "ctime": 0, + "mtime": 0, + "state": 0, + "fav_state": 0, + "like_state": 0, + "media_count": 0 + } +} +``` + +</details> + +### 删除收藏夹 + +> https://api.bilibili.com/x/v3/fav/folder/del + +*请求方式:POST* + +认证方式:APP或Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | ------------------------ | -------------- | ------------------- | +| media_ids | nums | 目标收藏夹mdid列表 | 必要 | 每个成员间用`,`分隔 | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | 成功为0 | +| ttl | num | 1 | | +| data | num | 信息本体 | 成功为0 | + +**示例:** + +删除id为`1182306172`的收藏夹: + +```shell +curl 'https://api.bilibili.com/x/v3/fav/folder/del' \ +--data-urlencode 'media_ids=1182306172' \ +--data-urlencode 'csrf=xxxx' \ +-b 'SESSDATA=xxxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code":0, + "message":"0", + "ttl":1, + "data":0 +} +``` + +</details> + +## 管理收藏内容 + +### 批量复制内容 + +> https://api.bilibili.com/x/v3/fav/resource/copy + +*请求方式:POST* + +认证方式:APP或Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------ | ---- | ------------------------ | -------------- | ------------------------------------------------------------ | +| src_media_id | num | 源收藏夹id | 必要 | | +| tar_media_id | num | 目标收藏夹id | 必要 | | +| mid | num | 当前用户mid | 必要 | | +| resources | strs | 目标内容id列表 | 必要 | 格式:{内容id}:{内容类型}<br />每个成员间用`,`分隔<br />类型:<br />2:视频稿件<br />12:音频<br />21:视频合集<br />内容id:<br />视频稿件:视频稿件avid<br />音频:音频auid<br />视频合集:视频合集id | +| platform | str | 平台标识 | 非必要 | 可为web | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf校验失败<br />-400:请求错误<br />11010:您访问的内容不存在 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | 成功为0 | + +**示例:** + +将id为`1288061499`的收藏夹中视频稿件`av21822819` `av21918689` `av22288065`复制到id为`1178751999`的收藏夹中 + +```shell +curl 'https://api.bilibili.com/x/v3/fav/resource/copy' \ +--data-urlencode 'src_media_id=1288061499' \ +--data-urlencode 'tar_media_id=1178751999' \ +--data-urlencode 'mid=233333' \ +--data-urlencode 'resources=21822819:2,21918689:2,22288065:2' \ +--data-urlencode 'platform=web' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + + +```json +{ + "code":0, + "message":"0", + "ttl":1, + "data":0 +} +``` + +</details> + +### 批量移动内容 + +> https://api.bilibili.com/x/v3/fav/resource/move + +*请求方式:POST* + +认证方式:APP或Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------ | ---- | ------------------------ | -------------- | ------------------------------------------------------------ | +| src_media_id | num | 源收藏夹id | 必要 | | +| tar_media_id | num | 目标收藏夹id | 必要 | | +| mid | num | 当前用户mid | 必要 | | +| resources | strs | 目标内容id列表 | 必要 | 格式:{内容id}:{内容类型}<br />每个成员间用`,`分隔<br />类型:<br />2:视频稿件<br />12:音频<br />21:视频合集<br />内容id:<br />视频稿件:视频稿件avid<br />音频:音频auid<br />视频合集:视频合集id | +| platform | str | 平台标识 | 非必要 | 可为web | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf校验失败<br />-400:请求错误<br />11010:您访问的内容不存在 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | 成功为0 | + +**示例:** + +将id为`1288061499`的收藏夹中视频稿件`av21822819` `av21918689` `av22288065`移动到id为`1178751999`的收藏夹中 + +```shell +curl 'https://api.bilibili.com/x/v3/fav/resource/move' \ +--data-urlencode 'src_media_id=1288061499' \ +--data-urlencode 'tar_media_id=1178751999' \ +--data-urlencode 'mid=233333' \ +--data-urlencode 'resources=21822819:2,21918689:2,22288065:2' \ +--data-urlencode 'platform=web' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + + +```json +{ + "code":0, + "message":"0", + "ttl":1, + "data":0 +} +``` + +</details> + +### 批量删除内容 + +> https://api.bilibili.com/x/v3/fav/resource/batch-del + +*请求方式:POST* + +认证方式:APP或Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | -------------- | ------------------------ | ------------------------------------------------------------ | ------- | +| resources | 目标内容id列表 | 必要 | 格式:{内容id}:{内容类型}<br />每个成员间用`,`分隔<br />类型:<br />2:视频稿件<br />12:音频<br />21:视频合集<br />内容id:<br />视频稿件:视频稿件avid<br />音频:音频auid<br />视频合集:视频合集id | | +| media_id | num | 目标收藏夹id | 必要 | | +| platform | str | 平台标识 | 非必要 | 可为web | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf校验失败<br />-400:请求错误<br />11010:您访问的内容不存在 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | 成功为0 | + +**示例:** + +将id为`1178751999`的收藏夹中视频稿件`av21822819` `av21918689` `av22288065`取消收藏 + +```shell +curl 'https://api.bilibili.com/x/v3/fav/resource/batch-del' \ +--data-urlencode 'resources=21822819:2,21918689:2,22288065:2' \ +--data-urlencode 'media_id=1178751999' \ +--data-urlencode 'platform=web' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + + +```json +{ + "code":0, + "message":"0", + "ttl":1, + "data":0 +} +``` + +</details> + +### 清空所有失效内容 + +> https://api.bilibili.com/x/v3/fav/resource/clean + +*请求方式:POST* + +认证方式:APP或Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------------------ | -------------- | ---- | +| media_id | num | 目标收藏夹id | 必要 | | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | 成功为0 | + +**示例:** + +清理id为`1161340172`的收藏夹 + +```shell +curl 'https://api.bilibili.com/x/v3/fav/resource/clean' \ +--data-urlencode 'media_id=1161340172' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + + +```json +{ + "code":0, + "message":"0", + "ttl":1, + "data":0 +} +``` + +</details> diff --git a/bb-api-collect/docs/fav/info.md b/bb-api-collect/docs/fav/info.md new file mode 100644 index 0000000000..fe0247833d --- /dev/null +++ b/bb-api-collect/docs/fav/info.md @@ -0,0 +1,571 @@ +# 收藏夹基本信息 + +<img src="../../assets/img/collect.svg" width="100" height="100" /> + +## 获取收藏夹元数据 + +> https://api.bilibili.com/x/v3/fav/folder/info + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) 或 APP + +**注:查询权限收藏夹时需要相应用户登录** + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ---------------------- | ------ | ---- | +| media_id | num | 目标收藏夹id(完整id) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----------------------------- | -------- | --------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-403:访问权限不足<br />11010: 内容不存在 | +| message | str | 错误信息 | 默认为0 | +| data | 有效时:obj<br />无效或:null | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | -------------------- | -------------------------------------------------- | +| id | num | 收藏夹mlid(完整id) | 收藏夹原始id+创建者mid尾号2位 | +| fid | num | 收藏夹原始id | | +| mid | num | 创建者mid | | +| attr | num | 属性位(?) | | +| title | str | 收藏夹标题 | | +| cover | str | 收藏夹封面图片url | | +| upper | obj | 创建者信息 | | +| cover_type | num | 封面图类别(?) | | +| cnt_info | obj | 收藏夹状态数 | | +| type | num | 类型(?) | 一般是11 | +| intro | str | 备注 | | +| ctime | num | 创建时间 | 时间戳 | +| mtime | num | 收藏时间 | 时间戳 | +| state | num | 状态(?) | 一般为0 | +| fav_state | num | 收藏夹收藏状态 | 已收藏收藏夹:1<br />未收藏收藏夹:0<br />需要登录 | +| like_state | num | 点赞状态 | 已点赞:1<br />未点赞:0<br />需要登录 | +| media_count | num | 收藏夹内容数量 | | + +`data`中的`upper`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ---------------- | ----------------------------------------------- | +| mid | num | 创建者mid | | +| name | str | 创建者昵称 | | +| face | str | 创建者头像url | | +| followed | bool | 是否已关注创建者 | | +| vip_type | num | 会员类别 | 0:无<br />1:月大会员<br />2:年度及以上大会员 | +| vip_statue | num | 会员开通状态 | 0:无<br />1:有 | + +`data`中的`cnt_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------ | ---- | +| collect | num | 收藏数 | | +| play | num | 播放数 | | +| thumb_up | num | 点赞数 | | +| share | num | 分享数 | | + +**示例:** + +查询收藏夹`id=1052622027`的元数据 + +```shell +curl -G 'https://api.bilibili.com/x/v3/fav/folder/info' \ +--data-urlencode 'media_id=1052622027' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "id": 1052622027, + "fid": 10526220, + "mid": 686127, + "attr": 54, + "title": "猛 男 生 存", + "cover": "http://i2.hdslb.com/bfs/archive/bb51ee8a5fc5e03996138155f0f682d30ee16484.jpg", + "upper": { + "mid": 686127, + "name": "籽岷", + "face": "http://i0.hdslb.com/bfs/face/7efb679569b2faeff38fa08f6f992fa1ada5e948.webp", + "followed": true, + "vip_type": 2, + "vip_statue": 1 + }, + "cover_type": 2, + "cnt_info": { + "collect": 3393, + "play": 184822, + "thumb_up": 3918, + "share": 44 + }, + "type": 11, + "intro": "猛 男 生 存", + "ctime": 1598884758, + "mtime": 1598884758, + "state": 0, + "fav_state": 0, + "like_state": 0, + "media_count": 28 + } +} +``` + +</details> + +## 获取指定用户创建的所有收藏夹信息 + +> https://api.bilibili.com/x/v3/fav/folder/created/list-all + +*请求方式:GET* + +认证方式:Cookie (SESSDATA) 或 APP + +若欲查看相应用户的私密收藏夹需要登录 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| up_mid | num | 目标用户mid | 必要 | | +| type | num | 目标内容属性 | 非必要 | 默认为全部<br />0:全部<br />2:视频稿件 | +| rid | num | 目标内容id | 非必要 | 视频稿件:视频稿件avid | +| web_location | str | 333.1387 | 非必要| | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----------------------------- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 隐藏时:null<br />公开时:obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | --------------------------------------- | -------------- | ---- | +| count | num | 创建的收藏夹数 | | +| list | 无收藏夹时:null<br />有收藏夹时:array | 收藏夹列表 | | +| season | null | (?) | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | --------------------- | +| 0 | obj | 收藏夹1 | | +| n | obj | 收藏夹(n+1) | 项数取决于`count`的值 | +| …… | obj | …… | | + +`data`中的`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ------------------------ | ------------------------------------------ | +| id | num | 收藏夹mlid(完整id) | 收藏夹原始id+创建者mid尾号2位 | +| fid | num | 收藏夹原始id | | +| mid | num | 创建者mid | | +| attr | num | 收藏夹属性 | 二进制位属性<br />详细说明见下表 | +| title | str | 收藏夹标题 | | +| fav_state | num | 目标id是否存在于该收藏夹 | 存在于该收藏夹:1<br />不存在于该收藏夹:0 | +| media_count | num | 收藏夹内容数量 | | + +`attr`属性位二进制值表: + +| 位 | 内容 | 备注 | +| --------------- | ---------------- | -------------------------------- | +| 0 | 私有收藏夹 | 0:公开<br />1:私有 | +| 1 | 是否为默认收藏夹 | 0:默认收藏夹<br />1:其他收藏夹 | +| 其他有待补充... | | | + +**示例:** + +查询用户`mid=7792521`的收藏夹列表 + +```shell +curl -G 'https://api.bilibili.com/x/v3/fav/folder/created/list-all' \ +--data-urlencode 'up_mid=7792521' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "count": 5, + "list": [{ + "id": 44233921, + "fid": 442339, + "mid": 7792521, + "attr": 0, + "title": "默认收藏夹", + "fav_state": 0, + "media_count": 85 + }, { + "id": 936347621, + "fid": 9363476, + "mid": 7792521, + "attr": 22, + "title": "放假君的鬼畜私房歌", + "fav_state": 0, + "media_count": 2 + }, { + "id": 845218621, + "fid": 8452186, + "mid": 7792521, + "attr": 22, + "title": "♪一言不合就开唱♪", + "fav_state": 0, + "media_count": 4 + }, { + "id": 844998121, + "fid": 8449981, + "mid": 7792521, + "attr": 22, + "title": "个人作品精选", + "fav_state": 0, + "media_count": 25 + }, { + "id": 381779121, + "fid": 3817791, + "mid": 7792521, + "attr": 22, + "title": "鬼畜小课堂", + "fav_state": 0, + "media_count": 25 + }] + } +} +``` + +</details> + +## 查询用户收藏的视频收藏夹 + +> https://api.bilibili.com/x/v3/fav/folder/collected/list + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| ps | num | 每页项数 | 必要 | 定义域 1 - 大于70 | +| pn | num | 页码 | 必要 | | +| up_mid | num | 目标用户mid | 必要 | | +| platform | str | 平台类型 | 非必要 | 填写web 返回值才会包含用户收藏的视频合集 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----------------------------- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf校验失败<br />40022:签名过长 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 隐藏时:null<br />公开时:obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | --------------------------------------- | -------------- | ---- | +| count | num | 创建的收藏夹数 | | +| list | 无收藏夹时:null<br />有收藏夹时:array | 收藏夹列表 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | --------------------- | +| 0 | obj | 收藏夹1 | | +| n | obj | 收藏夹(n+1) | 项数取决于`count`的值 | +| …… | obj | …… | | + +`data`中的`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ------------------ | ----------------------------------------- | +| id | num | 收藏夹ml | | +| fid | num | 原始收藏夹mlid | 去除两位mid尾号 | +| mid | num | 创建用户mid | | +| attr | num | 收藏夹属性 | [同上 attr](#获取指定用户创建的所有收藏夹信息) | +| title | str | 收藏夹标题 | | +| cover | str | 收藏夹封面图片url | | +| upper | obj | 收藏夹创建用户信息 | | +| cover_type | num | 2 | 作用尚不明确 | +| intro | str | 空 | 作用尚不明确 | +| ctime | num | 创建时间 | 时间戳 | +| mtime | num | 审核时间 | 时间戳 | +| state | num | 0, 1 | 0: 正常;1:收藏夹已失效 | +| fav_state | num | 0 | 作用尚不明确 | +| media_count | num | 收藏夹总计视频数 | | + +`data`中的`list`数组中的对象中的`upper`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------- | ------------ | +| mid | num | 创建人mid | | +| name | str | 创建人昵称 | | +| face | str | 空 | 作用尚不明确 | + +**示例:** + +查询用户`mid=293793435`的收藏夹收藏列表 + +```shell +curl -G 'https://api.bilibili.com/x/v3/fav/folder/collected/list' \ +--data-urlencode 'up_mid=293793435' \ +--data-urlencode 'ps=20' \ +--data-urlencode 'pn=1' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "count": 2, + "list": [{ + "id": 496307088, + "fid": 4963070, + "mid": 412466388, + "attr": 22, + "title": "入站必刷", + "cover": "http://i0.hdslb.com/bfs/archive/baae2b4050363c0ab45465b7cf696b8304fdaca8.jpg", + "upper": { + "mid": 412466388, + "name": "热门菌", + "face": "" + }, + "cover_type": 2, + "intro": "", + "ctime": 1563394571, + "mtime": 1563394571, + "state": 0, + "fav_state": 0, + "media_count": 55 + }, { + "id": 381779121, + "fid": 3817791, + "mid": 7792521, + "attr": 22, + "title": "鬼畜小课堂", + "cover": "http://i2.hdslb.com/bfs/archive/09a668cfdb38fb3a85f905c10f48a2947e36a695.jpg", + "upper": { + "mid": 7792521, + "name": "还有一天就放假了", + "face": "" + }, + "cover_type": 2, + "intro": "", + "ctime": 1553700224, + "mtime": 1557291666, + "state": 0, + "fav_state": 0, + "media_count": 25 + }] + } +} +``` + +</details> + +## 批量获取指定收藏id的内容 + +> https://api.bilibili.com/x/v3/fav/resource/infos + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | -------------- | ------ | ------------------------------------------------------------ | +| resources | strs | 目标内容id列表 | 必要 | 格式:{内容id}:{内容类型}<br />每个成员间用`,`分隔<br />类型:<br />2:视频稿件<br />12:音频<br />内容id:<br />视频稿件:视频稿件avid<br />音频:音频auid | +| platform | str | 平台标识 | 非必要 | 可为web(影响内容列表类型) | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------------------------------- | ------------ | --------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| data | 有效时:array<br />无效或:null | 内容信息列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | obj | 内容信息1 | | +| n | obj | 内容信息(n+1) | | +| ... | obj | ... | | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------------- | ------------------------------------------------------------ | +| id | num | 内容id | 视频稿件:视频稿件avid<br />音频:音频auid | +| type | num | 内容类型 | 2:视频稿件<br />12:音频 | +| title | str | 标题 | | +| cover | str | 封面url | | +| intro | str | 简介 | | +| page | num | 视频分P数 | | +| duration | num | 音频/视频时长 | | +| upper | obj | UP主信息 | | +| attr | num | 属性 | 0:正常<br />1:失效 | +| cnt_info | obj | 状态数 | | +| link | str | 跳转uri | | +| ctime | num | 投稿时间 | 时间戳 | +| pubtime | num | 发布时间 | 时间戳 | +| fav_time | num | 收藏时间 | 时间戳 | +| bv_id | str | 视频稿件bvid | | +| bvid | str | 视频稿件bvid | | +| season | null | (?) | | + +`data`数组中的对象中的`upper`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---- | +| mid | num | UP主mid | | +| name | str | UP主昵称 | | +| face | str | UP主头像url | | + +`data`数组中的对象中的`cnt_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ------ | ---- | +| collect | num | 收藏数 | | +| play | num | 播放数 | | +| danmaku | num | 弹幕数 | | + +**示例:** + +批量查询内容 + +1-视频稿件-`av583785685` + +2-音频-`au15664` + +```shell +curl -G 'https://api.bilibili.com/x/v3/fav/resource/infos' \ +--data-urlencode 'resources=583785685:2,15664:12' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "id": 583785685, + "type": 2, + "title": "已失效视频", + "cover": "http://i0.hdslb.com/bfs/archive/be27fd62c99036dce67efface486fb0a88ffed06.jpg", + "intro": "审核君辛苦了~\r\n使用curl命令访问B站api,实现二维码登录 查询登录信息 视频投币 发送评论的操作\r\n本视频作为api收集项目的一个硬核DEMO\r\n由于当时录音的问题,大部分是后期配的,后面声音有点小\r\n想了解更多的去github页面,也可以qq\r\n\r\nbgm:\r\n雲流れ\r\nAutumn rain(未修改版)\r\n四月,初雨微凉", + "page": 1, + "duration": 604, + "upper": { + "mid": 293793435, + "name": "社会易姐QwQ", + "face": "http://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg" + }, + "attr": 1, + "cnt_info": { + "collect": 1470, + "play": 28374, + "danmaku": 64 + }, + "link": "bilibili://video/583785685", + "ctime": 1594049831, + "pubtime": 1594049831, + "fav_time": 0, + "bv_id": "BV1kz4y1X7XP", + "bvid": "BV1kz4y1X7XP", + "season": null + }, + { + "id": 523, + "type": 21, + "title": "2021哔哩哔哩拜年纪", + "cover": "https://i0.hdslb.com/bfs/archive/8ccc50f7cbc671762e0536491bd2b8aeebc0837d.jpg", + "intro": "感谢各位制作者们的辛勤付出!节目精彩,愿大家看的开心!", + "page": 0, + "duration": 0, + "upper": { + "mid": 1868902080, + "name": "哔哩哔哩拜年纪", + "face": "http://i0.hdslb.com/bfs/face/7f6cb94fc071aca9fbb4b1ca9cc6415e86847576.jpg" + }, + "attr": 0, + "cnt_info": { + "collect": 0, + "play": 71527018, + "danmaku": 480547 + }, + "link": "bilibili://video/373561162", + "ctime": 0, + "pubtime": 0, + "fav_time": 0, + "bv_id": "", + "bvid": "", + "season": null + }, + { + "id": 15664, + "type": 12, + "title": "威风堂堂", + "cover": "http://i0.hdslb.com/bfs/music/c417d30b394a8a5d4e8a150ad75837dbae3b79d4.jpg", + "intro": "翻唱。在电脑里放了半个月终于!!!大家寒假快乐!!❁本家sm19233263;❁压制: 寒雨;❁mix: 三星堆;❁vocal: 茶理理。超喜欢michan的那段英文念白所以加了进来w 谢谢三月月和嘟比比你们后期辛苦了!", + "page": 1, + "duration": 200, + "upper": { + "mid": 684169, + "name": "茶理理理子", + "face": "" + }, + "attr": 0, + "cnt_info": { + "collect": 48872, + "play": 1508426, + "danmaku": 0 + }, + "link": "bilibili://music/detail/15664?name=%E5%A8%81%E9%A3%8E%E5%A0%82%E5%A0%82&uperName=%E8%8C%B6%E7%90%86%E7%90%86%E7%90%86%E5%AD%90&cover_url=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Fmusic%2Fc417d30b394a8a5d4e8a150ad75837dbae3b79d4.jpg&upperId=684169&author=%E8%8C%B6%E7%90%86%E7%90%86", + "ctime": 1502347604, + "pubtime": 1502347604, + "fav_time": 0, + "bv_id": "BV1bx411c7qt", + "bvid": "BV1bx411c7qt", + "season": null + } + ] +} +``` + +</details> diff --git a/bb-api-collect/docs/fav/list.md b/bb-api-collect/docs/fav/list.md new file mode 100644 index 0000000000..34cbae9a67 --- /dev/null +++ b/bb-api-collect/docs/fav/list.md @@ -0,0 +1,560 @@ +# 收藏夹内容 + +## 获取收藏夹内容明细列表 + +> https://api.bilibili.com/x/v3/fav/resource/list + +*请求方式:GET* + +认证方式:Cookie或APP + +**注:查询权限收藏夹时需要相应用户登录** + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------------------ | ------ | ------------------------------------------------------------ | +| media_id | num | 目标收藏夹mlid(完整id) | 必要 | | +| tid | num | 分区tid | 非必要 | 默认为全部分区<br />0:全部分区<br />[详见说明](../video/video_zone.md) | +| keyword | str | 搜索关键字 | 非必要 | | +| order | str | 排序方式 | 非必要 | 按收藏时间:mtime<br />按播放量: view<br />按投稿时间:pubtime | +| type | num | 查询范围 | 非必要 | 0:当前收藏夹(对应media_id)<br /> 1:全部收藏夹 | +| ps | num | 每页数量 | 必要 | 定义域:1-20 | +| pn | num | 页码 | 非必要 | 默认为1 | +| platform | str | 平台标识 | 非必要 | 可为web(影响内容列表类型) | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----------------------------- | -------- | --------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-403:访问权限不足 | +| message | str | 错误信息 | 默认为0 | +| data | 有效时:obj<br />无效或:null | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ----- | ------------ | ---- | +| info | obj | 收藏夹元数据 | | +| medias | array | 收藏夹内容 | | +| has_more | bool | 收藏夹是否有下一页 | | +| ttl | num | 接口返回时间 | 时间戳 | + +`data`中的`info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | -------------------- | -------------------------------------------------- | +| id | num | 收藏夹mlid(完整id) | 收藏夹原始id+创建者mid尾号2位 | +| fid | num | 收藏夹原始id | | +| mid | num | 创建者mid | | +| attr | num | 属性 | 0:正常<br />1:失效 | +| title | str | 收藏夹标题 | | +| cover | str | 收藏夹封面图片url | | +| upper | obj | 创建者信息 | | +| cover_type | num | 封面图类别(?) | | +| cnt_info | obj | 收藏夹状态数 | | +| type | num | 类型(?) | 一般是11 | +| intro | str | 备注 | | +| ctime | num | 创建时间 | 时间戳 | +| mtime | num | 收藏时间 | 时间戳 | +| state | num | 状态(?) | 一般为0 | +| fav_state | num | 收藏夹收藏状态 | 已收藏收藏夹:1<br />未收藏收藏夹:0<br />需要登录 | +| like_state | num | 点赞状态 | 已点赞:1<br />未点赞:0<br />需要登录 | +| media_count | num | 收藏夹内容数量 | | + + +`info`中的`upper`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ---------------- | ----------------------------------------------- | +| mid | num | 创建者mid | | +| name | str | 创建者昵称 | | +| face | str | 创建者头像url | | +| followed | bool | 是否已关注创建者 | | +| vip_type | num | 会员类别 | 0:无<br />1:月大会员<br />2:年度及以上大会员 | +| vip_statue | num | 会员开通状态 | 0:无<br />1:有 | + +`info`中的`cnt_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------ | ---- | +| collect | num | 收藏数 | | +| play | num | 播放数 | | +| thumb_up | num | 点赞数 | | +| share | num | 分享数 | | + +`data`中的`medias`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---- | +| 0 | obj | 收藏内容1 | | +| n | obj | 收藏内容(n+1) | | +| ... | obj | ... | | + +`medias`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------------- | ------------------------------------------------------------ | +| id | num | 内容id | 视频稿件:视频稿件avid<br />音频:音频auid<br />视频合集:视频合集id | +| type | num | 内容类型 | 2:视频稿件<br />12:音频<br />21:视频合集 | +| title | str | 标题 | | +| cover | str | 封面url | | +| intro | str | 简介 | | +| page | num | 视频分P数 | | +| duration | num | 音频/视频时长 | | +| upper | obj | UP主信息 | | +| attr | num | 失效 | 0: 正常;9: up自己删除;1: 其他原因删除 | +| cnt_info | obj | 状态数 | | +| link | str | 跳转uri | | +| ctime | num | 投稿时间 | 时间戳 | +| pubtime | num | 发布时间 | 时间戳 | +| fav_time | num | 收藏时间 | 时间戳 | +| bv_id | str | 视频稿件bvid | | +| bvid | str | 视频稿件bvid | | +| season | null | (?) | | + +`medias`数组中的对象中的`upper`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---- | +| mid | num | UP主mid | | +| name | str | UP主昵称 | | +| face | str | UP主头像url | | + +`medias`数组中的对象中的`cnt_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ------ | ---- | +| collect | num | 收藏数 | | +| play | num | 播放数 | | +| danmaku | num | 弹幕数 | | + +**示例:** + +查询收藏夹`id=1052622027`,每页5个视频,第`1`页的内容明细 + +```shell +curl -G 'https://api.bilibili.com/x/v3/fav/resource/list' \ +--data-urlencode 'media_id=1052622027' \ +--data-urlencode 'platform=web' \ +--data-urlencode 'pn=1' \ +--data-urlencode 'ps=5' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "info": { + "id": 1052622027, + "fid": 10526220, + "mid": 686127, + "attr": 54, + "title": "猛 男 生 存", + "cover": "http://i2.hdslb.com/bfs/archive/bb51ee8a5fc5e03996138155f0f682d30ee16484.jpg", + "upper": { + "mid": 686127, + "name": "籽岷", + "face": "http://i0.hdslb.com/bfs/face/7efb679569b2faeff38fa08f6f992fa1ada5e948.webp", + "followed": true, + "vip_type": 2, + "vip_statue": 1 + }, + "cover_type": 2, + "cnt_info": { + "collect": 3393, + "play": 184768, + "thumb_up": 3916, + "share": 44 + }, + "type": 11, + "intro": "猛 男 生 存", + "ctime": 1598884758, + "mtime": 1598884758, + "state": 0, + "fav_state": 0, + "like_state": 0, + "media_count": 28 + }, + "medias": [ + { + "id": 371494037, + "type": 2, + "title": "猛 男 生 存", + "cover": "http://i2.hdslb.com/bfs/archive/bb51ee8a5fc5e03996138155f0f682d30ee16484.jpg", + "intro": "如果大家喜欢我的视频,别忘了点个赞,一键三连,或者关注我的频道哦~\n也可以把我的视频分享给你们的朋友们~\n\n第一集:BV1CZ4y1T7gC\n第二集:BV1oA411a72k\n第三集:BV1fK4y1e7Yj\n第四集:BV1Ya4y1E7Y6\n第五集:BV17V411z75A\n第六集:BV1oi4y137sw\n第七集:BV1Wt4y1D7Uu\n第八集:BV1Bp4y1q7y9\n第九集:BV1Lv411v7G2\n第十集:BV1Xi4y137ER\n第十一集:BV1nC4y1879J\n第十二集:BV1K54y1", + "page": 1, + "duration": 546, + "upper": { + "mid": 686127, + "name": "籽岷", + "face": "http://i0.hdslb.com/bfs/face/7efb679569b2faeff38fa08f6f992fa1ada5e948.webp" + }, + "attr": 0, + "cnt_info": { + "collect": 11256, + "play": 1638040, + "danmaku": 7697 + }, + "link": "bilibili://video/371494037", + "ctime": 1595690513, + "pubtime": 1595690513, + "fav_time": 1598884777, + "bv_id": "BV1CZ4y1T7gC", + "bvid": "BV1CZ4y1T7gC", + "season": null + }, + { + "id": 328991940, + "type": 2, + "title": "猛 男 生 存 2", + "cover": "http://i1.hdslb.com/bfs/archive/aa801612ea0229a08d000a525b715af24cba0964.jpg", + "intro": "如果大家喜欢我的视频,别忘了点个赞,一键三连,或者关注我的频道哦~\n也可以把我的视频分享给你们的朋友们~\n\n第一集:BV1CZ4y1T7gC\n第二集:BV1oA411a72k\n第三集:BV1fK4y1e7Yj\n第四集:BV1Ya4y1E7Y6\n第五集:BV17V411z75A\n第六集:BV1oi4y137sw\n第七集:BV1Wt4y1D7Uu\n第八集:BV1Bp4y1q7y9\n第九集:BV1Lv411v7G2\n第十集:BV1Xi4y137ER\n第十一集:BV1nC4y1879J\n第十二集:BV1K54y1", + "page": 1, + "duration": 644, + "upper": { + "mid": 686127, + "name": "籽岷", + "face": "http://i0.hdslb.com/bfs/face/7efb679569b2faeff38fa08f6f992fa1ada5e948.webp" + }, + "attr": 0, + "cnt_info": { + "collect": 8695, + "play": 1334651, + "danmaku": 6064 + }, + "link": "bilibili://video/328991940", + "ctime": 1595770876, + "pubtime": 1595770876, + "fav_time": 1598884783, + "bv_id": "BV1oA411a72k", + "bvid": "BV1oA411a72k", + "season": null + }, + { + "id": 884042215, + "type": 2, + "title": "猛 男 生 存 3", + "cover": "http://i1.hdslb.com/bfs/archive/f99059637c110dcd1cdae765a946801fbcefe4ab.jpg", + "intro": "如果大家喜欢我的视频,别忘了点个赞,一键三连,或者关注我的频道哦~\n也可以把我的视频分享给你们的朋友们~\n\n第一集:BV1CZ4y1T7gC\n第二集:BV1oA411a72k\n第三集:BV1fK4y1e7Yj\n第四集:BV1Ya4y1E7Y6\n第五集:BV17V411z75A\n第六集:BV1oi4y137sw\n第七集:BV1Wt4y1D7Uu\n第八集:BV1Bp4y1q7y9\n第九集:BV1Lv411v7G2\n第十集:BV1Xi4y137ER\n第十一集:BV1nC4y1879J\n第十二集:BV1K54y1", + "page": 1, + "duration": 703, + "upper": { + "mid": 686127, + "name": "籽岷", + "face": "http://i0.hdslb.com/bfs/face/7efb679569b2faeff38fa08f6f992fa1ada5e948.webp" + }, + "attr": 0, + "cnt_info": { + "collect": 9449, + "play": 1429408, + "danmaku": 8243 + }, + "link": "bilibili://video/884042215", + "ctime": 1595847079, + "pubtime": 1595847079, + "fav_time": 1598884788, + "bv_id": "BV1fK4y1e7Yj", + "bvid": "BV1fK4y1e7Yj", + "season": null + }, + { + "id": 669013980, + "type": 2, + "title": "猛 男 生 存 4", + "cover": "http://i1.hdslb.com/bfs/archive/def0f7009cb9a8b581ee03be9565918ff0c1913d.jpg", + "intro": "如果大家喜欢我的视频,别忘了点个赞,一键三连,或者关注我的频道哦~\n也可以把我的视频分享给你们的朋友们~\n\n第一集:BV1CZ4y1T7gC\n第二集:BV1oA411a72k\n第三集:BV1fK4y1e7Yj\n第四集:BV1Ya4y1E7Y6\n第五集:BV17V411z75A\n第六集:BV1oi4y137sw\n第七集:BV1Wt4y1D7Uu\n第八集:BV1Bp4y1q7y9\n第九集:BV1Lv411v7G2\n第十集:BV1Xi4y137ER\n第十一集:BV1nC4y1879J\n第十二集:BV1K54y1", + "page": 1, + "duration": 895, + "upper": { + "mid": 686127, + "name": "籽岷", + "face": "http://i0.hdslb.com/bfs/face/7efb679569b2faeff38fa08f6f992fa1ada5e948.webp" + }, + "attr": 0, + "cnt_info": { + "collect": 9950, + "play": 1309544, + "danmaku": 13551 + }, + "link": "bilibili://video/669013980", + "ctime": 1595943988, + "pubtime": 1595943988, + "fav_time": 1598884792, + "bv_id": "BV1Ya4y1E7Y6", + "bvid": "BV1Ya4y1E7Y6", + "season": null + }, + { + "id": 414034824, + "type": 2, + "title": "猛 男 生 存 5", + "cover": "http://i2.hdslb.com/bfs/archive/b4844ac89dde221d13bb8ddff80a8c4658bf7dc5.jpg", + "intro": "如果大家喜欢我的视频,别忘了点个赞,一键三连,或者关注我的频道哦~\n也可以把我的视频分享给你们的朋友们~\n\n第一集:BV1CZ4y1T7gC\n第二集:BV1oA411a72k\n第三集:BV1fK4y1e7Yj\n第四集:BV1Ya4y1E7Y6\n第五集:BV17V411z75A\n第六集:BV1oi4y137sw\n第七集:BV1Wt4y1D7Uu\n第八集:BV1Bp4y1q7y9\n第九集:BV1Lv411v7G2\n第十集:BV1Xi4y137ER\n第十一集:BV1nC4y1879J\n第十二集:BV1K54y1", + "page": 1, + "duration": 814, + "upper": { + "mid": 686127, + "name": "籽岷", + "face": "http://i0.hdslb.com/bfs/face/7efb679569b2faeff38fa08f6f992fa1ada5e948.webp" + }, + "attr": 0, + "cnt_info": { + "collect": 9446, + "play": 1235998, + "danmaku": 9021 + }, + "link": "bilibili://video/414034824", + "ctime": 1596023668, + "pubtime": 1596023668, + "fav_time": 1598884798, + "bv_id": "BV17V411z75A", + "bvid": "BV17V411z75A", + "season": null + } + ], + "has_more": true, + "ttl": 1703349018 + } +} +``` + +</details> + +## 获取收藏夹全部内容id + +> https://api.bilibili.com/x/v3/fav/resource/ids + +*请求方式:GET* + +认证方式:Cookie或APP + +**注:查询权限收藏夹时需要相应用户登录** + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------------------ | ------ | --------------------------- | +| media_id | num | 目标收藏夹mlid(完整id) | 必要 | | +| platform | str | 平台标识 | 非必要 | 可为web(影响内容列表类型) | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------------------------------- | ---------- | --------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-400:请求错误<br />-403:访问权限不足 | +| message | str | 错误信息 | 默认为0 | +| data | 有效时:array<br />无效或:null | 内容id列表 | | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ------------ | ------------------------------------------------------------ | +| id | num | 内容id | 视频稿件:视频稿件avid<br />音频:音频auid<br />视频合集:视频合集id | +| type | num | 内容类型 | 2:视频稿件<br />12:音频<br />21:视频合集 | +| bv_id | str | 视频稿件bvid | | +| bvid | str | 视频稿件bvid | | + +**示例:** + +查询收藏夹`id=1052622027`的全部内容id + +```shell +curl -G 'https://api.bilibili.com/x/v3/fav/resource/ids' \ +--data-urlencode 'media_id=1052622027' \ +--data-urlencode 'platform=web' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "id": 371494037, + "type": 2, + "bv_id": "BV1CZ4y1T7gC", + "bvid": "BV1CZ4y1T7gC" + }, + { + "id": 328991940, + "type": 2, + "bv_id": "BV1oA411a72k", + "bvid": "BV1oA411a72k" + }, + { + "id": 884042215, + "type": 2, + "bv_id": "BV1fK4y1e7Yj", + "bvid": "BV1fK4y1e7Yj" + }, + { + "id": 669013980, + "type": 2, + "bv_id": "BV1Ya4y1E7Y6", + "bvid": "BV1Ya4y1E7Y6" + }, + { + "id": 414034824, + "type": 2, + "bv_id": "BV17V411z75A", + "bvid": "BV17V411z75A" + }, + { + "id": 541550765, + "type": 2, + "bv_id": "BV1oi4y137sw", + "bvid": "BV1oi4y137sw" + }, + { + "id": 626619000, + "type": 2, + "bv_id": "BV1Wt4y1D7Uu", + "bvid": "BV1Wt4y1D7Uu" + }, + { + "id": 969124957, + "type": 2, + "bv_id": "BV1Bp4y1q7y9", + "bvid": "BV1Bp4y1q7y9" + }, + { + "id": 244079274, + "type": 2, + "bv_id": "BV1Lv411v7G2", + "bvid": "BV1Lv411v7G2" + }, + { + "id": 541500006, + "type": 2, + "bv_id": "BV1Xi4y137ER", + "bvid": "BV1Xi4y137ER" + }, + { + "id": 796655080, + "type": 2, + "bv_id": "BV1nC4y1879J", + "bvid": "BV1nC4y1879J" + }, + { + "id": 839243447, + "type": 2, + "bv_id": "BV1K54y1U77v", + "bvid": "BV1K54y1U77v" + }, + { + "id": 329235451, + "type": 2, + "bv_id": "BV13A411e7ad", + "bvid": "BV13A411e7ad" + }, + { + "id": 884202228, + "type": 2, + "bv_id": "BV1UK4y1v7K6", + "bvid": "BV1UK4y1v7K6" + }, + { + "id": 926710567, + "type": 2, + "bv_id": "BV1BT4y157HK", + "bvid": "BV1BT4y157HK" + }, + { + "id": 754200948, + "type": 2, + "bv_id": "BV1qk4y117Uk", + "bvid": "BV1qk4y117Uk" + }, + { + "id": 371795957, + "type": 2, + "bv_id": "BV1iZ4y1K7LG", + "bvid": "BV1iZ4y1K7LG" + }, + { + "id": 969268280, + "type": 2, + "bv_id": "BV1hp4y1v7mU", + "bvid": "BV1hp4y1v7mU" + }, + { + "id": 414281629, + "type": 2, + "bv_id": "BV1xV411U7mm", + "bvid": "BV1xV411U7mm" + }, + { + "id": 839319009, + "type": 2, + "bv_id": "BV1t54y1U7hg", + "bvid": "BV1t54y1U7hg" + }, + { + "id": 329271769, + "type": 2, + "bv_id": "BV12A411J7JZ", + "bvid": "BV12A411J7JZ" + }, + { + "id": 969365400, + "type": 2, + "bv_id": "BV1wp4y1i7U8", + "bvid": "BV1wp4y1i7U8" + }, + { + "id": 796831427, + "type": 2, + "bv_id": "BV1yC4y1t7Gb", + "bvid": "BV1yC4y1t7Gb" + }, + { + "id": 711972863, + "type": 2, + "bv_id": "BV1YD4y1m7FP", + "bvid": "BV1YD4y1m7FP" + }, + { + "id": 754414390, + "type": 2, + "bv_id": "BV1Yk4y127YR", + "bvid": "BV1Yk4y127YR" + }, + { + "id": 839478683, + "type": 2, + "bv_id": "BV1i54y127uw", + "bvid": "BV1i54y127uw" + }, + { + "id": 499448381, + "type": 2, + "bv_id": "BV19K411N7KE", + "bvid": "BV19K411N7KE" + }, + { + "id": 926919797, + "type": 2, + "bv_id": "BV1QT4y1L7Bb", + "bvid": "BV1QT4y1L7Bb" + } + ] +} +``` + +</details> diff --git a/bb-api-collect/docs/garb/color.md b/bb-api-collect/docs/garb/color.md new file mode 100644 index 0000000000..c27c16b9a5 --- /dev/null +++ b/bb-api-collect/docs/garb/color.md @@ -0,0 +1,311 @@ +# 主题色 + +## 获取主题色基本信息1 + +> https://club.bilibili.com/api/query.skin.list.do + +*请求方式:GET* + +鉴权方式:appkey + +认证方式:仅可APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | ------------- | +| access_key | str | APP登录Token | APP方式必要 | | +| appkey | str | APP密钥 | APP方式必要 | | +| build | num | 版本 | APP方式必要 | 可为`6082000` | +| sign | str | APP签名 | APP方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ----- | ------------ | ---------------------------------------------------- | +| ts | num | 当前时间戳 | | +| code | num | 返回值 | 0:成功<br />-3:API校验密匙错误<br />-400:请求错误 | +| data | array | 主题颜色列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---- | +| 0 | obj | 主题颜色1 | | +| n | obj | 主题颜色(n+1) | | +| …… | obj | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------ | ------------------------------- | +| id | num | 颜色id | | +| name | str | 颜色名称 | | +| is_free | bool | 是否免费 | false:收费<br />true:免费 | +| price | num | 价格 | 单位为硬币 | +| is_bought | bool | 是否已购买 | false:未购买<br />true:已购买 | +| status | num | 状态 | 1:自动续费<br />4:已退订 | +| buy_time | num | 购买时间 | 毫秒时间戳 | +| due_time | num | 到期时间 | 毫秒时间戳 | +| color_name | str | 颜色类型名称 | | +| is_overdue | bool | 是否已到期 | false:未到期<br />true:已到期 | + +**示例:** + +```shell +curl -G 'https://club.bilibili.com/api/query.skin.list.do' \ +--data-urlencode 'access_key=xxx' \ +--data-urlencode 'appkey=1d8b6e7d45233436' \ +--data-urlencode 'build=6082000' \ +--data-urlencode 'sign=2d37f2cd6f86337a6a07cb3cf311be86' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "ts": 1599225638239, + "code": 0, + "data": [ + { + "id": 2, + "name": "少女粉", + "is_free": true, + "price": 0, + "is_bought": false, + "color_name": "pink", + "is_overdue": false + }, + { + "id": 1, + "name": "夜间模式", + "is_free": true, + "price": 0, + "is_bought": false, + "color_name": "black", + "is_overdue": false + }, + { + "id": 3, + "name": "姨妈红", + "is_free": false, + "price": 5, + "is_bought": false, + "color_name": "red", + "is_overdue": false + }, + { + "id": 4, + "name": "咸蛋黄", + "is_free": false, + "price": 5, + "is_bought": false, + "color_name": "yellow", + "is_overdue": false + }, + { + "id": 5, + "name": "早苗绿", + "is_free": false, + "price": 5, + "is_bought": false, + "status": 4, + "buy_time": 1599219782000, + "due_time": 1601811782000, + "color_name": "green", + "is_overdue": false + }, + { + "id": 6, + "name": "胖次蓝", + "is_free": false, + "price": 5, + "is_bought": false, + "color_name": "blue", + "is_overdue": false + }, + { + "id": 7, + "name": "基佬紫", + "is_free": false, + "price": 5, + "is_bought": false, + "color_name": "purple", + "is_overdue": false + } + ] +} +``` + +</details> + +## 获取主题色基本信息2 + +> https://api.bilibili.com/x/garb/skin/color/list + +*请求方式:GET* + +认证方式:仅可Cookie + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | -------- | ------ | ------------- | +| mobi_app | str | 平台标识 | 非必要 | 可为`android` | +| build | num | 版本 | 非必要 | 可为`6082000` | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | ------------ | ---------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-3:API校验密匙错误<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| data | array | 主题颜色列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---- | +| 0 | obj | 主题颜色1 | | +| n | obj | 主题颜色(n+1) | | +| …… | obj | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------ | ------------------------------- | +| id | num | 颜色id | | +| name | str | 颜色名称 | | +| is_free | bool | 是否免费 | false:收费<br />true:免费 | +| price | num | 价格 | 单位为硬币 | +| is_bought | bool | 是否已购买 | false:未购买<br />true:已购买 | +| status | num | 状态 | 1:自动续费<br />4:已退订 | +| buy_time | num | 购买时间 | 毫秒时间戳 | +| due_time | num | 到期时间 | 毫秒时间戳 | +| color_name | str | 颜色类型名称 | | +| is_overdue | bool | 是否已到期 | false:未到期<br />true:已到期 | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/garb/skin/color/list' \ +--data-urlencode 'mobi_app=android' \ +--data-urlencode 'build=6082000' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "id": 8, + "name": "简洁白", + "is_free": true, + "price": 0, + "is_bought": false, + "status": 0, + "buy_time": 0, + "due_time": 0, + "color_name": "white", + "is_overdue": false + }, + { + "id": 2, + "name": "少女粉", + "is_free": true, + "price": 0, + "is_bought": false, + "status": 0, + "buy_time": 0, + "due_time": 0, + "color_name": "pink", + "is_overdue": false + }, + { + "id": 1, + "name": "夜间模式", + "is_free": true, + "price": 0, + "is_bought": false, + "status": 0, + "buy_time": 0, + "due_time": 0, + "color_name": "black", + "is_overdue": false + }, + { + "id": 3, + "name": "姨妈红", + "is_free": false, + "price": 5, + "is_bought": false, + "status": 0, + "buy_time": 0, + "due_time": 0, + "color_name": "red", + "is_overdue": false + }, + { + "id": 4, + "name": "咸蛋黄", + "is_free": false, + "price": 5, + "is_bought": false, + "status": 0, + "buy_time": 0, + "due_time": 0, + "color_name": "yellow", + "is_overdue": false + }, + { + "id": 5, + "name": "早苗绿", + "is_free": false, + "price": 5, + "is_bought": false, + "status": 4, + "buy_time": 1599219782000, + "due_time": 1601811782000, + "color_name": "green", + "is_overdue": false + }, + { + "id": 6, + "name": "胖次蓝", + "is_free": false, + "price": 5, + "is_bought": false, + "status": 0, + "buy_time": 0, + "due_time": 0, + "color_name": "blue", + "is_overdue": false + }, + { + "id": 7, + "name": "基佬紫", + "is_free": false, + "price": 5, + "is_bought": false, + "status": 0, + "buy_time": 0, + "due_time": 0, + "color_name": "purple", + "is_overdue": false + } + ] +} +``` + +</details> \ No newline at end of file diff --git a/bb-api-collect/docs/garb/lottery.md b/bb-api-collect/docs/garb/lottery.md new file mode 100644 index 0000000000..d4dab774c7 --- /dev/null +++ b/bb-api-collect/docs/garb/lottery.md @@ -0,0 +1,3201 @@ +# 装扮/收藏集 + +由 [#1080](https://github.com/SocialSisterYi/bilibili-API-collect/issues/1080) 提供 + +## 装扮/收藏集搜索API + +> https://api.bilibili.com/x/garb/v2/mall/home/search + +*请求方式: GET* + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|----- |--- |------- |----- |--- | +| key_word | str | 关键词 | 不必要 | | +| ps | int | 每页返回数据的最大值 | 不必要 | | +| pn | int | 当前页数 | 不必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|-- |-- |-- |-- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 返回数据 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +|-|---|--|--| +| list | array | 返回数据 | 若无则为 null | +| ps | int | 每页返回数据的最大值 | 默认为20 | +| pn | int | 当前页数 | 默认为1 | +| total | int | 查询到数据的总个数 | | + +`data` 中的 `list` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|-|---|--|--| +| item_id | int | 装扮对应的id | 收藏集均为0,需要在properties获取 | +| name | str | 装扮/收藏集名称 | | +| group_id | int | ?分类的id | | +| group_name | str | ?分类的名称 | | +| part_id | int | 类型id | 装扮为6 收藏集为0 | +| state | str | 当前状态 | 默认为“active” | +| properties | obj | 见下方 | | +| current_activity | obj | 见下方 | | +| next_activity | int | ?下次活动的时间 | | +| current_sources | int | ?活动开始时间 | | +| finish_sources | int | ?活动结束时间 | | +| sale_left_time | int | ?销售剩余时间 | | +| sale_time_end | int | ?销售结束时间 | | +| sale_surplus | int | 未知 | | +| sale_count_desc | str | 销售量显示文本 | | +| total_count_desc | str | 总量显示文本 | | +| tag | str | 当前状态标签 | | +| jump_link | str | 跳转链接 | | +| sales_mode | int | ?销售状态 | | + +`list` 数组中的对象中的 `properties` 对象: + +共有字段: + +| 字段 | 类型 | 内容 | 备注| +|-|---|--|--| +| image_cover | str | 图片封面 | | +| sale_bp_forever_raw | str | 价格 | 以0.01B币为单位| +| type | str | 类型 | 收藏集为dlc_act, 装扮为ip| + +装扮特有: + +| 字段 | 类型 | 内容 | 备注| +| - | - | ---- | ----- | +| desc | str | 介绍文本 | 仅装扮| +| fan_desc | str | 装扮名称 | 仅装扮| +| fan_item_ids | str | 未知 | 仅装扮| +| fan_mid | str | 该up的uid | 仅装扮| +| fan_no_color | str | 十六进制颜色 | 仅装扮| +| fan_recommend_desc | str | 装备说明 | 仅装扮| +| fan_recommend_jump_type | str | 跳转类型 | 仅装扮| +| fan_recommend_jump_value | str | 跳转值 | 仅装扮| +| fan_share_image | str | 分享时的背景图 | 仅装扮| +| gray_rule | str | 未知 | 仅装扮| +| gray_rule_type | str | 未知 | 仅装扮| +| image_cover_color | str | ?图片封面纯色背景 | 仅装扮| +| is_hide | str | 是否隐藏 | 仅装扮| +| item_id_card | str | 装扮背景卡片id | 仅装扮| +| item_id_emoji | str | 装扮表情包id | 仅装扮| +| item_id_thumbup | str | 装扮点赞动画id | 仅装扮| +| open_platform_vip_discount | str | 是否有大会员减免 | 仅装扮| +| owner_uid | str | UID | 默认为虚拟主播衍生品小货架, 仅装扮| +| rank_investor_show | str | 未知 | 仅装扮| +| realname_auth | str | ?是否需要实名认证 | 仅装扮| +| sale_bp_pm_raw | str | 该装扮基础套餐价格 | 以0.01B币为单位, 仅装扮| +| sale_buy_num_limit | str | 购买限额 | 仅装扮| +| sale_quantity | str | 该装扮粉丝专属套餐限额 | 仅装扮| +| sale_quantity_limit | str | 该装扮粉丝专属套餐是否限额 | 仅装扮| +| sale_region_ip_limit | str | 该装扮限制购买地区 | 仅装扮| +| sale_reserve_switch | str | 未知 | 仅装扮| +| sale_time_begin | str | 开始售卖时的时间戳 | 仅装扮| +| sale_type | str | 售卖类型 | 默认为pay, 仅装扮| +| suit_card_type | str | 仅装扮 | | + +收藏集特有: + +| 字段 | 类型 | 内容 | 备注 | +| - | ---- | - | --------- | +| book_amount | str | 购买总数 | 仅收藏集 | +| dlc_act_id | str | 收藏集活动id | 仅收藏集 | +| dlc_act_status | str | 收藏集活动状态 | 仅收藏集 | +| dlc_is_free | str | 收藏集抽奖是否免费 | 仅收藏集 | +| dlc_lottery_id | str | 收藏集抽奖id | 仅收藏集 | +| dlc_lottery_sale_quantity | str | 购买总数 | 仅收藏集 | +| dlc_lottery_type | str | ?抽奖类型 | 仅收藏集 | +| dlc_sale_end_time | str | 收藏集抽奖结束时间 | 仅收藏集 | +| dlc_sale_mode | str | 未知 | 仅收藏集 | +| dlc_sale_start_time | str | 收藏集抽奖开始时间 | 仅收藏集 | +| dlc_surplus_stock | str | 未知 | 仅收藏集 | + +`list` 数组中的对象中的 `current_activity` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| - | --- | --- | - | +| type | str | 当前永久价格活动类型 | 装扮一般是open_platform_vip_discount, 收藏集一般是first_draw_discount | +| time_limit | bool | 是否存在时间限制 | | +| time_left | int | 剩余时间 | | +| tag | str | 显示标签 | | +| price_bp_forever | int | 永久价格 | 以0.01B币为单位 | +| price_bp_month | int | 一个月的价格 | 以0.01B币为单位 | +| type_month | str | 当前一个月的价格活动类型 | 仅装扮 | +| tag_month | str | 显示标签 | 仅装扮 | +| time_limit_month | bool | 是否存在时间限制 | 仅装扮 | +| time_left_month | int | 剩余时间 | 仅装扮 | + +**示例:** + +搜索关键词为 `2233`: + +```shell +curl -G 'https://api.bilibili.com/x/garb/v2/mall/home/search' \ +--data-urlencode 'key_word=2233' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "item_id": 0, + "name": "2024拜年纪-2233拜年画册", + "group_id": 70, + "group_name": "2024拜年纪-2233拜年画册", + "part_id": 0, + "state": "active", + "properties": { + "book_amount": "1395313", + "dlc_act_id": "279", + "dlc_act_status": "2", + "dlc_is_free": "0", + "dlc_lottery_id": "256", + "dlc_lottery_sale_quantity": "313028", + "dlc_lottery_type": "1", + "dlc_sale_end_time": "2114406245", + "dlc_sale_mode": "1", + "dlc_sale_start_time": "1707458400", + "dlc_surplus_stock": "0", + "image_cover": "http://i0.hdslb.com/bfs/archive/f96a8cf6866ccef8f54de4773acf0cb07b915ac6.png", + "sale_bp_forever_raw": "990", + "type": "dlc_act" + }, + "current_activity": null, + "next_activity": { + "type": "first_draw_discount", + "time_limit": false, + "time_left": -1728418723, + "tag": "大会员首抽", + "price_bp_month": 490, + "price_bp_forever": 490, + "type_month": "", + "tag_month": "", + "time_limit_month": false, + "time_left_month": 0 + }, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -1728418723, + "sale_time_end": -1728418723, + "sale_surplus": 0, + "sale_count_desc": "31万+", + "total_count_desc": "已售31万+份", + "tag": "", + "jump_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live\u0026act_id=279\u0026hybrid_set_header=2\u0026lottery_id=256", + "sales_mode": 0 + }, + { + "item_id": 0, + "name": "2024 BML\u0026BW 2233收藏集-2233福利卡池", + "group_id": 70, + "group_name": "2024 BML\u0026BW 2233收藏集-2233福利卡池", + "part_id": 0, + "state": "active", + "properties": { + "book_amount": "4376", + "dlc_act_id": "102962", + "dlc_act_status": "2", + "dlc_is_free": "1", + "dlc_lottery_id": "102966", + "dlc_lottery_sale_quantity": "2677", + "dlc_lottery_type": "2", + "dlc_sale_end_time": "1729828800", + "dlc_sale_mode": "2", + "dlc_sale_start_time": "1721876400", + "dlc_surplus_stock": "0", + "image_cover": "https://i0.hdslb.com/bfs/garb/4a374316b1e9a07cffeccbdeff585c472dcdcc26.png", + "sale_bp_forever_raw": "0", + "type": "dlc_act" + }, + "current_activity": null, + "next_activity": null, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -1728418723, + "sale_time_end": -1728418723, + "sale_surplus": 0, + "sale_count_desc": "2千+", + "total_count_desc": "已发放2千+份", + "tag": "限时DLC", + "jump_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live\u0026act_id=102962\u0026hybrid_set_header=2\u0026lottery_id=102966", + "sales_mode": 0 + }, + { + "item_id": 0, + "name": "2233·幻境序曲-长夜", + "group_id": 70, + "group_name": "2233·幻境序曲-长夜", + "part_id": 0, + "state": "active", + "properties": { + "book_amount": "228065", + "dlc_act_id": "102161", + "dlc_act_status": "2", + "dlc_is_free": "0", + "dlc_lottery_id": "103087", + "dlc_lottery_sale_quantity": "71200", + "dlc_lottery_type": "2", + "dlc_sale_end_time": "2114406245", + "dlc_sale_mode": "1", + "dlc_sale_start_time": "1722139200", + "dlc_surplus_stock": "0", + "image_cover": "https://i0.hdslb.com/bfs/garb/f7e4f434ba6b93434b9e60df3c57a07552af4ca1.png", + "sale_bp_forever_raw": "990", + "type": "dlc_act" + }, + "current_activity": null, + "next_activity": { + "type": "first_draw_discount", + "time_limit": false, + "time_left": -1728418723, + "tag": "大会员首抽", + "price_bp_month": 490, + "price_bp_forever": 490, + "type_month": "", + "tag_month": "", + "time_limit_month": false, + "time_left_month": 0 + }, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -1728418723, + "sale_time_end": -1728418723, + "sale_surplus": 0, + "sale_count_desc": "7万+", + "total_count_desc": "已售7万+份", + "tag": "DLC池", + "jump_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live\u0026act_id=102161\u0026hybrid_set_header=2\u0026lottery_id=103087", + "sales_mode": 0 + }, + { + "item_id": 0, + "name": "2233·群星闪耀时-双子座", + "group_id": 70, + "group_name": "2233·群星闪耀时-双子座", + "part_id": 0, + "state": "active", + "properties": { + "book_amount": "1164544", + "dlc_act_id": "113", + "dlc_act_status": "2", + "dlc_is_free": "0", + "dlc_lottery_id": "16", + "dlc_lottery_sale_quantity": "572712", + "dlc_lottery_type": "1", + "dlc_sale_end_time": "2114406245", + "dlc_sale_mode": "1", + "dlc_sale_start_time": "1686196800", + "dlc_surplus_stock": "0", + "image_cover": "http://i0.hdslb.com/bfs/archive/ed35d12a3dce7764d6cb5b02cb4a459373472522.jpg", + "sale_bp_forever_raw": "990", + "type": "dlc_act" + }, + "current_activity": null, + "next_activity": { + "type": "first_draw_discount", + "time_limit": false, + "time_left": -1728418723, + "tag": "大会员首抽", + "price_bp_month": 90, + "price_bp_forever": 90, + "type_month": "", + "tag_month": "", + "time_limit_month": false, + "time_left_month": 0 + }, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -1728418723, + "sale_time_end": -1728418723, + "sale_surplus": 0, + "sale_count_desc": "57万+", + "total_count_desc": "已售57万+份", + "tag": "", + "jump_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live\u0026act_id=113\u0026hybrid_set_header=2\u0026lottery_id=16", + "sales_mode": 0 + }, + { + "item_id": 39389, + "name": "2233人生百戏-花木兰", + "group_id": 70, + "group_name": "2233人生百戏-花木兰", + "part_id": 6, + "state": "active", + "properties": { + "desc": "为从军设妙计女扮男装,涉千山越万水亲赴戎机。2233人生百戏·花木兰装扮上线啦!本套装包括动态卡片、点赞动效和表情包,永久购买还能成为认证粉丝,领取粉丝专属装扮!", + "fan_desc": "人生百戏-花木兰", + "fan_id": "人生百戏-花木兰", + "fan_item_ids": "39335,39384,39353,39354", + "fan_mid": "35365327", + "fan_no_color": "#eb3d3e", + "fan_recommend_desc": "为从军设妙计女扮男装,涉千山越万水亲赴戎机。", + "fan_recommend_jump_type": "url", + "fan_recommend_jump_value": "https://space.bilibili.com/35365327?spm_id_from=333.337.0.0", + "fan_share_image": "https://i0.hdslb.com/bfs/garb/item/5ddd3f72ef2a938e9125851f488068012b841ad4.jpg", + "gray_rule": "true", + "gray_rule_type": "all", + "image_cover": "https://i0.hdslb.com/bfs/garb/item/e21ec12047bcd93e6afb8e52a68eb9835cd54a23.jpg", + "image_cover_color": "#d8b796", + "is_hide": "false", + "item_id_card": "39334", + "item_id_emoji": "39352", + "item_id_thumbup": "39336", + "open_platform_vip_discount": "true", + "owner_uid": "647193094", + "rank_investor_show": "false", + "realname_auth": "false", + "sale_bp_forever_raw": "5000", + "sale_bp_pm_raw": "800", + "sale_buy_num_limit": "100", + "sale_quantity": "20000", + "sale_quantity_limit": "true", + "sale_region_ip_limit": "全球", + "sale_reserve_switch": "false", + "sale_time_begin": "1666868400", + "sale_type": "pay", + "suit_card_type": "big_img", + "type": "ip" + }, + "current_activity": null, + "next_activity": { + "type": "open_platform_vip_discount", + "time_limit": true, + "time_left": 417469277, + "tag": "大会员平台折扣", + "price_bp_month": 640, + "price_bp_forever": 4000, + "type_month": "open_platform_vip_discount", + "tag_month": "大会员平台折扣", + "time_limit_month": true, + "time_left_month": 417469277 + }, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -61550323, + "sale_time_end": -1728418723, + "sale_surplus": 8650, + "sale_count_desc": "1万+", + "total_count_desc": "已售1万+份", + "tag": "", + "jump_link": "https://www.bilibili.com/h5/mall/suit/detail?navhide=1\u0026id=39389", + "sales_mode": 0 + }, + { + "item_id": 4259, + "name": "2233白色情人节", + "group_id": 70, + "group_name": "2233白色情人节", + "part_id": 6, + "state": "active", + "properties": { + "desc": "shot你的心——无论是谁都拥有爱的权利,快换上白色情人节专属装扮来遇见心里的那个ta吧!本套装包括头像挂件、动态卡片、点赞动效和表情包,永久购买还能成为认证粉丝,领取粉丝专属装扮!", + "fan_desc": "白色情人节", + "fan_id": "2233白色情人节", + "fan_item_ids": "4257,4230,4256,4255,4253,4254", + "fan_mid": "174501086", + "fan_no_color": "#f85574", + "fan_recommend_desc": "平淡日常中迎来浪漫的节日,象征爱情的丘比特们悄悄来到少女们身边,用爱之箭觉醒了懵懂悸动的心。新鲜的玫瑰,闪耀光泽的草莓,白色情人节这天为你准备不一样的惊喜。", + "fan_recommend_jump_type": "url", + "fan_recommend_jump_value": "https://b23.tv/54WVWS", + "fan_share_image": "https://i0.hdslb.com/bfs/garb/item/30e3f1b234dd33a2a5446dd7d05b31835ac74d4b.jpg", + "gray_rule": "true", + "gray_rule_type": "all", + "image_cover": "https://i0.hdslb.com/bfs/garb/item/a8d60a7d4f1f5a5de667b307736f701cb39c0741.jpg", + "image_cover_color": "#a3a8ec", + "image_cover_long": "https://i0.hdslb.com/bfs/garb/item/5ac3bb024d42ff0f26de07ce974351d62587c6ea.jpg", + "image_desc": "https://i0.hdslb.com/bfs/garb/item/cfe753a010d124a95fb311c372a5be69d82c8e13.jpg", + "is_hide": "false", + "item_id_card": "4231", + "item_id_emoji": "4252", + "item_id_pendant": "4229", + "item_id_thumbup": "4232", + "open_platform_vip_discount": "true", + "owner_uid": "647193094", + "rank_investor_show": "true", + "realname_auth": "false", + "sale_bp_forever_raw": "5900", + "sale_bp_pm_raw": "800", + "sale_buy_num_limit": "100", + "sale_quantity": "52000", + "sale_quantity_limit": "true", + "sale_region_ip_limit": "全球", + "sale_reserve_switch": "false", + "sale_time_begin": "1615694400", + "sale_type": "pay", + "suit_card_type": "big_img", + "type": "ip" + }, + "current_activity": null, + "next_activity": { + "type": "open_platform_vip_discount", + "time_limit": true, + "time_left": 417469277, + "tag": "大会员平台折扣", + "price_bp_month": 640, + "price_bp_forever": 4720, + "type_month": "open_platform_vip_discount", + "tag_month": "大会员平台折扣", + "time_limit_month": true, + "time_left_month": 417469277 + }, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -112724323, + "sale_time_end": -1728418723, + "sale_surplus": 0, + "sale_count_desc": "5万+", + "total_count_desc": "已售5万+份", + "tag": "粉丝套装已售罄", + "jump_link": "https://www.bilibili.com/h5/mall/suit/detail?navhide=1\u0026id=4259", + "sales_mode": 0 + }, + { + "item_id": 0, + "name": "2233·少女日记-蔚蓝幻想曲", + "group_id": 70, + "group_name": "2233·少女日记-蔚蓝幻想曲", + "part_id": 0, + "state": "active", + "properties": { + "book_amount": "100310", + "dlc_act_id": "103244", + "dlc_act_status": "2", + "dlc_is_free": "0", + "dlc_lottery_id": "103885", + "dlc_lottery_sale_quantity": "16563", + "dlc_lottery_type": "2", + "dlc_sale_end_time": "2114406245", + "dlc_sale_mode": "1", + "dlc_sale_start_time": "1727236800", + "dlc_surplus_stock": "0", + "image_cover": "http://i0.hdslb.com/bfs/archive/a04b3e9ef354493a0890a9197412f1c77e01ba0f.jpg", + "sale_bp_forever_raw": "990", + "type": "dlc_act" + }, + "current_activity": null, + "next_activity": { + "type": "first_draw_discount", + "time_limit": false, + "time_left": -1728418723, + "tag": "大会员首抽", + "price_bp_month": 490, + "price_bp_forever": 490, + "type_month": "", + "tag_month": "", + "time_limit_month": false, + "time_left_month": 0 + }, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -1728418723, + "sale_time_end": -1728418723, + "sale_surplus": 0, + "sale_count_desc": "1万+", + "total_count_desc": "已售1万+份", + "tag": "DLC池", + "jump_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live\u0026act_id=103244\u0026hybrid_set_header=2\u0026lottery_id=103885", + "sales_mode": 0 + }, + { + "item_id": 0, + "name": "2233·少女日记-十四岁生日", + "group_id": 70, + "group_name": "2233·少女日记-十四岁生日", + "part_id": 0, + "state": "active", + "properties": { + "book_amount": "100310", + "dlc_act_id": "103244", + "dlc_act_status": "2", + "dlc_is_free": "0", + "dlc_lottery_id": "103247", + "dlc_lottery_sale_quantity": "83747", + "dlc_lottery_type": "1", + "dlc_sale_end_time": "2114406245", + "dlc_sale_mode": "1", + "dlc_sale_start_time": "1723780800", + "dlc_surplus_stock": "0", + "image_cover": "https://i0.hdslb.com/bfs/garb/9c338eb4841cad917665140cc08c7d14b5c7e0bf.png", + "sale_bp_forever_raw": "990", + "type": "dlc_act" + }, + "current_activity": null, + "next_activity": { + "type": "first_draw_discount", + "time_limit": false, + "time_left": -1728418723, + "tag": "大会员首抽", + "price_bp_month": 490, + "price_bp_forever": 490, + "type_month": "", + "tag_month": "", + "time_limit_month": false, + "time_left_month": 0 + }, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -1728418723, + "sale_time_end": -1728418723, + "sale_surplus": 0, + "sale_count_desc": "8万+", + "total_count_desc": "已售8万+份", + "tag": "", + "jump_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live\u0026act_id=103244\u0026hybrid_set_header=2\u0026lottery_id=103247", + "sales_mode": 0 + }, + { + "item_id": 0, + "name": "2024 BML\u0026BW 2233收藏集-BML\u0026BW2024", + "group_id": 70, + "group_name": "2024 BML\u0026BW 2233收藏集-BML\u0026BW2024", + "part_id": 0, + "state": "active", + "properties": { + "book_amount": "4376", + "dlc_act_id": "102962", + "dlc_act_status": "2", + "dlc_is_free": "0", + "dlc_lottery_id": "102963", + "dlc_lottery_sale_quantity": "1699", + "dlc_lottery_type": "1", + "dlc_sale_end_time": "2114406245", + "dlc_sale_mode": "1", + "dlc_sale_start_time": "1721876400", + "dlc_surplus_stock": "0", + "image_cover": "https://i0.hdslb.com/bfs/garb/6c2d68faf143c33b484b110e2221ab15a0a1f85c.png", + "sale_bp_forever_raw": "990", + "type": "dlc_act" + }, + "current_activity": null, + "next_activity": { + "type": "first_draw_discount", + "time_limit": false, + "time_left": -1728418723, + "tag": "大会员首抽", + "price_bp_month": 490, + "price_bp_forever": 490, + "type_month": "", + "tag_month": "", + "time_limit_month": false, + "time_left_month": 0 + }, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -1728418723, + "sale_time_end": -1728418723, + "sale_surplus": 0, + "sale_count_desc": "1千+", + "total_count_desc": "已售1千+份", + "tag": "", + "jump_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live\u0026act_id=102962\u0026hybrid_set_header=2\u0026lottery_id=102963", + "sales_mode": 0 + } + ], + "pn": 1, + "ps": 20, + "total": 187 + } +} +``` + +</details> + +## 收藏集信息API + +> https://api.bilibili.com/x/vas/dlc_act/lottery_home_detail + +*请求方式: GET* + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | ---- | ---- | ---- | ---- | +| act_id | int | 收藏集活动id | 必要 | | +| lottery_id | int | 收藏集抽奖id|不必要| 但缺了不返回数据 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 返回数据 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +|-|-|-|-| +| lottery_id | int | 收藏集抽奖id | | +| name | str | 收藏集抽奖名称 | | +| item_list | array | 可抽出的物品列表 | | +| collect_list | obj | 见下方 | | +| button_bubble | null | 未知 | | +| guide_info | null | 未知 | | +| is_booked | int | 未知 | | +| total_book_cnt | int | 未知 | | +| is_fission | int | 未知 | | +| physical_exchange | int | 未知 | | + +`data` 中的 `item_list` 数组中的对象: + +|字段 | 类型 | 内容 | 备注| +|-|-|-|-| +|item_type | int | 物品类型 | 目前只拿到个1, 其他值未知| +|card_info | obj | 见下方 | | + +`item_list` 数组中的对象中的 `card_info` 对象: + +|字段 | 类型 | 内容 | 备注 | +|-|-|-|-| +|card_type_id | int | 该卡片id | | +|card_name | str | 该卡片名称 | | +|card_img | str | 该卡片图片 | 无水印| +|card_type | int | int | 未知| +|video_list | array | 该卡片动态视频 | 无水印| +|is_physical_orientation | int | 该卡片旋转方向 | | +|card_scarcity | int | 该卡片稀有度 | | +|is_mute | int | 该卡片是否静音 | | +|width | int | 该卡片像素宽度 | | +|height | int | 该卡片像素高度 | | +|card_ext_text | str | ?该卡片文件名字符串 | | +|card_img_download | str | 该卡片图片 | 有水印| +|video_list_download | array | 该卡片动态视频 | 有水印| +|subtitles_url | 未知 | | | +|play | null | 未知 | | +|tag | null | 未知 | | +|card_sub_type | int | 未知 | | +|is_new_tag | int | 未知 | | +|is_up_tag | int | 未知 | | +|is_limited_card | int | 未知 | | +|stock_info | null | 未知 | | + +`data` 中的 `collect_list` 对象: + +| 字段 | 类型 | 内容 | 备注| +|-|-|-|-| +| collect_infos | array | 见下方 | | +| collect_chain | null | 未知 | | + +`collect_list` 中的 `collect_infos` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|-|-|-|-| +| collect_id | int | 收集品id | | +| start_time | int | 开始时间 | | +| end_time | int | 结束时间 | | +| redeem_text | str | 兑换条件 | | +| redeem_item_type | int | 兑换物类型 | | +| redeem_item_id | str | 兑换物id | | +| redeem_item_name | str | 兑换物名称 | | +| redeem_item_image | str | 兑换物预览图片 | | +| owned_item_amount | int | 拥有的数量 | | +| require_item_amount | int | 需要的数量 | | +| has_redeemed_cnt | int | 兑换次数 | | +| effective_forever | int | 是否永久有效 | | +| redeem_item_image_download | str | 未知 | | +| card_item | obj | 见下方 | 有时为 null | +| jump_url | str | ?跳转链接 | | +| redeem_cond_type | str | 当前兑换状态 | | +| remain_stock | int | 当前库存 | | +| total_stock | int | 总库存 | | +| lottery_id | int | 抽奖id | | +| reward_tag | str | 奖励显示标签 | | +| redeem_detail_image | str | 兑换详情图片 | | +| redeem_detail_videos | null | 未知 | | +| sort | int | 排序 | | +| redeem_items_optional | null | 未知 | | +| unlock_condition | obj | 见下方 | | + +`collect_infos` 数组中的对象中的 `card_item` 对象: + +| 字段 | 类型 | 内容 | 备注| +|-|-|-|-| +| card_type_info | null | | | +| card_asset_info | null | | | +| play | null | | | +| tag | null | | | + +`collect_infos` 数组中的对象中的 `unlock_condition` 对象: + +|字段 | 类型 | 内容 | 备注| +|-|-|-|-| +|unlocked | bool | 是否解锁 | | +|lock_type | int | 解锁类型 | | +|expire_at | int | 过期与 | | +|unlocked_at | int | 解锁于 | | +|unlock_threshold | int | ?解锁起点 | | +|current_threshold | int | ?当前起点 | | + +**示例:** + +```shell +curl -G --url 'https://api.bilibili.com/x/vas/dlc_act/lottery_home_detail' \ +--url-query 'act_id=111' \ +--url-query 'lottery_id=15' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "lottery_id": 15, + "name": "夏日萌菜", + "item_list": [ + { + "item_type": 1, + "card_info": { + "card_type_id": 700903, + "card_name": "水中嬉戏·隐藏", + "card_img": "https://i0.hdslb.com/bfs/baselabs/d41acfc3bfcc9032a9759fbd9e64147a6d9a24b0.png", + "card_type": 2, + "video_list": [ + "https://upos-hz-mirrorakam.akamaized.net/panguxcodeboss/2b/y2/_000008vnv2ddoooah248hqoyz2gy22b-1-152111110023.mp4?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfq9rVEuxTEnE8L5F6VnEsSTx0vkX8fqJeYTj_lta53NCM=&uipk=5&nbs=1&deadline=1723459855&gen=playurlv2&os=akam&oi=1823807565&trid=400d9529a562468c8312c1f4c4beb2e3B&mid=0&platform=html5&og=cos&upsig=d22ca6102adb9ffe257f702047be6ef2&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform,og&hdnts=exp=1723459855~hmac=753ff946c9e4b3813eb72c744ed3a399ba9a225fe4767a7a03835890fcbe4b8a&bvc=vod&nettype=0&orderid=0,1&logo=00000000&f=B_0_0" + ], + "is_physical_orientation": 0, + "card_scarcity": 40, + "is_mute": 0, + "width": 1242, + "height": 1862, + "card_ext_text": "", + "card_img_download": "https://i0.hdslb.com/bfs/garb/d38c42b6f1151298888da5902bca5a41e14f67e1.png", + "video_list_download": [ + "https://upos-hz-mirrorakam.akamaized.net/panguxcodeboss/digital_watermark/ib/30/_00003d7cuie74gr9z2322d7js5b30ib-teaser.mp4?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfq9rVEuxTEnE8L5F6VnEsSTx0vkX8fqJeYTj_lta53NCM=&uipk=5&nbs=1&deadline=1723459855&gen=playurlv2&os=akam&oi=1823807565&trid=400d9529a562468c8312c1f4c4beb2e3B&mid=0&platform=html5&og=hw&upsig=24512302cfa3b1f762f3ad08a0a2f5fe&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform,og&hdnts=exp=1723459855~hmac=5dc3cdfca31fca94c29a2ec945589ff319e97c3291dec2685184ec4083616cc2&bvc=vod&nettype=0&orderid=0,1&logo=00000000&f=B_0_0" + ], + "subtitles_url": "", + "play": null, + "tag": null, + "card_sub_type": 0, + "is_new_tag": 0, + "is_up_tag": 0, + "is_limited_card": 0, + "stock_info": null + } + }, + { + "item_type": 1, + "card_info": { + "card_type_id": 700902, + "card_name": "轻纱花语·隐藏", + "card_img": "https://i0.hdslb.com/bfs/baselabs/e4721d06a5c435be216b5011f0604c9e07d5e4af.png", + "card_type": 2, + "video_list": [ + "https://upos-hz-mirrorakam.akamaized.net/panguxcodeboss/jb/4u/_00001f04wekkvpmr92osvwpej1e4ujb-1-152111110023.mp4?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfq9rVEuxTEnE8L5F6VnEsSTx0vkX8fqJeYTj_lta53NCM=&uipk=5&nbs=1&deadline=1723459855&gen=playurlv2&os=akam&oi=1823807565&trid=400d9529a562468c8312c1f4c4beb2e3B&mid=0&platform=html5&og=cos&upsig=ad574839c71e5327783acf248b552b3d&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform,og&hdnts=exp=1723459855~hmac=49276ec1afce1a8f571e257fb6d2ab7488f623aa50c2c3b7252258be72315c5e&bvc=vod&nettype=0&orderid=0,1&logo=00000000&f=B_0_0" + ], + "is_physical_orientation": 0, + "card_scarcity": 30, + "is_mute": 0, + "width": 1242, + "height": 1862, + "card_ext_text": "", + "card_img_download": "https://i0.hdslb.com/bfs/garb/0e49e7c8108a98944a96bfa594cf7f74c72398cf.png", + "video_list_download": [ + "https://upos-hz-mirrorakam.akamaized.net/panguxcodeboss/digital_watermark/nb/58/_000007ovzgblf574s1ywvm7inwx58nb-teaser.mp4?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfq9rVEuxTEnE8L5F6VnEsSTx0vkX8fqJeYTj_lta53NCM=&uipk=5&nbs=1&deadline=1723459855&gen=playurlv2&os=akam&oi=1823807565&trid=400d9529a562468c8312c1f4c4beb2e3B&mid=0&platform=html5&og=cos&upsig=ec9de21147240e94494d736f277dfb64&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform,og&hdnts=exp=1723459855~hmac=2370473349a25fae0ea023f65f1e09c70b45d086831eef5f4727b8443acdf9f5&bvc=vod&nettype=0&orderid=0,1&logo=00000000&f=B_0_0" + ], + "subtitles_url": "", + "play": null, + "tag": null, + "card_sub_type": 0, + "is_new_tag": 0, + "is_up_tag": 0, + "is_limited_card": 0, + "stock_info": null + } + }, + { + "item_type": 1, + "card_info": { + "card_type_id": 700904, + "card_name": "甜心女仆", + "card_img": "https://i0.hdslb.com/bfs/baselabs/e1f9c56a8f49910d07852f2bd648fee910f36ff6.png", + "card_type": 2, + "video_list": [ + "https://upos-hz-mirrorakam.akamaized.net/panguxcodeboss/gb/j6/_000015vmteklku8oj1ypmp1yjijj6gb-1-152111110023.mp4?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfq9rVEuxTEnE8L5F6VnEsSTx0vkX8fqJeYTj_lta53NCM=&uipk=5&nbs=1&deadline=1723459855&gen=playurlv2&os=akam&oi=1823807565&trid=400d9529a562468c8312c1f4c4beb2e3B&mid=0&platform=html5&og=cos&upsig=c7412fe7b155deecbfea939f7c3d1b21&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform,og&hdnts=exp=1723459855~hmac=8989673c367aa0ffbe747cdc66129a6d1698f1c2b60ace24861ad62127cdd6da&bvc=vod&nettype=0&orderid=0,1&logo=00000000&f=B_0_0" + ], + "is_physical_orientation": 0, + "card_scarcity": 20, + "is_mute": 0, + "width": 1242, + "height": 1862, + "card_ext_text": "", + "card_img_download": "https://i0.hdslb.com/bfs/garb/e6c69329d843603166fac8d41682c3489fd137d4.png", + "video_list_download": [ + "https://upos-hz-mirrorakam.akamaized.net/panguxcodeboss/digital_watermark/zb/eq/_000018oi0e68wv4id2vkrk9ovpteqzb-teaser.mp4?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfq9rVEuxTEnE8L5F6VnEsSTx0vkX8fqJeYTj_lta53NCM=&uipk=5&nbs=1&deadline=1723459855&gen=playurlv2&os=akam&oi=1823807565&trid=400d9529a562468c8312c1f4c4beb2e3B&mid=0&platform=html5&og=hw&upsig=f972e8cd996d058deb4e0ffb1d57671e&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform,og&hdnts=exp=1723459855~hmac=99054c626717b4ba61c01bbb0fe59f67feac394b89e19e4bbf95290d3a425f94&bvc=vod&nettype=0&orderid=0,1&logo=00000000&f=B_0_0" + ], + "subtitles_url": "", + "play": null, + "tag": null, + "card_sub_type": 0, + "is_new_tag": 0, + "is_up_tag": 0, + "is_limited_card": 0, + "stock_info": null + } + }, + { + "item_type": 1, + "card_info": { + "card_type_id": 700901, + "card_name": "约会憧憬", + "card_img": "https://i0.hdslb.com/bfs/baselabs/924ef9a71bf39010935b4a43845bec13c8a2022c.png", + "card_type": 1, + "video_list": null, + "is_physical_orientation": 0, + "card_scarcity": 10, + "is_mute": 0, + "width": 1242, + "height": 1863, + "card_ext_text": "", + "card_img_download": "https://i0.hdslb.com/bfs/garb/40a9ff949ca7a50dbce146ad28fbb567c2583261.png", + "video_list_download": null, + "subtitles_url": "", + "play": null, + "tag": null, + "card_sub_type": 0, + "is_new_tag": 0, + "is_up_tag": 0, + "is_limited_card": 0, + "stock_info": null + } + }, + { + "item_type": 1, + "card_info": { + "card_type_id": 700900, + "card_name": "夏日小憩", + "card_img": "https://i0.hdslb.com/bfs/baselabs/0eddbfc70200f16bef06acc88ef132eb25ede52d.png", + "card_type": 1, + "video_list": null, + "is_physical_orientation": 0, + "card_scarcity": 10, + "is_mute": 0, + "width": 1242, + "height": 1863, + "card_ext_text": "", + "card_img_download": "https://i0.hdslb.com/bfs/garb/61e26e17705e06ecdfdb9ff97befb19c702cf81e.png", + "video_list_download": null, + "subtitles_url": "", + "play": null, + "tag": null, + "card_sub_type": 0, + "is_new_tag": 0, + "is_up_tag": 0, + "is_limited_card": 0, + "stock_info": null + } + }, + { + "item_type": 1, + "card_info": { + "card_type_id": 700899, + "card_name": "微风校园", + "card_img": "https://i0.hdslb.com/bfs/baselabs/bbeaf7993566684e328e74d8ef7c47e6242869a2.png", + "card_type": 1, + "video_list": null, + "is_physical_orientation": 0, + "card_scarcity": 10, + "is_mute": 0, + "width": 1242, + "height": 1863, + "card_ext_text": "", + "card_img_download": "https://i0.hdslb.com/bfs/garb/8ac61045334699d621363ccac87153a7128ef0c3.png", + "video_list_download": null, + "subtitles_url": "", + "play": null, + "tag": null, + "card_sub_type": 0, + "is_new_tag": 0, + "is_up_tag": 0, + "is_limited_card": 0, + "stock_info": null + } + }, + { + "item_type": 1, + "card_info": { + "card_type_id": 700898, + "card_name": "萌宠幻想", + "card_img": "https://i0.hdslb.com/bfs/baselabs/f93f200ec862b4520b30e8f03219fbaca91a2089.png", + "card_type": 1, + "video_list": null, + "is_physical_orientation": 0, + "card_scarcity": 10, + "is_mute": 0, + "width": 1242, + "height": 1863, + "card_ext_text": "", + "card_img_download": "https://i0.hdslb.com/bfs/garb/93e59f3080f6b8070b0d0621496e4ed6cb20cf8f.png", + "video_list_download": null, + "subtitles_url": "", + "play": null, + "tag": null, + "card_sub_type": 0, + "is_new_tag": 0, + "is_up_tag": 0, + "is_limited_card": 0, + "stock_info": null + } + }, + { + "item_type": 1, + "card_info": { + "card_type_id": 700897, + "card_name": "空中环游", + "card_img": "https://i0.hdslb.com/bfs/baselabs/fc0c020091c0a9fb1778c420bc4f9773a72ea7ba.png", + "card_type": 1, + "video_list": null, + "is_physical_orientation": 0, + "card_scarcity": 10, + "is_mute": 0, + "width": 1242, + "height": 1863, + "card_ext_text": "", + "card_img_download": "https://i0.hdslb.com/bfs/garb/c1c6c9ca84b584bf5f2b0e1ec7d239eb935e4d44.png", + "video_list_download": null, + "subtitles_url": "", + "play": null, + "tag": null, + "card_sub_type": 0, + "is_new_tag": 0, + "is_up_tag": 0, + "is_limited_card": 0, + "stock_info": null + } + } + ], + "collect_list": { + "collect_infos": [ + { + "collect_id": 0, + "start_time": 1685372400, + "end_time": 2114406245, + "redeem_text": "1抽必得勋章,可应用为评论背景&动态卡片", + "redeem_item_type": 1001, + "redeem_item_id": "", + "redeem_item_name": "夏日萌菜勋章", + "redeem_item_image": "http://i0.hdslb.com/bfs/archive/b3d915c6ad88609fb658393585f018459a7e620d.png", + "owned_item_amount": 0, + "require_item_amount": 1, + "has_redeemed_cnt": 0, + "effective_forever": 1, + "redeem_item_image_download": "", + "card_item": null, + "jump_url": "", + "redeem_cond_type": "", + "remain_stock": 0, + "total_stock": -1, + "lottery_id": 0, + "reward_tag": "", + "redeem_detail_image": "", + "redeem_detail_videos": null, + "sort": 0, + "redeem_items_optional": null, + "unlock_condition": { + "unlocked": true, + "lock_type": 0, + "expire_at": 0, + "unlocked_at": 0, + "unlock_threshold": 0, + "current_threshold": 0 + } + }, + { + "collect_id": 172, + "start_time": 1691640000, + "end_time": 2114406245, + "redeem_text": "抽出任意5张不同卡牌,即可领取,单UID仅可领取一次", + "redeem_item_type": 5, + "redeem_item_id": "56658", + "redeem_item_name": "夏日萌菜个性主题", + "redeem_item_image": "https://i0.hdslb.com/bfs/garb/48f755d6d08d96bfebcadee0be4bc34ce42421de.jpg", + "owned_item_amount": 0, + "require_item_amount": 5, + "has_redeemed_cnt": 0, + "effective_forever": 1, + "redeem_item_image_download": "", + "card_item": { + "card_type_info": null, + "play": null, + "tag": null, + "card_asset_info": null + }, + "jump_url": "", + "redeem_cond_type": "scarcity", + "remain_stock": -1, + "total_stock": -1, + "lottery_id": 0, + "reward_tag": "任务奖励限定", + "redeem_detail_image": "https://i0.hdslb.com/bfs/garb/48f755d6d08d96bfebcadee0be4bc34ce42421de.jpg", + "redeem_detail_videos": null, + "sort": 0, + "redeem_items_optional": null, + "unlock_condition": { + "unlocked": true, + "lock_type": 0, + "expire_at": 0, + "unlocked_at": 0, + "unlock_threshold": 0, + "current_threshold": 0 + } + }, + { + "collect_id": 51, + "start_time": 1685372400, + "end_time": 2114406245, + "redeem_text": "抽出任意1张隐藏卡牌,即可领取,单UID仅可领取一次", + "redeem_item_type": 3, + "redeem_item_id": "53199", + "redeem_item_name": "夏日萌菜头像框", + "redeem_item_image": "https://i0.hdslb.com/bfs/garb/item/9fcb99ccfd057c5eac165832d71fb63f07f26097.png", + "owned_item_amount": 0, + "require_item_amount": 1, + "has_redeemed_cnt": 0, + "effective_forever": 1, + "redeem_item_image_download": "", + "card_item": { + "card_type_info": null, + "play": null, + "tag": null, + "card_asset_info": null + }, + "jump_url": "", + "redeem_cond_type": "scarcity", + "remain_stock": -1, + "total_stock": -1, + "lottery_id": 0, + "reward_tag": "任务奖励限定", + "redeem_detail_image": "https://i0.hdslb.com/bfs/garb/item/9fcb99ccfd057c5eac165832d71fb63f07f26097.png", + "redeem_detail_videos": null, + "sort": 0, + "redeem_items_optional": null, + "unlock_condition": { + "unlocked": true, + "lock_type": 0, + "expire_at": 0, + "unlocked_at": 0, + "unlock_threshold": 0, + "current_threshold": 0 + } + }, + { + "collect_id": 50, + "start_time": 1685372400, + "end_time": 2114406245, + "redeem_text": "抽出任意3张不同卡牌,即可领取,单UID仅可领取一次", + "redeem_item_type": 2, + "redeem_item_id": "53178", + "redeem_item_name": "夏日萌菜表情包", + "redeem_item_image": "https://i0.hdslb.com/bfs/garb/462ae9b5735fef4bb9ed87a6d6467a4768b06006.png", + "owned_item_amount": 0, + "require_item_amount": 3, + "has_redeemed_cnt": 0, + "effective_forever": 1, + "redeem_item_image_download": "", + "card_item": { + "card_type_info": null, + "play": null, + "tag": null, + "card_asset_info": null + }, + "jump_url": "", + "redeem_cond_type": "scarcity", + "remain_stock": -1, + "total_stock": -1, + "lottery_id": 0, + "reward_tag": "任务奖励限定", + "redeem_detail_image": "https://i0.hdslb.com/bfs/garb/462ae9b5735fef4bb9ed87a6d6467a4768b06006.png", + "redeem_detail_videos": null, + "sort": 0, + "redeem_items_optional": null, + "unlock_condition": { + "unlocked": true, + "lock_type": 0, + "expire_at": 0, + "unlocked_at": 0, + "unlock_threshold": 0, + "current_threshold": 0 + } + }, + { + "collect_id": 366, + "start_time": 1694768400, + "end_time": 1696953600, + "redeem_text": "抽齐全部8张卡牌领取,直接获得全图鉴进度条标记,10月28日前人工发放头像", + "redeem_item_type": 5, + "redeem_item_id": "59374", + "redeem_item_name": "水中嬉戏·隐藏出框头像", + "redeem_item_image": "https://i0.hdslb.com/bfs/garb/ff981dbdca5c6b539e22596674265ef1cb110c9c.png", + "owned_item_amount": 0, + "require_item_amount": 8, + "has_redeemed_cnt": 0, + "effective_forever": 0, + "redeem_item_image_download": "", + "card_item": { + "card_type_info": null, + "play": null, + "tag": null, + "card_asset_info": null + }, + "jump_url": "", + "redeem_cond_type": "scarcity", + "remain_stock": -1, + "total_stock": -1, + "lottery_id": 0, + "reward_tag": "任务奖励限定", + "redeem_detail_image": "https://i0.hdslb.com/bfs/garb/ff981dbdca5c6b539e22596674265ef1cb110c9c.png", + "redeem_detail_videos": null, + "sort": 0, + "redeem_items_optional": null, + "unlock_condition": { + "unlocked": true, + "lock_type": 0, + "expire_at": 0, + "unlocked_at": 0, + "unlock_threshold": 0, + "current_threshold": 0 + } + } + ], + "collect_chain": null + }, + "button_bubble": null, + "guide_info": null, + "is_booked": 0, + "total_book_cnt": 0, + "is_fission": 0, + "physical_exchange": 0 + } +} +``` + +</details> + +## 主题装扮信息API + +> https://api.bilibili.com/x/garb/v2/mall/suit/detail + +*请求方式: GET* + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|---------|-----|------|----| ---- | +| buvid | str | 设备唯一标识 | 不必要 | | +| csrf | str | 用户csrf | 不必要 | | +| from | str | 来源页面 | 不必要 | | +| from_id | int | 来源页面id | 不必要 | | +| item_id | int | 装扮id | 必要 | | +| part | str | ?分类 | 不必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|-----------------| +| code | num | 返回值 | `0`:成功<br />`-400`:错误 | +| message | str | 错误信息 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|--------|------------| +| item_id | num | 装扮id | | +| name | str | 装扮名称 | | +| group_id | num | 分组id | | +| group_name | str | 分组名称 | | +| part_id | num | 分类id | | +| state | str | 状态 | | +| properties | obj | 装扮具体属性 | | +| current_activity | str | 当前活动 | | +| next_activity | obj | 下一个活动 | | +| current_sources | str | | **作用尚不明确** | +| finish_sources | str | | **作用尚不明确** | +| sale_left_time | num | | **作用尚不明确** | +| sale_time_end | num | | **作用尚不明确** | +| sale_surplus | num | 商品剩余数量 | | +| sale_count_desc | str | 促销销量说明 | | +| total_count_desc | str | 总销量说明 | | +| tag | str | 标签 | | +| jump_link | str | 跳转链接 | | +| sales_mode | num | 促销模式 | | +| suit_items | obj | 装扮具体内容 | | +| fan_user | obj | 装扮来源用户 | | +| unlock_items | obj | 未解锁装扮 | | +| activity_entrance | obj | 活动入口 | | + +`properties` 对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|----------------|-----------------------------| +| desc | str | 说明 | | +| fan_desc | str | 用户说明 | | +| fan_id | str | 装扮id | 获取到的数据,有时候是数字文本,有时候是普通文本 | +| fan_item_ids | str | 装扮id列表 | | +| fan_mid | str | 用户mid | | +| fan_no_color | str | | **为一串颜色16进制字符串,但作用尚不明确** | +| fan_recommend_desc | str | 用户推荐说明 | | +| fan_recommend_jump_type | str | 跳转类型 | | +| fan_recommend_jump_value | str | 跳转的值 | 一般为该装扮所有者的个人空间链接 | +| fan_share_image | str | | | +| gray_rule | str | | **布尔型转换的字符串,作用尚不明确** | +| gray_rule_type | str | | **作用尚不明确** | +| image_cover | str | 图片封面链接 | | +| image_cover_color | str | 图片封面颜色 | | +| is_hide | str | 是否隐藏 | **布尔型转换的字符串,作用尚不明确** | +| item_id_card | str | 动态卡片id | | +| item_id_emoji | str | 表情包id | | +| item_id_thumbup | str | 动态点赞特效id | | +| open_platform_vip_discount | str | 是否开启平台VIP折扣 | | +| owner_uid | str | 装扮所有者的用户uid | | +| rank_investor_show | str | ?显示投资者排名 | **布尔型转换的字符串,作用尚不明确** | +| realname_auth | str | | **布尔型转换的字符串,作用尚不明确** | +| sale_bp_forever_raw | str | | | +| sale_bp_pm_raw | str | | | +| sale_buy_num_limit | str | 促销限制数量 | | +| sale_quantity | str | 促销质量 | 整数型转换的字符串,"10000"可能表示的是这张图的原画 | +| sale_quantity_limit | str | ?是否限制某些质量装扮的销售 | **布尔型转换的字符串,作用尚不明确** | +| sale_region_ip_limit | str | 促销限制地区 | | +| sale_reserve_switch | str | | **布尔型转换的字符串,作用尚不明确** | +| sale_time_begin | str | 促销开始时间的时间戳 | | +| sale_type | str | 促销类型 | | +| suit_card_type | str | 装扮卡片类型 | | +| type | str | 类型 | **作用尚不明确** | + +`suit_items` 对象(可能不全,会继续补充): + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|--------|------------| +| card | array | 动态卡片 | | +| emoji_package | array | 表情包 | | +| card_bg | array | 专属评论装扮 | | +| thumbup | array | 动态点赞特效 | | +| loading | array | 专属加载动画 | | +| play_icon | array | 专属进度条 | | +| skin | array | 专属个性主题 | | +| space_bg | array | 专属空间海报 | | + +`suit_items` 中每个数组的对象: + +**即上文中所列出的 `suit_items` 中的那些数组对象,对于这些数组,<br />它们其中的字段基本都是相同的,不同的地方会在后面继续说明。** + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|---------|----------------------| +| item_id | num | 装扮id | | +| name | str | 装扮名称 | | +| state | str | 状态 | | +| tab_id | num | 分栏id | | +| suit_item_id | num | 所属装扮的id | | +| properties | obj | 装扮具体属性 | **不同点主要集中在这个地方,下文将继续说明** | +| current_activity | str | 当前活动 | | +| next_activity | obj | 下一个活动 | | +| current_sources | str | | **作用尚不明确** | +| finish_sources | str | | **作用尚不明确** | +| sale_left_time | str | | **作用尚不明确** | +| sale_time_end | str | | **作用尚不明确** | +| sale_surplus | str | 商品剩余数量 | | +| items | str | 装扮的具体内容 | | + +关于上述提到的 `properties` 对象中的共有字段: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|----------------------| +| gray_rule | str | | **布尔型转换的字符串,作用尚不明确** | +| gray_rule_type | str | | **作用尚不明确** | +| realname_auth | str | | **布尔型转换的字符串,作用尚不明确** | +| sale_type | str | 促销类型 | | +| image | str | 图片 | | +| image_preview_small | str | 预览图 | | + +`emoji_package` 数组中的对象中 `properties` 对象中的额外字段: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|-------|----------------------| +| addable | str | | **布尔型转换的字符串,作用尚不明确** | +| biz | str | | **作用尚不明确** | +| is_symbol | str | | **布尔型转换的字符串,作用尚不明确** | +| permanent | str | 是否永久 | | +| preview | str | | **布尔型转换的字符串,作用尚不明确** | +| recently_used | str | | **布尔型转换的字符串,作用尚不明确** | +| recommend | str | 是否推荐 | | +| ref_mid | str | | | +| removable | str | 是否可移除 | | +| setting_pannel_not_show | str | | **布尔型转换的字符串,作用尚不明确** | +| size | str | 尺寸 | | +| sortable | str | 排序类型 | | + +`loading` 数组中的对象中 `properties` 对象中的额外字段: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------------|----------------------| +| loading_frame_url | str | 进度条动画的其中一帧 | | +| loading_url | str | 进度条动画 | | + +`play_icon` 数组中的对象中 `properties` 对象中的额外字段: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|-------------|----------------------| +| drag_left_png | str | 进度条向左拖动时的图片 | | +| drag_right_png | str | 进度条向右拖动时的图片 | | +| middle_png | str | 进度条暂停时的图片 | | +| squared_image | str | 效果图 | | +| static_icon_image | str | 静态图标 | | + +`skin` 数组中的对象中 `properties` 对象中的额外字段: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|---------------------|----------------------| +| head_bg | str | 首页顶部图片 | | +| head_myself_mp4_play | str | 个人空间顶部视频动画的播放类型 | | +| head_myself_squared_bg | str | 个人空间顶部图片 | | +| head_tab_bg | str | 首页顶部标签栏背景图 | | +| image_cover | str | 封面图 | | +| package_md5 | str | 装扮图包的md5值 | | +| package_url | str | 装扮图包的压缩包链接 | | +| skin_mode | str | 皮肤模式 | | +| tail_bg | str | 首页底部图片 | | +| tail_color | str | 首页底部颜色 | | +| tail_color_selected | str | 首页底部被选中时的颜色 | | +| tail_icon_ani | str | 首页底部是否播放动画 | | +| tail_icon_ani_mode | str | 首页底部动画的播放类型 | | +| tail_icon_channel | str | 首页底部“动态”按钮图片 | | +| tail_icon_dynamic | str | 首页底部“发布动态”按钮图片 | | +| tail_icon_main | str | 首页底部“首页”按钮图片 | | +| tail_icon_mode | str | 首页底部图标模式 | | +| tail_icon_myself | str | 首页底部“我的”按钮图片 | | +| tail_icon_pub_btn_bg | str | 首页底部“发布动态”按钮图片 | | +| tail_icon_selected_channel | str | 首页底部“动态”按钮被选中时的图片 | | +| tail_icon_selected_dynamic | str | 首页底部“发布动态”按钮被选中时的图片 | | +| tail_icon_selected_main | str | 首页底部“首页”按钮被选中时的图片 | | +| tail_icon_selected_myself | str | 首页底部“我的”按钮被选中时的图片 | | +| tail_icon_selected_pub_btn_bg | str | 首页底部“发布动态”按钮被选中时的图片 | | +| tail_icon_selected_shop | str | 首页底部“会员购”按钮被选中时的图片 | | +| tail_icon_shop | str | 首页底部“会员购”按钮图片 | | + +`space_bg` 数组中的对象中 `properties` 对象中的额外字段: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|-------------|----------------------| +| image1_landscape | str | 第一张空间海报 | | +| image1_portrait | str | 第一张空间海报(纵向) | | + +**如果是第二张图,则是`image2_xxx`,以此类推。** + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/garb/v2/mall/suit/detail' \ + --data-urlencode 'buvid=xxx(非必须)' \ + --data-urlencode 'csrf=xxx(非必须)' \ + --data-urlencode 'item_id=42193' \ + --data-urlencode 'part=suit(非必须)' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code":0, + "message":"0", + "ttl":1, + "data":{ + "item_id":42193, + "name":"装扮小姐姐·梦幻冬季", + "group_id":69, + "group_name":"装扮小姐姐·梦幻冬季", + "part_id":6, + "state":"active", + "properties":{ + "desc":"扮扮糖集合啦!装扮小姐姐邀你共度梦幻冬季~", + "fan_desc":"装扮小姐姐·梦幻冬季", + "fan_id":"装扮小姐姐·梦幻冬季", + "fan_item_ids":"42190,42124,42192,42191,42188,42189", + "fan_mid":"647193094", + "fan_no_color":"#3e52eb", + "fan_recommend_desc":"扮扮糖集合啦!装扮小姐姐邀你共度梦幻冬季~", + "fan_recommend_jump_type":"url", + "fan_recommend_jump_value":"https://space.bilibili.com/647193094?spm_id_from=333.337.0.0", + "fan_share_image":"https://i0.hdslb.com/bfs/garb/item/f9ad456fb74fc58896743eb393664e3c7622de0c.jpg", + "gray_rule":"true", + "gray_rule_type":"all", + "image_cover":"https://i0.hdslb.com/bfs/garb/item/14072c2cb4f82c053d85dc92911da37583a17668.jpg", + "image_cover_color":"#dcf0f9", + "is_hide":"false", + "item_id_card":"42123", + "item_id_emoji":"42157", + "item_id_thumbup":"42125", + "open_platform_vip_discount":"true", + "owner_uid":"647193094", + "rank_investor_show":"false", + "realname_auth":"false", + "sale_bp_forever_raw":"5500", + "sale_bp_pm_raw":"800", + "sale_buy_num_limit":"100", + "sale_quantity":"10000", + "sale_quantity_limit":"true", + "sale_region_ip_limit":"全球", + "sale_reserve_switch":"false", + "sale_time_begin":"1670410800", + "sale_type":"pay", + "suit_card_type":"big_img", + "type":"ip" + }, + "current_activity":null, + "next_activity":{ + "type":"open_platform_vip_discount", + "time_limit":true, + "time_left":410175990, + "tag":"大会员平台折扣", + "price_bp_month":640, + "price_bp_forever":4400, + "type_month":"open_platform_vip_discount", + "tag_month":"大会员平台折扣", + "time_limit_month":true, + "time_left_month":410175990 + }, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-65301210, + "sale_time_end":-1735712010, + "sale_surplus":0, + "sale_count_desc":"1万+", + "total_count_desc":"", + "tag":"粉丝套装已售罄", + "jump_link":"", + "sales_mode":0, + "suit_items":{ + "card":[ + { + "item_id":42124, + "name":"装扮小姐姐梦幻冬季粉丝", + "state":"active", + "tab_id":35, + "suit_item_id":42193, + "properties":{ + "gray_rule":"true", + "gray_rule_type":"all", + "hot":"false", + "image":"https://i0.hdslb.com/bfs/garb/item/3bebd46d5ac6eaa1d6c3f65854b184932fb6230b.png", + "image_preview_small":"https://i0.hdslb.com/bfs/garb/item/611fc0d3401623977f580f592747d721de330fc6.png", + "realname_auth":"false", + "sale_type":"other" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0, + "items":null + }, + { + "item_id":42123, + "name":"装扮小姐姐梦幻冬季", + "state":"active", + "tab_id":35, + "suit_item_id":42193, + "properties":{ + "gray_rule":"true", + "gray_rule_type":"all", + "hot":"false", + "image":"https://i0.hdslb.com/bfs/garb/item/757320776561f6bf881b3c50bd59fc937cea3387.png", + "realname_auth":"false", + "sale_type":"other" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0, + "items":null + } + ], + "card_bg":[ + { + "item_id":42189, + "name":"装扮小姐姐梦幻冬季", + "state":"active", + "tab_id":44, + "suit_item_id":42193, + "properties":{ + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/38cbcb481923f6a3d7e724a3837324a8ab0f602e.png", + "image_preview_small":"https://i0.hdslb.com/bfs/garb/item/c9621eedabdc728d728158aafab2e271f152561e.png", + "realname_auth":"false", + "sale_type":"suit" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0, + "items":null + } + ], + "emoji_package":[ + { + "item_id":42157, + "name":"装扮小姐姐梦幻冬季", + "state":"active", + "tab_id":8, + "suit_item_id":42193, + "properties":{ + "addable":"true", + "biz":"dynamic,reply,watch_full", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/0dd53dc27d401cad0a3bfc07d91dba3af3a5d6d0.png", + "is_symbol":"false", + "item_ids":"42158,42159,42160,42161,42162,42163,42164,42165,42166,42167,42168,42169,42170,42171,42172,42173,42174,42175,42176,42177,42178,42179,42180,42181,42182,42183,42184,42185,42186,42187", + "permanent":"false", + "preview":"false", + "realname_auth":"false", + "recently_used":"false", + "recommend":"false", + "ref_mid":"0", + "removable":"true", + "sale_type":"pay", + "setting_pannel_not_show":"false", + "size":"L", + "sortable":"true" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0, + "items":[ + { + "item_id":42158, + "name":"[装扮小姐姐梦幻冬季_揉脸]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/e47ad8b1c16ebaa780e0574f360c67f4c45e6325.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42159, + "name":"[装扮小姐姐梦幻冬季_啾咪]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/098619d6f2859966157dc0da4d3a24ae7a690781.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42160, + "name":"[装扮小姐姐梦幻冬季_下雪了]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/08a64a396b710f8670096c5f380f2839f973d218.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42161, + "name":"[装扮小姐姐梦幻冬季_圣诞老人]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/e86122e145000e00362d635c6ebe8ac4260de7f6.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42162, + "name":"[装扮小姐姐梦幻冬季_多喝热水]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/59fb78d3801682c94b126abc0fc1f1b7603dee06.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42163, + "name":"[装扮小姐姐梦幻冬季_扔]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/d762bb454bb2f4fc3827167749b3d61597657b3b.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42164, + "name":"[装扮小姐姐梦幻冬季_生气]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/47fc00a0f13ebd61237c4617a1e5485d0647e7f5.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42165, + "name":"[装扮小姐姐梦幻冬季_贴贴]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/3a7580978ee11f033860af2435bcef6fa282ee64.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42166, + "name":"[装扮小姐姐梦幻冬季_没米了]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/55b3660d73951fb394c6f0594c9fdbeca4f39bea.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42167, + "name":"[装扮小姐姐梦幻冬季_冲鸭]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/cb7c2fbc6ab19d3462d44cabf10b87458650bf28.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42168, + "name":"[装扮小姐姐梦幻冬季_累了]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/884f721618392a0efe6686c2c61fddf04c6f2d73.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42169, + "name":"[装扮小姐姐梦幻冬季_斯密马赛]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/1bbe9b564ee17701a22e848287a5f7983fdfcb34.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42170, + "name":"[装扮小姐姐梦幻冬季_告辞]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/264c9ab6a2503013e79eecdb86118f057762bae5.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42171, + "name":"[装扮小姐姐梦幻冬季_吃我一拳]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/2f7b233826fa0d0729619bbf3dc2220b4c534b3f.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42172, + "name":"[装扮小姐姐梦幻冬季_乌拉]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/23dca67aed7565a4f3e21d8d9d5337125b34d399.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42173, + "name":"[装扮小姐姐梦幻冬季_委屈]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/cec0b3ade7249740cee45f98100275fa7cf7320a.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42174, + "name":"[装扮小姐姐梦幻冬季_溜冰]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/3704984c68c867820103795c4b5313fea0c097e9.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42175, + "name":"[装扮小姐姐梦幻冬季_好耶]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/621d4683d492901c814c64ca3c7bb880ae818779.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42176, + "name":"[装扮小姐姐梦幻冬季_硬撑罢了]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/b4d10356d0ac483b29c875518e0c539809468ba9.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42177, + "name":"[装扮小姐姐梦幻冬季_摸鱼]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/da7205f6a8e7213cca2a06e71c819850cae28977.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42178, + "name":"[装扮小姐姐梦幻冬季_注意保暖]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/170df6f81c3f42defbc07192d19de02525b14348.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42179, + "name":"[装扮小姐姐梦幻冬季_抽我]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/45541e4471e57e59b4aa6b7bcc43e800e3cbde85.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42180, + "name":"[装扮小姐姐梦幻冬季_疑问]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/0d07fd66d3888ea55aa98fa8d520a6e759596e2b.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42181, + "name":"[装扮小姐姐梦幻冬季_抱抱]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/44481b886560e9e1300781ad8a1a4d1dfbbfd6fe.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42182, + "name":"[装扮小姐姐梦幻冬季_烤红薯]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/828555bbfa4dd8cadb9fdfa5868d3101c637945b.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42183, + "name":"[装扮小姐姐梦幻冬季_Power!]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/e4744b70edd5a271dcb6f1b1c62fa32dfa92c9fb.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42184, + "name":"[装扮小姐姐梦幻冬季_堆雪人]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/9407cb861173253f1a1206e3bda7497aebfd98ec.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42185, + "name":"[装扮小姐姐梦幻冬季_好的]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/d73bccf93a20c6eedeb81d975eba99ebc048a88e.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42186, + "name":"[装扮小姐姐梦幻冬季_滑雪]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/36af70fea3fc1636de990597c1a929fecba412db.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + }, + { + "item_id":42187, + "name":"[装扮小姐姐梦幻冬季_吃火锅]", + "state":"active", + "tab_id":7, + "suit_item_id":0, + "properties":{ + "associate":"false", + "gray_rule":"true", + "gray_rule_type":"all", + "image":"https://i0.hdslb.com/bfs/garb/item/bc234259d7971bd6255f9c464597285582e7ff82.png", + "is_symbol":"false", + "ref_mid":"0", + "sale_type":"pay" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0 + } + ] + } + ], + "loading":[ + { + "item_id":42191, + "name":"装扮小姐姐梦幻冬季", + "state":"active", + "tab_id":54, + "suit_item_id":42193, + "properties":{ + "gray_rule":"true", + "gray_rule_type":"all", + "image_preview_small":"https://i0.hdslb.com/bfs/garb/item/32377c9cb1167e1e251c467f6a56ca2b59f130b0.png", + "loading_frame_url":"https://i0.hdslb.com/bfs/garb/item/f2121039298817318e9a10ef25cd802ef7a546f0.png", + "loading_url":"https://i0.hdslb.com/bfs/garb/item/e5ba77a4c2d21809e5f2e407e7bf03a7df635a2c.webp", + "realname_auth":"false", + "ver":"1670384406" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0, + "items":null + } + ], + "play_icon":[ + { + "item_id":42192, + "name":"装扮小姐姐梦幻冬季", + "state":"active", + "tab_id":56, + "suit_item_id":42193, + "properties":{ + "drag_left_png":"https://i0.hdslb.com/bfs/garb/item/933cdf41a554ce65b2bac7cc2af578c065a01ff8.png", + "drag_right_png":"https://i0.hdslb.com/bfs/garb/item/1632ab1d853694d61fe170710b447f6bd9c9152b.png", + "gray_rule":"true", + "gray_rule_type":"all", + "middle_png":"https://i0.hdslb.com/bfs/garb/item/4e1eaa52e65da8e14bce321e7abab9e9a3a28b30.png", + "realname_auth":"false", + "squared_image":"https://i0.hdslb.com/bfs/garb/item/ca4d76d7e8384b18354709ac7e3a422a900f7e07.png", + "static_icon_image":"https://i0.hdslb.com/bfs/garb/item/a98ffc9a8871ded890959c22916f38aba61521fc.png", + "ver":"1670384416" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0, + "items":null + } + ], + "skin":[ + { + "item_id":42190, + "name":"装扮小姐姐梦幻冬季", + "state":"active", + "tab_id":45, + "suit_item_id":42193, + "properties":{ + "color":"#ffffff", + "color_mode":"dark", + "color_second_page":"#5d85c0", + "gray_rule":"true", + "gray_rule_type":"all", + "head_bg":"https://i0.hdslb.com/bfs/garb/item/6c74dac067a429029befc787572b5b7bc83f50a1.jpg", + "head_myself_mp4_play":"once", + "head_myself_squared_bg":"https://i0.hdslb.com/bfs/garb/item/8cff6c83023c9523669e89fc28e1cd7600f196ff.jpg", + "head_tab_bg":"https://i0.hdslb.com/bfs/garb/item/1fe3d1b486ab50d6ffdf30b29bc063818ecde544.jpg", + "image_cover":"https://i0.hdslb.com/bfs/garb/item/14072c2cb4f82c053d85dc92911da37583a17668.jpg", + "image_preview":"https://i0.hdslb.com/bfs/garb/item/14072c2cb4f82c053d85dc92911da37583a17668.jpg", + "package_md5":"4ed60db32789eb79c3e96dc8d6a23ebb", + "package_url":"https://i0.hdslb.com/bfs/garb/zip/b3c95365b791bc58fd56bba7c14b43377d7af82d.zip", + "realname_auth":"false", + "skin_mode":"normal", + "tail_bg":"https://i0.hdslb.com/bfs/garb/item/fda401903a377d79afd576f9ba921c83091e6943.png", + "tail_color":"#f6f1fd", + "tail_color_selected":"#5af1ff", + "tail_icon_ani":"true", + "tail_icon_ani_mode":"once", + "tail_icon_channel":"https://i0.hdslb.com/bfs/garb/item/504a27e5227f30741e35b5817079974335f13d29.png", + "tail_icon_dynamic":"https://i0.hdslb.com/bfs/garb/item/4e0ef0c9540277694087f0aca8aca86b87dc9331.png", + "tail_icon_main":"https://i0.hdslb.com/bfs/garb/item/2a1a97c098bf0d2374a141d8da7fad1e0d1cee24.png", + "tail_icon_mode":"img", + "tail_icon_myself":"https://i0.hdslb.com/bfs/garb/item/20050ddbc0265828e42f068b74b8f5d947f8b7b8.png", + "tail_icon_pub_btn_bg":"https://i0.hdslb.com/bfs/garb/item/4e0ef0c9540277694087f0aca8aca86b87dc9331.png", + "tail_icon_selected_channel":"https://i0.hdslb.com/bfs/garb/item/d14d87016fa2e995917f40148239bc1fa5961ec5.png", + "tail_icon_selected_dynamic":"https://i0.hdslb.com/bfs/garb/item/1b0fb973534600990ad48058eff901643fe7e9fc.png", + "tail_icon_selected_main":"https://i0.hdslb.com/bfs/garb/item/ce1272d036f196ea90e08a433d0003246822aabf.png", + "tail_icon_selected_myself":"https://i0.hdslb.com/bfs/garb/item/a7bbb67de4f22c105529e57b2a1b27737fb6d9df.png", + "tail_icon_selected_pub_btn_bg":"https://i0.hdslb.com/bfs/garb/item/1b0fb973534600990ad48058eff901643fe7e9fc.png", + "tail_icon_selected_shop":"https://i0.hdslb.com/bfs/garb/item/e1622e9643b6ec2186e9f88ee6251334a842e3d0.png", + "tail_icon_shop":"https://i0.hdslb.com/bfs/garb/item/a2eaa41ae4aba160b8b8a9cdc7bc98fd47f2720d.png", + "ver":"1670384396" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0, + "items":null + } + ], + "space_bg":[ + { + "item_id":42188, + "name":"装扮小姐姐梦幻冬季", + "state":"active", + "tab_id":37, + "suit_item_id":42193, + "properties":{ + "fan_no_color":"#3e52eb", + "fan_no_image":"https://i0.hdslb.com/bfs/garb/item/d4888365d80401c72fc34bcc1697c36eb2477a97.png", + "gray_rule":"true", + "gray_rule_type":"all", + "image1_landscape":"https://i0.hdslb.com/bfs/garb/item/971519888f96d2e3cd88e55cb2360ac087f1dde7.png", + "image1_portrait":"https://i0.hdslb.com/bfs/garb/item/78fb9e4a63a17854c7df1e3b1f5f9f48df723e2c.jpg", + "image2_landscape":"https://i0.hdslb.com/bfs/garb/item/90a99f2615ba34596b05cd2a268490cf0072f1e7.png", + "image2_portrait":"https://i0.hdslb.com/bfs/garb/item/11d1a96097ebe357c47277f6c0397a0323c316a5.jpg", + "image3_landscape":"https://i0.hdslb.com/bfs/garb/item/3d2e029d2f6d8c3a425377af5be47a4c8bf2d102.jpg", + "image3_portrait":"https://i0.hdslb.com/bfs/garb/item/3d1495d80211c07ab6773f7aa1d6cb198940907d.jpg", + "realname_auth":"false" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0, + "items":null + } + ], + "thumbup":[ + { + "item_id":42125, + "name":"装扮小姐姐梦幻冬季", + "state":"active", + "tab_id":36, + "suit_item_id":42193, + "properties":{ + "gray_rule":"true", + "gray_rule_type":"all", + "image_ani":"https://i0.hdslb.com/bfs/garb/item/6a2ae0534879d765087c284c745b3e88340a7371.bin", + "image_ani_cut":"https://i0.hdslb.com/bfs/garb/item/6a2ae0534879d765087c284c745b3e88340a7371.bin", + "image_preview":"https://i0.hdslb.com/bfs/garb/item/0cbe14efc8d5397bb6edbd4adae5dcf0ce307c15.png", + "realname_auth":"false" + }, + "current_activity":null, + "next_activity":null, + "current_sources":null, + "finish_sources":null, + "sale_left_time":-1735712010, + "sale_time_end":-1735712010, + "sale_surplus":0, + "items":null + } + ] + }, + "fan_user":{ + "mid":647193094, + "nickname":"装扮小姐姐", + "avatar":"https://i1.hdslb.com/bfs/baselabs/523830e526a81001e4c3dcec9f317623a4f1dd2e.png" + }, + "unlock_items":null, + "activity_entrance":{ + "id":0, + "item_id":0, + "title":"", + "image_cover":"", + "jump_link":"" + } + } +} +``` + +</details> + +## 主题装扮列表API + +> https://api.bilibili.com/x/garb/v2/mall/partition/item/list + +*请求方式: GET* + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|----------|-----|---------|-----|---------------------------------------------------------------------------| +| csrf | str | 用户csrf | 非必要 | | +| group_id | num | 分组id | 非必要 | 建议加上,不填的时候为0,一般配合`part_id`使用。<br />`0`: 装扮<br />`22`: 头像挂件<br />`5`: 动态卡片 | +| location | str | | 非必要 | **尚不明确** | +| part_id | num | 分类id | 必要 | 一般配合`group_id`使用。<br />`6`: 装扮<br />`1`: 头像挂件<br />`2`: 动态卡片<br /> | +| pn | num | 页码 | 非必要 | 不填为1 | +| ps | num | 每页的数据数量 | 非必要 | 不填为20,默认值和最大值也都为20 | +| sort_type | num | 排序方式 | 非必要 | `0`: 默认排序<br />`1`: 按销量排序<br />`2`: 按最新上架时间排序 | +| user_info | str | 用户信息 | 非必要 | 为json对象,其中包含`buvid`和`buvid3`两个字段。 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|-----------------------| +| code | num | 返回值 | `0`:成功<br />`-400`:错误 | +| message | str | 错误信息 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +|------|-------|------|--------------| +| page | obj | 分页信息 | 包含装扮总数、页码和每页的数据数量 | +| list | array | 装扮列表 | | +| offset_info | str | 补偿信息 | **作用尚不明确** | +| group | str | 分组 | **作用尚不明确** | + +`list`对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------------|-----|-----|---------------| +| item_id | num | 装扮id | 如果为0,则该装扮为收藏集 | +| name | str | 装扮名称 | | +| group_id | num | 分组id | | +| group_name | str | 分组名称 | | +| part_id | num | 分类id | | +| state | str | 状态 | | +| properties | obj | 装扮具体属性 | | +| current_activity | str | 当前活动 | | +| next_activity | obj | 下一个活动 | | +| current_sources | str | | **作用尚不明确** | +| finish_sources | str | | **作用尚不明确** | +| sale_left_time | num | | **作用尚不明确** | +| sale_time_end | num | | **作用尚不明确** | +| sale_surplus | num | 商品剩余数量 | | +| sale_count_desc | str | 促销销量说明 | | +| total_count_desc | str | 总销量说明 | | +| tag | str | 标签 | | +| jump_link | str | 跳转链接 | | +| sales_mode | num | 促销模式 | | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/garb/v2/mall/partition/item/list' \ + --data-urlencode 'group_id=0' \ + --data-urlencode 'part_id=6' \ + --data-urlencode 'pn=1' \ + --data-urlencode 'ps=20' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "page": { + "total": 0, + "pn": 1, + "ps": 10 + }, + "list": [ + { + "item_id": 0, + "name": "MyGO!!!!!收藏集", + "group_id": 47, + "group_name": "MyGO!!!!!收藏集", + "part_id": 0, + "state": "active", + "properties": { + "book_amount": "59811", + "dlc_act_id": "102857", + "dlc_act_status": "2", + "dlc_is_free": "0", + "dlc_lottery_id": "102858", + "dlc_lottery_sale_quantity": "1418368", + "dlc_lottery_type": "1", + "dlc_sale_end_time": "0", + "dlc_sale_mode": "0", + "dlc_sale_start_time": "0", + "dlc_surplus_stock": "0", + "image_cover": "https://i0.hdslb.com/bfs/garb/c34fdba0b2a2aa31ff22bda77e217ca9c7e37344.jpg", + "sale_bp_forever_raw": "990", + "type": "dlc_act" + }, + "current_activity": null, + "next_activity": null, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -1735808611, + "sale_time_end": -1735808611, + "sale_surplus": 0, + "sale_count_desc": "100万+", + "total_count_desc": "已售100万+份", + "tag": "", + "jump_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=102857&hybrid_set_header=2&lottery_id=102858", + "sales_mode": 0 + }, + { + "item_id": 0, + "name": "饿殍:明末千里行", + "group_id": 49, + "group_name": "饿殍:明末千里行", + "part_id": 0, + "state": "active", + "properties": { + "book_amount": "21825", + "dlc_act_id": "102794", + "dlc_act_status": "2", + "dlc_is_free": "0", + "dlc_lottery_id": "102886", + "dlc_lottery_sale_quantity": "520677", + "dlc_lottery_type": "1", + "dlc_sale_end_time": "0", + "dlc_sale_mode": "0", + "dlc_sale_start_time": "0", + "dlc_surplus_stock": "0", + "image_cover": "https://i0.hdslb.com/bfs/garb/838639725c0c37f6ccc5e85b2a1ed6ff895baca2.jpg", + "sale_bp_forever_raw": "990", + "type": "dlc_act" + }, + "current_activity": null, + "next_activity": null, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -1735808611, + "sale_time_end": -1735808611, + "sale_surplus": 0, + "sale_count_desc": "52万+", + "total_count_desc": "已售52万+份", + "tag": "", + "jump_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=102794&hybrid_set_header=2&lottery_id=102886", + "sales_mode": 0 + }, + { + "item_id": 0, + "name": "2024拜年纪", + "group_id": 70, + "group_name": "2024拜年纪", + "part_id": 0, + "state": "active", + "properties": { + "book_amount": "30103", + "dlc_act_id": "279", + "dlc_act_status": "2", + "dlc_is_free": "0", + "dlc_lottery_id": "256", + "dlc_lottery_sale_quantity": "332544", + "dlc_lottery_type": "1", + "dlc_sale_end_time": "0", + "dlc_sale_mode": "0", + "dlc_sale_start_time": "0", + "dlc_surplus_stock": "0", + "image_cover": "http://i0.hdslb.com/bfs/archive/f96a8cf6866ccef8f54de4773acf0cb07b915ac6.png", + "sale_bp_forever_raw": "990", + "type": "dlc_act" + }, + "current_activity": null, + "next_activity": null, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -1735808611, + "sale_time_end": -1735808611, + "sale_surplus": 0, + "sale_count_desc": "33万+", + "total_count_desc": "已售33万+份", + "tag": "", + "jump_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=279&hybrid_set_header=2&lottery_id=256", + "sales_mode": 0 + }, + { + "item_id": 0, + "name": "2233·十五周年站庆", + "group_id": 70, + "group_name": "2233·十五周年站庆", + "part_id": 0, + "state": "active", + "properties": { + "book_amount": "38339", + "dlc_act_id": "293", + "dlc_act_status": "2", + "dlc_is_free": "0", + "dlc_lottery_id": "302", + "dlc_lottery_sale_quantity": "63336", + "dlc_lottery_type": "1", + "dlc_sale_end_time": "0", + "dlc_sale_mode": "0", + "dlc_sale_start_time": "0", + "dlc_surplus_stock": "0", + "image_cover": "http://i0.hdslb.com/bfs/archive/633174e11f3587166e31b37cc87feb184808408d.jpg", + "sale_bp_forever_raw": "990", + "type": "dlc_act" + }, + "current_activity": null, + "next_activity": null, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -1735808611, + "sale_time_end": -1735808611, + "sale_surplus": 0, + "sale_count_desc": "6万+", + "total_count_desc": "已售6万+份", + "tag": "", + "jump_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=293&hybrid_set_header=2&lottery_id=302", + "sales_mode": 0 + }, + { + "item_id": 0, + "name": "奈姬niki收藏集", + "group_id": 47, + "group_name": "奈姬niki收藏集", + "part_id": 0, + "state": "active", + "properties": { + "book_amount": "24158", + "dlc_act_id": "104783", + "dlc_act_status": "2", + "dlc_is_free": "0", + "dlc_lottery_id": "104784", + "dlc_lottery_sale_quantity": "120787", + "dlc_lottery_type": "1", + "dlc_sale_end_time": "0", + "dlc_sale_mode": "0", + "dlc_sale_start_time": "0", + "dlc_surplus_stock": "0", + "image_cover": "https://i0.hdslb.com/bfs/garb/6a2395d9be428ac09766deafbd8ead49503216ea.jpg", + "sale_bp_forever_raw": "990", + "type": "dlc_act" + }, + "current_activity": null, + "next_activity": null, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -1735808611, + "sale_time_end": -1735808611, + "sale_surplus": 0, + "sale_count_desc": "12万+", + "total_count_desc": "已售12万+份", + "tag": "", + "jump_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=104783&hybrid_set_header=2&lottery_id=104784", + "sales_mode": 0 + }, + { + "item_id": 0, + "name": "黎歌Neeko收藏集-幻夏恋歌", + "group_id": 47, + "group_name": "黎歌Neeko收藏集-幻夏恋歌", + "part_id": 0, + "state": "active", + "properties": { + "book_amount": "22125", + "dlc_act_id": "100858", + "dlc_act_status": "2", + "dlc_is_free": "0", + "dlc_lottery_id": "102305", + "dlc_lottery_sale_quantity": "528139", + "dlc_lottery_type": "2", + "dlc_sale_end_time": "0", + "dlc_sale_mode": "0", + "dlc_sale_start_time": "0", + "dlc_surplus_stock": "0", + "image_cover": "https://i0.hdslb.com/bfs/garb/ff57aba427ce4dd3608660233ba1d3ec518ff6aa.png", + "sale_bp_forever_raw": "990", + "type": "dlc_act" + }, + "current_activity": null, + "next_activity": null, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -1735808611, + "sale_time_end": -1735808611, + "sale_surplus": 0, + "sale_count_desc": "52万+", + "total_count_desc": "已售52万+份", + "tag": "", + "jump_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=100858&hybrid_set_header=2&lottery_id=102305", + "sales_mode": 0 + }, + { + "item_id": 0, + "name": "2024明日方舟音律联觉", + "group_id": 49, + "group_name": "2024明日方舟音律联觉", + "part_id": 0, + "state": "active", + "properties": { + "book_amount": "59594", + "dlc_act_id": "102942", + "dlc_act_status": "2", + "dlc_is_free": "0", + "dlc_lottery_id": "102943", + "dlc_lottery_sale_quantity": "1126215", + "dlc_lottery_type": "1", + "dlc_sale_end_time": "0", + "dlc_sale_mode": "0", + "dlc_sale_start_time": "0", + "dlc_surplus_stock": "0", + "image_cover": "https://i0.hdslb.com/bfs/garb/c59397dff6e6618058b7d943aa9614b0d74a9c17.jpg", + "sale_bp_forever_raw": "990", + "type": "dlc_act" + }, + "current_activity": null, + "next_activity": null, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -1735808611, + "sale_time_end": -1735808611, + "sale_surplus": 0, + "sale_count_desc": "100万+", + "total_count_desc": "已售100万+份", + "tag": "", + "jump_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=102942&hybrid_set_header=2&lottery_id=102943", + "sales_mode": 0 + }, + { + "item_id": 0, + "name": "BLG·2023LPL出征收藏集", + "group_id": 49, + "group_name": "BLG·2023LPL出征收藏集", + "part_id": 0, + "state": "active", + "properties": { + "book_amount": "18878", + "dlc_act_id": "228", + "dlc_act_status": "2", + "dlc_is_free": "0", + "dlc_lottery_id": "157", + "dlc_lottery_sale_quantity": "14537", + "dlc_lottery_type": "1", + "dlc_sale_end_time": "0", + "dlc_sale_mode": "0", + "dlc_sale_start_time": "0", + "dlc_surplus_stock": "0", + "image_cover": "http://i0.hdslb.com/bfs/archive/dc0af06ae0e5018cc24ecab1be76742ff1ad9fc2.png", + "sale_bp_forever_raw": "990", + "type": "dlc_act" + }, + "current_activity": null, + "next_activity": null, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -1735808611, + "sale_time_end": -1735808611, + "sale_surplus": 0, + "sale_count_desc": "1万+", + "total_count_desc": "已售1万+份", + "tag": "", + "jump_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=228&hybrid_set_header=2&lottery_id=157", + "sales_mode": 0 + }, + { + "item_id": 0, + "name": "幻星乐园", + "group_id": 107, + "group_name": "幻星乐园", + "part_id": 0, + "state": "active", + "properties": { + "book_amount": "22563", + "dlc_act_id": "103874", + "dlc_act_status": "2", + "dlc_is_free": "0", + "dlc_lottery_id": "103875", + "dlc_lottery_sale_quantity": "319104", + "dlc_lottery_type": "1", + "dlc_sale_end_time": "0", + "dlc_sale_mode": "0", + "dlc_sale_start_time": "0", + "dlc_surplus_stock": "0", + "image_cover": "https://i0.hdslb.com/bfs/garb/0f8eb52dfb0d3c7f89fb4d33749e4bf62544112e.jpg", + "sale_bp_forever_raw": "990", + "type": "dlc_act" + }, + "current_activity": null, + "next_activity": null, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -1735808611, + "sale_time_end": -1735808611, + "sale_surplus": 0, + "sale_count_desc": "31万+", + "total_count_desc": "已售31万+份", + "tag": "", + "jump_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=103874&hybrid_set_header=2&lottery_id=103875", + "sales_mode": 0 + }, + { + "item_id": 0, + "name": "玉之けだま_毛玉收藏集", + "group_id": 46, + "group_name": "玉之けだま_毛玉收藏集", + "part_id": 0, + "state": "active", + "properties": { + "book_amount": "30723", + "dlc_act_id": "104459", + "dlc_act_status": "2", + "dlc_is_free": "0", + "dlc_lottery_id": "104460", + "dlc_lottery_sale_quantity": "267724", + "dlc_lottery_type": "1", + "dlc_sale_end_time": "0", + "dlc_sale_mode": "0", + "dlc_sale_start_time": "0", + "dlc_surplus_stock": "0", + "image_cover": "https://i0.hdslb.com/bfs/garb/565bf9465865efdd28b07c40f8352e43091ff4da.png", + "sale_bp_forever_raw": "990", + "type": "dlc_act" + }, + "current_activity": null, + "next_activity": null, + "current_sources": null, + "finish_sources": null, + "sale_left_time": -1735808611, + "sale_time_end": -1735808611, + "sale_surplus": 0, + "sale_count_desc": "26万+", + "total_count_desc": "已售26万+份", + "tag": "", + "jump_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=104459&hybrid_set_header=2&lottery_id=104460", + "sales_mode": 0 + } + ], + "offset_info": "pool::10", + "group": "garb_feed_recommend_rule_ab_key:1" + } +} +``` + +</details> + +## 收藏集列表API + +> https://api.bilibili.com/x/vas/dlc_act/act/list + +*请求方式: GET* + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|-------|------|--------|-----|---------------------------| +| csrf | str | 用户csrf | 非必要 | | +| scene | num | | 非必要 | **作用尚不明确,默认为1,不填则获取到空数据** | +| site | site | 位置 | 非必要 | 不填为20,但建议填上,会影响到后面的json数据 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|------|------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------| +| code | num | 返回值 | `0`:成功 | +| message | str | 错误信息 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | +| is_more | bool | 是否还有足够的收藏集 | 如果为true,则说明如果继续增加url参数中site的值,都还能从当前的位置往后列出20份收藏集;<br />如果为false,则说明如果继续增加url参数中site的值,将无法继续从当前位置列出20份收藏集(最多也是20份),<br />这表示页面已经拉到底了,可用于判断是否已经获取完了所有收藏集的数据。 | +| site | num | 位置 | **它的值为url参数中site的值的基础上再加20**,比如url参数中的site值为0,则此site的值为20,<br />表示这页的收藏集列表是从序号为0的收藏集开始列出,直到列出往后的20份。 | + +`data` 对象中的 `list` 数组对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------------|-----|---------|---------------| +| act_id | num | 收藏集id | | +| act_name | num | 收藏集名称 | | +| act_pic | num | 收藏集封面图片 | | +| sale_price | num | 收藏集价格 | 以0.01B币为单位 | +| act_desc | num | 收藏集说明 | | +| tag | num | 标签 | | +| lottery_id | num | 抽奖id | | +| lottery_type | num | 抽奖类型 | | +| act_link | num | 收藏集链接 | | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/vas/dlc_act/act/list' \ + --data-urlencode 'csrf=xxx' \ + --data-urlencode 'scene=1' \ + --data-urlencode 'site=0' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "act_id": 105432, + "act_name": "挚友的旅途·羽毛收藏集", + "act_pic": "https://i0.hdslb.com/bfs/garb/b6a7314b6ad321b638c3d2270903c02c0d2d7b20.png", + "sale_price": 9900, + "act_desc": "已售份数6千+", + "tag": "新奖励", + "lottery_id": 105433, + "lottery_type": 1, + "act_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=105432&hybrid_set_header=2&lottery_id=105433" + }, + { + "act_id": 102054, + "act_name": "兰音的衣柜奇缘-兰音·拾光幻梦", + "act_pic": "https://i0.hdslb.com/bfs/garb/b7e5465ff80a3260cdc1c1255853730bfc6bd818.jpg", + "sale_price": 9900, + "act_desc": "已售份数3万+", + "tag": "新卡池", + "lottery_id": 105434, + "lottery_type": 2, + "act_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=102054&hybrid_set_header=2&lottery_id=105434" + }, + { + "act_id": 102550, + "act_name": "洛天依·收藏集-戏游九州", + "act_pic": "https://i0.hdslb.com/bfs/garb/74706a52bc08764828f9251439055b18646e98b3.png", + "sale_price": 9900, + "act_desc": "已售份数6万+", + "tag": "新奖励", + "lottery_id": 105269, + "lottery_type": 2, + "act_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=102550&hybrid_set_header=2&lottery_id=105269" + }, + { + "act_id": 105006, + "act_name": "村村宇宙·小猫女仆降临", + "act_pic": "https://i0.hdslb.com/bfs/garb/cfccce3c1520b828f02d7b4e009cc7d965133025.jpg", + "sale_price": 9900, + "act_desc": "已售份数1万+", + "tag": "新奖励", + "lottery_id": 105167, + "lottery_type": 1, + "act_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=105006&hybrid_set_header=2&lottery_id=105167" + }, + { + "act_id": 105435, + "act_name": "东方收藏集·浮生若梦", + "act_pic": "https://i0.hdslb.com/bfs/garb/27156281f59f774198f38b9a4a64d9a74efb9290.png", + "sale_price": 9900, + "act_desc": "已售份数6万+", + "tag": "新奖励", + "lottery_id": 105438, + "lottery_type": 1, + "act_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=105435&hybrid_set_header=2&lottery_id=105438" + }, + { + "act_id": 105407, + "act_name": "紫罗兰永恒花园收藏集", + "act_pic": "https://i0.hdslb.com/bfs/garb/9e54ae06dfd32625071153adc702eb7554b45af8.jpg", + "sale_price": 9900, + "act_desc": "已售份数1万+", + "tag": "新奖励", + "lottery_id": 105408, + "lottery_type": 1, + "act_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=105407&hybrid_set_header=2&lottery_id=105408" + }, + { + "act_id": 105461, + "act_name": "Team Spirit 冠军收藏集", + "act_pic": "https://i0.hdslb.com/bfs/garb/0a68dac1e2d37767c26930ad4d3121e2b7c56c44.jpg", + "sale_price": 9900, + "act_desc": "已售份数9千+", + "tag": "新奖励", + "lottery_id": 105462, + "lottery_type": 1, + "act_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=105461&hybrid_set_header=2&lottery_id=105462" + }, + { + "act_id": 105326, + "act_name": "小神奈殿下收藏集", + "act_pic": "https://i0.hdslb.com/bfs/garb/ed3b6e516ef05cf595cf9d24203e16205eea55e5.png", + "sale_price": 9900, + "act_desc": "已售份数1万+", + "tag": "新奖励", + "lottery_id": 105327, + "lottery_type": 1, + "act_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=105326&hybrid_set_header=2&lottery_id=105327" + }, + { + "act_id": 105444, + "act_name": "yumekiii收藏集", + "act_pic": "https://i0.hdslb.com/bfs/garb/afc2dd57c962244d8021b92752038714b7b3341e.png", + "sale_price": 9900, + "act_desc": "已售份数3千+", + "tag": "新奖励", + "lottery_id": 105445, + "lottery_type": 1, + "act_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=105444&hybrid_set_header=2&lottery_id=105445" + }, + { + "act_id": 101545, + "act_name": "Sheya收藏集-月食梦-镜海之梦", + "act_pic": "https://i0.hdslb.com/bfs/garb/262e59d60698d6797488f081826e172e6689c339.jpg", + "sale_price": 9900, + "act_desc": "已售份数3千+", + "tag": "新卡池", + "lottery_id": 105451, + "lottery_type": 2, + "act_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=101545&hybrid_set_header=2&lottery_id=105451" + }, + { + "act_id": 105388, + "act_name": "LOOPY可爱计划", + "act_pic": "https://i0.hdslb.com/bfs/garb/f24711f2f35cb9db7919bb888af3fe23f5c588ad.jpg", + "sale_price": 9900, + "act_desc": "", + "tag": "限时卡池", + "lottery_id": 105411, + "lottery_type": 1, + "act_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=105388&hybrid_set_header=2&lottery_id=105411" + }, + { + "act_id": 105413, + "act_name": "范式起源", + "act_pic": "https://i0.hdslb.com/bfs/garb/784d6073f5cc3110117449da018845443b9c484d.png", + "sale_price": 9900, + "act_desc": "已售份数1万+", + "tag": "", + "lottery_id": 105414, + "lottery_type": 1, + "act_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=105413&hybrid_set_header=2&lottery_id=105414" + }, + { + "act_id": 105409, + "act_name": "VirtuaReal碧波澜影", + "act_pic": "https://i0.hdslb.com/bfs/garb/63f57f0014e47d1302005a5c6ab0164e925c69ef.png", + "sale_price": 9900, + "act_desc": "已售份数3万+", + "tag": "", + "lottery_id": 105410, + "lottery_type": 1, + "act_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=105409&hybrid_set_header=2&lottery_id=105410" + }, + { + "act_id": 101388, + "act_name": "寺田堤拉 TERADA TERA-白橙绘锦", + "act_pic": "https://i0.hdslb.com/bfs/garb/8ec594c0a11706846f5394eaac78fd97065000b1.png", + "sale_price": 9900, + "act_desc": "已售份数5千+", + "tag": "", + "lottery_id": 104985, + "lottery_type": 2, + "act_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=101388&hybrid_set_header=2&lottery_id=104985" + }, + { + "act_id": 104978, + "act_name": "少女乐队的呐喊", + "act_pic": "https://i0.hdslb.com/bfs/garb/cdf0c00bd070ee77951e695355b3394be53b8288.jpg", + "sale_price": 9900, + "act_desc": "已售份数39万+", + "tag": "", + "lottery_id": 105056, + "lottery_type": 1, + "act_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=104978&hybrid_set_header=2&lottery_id=105056" + }, + { + "act_id": 104174, + "act_name": "顾晓Khaos收藏集", + "act_pic": "https://i0.hdslb.com/bfs/garb/52152a236bcd4e2829012eb8cc32d1e2f24490c9.png", + "sale_price": 9900, + "act_desc": "已售份数8千+", + "tag": "", + "lottery_id": 104181, + "lottery_type": 1, + "act_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=104174&hybrid_set_header=2&lottery_id=104181" + }, + { + "act_id": 105151, + "act_name": "晴云-醒时晴空", + "act_pic": "https://i0.hdslb.com/bfs/garb/1320dd55c13a11dfc7c714a75b56159d73c2feae.jpg", + "sale_price": 9900, + "act_desc": "已售份数3千+", + "tag": "", + "lottery_id": 105168, + "lottery_type": 1, + "act_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=105151&hybrid_set_header=2&lottery_id=105168" + }, + { + "act_id": 103966, + "act_name": "礼拜六Liu收藏集", + "act_pic": "https://i0.hdslb.com/bfs/garb/9c5b03a79074b1354ee4277d77c108441ac8ff35.jpg", + "sale_price": 9900, + "act_desc": "已售份数1万+", + "tag": "", + "lottery_id": 103967, + "lottery_type": 1, + "act_link": "https://www.bilibili.com/h5/mall/digital-card/home?-Abrowser=live&act_id=103966&hybrid_set_header=2&lottery_id=103967" + } + ], + "is_more": true, + "site": 20 + } +} +``` + +</details> \ No newline at end of file diff --git a/bb-api-collect/docs/garb/skin.md b/bb-api-collect/docs/garb/skin.md new file mode 100644 index 0000000000..c91d5d59ae --- /dev/null +++ b/bb-api-collect/docs/garb/skin.md @@ -0,0 +1,267 @@ +# APP主题 + +## 获取主题及加载动画 + +> https://app.bilibili.com/x/resource/show/skin + +*请求方式:GET* + +鉴权方式:appkey + +认证方式:仅可APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | ------------- | +| access_key | str | APP登录Token | APP方式必要 | | +| appkey | str | APP密钥 | APP方式必要 | | +| build | num | 版本 | APP方式必要 | 可为`6082000` | +| ts | num | 当前时间戳 | APP方式必要 | 可为`0` | +| sign | str | APP签名 | APP方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-3:API校验密匙错误<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----- | ------------ | ------------ | +| user_equip | obj | 个性主题信息 | 有效时有此项 | +| skin_colors | array | 主题颜色列表 | | +| load_equip | obj | 加载动画信息 | 有效时有此项 | + +`data`中的`user_equip`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | --------------- | ------ | +| id | num | 装扮id | | +| name | str | 装扮名称 | | +| preview | str | 装扮封面url | | +| ver | num | 装扮版本 | 时间戳 | +| package_url | str | 装扮包url | | +| package_md5 | str | 装扮包md5校验值 | | +| data | obj | 装扮配置 | | + +`user_equip`中的`data`对象: + +| 字段 | 类型 | 内容 | 必要性 | 备注 | +| ------------------- | ---- | ----------------- | -------- | --------------------------- | +| color_mode | str | 颜色模式 | 必要 | light:亮色<br />dark:暗色 | +| color | str | 前景色? | 必要 | 颜色<br />1. 使用十六进制颜色值<br />2. 颜色值的大小写不限,下同<br />3. 例:#ffffff | +| color_second_page | str | 背景色? | 必要 | 颜色 | +| tail_color | str | 底边栏颜色 | 必要 | 颜色 | +| tail_color_selected | str | 底边栏颜色(选择时) | 必要 | 颜色 | +| tail_icon_ani | bool | 有无底边栏动画 | 必要 | false:无<br />true:有 | +| tail_icon_ani_mode | str | 底边栏动画循环播放 | 必要 | once:播放一次 | +| head_myself_mp4_play| str | 我的页面头图(视频)循环 | 必要 | once:播放一次<br />loop:循环播放 | +| tail_icon_mode | str | 底栏改图标或改颜色 | 必要 | img:图标<br />color:颜色 | +| side_bg_color | str | 侧边栏颜色 | 非必要 | 颜色<br />5.x 版本客户端的侧边栏 | +| side_line_color | str | 侧边栏线条颜色? | 非必要 | 颜色<br />5.x 版本客户端的侧边栏 | +| tail_icon_color | str | 底栏图标颜色 | 可能必要 | 颜色<br />若 tail_icon_mode = "color",则必要 | +| tail_icon_color_dark| str | 底栏图标颜色(夜间模式) | 可能必要 | 颜色<br />若 tail_icon_mode = "color",则必要 | +| tail_icon_color_selected| str | 底栏图标颜色(选择时) | 可能必要 | 颜色<br />若 tail_icon_mode = "color",则必要 | +| tail_icon_color_selected_dark| str | 底栏图标颜色(选择时)(夜间模式) | 可能必要 | 颜色<br />若 tail_icon_mode = "color",则必要 | + +`skin_colors`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---- | +| 0 | obj | 主题颜色1 | | +| n | obj | 主题颜色(n+1) | | +| …… | obj | …… | …… | + +`skin_colors`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------ | ------------------------------- | +| id | num | 颜色id | | +| name | str | 颜色名称 | | +| is_free | bool | 是否免费 | false:收费<br />true:免费 | +| price | num | 价格 | 单位为硬币 | +| is_bought | bool | 是否已购买 | false:未购买<br />true:已购买 | +| status | num | 状态 | 1:自动续费<br />4:已退订 | +| buy_time | num | 购买时间 | 毫秒时间戳 | +| due_time | num | 到期时间 | 毫秒时间戳 | +| color_name | str | 颜色类型名称 | | +| is_overdue | bool | 是否已到期 | false:未到期<br />true:已到期 | + +`data`中的`load_equip`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | --------------- | ------ | +| id | num | 装扮id | | +| name | str | 装扮名称 | | +| ver | num | 装扮版本 | 时间戳 | +| loading_url | str | 加载动画图标url | | + +**示例:** + +```shell +curl -G 'https://app.bilibili.com/x/resource/show/skin' \ +--data-urlencode 'access_key=xxx' \ +--data-urlencode 'appkey=1d8b6e7d45233436' \ +--data-urlencode 'build=6082000' \ +--data-urlencode 'ts=0' \ +--data-urlencode 'sign=ea212fea5b00a6278ea6d9938b4c500e' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "user_equip": { + "id": 2529, + "name": "初音未来-日版", + "preview": "http://i0.hdslb.com/bfs/garb/item/2fa16380b31b3cee6c889d645f2699de8e9d9faf.jpg", + "ver": 1598600025, + "package_url": "http://i0.hdslb.com/bfs/garb/zip/9c393edea0c7b7b59685a20cd655363ef573a325.zip", + "package_md5": "7b6d20d998ad543c6a275948a6a1a5fe", + "data": { + "color_mode": "light", + "color": "#212121", + "color_second_page": "#fff2d2", + "side_bg_color": "#ffe7ae", + "tail_color": "#996c00", + "tail_color_selected": "#0d6872", + "tail_icon_ani": true, + "tail_icon_ani_mode": "once" + } + }, + "skin_colors": [ + { + "id": 2, + "name": "少女粉", + "is_free": true, + "color_name": "pink" + }, + { + "id": 1, + "name": "夜间模式", + "is_free": true, + "color_name": "black" + }, + { + "id": 3, + "name": "姨妈红", + "price": 5, + "color_name": "red" + }, + { + "id": 4, + "name": "咸蛋黄", + "price": 5, + "color_name": "yellow" + }, + { + "id": 5, + "name": "早苗绿", + "price": 5, + "status": 4, + "buy_time": 1599219782000, + "due_time": 1601811782000, + "color_name": "green" + }, + { + "id": 6, + "name": "胖次蓝", + "price": 5, + "color_name": "blue" + }, + { + "id": 7, + "name": "基佬紫", + "price": 5, + "color_name": "purple" + } + ], + "load_equip": { + "id": 2531, + "name": "初音未来13周年", + "ver": 1598602035, + "loading_url": "http://i0.hdslb.com/bfs/garb/item/9b12e8b5cc16a4c2e71e91c43796f09d5e132847.webp" + } + } +} +``` + +</details> + +## 主题包结构 + +主题包为app端付费主题(套装)的整合包,以zip格式通过url分发 + +包内的图片文件为app对应的资源替换,替换时可随意修改后缀 jpg 或 png + +必要性:head_bg 及 head_tab_bg 为必要,其他非必要 + +| 文件名 | 说明 | +| --------------------------------- | -------------------------- | +| head_bg.jpg | 首页顶部栏背景 | +| head_tab_bg.jpg | 顶部栏背景 | +| head_myself_bg.jpg | 【我的】页面头图(小) | +| head_myself_squared_bg.jpg | 【我的】页面头图(大) | +| head_myself_mp4_bg.mp4 | 【我的】页面头图(视频)<br />格式参考:后缀必须 mp4、分辨率 1242 x 1074、60 FPS、去掉音轨(音频) | +| side_bg.jpg | 侧边栏背景 | +| side_bg_bottom.jpg | 侧边栏底部背景 | +| tail_bg.png | 底部栏背景 | +| tail_icon_main.png | 【首页】按钮 | +| tail_icon_channel.png | 【频道】按钮 | +| tail_icon_dynamic.png | 【动态】按钮 | +| tail_icon_shop.png | 【会员购】按钮 | +| tail_icon_myself.png | 【我的】按钮 | +| tail_icon_pub_btn_bg.png | 【发布】按钮 | +| tail_icon_selected_main.png | 【首页】按钮(选中状态) | +| tail_icon_selected_channel.png | 【频道】按钮(选中状态) | +| tail_icon_selected_dynamic.png | 【动态】按钮(选中状态) | +| tail_icon_selected_shop.png | 【会员购】按钮(选中状态) | +| tail_icon_selected_myself.png | 【我的】按钮(选中状态) | +| tail_icon_selected_pub_btn_bg.png | 【发布】按钮(选中状态) | + + +以`id=2529(初音未来-日版)`的资源为例 + +```shell +wget https://i0.hdslb.com/bfs/garb/zip/9c393edea0c7b7b59685a20cd655363ef573a325.zip +unzip -l 9c393edea0c7b7b59685a20cd655363ef573a325.zip +``` + +返回为 + +``` +Archive: 9c393edea0c7b7b59685a20cd655363ef573a325.zip + Length Date Time Name +--------- ---------- ----- ---- + 22995 1980-00-00 00:00 tail_icon_selected_myself.png + 18444 1980-00-00 00:00 head_bg.jpg + 3061 1980-00-00 00:00 head_tab_bg.jpg + 188898 1980-00-00 00:00 side_bg.jpg + 2842 1980-00-00 00:00 side_bg_bottom.jpg + 203134 1980-00-00 00:00 tail_bg.png + 27539 1980-00-00 00:00 tail_icon_main.png + 25632 1980-00-00 00:00 tail_icon_selected_main.png + 27415 1980-00-00 00:00 tail_icon_selected_channel.png + 191706 1980-00-00 00:00 head_myself_squared_bg.jpg + 27919 1980-00-00 00:00 tail_icon_channel.png + 27262 1980-00-00 00:00 tail_icon_selected_dynamic.png + 147738 1980-00-00 00:00 head_myself_bg.jpg + 28182 1980-00-00 00:00 tail_icon_dynamic.png + 25878 1980-00-00 00:00 tail_icon_shop.png + 26487 1980-00-00 00:00 tail_icon_selected_shop.png + 21831 1980-00-00 00:00 tail_icon_myself.png +--------- ------- + 1016963 17 files +``` + diff --git a/bb-api-collect/docs/historytoview/history.md b/bb-api-collect/docs/historytoview/history.md new file mode 100644 index 0000000000..bf49a71129 --- /dev/null +++ b/bb-api-collect/docs/historytoview/history.md @@ -0,0 +1,845 @@ +# 历史记录 + +## 获取历史记录列表_web端 + +> https://api.bilibili.com/x/web-interface/history/cursor + +*请求方式:GET* + +认证方式:Cookie (SESSDATA) + +注:`max`、`business`、`view_at`参数用于历史记录列表的 IFS (无限滚动),其用法类似链表的 next 指针 + +本接口也可以返回已失效稿件的信息 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------------------ | ------ | ------------------------------------------------------------ | +| max | num | 历史记录截止目标 id | 非必要 | 默认为 0<br />稿件:稿件 avid<br />剧集(番剧 / 影视):剧集 ssid<br />直播:直播间 id<br />文集:文集 rlid<br />文章:文章 cvid | +| business | str | 历史记录截止目标业务类型 | 非必要 | 默认为空<br />archive:稿件<br />pgc:剧集(番剧 / 影视)<br />live:直播<br />article-list:文集<br />article:文章 | +| view_at | num | 历史记录截止时间 | 非必要 | 时间戳<br />默认为 0<br />0 为当前时间 | +| type | str | 历史记录分类筛选 | 非必要 | all:全部类型(默认)<br />archive:稿件<br />live:直播<br />article:文章 | +| ps | num | 每页项数 | 非必要 | 默认为 20,最大 30 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | ------------ | ------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-400:请求错误 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | array | 历史记录列表 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ----- | ---------------- | ---- | +| cursor | obj | 历史记录页面信息 | | +| tab | array | 历史记录筛选类型 | | +| list | array | 分段历史记录列表 | | + +`data`中的`cursor`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ---------------- | -------------- | +| max | num | 最后一项目标 id | **见请求参数** | +| view_at | num | 最后一项时间节点 | 时间戳 | +| business | str | 最后一项业务类型 | **见请求参数** | +| ps | num | 每页项数 | | + +`data`中的`tab`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------------ | ---- | +| 0 | obj | 历史记录筛选类型 1 | | +| 1 | obj | 历史记录筛选类型 2 | | +| 2 | obj | 历史记录筛选类型 3 | | + +`tab`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | ---- | +| type | str | 类型 | | +| name | str | 类型名 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | ---------------- | +| 0 | obj | 历史记录 1 | | +| n | obj | 历史记录 (n+1) | 按照查看顺序排列 | +| …… | obj | | | + +`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ------------------------------- | ------------------------ | ---------------------------------------- | +| title | str | 条目标题 | | +| long_title | str | 条目副标题 | | +| cover | str | 条目封面图 url | 用于专栏以外的条目 | +| covers | 有效时:array<br />无效时:null | 条目封面图组 | 仅用于专栏 | +| uri | str | 重定向 url | 仅用于剧集和直播 | +| history | obj | 条目详细信息 | | +| videos | num | 视频分 P 数目 | 仅用于稿件视频 | +| author_name | str | UP 主昵称 | | +| author_face | str | UP 主头像 url | | +| author_mid | num | UP 主 mid | | +| view_at | num | 查看时间 | 时间戳 | +| progress | num | 视频观看进度 | 单位为秒<br />用于稿件视频或剧集 | +| badge | str | 角标文案 | 稿件视频 / 剧集 / 笔记 | +| show_title | str | 分 P 标题 | 用于稿件视频或剧集 | +| duration | num | 视频总时长 | 用于稿件视频或剧集 | +| current | str | (?) | | +| total | num | 总计分集数 | 仅用于剧集 | +| new_desc | str | 最新一话 / 最新一 P 标识 | 用于稿件视频或剧集 | +| is_finish | num | 是否已完结 | 仅用于剧集<br />0:未完结<br />1:已完结 | +| is_fav | num | 是否收藏 | 0:未收藏<br />1:已收藏 | +| kid | num | 条目目标 id | **详细内容见参数** | +| tag_name | str | 子分区名 | 用于稿件视频和直播 | +| live_status | num | 直播状态 | 仅用于直播<br />0:未开播<br />1:已开播 | + +`list`数组中的对象中的`covers`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | ---- | +| 0 | str | 封面图片 1 | | +| n | str | 封面图片 (n+1) | | +| …… | str | …… | | + +`list`数组中的对象中的`history`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | --------------------- | ------------------------------------------------------------ | +| oid | num | 目标id | 稿件视频&剧集(当`business=archive`或`business=pgc`时):稿件avid<br />直播(当`business=live`时):直播间id<br />文章(当`business=article`时):文章cvid<br />文集(当`business=article-list`时):文集rlid | +| epid | num | 剧集epid | 仅用于剧集 | +| bvid | str | 稿件bvid | 仅用于稿件视频 | +| page | num | 观看到的视频分P数 | 仅用于稿件视频 | +| cid | num | 观看到的对象id | 稿件视频&剧集(当`business=archive`或`business=pgc`时):视频cid<br />文集(当`business=article-list`时):文章cvid | +| part | str | 观看到的视频分 P 标题 | 仅用于稿件视频 | +| business | str | 业务类型 | **见请求参数** | +| dt | num | 记录查看的平台代码 | 1 3 5 7:手机端<br />2:web端<br />4 6:pad端<br />9: 智能音箱/游戏机33:TV端<br />0:其他 | + +**示例:** + +获取当前时间截止的5条历史记录 + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/history/cursor' \ +--data-urlencode 'ps=5' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "cursor": { + "max": 26193, + "view_at": 1592985807, + "business": "pgc", + "ps": 5 + }, + "tab": [ + { + "type": "archive", + "name": "视频" + }, + { + "type": "live", + "name": "直播" + }, + { + "type": "article", + "name": "专栏" + } + ], + "list": [ + { + "title": "韩国漫画如何出海掘金?一年出口额2.8亿元", + "long_title": "", + "cover": "", + "covers": [ + "https://i0.hdslb.com/bfs/article/b170c6fd7429ae205d6cb935e1d431710d82609d.jpg" + ], + "uri": "", + "history": { + "oid": 6470274, + "epid": 0, + "bvid": "", + "page": 0, + "cid": 0, + "part": "", + "business": "article", + "dt": 2 + }, + "videos": 0, + "author_name": "三文娱", + "author_face": "http://i1.hdslb.com/bfs/face/98566839756a8e3de6e183109984b032de6ff2d9.jpg", + "author_mid": 34772409, + "view_at": 1593000539, + "progress": 0, + "badge": "专栏", + "show_title": "", + "duration": 0, + "current": "", + "total": 0, + "new_desc": "", + "is_finish": 0, + "is_fav": 0, + "kid": 6470274, + "tag_name": "", + "live_status": 0 + }, + { + "title": "从国际空间站俯瞰地球,静谧蓝星守护者", + "long_title": "", + "cover": "http://i0.hdslb.com/bfs/live/new_room_cover/f07d8a0c7c5655f81cf1586903a121f2680cf3bc.jpg", + "covers": null, + "uri": "https://live.bilibili.com/14047", + "history": { + "oid": 14047, + "epid": 0, + "bvid": "", + "page": 0, + "cid": 0, + "part": "", + "business": "live", + "dt": 2 + }, + "videos": 0, + "author_name": "Zelo-Balance", + "author_face": "http://i1.hdslb.com/bfs/face/7303b3032d1e13ca7c788cd9c30d4430f8ffd1ea.jpg", + "author_mid": 19193, + "view_at": 1592999822, + "progress": 0, + "badge": "直播中", + "show_title": "", + "duration": 0, + "current": "", + "total": 0, + "new_desc": "", + "is_finish": 0, + "is_fav": 0, + "kid": 14047, + "tag_name": "户外", + "live_status": 1 + }, + { + "title": "许巍 《蓝莲花》吉他Cover,这回你们不用截图抓我了吧", + "long_title": "", + "cover": "http://i2.hdslb.com/bfs/archive/0225b1f1a790393097ceebb51e89796be806d6bc.jpg", + "covers": null, + "uri": "", + "history": { + "oid": 883617049, + "epid": 0, + "bvid": "BV1sK4y147ob", + "page": 1, + "cid": 205017957, + "part": "许巍 《蓝莲花》 Cover_1", + "business": "archive", + "dt": 2 + }, + "videos": 1, + "author_name": "硬核拆解", + "author_face": "http://i1.hdslb.com/bfs/face/4e131c9609299303cdde882792fc62b9f99cdcde.jpg", + "author_mid": 427494870, + "view_at": 1592999572, + "progress": 13, + "badge": "", + "show_title": "", + "duration": 91, + "current": "", + "total": 0, + "new_desc": "", + "is_finish": 0, + "is_fav": 0, + "kid": 883617049, + "tag_name": "演奏", + "live_status": 0 + }, + { + "title": "从清楚与混沌之分看Vtuber形象塑造", + "long_title": "", + "cover": "", + "covers": [ + "https://i0.hdslb.com/bfs/article/5ddb94dd1890c639622717c7083fb2917b4aa475.jpg" + ], + "uri": "", + "history": { + "oid": 268656, + "epid": 0, + "bvid": "", + "page": 0, + "cid": 6233590, + "part": "", + "business": "article-list", + "dt": 2 + }, + "videos": 0, + "author_name": "普天一光", + "author_face": "http://i2.hdslb.com/bfs/face/3702810bdac3d5103d684e61dc5bc8492a74f904.jpg", + "author_mid": 6614889, + "view_at": 1592998686, + "progress": 0, + "badge": "专栏", + "show_title": "", + "duration": 0, + "current": "", + "total": 0, + "new_desc": "", + "is_finish": 0, + "is_fav": 0, + "kid": 268656, + "tag_name": "", + "live_status": 0 + }, + { + "title": "百妖谱", + "long_title": "庆忌(下)", + "cover": "http://i0.hdslb.com/bfs/archive/695a4566d05620a24c51d6eb935fa4767d673b45.jpg", + "covers": null, + "uri": "https://www.bilibili.com/bangumi/play/ss26193", + "history": { + "oid": 370908663, + "epid": 326789, + "bvid": "", + "page": 0, + "cid": 199204975, + "part": "", + "business": "pgc", + "dt": 3 + }, + "videos": 0, + "author_name": "", + "author_face": "", + "author_mid": 0, + "view_at": 1592985807, + "progress": 533, + "badge": "国创", + "show_title": "第8话 庆忌(下)", + "duration": 1402, + "current": "", + "total": 12, + "new_desc": "更新至第10话", + "is_finish": 0, + "is_fav": 0, + "kid": 26193, + "tag_name": "", + "live_status": 0 + } + ] + } +} +``` + +</details> + +## 获取视频观看历史记录_web端旧版 + +> https://api.bilibili.com/x/v2/history + +*请求方式:GET* + +认证方式:Cookie (SESSDATA) + +本接口也可以返回已失效稿件的信息 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ------- | +| pn | num | 页码 | 非必要 | 默认为1 | +| ps | num | 每页项数 | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | ------------ | ------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | array | 历史记录列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ------------------------------------------ | +| 0 | obj | 历史观看1 | | +| n | obj | 历史观看(n+1) | 按照观看顺序排列<br />项数为总计观看视频数 | +| …… | obj | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------------------- | ------- | ------------------------------ | ------------------------------------------------------------ | +| aid | num | 稿件avid | | +| videos | num | 视频分P总数 | 默认为1 | +| tid | num | 分区tid | | +| tname | str | 子分区名称 | | +| copyright | num | 是否转载 | 1:原创<br />2:转载<br />3:未填写 | +| pic | str | 视频封面图片url | | +| title | str | 稿件标题 | | +| pubdate | num | 稿件发布时间 | 时间戳 | +| ctime | num | 用户提交稿件的时间 | 时间戳 | +| desc | str | 视频简介 | | +| 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`对象 | +| dynamic | str | 视频同步发布的的动态的文字内容 | 无为空 | +| cid | num | 视频1P cid | | +| dimension | obj | 视频1P分辨率 | 略,见[获取视频详细信息(web端)](../video/info.md#获取视频详细信息(web端))中的`dimension`对象 | +| bangumi | obj | 番剧/影视信息 | 非番剧/影视无此项 | +| cheese | obj | 课程信息 | 非课程无此项 | +| favorite | bool | 是否已收藏 | true:已收藏<br />false:未收藏 | +| type | num | 视频属性 | 3:普通视频<br />4:剧集<br />10:课程 | +| sub_type | num | 附视频属性 | 0:普通视频<br />1:番剧<br />2:电影<br />3:纪录片<br />4:国创<br />5:电视剧<br />7:综艺 | +| device | num | 观看平台代码 | 1 3 5 7:手机端<br />2:web端<br />4 6:pad端<br />33:TV端<br />0:其他 | +| page | obj | 最后观看的分P信息 | | +| count | num | 分P数 | 非投稿视频无此项 | +| progress | num | 观看进度 | 单位为秒 | +| view_at | num | 观看时间 | 时间戳 | +| kid | num | 稿件avid | | +| business | str | 视频类型标识 | archive:用户投稿视频<br />pgc:番剧/影视<br />cheese:课程 | +| redirect_link | str | 重定向url | | +| bvid | str | 稿件bvid | | + +`data`数组中的对象`bangumi`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | --------------- | ------------ | +| cover | str | 番剧封面图片url | | +| ep_id | num | 番剧epid | | +| episode_status | num | ??? | | +| follow | num | 0 | 作用尚不明确 | +| long_title | str | 单集标题 | | +| season | obj | 剧集信息 | | +| title | str | 集数 | | + +`bangumi`中的`season`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | ------------ | ---------------------- | +| is_finish | num | 是否完结 | 0:连载中<br />1:完结 | +| newest_ep_id | num | 最细一话epid | | +| newest_ep_index | str | 最细一话集数 | | +| season_id | num | 番剧ssid | | +| season_status | num | ??? | | +| season_type | num | ??? | | +| title | str | 番剧标题 | | +| total_count | num | 总集数 | | + +`data`数组中的对象`cheese`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | --------------- | ---- | +| cover | str | 课程封面图片url | | +| long_title | str | 完整标题 | | +| number | str | 本集数 | | +| season_id | num | 课程ssid | | +| update_info | str | 总集数 | | + +**示例:** + +查询当前视频历史记录列表 + +```shell +curl -G 'https://api.bilibili.com/x/v2/history' \ +--data-urlencode 'ps=5' \ +--data-urlencode 'pn=1' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "aid": 96523832, + "videos": 1, + "tid": 33, + "tname": "连载动画", + "copyright": 2, + "pic": "http://i0.hdslb.com/bfs/archive/dfc29be381565ee041a0ec9cfc7a32f8a63f76cd.jpg", + "title": "【1月】异度侵入 ID:INVADED 12【独家正版】", + "pubdate": 1584289800, + "ctime": 1584289800, + "desc": "#12", + "state": 0, + "attribute": 338688, + "duration": 1481, + "redirect_url": "https://www.bilibili.com/bangumi/play/ep307457", + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 1, + "hd5": 1, + "no_reprint": 0, + "autoplay": 0, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0 + }, + "owner": { + "mid": 928123, + "name": "哔哩哔哩番剧", + "face": "http://i1.hdslb.com/bfs/face/7a8412cbacb9fd18f40ddbbf0ad183e45afc1365.jpg" + }, + "stat": { + "aid": 96523832, + "view": 4772927, + "danmaku": 108890, + "reply": 48584, + "favorite": 46, + "coin": 61768, + "share": 290, + "now_rank": 0, + "his_rank": 0, + "like": 1241, + "dislike": 0 + }, + "dynamic": "", + "cid": 164789275, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "favorite": false, + "type": 4, + "sub_type": 1, + "device": 3, + "page": { + "cid": 164789275, + "page": 1, + "from": "vupload", + "part": "ID_INVADED_112.encoded", + "duration": 1481, + "vid": "", + "weblink": "", + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + } + }, + "bangumi": { + "ep_id": 307457, + "title": "12", + "long_title": "CHANNELED", + "episode_status": 13, + "follow": 0, + "cover": "http://i0.hdslb.com/bfs/archive/dfc29be381565ee041a0ec9cfc7a32f8a63f76cd.jpg", + "season": { + "season_id": 29310, + "title": "异度侵入 ID:INVADED", + "season_status": 13, + "is_finish": 1, + "total_count": 13, + "newest_ep_id": 307774, + "newest_ep_index": "13", + "season_type": 1 + } + }, + "progress": 277, + "view_at": 1588831600, + "kid": 29310, + "business": "pgc", + "redirect_link": "https://www.bilibili.com/bangumi/play/ep307457", + "bvid": "BV1K7411f7uu" + }, + { + "aid": 497899395, + "videos": 1, + "tid": 189, + "tname": "电脑装机", + "copyright": 1, + "pic": "http://i0.hdslb.com/bfs/archive/fd4e0893b234ee729cf15198065eced98367ebfe.jpg", + "title": "600元的2007款iMac,如今过时了吗?", + "pubdate": 1587727345, + "ctime": 1587708111, + "desc": "苹果东西是真的保值,酷睿2现在都还能卖的这么贵。第一次使用4K画质进行拍摄,应该比以前清楚一些。如有问题请在评论区指出,谢谢!", + "state": 0, + "attribute": 16768, + "duration": 389, + "mission_id": 13106, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0 + }, + "owner": { + "mid": 3391089, + "name": "数字云糕Official", + "face": "http://i2.hdslb.com/bfs/face/238dfbca5dda5de2d5ba95ee4e99804714e2b5e2.jpg" + }, + "stat": { + "aid": 497899395, + "view": 23325, + "danmaku": 92, + "reply": 115, + "favorite": 195, + "coin": 132, + "share": 23, + "now_rank": 0, + "his_rank": 0, + "like": 555, + "dislike": 0 + }, + "dynamic": "#IMAC##APPLE##MAC# 苹果东西是真的保值,酷睿2现在都还能卖的这么贵。第一次使用4K画质进行拍摄,应该比以前清楚一些。", + "cid": 182570131, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "favorite": false, + "type": 3, + "sub_type": 0, + "device": 3, + "page": { + "cid": 182570131, + "page": 1, + "from": "vupload", + "part": "iMac", + "duration": 389, + "vid": "", + "weblink": "", + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + } + }, + "count": 1, + "progress": -1, + "view_at": 1588828357, + "kid": 497899395, + "business": "archive", + "redirect_link": "https://www.bilibili.com/video/av497899395", + "bvid": "BV1NK41157EF" + } + ] +} +``` + +</details> + +## 删除历史记录 + +> https://api.bilibili.com/x/v2/history/delete + +*请求方式:POST* + +认证方式:Cookie (SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | --------------------------------------------------- | ------ | ------------------------------------------------------------ | +| kid | str | 删除的目标记录,格式为`{业务类型}_{目标id}`详见备注 | 必要 | 视频:archive\_{稿件avid}<br />直播:live_{直播间id}<br />专栏:article\_{专栏cvid}<br />剧集:pgc\_{剧集ssid}<br />文集:article-list\_{文集rlid} | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf校验失败<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +删除视频`av540580868`的观看历史记录 + +```shell +curl 'https://api.bilibili.com/x/v2/history/delete' \ +--data-urlencode 'kid=archive_540580868' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +## 清空历史记录 + +> https://api.bilibili.com/x/v2/history/clear + +*请求方式:POST* + +认证方式:Cookie (SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------ | ------ | ---- | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf校验失败 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +清空历史记录 + +```shell +curl 'https://api.bilibili.com/x/v2/history/clear' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +## 停用历史记录 + +> https://api.bilibili.com/x/v2/history/shadow/set + +*请求方式:POST* + +认证方式:Cookie (SESSDATA) + +该操作不会影响原有历史记录 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------ | ------ | -------------------------------------------- | +| switch | bool | 停用开关 | 非必要 | true:停用<br />false:正常<br />默认为false | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf校验失败 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +停用历史记录功能 + +```shell +curl 'https://api.bilibili.com/x/v2/history/shadow/set' \ +--data-urlencode 'switch=true' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +## 查询历史记录停用状态 + +> https://api.bilibili.com/x/v2/history/shadow + +*请求方式:GET* + +认证方式:Cookie (SESSDATA) + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | bool | 停用状态 | true:停用<br />false:正常 | + +**示例:** + +当前状态为未停用视频历史记录 + +```shell +curl 'https://api.bilibili.com/x/v2/history/shadow' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": false +} +``` + +</details> diff --git a/bb-api-collect/docs/historytoview/toview.md b/bb-api-collect/docs/historytoview/toview.md new file mode 100644 index 0000000000..e44248a5c0 --- /dev/null +++ b/bb-api-collect/docs/historytoview/toview.md @@ -0,0 +1,462 @@ +# 稍后再看 + +<img src="../../assets/img/toview.png" width="25" height="20"/> + +## 视频添加稍后再看 + +> https://api.bilibili.com/x/v2/history/toview/add + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +最多添加100个视频 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------ | ------------ | ------------------ | +| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 | +| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf校验失败<br />-400:请求错误<br />90001:列表已满<br />90003:稿件已经被删除 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +添加视频`av41687433`/`BV1ht41147kj`到稍后再看列表 + +avid方式: + +```shell +curl 'https://api.bilibili.com/x/v2/history/toview/add' \ +--data-urlencode 'aid=41687433' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +bvid方式: + +```shell +curl 'https://api.bilibili.com/x/v2/history/toview/add' \ +--data-urlencode 'bvid=BV1ht41147kj' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +## 添加频道中所有视频到稍后再看 + +> https://space.bilibili.com/ajax/channel/addAllToView + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +鉴权方式:Cookie中`DedeUserID`及`DedeUserID__ckMd5`存在且不为0,referer为 `.bilibili.com`域名下 + +带有转义 + +超过容量后会截取容量之内的添加 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------ | ------ | ---- | +| cid | num | 目标频道id | 必要 | | +| mid | num | 目标频道所属的用户mid | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | -------- | --------------------------- | +| status | bool | 是否成功 | false:失败<br />true:成功 | +| data | str | 错误信息 | | + +**示例:** + +添加用户`mid=282994`下的频道`4693`中所有视频到稍后再看 + +```shell +curl 'https://space.bilibili.com/ajax/channel/addAllToView' \ +--data-urlencode 'cid=4693' \ +--data-urlencode 'mid=282994' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx;DedeUserID=1;DedeUserID__ckMd5=1;' +-e 'https://www.bilibili.com' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "status": true, + "data": "操作成功" +} +``` + +</details> + +## 获取稍后再看视频列表 + +> https://api.bilibili.com/x/v2/history/toview + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | data | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ------ | ---------------- | ---- | +| count | num | 稍后再看视频数 | | +| list | array | 稍后再看视频列表 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---------------------------------------------- | +| 0 | obj | 稍后再看1 | | +| n | obj | 稍后再看(n+1) | 按照添加顺序排列<br />项数为总计稍后再看视频数 | +| …… | obj | …… | …… | +| 99 | obj | 最后一项 | | + +`data`中的`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------------------- | ------- | ------------------------------ | ------------------------------------------------------------ | +| aid | num | 稿件avid | | +| videos | num | 稿件分P总数 | 默认为1 | +| tid | num | 分区tid | | +| tname | str | 子分区名称 | | +| copyright | num | 是否转载 | 1:原创<br />2:转载<br />3:未填写 | +| pic | str | 稿件封面图片url | | +| title | str | 稿件标题 | | +| pubdate | num | 稿件发布时间 | 时间戳 | +| ctime | num | 用户提交稿件的时间 | 时间戳 | +| desc | str | 视频简介 | | +| 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`对象 | +| dynamic | str | 视频同步发布的的动态的文字内容 | 无为空 | +| dimension | obj | 稿件1P分辨率 | 略,见[获取视频详细信息(web端)](../video/info.md#获取视频详细信息(web端))中的`dimension`对象 | +| count | num | 稿件分P数 | 非投稿视频无此项 | +| cid | num | 视频cid | | +| progress | num | 观看进度时间 | 单位为秒 | +| add_at | num | 添加时间 | 时间戳 | +| bvid | str | 稿件bvid | | + +**示例:** + +获取稍后再看视频列表 + +```shell +curl 'https://api.bilibili.com/x/v2/history/toview' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "count": 25, + "list": [ + { + "aid": 200333024, + "videos": 1, + "tid": 95, + "tname": "手机平板", + "copyright": 1, + "pic": "http://i1.hdslb.com/bfs/archive/a5e3072e670daec4c01a182aae91c1f85a48001e.jpg", + "title": "【山新】疫情下,配音演员怎么开工录音?", + "pubdate": 1586959137, + "ctime": 1586959137, + "desc": "疫情这段时间,配音演员们是怎么录音的呢=W=", + "state": 0, + "attribute": 16768, + "duration": 218, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0 + }, + "owner": { + "mid": 14082, + "name": "山新", + "face": "http://i0.hdslb.com/bfs/face/74c82caee6d9eb623e56161ea8ed6d68afabfeae.jpg" + }, + "stat": { + "aid": 200333024, + "view": 361123, + "danmaku": 1792, + "reply": 1376, + "favorite": 7571, + "coin": 12129, + "share": 895, + "now_rank": 0, + "his_rank": 0, + "like": 54705, + "dislike": 0 + }, + "dynamic": "疫情这段时间,配音演员们是怎么录音的呢=W=", + "dimension": { + "width": 3840, + "height": 2160, + "rotate": 0 + }, + "page": { + "cid": 178808041, + "page": 1, + "from": "vupload", + "part": "无标题", + "duration": 218, + "vid": "", + "weblink": "", + "dimension": { + "width": 3840, + "height": 2160, + "rotate": 0 + } + }, + "count": 1, + "cid": 178808041, + "progress": 32, + "add_at": 1587041785, + "bvid": "BV1Yz411B7n3" + }, + { + "aid": 710350011, + "videos": 1, + "tid": 124, + "tname": "趣味科普人文", + "copyright": 1, + "pic": "http://i0.hdslb.com/bfs/archive/c5b7e7c07a4abf27029c5afb3ab65fee4475b9a9.jpg", + "title": "不花一分钱建立自己的网站!给硬盘里的小姐姐换个新家!", + "pubdate": 1586919626, + "ctime": 1586898238, + "desc": "制作视频不易,你的点赞是对我最大的支持!\nUP主的个人网站:https://amdradeonrin.github.io/MIKU/\n视频提到的文件在网站有下载\nGitHub上的网站源码:https://github.com/AMDRadeonRin/MIKU", + "state": 0, + "attribute": 16768, + "duration": 169, + "mission_id": 13106, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0 + }, + "owner": { + "mid": 179757857, + "name": "GTX690战术核显卡导弹", + "face": "http://i2.hdslb.com/bfs/face/2504de8c1eeef22d91bbc45803f6b29afcbb0adf.jpg" + }, + "stat": { + "aid": 710350011, + "view": 3293, + "danmaku": 37, + "reply": 117, + "favorite": 355, + "coin": 76, + "share": 11, + "now_rank": 0, + "his_rank": 0, + "like": 325, + "dislike": 0 + }, + "dynamic": "#网页制作##HTML##网页#给你们科普一下怎么弄网站吧,你们也可以考虑整一个XD", + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "count": 1, + "cid": 0, + "progress": 0, + "add_at": 1587012410, + "bvid": "BV1LQ4y1T7Xh" + }, + ………… + ] + } +} +``` + +</details> + +## 删除稍后再看视频 + +> https://api.bilibili.com/x/v2/history/toview/del + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------ | ------ | ------------------------------------------------------------ | +| viewed | bool | 是否删除所有已观看的视频 | 非必要 | true:删除已观看视频<br />false:不删除已观看视频<br />默认为false | +| aid | num | 删除的目标记录的avid | 非必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf校验失败<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +删除视频`av540580868`的稍后再看记录 + +```shell +curl 'https://api.bilibili.com/x/v2/history/toview/del' \ +--data-urlencode 'aid=540580868' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +删除所有已观看的视频 + +```shell +curl 'https://api.bilibili.com/x/v2/history/toview/del' \ +--data-urlencode 'viewed=true' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> + +## 清空稍后再看视频列表 + +> https://api.bilibili.com/x/v2/history/toview/clear + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------ | ------ | ---- | +| csrf | num | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-101:账号未登录<br />-111:csrf校验失败 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +清空稍后再看视频列表 + +```shell +curl 'https://api.bilibili.com/x/v2/history/toview/clear' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +</details> diff --git a/bb-api-collect/docs/live/danmaku.md b/bb-api-collect/docs/live/danmaku.md new file mode 100644 index 0000000000..3171c476b5 --- /dev/null +++ b/bb-api-collect/docs/live/danmaku.md @@ -0,0 +1,1828 @@ +# 直播间弹幕 + +## 获取当前用户对应直播间可发弹幕配置 + +> https://api.live.bilibili.com/xlive/web-room/v1/dM/GetDMConfigByGroup + +*请求方式: GET* + +认证方式: Cookie (SESSDATA) + +未登录也可以获取,但颜色只有白色可用,模式只有滚动。 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---- | --- | --- | ---- | --- | +| room_id | num | 直播间id | 必要 | | +| web_location | str | (?) | 非必要 | 作用尚不明确 | +| w_rid | str | wbi签名 | 非必要 | 不强制需要 | +| wts | num | 秒时间戳 | 非必要 | 不强制需要 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0: 成功<br />-400: 参数错误 | +| data | obj | 信息本体 | | +| message | str | 错误信息 | | +| msg | str | 信息 | 成功时存在,为`""`(空字符串) | +| ttl | num | `1` | 成功时不存在 | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| group | arr | 弹幕颜色组 | | +| mode | arr | 弹幕显示模式 | | + +`data.group` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| name | str | 显示名称 | | +| sort | num | 用于排序 | | +| color | arr | 该组颜色列表 | | + +`data.group[i].color` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| name | str | 颜色名 | | +| color | str | 十进制颜色值 | 发送弹幕用 | +| color\_hex | str | 十六进制颜色值 | 发送弹幕用 | +| status | num | 可用状态 | 0: 不可用<br />1: 可用 | +| weight | num | (?) | 作用尚不明确 | +| color\_id | num | 颜色id? | | +| origin | num | (?) | | + +`data.mode` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| name | str | 模式名称 | | +| mode | num | 模式值 | 发送弹幕用 | +| type | str | 模式类型 | | +| status | num | 可用状态 | 0: 不可用<br />1: 可用 | + +**示例:** + +获取未登录用户在直播间 `1` 的弹幕配置可用情况 + +```shell +curl 'https://api.live.bilibili.com/xlive/web-room/v1/dM/GetDMConfigByGroup?room_id=1' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "group": [ + { + "name": "普", + "sort": 0, + "color": [ + { + "name": "白色", + "color": "16777215", + "color_hex": "ffffff", + "status": 1, + "weight": -9999, + "color_id": -9999, + "origin": 0 + } + ] + }, + { + "name": "航", + "sort": 100, + "color": [ + { + "name": "紫色", + "color": "14893055", + "color_hex": "e33fff", + "status": 0, + "weight": 0, + "color_id": 6, + "origin": 1 + } + ] + }, + { + "name": "粉", + "sort": 200, + "color": [ + { + "name": "松石绿", + "color": "5566168", + "color_hex": "54eed8", + "status": 0, + "weight": 99, + "color_id": 66, + "origin": 2 + }, + { + "name": "雨后蓝", + "color": "5816798", + "color_hex": "58c1de", + "status": 0, + "weight": 98, + "color_id": 67, + "origin": 2 + }, + { + "name": "星空蓝", + "color": "4546550", + "color_hex": "455ff6", + "status": 0, + "weight": 97, + "color_id": 68, + "origin": 2 + }, + { + "name": "紫罗兰", + "color": "9920249", + "color_hex": "975ef9", + "status": 0, + "weight": 96, + "color_id": 69, + "origin": 2 + }, + { + "name": "梦境红", + "color": "12802438", + "color_hex": "c35986", + "status": 0, + "weight": 95, + "color_id": 70, + "origin": 2 + }, + { + "name": "热力橙", + "color": "16747553", + "color_hex": "ff8c21", + "status": 0, + "weight": 94, + "color_id": 71, + "origin": 2 + }, + { + "name": "香槟金", + "color": "16774434", + "color_hex": "fff522", + "status": 0, + "weight": 93, + "color_id": 72, + "origin": 2 + } + ] + }, + { + "name": "爷", + "sort": 300, + "color": [ + { + "name": "红色", + "color": "16738408", + "color_hex": "ff6868", + "status": 0, + "weight": 0, + "color_id": 8, + "origin": 3 + }, + { + "name": "蓝色", + "color": "6737151", + "color_hex": "66ccff", + "status": 0, + "weight": 0, + "color_id": 7, + "origin": 3 + } + ] + }, + { + "name": "活", + "sort": 400, + "color": [ + { + "name": "盛典金", + "color": "16766720", + "color_hex": "ffd700", + "status": 0, + "weight": 100, + "color_id": 44, + "origin": 4 + }, + { + "name": "升腾蓝", + "color": "4286945", + "color_hex": "4169e1", + "status": 0, + "weight": 100, + "color_id": 43, + "origin": 4 + }, + { + "name": "青色", + "color": "65532", + "color_hex": "fffc", + "status": 0, + "weight": 0, + "color_id": 5, + "origin": 4 + }, + { + "name": "绿色", + "color": "8322816", + "color_hex": "7eff00", + "status": 0, + "weight": 0, + "color_id": 4, + "origin": 4 + }, + { + "name": "黄色弹幕", + "color": "16772431", + "color_hex": "ffed4f", + "status": 0, + "weight": 0, + "color_id": 3, + "origin": 4 + }, + { + "name": "橙色", + "color": "16750592", + "color_hex": "ff9800", + "status": 0, + "weight": 0, + "color_id": 2, + "origin": 4 + }, + { + "name": "粉色", + "color": "16741274", + "color_hex": "ff739a", + "status": 0, + "weight": 0, + "color_id": 1, + "origin": 4 + } + ] + } + ], + "mode": [ + { + "name": "滚动", + "mode": 1, + "type": "scroll", + "status": 1 + }, + { + "name": "底部", + "mode": 4, + "type": "bottom", + "status": 0 + }, + { + "name": "顶部", + "mode": 5, + "type": "top", + "status": 0 + } + ] + }, + "message": "", + "msg": "" +} +``` + +</details> + + +## 获取直播间最近历史弹幕 + +> https://api.live.bilibili.com/xlive/web-room/v1/dM/gethistory + +<!--{ + "from": { + "url": "https://www.bilibili.com/read/cv8186413/" + } +}--> + +*请求方式: GET* + +注: 该接口部分返回信息不明, 仅供参考, 来源 [cv8186413](https://www.bilibili.com/read/cv8186413/) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | ---- | --- | - | - | +| roomid | num | 直播间短ID | 必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0: 成功<br />-400: 请求错误 | +| message | str | 错误信息 | 默认为空 | +| msg | str | 空 | 仅请求成功时存在 | +| ttl | num | 1 | 仅请求失败时存在 | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| admin | array | 管理员最新的10条弹幕消息 | 格式与`room`相同 | +| room | array | 普通用户的10条弹幕信息 | 格式与`admin`相同 | + +`data`中的任意数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| text | str | 弹幕内容 | | +| dm_type | num | 弹幕类型 | | +| uid | num | 弹幕发送者的UID | | +| nickname | str | 弹幕发送者的昵称 | | +| uname_color | str | 弹幕发送者的昵称颜色? | | +| timeline | str | 弹幕发送时间 | 格式为`yyyy-MM-dd HH:mm:ss` | +| isadmin | num | 是否为管理员 | | +| vip | num | 是否为VIP? || +| svip | num | 是否为SVIP? || +| medal | array | 粉丝勋章信息? | 格式不明 | +| title | array | 标题? | 格式不明 | +| user_level | array | 用户等级信息? | 格式不明 | +| rank | num | 排名? | [用户空间详细信息](../user/info.md#获取用户详细信息) | +| teamid | num | | | +| rnd | str | 随机数种子? | | +| user_title | str | 用户头衔? |格式不明| +| guard_level | | 大航海等级? | | +| bubble | | | | +| bubble_color | | | | +| lpl | | | | +| yeah_space_url | | | | +| jump_to_url | | | | +| check_info | obj | 弹幕审核信息? | | +| voice_dm_info | obj | 语音弹幕信息? | | +| emoticon | obj | 房间独有表情信息 | | +| emots | obj | 默认表情信息 | 结构为`表情名-信息`组成的键值对<br />如果信息不含默认表情,则返回 null | +| id_str | str | 弹幕ID? | | +| wealth_level | num | 财富等级? | | +| bubble_id_v2 | num | | | +| reply | obj | 回复的弹幕 | | +| group_medal | null | | | +| user | obj | 该用户信息 || + +`data`对象中的`emoticon`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | ------------------------ | ---------------------------- | +| id | num | 0 | | +| emoticon_unique | str | 表情的独特标识 | 格式为`room_房间号_表情id` | +| text | text | 表情的触发词 | | +| perm | num | 发送权限? | 1:所有人都可发送 | +| url | str | 表情的图像链接 | | +| in_player_area | num | 是否显示在直播画面区域? | | +| bulge_display | num | 是否高亮显示? | | +| is_dynamic | num | 是否为动态表情 | 0:静态图像<br />1:动态图像 | +| height | num | 表情的高度 | | +| width | num | 表情的宽度 | | + +`data`对象中的`emots`对象中的任意一个值对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | ---------------- | ------------------------- | +| count | num | 重复发送数量 | | +| descript | str | 表情描述 | | +| emoji | str | 表情描述 | | +| emotion_id | num | 表情 id | | +| emotion_unique | str | 表情的独特标识符 | 格式可能为`emoji_表情 id` | +| height | num | 表情的宽度 | | +| url | str | 表情的图像链接 | | +| width | num | 表情的高度 | | + +`data`对象中的`user`对象: + +| 字段 | 类型 | 内容 | 备注 | +| - | - | --- | --- | +| uid | num | 用户 mid || +| base | obj | 用户基本信息 || +| medal | null | || +| wealth | null | || +| title | obj | 用户标题? || +| guard | null | || +| uhead_frame | null | || +| guard_leader | obj | | | + +`data`对象中的`user`对象中的`base`对象: + +| 字段 | 类型 | 内容 | 备注 | +| - | - | --- | --- | +| name | str | 用户名 || +| face | str | 用户头像 url || +| name_color | num | 用户名颜色? || +| is_mystery | bool | 是否为神秘用户? || +| risk_ctrl_info | null | | | +| origin_info | obj | 原始信息? | | +| official_info | obj | 认证信息 | | +| name_color_str | str | | | + +**示例:** + +```shell +curl -G 'https://api.live.bilibili.com/xlive/web-room/v1/dM/gethistory' \ +--url-query 'roomid=1' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "admin": [], + "room": [ + { + "text": "‫", + "dm_type": 0, + "uid": 20276964, + "nickname": "咸菜拉面", + "uname_color": "", + "timeline": "2024-08-15 05:05:06", + "isadmin": 0, + "vip": 0, + "svip": 0, + "medal": [ + 27, + "小孩梓", + "阿梓从小就很可爱", + 80397, + 398668, + "", + 0, + 6809855, + 398668, + 6850801, + 3, + 1, + 7706705 + ], + "title": [ + "title-86-1", + "title-86-1" + ], + "user_level": [ + 59, + 0, + 16752445, + 931 + ], + "rank": 10000, + "teamid": 0, + "rnd": "1723669505", + "user_title": "title-86-1", + "guard_level": 0, + "bubble": 0, + "bubble_color": "", + "lpl": 0, + "yeah_space_url": "", + "jump_to_url": "", + "check_info": { + "ts": 1723669506, + "ct": "18434F3D" + }, + "voice_dm_info": { + "voice_url": "", + "file_format": "", + "text": "", + "file_duration": 0, + "file_id": "" + }, + "emoticon": { + "id": 0, + "emoticon_unique": "", + "text": "", + "perm": 0, + "url": "", + "in_player_area": 0, + "bulge_display": 0, + "is_dynamic": 0, + "height": 0, + "width": 0 + }, + "emots": null, + "id_str": "74368f428dfaec806cd205e62866bd1c45", + "wealth_level": 37, + "bubble_id_v2": 0, + "reply": { + "show_reply": true, + "reply_mid": 0, + "reply_uname": "", + "reply_uname_color": "", + "reply_is_mystery": false + }, + "group_medal": null, + "user": { + "uid": 20276964, + "base": { + "name": "咸菜拉面", + "face": "https://i0.hdslb.com/bfs/face/182b73f6b6274fcee7491219f511b1748c4bc712.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": null, + "origin_info": { + "name": "咸菜拉面", + "face": "https://i0.hdslb.com/bfs/face/182b73f6b6274fcee7491219f511b1748c4bc712.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": { + "name": "小孩梓", + "level": 27, + "color_start": 398668, + "color_end": 6850801, + "color_border": 6809855, + "color": 398668, + "id": 13139, + "typ": 0, + "is_light": 1, + "ruid": 7706705, + "guard_level": 3, + "score": 50112778, + "guard_icon": "https://i0.hdslb.com/bfs/live/143f5ec3003b4080d1b5f817a9efdca46d631945.png", + "honor_icon": "", + "v2_medal_color_start": "#4775EFCC", + "v2_medal_color_end": "#4775EFCC", + "v2_medal_color_border": "#58A1F8FF", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + }, + "wealth": null, + "title": { + "old_title_css_id": "title-86-1", + "title_css_id": "title-86-1" + }, + "guard": null, + "uhead_frame": null, + "guard_leader": { + "is_guard_leader": false + } + } + }, + { + "text": "‫", + "dm_type": 0, + "uid": 20276964, + "nickname": "咸菜拉面", + "uname_color": "", + "timeline": "2024-08-16 05:05:06", + "isadmin": 0, + "vip": 0, + "svip": 0, + "medal": [ + 27, + "小孩梓", + "阿梓从小就很可爱", + 80397, + 398668, + "", + 0, + 6809855, + 398668, + 6850801, + 3, + 1, + 7706705 + ], + "title": [ + "title-86-1", + "title-86-1" + ], + "user_level": [ + 59, + 0, + 16752445, + 931 + ], + "rank": 10000, + "teamid": 0, + "rnd": "1723755905", + "user_title": "title-86-1", + "guard_level": 0, + "bubble": 0, + "bubble_color": "", + "lpl": 0, + "yeah_space_url": "", + "jump_to_url": "", + "check_info": { + "ts": 1723755906, + "ct": "F65D229F" + }, + "voice_dm_info": { + "voice_url": "", + "file_format": "", + "text": "", + "file_duration": 0, + "file_id": "" + }, + "emoticon": { + "id": 0, + "emoticon_unique": "", + "text": "", + "perm": 0, + "url": "", + "in_player_area": 0, + "bulge_display": 0, + "is_dynamic": 0, + "height": 0, + "width": 0 + }, + "emots": null, + "id_str": "7f3bb90826ad642012a31368f266be6d2", + "wealth_level": 37, + "bubble_id_v2": 0, + "reply": { + "show_reply": true, + "reply_mid": 0, + "reply_uname": "", + "reply_uname_color": "", + "reply_is_mystery": false + }, + "group_medal": null, + "user": { + "uid": 20276964, + "base": { + "name": "咸菜拉面", + "face": "https://i0.hdslb.com/bfs/face/182b73f6b6274fcee7491219f511b1748c4bc712.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": null, + "origin_info": { + "name": "咸菜拉面", + "face": "https://i0.hdslb.com/bfs/face/182b73f6b6274fcee7491219f511b1748c4bc712.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": { + "name": "小孩梓", + "level": 27, + "color_start": 398668, + "color_end": 6850801, + "color_border": 6809855, + "color": 398668, + "id": 13139, + "typ": 0, + "is_light": 1, + "ruid": 7706705, + "guard_level": 3, + "score": 50112778, + "guard_icon": "https://i0.hdslb.com/bfs/live/143f5ec3003b4080d1b5f817a9efdca46d631945.png", + "honor_icon": "", + "v2_medal_color_start": "#4775EFCC", + "v2_medal_color_end": "#4775EFCC", + "v2_medal_color_border": "#58A1F8FF", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + }, + "wealth": null, + "title": { + "old_title_css_id": "title-86-1", + "title_css_id": "title-86-1" + }, + "guard": null, + "uhead_frame": null, + "guard_leader": { + "is_guard_leader": false + } + } + }, + { + "text": "好帅", + "dm_type": 0, + "uid": 3546708493469870, + "nickname": "aodun1", + "uname_color": "", + "timeline": "2024-08-16 22:33:28", + "isadmin": 0, + "vip": 0, + "svip": 0, + "medal": [], + "title": [ + "", + "" + ], + "user_level": [ + 0, + 0, + 9868950, + ">50000" + ], + "rank": 10000, + "teamid": 0, + "rnd": "1723811729", + "user_title": "", + "guard_level": 0, + "bubble": 0, + "bubble_color": "", + "lpl": 0, + "yeah_space_url": "", + "jump_to_url": "", + "check_info": { + "ts": 1723818808, + "ct": "1B75FB" + }, + "voice_dm_info": { + "voice_url": "", + "file_format": "", + "text": "", + "file_duration": 0, + "file_id": "" + }, + "emoticon": { + "id": 0, + "emoticon_unique": "", + "text": "", + "perm": 0, + "url": "", + "in_player_area": 0, + "bulge_display": 0, + "is_dynamic": 0, + "height": 0, + "width": 0 + }, + "emots": null, + "id_str": "088336a59eb277942ee353dd6666bf6347", + "wealth_level": 0, + "bubble_id_v2": 0, + "reply": { + "show_reply": true, + "reply_mid": 0, + "reply_uname": "", + "reply_uname_color": "", + "reply_is_mystery": false + }, + "group_medal": null, + "user": { + "uid": 3546708493469870, + "base": { + "name": "aodun1", + "face": "https://i2.hdslb.com/bfs/face/6fb05f895d854e68419d45eef2c2e272b04ad25f.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": null, + "origin_info": { + "name": "aodun1", + "face": "https://i2.hdslb.com/bfs/face/6fb05f895d854e68419d45eef2c2e272b04ad25f.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": null, + "wealth": null, + "title": { + "old_title_css_id": "", + "title_css_id": "" + }, + "guard": null, + "uhead_frame": null, + "guard_leader": { + "is_guard_leader": false + } + } + }, + { + "text": "好帅", + "dm_type": 0, + "uid": 3546708493469870, + "nickname": "aodun1", + "uname_color": "", + "timeline": "2024-08-16 22:35:16", + "isadmin": 0, + "vip": 0, + "svip": 0, + "medal": [], + "title": [ + "", + "" + ], + "user_level": [ + 0, + 0, + 9868950, + ">50000" + ], + "rank": 10000, + "teamid": 0, + "rnd": "1723811729", + "user_title": "", + "guard_level": 0, + "bubble": 0, + "bubble_color": "", + "lpl": 0, + "yeah_space_url": "", + "jump_to_url": "", + "check_info": { + "ts": 1723818916, + "ct": "D6ABF2E7" + }, + "voice_dm_info": { + "voice_url": "", + "file_format": "", + "text": "", + "file_duration": 0, + "file_id": "" + }, + "emoticon": { + "id": 0, + "emoticon_unique": "", + "text": "", + "perm": 0, + "url": "", + "in_player_area": 0, + "bulge_display": 0, + "is_dynamic": 0, + "height": 0, + "width": 0 + }, + "emots": null, + "id_str": "6f421255746f5d8e4731fdadac66bf6356", + "wealth_level": 0, + "bubble_id_v2": 0, + "reply": { + "show_reply": true, + "reply_mid": 0, + "reply_uname": "", + "reply_uname_color": "", + "reply_is_mystery": false + }, + "group_medal": null, + "user": { + "uid": 3546708493469870, + "base": { + "name": "aodun1", + "face": "https://i2.hdslb.com/bfs/face/6fb05f895d854e68419d45eef2c2e272b04ad25f.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": null, + "origin_info": { + "name": "aodun1", + "face": "https://i2.hdslb.com/bfs/face/6fb05f895d854e68419d45eef2c2e272b04ad25f.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": null, + "wealth": null, + "title": { + "old_title_css_id": "", + "title_css_id": "" + }, + "guard": null, + "uhead_frame": null, + "guard_leader": { + "is_guard_leader": false + } + } + }, + { + "text": "好帅", + "dm_type": 0, + "uid": 3546708493469870, + "nickname": "aodun1", + "uname_color": "", + "timeline": "2024-08-16 22:36:51", + "isadmin": 0, + "vip": 0, + "svip": 0, + "medal": [], + "title": [ + "", + "" + ], + "user_level": [ + 0, + 0, + 9868950, + ">50000" + ], + "rank": 10000, + "teamid": 0, + "rnd": "1723811729", + "user_title": "", + "guard_level": 0, + "bubble": 0, + "bubble_color": "", + "lpl": 0, + "yeah_space_url": "", + "jump_to_url": "", + "check_info": { + "ts": 1723819011, + "ct": "1B6978C1" + }, + "voice_dm_info": { + "voice_url": "", + "file_format": "", + "text": "", + "file_duration": 0, + "file_id": "" + }, + "emoticon": { + "id": 0, + "emoticon_unique": "", + "text": "", + "perm": 0, + "url": "", + "in_player_area": 0, + "bulge_display": 0, + "is_dynamic": 0, + "height": 0, + "width": 0 + }, + "emots": null, + "id_str": "270f5a2ac69c5904617873cc4666bf640", + "wealth_level": 0, + "bubble_id_v2": 0, + "reply": { + "show_reply": true, + "reply_mid": 0, + "reply_uname": "", + "reply_uname_color": "", + "reply_is_mystery": false + }, + "group_medal": null, + "user": { + "uid": 3546708493469870, + "base": { + "name": "aodun1", + "face": "https://i2.hdslb.com/bfs/face/6fb05f895d854e68419d45eef2c2e272b04ad25f.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": null, + "origin_info": { + "name": "aodun1", + "face": "https://i2.hdslb.com/bfs/face/6fb05f895d854e68419d45eef2c2e272b04ad25f.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": null, + "wealth": null, + "title": { + "old_title_css_id": "", + "title_css_id": "" + }, + "guard": null, + "uhead_frame": null, + "guard_leader": { + "is_guard_leader": false + } + } + }, + { + "text": "好帅", + "dm_type": 0, + "uid": 3546708493469870, + "nickname": "aodun1", + "uname_color": "", + "timeline": "2024-08-16 22:39:01", + "isadmin": 0, + "vip": 0, + "svip": 0, + "medal": [], + "title": [ + "", + "" + ], + "user_level": [ + 0, + 0, + 9868950, + ">50000" + ], + "rank": 10000, + "teamid": 0, + "rnd": "1723811729", + "user_title": "", + "guard_level": 0, + "bubble": 0, + "bubble_color": "", + "lpl": 0, + "yeah_space_url": "", + "jump_to_url": "", + "check_info": { + "ts": 1723819141, + "ct": "143613AF" + }, + "voice_dm_info": { + "voice_url": "", + "file_format": "", + "text": "", + "file_duration": 0, + "file_id": "" + }, + "emoticon": { + "id": 0, + "emoticon_unique": "", + "text": "", + "perm": 0, + "url": "", + "in_player_area": 0, + "bulge_display": 0, + "is_dynamic": 0, + "height": 0, + "width": 0 + }, + "emots": null, + "id_str": "002ebbdc402b3d625052865f7b66bf6469", + "wealth_level": 0, + "bubble_id_v2": 0, + "reply": { + "show_reply": true, + "reply_mid": 0, + "reply_uname": "", + "reply_uname_color": "", + "reply_is_mystery": false + }, + "group_medal": null, + "user": { + "uid": 3546708493469870, + "base": { + "name": "aodun1", + "face": "https://i2.hdslb.com/bfs/face/6fb05f895d854e68419d45eef2c2e272b04ad25f.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": null, + "origin_info": { + "name": "aodun1", + "face": "https://i2.hdslb.com/bfs/face/6fb05f895d854e68419d45eef2c2e272b04ad25f.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": null, + "wealth": null, + "title": { + "old_title_css_id": "", + "title_css_id": "" + }, + "guard": null, + "uhead_frame": null, + "guard_leader": { + "is_guard_leader": false + } + } + }, + { + "text": "赚麻了 哈哈", + "dm_type": 0, + "uid": 243082910, + "nickname": "可人的樱花", + "uname_color": "", + "timeline": "2024-08-17 01:00:49", + "isadmin": 0, + "vip": 0, + "svip": 0, + "medal": [], + "title": [ + "", + "" + ], + "user_level": [ + 0, + 0, + 9868950, + ">50000" + ], + "rank": 10000, + "teamid": 0, + "rnd": "1723379161", + "user_title": "", + "guard_level": 0, + "bubble": 0, + "bubble_color": "", + "lpl": 0, + "yeah_space_url": "", + "jump_to_url": "", + "check_info": { + "ts": 1723827649, + "ct": "3917D4D7" + }, + "voice_dm_info": { + "voice_url": "", + "file_format": "", + "text": "", + "file_duration": 0, + "file_id": "" + }, + "emoticon": { + "id": 0, + "emoticon_unique": "", + "text": "", + "perm": 0, + "url": "", + "in_player_area": 0, + "bulge_display": 0, + "is_dynamic": 0, + "height": 0, + "width": 0 + }, + "emots": null, + "id_str": "03f3261e144366383c49c6b5d166bf8563", + "wealth_level": 7, + "bubble_id_v2": 0, + "reply": { + "show_reply": true, + "reply_mid": 0, + "reply_uname": "", + "reply_uname_color": "", + "reply_is_mystery": false + }, + "group_medal": null, + "user": { + "uid": 243082910, + "base": { + "name": "可人的樱花", + "face": "http://i2.hdslb.com/bfs/face/5faa9bef952f831236b740932c559476658f88e5.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": null, + "origin_info": { + "name": "可人的樱花", + "face": "http://i2.hdslb.com/bfs/face/5faa9bef952f831236b740932c559476658f88e5.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": null, + "wealth": null, + "title": { + "old_title_css_id": "", + "title_css_id": "" + }, + "guard": null, + "uhead_frame": null, + "guard_leader": { + "is_guard_leader": false + } + } + }, + { + "text": "‫", + "dm_type": 0, + "uid": 20276964, + "nickname": "咸菜拉面", + "uname_color": "", + "timeline": "2024-08-17 05:05:07", + "isadmin": 0, + "vip": 0, + "svip": 0, + "medal": [ + 27, + "小孩梓", + "阿梓从小就很可爱", + 80397, + 398668, + "", + 0, + 6809855, + 398668, + 6850801, + 3, + 1, + 7706705 + ], + "title": [ + "title-86-1", + "title-86-1" + ], + "user_level": [ + 59, + 0, + 16752445, + 931 + ], + "rank": 10000, + "teamid": 0, + "rnd": "1723842307", + "user_title": "title-86-1", + "guard_level": 0, + "bubble": 0, + "bubble_color": "", + "lpl": 0, + "yeah_space_url": "", + "jump_to_url": "", + "check_info": { + "ts": 1723842307, + "ct": "8B947ABC" + }, + "voice_dm_info": { + "voice_url": "", + "file_format": "", + "text": "", + "file_duration": 0, + "file_id": "" + }, + "emoticon": { + "id": 0, + "emoticon_unique": "", + "text": "", + "perm": 0, + "url": "", + "in_player_area": 0, + "bulge_display": 0, + "is_dynamic": 0, + "height": 0, + "width": 0 + }, + "emots": null, + "id_str": "1a928b968afaa7825ea506ffe566bfbf16", + "wealth_level": 37, + "bubble_id_v2": 0, + "reply": { + "show_reply": true, + "reply_mid": 0, + "reply_uname": "", + "reply_uname_color": "", + "reply_is_mystery": false + }, + "group_medal": null, + "user": { + "uid": 20276964, + "base": { + "name": "咸菜拉面", + "face": "https://i0.hdslb.com/bfs/face/182b73f6b6274fcee7491219f511b1748c4bc712.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": null, + "origin_info": { + "name": "咸菜拉面", + "face": "https://i0.hdslb.com/bfs/face/182b73f6b6274fcee7491219f511b1748c4bc712.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": { + "name": "小孩梓", + "level": 27, + "color_start": 398668, + "color_end": 6850801, + "color_border": 6809855, + "color": 398668, + "id": 13139, + "typ": 0, + "is_light": 1, + "ruid": 7706705, + "guard_level": 3, + "score": 50112778, + "guard_icon": "https://i0.hdslb.com/bfs/live/143f5ec3003b4080d1b5f817a9efdca46d631945.png", + "honor_icon": "", + "v2_medal_color_start": "#4775EFCC", + "v2_medal_color_end": "#4775EFCC", + "v2_medal_color_border": "#58A1F8FF", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + }, + "wealth": null, + "title": { + "old_title_css_id": "title-86-1", + "title_css_id": "title-86-1" + }, + "guard": null, + "uhead_frame": null, + "guard_leader": { + "is_guard_leader": false + } + } + }, + { + "text": "下播啦~ 感谢大家的陪伴~ 下次见哦~", + "dm_type": 0, + "uid": 3546614675278489, + "nickname": "机器人管家_鱼", + "uname_color": "", + "timeline": "2024-08-18 00:07:36", + "isadmin": 0, + "vip": 0, + "svip": 0, + "medal": [ + 21, + "赴神明", + "Mr_钟明", + 27751673, + 1725515, + "", + 0, + 12632256, + 12632256, + 12632256, + 0, + 0, + 3493291261692485 + ], + "title": [ + "", + "" + ], + "user_level": [ + 11, + 0, + 6406234, + ">50000" + ], + "rank": 10000, + "teamid": 0, + "rnd": "1723910862", + "user_title": "", + "guard_level": 0, + "bubble": 0, + "bubble_color": "", + "lpl": 0, + "yeah_space_url": "", + "jump_to_url": "", + "check_info": { + "ts": 1723910856, + "ct": "9BD05026" + }, + "voice_dm_info": { + "voice_url": "", + "file_format": "", + "text": "", + "file_duration": 0, + "file_id": "" + }, + "emoticon": { + "id": 0, + "emoticon_unique": "", + "text": "", + "perm": 0, + "url": "", + "in_player_area": 0, + "bulge_display": 0, + "is_dynamic": 0, + "height": 0, + "width": 0 + }, + "emots": null, + "id_str": "2ee6101973eeb69931eb86ac7e66c0ca17", + "wealth_level": 23, + "bubble_id_v2": 0, + "reply": { + "show_reply": true, + "reply_mid": 0, + "reply_uname": "", + "reply_uname_color": "", + "reply_is_mystery": false + }, + "group_medal": null, + "user": { + "uid": 3546614675278489, + "base": { + "name": "机器人管家_鱼", + "face": "https://i1.hdslb.com/bfs/face/de737cd746a96742c07ced6c213aa25cf0429d90.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": null, + "origin_info": { + "name": "机器人管家_鱼", + "face": "https://i1.hdslb.com/bfs/face/de737cd746a96742c07ced6c213aa25cf0429d90.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": { + "name": "赴神明", + "level": 21, + "color_start": 12632256, + "color_end": 12632256, + "color_border": 12632256, + "color": 1725515, + "id": 1231122, + "typ": 0, + "is_light": 0, + "ruid": 3493291261692485, + "guard_level": 0, + "score": 50001573, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#919298CC", + "v2_medal_color_end": "#919298CC", + "v2_medal_color_border": "#919298CC", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#6C6C7299", + "user_receive_count": 0 + }, + "wealth": null, + "title": { + "old_title_css_id": "", + "title_css_id": "" + }, + "guard": null, + "uhead_frame": null, + "guard_leader": { + "is_guard_leader": false + } + } + }, + { + "text": "‫", + "dm_type": 0, + "uid": 20276964, + "nickname": "咸菜拉面", + "uname_color": "", + "timeline": "2024-08-18 05:05:05", + "isadmin": 0, + "vip": 0, + "svip": 0, + "medal": [ + 27, + "小孩梓", + "阿梓从小就很可爱", + 80397, + 398668, + "", + 0, + 6809855, + 398668, + 6850801, + 3, + 1, + 7706705 + ], + "title": [ + "title-86-1", + "title-86-1" + ], + "user_level": [ + 59, + 0, + 16752445, + 931 + ], + "rank": 10000, + "teamid": 0, + "rnd": "1723928706", + "user_title": "title-86-1", + "guard_level": 0, + "bubble": 0, + "bubble_color": "", + "lpl": 0, + "yeah_space_url": "", + "jump_to_url": "", + "check_info": { + "ts": 1723928705, + "ct": "8A379FF4" + }, + "voice_dm_info": { + "voice_url": "", + "file_format": "", + "text": "", + "file_duration": 0, + "file_id": "" + }, + "emoticon": { + "id": 0, + "emoticon_unique": "", + "text": "", + "perm": 0, + "url": "", + "in_player_area": 0, + "bulge_display": 0, + "is_dynamic": 0, + "height": 0, + "width": 0 + }, + "emots": null, + "id_str": "41e8b55dea381d494cfe60ba3466c11064", + "wealth_level": 37, + "bubble_id_v2": 0, + "reply": { + "show_reply": true, + "reply_mid": 0, + "reply_uname": "", + "reply_uname_color": "", + "reply_is_mystery": false + }, + "group_medal": null, + "user": { + "uid": 20276964, + "base": { + "name": "咸菜拉面", + "face": "https://i0.hdslb.com/bfs/face/182b73f6b6274fcee7491219f511b1748c4bc712.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": null, + "origin_info": { + "name": "咸菜拉面", + "face": "https://i0.hdslb.com/bfs/face/182b73f6b6274fcee7491219f511b1748c4bc712.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": { + "name": "小孩梓", + "level": 27, + "color_start": 398668, + "color_end": 6850801, + "color_border": 6809855, + "color": 398668, + "id": 13139, + "typ": 0, + "is_light": 1, + "ruid": 7706705, + "guard_level": 3, + "score": 50112778, + "guard_icon": "https://i0.hdslb.com/bfs/live/143f5ec3003b4080d1b5f817a9efdca46d631945.png", + "honor_icon": "", + "v2_medal_color_start": "#4775EFCC", + "v2_medal_color_end": "#4775EFCC", + "v2_medal_color_border": "#58A1F8FF", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + }, + "wealth": null, + "title": { + "old_title_css_id": "title-86-1", + "title_css_id": "title-86-1" + }, + "guard": null, + "uhead_frame": null, + "guard_leader": { + "is_guard_leader": false + } + } + } + ] + }, + "message": "", + "msg": "" +} +``` + +</details> + +## 设置弹幕样式 + +> https://api.live.bilibili.com/xlive/web-room/v1/dM/AjaxSetConfig + +*请求方式: POST* + +认证方式: Cookie (SESSDATA) + +鉴权方式: Cookie中`bili_jct`的值正确并与`csrf`相同 + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---- | --- | --- | ---- | --- | +| csrf | str | CSRF Token(位于cookie) | 必要 | | +| csrf\_token | str | 同csrf | 非必要 | | +| room\_id | num | 直播间id | 必要 | | +| color | str | 颜色值 | 必要(可选) | color和mode任选一个 | +| mode | num | 弹幕模式 | 必要(可选) | color和mode任选一个 | + +注1: 抓取到的color格式是`"0x"+六位十六进制小写颜色值`,实际不需要`0x`,且不区分大小写。 + +注2: 若color和mode同时存在将只处理color,mode将被忽略。(见[#1236(comment)](https://github.com/SocialSisterYi/bilibili-API-collect/issues/1236#issuecomment-2849019923)) + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0: 成功<br />-101: 账号未登录<br />-500: 未达到使用条件<br />10064002: 参数错误<br />10065107: 颜色不存在 | +| message | str | 错误信息 | | +| ttl | num | `1` | | +| data | obj | 信息本体 | 部分情况不存在,10064002时为`null` | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| status | num | 同code | | +| msg | str | 提示信息 | 成功时有内容 | +| roomid | num | 直播间id | | + +**示例:** + +更改直播间 `1017` 的弹幕颜色为白色 + +```shell +curl 'https://api.live.bilibili.com/xlive/web-room/v1/dM/AjaxSetConfig' \ + --data-urlencode 'room_id=1017' \ + --data-urlencode 'color=0xffffff' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx;bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code":0, + "message":"0", + "ttl":1, + "data":{ + "status":0, + "msg":"设置成功~", + "roomid":1017 + } +} +``` + +</details> + +## 发送直播弹幕 + +> https://api.live.bilibili.com/msg/send + +*请求方式: POST* + +认证方式: Cookie (SESSDATA) + +鉴权方式: Cookie中`bili_jct`的值正确并与`csrf`相同 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | ---- | --- | ----- | --- | +| w_rid | str | wbi签名 | 非必要 | 不强制需要 | +| wts | num | Unix 秒时间戳 | 非必要 | 不强制需要 | + +**正文参数 (`application/x-www-form-urlencoded`或`multipart/form-data`):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---- | --- | --- | ---- | --- | +| csrf | str | CSRF Token(位于cookie) | 必要 | | +| roomid | num | 直播间id | 必要 | | +| msg | str | 弹幕内容 | 必要 | | +| rnd | num | 当前 Unix 秒时间戳 | 必要 | | +| fontsize | num | 字体大小 | 必要 | 默认为`25` | +| color | num | 十进制颜色值 | 必要 | 实际无效果 | +| mode | num | 展示模式 | 非必要 | 默认为`1` | +| bubble | num | (?) | 非必要 | 值为`0` | +| room\_type | num | (?) | 非必要 | `0` | +| jumpfrom | num | (?) | 非必要 | `0` | +| reply\_mid | num | 要“@”的用户mid | 非必要 | 默认为`0` | +| reply\_attr | num | (?) | 非必要 | `0` | +| reply\_uname | str | 要“@”的用户名称 | 非必要 | 默认为`""`,提供reply\_mid时不需要提供 | +| replay\_dmid | str | 要回复的弹幕id | 非必要 | 默认为`""` | +| statistics | str | (?) | 非必要 | `{"appId":100,"platform":5}` | +| csrf_token | str | 同csrf | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | `-101`:账号未登录<br />`-111`:csrf 校验失败<br />`-400`:请求错误,带有必须参数的信息<br />`1003212`:超出限制长度<br />`10031`:发送频率过快 | +| message | str | 错误信息 | | +| msg | str | 同`message` | | +| data | obj | 信息本体 | | +| ttl | num | `1` | 在小于0的code中存在 | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| mode_info | obj | 弹幕信息 | | +| dm_v2 | null | v2弹幕 | | + +`data.mode_info` 对象: + +基本上与[直播间信息流#弹幕 (DANMU_MSG)](message_stream.md#弹幕-danmu_msg)的`info[0][15]`对象相同。 + +**示例:** + +给直播间 `1899237171` 发送内容为 `QwQ` 的弹幕 + +```shell +curl 'https://api.live.bilibili.com/msg/send' \ + --data-urlencode 'roomid=1899237171' \ + --data-urlencode 'msg=QwQ' \ + --data-urlencode 'rnd=1744956003' \ + --data-urlencode 'fontsize=25' + --data-urlencode 'color=16777215' + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx;bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code":0, + "data":{ + "mode_info":{ + "mode":0, + "show_player_type":0, + "extra":"{\"send_from_me\":true,\"master_player_hidden\":false,\"mode\":0,\"color\":16777215,\"dm_type\":0,\"font_size\":25,\"player_mode\":1,\"show_player_type\":0,\"content\":\"QwQ\",\"user_hash\":\"2402762465\",\"emoticon_unique\":\"\",\"bulge_display\":0,\"recommend_score\":7,\"main_state_dm_color\":\"\",\"objective_state_dm_color\":\"\",\"direction\":0,\"pk_direction\":0,\"quartet_direction\":0,\"anniversary_crowd\":0,\"yeah_space_type\":\"\",\"yeah_space_url\":\"\",\"jump_to_url\":\"\",\"space_type\":\"\",\"space_url\":\"\",\"animation\":{},\"emots\":null,\"is_audited\":false,\"id_str\":\"4e3ed8ede9409b234b5e1d64c06801ea3119\",\"icon\":null,\"show_reply\":true,\"reply_mid\":0,\"reply_uname\":\"\",\"reply_uname_color\":\"\",\"reply_is_mystery\":false,\"reply_type_enum\":0,\"hit_combo\":0,\"esports_jump_url\":\"\"}", + "user":{ + "uid":438160221, + "base":{ + "name":"weatfe", + "face":"https://i0.hdslb.com/bfs/face/member/noface.jpg", + "name_color":0, + "is_mystery":false, + "risk_ctrl_info":null, + "origin_info":{ + "name":"weatfe", + "face":"https://i0.hdslb.com/bfs/face/member/noface.jpg" + }, + "official_info":{ + "role":0, + "title":"", + "desc":"", + "type":-1 + }, + "name_color_str":"" + }, + "medal":null, + "wealth":null, + "title":{ + "old_title_css_id":"", + "title_css_id":"" + }, + "guard":null, + "uhead_frame":null, + "guard_leader":{ + "is_guard_leader":false + } + } + }, + "dm_v2":null + }, + "message":"", + "msg":"" +} +``` + +</details> diff --git a/bb-api-collect/docs/live/emoticons.md b/bb-api-collect/docs/live/emoticons.md new file mode 100644 index 0000000000..75ee998dd7 --- /dev/null +++ b/bb-api-collect/docs/live/emoticons.md @@ -0,0 +1,927 @@ +# 直播间表情 + +## 获取直播间的表情包 + +> https://api.live.bilibili.com/xlive/web-ucenter/v2/emoticon/GetEmoticons + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ------ | ---------- | ------ | ---- | +| platform | string | 平台 | 必要 | 已知: `pc``android` `ios` | +| room_id | number | 直播间长号 | 必要 | 只支持 `room_id` 不支持 `short_id` | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | -------- | ---- | +| code | number | 返回值 | 0: 成功 | +| message | string | 错误消息 | 默认为 0 | +| ttl | number | 1 | | +| data | object | 信息本体 | 见下 | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | -------- | ---------- | ---- | +| data | object[] | 表情包数据 | 套了个娃 | +| fans_brand | number | 品牌标识? | | +| purchase_url | null? | 购买链接? | | + +`data.data[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------------- | -------- | --------- | ---- | +| current_cover | string | 封面 URL | | +| emoticons | object[] | 表情列表 | | +| pkg_descript | string | 文字描述 | | +| pkg_id | number | 包 ID | | +| pkg_name | string | 包名称 | | +| pkg_perm | number | 使用权限? | | +| pkg_type | number | 包类型 | | +| recently_used_emoticons | unknown[] | 最近使用的表情 | | +| top_show | object | 顶部展示信息? | | +| top_show_recent | object | 最近使用的顶部展示信息? | | +| unlock_identity | number | 解锁所需身份标识? | | +| unlock_need_gift | number | 解锁所需礼物? | | + +`data.data[].emoticons[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ------ | ---- | ---- | +| bulge_display | number | 突出展示? | | +| descript | string | 描述 | | +| emoji | string | 触发关键词? | | +| emoticon_id | number | 表情 ID | | +| emoticon_unique | string | 表情唯一标识 | | +| emoticon_value_type | number | 表情值类型? | | +| height | number | 表情图片高度 | | +| identity | number | 身份限制标识? | | +| in_player_area | number | 播放器区域内展示? | | +| is_dynamic | number | 是否为动态表情? | | +| perm | number | 使用权限? | | +| unlock_need_gift | number | 解锁需求礼物? | | +| unlock_need_level | number | 解锁需求等级? | | +| unlock_show_color | string | 解锁展示颜色? | | +| unlock_show_image | string | 解锁展示图片? | | +| unlock_show_text | string | 解锁展示文字? | | +| url | string | 表情图片 URL | | +| width | number | 表情图片宽度 | | + +`data.data[].top_show` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ------ | ---- | ---- | +| top_left | object | | 左上 | +| top_right | object | | 右上 | + +`data.data[].top_show.top_left` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ------ | ----- | ---- | +| image | string | 图片? | | +| text | string | 文字 | | + +`data.data[].top_show.top_right` 对象: + +同 `data.data[].top_show.top_left` 对象 + +`data.data[].top_show_recent` 对象: + +同 `data.data[].top_show` 对象 + +`data.data[].top_show_recent.top_left` 对象: + +同 `data.data[].top_show.top_left` 对象 + +`data.data[].top_show_recent.top_right` 对象: + +同 `data.data[].top_show.top_left` 对象 + +**示例:** + +获取直播间 `14047` 的表情包, 平台为 `android` + +```shell +curl -G 'https://api.live.bilibili.com/xlive/web-ucenter/v2/emoticon/GetEmoticons' \ +--url-query 'room_id=14047' \ +--url-query 'platform=android' \ +-b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data": { + "data": [ + { + "current_cover": "http://i0.hdslb.com/bfs/live/39b7667c2601e4da8019472f5e3df1f2278278b6.png", + "emoticons": [ + { + "bulge_display": 0, + "descript": "", + "emoji": "啊", + "emoticon_id": 331, + "emoticon_unique": "official_331", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/cbf2746062242e77bdcb9eb08edbf9b151fe0c2e.png", + "width": 200 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "冲鸭", + "emoticon_id": 332, + "emoticon_unique": "official_332", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/dea7fbbc1c3d3c80f4c7b27263e13460f21874e4.png", + "width": 200 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "upup", + "emoticon_id": 348, + "emoticon_unique": "official_348", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/38d84a4cd2f40069202ee13bbdca5b23d29710fb.png", + "width": 200 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "星星向龙", + "emoticon_id": 343, + "emoticon_unique": "official_343", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/a69423be39b0f2a87dc74f2e44ead70de0eb0d4f.png", + "width": 200 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "欧皇驾到", + "emoticon_id": 335, + "emoticon_unique": "official_335", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/650399e68d0d93df4b3f9e95e7437e83be7fbb1a.png", + "width": 200 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "这个好耶", + "emoticon_id": 345, + "emoticon_unique": "official_345", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/2ce08b31618d3ad0d34877bf949ef0089a0438b7.png", + "width": 200 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "泰裤辣", + "emoticon_id": 339, + "emoticon_unique": "official_339", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/82c38fc930ae764b4c6215f544bf8e1dba73b51c.png", + "width": 200 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "闪避技能", + "emoticon_id": 337, + "emoticon_unique": "official_337", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/fa3febe6c62f3bcd042953141930d96fb8451e60.png", + "width": 200 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "稳住能赢", + "emoticon_id": 342, + "emoticon_unique": "official_342", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/b3495aaa935b045bfc2e1d52738ea7b124e0d552.png", + "width": 200 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "中奖喷雾", + "emoticon_id": 346, + "emoticon_unique": "official_346", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/c3cfa182d16564301d39e4c7e4c186dfb9fabf96.png", + "width": 200 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "赞", + "emoticon_id": 147, + "emoticon_unique": "official_147", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/bbd9045570d0c022a984c637e406cb0e1f208aa9.png", + "width": 150 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "妙啊", + "emoticon_id": 109, + "emoticon_unique": "official_109", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/7b7a2567ad1520f962ee226df777eaf3ca368fbc.png", + "width": 138 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "有点东西", + "emoticon_id": 113, + "emoticon_unique": "official_113", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/39e518474a3673c35245bf6ef8ebfff2c003fdc3.png", + "width": 186 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "很有精神", + "emoticon_id": 150, + "emoticon_unique": "official_150", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/e91cbe30b2db1e624bd964ad1f949661501f42f8.png", + "width": 201 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "泪目", + "emoticon_id": 103, + "emoticon_unique": "official_103", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/aa93b9af7ba03b50df23b64e9afd0d271955cd71.png", + "width": 144 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "赢麻了", + "emoticon_id": 128, + "emoticon_unique": "official_128", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/1d4c71243548a1241f422e90cd8ba2b75c282f6b.png", + "width": 156 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "钝角", + "emoticon_id": 133, + "emoticon_unique": "official_133", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/38cf68c25d9ff5d364468a062fc79571db942ff3.png", + "width": 153 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "干杯", + "emoticon_id": 149, + "emoticon_unique": "official_149", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/8fedede4028a72e71dae31270eedff5f706f7d18.png", + "width": 162 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "2333", + "emoticon_id": 124, + "emoticon_unique": "official_124", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/a98e35996545509188fe4d24bd1a56518ea5af48.png", + "width": 183 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "打call", + "emoticon_id": 146, + "emoticon_unique": "official_146", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/fa1eb4dce3ad198bb8650499830560886ce1116c.png", + "width": 195 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "多谢款待", + "emoticon_id": 148, + "emoticon_unique": "official_148", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/4609dad97c0dfa61f8da0b52ab6fff98e0cf1e58.png", + "width": 207 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "awsl", + "emoticon_id": 102, + "emoticon_unique": "official_102", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/328e93ce9304090f4035e3aa7ef031d015bbc915.png", + "width": 162 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "鸡汤来咯", + "emoticon_id": 137, + "emoticon_unique": "official_137", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/b371151503978177b237afb85185b0f5431d0106.png", + "width": 198 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "雀食", + "emoticon_id": 118, + "emoticon_unique": "official_118", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/7251dc7df587388a3933743bf38394d12a922cd7.png", + "width": 159 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "禁止套娃", + "emoticon_id": 108, + "emoticon_unique": "official_108", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/6a644577437d0bd8a314990dd8ccbec0f3b30c92.png", + "width": 204 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "暗中观察", + "emoticon_id": 104, + "emoticon_unique": "official_104", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/18af5576a4582535a3c828c3ae46a7855d9c6070.png", + "width": 156 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "保熟吗", + "emoticon_id": 105, + "emoticon_unique": "official_105", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/0e28444c8e2faef3169e98e1a41c487144d877d4.png", + "width": 162 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "比心", + "emoticon_id": 106, + "emoticon_unique": "official_106", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/1ba5126b10e5efe3e4e29509d033a37f128beab2.png", + "width": 132 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "咸鱼翻身", + "emoticon_id": 110, + "emoticon_unique": "official_110", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/7db4188c050f55ec59a1629fbc5a53661e4ba780.png", + "width": 180 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "mua", + "emoticon_id": 111, + "emoticon_unique": "official_111", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/08f1aebaa4d9c170aa79cbafe521ef0891bdf2b5.png", + "width": 165 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "来了来了", + "emoticon_id": 115, + "emoticon_unique": "official_115", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/61e790813c51eab55ebe0699df1e9834c90b68ba.png", + "width": 168 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "贴贴", + "emoticon_id": 116, + "emoticon_unique": "official_116", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/88b49dac03bfd5d4cb49672956f78beb2ebd0d0b.png", + "width": 162 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "牛牛牛", + "emoticon_id": 117, + "emoticon_unique": "official_117", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/343f7f7e87fa8a07df63f9cba6b776196d9066f0.png", + "width": 168 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "颠个勺", + "emoticon_id": 119, + "emoticon_unique": "official_119", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/625989e78079e3dc38d75cb9ac392fe8c1aa4a75.png", + "width": 195 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "好家伙", + "emoticon_id": 122, + "emoticon_unique": "official_122", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/c2650bf9bbc79b682a4b67b24df067fdd3e5e9ca.png", + "width": 165 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "下次一定", + "emoticon_id": 125, + "emoticon_unique": "official_125", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/cc2652cef69b22117f1911391567bd2957f27e08.png", + "width": 177 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "不上Ban", + "emoticon_id": 126, + "emoticon_unique": "official_126", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/eff44c1fc03311573e8817ca8010aca72404f65c.png", + "width": 231 + }, + { + "bulge_display": 0, + "descript": "", + "emoji": "上热榜", + "emoticon_id": 134, + "emoticon_unique": "official_134", + "emoticon_value_type": 0, + "height": 60, + "identity": 99, + "in_player_area": 1, + "is_dynamic": 1, + "perm": 1, + "unlock_need_gift": 0, + "unlock_need_level": 0, + "unlock_show_color": "", + "unlock_show_image": "", + "unlock_show_text": "", + "url": "http://i0.hdslb.com/bfs/live/83d5b9cdaaa820c2756c013031d34dac1fd4156b.png", + "width": 168 + } + ], + "pkg_descript": "官方表情(系统)", + "pkg_id": 1, + "pkg_name": "通用表情", + "pkg_perm": 1, + "pkg_type": 1, + "recently_used_emoticons": [], + "top_show": { + "top_left": { + "image": "", + "text": "通用表情" + }, + "top_right": { + "image": "", + "text": "" + } + }, + "top_show_recent": { + "top_left": { + "image": "", + "text": "" + }, + "top_right": { + "image": "", + "text": "" + } + }, + "unlock_identity": 0, + "unlock_need_gift": 0 + } + ], + "fans_brand": 1, + "purchase_url": null + }, + "message": "0", + "ttl": 1 +} +``` +</details> diff --git a/bb-api-collect/docs/live/follow_up_live.md b/bb-api-collect/docs/live/follow_up_live.md new file mode 100644 index 0000000000..8c7d0a12d0 --- /dev/null +++ b/bb-api-collect/docs/live/follow_up_live.md @@ -0,0 +1,317 @@ +# 关注UP直播情况 + +## 用户关注的所有UP的直播情况 + +> https://api.live.bilibili.com/xlive/web-ucenter/user/following + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|---------|-----|------|-----|-------| +| page | num | 页码 | 非必要 | 默认为`1` | +| page_size | num | 每页的数据数量 | 非必要 | 有效值`1`-`10`, 默认为`10` | +| ignoreRecord | num | | | **尚不明确**<br />一般为`1` | +| hit_ab | bool | | | **尚不明确**<br />建议用`true`, 不填为`false` | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|-----------------| +| code | num | 返回值 | `0`:成功<br />`-101`:错误 | +| message | str | 错误信息 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|-----------------| +| title | str | 标题 | | +| pageSize | num | 每页的数据数量 | | +| totalPage | num | 分页数量 | | +| list | obj | UP直播情况列表 | | +| count | num | 曾直播过的UP数量 | | +| never_lived_count | num | 未直播过的UP数量 | | +| live_count | num | 正在直播的UP数量 | | +| never_lived_faces | list | | **尚不明确** | + +`list`对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------------|-----|-----|-----------| +| roomid | num | 房间号 | | +| uid | num | 主播uid | | +| uname | str | 主播名 | | +| title | str | 直播标题 | | +| face | str | 主播头像 | | +| live_status | num | 是否正在直播 | `0`: 未直播<br />`1`: 正在直播 | +| record_num | num | | **尚不明确**<br />一般为0 | +| recent_record_id | str | | **尚不明确**<br />一般为空 | +| is_attention | num | | **尚不明确**<br />一般为1 | +| clipnum | num | | **尚不明确**<br />一般为0 | +| fans_num | num | | **尚不明确**<br />一般为0 | +| area_name | str | | **尚不明确**<br />一般为空 | +| area_value | str | | **尚不明确**<br />一般为空 | +| tags | str | | **尚不明确**<br />一般为空 | +| recent_record_id_v2 | str | | **尚不明确**<br />一般为空 | +| record_num_v2 | num | | **尚不明确**<br />一般为0 | +| record_live_time | num | 主播上一次直播结束的时间戳 | 正在直播时, 值为`0` | +| area_name_v2 | str | 频道的名称 | | +| room_news | str | 房间公告 | | +| switch | bool | | **尚不明确** | +| watch_icon | str | | **尚不明确** | +| text_small | str | | **尚不明确**<br />当主播正在直播时, 为在线人数(可能) | +| room_cover | str | 房间封面图片的URL | | +| parent_area_id | num | 父分区id | | +| area_id | num | 分区id | | + +**示例:** + +```shell +curl -G 'https://api.live.bilibili.com/xlive/web-ucenter/user/following' \ + -b 'SESSDATA=xxx' \ + --data-urlencode 'page=1' \ + --data-urlencode 'page_size=2' \ + --data-urlencode 'ignoreRecord=1' \ + --data-urlencode 'hit_ab=true' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "title": "哔哩哔哩直播 - 我的关注", + "pageSize": 2, + "totalPage": 26, + "list": [ + { + "roomid": 544853, + "uid": 686127, + "uname": "籽岷", + "title": "尝试双机位", + "face": "https://i0.hdslb.com/bfs/face/7efb679569b2faeff38fa08f6f992fa1ada5e948.webp", + "live_status": 0, + "record_num": 0, + "recent_record_id": "", + "is_attention": 1, + "clipnum": 0, + "fans_num": 0, + "area_name": "", + "area_value": "", + "tags": "", + "recent_record_id_v2": "", + "record_num_v2": 0, + "record_live_time": 1720011626, + "area_name_v2": "新游推荐", + "room_news": "", + "switch": true, + "watch_icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "text_small": "10.9万", + "room_cover": "http://i0.hdslb.com/bfs/live/new_room_cover/6c89c41d7695a080d31ae21c128f7759a7f419e5.jpg", + "parent_area_id": 6, + "area_id": 889 + }, + { + "roomid": 21686237, + "uid": 456664753, + "uname": "央视新闻", + "title": "央视新闻的直播间", + "face": "https://i1.hdslb.com/bfs/face/38a8db1c187b64a1412fafffbf350f8a3f436371.jpg", + "live_status": 0, + "record_num": 0, + "recent_record_id": "", + "is_attention": 1, + "clipnum": 0, + "fans_num": 0, + "area_name": "", + "area_value": "", + "tags": "", + "recent_record_id_v2": "", + "record_num_v2": 0, + "record_live_time": 1720001717, + "area_name_v2": "社科法律心理", + "room_news": "", + "switch": false, + "watch_icon": "https://i0.hdslb.com/bfs/live/0b265af1af0a77abc47aa3b8f1a5c0769d8bd23b.png", + "text_small": "0", + "room_cover": "http://i0.hdslb.com/bfs/live/d650d0e6e49397ea71d630be0a0e686679df16d8.jpg", + "parent_area_id": 11, + "area_id": 376 + } + ], + "count": 52, + "never_lived_count": 30, + "live_count": 0, + "never_lived_faces": [] + } +} + +``` + +</details> + +## 用户关注的所有UP且正在直播的列表(PC端) + +> https://api.live.bilibili.com/xlive/web-ucenter/v1/xfetter/GetWebList + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|-----|------|----------------------------------|-----|------------------| +| hit_ab | bool | 会影响到json回复中部分字段的值,具体的影响效果会在下表列出。 | 非必要 | 默认为true,不填为false | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|------------------| +| code | num | 返回值 | 0:成功<br />1:参数错误 | +| msg | str | 错误信息 | 默认为空 | +| message | str | 错误信息 | 默认为空 | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|------|--------------|--------------------------------------------------------------------| +| rooms | list | 正在直播的房间列表 | 受到url参数hit_ab的影响:<br />true时能够获取到全部正在开播的直播间列表,<br />false时只会获取到前10个。 | +| list | list | 正在直播的房间列表 | 疑似与rooms字段的内容相同,并且同样受到url参数hit_ab的影响,受影响的效果同rooms字段。 | +| count | num | 关注列表中正在直播的人数 | 受到url参数hit_ab的影响:hit_ab为true时为0 | +| not_living_num | num | 关注列表中未开播的人数 | 受到url参数hit_ab的影响:hit_ab为false时为0 | + +`rooms`对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|------|--------------|---------------------------------------------------------------| +| title | num | 直播间标题 | | +| room_id | num | 直播间真实id | | +| uid | num | 目标用户mid | | +| online | num | 观看人数 | 受url参数hit_ab的影响,hit_ab为true时为0 | +| live_time | num | 已经直播的时长(单位为秒) | 受url参数hit_ab的影响,hit_ab为true时为0 | +| live_status | num | 开播状态 | 0:未开播<br />1:直播中<br />2:轮播中 | +| short_id | num | 直播间短id | 受url参数hit_ab的影响,hit_ab为true时为0 | +| area | num | 分区id | 受url参数hit_ab的影响,hit_ab为true时为0 | +| area_name | str | 分区名称 | | +| area_v2_id | num | 二级分区id | | +| area_v2_name | str | 二级分区名 | | +| area_v2_parent_name | str | 二级父分区名 | | +| area_v2_parent_id | num | 二级父分区id | | +| uname | str | 用户名 | | +| face | str | 用户头像图片链接 | | +| tag_name | str | 标签名 | | +| tags | str | 标签列表 | | +| cover_from_user | str | 直播间封面图片链接 | 受url参数hit_ab的影响,hit_ab为true时为0 | +| keyframe | str | 关键帧图片链接 | 用于网页端悬浮展示。受url参数hit_ab的影响,hit_ab为true时为0 | +| lock_till | str | 未知 | 时间日期格式为:yyyy-MM-dd hh-mm-ss。<br />受url参数hit_ab的影响,hit_ab为true时为空字符串 | +| hidden_till | str | 未知 | 时间日期格式为:yyyy-MM-dd hh-mm-ss。<br />受url参数hit_ab的影响,hit_ab为true时为空字符串 | +| broadcast_type | num | 广播类型 | | +| is_encrypt | bool | 直播间是否加密 | | +| link | str | 直播间链接 | 受url参数hit_ab的影响,hit_ab为true时为空字符串 | +| nickname | str | 用户昵称 | 受url参数hit_ab的影响,hit_ab为true时为空字符串 | +| roomname | str | 直播间名称 | 受url参数hit_ab的影响,hit_ab为true时为空字符串 | +| roomid | num | 直播间真实id | 受url参数hit_ab的影响,hit_ab为true时为0 | +| liveTime | num | 开播时间 | 受url参数hit_ab的影响,hit_ab为true时为0 | + +**示例:** + +```shell +curl -G 'https://api.live.bilibili.com/xlive/web-ucenter/v1/xfetter/GetWebList' \ +--header 'Cookie: SESSDATA=xxx' \ +--data-urlencode 'hit_ab=false' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "rooms": [ + { + "title": "虚拟区优质跨年直播展演", + "room_id": 21496316, + "uid": 441666939, + "online": 2308, + "live_time": 17313, + "live_status": 1, + "short_id": 36, + "area": 6, + "area_name": "生活娱乐", + "area_v2_id": 744, + "area_v2_name": "虚拟Singer", + "area_v2_parent_name": "虚拟主播", + "area_v2_parent_id": 9, + "uname": "虚拟区官方频道", + "face": "https://i0.hdslb.com/bfs/face/a26b52bc7837ce6867802575d300ed70d5e6f2d5.jpg", + "tag_name": "", + "tags": "", + "cover_from_user": "https://i0.hdslb.com/bfs/live/new_room_cover/5d7a4526062cf1dc4e88e016638a856c1ac7db03.jpg", + "keyframe": "https://i0.hdslb.com/bfs/live-key-frame/keyframe12311645000021496316pkuk08.jpg", + "lock_till": "0000-00-00 00:00:00", + "hidden_till": "0000-00-00 00:00:00", + "broadcast_type": 0, + "is_encrypt": false, + "link": "https://live.bilibili.com/21496316?broadcast_type=0", + "nickname": "虚拟区官方频道", + "roomname": "虚拟区优质跨年直播展演", + "roomid": 21496316, + "liveTime": 1735617438 + } + ], + "list": [ + { + "title": "虚拟区优质跨年直播展演", + "room_id": 21496316, + "uid": 441666939, + "online": 2308, + "live_time": 17313, + "live_status": 1, + "short_id": 36, + "area": 6, + "area_name": "生活娱乐", + "area_v2_id": 744, + "area_v2_name": "虚拟Singer", + "area_v2_parent_name": "虚拟主播", + "area_v2_parent_id": 9, + "uname": "虚拟区官方频道", + "face": "https://i0.hdslb.com/bfs/face/a26b52bc7837ce6867802575d300ed70d5e6f2d5.jpg", + "tag_name": "", + "tags": "", + "cover_from_user": "https://i0.hdslb.com/bfs/live/new_room_cover/5d7a4526062cf1dc4e88e016638a856c1ac7db03.jpg", + "keyframe": "https://i0.hdslb.com/bfs/live-key-frame/keyframe12311645000021496316pkuk08.jpg", + "lock_till": "0000-00-00 00:00:00", + "hidden_till": "0000-00-00 00:00:00", + "broadcast_type": 0, + "is_encrypt": false, + "link": "https://live.bilibili.com/21496316?broadcast_type=0", + "nickname": "虚拟区官方频道", + "roomname": "虚拟区优质跨年直播展演", + "roomid": 21496316, + "liveTime": 1735617438 + } + ], + "count": 1, + "not_living_num": 0 + } +} +``` + +</details> \ No newline at end of file diff --git a/bb-api-collect/docs/live/gift.md b/bb-api-collect/docs/live/gift.md new file mode 100644 index 0000000000..daa99a135d --- /dev/null +++ b/bb-api-collect/docs/live/gift.md @@ -0,0 +1,191 @@ +## 获取直播间内礼物 + +> https://api.live.bilibili.com/xlive/web-room/v1/giftPanel/roomGiftList + +*请求方式:GET* + +认证方式:无 (无需添加Cookie) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------------- | ---- | ---------- | ------ | -------------------------------- | +| platform | str | web | 必要 | | +| room_id | num | 主播房间号 | 必要 | | +| area_parent_id | num | 直播分区 | 非必要 | 不填写可能会获取不到部分活动礼物 | +| area_id | num | 直播子分区 | 非必要 | 不填写可能会获取不到部分活动礼物 | + +**json回复:** + + + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | | +| data | obj | 信息本体 | | + +`data.gift_config.base_config.list` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------- | ---- | ------------------- | --------------------------- | +| id | num | 礼物id | | +| name | str | 礼物名字 | | +| price | num | 该值/1000的单位为元 | | +| type | num | | | +| coin_type | str | 一般为gold,即电池 | | +| effect | num | 特效类型? | 观察到可能出现的值为0,2,3 | +| stay_time | num | 礼物展示的时间? | 均为3 | +| animation_frame_num | num | 礼物动画帧数 | | +| desc | str | 礼物描述 | | +| img_basic | str | 礼物图片 | | +| gif | str | 礼物gif动画 | | + +**示例:** + +查询`room_id=23375552`的直播间礼物信息 + +```shell +curl 'https://api.live.bilibili.com/xlive/web-room/v1/giftPanel/roomGiftList?platform=pc&room_id=23174842' +``` + +## 获取盲盒概率 + +> https://api.live.bilibili.com/xlive/general-interface/v1/blindFirstWin/getInfo + +*请求方式:GET* + +认证方式:无 (无需添加Cookie) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | ---- | ---------------- | ---- | +| gift_id | num | | 盲盒对应的礼物id | | + +**json回复:** + + + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | | +| data | obj | 信息本体 | | + +`data`中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ----- | -------- | ---- | +| note_text | str | 描述 | | +| blind_price | num | 盲盒价格 | | +| blind_gift_name | str | 盲盒名字 | | +| gifts | array | 盲盒价格 | | + +`gifts数组`中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | -------------- | ---- | +| gift_id | num | 爆出的礼物id | | +| price | num | 爆出的礼物价格 | | +| gift_name | str | 礼物名字 | | +| gift_img | str | 礼物图片 | | +| chance | str | 概率 | | + +**示例:** + +查询`心动盲盒`的概率 + +```shell +curl 'https://api.live.bilibili.com/xlive/general-interface/v1/blindFirstWin/getInfo?gift_id=32251' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "note_text": "每日1次机会,首次投喂盲盒时享首抽福利!", + "blind_price": 15000, + "gifts": [ + { + "gift_id": 32125, + "price": 2000, + "gift_name": "电影票", + "gift_img": "https://s1.hdslb.com/bfs/live/20864a10beaea541c7dce264d5bbc56676d63e4f.png", + "is_win_gift": 0, + "chance": "6%" + }, + { + "gift_id": 32126, + "price": 9000, + "gift_name": "棉花糖", + "gift_img": "https://s1.hdslb.com/bfs/live/b555682af41551c28f8ad19dc5c4ed87943c84f4.png", + "is_win_gift": 0, + "chance": "44.5%" + }, + { + "gift_id": 32128, + "price": 16000, + "gift_name": "爱心抱枕", + "gift_img": "https://s1.hdslb.com/bfs/live/824714c830966d7bec381e35ef808b1f478e21ee.png", + "is_win_gift": 1, + "chance": "45.56%" + }, + { + "gift_id": 32281, + "price": 40000, + "gift_name": "绮彩权杖", + "gift_img": "https://s1.hdslb.com/bfs/live/5cecbf274a4205ef76ed3f11c6540f0c6743363c.png", + "is_win_gift": 1, + "chance": "3.7%" + }, + { + "gift_id": 32282, + "price": 100000, + "gift_name": "时空之站", + "gift_img": "https://s1.hdslb.com/bfs/live/9ee53aedda3c891fdf23d35c14b3bdc4e0504a97.png", + "is_win_gift": 1, + "chance": "0.12%" + }, + { + "gift_id": 34894, + "price": 200000, + "gift_name": "蛇形护符", + "gift_img": "https://s1.hdslb.com/bfs/live/2127dd998083a8981ef4e31a4e6787ce5a4d0f9f.png", + "is_win_gift": 1, + "chance": "0.08%" + }, + { + "gift_id": 32132, + "price": 2233000, + "gift_name": "浪漫城堡", + "gift_img": "https://s1.hdslb.com/bfs/live/216fac597b3c5619d56ed332bcf5f880ea657e8e.png", + "is_win_gift": 1, + "chance": "0.04%" + } + ], + "friday_yq_id": 106472, + "is_first": true, + "ab_res": 1, + "uid": 451537183, + "conf_id": 51, + "pre_imgs": [ + { + "gift_id": 32132, + "preview_url": "http://i0.hdslb.com/bfs/live/e40708d0c8ef9505027ac33ad2a17a23e8e01139.mp4" + } + ], + "blind_gift_name": "心动盲盒" + } +} +``` +</details> \ No newline at end of file diff --git a/bb-api-collect/docs/live/guard.md b/bb-api-collect/docs/live/guard.md new file mode 100644 index 0000000000..29389072e9 --- /dev/null +++ b/bb-api-collect/docs/live/guard.md @@ -0,0 +1,592 @@ +## 查询大航海成员 +> https://api.live.bilibili.com/xlive/app-room/v2/guardTab/topListNew + +*请求方式: GET* + +认证方式:无(无需Cookie) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | -------- | ------ | --------------------------------------- | +| roomid | num | 直播间号 | 必要 | | +| page | num | 页数 | 必要 | | +| ruid | num | 主播id | 必要 | | +| page_size | num | 页大小 | 非必要 | 默认20,最大30,若超过则作为10处理 | +| typ | num | 排序方式 | 非必要 | typ=3,4,5分别为按周/月/总航海亲密度排序 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ----- | -------------- | --------------------------------------- | +| info | obj | 主播mid | | +| top3 | array | 整个列表的top3 | +| list | array | 大航海成员 | page=1时,list[0]得到的会是榜单的第四名 | + +`list`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | -------- | ----- | +| ruid | num | 主播UID | | +| rank | num | 榜单排名 | | +| accompany | num | 陪伴天数 | | +| uinfo | obj | 用户信息 | | +| score | num | 亲密度 | 恒为0 | + +`list`对象的`uinfo`: +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ------------ | -------------------------------------------------------- | +| uid | num | 用户UID | | +| base | obj | 用户基本信息 | | +| medal | obj | 粉丝牌 | 与[此处](/bilibili-API-collect/docs/user/medals)基本一致 | + +`list`对象的`uinfo`的`base`: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ------ | -------- | ---- | +| name | string | 用户名 | | +| face | string | 用戶头像 | | + + +**示例:** + +查询`23174842`直播间的大航海成员 + + +```shell +curl ' https://api.live.bilibili.com/xlive/app-room/v2/guardTab/topListNew?ruid=504140200&roomid=23174842&page=1' +``` + + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "info": { + "num": 23, + "page": 10, + "now": 1, + "achievement_level": 1, + "anchor_guard_achieve_level": 0, + "achievement_icon_src": "", + "buy_guard_icon_src": "https://i0.hdslb.com/bfs/live/4a481b491767f9d91165a4631252de4503d63a17.png", + "rule_doc_src": "", + "ex_background_src": "https://i0.hdslb.com/bfs/live/d0e938839a9dee733e8a7f9f6a3a132108ae22bc.png", + "color_start": "", + "color_end": "", + "tab_color": [ + "#4DDDDBD5", + "#26CFCBC0" + ], + "title_color": [ + "#FFC9CCD0", + "#FF9499A0" + ] + }, + "list": [ + { + "ruid": 504140200, + "rank": 4, + "accompany": 36, + "uinfo": { + "uid": 432911315, + "base": { + "name": "幻想乡的年华", + "face": "https://i2.hdslb.com/bfs/face/5ddde7a8466aa2d60d082ccfc08a0267445b193b.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": null, + "origin_info": { + "name": "幻想乡的年华", + "face": "https://i2.hdslb.com/bfs/face/5ddde7a8466aa2d60d082ccfc08a0267445b193b.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": { + "name": "软饭兔", + "level": 25, + "color_start": 398668, + "color_end": 6850801, + "color_border": 16771156, + "color": 398668, + "id": 0, + "typ": 0, + "is_light": 1, + "ruid": 504140200, + "guard_level": 2, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#4775EFCC", + "v2_medal_color_end": "#4775EFCC", + "v2_medal_color_border": "#58A1F8FF", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + }, + "wealth": null, + "title": null, + "guard": { + "level": 2, + "expired_str": "" + }, + "uhead_frame": null, + "guard_leader": null + }, + "score": 0 + }, + { + "ruid": 504140200, + "rank": 5, + "accompany": 513, + "uinfo": { + "uid": 7816639, + "base": { + "name": "在这样的时光", + "face": "https://i1.hdslb.com/bfs/face/3b0091dda76e095351907e9c708b9571716aa3e1.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": null, + "origin_info": { + "name": "在这样的时光", + "face": "https://i1.hdslb.com/bfs/face/3b0091dda76e095351907e9c708b9571716aa3e1.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": { + "name": "软饭兔", + "level": 30, + "color_start": 2951253, + "color_end": 10329087, + "color_border": 6809855, + "color": 2951253, + "id": 0, + "typ": 0, + "is_light": 1, + "ruid": 504140200, + "guard_level": 3, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#9660E5CC", + "v2_medal_color_end": "#9660E5CC", + "v2_medal_color_border": "#D47AFFFF", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#6C00A099", + "user_receive_count": 0 + }, + "wealth": null, + "title": null, + "guard": { + "level": 3, + "expired_str": "" + }, + "uhead_frame": null, + "guard_leader": null + }, + "score": 0 + } + ], + "top3": [ + { + "ruid": 504140200, + "rank": 1, + "accompany": 306, + "uinfo": { + "uid": 85743027, + "base": { + "name": "-小fa---", + "face": "https://i0.hdslb.com/bfs/face/82b2d0fef27b7b69be0d121b3ef0491504bbaae8.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": null, + "origin_info": { + "name": "-小fa---", + "face": "https://i0.hdslb.com/bfs/face/82b2d0fef27b7b69be0d121b3ef0491504bbaae8.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": { + "name": "软饭兔", + "level": 30, + "color_start": 2951253, + "color_end": 10329087, + "color_border": 16771156, + "color": 2951253, + "id": 0, + "typ": 0, + "is_light": 1, + "ruid": 504140200, + "guard_level": 2, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#9660E5CC", + "v2_medal_color_end": "#9660E5CC", + "v2_medal_color_border": "#D47AFFFF", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#6C00A099", + "user_receive_count": 0 + }, + "wealth": null, + "title": null, + "guard": { + "level": 2, + "expired_str": "" + }, + "uhead_frame": null, + "guard_leader": null + }, + "score": 0 + }, + { + "ruid": 504140200, + "rank": 2, + "accompany": 1005, + "uinfo": { + "uid": 28601039, + "base": { + "name": "捏软软的上帝", + "face": "https://i2.hdslb.com/bfs/face/1f2a9b20294452d5c6ce9f40c66b186ef57b92e5.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": null, + "origin_info": { + "name": "捏软软的上帝", + "face": "https://i2.hdslb.com/bfs/face/1f2a9b20294452d5c6ce9f40c66b186ef57b92e5.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": { + "name": "软饭兔", + "level": 29, + "color_start": 2951253, + "color_end": 10329087, + "color_border": 16771156, + "color": 2951253, + "id": 0, + "typ": 0, + "is_light": 1, + "ruid": 504140200, + "guard_level": 2, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#9660E5CC", + "v2_medal_color_end": "#9660E5CC", + "v2_medal_color_border": "#D47AFFFF", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#6C00A099", + "user_receive_count": 0 + }, + "wealth": null, + "title": null, + "guard": { + "level": 2, + "expired_str": "" + }, + "uhead_frame": null, + "guard_leader": null + }, + "score": 0 + }, + { + "ruid": 504140200, + "rank": 3, + "accompany": 95, + "uinfo": { + "uid": 3546834244995088, + "base": { + "name": "老实逸流-恩师软软riu", + "face": "https://i1.hdslb.com/bfs/face/0b1f95d926acfb06c8d7d9c66d2e1fabf3e1a3c4.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": null, + "origin_info": { + "name": "老实逸流-恩师软软riu", + "face": "https://i1.hdslb.com/bfs/face/0b1f95d926acfb06c8d7d9c66d2e1fabf3e1a3c4.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": { + "name": "软饭兔", + "level": 28, + "color_start": 398668, + "color_end": 6850801, + "color_border": 16771156, + "color": 398668, + "id": 0, + "typ": 0, + "is_light": 1, + "ruid": 504140200, + "guard_level": 2, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#4775EFCC", + "v2_medal_color_end": "#4775EFCC", + "v2_medal_color_border": "#58A1F8FF", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + }, + "wealth": null, + "title": null, + "guard": { + "level": 2, + "expired_str": "" + }, + "uhead_frame": null, + "guard_leader": null + }, + "score": 0 + } + ], + "my_follow_info": { + "accompany_days": 0, + "auto_renew": 0, + "renew_remind": { + "content": "", + "type": 0, + "hint": "" + }, + "rank": 0, + "ruid": 0, + "uinfo": null, + "expired_time": "" + }, + "guard_warn": { + "is_warn": 0, + "warn": "", + "expired": 0, + "will_expired": 0, + "address": "" + }, + "exist_benefit": false, + "remind_benefit": "立即上船", + "ab": { + "guard_accompany_list": 1 + }, + "remind_msg": "头号粉丝大航海,上船后可上榜", + "typ": 0, + "extop": null, + "guard_leader": null, + "main_text": "", + "sub_text": "", + "btn_type": 1, + "prompt_text": "头号粉丝大航海,等你来上船" + } +} +``` + +</details> + + +## 查询粉丝团成员 + + +> https://api.live.bilibili.com/xlive/general-interface/v1/rank/getFansMembersRank + +*请求方式: GET* + +认证方式:无(无需Cookie) + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | -------------- | ------------------- | ----------------------------------------------------------------------------------------------- | +| page | num | 页数 | 必要 | | +| ruid | num | 主播id | 必要 | | +| page_size | num | 每页返回的数量 | 必要 | 最大30,若超过则作为10处理 | +| rank_type | num | 排序方式 | 非必要 | 1:按照粉丝牌还亮着的粉丝团成员的亲密度排序<br> 2:按照**所有**没上过舰的粉丝团成员的亲密度排序 | +| ts | num | 13位时间戳 | 当rank_type=2时必要 | 该值>=1000即可 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ----- | -------------- | ---- | +| item | array | 内容 | | +| num | num | 粉丝团成员数量 | +| medal_status | num | | + +`list`对象 + +| 字段 | 类型 | 内容 | 备注 | +| ------------------ | ---- | ---------------------------------------------------------------- | ---- | +| user_rank | num | 排名 | +| uid | num | 用户UID | +| name | str | 用户名 | +| face | str | 用户头像 | +| score | num | 亲密度 | +| medal_name | str | 粉丝牌名字 | +| level | num | 粉丝牌等级 | +| target_id | num | 主播UID | +| guard_level | num | 大航海类型,1,2,3分别为总督,提督,舰长 | +| medal_color_start | num | 粉丝牌渐变起始色 | +| medal_color_end | num | 粉丝牌渐变结束色 | +| medal_color_border | num | 粉丝牌边框颜色 | +| guard_icon | str | 大航海图标URL | +| uinfo_medal | obj | 粉丝牌,与[此处](/bilibili-API-collect/docs/user/medals)基本一致 | + + +**示例:** + +查询用户`504140200`的粉丝团成员 + +```shell +curl 'https://api.live.bilibili.com/xlive/general-interface/v1/rank/getFansMembersRank?ruid=504140200&page_size=10&page=1' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "item": [ + { + "user_rank": 1, + "uid": 85743027, + "name": "小软兔のfa", + "face": "https://i0.hdslb.com/bfs/face/bdbcabf8d927844ae4f8f9c65862077e29afb989.jpg", + "score": 50990540, + "medal_name": "软饭兔", + "level": 30, + "target_id": 504140200, + "special": "", + "guard_level": 3, + "medal_color_start": 2951253, + "medal_color_end": 10329087, + "medal_color_border": 6809855, + "guard_icon": "https://i0.hdslb.com/bfs/live/143f5ec3003b4080d1b5f817a9efdca46d631945.png", + "honor_icon": "", + "uinfo_medal": { + "name": "软饭兔", + "level": 30, + "color_start": 2951253, + "color_end": 10329087, + "color_border": 6809855, + "color": 0, + "id": 0, + "typ": 0, + "is_light": 1, + "ruid": 504140200, + "guard_level": 3, + "score": 50990540, + "guard_icon": "https://i0.hdslb.com/bfs/live/143f5ec3003b4080d1b5f817a9efdca46d631945.png", + "honor_icon": "", + "v2_medal_color_start": "#9660E5CC", + "v2_medal_color_end": "#9660E5CC", + "v2_medal_color_border": "#D47AFFFF", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#6C00A099", + "user_receive_count": 0 + }, + "tag": null, + "is_pokeable": false + }, + { + "user_rank": 2, + "uid": 7816639, + "name": "在这样的时光", + "face": "https://i1.hdslb.com/bfs/face/3b0091dda76e095351907e9c708b9571716aa3e1.jpg", + "score": 50704568, + "medal_name": "软饭兔", + "level": 30, + "target_id": 504140200, + "special": "", + "guard_level": 3, + "medal_color_start": 2951253, + "medal_color_end": 10329087, + "medal_color_border": 6809855, + "guard_icon": "https://i0.hdslb.com/bfs/live/143f5ec3003b4080d1b5f817a9efdca46d631945.png", + "honor_icon": "", + "uinfo_medal": { + "name": "软饭兔", + "level": 30, + "color_start": 2951253, + "color_end": 10329087, + "color_border": 6809855, + "color": 0, + "id": 0, + "typ": 0, + "is_light": 1, + "ruid": 504140200, + "guard_level": 3, + "score": 50704568, + "guard_icon": "https://i0.hdslb.com/bfs/live/143f5ec3003b4080d1b5f817a9efdca46d631945.png", + "honor_icon": "", + "v2_medal_color_start": "#9660E5CC", + "v2_medal_color_end": "#9660E5CC", + "v2_medal_color_border": "#D47AFFFF", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#6C00A099", + "user_receive_count": 0 + }, + "tag": null, + "is_pokeable": false + } + ], + "num": 89, + "medal_status": 1 + } +} +``` + +</details> diff --git a/bb-api-collect/docs/live/info.md b/bb-api-collect/docs/live/info.md new file mode 100644 index 0000000000..0ad09b8d10 --- /dev/null +++ b/bb-api-collect/docs/live/info.md @@ -0,0 +1,1269 @@ +# 直播间基本信息 + +## 获取直播间信息 + +> https://api.live.bilibili.com/room/v1/Room/get_info + +*请求方式: GET* + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|---------|-----|------|-----|-------| +| room_id | num | 直播间号 | 必要 | 可以为短号 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|-----------------| +| code | num | 返回值 | 0:成功<br />1:不存在 | +| message | str | 错误信息 | | +| msg | str | 错误信息 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------------------|-----------|--------|-----------------------------| +| uid | num | 主播mid | | +| room_id | num | 直播间长号 | | +| short_id | num | 直播间短号 | 为0是无短号 | +| attention | num | 关注数量 | | +| online | num | 观看人数 | | +| is_portrait | bool | 是否竖屏 | | +| description | str | 描述 | | +| live_status | num | 直播状态 | 0:未开播<br />1:直播中<br />2:轮播中 | +| area_id | num | 分区id | | +| parent_area_id | num | 父分区id | | +| parent_area_name | str | 父分区名称 | | +| old_area_id | num | 旧版分区id | | +| background | str | 背景图片链接 | | +| title | str | 标题 | | +| user_cover | str | 封面 | | +| keyframe | str | 关键帧 | 用于网页端悬浮展示 | +| is_strict_room | bool | 未知 | 未知 | +| live_time | str | 直播开始时间 | YYYY-MM-DD HH:mm:ss | +| tags | str | 标签 | ','分隔 | +| is_anchor | num | 未知 | 未知 | +| room_silent_type | str | 禁言状态 | | +| room_silent_level | num | 禁言等级 | | +| room_silent_second | num | 禁言时间 | 单位是秒 | +| area_name | str | 分区名称 | | +| pardants | str | 未知 | 未知 | +| area_pardants | str | 未知 | 未知 | +| hot_words | list(str) | 热词 | | +| hot_words_status | num | 热词状态 | | +| verify | str | 未知 | 未知 | +| new_pendants | obj | 头像框\大v | | +| up_session | str | 未知 | | +| pk_status | num | pk状态 | | +| pk_id | num | pk id | | +| battle_id | num | 未知 | | +| allow_change_area_time | num | | | +| allow_upload_cover_time | num | | | +| studio_info | obj | | | + +`new_pendants`对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------------|-----|-----|-------------------| +| frame | obj | 头像框 | | +| mobile_frame | obj | 同上 | 手机版, 结构一致, 可能null | +| badge | obj | 大v | | +| mobile_badge | obj | 同上 | 手机版, 结构一致, 可能null | + +`frame`对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------------|------|--------|-----| +| name | str | 名称 | | +| value | str | 值 | | +| position | num | 位置 | | +| desc | str | 描述 | | +| area | num | 分区 | | +| area_old | num | 旧分区 | | +| bg_color | str | 背景色 | | +| bg_pic | str | 背景图 | | +| use_old_area | bool | 是否旧分区号 | | + +`badge`对象: + +| 字段 | 类型 | 内容 | 备注 | +|----------|-----|-----|-------------------------------------------| +| name | str | 类型 | v_person: 个人认证(黄) <br /> v_company: 企业认证(蓝) | +| position | num | 位置 | | +| value | str | 值 | | +| desc | str | 描述 | | + +`studio_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------|-------|-----|-----| +| status | num | | | +| master_list | array | | | + +**示例:** + +查询直播间`room_id=1`信息 + +```shell +curl -G 'https://api.live.bilibili.com/room/v1/Room/get_info' \ +--data-urlencode 'room_id=1' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "ok", + "message": "ok", + "data": { + "uid": 9617619, + "room_id": 5440, + "short_id": 1, + "attention": 11919499, + "online": 0, + "is_portrait": false, + "description": "欢迎加入bilibili《快乐运动研究社》,和B站UP主们一起探讨有关运动的经历感受,解决身体和情绪的“疑难杂症”,寻找适合自己的运动,一起跟练!本期我们一起探讨:运动健身能缓解社交恐惧吗?", + "live_status": 2, + "area_id": 145, + "parent_area_id": 1, + "parent_area_name": "娱乐", + "old_area_id": 6, + "background": "", + "title": "快乐运动研究社", + "user_cover": "https://i0.hdslb.com/bfs/live/new_room_cover/96943b8d106a777a34cf796421bb4254163b30e1.jpg", + "keyframe": "https://i0.hdslb.com/bfs/live-key-frame/keyframe08121926000000005440np0q7a.jpg", + "is_strict_room": false, + "live_time": "0000-00-00 00:00:00", + "tags": "", + "is_anchor": 0, + "room_silent_type": "", + "room_silent_level": 1, + "room_silent_second": 0, + "area_name": "视频聊天", + "pendants": "", + "area_pendants": "", + "hot_words": [ + "2333333", + "喂,妖妖零吗", + "红红火火恍恍惚惚", + "FFFFFFFFFF", + "Yooooooo", + "啪啪啪啪啪", + "666666666", + "老司机带带我", + "你为什么这么熟练啊", + "gg", + "prprpr", + "向大佬低头", + "请大家注意弹幕礼仪哦!", + "还有这种操作!", + "囍", + "打call", + "你气不气?", + "队友呢?" + ], + "hot_words_status": 0, + "verify": "", + "new_pendants": { + "frame": { + "name": "", + "value": "", + "position": 0, + "desc": "", + "area": 0, + "area_old": 0, + "bg_color": "", + "bg_pic": "", + "use_old_area": false + }, + "badge": { + "name": "v_company", + "position": 3, + "value": "", + "desc": "哔哩哔哩直播官方账号" + }, + "mobile_frame": { + "name": "", + "value": "", + "position": 0, + "desc": "", + "area": 0, + "area_old": 0, + "bg_color": "", + "bg_pic": "", + "use_old_area": false + }, + "mobile_badge": null + }, + "up_session": "", + "pk_status": 0, + "pk_id": 0, + "battle_id": 0, + "allow_change_area_time": 0, + "allow_upload_cover_time": 0, + "studio_info": { + "status": 0, + "master_list": [] + } + } +} +``` + +</details> + +## 获取用户对应的直播间状态 + +> https://api.live.bilibili.com/room/v1/Room/getRoomInfoOld + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|-----|-----|---------|-----|-----| +| mid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|---------------------| +| code | num | 返回值 | 0:成功<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +|----------------|-----|-----------|------------------| +| roomStatus | num | 直播间状态 | 0:无房间<br />1:有房间 | +| roundStatus | num | 轮播状态 | 0:未轮播<br />1:轮播 | +| live_status | num | 直播状态 | 0:未开播<br />1:直播中 | +| url | str | 直播间网页url | | +| title | str | 直播间标题 | | +| cover | str | 直播间封面url | | +| online | num | 直播间人气 | 值为上次直播时刷新 | +| roomid | num | 直播间id(短号) | | +| broadcast_type | num | 0 | | +| online_hidden | num | 0 | | + +**示例:** + +查询用户`mid=322892`的直播间信息 + +```shell +curl -G 'https://api.live.bilibili.com/room/v1/Room/getRoomInfoOld' \ +--data-urlencode 'mid=322892' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "roomStatus": 1, + "roundStatus": 0, + "live_status": 1, + "url": "https://live.bilibili.com/5441", + "title": "好久没当黑铁主播了", + "cover": "http://i0.hdslb.com/bfs/live/room_cover/833f7ff506bac17c06010e8834922993657505b2.jpg", + "online": 268602, + "roomid": 5441, + "broadcast_type": 0, + "online_hidden": 0 + } +} +``` + +</details> + +## 获取房间页初始化信息 + +> https://api.live.bilibili.com/room/v1/Room/room_init + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|-----|-----|------------|-----|-----| +| id | num | 目标直播间号(短号) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|------------------------| +| code | num | 返回值 | 0:成功<br />60004:直播间不存在 | +| msg | str | 错误信息 | 默认为ok | +| message | str | 错误信息 | 默认为ok | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------------|------|--------------|------------------------------------| +| room_id | num | 直播间真实id | | +| short_id | num | 直播间id(短号) | | +| uid | num | 主播用户mid | | +| need_p2p | num | 是否p2p | | +| is_hidden | bool | 是否隐藏 | | +| is_locked | bool | 是否锁定 | | +| is_portrait | bool | 是否竖屏 | | +| live_status | num | 直播状态 | 0:未开播<br />1:直播中<br />2:轮播中 | +| hidden_till | num | 隐藏时间戳 | | +| lock_till | num | 锁定时间戳 | | +| encrypted | bool | 是否加密 | | +| pwd_verified | bool | 加密房间是否通过密码验证 | `encrypted`=true时才有意义 | +| live_time | num | 开播时间 | 未开播时为`-62170012800` | +| room_shield | num | 未知 | | +| is_sp | num | 是否为特殊直播间 | 0:普通直播间<br />1:付费直播间 | +| special_type | num | 特殊直播间标志 | 0:普通直播间<br />1:付费直播间<br />2:拜年祭直播间 | + +**示例:** + +查询直播间`id=76`的直播间信息 + +```shell +curl -G 'https://api.live.bilibili.com/room/v1/Room/room_init' \ +--data-urlencode 'id=76' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "ok", + "message": "ok", + "data": { + "room_id": 14073662, + "short_id": 76, + "uid": 50333369, + "need_p2p": 0, + "is_hidden": false, + "is_locked": false, + "is_portrait": false, + "live_status": 1, + "hidden_till": 0, + "lock_till": 0, + "encrypted": false, + "pwd_verified": false, + "live_time": 1602151186, + "room_shield": 1, + "is_sp": 0, + "special_type": 0 + } +} +``` + +</details> + +## 获取主播信息 + +> https://api.live.bilibili.com/live_user/v1/Master/info + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|-----|-----|---------|-----|-----| +| uid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|------------------| +| code | num | 返回值 | 0:成功<br />1:参数错误 | +| msg | str | 错误信息 | 默认为空 | +| message | str | 错误信息 | 默认为空 | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +|----------------|-----|-----------|------------| +| info | obj | 主播信息 | | +| exp | obj | 经验等级 | | +| follower_num | num | 主播粉丝数 | | +| room_id | num | 直播间id(短号) | | +| medal_name | str | 粉丝勋章名 | | +| glory_count | num | 主播荣誉数 | | +| pendant | str | 直播间头像框url | | +| link_group_num | num | 0 | **作用尚不明确** | +| room_news | obj | 主播公告 | | + +`info`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-----------------|-----|---------|-------------------------| +| uid | num | 主播mid | | +| uname | str | 主播用户名 | | +| face | str | 主播头像url | | +| official_verify | obj | 认证信息 | | +| gender | num | 主播性别 | -1:保密<br />0:女<br />1:男 | + +`info`中的`official_verify`对象: + +| 字段 | 类型 | 内容 | 备注 | +|------|-----|--------|------------------------------| +| type | num | 主播认证类型 | -1:无<br />0:个人认证<br />1:机构认证 | +| desc | str | 主播认证信息 | | + +`exp`对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------------|-----|------|-----| +| master_level | obj | 主播等级 | | + +`exp`中的`master_level`对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-------|--------|-----| +| level | num | 当前等级 | | +| color | num | 等级框颜色 | | +| current | array | 当前等级信息 | | +| next | array | 下一等级信息 | | + +`master_level`中的`current`数组: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|------|-----| +| 0 | num | 升级积分 | | +| 1 | num | 总积分 | | + +`master_level`中的`next`数组: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|------|-----| +| 0 | num | 升级积分 | | +| 1 | num | 总积分 | | + +`room_news`对象: + +| 字段 | 类型 | 内容 | 备注 | +|------------|-----|------|-----| +| content | str | 公告内容 | | +| ctime | str | 公告时间 | | +| ctime_text | str | 公告日期 | | + +**示例:** + +查询直播间`mid=2`的主播信息 + +```shell +curl -G 'https://api.live.bilibili.com/live_user/v1/Master/info' \ +--data-urlencode 'uid=2' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "", + "message": "", + "data": { + "info": { + "uid": 2, + "uname": "碧诗", + "face": "https://i0.hdslb.com/bfs/face/ef0457addb24141e15dfac6fbf45293ccf1e32ab.jpg", + "official_verify": { + "type": 0, + "desc": "bilibili个人认证:bilibili创始人(站长)" + }, + "gender": 1 + }, + "exp": { + "master_level": { + "level": 30, + "color": 10512625, + "current": [ + 2870000, + 11883810 + ], + "next": [ + 3730000, + 15613810 + ] + } + }, + "follower_num": 926624, + "room_id": 1024, + "medal_name": "逸国", + "glory_count": 0, + "pendant": "", + "link_group_num": 0, + "room_news": { + "content": "", + "ctime": "", + "ctime_text": "" + } + } +} +``` + +</details> + +## 获取直播间基本信息 + +> https://api.live.bilibili.com/xlive/web-room/v1/index/getRoomBaseInfo + +*请求方式: GET* + +注: 亦可用于批量获取 + +<!--{ + "gh": [745] +}--> + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | ---- | --- | - | - | +| req_biz | str | `web_room_componet` | 必要 | | +| room_ids | num | 直播间短ID | 不必要 | 多个重复该参数即可 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0: 成功<br />-400: 请求错误 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| by_uids | obj | 空 | | +| by_room_ids | obj | 直播间信息 | | + +`data`中的`by_room_ids`对象: + +以直播间长ID为键, 直播间信息为值的, 按键名降序排序 + +`by_room_ids`中的值对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| room_id | num | 直播间长ID | | +| uid | num | 主播用户mid | | +| area_id | num | 直播间分区ID | | +| live_status | num | 直播状态 | 0: 未开播<br />1: 直播中<br />2: 轮播中 | +| live_url | str | 直播间网页url | | +| parent_area_id | num | 直播间父分区ID | | +| title | str | 直播间标题 | | +| parent_area_name | str | 直播间父分区名称 | | +| area_name | str | 直播间分区名称 | | +| live_time | str | 开播时间 | `yyyy-MM-dd HH:mm:ss` | +| description | str | 直播间简介 | | +| tags | str | 直播间标签 | 以 `,` 分隔 | +| attention | num | 关注数 | | +| online | num | 在线人数 | | +| short_id | num | 直播间短ID | 为0是无短号 | +| uname | str | 主播用户名 | | +| cover | str | 直播间封面url | | +| background | str | 直播间背景url | | +| join_slide | num | 1 | | +| live_id | num | 0 | | +| live_id_str | str | "0" | | + +**示例:** + +```shell +curl -G 'https://api.live.bilibili.com/xlive/web-room/v1/index/getRoomBaseInfo' \ +--url-query 'req_biz=web_room_componet' \ +--url-query 'room_ids=1' \ +--url-query 'room_ids=3 +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "by_uids": {}, + "by_room_ids": { + "23058": { + "room_id": 23058, + "uid": 11153765, + "area_id": 190, + "live_status": 0, + "live_url": "https://live.bilibili.com/23058", + "parent_area_id": 5, + "title": "哔哩哔哩音悦台", + "parent_area_name": "电台", + "area_name": "唱见电台", + "live_time": "0000-00-00 00:00:00", + "description": "<p>这里是哔哩哔哩官方音乐台喔!</p><p>一起来听音乐吧ε=ε=(ノ≧∇≦)ノ</p><p>没想到蒸汽配圣诞下装,意外的很暴露呢=3=</p>\n", + "tags": "", + "attention": 225431, + "online": 0, + "short_id": 3, + "uname": "3号直播间", + "cover": "", + "background": "https://i0.hdslb.com/bfs/live/2836bb7b84c792e2c6aadfd4d1cce13484775fa3.jpg", + "join_slide": 1, + "live_id": 0, + "live_id_str": "0" + }, + "5440": { + "room_id": 5440, + "uid": 9617619, + "area_id": 701, + "live_status": 2, + "live_url": "https://live.bilibili.com/5440", + "parent_area_id": 11, + "title": "华为nova Flip新生之夜", + "parent_area_name": "知识", + "area_name": "科技·科学", + "live_time": "0000-00-00 00:00:00", + "description": "<p>华为novaFlip新生之夜正在直播中!备案号:Z0910417240818001<br></p>", + "tags": "", + "attention": 17848313, + "online": 0, + "short_id": 1, + "uname": "哔哩哔哩直播", + "cover": "http://i0.hdslb.com/bfs/live/1a862058e4211a5e73a8a1bf0635953ea08a4091.jpg", + "background": "http://i0.hdslb.com/bfs/live/ec518ede15d4c2547c83cb59f14752450c0889b0.jpg", + "join_slide": 1, + "live_id": 0, + "live_id_str": "0" + } + } + } +} +``` + +</details> + +## 批量查询直播间状态 + +> https://api.live.bilibili.com/room/v1/Room/get_status_info_by_uids + +*请求方式:GET/POST* + +认证方式:无 (无需添加Cookie) + +**url参数 (GET方式):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|--------|-------|------------|-----|-----| +| uids[] | array | 要查询的主播 mid | 必要 | | + +**正文参数 (POST方式):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|------|------|------------|-----|-----| +| uids | nums | 要查询的主播 mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|-------------------------| +| code | num | 返回值 | 0:成功<br />-111:csrf校验失败 | +| message | str | 错误信息 | 默认为success | +| msg | str | 错误信息 | 默认为success | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-----|-----|-------|------------| +| uid | str | 直播间信息 | 实际字段为主播mid | + +`uid`对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------------------|-----|-----------|------------------------------| +| title | str | 直播间标题 | | +| room_id | num | 直播间房间号 | 直播间实际房间号 | +| uid | num | 主播mid | | +| online | num | 直播间在线人数 | | +| live_time | num | 开播时间戳,单位秒,未开播时为0 | | +| live_status | num | 直播间开播状态 | 0:未开播<br />1:正在直播<br />2:轮播中 | +| short_id | num | 直播间房间号 | 直播间短房间号,常见于签约主播 | +| area | num | 直播间分区id | | +| area_name | str | 直播间分区名 | | +| area_v2_id | num | 直播间新版分区id | | +| area_v2_name | str | 直播间新版分区名 | | +| area_v2_parent_id | num | 直播间父分区id | | +| area_v2_parent_name | str | 直播间父分区名 | | +| uname | str | 主播用户名 | | +| face | str | 主播头像url | | +| tag_name | str | 直播间标签 | | +| tags | str | 直播间自定标签 | | +| cover_from_user | str | 直播间封面url | | +| keyframe | str | 直播间关键帧url | | +| lock_till | str | 直播间封禁信息 | | +| hidden_till | str | 直播间隐藏信息 | | +| broadcast_type | num | 直播类型 | 0:普通直播<br />1:手机直播 | + +**示例:** + +查询用户`mid=672328094`的直播间信息 + +```shell +# GET方式 +curl -G 'https://api.live.bilibili.com/room/v1/Room/get_status_info_by_uids' +--data-urlencode 'uids[]=672328094' + +# POST方式 +curl 'https://api.live.bilibili.com/room/v1/Room/get_status_info_by_uids' \ +-H "Content-Type: application/json" \ +-d "{\"uids\": [672328094]}" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "message": "success", + "data": { + "672328094": { + "title": "【B限】玩个毛线", + "room_id": 22637261, + "uid": 672328094, + "online": 4087370, + "live_time": 0, + "live_status": 2, + "short_id": 0, + "area": 6, + "area_name": "生活娱乐", + "area_v2_id": 371, + "area_v2_name": "虚拟主播", + "area_v2_parent_name": "虚拟主播", + "area_v2_parent_id": 9, + "uname": "嘉然今天吃什么", + "face": "http://i2.hdslb.com/bfs/face/d399d6f5cf7943a996ae96999ba3e6ae2a2988de.jpg", + "tag_name": "日常,学习,萌宠,厨艺,手机直播", + "tags": "", + "cover_from_user": "http://i0.hdslb.com/bfs/live/new_room_cover/f3ed7a782c13086e536ec8bc6e9593bb4918f905.jpg", + "keyframe": "http://i0.hdslb.com/bfs/live-key-frame/keyframe041722000000226372619dr3m8.jpg", + "lock_till": "0000-00-00 00:00:00", + "hidden_till": "0000-00-00 00:00:00", + "broadcast_type": 0 + } + } +} +``` + +</details> + + +## 清晰度代码 + +| 代码 | 说明 | +|-------|-----| +| 30000 | 杜比 | +| 20000 | 4K | +| 10000 | 原画 | +| 400 | 蓝光 | +| 250 | 超清 | +| 150 | 高清 | +| 80 | 流畅 | + +## 获取直播间信息 + +> https://api.live.bilibili.com/xlive/web-room/v2/index/getRoomPlayInfo + +*请求方式:GET* + +认证方式:无 (无需添加Cookie) + +**url参数 (GET方式):** + +| 参数名 | 类型 | 内容 | 必填 | 备注 | +|----------|-----|-------|-----|------------------------------------------------| +| room_id | num | 直播间id | 必要 | | +| protocol | str | 直播协议 | 必要 | 0:http_stream<br/>1:http_hls<br/>可多选, 使用英文逗号分隔 | +| format | str | 格式 | 必要 | 0:flv<br/>1:ts<br/>2:fmp4<br/>可多选, 使用英文逗号分隔 | +| codec | str | 编码格式 | 必要 | 0:AVC<br/>1:HEVC<br/>可多选, 使用英文逗号分隔 | +| qn | num | 清晰度编码 | | 默认`150`<br/>[清晰度代码](#清晰度代码) | +| platform | str | `web` | | | +| ptype | num | `8` | | | +| dolby | num | `5` | | | +| panorama | num | `1` | | | +| only_audio | num | 是否为音频流 | 非必要 | 默认为视频流,`1` 为音频流 | + +**json回复:** + +根对象: + +| 字段名 | 类型 | 内容 | 备注 | +|---------|-----|------|-----------------------| +| code | num | 响应码 | 0:成功<br/>1002002:参数错误 | +| message | str | 0 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段名 | 类型 | 内容 | 备注 | +|-------------------|-------|-----------|---------------------------| +| room_id | num | 直播间id | | +| short_id | num | 直播间短id | | +| uid | num | 主播uid | | +| is_hidden | bool | 直播间是否被隐藏 | | +| is_locked | bool | 直播间是否被锁定 | | +| is_portrait | bool | 是否竖屏 | | +| live_status | num | 直播状态 | 0:未开播<br/>1:直播中<br/>2:轮播中 | +| hidden_till | num | 隐藏结束时间 | | +| lock_till | num | 封禁结束时间 | 秒级时间戳 | +| encrypted | bool | 直播间为加密直播间 | | +| pwd_verified | bool | 是否通过密码验证 | 当`encrypted`为`true`时才有意义 | +| live_time | num | 本次开播时间 | 秒级时间戳 | +| room_shield | num | | | +| all_special_types | array | | | +| playurl_info | obj | 直播流信息 | | + +`playurl_info`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-----------|-----|-----|-----| +| conf_json | str | | | +| playurl | obj | | | + +`playurl`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-----------|-------|-------|-----| +| cid | num | 直播间id | | +| g_qn_desc | array | 清晰度列表 | | +| stream | array | 直播流信息 | | +| p2p_data | obj | | | +| dolby_qn | | | | + +`g_qn_desc`数组中的对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-----------|-----|-------|-----------------| +| qn | num | 清晰度代码 | [清晰度代码](#清晰度代码) | +| desc | str | 清晰度描述 | | +| hdr_desc | str | | | +| attr_desc | | | | + +`stream`数组中的对象 + +| 字段名 | 类型 | 内容 | 备注 | +|---------------|-------|------|-----| +| protocol_name | str | 协议名 | | +| format | array | 格式列表 | | + +`format`数组中的对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-------------|-------|------|-----| +| format_name | str | 格式名 | | +| codec | array | 编码列表 | | + +`codec`数组中的对象 + +| 字段名 | 类型 | 内容 | 备注 | +|------------|-------|-----------|-----------------| +| codec_name | str | 编码名 | | +| current_qn | num | 当前清晰度编码 | [清晰度代码](#清晰度代码) | +| accept_qn | array | 可用清晰度编码列表 | [清晰度代码](#清晰度代码) | +| base_url | str | 播放源路径 | | +| url_info | array | 域名信息列表 | | +| hdr_qn | null | | | +| dolby_type | num | | | +| attr_name | str | | | + +`url_info`数组中的对象 + +| 字段名 | 类型 | 内容 | 备注 | +|------------|-----|-------|-----| +| host | str | 域名 | | +| extra | str | URL参数 | | +| stream_ttl | num | | | + +`p2p_data`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-----------|------|-----|-----| +| p2p | bool | | | +| p2p_type | num | | | +| m_p2p | bool | | | +| m_servers | null | | | + +**示例:** + +查询`room_id=3`的直播间信息 + +```shell +curl -L -X GET 'https://api.live.bilibili.com/xlive/web-room/v2/index/getRoomPlayInfo?room_id=3&protocol=0,1&format=0,1,2&codec=0,1&qn=10000' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "room_id": 23058, + "short_id": 3, + "uid": 11153765, + "is_hidden": false, + "is_locked": false, + "is_portrait": false, + "live_status": 1, + "hidden_till": 0, + "lock_till": 0, + "encrypted": false, + "pwd_verified": true, + "live_time": 1671425336, + "room_shield": 1, + "all_special_types": [], + "playurl_info": { + "conf_json": "{\"cdn_rate\":10000,\"report_interval_sec\":150}", + "playurl": { + "cid": 23058, + "g_qn_desc": [ + { + "qn": 30000, + "desc": "杜比", + "hdr_desc": "", + "attr_desc": null + }, + { + "qn": 20000, + "desc": "4K", + "hdr_desc": "", + "attr_desc": null + }, + { + "qn": 10000, + "desc": "原画", + "hdr_desc": "", + "attr_desc": null + }, + { + "qn": 400, + "desc": "蓝光", + "hdr_desc": "HDR", + "attr_desc": null + }, + { + "qn": 250, + "desc": "超清", + "hdr_desc": "HDR", + "attr_desc": null + }, + { + "qn": 150, + "desc": "高清", + "hdr_desc": "", + "attr_desc": null + }, + { + "qn": 80, + "desc": "流畅", + "hdr_desc": "", + "attr_desc": null + } + ], + "stream": [ + { + "protocol_name": "http_stream", + "format": [ + { + "format_name": "flv", + "codec": [ + { + "codec_name": "avc", + "current_qn": 10000, + "accept_qn": [ + 10000, + 150 + ], + "base_url": "/live-bvc/462997/live_11153765_9369560.flv?", + "url_info": [ + { + "host": "https://cn-hbcd-cu-02-20.bilivideo.com", + "extra": "expires=1674103815&pt=web&deadline=1674103815&len=0&oi=1963941079&platform=web&qn=10000&trid=1000061f434c07ac4f4184820bfb141e75e8&uipk=100&uipv=100&nbs=1&uparams=cdn,deadline,len,oi,platform,qn,trid,uipk,uipv,nbs&cdn=cn-gotcha01&upsig=f494aa9e92e24943061fe5082494ec44&sk=33541455720f64c7671bc1480acfb176&p2p_type=1&src=57345&sl=1&free_type=0&sid=cn-hbcd-cu-02-20&chash=1&sche=ban&score=12&pp=rtmp&machinezone=jd&source=onetier&trace=0&site=92e80b6f3ebfd393e7d1c1e2e648d9c1&order=1", + "stream_ttl": 3600 + } + ], + "hdr_qn": null, + "dolby_type": 0, + "attr_name": "" + } + ] + } + ] + }, + { + "protocol_name": "http_hls", + "format": [ + { + "format_name": "ts", + "codec": [ + { + "codec_name": "avc", + "current_qn": 10000, + "accept_qn": [ + 10000, + 150 + ], + "base_url": "/live-bvc/462997/live_11153765_9369560.m3u8?", + "url_info": [ + { + "host": "https://cn-hbcd-cu-02-20.bilivideo.com", + "extra": "expires=1674103815&len=0&oi=1963941079&pt=web&qn=10000&trid=1003061f434c07ac4f4184820bfb141e75e8&sigparams=cdn,expires,len,oi,pt,qn,trid&cdn=cn-gotcha01&sign=4f9bcec18e3afdca04b31ffb285ec915&sk=33541455720f64c7671bc1480acfb176&p2p_type=1&src=57345&sl=1&free_type=0&sid=cn-hbcd-cu-02-20&chash=1&sche=ban&score=12&pp=rtmp&machinezone=jd&source=onetier&trace=0&site=92e80b6f3ebfd393e7d1c1e2e648d9c1&order=1", + "stream_ttl": 3600 + } + ], + "hdr_qn": null, + "dolby_type": 0, + "attr_name": "" + } + ] + }, + { + "format_name": "fmp4", + "codec": [ + { + "codec_name": "avc", + "current_qn": 10000, + "accept_qn": [ + 10000, + 150 + ], + "base_url": "/live-bvc/462997/live_11153765_9369560/index.m3u8?", + "url_info": [ + { + "host": "https://cn-hbcd-cu-02-20.bilivideo.com", + "extra": "expires=1674103815&len=0&oi=1963941079&pt=web&qn=10000&trid=1007061f434c07ac4f4184820bfb141e75e8&sigparams=cdn,expires,len,oi,pt,qn,trid&cdn=cn-gotcha01&sign=cc57dce528316d8389f2f34e7bd15f5c&sk=a99391b8b4d5779b2e32e41dbc989d2d&flvsk=33541455720f64c7671bc1480acfb176&p2p_type=1&src=57345&sl=1&free_type=0&sid=cn-hbcd-cu-02-20&chash=1&sche=ban&bvchls=1&score=12&pp=rtmp&machinezone=jd&source=onetier&trace=0&site=92e80b6f3ebfd393e7d1c1e2e648d9c1&order=1", + "stream_ttl": 3600 + }, + { + "host": "https://c1--cn-gotcha208.bilivideo.com", + "extra": "expires=1674103815&len=0&oi=1963941079&pt=web&qn=10000&trid=1007061f434c07ac4f4184820bfb141e75e8&sigparams=cdn,expires,len,oi,pt,qn,trid&cdn=cn-gotcha208&sign=2ff96adf5056c8dbee546955260fc2df&sk=a99391b8b4d5779b2e32e41dbc989d2d&p2p_type=1&src=57345&sl=1&free_type=0&pp=rtmp&machinezone=jd&source=onetier&trace=0&site=92e80b6f3ebfd393e7d1c1e2e648d9c1&order=2", + "stream_ttl": 3600 + } + ], + "hdr_qn": null, + "dolby_type": 0, + "attr_name": "" + } + ] + } + ] + } + ], + "p2p_data": { + "p2p": true, + "p2p_type": 1, + "m_p2p": false, + "m_servers": null + }, + "dolby_qn": null + } + } + } +} +``` + +</details> + + + + + +## 获取直播间主播信息 + +> https://api.live.bilibili.com/live_user/v1/UserInfo/get_anchor_in_room + +*请求方式: GET* + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|---------|-----|------|-----|-------| +| roomid | num | 直播间号 | 必要 | 可以为短号 | + + +**json回复:** + + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|-----------------| +| code | num | 返回值 | 0:成功 (直播间不存在也为0) | +| message | str | 错误信息 | | +| msg | str | 错误信息 | | +| data | obj | 信息本体 | | + + + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------------------|-----------|--------|-----------------------------| +| info | obj | 主播信息 | | +| level | obj | 直播等级 | | +| san | num | 主播san值 | 12满分 | + + +`info`对象: + + +| 字段 | 类型 | 内容 | 备注 | +|-------------------|------|------------------|----------| +| uid | num | 主播mid | | +| uname | str | 主播用户名 | | +| face | str | 主播头像URL | | +| rank | str | 主播排名 | | +| platform_user_level | num | 平台用户等级 | | +| mobile_verify | num | 手机验证状态 | | +| identification | num | 身份认证状态 | | +| official_verify | obj | 认证信息 | | +| vip_type | num | VIP类型 | | +| gender | num | 主播性别 | -1:保密<br />0:女<br />1:男 | + + +`info`中的`official_verify`对象: + +| 字段 | 类型 | 内容 | 备注 | +|------|------|----------|-----| +| type | num | 主播认证类型 | -1:无<br />0:个人认证<br />1:机构认证 | +| desc | str | 主播认证信息 | | +| role | num | 未知 | | + +`level`对象: + + + +| 字段 | 类型 | 内容 | 备注 | +|--------------|------|------------------|----------| +| uid | num | 用户ID | | +| cost | num | 消费金额 | | +| rcost | num | 充值金额 | | +| user_score | str | 用户积分 | | +| vip | num | VIP状态 | | +| vip_time | str | VIP到期时间 | | +| svip | num | SVIP状态 | | +| svip_time | str | SVIP到期时间 | | +| update_time | str | 更新时间 | | +| master_level | obj | 主播等级 | | +| user_level | num | 用户等级 | | +| color | num | 颜色值 | | +| anchor_score | num | 主播积分 | | + + + +`level` 中的 `master_level`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------------|------|------------------|----------| +| level | num | 主播等级 | | +| color | num | 颜色值 | | +| current | list | 当前积分 | | +| next | list | 下一等级积分 | | +| anchor_score | num | 主播积分 | | +| upgrade_score | num | 升级积分 | | +| master_level_color | num | 主播等级颜色值 | | +| sort | str | 排名 | | + + +**示例:** + +查询`roomid=1`的直播间主播信息 + +```shell +curl -G 'https://api.live.bilibili.com/live_user/v1/UserInfo/get_anchor_in_room' \ +--data-urlencode 'roomid=1' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "message": "success", + "data": { + "info": { + "uid": 9617619, + "uname": "哔哩哔哩直播", + "face": "https://i0.hdslb.com/bfs/face/8f6a614a48a3813d90da7a11894ae56a59396fcd.jpg", + "rank": "10000", + "platform_user_level": 6, + "mobile_verify": 1, + "identification": 1, + "official_verify": { + "type": 1, + "desc": "哔哩哔哩直播官方账号", + "role": 3 + }, + "vip_type": 2, + "gender": -1 + }, + "level": { + "uid": 9617619, + "cost": 7782673656, + "rcost": 20199200291, + "user_score": "0", + "vip": 0, + "vip_time": "0000-00-00 00:00:00", + "svip": 0, + "svip_time": "0000-00-00 00:00:00", + "update_time": "2024-08-08 17:13:12", + "master_level": { + "level": 40, + "color": 16746162, + "current": [0, 147013810], + "next": [0, 147013810], + "anchor_score": 201992002, + "upgrade_score": 0, + "master_level_color": 16746162, + "sort": "\u003E10000" + }, + "user_level": 60, + "color": 16752445, + "anchor_score": 201992002 + }, + "san": 12 + } +} +``` + +</details> diff --git a/bb-api-collect/docs/live/live_area.md b/bb-api-collect/docs/live/live_area.md new file mode 100644 index 0000000000..4f86ef9abd --- /dev/null +++ b/bb-api-collect/docs/live/live_area.md @@ -0,0 +1,210 @@ +# 直播间分区 + +## 获取全部直播间分区列表 + +> https://api.live.bilibili.com/room/v1/Area/getList + +*请求方式:GET* + +直播分区共有两级,分别是父分区和子分区 + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | ---------- | ------------- | +| code | num | 返回值 | 0:成功 | +| msg | str | 错误信息 | 默认为success | +| message | str | 错误信息 | 默认为success | +| data | array | 父分区列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---- | +| 0 | obj | 父分区1 | | +| n | obj | 父分区(n+1) | | +| …… | obj | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------- | ---- | +| id | num | 父分区id | | +| name | name | 父分区名 | | +| list | list | 子分区列表 | | + +`data`数组中的对象中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---- | +| 0 | obj | 子分区1 | | +| n | obj | 子分区(n+1) | | +| …… | obj | …… | …… | + +`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ----------------- | ---------------- | +| id | str | 子分区id | | +| parent_id | str | 父分区id | | +| old_area_id | str | 旧分区id | | +| name | str | 子分区名 | | +| act_id | str | 0 | **作用尚不明确** | +| pk_status | str | ??? | **作用尚不明确** | +| hot_status | num | 是否为热门分区 | 0:否<br />1:是 | +| lock_status | str | 0 | **作用尚不明确** | +| pic | str | 子分区标志图片url | | +| parent_name | str | 父分区名 | | +| area_type | num | | | + +**示例:** + +如想在`网游`父分区下的`英雄联盟`分区开播,则查到子分区id为`86` + +```shell +curl 'https://api.live.bilibili.com/room/v1/Area/getList' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "success", + "message": "success", + "data": [ + { + "id": 2, + "name": "网游", + "list": [ + { + "id": "86", + "parent_id": "2", + "old_area_id": "4", + "name": "英雄联盟", + "act_id": "0", + "pk_status": "0", + "hot_status": 1, + "lock_status": "0", + "pic": "http://i0.hdslb.com/bfs/vc/dcfb14f14ec83e503147a262e7607858b05d7ac0.png", + "parent_name": "网游", + "area_type": 0 + }, + { + "id": "252", + "parent_id": "2", + "old_area_id": "3", + "name": "逃离塔科夫", + "act_id": "0", + "pk_status": "0", + "hot_status": 1, + "lock_status": "0", + "pic": "http://i0.hdslb.com/bfs/vc/762a7de3dd5fe8165d1d55b232484a017941592f.png", + "parent_name": "网游", + "area_type": 0 + }, + { + "id": "80", + "parent_id": "2", + "old_area_id": "1", + "name": "绝地求生", + "act_id": "0", + "pk_status": "0", + "hot_status": 1, + "lock_status": "0", + "pic": "http://i0.hdslb.com/bfs/vc/43ca83fdcd10505eaeef1b76cf8ce642a53b94da.png", + "parent_name": "网游", + "area_type": 0 + }, + ………… + ] + }, + { + "id": 3, + "name": "手游", + "list": [ + { + "id": "35", + "parent_id": "3", + "old_area_id": "12", + "name": "王者荣耀", + "act_id": "0", + "pk_status": "0", + "hot_status": 1, + "lock_status": "0", + "pic": "http://i0.hdslb.com/bfs/vc/0fefa924760b2dd492a12dddafe179bfa1216918.png", + "parent_name": "手游", + "area_type": 0 + }, + ………… + ] + }, + { + "id": 6, + "name": "单机", + "list": [ + { + "id": "236", + "parent_id": "6", + "old_area_id": "1", + "name": "主机游戏", + "act_id": "0", + "pk_status": "0", + "hot_status": 1, + "lock_status": "0", + "pic": "http://i0.hdslb.com/bfs/vc/edb636ee59f902e3134a2790545045bddd70978e.png", + "parent_name": "单机", + "area_type": 0 + }, + ………… + ] + }, + { + "id": 1, + "name": "娱乐", + "list": [ + { + "id": "21", + "parent_id": "1", + "old_area_id": "10", + "name": "视频唱见", + "act_id": "0", + "pk_status": "1", + "hot_status": 1, + "lock_status": "0", + "pic": "http://i0.hdslb.com/bfs/vc/72b93ddafdf63c9f0b626ad546847a3c03c92b6f.png", + "cate_id": "12", + "parent_name": "娱乐", + "area_type": 0 + }, + ………… + ] + }, + { + "id": 5, + "name": "电台", + "list": [ + { + "id": "190", + "parent_id": "5", + "old_area_id": "10", + "name": "唱见电台", + "act_id": "0", + "pk_status": "0", + "hot_status": 0, + "lock_status": "0", + "pic": "http://i0.hdslb.com/bfs/vc/d22d7fafbf9b24e2bc3ce1df5eb9f006e6035e5d.png", + "parent_name": "电台", + "area_type": 0 + }, + ………… + ] + } + ] +} +``` + +</details> diff --git a/bb-api-collect/docs/live/live_bill.md b/bb-api-collect/docs/live/live_bill.md new file mode 100644 index 0000000000..16c07fd8de --- /dev/null +++ b/bb-api-collect/docs/live/live_bill.md @@ -0,0 +1,328 @@ +# 直播流水 + +## 获取所有礼物列表 + +> https://api.live.bilibili.com/gift/v1/master/getGiftTypes + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | -------------- | +| code | num | 返回值 | 0:成功 | +| msg | str | 错误信息 | 默认为 success | +| message | str | 错误信息 | 默认为 success | +| data | array | 礼物列表 | | + +`data` 数组: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | -------- | ------------------------------------------------------------------------------ | +| gift_id | num | 礼物 id | | +| gift_name | str | 礼物名称 | | +| price | num | 瓜子数量 | 电池礼物为金瓜子数量,银瓜子礼物为银瓜子数量。 (金瓜子数量 / 100 = 电池数量) | + +*注:特殊礼物如舰长、提督、总督等没有 `price` 字段* + +<details> +<summary>查看响应示例:</summary> + +```jsonc + { + "code": 0, + "msg": "success", + "message": "success", + "data": [ + { + "gift_id": 10001, + "gift_name": "总督" + }, + { + "gift_id": 10002, + "gift_name": "提督" + }, + { + "gift_id": 10003, + "gift_name": "舰长" + }, + { + "gift_id": 12000, + "gift_name": "醒目留言" + }, + { + "gift_id": 1, + "price": 100, + "gift_name": "辣条" + }, + { + "gift_id": 3, + "price": 9900, + "gift_name": "B坷垃" + }, + { + "gift_id": 6, + "price": 1000, + "gift_name": "亿圆" + }, + { + "gift_id": 30426, + "price": 0, + "gift_name": "BLS能量石" + }, + { + "gift_id": 30706, + "price": 1000, + "gift_name": "生日快乐" + }, + { + "gift_id": 30707, + "price": 5200, + "gift_name": "生日蛋糕" + }, + { + "gift_id": 30708, + "price": 52000, + "gift_name": "生日王冠" + }, + { + "gift_id": 31049, + "price": 6600, + "gift_name": "干杯" + }, + { + "gift_id": 31116, + "price": 6600, + "gift_name": "干杯" + }, + { + "gift_id": 31251, + "price": 6600, + "gift_name": "干杯" + }, + { + "gift_id": 31531, + "price": 0, + "gift_name": "PK票" + }, + { + "gift_id": 31588, + "price": 19900, + "gift_name": "星河入梦" + }, + { + "gift_id": 31589, + "price": 131400, + "gift_name": "我星永恒" + }, + { + "gift_id": 32276, + "price": 0, + "gift_name": "粉丝团灯牌" + }, + // ... + ] + } +``` + +</details> + +## 获取流水 + +> https://api.live.bilibili.com/xlive/revenue/v1/giftStream/getReceivedGiftStreamNextList + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +请求参数: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ------------- | ----------------------- | ---------- | -------------------------------------- | +| limit | num | 一页有多少条目 | 必要 | | +| coin_type | num | 礼物类型 | 必要 | 0 为所有,1 为电池礼物,2 为银瓜子礼物 | +| begin_time | date / string | 流水的日期 | 必要 | 格式为 yyyy-MM-dd | +| uname | string | 筛选的用户名 | 非必要 | | +| last_id | num | 上一页页末的礼物列表 id | 翻页时必要 | 见下方 `list` 数组说明 | +| gift_id | num | 筛选的礼物 id | | | + +请求示例:`https://api.live.bilibili.com/xlive/revenue/v1/giftStream/getReceivedGiftStreamNextList?limit=20&coin_type=0&begin_time=2023-01-01` + +请求示例(翻页时):`https://api.live.bilibili.com/xlive/revenue/v1/giftStream/getReceivedGiftStreamNextList?last_id=13834493&limit=20&coin_type=0&begin_time=2023-01-01` + +**json 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | -------- | -------------- | +| code | num | 返回值 | 0:成功 | +| msg | str | 错误信息 | 默认为 success | +| message | str | 错误信息 | 默认为 success | +| data | object | 流水 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ----- | -------------- | -------------- | +| has_more | num | 是否由下一页 | 1 为是,0 为否 | +| total_hamster | num | 总的金仓鼠收益 | | +| list | array | 礼物列表 | | + +`list` 数组: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------ | ---------- | ------------------------------------- | -------------------------- | +| uid | num | 送礼用户的 uid | | +| uname | str | 用户名 | | +| time | date / str | 送礼时间 | | +| gift_id | num | 礼物 id | | +| gift_name | str | 礼物名字 | | +| gift_img | str | 礼物图片链接 | | +| gift_num | num | 礼物数量 | | +| hamster | num | 金仓鼠数量 | | +| gold | num | 礼物价值(金瓜子) | | +| silver | num | 礼物价值(银瓜子) | | +| ios_hamster | num | 由 iOS 端送出的礼物所收到的金仓鼠 | | +| normal_hamster | num | 一般情况下收到的金仓鼠 | | +| ios_gold | num | 由 iOS 端送出的礼物所收到的金瓜子数量 | | +| normal_gold | num | 一般情况下收到的金瓜子数量 | | +| is_hybrid | bool | 是否混合 | 作用不明 | +| id | num | 此项 id | 用于翻页 | +| is_open_platfrom | num | 是否开放平台 | 作用不明 | +| open_platfrom_rate | num | 开放平台比率 (?) | 作用不明 | +| receive_title | str | | 作用不明 ,一般为 `"主播"` | +| room_id | num | 送礼房间id | 如果礼物为上舰,此项为 `0` | + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "uid": 0000000000, + "uname": "XXXXXXX", + "time": "2023-01-01 00:00:00", + "gift_id": 31216, + "gift_name": "i了i了", + "gift_img": "https://s1.hdslb.com/bfs/live/1157a445487b39c0b7368d91b22290c60fa665b2.png", + "gift_num": 1, + "hamster": 50, + "gold": 100, + "silver": 0, + "ios_hamster": 0, + "normal_hamster": 50, + "ios_gold": 0, + "normal_gold": 100, + "is_hybrid": false, + "id": 14269551, + "is_open_platfrom": 0, + "open_platfrom_rate": 0, + "receive_title": "主播", + "room_id": 000001 + }, + { + "uid": 0000000000, + "uname": "XXXXXXX", + "time": "2023-01-01 00:00:00", + "gift_id": 10003, + "gift_name": "舰长", + "gift_img": "https://i0.hdslb.com/bfs/live/f1be2a2d5b227ce72641de1ad64bcc7f9e4111c3.png", + "gift_num": 1, + "hamster": 69000, + "gold": 138000, + "silver": 0, + "ios_hamster": 0, + "normal_hamster": 69000, + "ios_gold": 0, + "normal_gold": 138000, + "is_hybrid": false, + "id": 14258453, + "is_open_platfrom": 0, + "open_platfrom_rate": 0, + "receive_title": "主播", + "room_id": 000000 + }, + { + "uid": 0000000000, + "uname": "XXXXXXX", + "time": "2023-01-01 00:00:00", + "gift_id": 31036, + "gift_name": "小花花", + "gift_img": "https://s1.hdslb.com/bfs/live/8b40d0470890e7d573995383af8a8ae074d485d9.png", + "gift_num": 1, + "hamster": 50, + "gold": 100, + "silver": 0, + "ios_hamster": 0, + "normal_hamster": 50, + "ios_gold": 0, + "normal_gold": 100, + "is_hybrid": false, + "id": 14243903, + "is_open_platfrom": 0, + "open_platfrom_rate": 0, + "receive_title": "主播", + "room_id": 000001 + }, + { + "uid": 0000000000, + "uname": "XXXXXXX", + "time": "2023-01-01 00:00:00", + "gift_id": 30047, + "gift_name": "友谊的小船", + "gift_img": "https://s1.hdslb.com/bfs/live/b33c94c51b669bd88f811ecf5f4e34a1db22a648.png", + "gift_num": 1, + "hamster": 2450, + "gold": 4900, + "silver": 0, + "ios_hamster": 0, + "normal_hamster": 2450, + "ios_gold": 0, + "normal_gold": 4900, + "is_hybrid": false, + "id": 14242683, + "is_open_platfrom": 0, + "open_platfrom_rate": 0, + "receive_title": "主播", + "room_id": 000001 + }, + { + "uid": 0000000000, + "uname": "XXXXXXX", + "time": "2023-01-01 00:00:00", + "gift_id": 31738, + "gift_name": "粉丝团灯牌", + "gift_img": "https://s1.hdslb.com/bfs/live/cbed3bb0a894369b49ceaf0b5337b4491b75ac42.png", + "gift_num": 1, + "hamster": 0, + "gold": 1000, + "silver": 1000, + "ios_hamster": 0, + "normal_hamster": 0, + "ios_gold": 0, + "normal_gold": 0, + "is_hybrid": false, + "id": 14237376, + "is_open_platfrom": 0, + "open_platfrom_rate": 0, + "receive_title": "主播", + "room_id": 000001 + } + ], + "has_more": 1, + "total_hamster": 122050 + } +} +``` + +</details> diff --git a/bb-api-collect/docs/live/live_data.md b/bb-api-collect/docs/live/live_data.md new file mode 100644 index 0000000000..5cec881a8d --- /dev/null +++ b/bb-api-collect/docs/live/live_data.md @@ -0,0 +1,183 @@ +# 直播数据 + +## 获取直播场次的直播数据 + +> https://api.live.bilibili.com/xlive/app-blink/v1/live/StopLiveData + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +只能获取自己的直播数据。最好在直播结束时立即请求,否则直播时长可能不准确。 + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| live_key | str | 标记直播场次的key | 必要 | 若不提供将会获得无效数据 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0:成功<br />-101:未登录 | +| message | str | 提示信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| LiveTime | num | 该直播场次的直播时长 | 单位:秒,直播结束后还会增长 | +| AddFans | num | 该直播场次的新增粉丝 | | +| HamsterRmb | num | 该直播场次的收益 | | +| NewFansClub | num | 该直播场次新获得粉丝勋章数量 | | +| DanmuNum | num | 该直播场次的弹幕条数 | | +| MaxOnline | num | 该直播场次的最大在线? | [需要验证] | +| WatchedCount | num | 该直播场次的看过人数 | | + +**示例:** + +获取自己的直播数据 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/live/StopLiveData?live_key=634808443264569139' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "LiveTime": 77603, + "AddFans": 0, + "HamsterRmb": 0, + "NewFansClub": 0, + "DanmuNum": 3, + "MaxOnline": 13, + "WatchedCount": 2 + } +} +``` + +</details> + +## 获取直播表现 + +> https://api.live.bilibili.com/xlive/app-blink/v1/date/Overview + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0:成功<br />-101:未登录 | +| message | str | 提示信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| graph | arr | 图表数据 | 在界面显示为雷达图 | +| propose | null | (?) | | + +`data.graph` 数组: + +| 索引 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| 0 | obj | 数据类别 | | +| … | obj | 数据类别 | | + +`data.graph` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| name | str | 显示的名称 | | +| index | str | 类别标识 | | +| me | num | 自己在这个类别的数值 | | +| max | num | 这个类别最外侧那条线的数值 | | +| aver | num | 同水平主播在这个类别的数值 | | + +**示例:** + +获取自己的直播表现 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/date/Overview' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "graph": [ + { + "name": "收益", + "index": "income", + "me": 0, + "max": 9.27, + "aver": 8.04 + }, + { + "name": "累计观看", + "index": "watchedCount", + "me": 5.13, + "max": 7.01, + "aver": 6.17 + }, + { + "name": "新增粉丝", + "index": "fans", + "me": 0, + "max": 2.58, + "aver": 0 + }, + { + "name": "用户平均观看时长", + "index": "watchTime", + "me": 9.31, + "max": 11.82, + "aver": 10.88 + }, + { + "name": "开播时长", + "index": "broadcast", + "me": 17.57, + "max": 17.42, + "aver": 16.6 + }, + { + "name": "弹幕数量", + "index": "barrage", + "me": 7.37, + "max": 8.02, + "aver": 6.91 + } + ], + "propose": null + } +} +``` + +</details> diff --git a/bb-api-collect/docs/live/live_replay.md b/bb-api-collect/docs/live/live_replay.md new file mode 100644 index 0000000000..e158cbc77a --- /dev/null +++ b/bb-api-collect/docs/live/live_replay.md @@ -0,0 +1,2147 @@ +# 直播回放 + +<!-- 网页端: https://link.bilibili.com/#/my-room/live-record ;移动端: https://live.bilibili.com/p/html/live-app-playback/index.html#new --> + +注: 直播回放相关接口较新,随时可能出现变化。 + +## 获取直播回放列表 + +> https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/AnchorGetReplayList + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +只能获取自己14天的回放,详细信息请查看[对应页面](https://link.bilibili.com/#/my-room/live-record) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| page | num | 页码 | 非必要 | 默认第1页 | +| page_size | num | 每页内容数量 | 非必要 | 默认30项,最大30项 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0:成功<br />-101:未登录 | +| message | str | 提示信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| replay_info | arr | 回放信息列表 | 无结果时为`null` | +| pagination | obj | 分页信息 | | +| archive_flag | bool | (?) | 作用尚不明确 | +| can\_edit | num | (?) | 作用尚不明确 | +| can_upload | bool | (?) | 作用尚不明确 | +| has_third_platform_live| bool | (?) | 作用尚不明确 | + +`data.replay_info` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| replay_id | num | 直播回放id | | +| live_info | obj | 直播信息 | | +| video_info | obj | 回放视频信息 | | +| alarm_info | obj | 警报信息 | | +| room_id | num | 直播间id | | +| live_key | str | 标记直播场次的key | | +| start_time | num | 直播开始秒时间戳 | 调用[开始直播](manage.md#开始直播)接口的时间 | +| end_time | num | 直播结束秒时间戳 | 调用[关闭直播](manage.md#关闭直播)接口的时间 | + +`data.replay_info[i].live_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| title | str | 直播标题 | 直播结束时的标题 | +| cover | str | 直播封面 | | +| live_time | num | 直播时间 | 同`data.replay_info[i].start_time` | +| live_type | num | 直播类型? | 作用尚不明确 | +| platform | str | 直播平台 | | + +`data.replay_info[i].video_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| replay_status | num | 回放状态 | 作用尚不明确 | +| estimated_time | str | 直播回放合成结束时间 | 未合成时为`"1970-01-01 08:00:00"` | +| duration | num | 直播时长 | 单位秒 | +| download_url | str | 下载链接片段 | 整场直播回放合成成功时存在<br />建议通过[请求整场直播回放下载链接](#请求整场直播回放下载链接)来获取下载链接 | +| alert_code | num | 快速检查警告代码 | 整场直播回放合成失败时不存在 | +| alert_message | str | 快速检查警告信息 | 整场直播回放合成失败时不存在 | + +`data.replay_info[i].alarm_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 回放合成警报代码 | | +| message | str | 回放合成错误信息 | | +| cur_time | num | 当前时间戳 | Unix秒时间戳 | +| is_ban_publish | bool | 是否禁止发布? | | + +`data.pagination` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| page | num | 请求的页码 | | +| page_size | num | 内容数量 | | +| total | num | 总计内容数量 | | + +**示例:** + +获取自己直播回放列表的第1页,每页2项 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/AnchorGetReplayList?page=1&page_size=2' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "replay_info": [ + { + "replay_id": 13517082, + "live_info": { + "title": "随缘摸鱼", + "cover": "https://i0.hdslb.com/bfs/live/59fc254c1f51a962dbf69ae85e4920f2f6fb8dcd.png", + "live_time": 1756479520, + "live_type": 1, + "platform": "android_link" + }, + "video_info": { + "replay_status": -8, + "estimated_time": "1970-01-01 08:00:00", + "duration": 9350, + "alert_code": 2, + "alert_message": "录像时长远小于开播时长,请关注直播时网络状况" + }, + "alarm_info": { + "code": -8, + "message": "直播内容存在违规片段", + "cur_time": 1756496581, + "is_ban_publish": false + }, + "room_id": 1899237171, + "live_key": "637117671085969203", + "start_time": 1756479520, + "end_time": 1756488870 + }, + { + "replay_id": 13487274, + "live_info": { + "title": "随缘摸鱼", + "cover": "https://i0.hdslb.com/bfs/live/59fc254c1f51a962dbf69ae85e4920f2f6fb8dcd.png", + "live_time": 1756385910, + "live_type": 1, + "platform": "android_link" + }, + "video_info": { + "replay_status": 2, + "estimated_time": "1970-01-01 08:00:00", + "duration": 14985, + "alert_code": 2, + "alert_message": "录像时长远小于开播时长,请关注直播时网络状况" + }, + "alarm_info": { + "code": 2, + "message": "录像生成失败,请稍后再试", + "cur_time": 1756496581, + "is_ban_publish": false + }, + "room_id": 1899237171, + "live_key": "636823272552664883", + "start_time": 1756385910, + "end_time": 1756400895 + } + ], + "pagination": { + "page": 1, + "page_size": 2, + "total": 16 + }, + "archive_flag": false, + "can_edit": 1, + "can_upload": false, + "has_third_platform_live": false + } +} +``` + +</details> + +## 获取某位主播的回放列表 + +> https://api.live.bilibili.com/xlive/web-room/v1/videoService/GetOtherSliceList + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +需要获得那位主播的授权才能获取数据。 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| live_uid | num | 目标主播的uid | 必要 | | +| time_range | num | 回放列表的时间范围 | 非必要 | 默认获取近14天<br />1:近3天<br />2:近7天<br />3:近14天 | +| page | num | 页码 | 非必要 | 默认第1页 | +| page_size | num | 每页内容数量 | 非必要 | 默认30项,最大30项 | +| web_location | str | (?) | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -101:未登录<br />0:成功<br />301:没有剪辑权限 | +| message | str | 提示信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | 与[获取直播回放列表](#获取直播回放列表)接口的信息本体相同 | + +**示例:** + +获取某位主播的回放列表,他已授权你回放剪辑权限 + +```shell +curl 'https://api.live.bilibili.com/xlive/web-room/v1/videoService/GetOtherSliceList?live_uid=1&time_range=1&page=1&page_size=2' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "replay_info": [ + { + "replay_id": 14657830, + "live_info": { + "title": "随缘摸鱼", + "cover": "https://i0.hdslb.com/bfs/live/59fc254c1f51a962dbf69ae85e4920f2f6fb8dcd.png", + "live_time": 1760352139, + "live_type": 1, + "platform": "android_link" + }, + "video_info": { + "replay_status": 2, + "estimated_time": "1970-01-01 08:00:00", + "duration": 858, + "alert_code": 2, + "alert_message": "录像时长远小于开播时长,请关注直播时网络状况" + }, + "alarm_info": { + "code": 2, + "message": "录像生成失败,请稍后再试", + "cur_time": 1760362012, + "is_ban_publish": false + }, + "room_id": 1899237171, + "live_key": "648437353747320627", + "start_time": 1760352139, + "end_time": 1760352997 + }, + { + "replay_id": 14646585, + "live_info": { + "title": "随缘摸鱼", + "cover": "https://i0.hdslb.com/bfs/live/59fc254c1f51a962dbf69ae85e4920f2f6fb8dcd.png", + "live_time": 1760285326, + "live_type": 1, + "platform": "android_link" + }, + "video_info": { + "replay_status": 2, + "estimated_time": "1970-01-01 08:00:00", + "duration": 464, + "alert_code": 2, + "alert_message": "录像时长远小于开播时长,请关注直播时网络状况" + }, + "alarm_info": { + "code": 2, + "message": "录像生成失败,请稍后再试", + "cur_time": 1760362012, + "is_ban_publish": false + }, + "room_id": 1899237171, + "live_key": "648321565723987763", + "start_time": 1760285326, + "end_time": 1760285790 + } + ], + "pagination": { + "page": 1, + "page_size": 2, + "total": 4 + }, + "archive_flag": false, + "can_edit": 1, + "can_upload": false, + "has_third_platform_live": false + } +} +``` + +</details> + +## 获取已发布片段的信息 + +> https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/AnchorGetVideoSliceList + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +只能获取主播自己的已发布片段。 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| page | num | 页码 | 非必要 | 默认第1页 | +| page_size | num | 每页内容数量 | 非必要 | 默认20项,最大20项 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0:成功<br />-101:未登录 | +| message | str | 提示信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| list | arr | 切片信息 | | +| page | num | 请求的页码 | | +| page_size | num | 内容数量 | | +| total | num | 总计内容数量 | | + +`data.list` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| silce_id | num | 切片id | | +| av_title | str | 切片标题 | | +| av_cover | str | 切片封面 | | +| av_status | num | 切片状态 | 1:发布中<br />2:已投稿<br />3:投稿失败 | +| avid | num | 切片视频的avid | 状态为2时存在 | +| ctime | str | 切片创建时间 | | +| start_tm | str | 切片开始时间 | | +| end_tm | str | 切片结束时间 | | +| av_duration | num | 切片时长 | 状态为2且创作中心出现有效视频时长时存在 | +| failed_reason | str | 失败原因 | 状态为3时存在,2024-09-01前发布失败的切片可能不存在 | +| live_type | num | (?) | 作用尚不明确 | +| cnt_play | num | 播放数 | 视频有播放时存在;若该页出现任意状态不为2的项也会不存在 | +| cnt_danmaku | num | 弹幕数 | 视频有弹幕时存在;若该页出现任意状态不为2的项也会不存在 | + +**示例:** + +获取自己第1页的已发布片段信息,每页3项 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/AnchorGetVideoSliceList?page=1&page_size=3' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "slice_id": 882357, + "av_title": "2025051720 error", + "av_cover": "https://i0.hdslb.com/bfs/live/59fc254c1f51a962dbf69ae85e4920f2f6fb8dcd.png", + "av_status": 1, + "ctime": "2025-05-18 18:13:13", + "start_tm": "2025-05-17 21:07:04", + "end_tm": "2025-05-17 21:16:00", + "live_type": 1 + }, + { + "slice_id": 879189, + "av_title": "2025051721 zzz 0", + "av_cover": "https://i0.hdslb.com/bfs/live/59fc254c1f51a962dbf69ae85e4920f2f6fb8dcd.png", + "av_status": 3, + "ctime": "2025-05-18 00:32:52", + "start_tm": "2025-05-17 21:07:34", + "end_tm": "2025-05-17 23:02:03", + "failed_reason": "duration_false", + "live_type": 1 + }, + { + "slice_id": 876259, + "av_title": "202505171449", + "av_cover": "https://i0.hdslb.com/bfs/live/59fc254c1f51a962dbf69ae85e4920f2f6fb8dcd.png", + "av_status": 2, + "avid": 114521830065531, + "ctime": "2025-05-17 14:49:18", + "start_tm": "2025-05-17 14:19:36", + "end_tm": "2025-05-17 14:23:48", + "av_duration": 341, + "live_type": 1 + } + ], + "page": 1, + "page_size": 3, + "total": 347 + } +} +``` + +</details> + +## 获取你为某位主播剪辑的已发布片段 + +> https://api.live.bilibili.com/xlive/web-room/v1/videoService/GetPublishedList + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +需要获得那位主播的授权才能获取数据。 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| live_uid | num | 目标主播的uid | 必要 | | +| page | num | 页码 | 非必要 | 默认第1页 | +| page_size | num | 每页内容数量 | 非必要 | 默认20项,最大20项 | +| web_location | str | (?) | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -101:未登录<br />0:成功<br />301:没有剪辑权限 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| slice_info | arr 或 null | 切片信息 | 无内容时为`null` | +| pagination | obj | 分页信息 | | + +`data.slice_info` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| slice_id | num | 切片id | | +| uid | num | 发布者uid? | | +| live_uid | num | 主播uid | | +| live_key | str | 标记直播场次的key | | +| title | str | 切片标题 | | +| cover | str | 切片封面 | 若未在[给某位主播投稿直播回放片段](#给某位主播投稿直播回放片段)接口中传递封面将会无此字段,同时及大可能导致发布失败且没有失败提示 | +| high_light_id | num | 绑定的高光时刻 | 在[给某位主播投稿直播回放片段](#给某位主播投稿直播回放片段)接口中提供相关参数时存在 | +| start_time | str | 片段开始时间 | | +| end_time | str | 片段结束时间 | | +| status | num | 切片状态 | 参见[获取已发布片段的信息](#获取已发布片段的信息)接口 | +| fail_reason | str | 失败提示 | 状态为3且有提示信息时存在 | +| filename | str | 切片视频文件名 | 内部使用,可作为参数传递给创作中心,视频合成完成时存在 | +| avid | num | 切片视频的avid | 状态为2时存在 | +| ctime | str | 切片创建时间 | | +| av_duration | num | 切片时长 | 状态为2且创作中心出现有效视频时长时存在 | +| live_type | num | (?) | 作用尚不明确 | + +`data.pagination` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| page | num | 请求的页码 | | +| page_size | num | 内容数量 | | +| total | num | 总计内容数量 | `data.slice_info`有内容时存在 | + +**示例:** + +获取为某位主播剪辑的已发布片段,他已授权你回放剪辑权限 + +```shell +curl 'https://api.live.bilibili.com/xlive/web-room/v1/videoService/GetPublishedList?live_uid=1&page=1&page_size=20' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "slice_info": [ + { + "slice_id": 4302, + "uid": 438160221, + "live_uid": 438160221, + "live_key": "648506223547911987", + "title": "test202510201450", + "cover": "https://i0.hdslb.com/bfs/live/59fc254c1f51a962dbf69ae85e4920f2f6fb8dcd.png", + "high_light_id": 12810575, + "start_time": "2025-10-13 23:11:00", + "end_time": "2025-10-13 23:14:00", + "status": 3, + "fail_reason": "合成失败,重新编辑投稿试试~", + "ctime": "2025-10-20 14:50:18", + "live_type": 1 + }, + { + "slice_id": 4300, + "uid": 438160221, + "live_uid": 438160221, + "live_key": "648437353747320627", + "title": "test202510201318", + "start_time": "2025-10-13 18:42:36", + "end_time": "2025-10-13 18:43:36", + "status": 3, + "filename": "n251020tx1rbha851nt85y2fj21bygm8", + "ctime": "2025-10-20 13:41:00", + "live_type": 1 + }, + { + "slice_id": 4299, + "uid": 438160221, + "live_uid": 438160221, + "live_key": "648437353747320627", + "title": "test202510201318", + "cover": "https://i0.hdslb.com/bfs/live/59fc254c1f51a962dbf69ae85e4920f2f6fb8dcd.png", + "start_time": "2025-10-13 18:42:35", + "end_time": "2025-10-13 18:43:35", + "status": 2, + "filename": "n251020tx2u500g1krssxg3om5ou8bdw", + "avid": 115404865274992, + "ctime": "2025-10-20 13:36:44", + "av_duration": 63, + "live_type": 1 + } + ], + "pagination": { + "page": 1, + "page_size": 20, + "total": 4 + } + } +} +``` + +</details> + +## 获取回放剪辑草稿列表 + +> https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/GetDraftList + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +只能获取主播自己的回放剪辑草稿。 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| page | num | 页码 | 非必要 | 默认第1页 | +| page_size | num | 每页内容数量 | 非必要 | 默认30项,最大30项 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -101:未登录<br />0:成功<br />301:没有剪辑权限 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| draft_info | arr | 草稿信息 | 无结果时为`null` | +| pagination | obj | 分页信息 | | + +`data.draft_info` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| id | num | 回放剪辑id | | +| title | str | 回放剪辑标题 | | +| cover | str | 回放剪辑封面 | 有封面时存在;若不存在将使用 https://s1.hdslb.com/bfs/static/blive/blfe-link-center/static/img/default.187078d.png | +| live\_key | str | 标记直播场次的key | | +| ctime | str | 回放剪辑创建时间 | | +| live_start_time | str | 直播开始时间 | | +| live_end_time | str | 直播结束时间 | | +| live_type | num | (?) | 作用尚不明确 | + +`data.pagination` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| page | num | 请求的页码 | | +| page_size | num | 内容数量 | | +| total | num | 总计内容数量 | | + +**示例:** + +请求自己的回放剪辑草稿列表 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/GetDraftList?page=1&page_size=12' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "draft_info": [ + { + "id": 988275, + "title": "直播场次 2025-05-19 20:45:04", + "live_key": "609431465787395891", + "ctime": "2025-05-22 01:08:20", + "live_start_time": "2025-05-19 20:45:04", + "live_end_time": "2025-05-20 09:40:13", + "live_type": 1 + }, + { + "id": 987665, + "title": "直播场次 2025-05-19 20:45:04 切片", + "cover": "http://i0.hdslb.com/bfs/live/9bdf1df3d823734c59382120a9a7c10b177dbefd.png", + "live_key": "609431465787395891", + "ctime": "2025-05-21 20:28:48", + "live_start_time": "2025-05-19 20:45:04", + "live_end_time": "2025-05-20 09:40:13", + "live_type": 1 + } + ], + "pagination": { + "page": 1, + "page_size": 30, + "total": 2 + } + } +} +``` + +</details> + +## 获取你为某位主播剪辑的草稿 + +> https://api.live.bilibili.com/xlive/web-room/v1/videoService/GetDraftList + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +需要获得那位主播的授权才能获取数据。 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| live_uid | num | 目标主播的uid | 必要 | | +| page | num | 页码 | 非必要 | 默认第1页 | +| page_size | num | 每页内容数量 | 非必要 | 默认30项,最大30项 | +| web_location | str | (?) | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -101:未登录<br />0:成功<br />301:没有剪辑权限 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | 与[获取回放剪辑草稿列表](#获取回放剪辑草稿列表)接口的信息本体相同 | + +**示例:** + +获取你为某位主播剪辑的草稿,他已授权你回放剪辑权限 + +```shell +curl 'https://api.live.bilibili.com/xlive/web-room/v1/videoService/GetDraftList?live_uid=1&page=1&page_size=20' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "draft_info": [ + { + "id": 1148889, + "title": "直播场次 2025-09-30 23:53:06", + "live_key": "645328214036844339", + "ctime": "2025-10-14 14:48:22", + "live_start_time": "2025-09-30 23:53:06", + "live_end_time": "2025-10-01 01:41:29", + "live_type": 1 + } + ], + "pagination": { + "page": 1, + "page_size": 30, + "total": 1 + } + } +} +``` + +</details> + +## 删除某个回放剪辑草稿 + +> https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/DeleteSliceDraft + +*请求方法: POST* + +认证方式: Cookie (SESSDATA) + +鉴权方式: Cookie中`bili_jct`的值正确并与`csrf`相同 + +主播删除自己的回放剪辑草稿时使用。 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| draft_id | num | 回放剪辑id | 必要 | | +| csrf_token | str | CSRF Token(位于cookie) | 非必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -400:参数错误<br />-101:未登录<br />-111:csrf校验失败<br />0:成功<br />206:无可操作草稿 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | `0` | | +| message | str | `""` | | + +**示例:** + +删除回放剪辑id为`988275`的草稿 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/DeleteSliceDraft' \ + --data-urlencode 'draft_id=988275' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx;bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "code": 0, + "message": "" + } +} +``` + +</details> + +## 删除为某个主播剪辑的草稿 + +> https://api.live.bilibili.com/xlive/web-room/v1/videoService/DeleteSliceDraft + +*请求方法: POST* + +认证方式: Cookie (SESSDATA) + +鉴权方式: Cookie中`bili_jct`的值正确并与`csrf`相同 + +删除你为某位主播创建的回放剪辑草稿。 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**正文参数( application/json ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| draft_id | num | 回放剪辑id | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -400:请求错误<br />-101:未登录<br />-111:csrf校验失败<br />0:成功<br />206:无可操作草稿 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | 与[](#删除某个回放剪辑草稿)的信息本体相同 | + +**示例:** + +删除回放剪辑id为`1148889`的草稿 + +```shell +curl 'https://api.live.bilibili.com/xlive/web-room/v1/videoService/DeleteSliceDraft?csrf=xxx' \ + -H 'Content-Type: application/json' \ + -b 'SESSDATA=xxx;bili_jct=xxx' \ + -d '{"draft_id":1148889}' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "code": 0, + "message": "" + } +} +``` + +</details> + +## 请求整场直播回放下载链接 + +> https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/AnchorVideoDownload + +*请求方法: POST* + +认证方式: Cookie (SESSDATA) + +鉴权方式: Cookie中`bili_jct`的值正确并与`csrf`相同 + +是否生成回放取决于回放状态,处于可生成回放状态且未生成整场直播回放时将进行生成。 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| record_id | num | 直播回放id | 必要(可选) | `record_id`和`live_key`必选其一 | +| live_key | str | 标记直播场次的key | 必要(可选) | `record_id`和`live_key`必选其一 | +| csrf_token | str | CSRF Token(位于cookie) | 非必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -101:未登录<br />-111:csrf校验失败<br />0:成功<br />100:非法参数<br />210:回放id或场次key无效<br />217:未找到直播录像 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| record | obj | 回放状态 | | +| download_url | str | 回放下载链接 | 完成时存在 | +| download_url_list | arr | 回放下载链接列表 | 完成时存在 | + +`data.record` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| uid | num | 用户mid | | +| record_id | num | 直播回放id | | +| status | num | 回放状态 | | +| estimated_time | num | 预计结束时间 | Unix秒时间戳 | +| current_time | num | 当前时间 | Unix秒时间戳 | +| merge_time | num | 开始合并时间 | Unix秒时间戳 | +| toast | str | 提示信息 | 失败时存在 | + +`data.download_url_list` 数组: + +| 项 | 类型 | 内容 | 备注 | +| -- | --- | --- | --- | +| 0 | str | 回放下载链接 | | + +**示例:** + +请求回放id为`10597910`的下载链接 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/AnchorVideoDownload' \ + --data-urlencode 'record_id=10597910' \ + --data-urlencode 'live_key=607942821532667699' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx;bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "record": { + "uid": 438160221, + "record_id": 10597910, + "status": 30, + "estimated_time": 1747639543, + "current_time": 1747639106, + "merge_time": 1747638665 + }, + "download_url": "https://upos-sz-mirrorali.bilivideo.com/ugcever/n250519sa3hkpirw61hjskuit4d9fdsj.mp4?deadline=1747682306&gen=record2vod&os=upos&trid=da40b42594d5446da29cb0d2b2f25f45&uparams=deadline,gen,os,trid&upsig=c6ac5f218af40b2c120b3f5add2e4d6b&attname=直播回放_2025-05-13_20-49-04.mp4", + "download_url_list": [ + "https://upos-sz-mirrorali.bilivideo.com/ugcever/n250519sa3hkpirw61hjskuit4d9fdsj.mp4?deadline=1747682306&gen=record2vod&os=upos&trid=da40b42594d5446da29cb0d2b2f25f45&uparams=deadline,gen,os,trid&upsig=c6ac5f218af40b2c120b3f5add2e4d6b&attname=直播回放_2025-05-13_20-49-04.mp4" + ] + } +} +``` + +</details> + +## 获取回放的信息 + +> https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/GetAnchorVideoUidRecordsSubsect + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| record_id | num | 直播回放id | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -400:参数错误<br />-101:未登录<br />0:成功 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | 失败时不可用 | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| list | arr | 回放信息列表 | | + +`data.list` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| uid | num | 用户mid | | +| record_id | num | 直播回放id | | +| title | str | 直播标题 | | +| cover | str | 直播封面 | | +| status | num | 回放状态 | | +| start\_time | num | 直播开始时间 | Unix秒时间戳 | +| end_time | num | 直播结束时间 | Unix秒时间戳 | + +**示例:** + +获取回放id为`10707664`的信息 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/GetAnchorVideoUidRecordsSubsect?record_id=10707664' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "uid": 438160221, + "record_id": 10707664, + "title": "摆", + "cover": "https://i0.hdslb.com/bfs/live/59fc254c1f51a962dbf69ae85e4920f2f6fb8dcd.png", + "status": 2, + "start_time": 1747508293, + "end_time": 1747508499 + } + ] + } +} +``` + +</details> + +## 轮询回放状态 + +> https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/GetAnchorVideoUidRecord + +*请求方法: POST* + +认证方式: Cookie (SESSDATA) + +鉴权方式: Cookie中`bili_jct`的值正确并与`csrf`相同 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| records | str | 直播回放id列表 | 必要 | 用`,`分隔 | +| csrf_token | str | CSRF Token(位于cookie) | 非必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -101:未登录<br />-400:参数错误<br />0:成功 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| list | arr | 查询结果 | 无效的id会被忽略 | + +`data.list` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| uid | num | 用户mid | | +| record_id | num | 直播回放id | | +| status | num | 回放状态 | | +| current_time | num | 当前时间戳 | Unix秒时间戳 | +| estimated_time | num | 预计结束时间戳 | 初次[请求回放下载链接](#请求整场直播回放下载链接)后存在 | +| merge_time | num | 合成开始时间戳 | 初次[请求回放下载链接](#请求整场直播回放下载链接)后存在 | + +**示例:** + +查询各种回放id + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/GetAnchorVideoUidRecord' \ + --data-urlencode 'records=10727160,10597910,10687720,10230000,99999999' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx;bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "uid": 91089731, + "record_id": 10230000, + "status": 2, + "current_time": 1747641604 + }, + { + "uid": 438160221, + "record_id": 10597910, + "status": 30, + "estimated_time": 1747639543, + "current_time": 1747641604, + "merge_time": 1747638665 + }, + { + "uid": 438160221, + "record_id": 10687720, + "status": -30, + "estimated_time": 1747635525, + "current_time": 1747641604, + "merge_time": 1747635486, + "toast": "因直播过程中存在推流质量问题(网络波动或丢包),本场直播回放无法合成" + }, + { + "uid": 3493299121817771, + "record_id": 10727160, + "status": 2, + "current_time": 1747641604 + } + ] + } +} +``` + +</details> + +## 获取切片视频流 + +> https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/GetSliceStream + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +主播获取自己的切片视频流时使用。 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| live_key | str | 标记直播场次的key | 必要 | 对应[获取直播回放列表](#获取直播回放列表)的`data.replay_info[i].live_key` | +| start_time | num | 直播开始时间戳 | 必要 | 对应[获取直播回放列表](#获取直播回放列表)的`data.replay_info[i].start_time` | +| end_time | num | 直播结束时间戳 | 必要 | 对应[获取直播回放列表](#获取直播回放列表)的`data.replay_info[i].end_time` | +| web_location | str | (?) | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -400:参数缺失<br />-101:未登录<br />0:成功<br />100:非法参数<br />202:场次无效 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| list | arr 或 null | 直播回放视频列表 | 如果该场回放没有视频流将为`null` | +| ban_list | null 或 arr | 不可发布的回放时间 | 如果该场回放没有不可发布的时间将为`null` | + +`data.list` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| start_time | num | 片段开始时间戳 | Unix秒时间戳 | +| end_time | num | 片段结束时间戳 | Unix秒时间戳 | +| stream | str | 直播回放视频流 | | +| type | num | 类型? | 2:一般回放? | + +`data.ban_list` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| start_time | num | 不可发布片段的开始时间戳 | Unix秒时间戳 | +| end_time | num | 不可发布片段的结束时间戳 | Unix秒时间戳 | + +**示例:** + +获取某个场次的视频流 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/GetSliceStream?live_key=637117671085969203&start_time=1756479520&end_time=1756488870' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "start_time": 1756479528, + "end_time": 1756488870, + "stream": "https://bvc-live.bilivideo.com/hls-record-gateway/videoPlay?none=为了防止信息泄露,不提供完整链接。目前该视频流可以获取违规片段的视频。", + "type": 2 + } + ], + "ban_list": [ + { + "start_time": 1756487070, + "end_time": 1756488870 + } + ] + } +} +``` + +</details> + +## 获取某位主播的切片视频流 + +> https://api.live.bilibili.com/xlive/web-room/v1/videoService/GetUserSliceStream + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +需要获得那位主播的授权才能获取数据。 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| live_key | str | 标记直播场次的key | 必要 | 对应[获取直播回放列表](#获取直播回放列表)的`data.replay_info[i].live_key` | +| start_time | num | 直播开始时间戳 | 必要 | 对应[获取直播回放列表](#获取直播回放列表)的`data.replay_info[i].start_time` | +| end_time | num | 直播结束时间戳 | 必要 | 对应[获取直播回放列表](#获取直播回放列表)的`data.replay_info[i].end_time` | +| live_uid | num | 目标主播的uid | 必要 | | +| web_location | str | (?) | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -400:参数缺失<br />-101:未登录<br />0:成功<br />100:非法参数<br />202:场次无效<br />301:没有剪辑权限 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| list | arr | 直播回放视频列表 | 与[获取切片视频流](#获取切片视频流)的`data.list`数组相同 | + +**示例:** + +获取某个场次的视频流,他已授权你回放剪辑权限 + +```shell +curl 'https://api.live.bilibili.com/xlive/web-room/v1/videoService/GetUserSliceStream?live_key=646125196758224691&start_time=1759507126&end_time=1759513440&live_uid=1' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "start_time": 1759507132, + "end_time": 1759508222, + "stream": "https://bvc-live.bilivideo.com/hls-record-gateway/videoPlay?none=获取视频流的参数。", + "type": 2 + } + ] + } +} +``` + +</details> + +## 获取直播会话数据 + +> https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/GetLiveSessionData + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +主播获取自己的直播会话数据时使用。 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| live_key | str | 标记直播场次的key | 必要 | | +| start_tm | str | 开始时间 | 必要 | 格式为`yyyy-mm-dd HH:MM:SS`,时区为`UTC+08:00`(中国标准时间);取值对实际无影响 | +| end_tm | str | 开始时间 | 必要 | 格式为`yyyy-mm-dd HH:MM:SS`,时区为`UTC+08:00`(中国标准时间);取值对实际无影响 | +| web_location | str | (?) | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -500:服务器错误<br />-101:未登录<br />0:成功<br />100:非法参数<br />202:场次无效 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| session_data | arr | 会话数据 | | +| max_danmaku | num | 弹幕最多的时间戳 | Unix秒时间戳,没有则为`0` | +| max_pcu | num | 进房最多的时间戳 | Unix秒时间戳,没有则为`0` | +| max_value | num | (?) | 效果未知 | +| high_light_data | arr | 高光时刻数据 | | +| ass_url | str | ASS字幕链接 | 用作弹幕显示 | +| high_light_stat | obj | 高亮状态信息 | | + +`data.session_data` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| ts | num | 采样时间 | Unix秒时间戳 | +| value | num | 弹幕数量 | | + +`data.high_light_data` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| id | num | 高光id | | +| type | num | 高光类型 | 1:弹幕<br />2:进房 | +| start_time | num | 高光开始时间戳 | Unix秒时间戳 | +| end_time | num | 高光结束时间戳 | Unix秒时间戳 | +| title | str | 高光提示标题 | | +| cover | str | (?) | 目前为`""` | +| extra | str | (?) | 目前为`""` | + +`data.high_light_stat` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| original_hl | num | “高光时刻”数量 | 有“高光时刻”时存在 | +| manual_hl | num | “已保存”数量 | 有“已保存”时存在,调用[手动保存高亮片段](#手动保存高亮片段)进行保存 | + +注: 可能还存在一个“回溯录制”的字段。 + +**示例:** + +获取场次key为`607113721045847859`的会话数据 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/GetLiveSessionData?live_key=607113721045847859&start_tm=0000-01-01+00:00:00&end_tm=1970-01-01+00:00:00' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```jsonc +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "session_data": [ + { + "ts": 1752927300, + "value": 0 + }, + { + "ts": 1752927360, + "value": 0 + }, + { + "ts": 1752927420, + "value": 0 + }, + // 省略掉大部分重复内容 + { + "ts": 1752946620, + "value": 0 + }, + { + "ts": 1752946680, + "value": 0 + }, + { + "ts": 1752946740, + "value": 0 + } + ], + "max_danmaku": 1752928860, + "max_pcu": 1752928200, + "max_value": 0, + "high_light_data": [ + { + "id": 9628113, + "type": 1, + "start_time": 1752928860, + "end_time": 1752929040, + "title": "弹幕高光 Top 1", + "cover": "", + "extra": "" + }, + { + "id": 9628114, + "type": 1, + "start_time": 1752938460, + "end_time": 1752938640, + "title": "弹幕高光 Top 2", + "cover": "", + "extra": "" + }, + { + "id": 9628115, + "type": 1, + "start_time": 1752938040, + "end_time": 1752938220, + "title": "弹幕高光 Top 3", + "cover": "", + "extra": "" + }, + { + "id": 9628112, + "type": 2, + "start_time": 1752928140, + "end_time": 1752928320, + "title": "进房高光时刻", + "cover": "", + "extra": "" + } + ], + "ass_url": "https://jssz-boss.hdslb.com/live2arc_anchor_video/dmass_1899237171_625727121464233779.ass?X-Amz-Algorithm=AWS4-HMAC-SHA256\u0026X-Amz-Credential=y4zI4XTQzlOkmSKg%2F20250802%2Fjssz%2Fs3%2Faws4_request\u0026X-Amz-Date=20250802T072504Z\u0026X-Amz-Expires=7200\u0026X-Amz-SignedHeaders=host\u0026X-Amz-Signature=384b42382469059a1f4c6b04c7bd2290a0c74c01375df1681eedb3ba8aca5c3c", + "high_light_stat": { + "original_hl": 4, + "manual_hl": 6 + } + } +} +``` + +</details> + +## 获取某位主播的直播会话数据 + +> https://api.live.bilibili.com/xlive/web-room/v1/videoService/GetUserLiveSessionData + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +需要获得那位主播的授权才能获取数据。 + +若已提供`live_key`和`live_uid`参数,则必须正确提供`start_tm`和`end_tm`参数,否则服务器可能无法成功响应,响应头中的`Bili-Status-Code`为`-500`。 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| live_key | str | 标记直播场次的key | 必要 | 需要提供目标主播的live_key | +| start_tm | str | 开始时间 | 必要 | 格式为`yyyy-mm-dd HH:MM:SS`,时区为`UTC+08:00`(中国标准时间);取值对实际无影响 | +| end_tm | str | 开始时间 | 必要 | 格式为`yyyy-mm-dd HH:MM:SS`,时区为`UTC+08:00`(中国标准时间);取值对实际无影响 | +| live_uid | num | 目标主播的uid | 必要 | | +| web_location | str | (?) | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -500:服务器错误<br />-101:未登录<br />0:成功<br />100:非法参数<br />202:场次无效<br />301:没有剪辑权限 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | 与[获取直播会话数据](#获取直播会话数据)的信息本体相同 | + +**示例:** + +获取某位主播的某场次会话数据,他已授权你回放剪辑权限 + +```shell +curl 'https://api.live.bilibili.com/xlive/web-room/v1/videoService/GetUserLiveSessionData?live_key=645810156612095795&start_tm=2025-10-02+20:58:21&end_tm=2025-10-03+01:21:06&live_uid=1' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```jsonc +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "session_data": [ + { + "ts": 1759507080, + "value": 0 + }, + { + "ts": 1759507140, + "value": 0 + },// 省略掉绝大部分数据 + { + "ts": 1759513440, + "value": 1 + } + ], + "max_danmaku": 1759513380, + "max_pcu": 1759507200, + "max_value": 0, + "high_light_data": [ + { + "id": 12472658, + "type": 1, + "start_time": 1759513320, + "end_time": 1759513440, + "title": "弹幕高光 Top 1", + "cover": "", + "extra": "" + }// 省略掉剩下两条 + ], + "high_light_stat": { + "original_hl": 3 + } + } +} +``` + +</details> + +## 获取用户高光列表 + +> https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/UserGetManualHighlightList (主播使用) + +> https://api.live.bilibili.com/xlive/web-room/v1/videoService/UserGetManualHighlightList (粉丝使用) + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| live_key | str | 标记直播场次的key | 必要 | | +| manual_type | num | 查询类型 | 必要 | 1:回溯录制<br />2:已保存片段 | +| live_uid | num | 目标主播的uid | 必要(可选) | 通过粉丝使用接口时必要 | +| web_location | str | (?) | 非必要 | 作用尚不明确 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -400:请求错误<br />-101:未登录<br />0:成功 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| high_light_stat | obj | 高亮状态信息 | | +| manual_highlight_list | arr | 高光列表 | 有内容时存在 | + +`data.manual_highlight_list` 数组: + +| 索引 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| 0 | obj | 第一条高光信息 | 最少存在1条,目前没有高光内容将看不到这个数组 | +| … | obj | 某一条高光信息 | | +| i | obj | 最后一条高光信息 | | + +`data.manual_highlight_list` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| manual_id | num | 片段id | | +| highlight_title | str | 片段标题 | | +| start_ts | num | 开始时间戳 | Unix 秒时间戳 | +| end_ts | num | 结束时间戳 | Unix 秒时间戳 | +| uid | num | 保存者uid? | | +| ruid | num | 主播uid | | +| live_key | str | 标记直播场次的key | | + +`data.high_light_stat` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| original_hl | num | “高光时刻”数量 | 有“高光时刻”时存在 | +| manual_hl | num | “已保存”数量 | 有“已保存”时存在,调用[手动保存高亮片段](#手动保存高亮片段)进行保存 | + +注: 可能还存在一个“回溯录制”的字段。 + +**示例:** + +主播获取用户保存列表 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/UserGetManualHighlightList?live_key=625727121464233779&manual_type=2' \ + -b 'SESSDATA=xxx' +``` + +粉丝获取用户保存列表 + +```shell +curl 'https://api.live.bilibili.com/xlive/web-room/v1/videoService/UserGetManualHighlightList?live_key=645810156612095795&manual_type=2&live_uid=1' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +只有高光时刻的示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "high_light_stat": { + "original_hl": 4 + } + } +} +``` + +有保存片段的示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "manual_highlight_list": [ + { + "manual_id": 14434, + "highlight_title": "手动保存片段【6】", + "start_ts": 1752935402, + "end_ts": 1752935402, + "uid": 438160221, + "ruid": 438160221, + "live_key": "625727121464233779" + }, + { + "manual_id": 14428, + "highlight_title": "手动保存片段【5】", + "start_ts": 1752935402, + "end_ts": 1752935204, + "uid": 438160221, + "ruid": 438160221, + "live_key": "625727121464233779" + }, + { + "manual_id": 14426, + "highlight_title": "手动保存片段【4】", + "start_ts": 1752935402, + "end_ts": 1752935404, + "uid": 438160221, + "ruid": 438160221, + "live_key": "625727121464233779" + }, + { + "manual_id": 14425, + "highlight_title": "手动保存片段【3】", + "start_ts": 1752935402, + "end_ts": 1752935404, + "uid": 438160221, + "ruid": 438160221, + "live_key": "625727121464233779" + }, + { + "manual_id": 14424, + "highlight_title": "手动保存片段【2】", + "start_ts": 1752927342, + "end_ts": 1752935404, + "uid": 438160221, + "ruid": 438160221, + "live_key": "625727121464233779" + }, + { + "manual_id": 14423, + "highlight_title": "手动保存片段【1】", + "start_ts": 1752927336, + "end_ts": 1752946748, + "uid": 438160221, + "ruid": 438160221, + "live_key": "625727121464233779" + } + ], + "high_light_stat": { + "original_hl": 4, + "manual_hl": 6 + } + } +} +``` + +</details> + +## 获取某个时间的视频帧 + +> https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/GetAnchorVideoKeyFrame (主播使用) + +> https://api.live.bilibili.com/xlive/web-room/v1/videoService/GetAnchorVideoKeyFrame (粉丝使用) + +*请求方法: POST* + +认证方式: Cookie (SESSDATA) + +鉴权方式: Cookie中`bili_jct`的值正确并与`csrf`相同 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**正文参数( application/json ):** + +根对象: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| live_key | str | 标记直播场次的key | 必要 | | +| live_uid | num | 目标主播的uid | 必要(可选) | 通过粉丝使用接口时必要 | +| time_list | str | 秒时间戳列表,用`,`分隔 | 必要 | 时间间隔低于30秒将会导致只提供部分内容 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -400:请求错误<br />-111:csrf校验失败<br />-101:未登录<br />0:成功<br />10121188:权限不足 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| list | arr | 指定时间的视频帧列表 | 场次key无效时为`null` | + +`data.list` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| ts | num | 时间戳 | 对应请求的`time_list`其中某一个 | +| url | str | 该时间的视频帧 | 该时间有视频且取帧成功时存在 | + +**示例:** + +主播获取某场直播的视频帧 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/GetAnchorVideoKeyFrame?csrf=xxx' \ + -H 'Content-Type: application/json' \ + -b 'SESSDATA=xxx;bili_jct=xxx' \ + -d '{"live_key":"609431465787395891","time_list":"174758900,1747658930,1747658960"}' +``` + +粉丝获取某场直播的视频帧 + +```shell +curl 'https://api.live.bilibili.com/xlive/web-room/v1/videoService/GetAnchorVideoKeyFrame?csrf=xxx' \ + -H 'Content-Type: application/json' \ + -b 'SESSDATA=xxx;bili_jct=xxx' \ + -d '{"live_key":"645810156612095795","time_list":"1759410340,1759418126","live_uid":1}' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "ts": 174758900 + }, + { + "ts": 1747658930, + "url": "https://jssz-boss.hdslb.com/live2arc_anchor_video/live_438160221_32373699_20250519204900.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=y4zI4XTQzlOkmSKg%2F20250520%2Fjssz%2Fs3%2Faws4_request&X-Amz-Date=20250520T180202Z&X-Amz-Expires=7200&X-Amz-SignedHeaders=host&X-Amz-Signature=8d42a3d5fd1995e5e2bf98d453a986bec48529a9ae97d5d7eedee8a59b22418a" + }, + { + "ts": 1747658960, + "url": "https://jssz-boss.hdslb.com/live2arc_anchor_video/live_438160221_32373699_20250519205001.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=y4zI4XTQzlOkmSKg%2F20250520%2Fjssz%2Fs3%2Faws4_request&X-Amz-Date=20250520T180202Z&X-Amz-Expires=7200&X-Amz-SignedHeaders=host&X-Amz-Signature=f4a3803d4147492ced14eefbb6953e772b886e195d51dbfac800e77320adeba2" + } + ] + } +} +``` + +</details> + +## 手动保存高亮片段 + +> https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/UserManualSaveHighlight (主播使用) + +> https://api.live.bilibili.com/xlive/web-room/v1/videoService/UserManualSaveHighlight (粉丝使用) + +*请求方法: POST* + +认证方式: Cookie (SESSDATA) + +鉴权方式: Cookie中`bili_jct`的值正确并与`csrf`相同 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| live_key | str | 标记直播场次的key | 必要 | | +| start_ts | num | 开始时间戳 | 必要 | Unix 秒时间戳 | +| end_ts | num | 结束时间戳 | 必要 | Unix 秒时间戳 | +| live_uid | num | 目标主播的uid | 必要(可选) | 通过粉丝使用接口时必要 | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +注: 开始时间减结束时间的结果小于1可能导致[直播回放片段发布页面](#直播回放片段发布页面)无法处理这个片段。 + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -400:请求错误<br />-111:csrf校验失败<br />-101:未登录<br />0:成功<br /> | +| message | str | 错误信息 | | +| ttl | num | `1` | | +| data | obj | 信息本体 | 成功时为空对象 | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | `-1` | | +| message | str | 错误提示 | `主播没有对应场次` , `保存时间点未开播` | + +**示例:** + +主播手动保存一个片段 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/UserManualSaveHighlight' \ + --data-urlencode 'live_key=625727121464233779' \ + --data-urlencode 'start_ts=1752935402' \ + --data-urlencode 'end_ts=1752935404' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx;bili_jct=xxx' +``` + +粉丝手动保存一个片段 + +```shell +curl 'https://api.live.bilibili.com/xlive/web-room/v1/videoService/UserManualSaveHighlight' \ + --data-urlencode 'live_key=645810156612095795' \ + --data-urlencode 'start_ts=1759409907' \ + --data-urlencode 'end_ts=1759410087' \ + --data-urlencode 'live_uid=1' \ + --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/xlive/app-blink/v1/anchorVideo/AnchorPublishVideoSlice + +*请求方法: POST* + +认证方式: Cookie (SESSDATA) + +鉴权方式: Cookie中`bili_jct`的值正确并与`csrf`相同 + +主播投稿自己的直播回放片段时使用。 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| live_key | str | 标记直播场次的key | 必要 | 必须为自己的live_key | +| start_ts | num | 开始时间戳 | 必要 | 开始和结束时间目前相差不能大于2小时 | +| end_ts | num | 结束时间戳 | 必要 | 开始和结束时间目前相差不能大于2小时 | +| av_title | str | 切片标题 | 必要 | 不能与现有标题重复 | +| av_cover | str | 切片封面URL | 必要 | 必须为`.hdslb.com`域名下的图片,否则合成结束时会出错 | +| av_highlight | num | 高光绑定 | 非必要 | | +| with_subtitle | num | 是否携带字幕 | 非必要 | 效果不明确 | +| with_danmaku | num | 是否带弹幕? | 非必要 | 传递`1`时可能导致处于“发布中”状态时不在[获取已发布片段的信息](#获取已发布片段的信息)中显示 | +| with_reserve | num | 投稿携带下场直播提醒 | 非必要 | 0:不携带,1:携带 | +| av_speed | str | 倍速投稿 | 非必要 | 格式为 `倍速值 + "x"` ,使用非1x倍速时可能导致处于“发布中”状态时不在[获取已发布片段的信息](#获取已发布片段的信息)中显示<br />允许值: `0.5x` , `0.75x` , `1.0x` , `1.25x` , `1.5x` , `2.0x` | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -111:csrf校验失败<br />-101:未登录<br />0:成功<br />4000:时长过长<br />4001:操作太快<br />4002:片段已投稿<br />4003:请选择精彩片段再投稿哦<br />4006:标题已使用<br />4008:不被允许的视频倍速<br />4009:该片段存在违规内容,不允许投稿 | +| message | str | 错误信息 | | +| ttl | num | `1` | | +| data | obj | 信息本体 | 成功时有效 | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| video_slice_id | num | 切片id | | + +注: 若返回值出现4001不一定就是操作太快,不提供某些必要参数或某个参数不正确也会导致返回4001。 + +**示例:** + +为某个场次投稿切片 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/anchorVideo/AnchorPublishVideoSlice' \ + --data-urlencode 'live_key=609431465787395891' \ + --data-urlencode 'start_ts=1747680306' \ + --data-urlencode 'end_ts=1747687506' \ + --data-urlencode 'av_title=2025051920' \ + --data-urlencode 'av_cover=https://i0.hdslb.com/bfs/live/59fc254c1f51a962dbf69ae85e4920f2f6fb8dcd.png' \ + --data-urlencode 'av_highlight=0' \ + --data-urlencode 'with_subtitle=0' \ + --data-urlencode 'with_danmaku=0' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx;bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data":{ + "video_slice_id": 898374 + } +} +``` + +</details> + +## 给某位主播投稿直播回放片段 + +> https://api.live.bilibili.com/xlive/web-room/v1/videoService/UserPublishOtherVideoSlice + +*请求方法: POST* + +认证方式: Cookie (SESSDATA) + +鉴权方式: Cookie中`bili_jct`的值正确并与`csrf`相同 + +需要获得那位主播的授权。 + +**正文参数( application/x-www-form-urlencoded ):** + +与[投稿直播回放片段](#投稿直播回放片段)的正文参数相比,多了`live_uid`参数,少了`av_speed`参数,其它参数基本相同。 + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| live_uid | num | 目标主播的uid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -111:csrf校验失败<br />-101:未登录<br />0:成功<br />100:非法参数<br />4000:时长过长<br />5006:用户已经投稿过该片段 | +| message | str | 错误信息 | | +| ttl | num | `1` | | +| data | obj | 信息本体 | 成功时有效 | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| video_slice_id | num | 切片id | 似乎与主播不共用一个切片id | + +**示例:** + +为某个场次投稿切片 + +```shell +curl 'https://api.live.bilibili.com/xlive/web-room/v1/videoService/UserPublishOtherVideoSlice' \ + --data-urlencode 'live_key=648437353747320627' \ + --data-urlencode 'start_ts=1760352154' \ + --data-urlencode 'end_ts=1760352214' \ + --data-urlencode 'av_title=202510201318' \ + --data-urlencode 'av_cover=https://i0.hdslb.com/bfs/live/59fc254c1f51a962dbf69ae85e4920f2f6fb8dcd.png' \ + --data-urlencode 'av_highlight=0' \ + --data-urlencode 'with_subtitle=0' \ + --data-urlencode 'with_danmaku=0' \ + --data-urlencode 'with_reserve=1' \ + --data-urlencode 'live_uid=1' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx;bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data":{ + "video_slice_id": 4300 + } +} +``` + +</details> + +## 下载整场直播回放的流程 + +此处的流程是从[直播回放](https://link.bilibili.com/#/my-room/live-record)的“下载回放”功能得出的。 + +1. 先[请求整场直播回放下载链接](#请求整场直播回放下载链接)接口,让它开始合成回放; + +2. (可选)请求[获取回放的信息](#获取回放的信息)接口,生成合成进度页面; + +3. [轮询回放合成状态](#轮询回放状态),当状态变为`30`转到流程4,变为`-30`转到流程5; + +4. 再次[请求整场直播回放下载链接](#请求整场直播回放下载链接),获取下载链接并下载。 + +5. 请求[获取直播回放列表](#获取直播回放列表),刷新页面并根据信息提示失败。 + +## 直播回放片段发布页面 + +通过此处的链接可以打开直播回放片段发布页面。 + +> https://live.bilibili.com/web-cut/quick-publish.html (网页端) + +> https://live.bilibili.com/web-cut/quick-publish-mobile.html (移动端) + +注:移动端强制限制只能投稿15分钟的片段,网页端则看[投稿直播回放片段](#投稿直播回放片段)接口允许多长的时间。 + +**url查询参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| start_time | num | 直播开始时间 | 必要 | 对应[获取直播回放列表](#获取直播回放列表)的`data.replay_info[i].start_time` | +| end_time | num | 直播结束时间 | 必要 | 对应[获取直播回放列表](#获取直播回放列表)的`data.replay_info[i].end_time` | +| live_key | str | 标记直播场次的key | 必要 | 对应[获取直播回放列表](#获取直播回放列表)的`data.replay_info[i].live_key` | +| cover | str | 封面URL | 非必要 | 可以自定义封面(必须为B站图床,详见[投稿接口](#投稿直播回放片段)),或者在[获取直播回放列表](#获取直播回放列表)使用直播封面 | +| anchor_id | num | 目标主播的uid | 非必要 | 要剪辑某位主播的回放时必须提供 | +| anchor_name | num | 目标主播的名称 | 非必要 | 由[某位主播的直播回放剪辑界面](#某位主播的直播回放剪辑界面)传递 | + +**示例链接:** + +网页端: https://live.bilibili.com/web-cut/quick-publish.html?start_time=1747508293&end_time=1747508499&live_key=609041817764368179&cover=https%3A%2F%2Fi0.hdslb.com%2Fbfs%2Flive%2F59fc254c1f51a962dbf69ae85e4920f2f6fb8dcd.png + +移动端: https://live.bilibili.com/web-cut/quick-publish-mobile.html?start_time=1747508293&end_time=1747508499&live_key=609041817764368179 + +粉丝剪辑: https://live.bilibili.com/web-cut/quick-publish.html?start_time=1760766799&end_time=1760774101&live_key=649597291269984051&cover=https://i0.hdslb.com/bfs/live/59fc254c1f51a962dbf69ae85e4920f2f6fb8dcd.png&anchor_id=1&anchor_name=null + +## 直播回放剪辑页面 + +此链接用于打开直播回放轻剪辑页面,在点击[直播回放片段发布页面](#直播回放片段发布页面)的“高级剪辑”按钮或某一个[主播回放剪辑草稿](#获取回放剪辑草稿列表)、[粉丝回放剪辑草稿](#获取你为某位主播剪辑的草稿)后自动打开。 + +> https://live.bilibili.com/web-cut/index.html + +**url查询参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| start_time | num | 直播开始时间戳 | 必要 | 用于[获取切片视频流](#获取切片视频流) | +| end_time | num | 直播结束时间戳 | 必要 | 用于[获取切片视频流](#获取切片视频流) | +| live_key | str | 标记直播场次的key | 必要 | 用于[获取切片视频流](#获取切片视频流) | +| draft_id | num | 回放剪辑id | 必要 | | +| init | num | (?) | 非必要 | 作用尚不明确 | +| with_reserve | num | 投稿携带下场直播提醒? | 非必要 | 0:不携带,1:携带 | +| anchor_id | num | 目标主播的uid | 非必要 | | + +**示例链接:** https://live.bilibili.com/web-cut/index.html?start_time=1747658704&end_time=1747705213&live_key=609431465787395891&draft_id=988275 + +## 某位主播的直播回放剪辑界面 + +此链接用于打开某位主播的直播回放剪辑界面,需要获得那位主播的授权。 + +主播自己访问该界面也需要自己在剪辑权限页面内开启该功能。 + +> https://live.bilibili.com/web-cut/replay-cut.html + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| anchor_Id | num | 主播uid | 必要 | 参数名不区分大小写 | +| anchor_name | str | 主播名称 | 非必要 | 用于在UI中显示主播名称,目前可随意传递,若不提供将使用 `未知主播` 显示 | + +**示例链接:** https://live.bilibili.com/web-cut/replay-cut.html?anchor_Id=1&anchor_name=bishi diff --git a/bb-api-collect/docs/live/live_stream.md b/bb-api-collect/docs/live/live_stream.md new file mode 100644 index 0000000000..57b9fac6fd --- /dev/null +++ b/bb-api-collect/docs/live/live_stream.md @@ -0,0 +1,156 @@ +# 直播间视频流 + +## 根据真实直播间号获取直播视频流 + +> https://api.live.bilibili.com/room/v1/Room/playUrl + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| cid | num | 目标真实直播间号 | 必要 | 直播间的`room_id`(非短号) | +| platform | str | 直播流格式 | 非必要 | h5:hls方式<br />web:http-flv方式<br />默认为http-flv方式 | +| quality | num | 画质 | 非必要 | `qn`与`quality`任选其一<br />2:流畅<br />3:高清<br />4:原画 | +| qn | str | 画质 | 非必要 | `qn`与`quality`任选其一<br />80:流畅<br />150:高清<br />250:超清<br />400:蓝光<br />10000:原画<br />20000:4K<br />25000:默认<br />30000:杜比 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功<br />-400:参数错误<br />19002003:房间信息不存在 | +| message | str | 错误信息 | 默认为0 | +| ttl | str | 1 | | +| data | obj | 信息本体 | | + + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | ------------- | ------------------------ | +| current_quality | num | 当前画质代码`qn` | | +| accept_quality | array | 可选画质数参数 | | +| current_qn | num | 当前画质代码`quality` | | +| quality_description | array | 可选画质参数`quality` | | +| durl | array | 直播流url组 | | + +`accept_quality`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------------- | ---- | +| 0 | str | `qn`画质代码1 | | +| n | str | `qn`画质代码(n+1) | | +| …… | str | …… | …… | + +`quality_description`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---- | +| 0 | obj | 画质代码1 | | +| n | obj | 画质代码(n+1) | | +| …… | obj | …… | …… | + +`quality_description`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------------- | ---- | +| qn | num | 画质代码 | | +| desc | str | 该代码对应的画质名称 | | + +`durl`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---- | +| 0 | obj | 主线服务器 | | +| n | obj | 备线n服务器 | | +| …… | obj | …… | …… | + +`durl`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | ------------- | ------------------------ | +| url | str | 直播流url | flv或m3u8格式<br />**注:带有转义** | +| length | num | 0 | 作用尚不明确 | +| order | num | 服务器线路序号 | | +| stream_type | num | 0 | 作用尚不明确 | +| p2p_type | num | 0 | 作用尚不明确 | + +**示例:** + +查询直播间`cid=14073662`的直播间信息 + +```shell +curl -G 'https://api.live.bilibili.com/room/v1/Room/playUrl' \ +--data-urlencode 'cid=14073662' \ +--data-urlencode 'qn=10000' \ +--data-urlencode 'platform=web' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "current_quality": 3, + "accept_quality": [ + "4", + "3", + "2" + ], + "current_qn": 3, + "quality_description": [ + { + "qn": 4, + "desc": "原画" + }, + { + "qn": 3, + "desc": "高清" + }, + { + "qn": 2, + "desc": "流畅" + } + ], + "durl": [ + { + "url": "https://d1--cn-gotcha04.bilivideo.com/live-bvc/601131/live_14073662_bs_3699814_1500.flv?cdn=cn-gotcha04&expires=1602496530&len=0&oi=1939228219&pt=&qn=150&trid=e6540d81a5d04c2ea459c46ebe77472a&sigparams=cdn,expires,len,oi,pt,qn,trid&sign=20e4ac695fbdd1d11d5dac4f93caa783&ptype=0&src=9&sl=1&order=1", + "length": 0, + "order": 1, + "stream_type": 0, + "p2p_type": 0 + }, + { + "url": "https://d1--cn-gotcha01.bilivideo.com/live-bvc/757951/live_14073662_bs_3699814_1500.flv?cdn=cn-gotcha01&expires=1602496530&len=0&oi=1939228219&pt=&qn=150&trid=e6540d81a5d04c2ea459c46ebe77472a&sigparams=cdn,expires,len,oi,pt,qn,trid&sign=9deea67bb9e9c1f0fa3886a34aa09473&ptype=0&src=9&sl=1&order=2", + "length": 0, + "order": 2, + "stream_type": 0, + "p2p_type": 0 + }, + { + "url": "https://d1--cn-gotcha04.bilivideo.com/live-bvc/982058/live_14073662_bs_3699814_1500.flv?cdn=cn-gotcha04&expires=1602496530&len=0&oi=1939228219&pt=&qn=150&trid=e6540d81a5d04c2ea459c46ebe77472a&sigparams=cdn,expires,len,oi,pt,qn,trid&sign=8753b270960034660184d975d86c0161&ptype=0&src=9&sl=1&order=3", + "length": 0, + "order": 3, + "stream_type": 0, + "p2p_type": 0 + }, + { + "url": "https://d1--cn-gotcha04.bilivideo.com/live-bvc/139554/live_14073662_bs_3699814_1500.flv?cdn=cn-gotcha04&expires=1602496530&len=0&oi=1939228219&pt=&qn=150&trid=e6540d81a5d04c2ea459c46ebe77472a&sigparams=cdn,expires,len,oi,pt,qn,trid&sign=cf93474e923c9ba8288c45d954f81045&ptype=0&src=9&sl=1&order=4", + "length": 0, + "order": 4, + "stream_type": 0, + "p2p_type": 0 + } + ] + } +} +``` + +</details> diff --git a/bb-api-collect/docs/live/live_vote.md b/bb-api-collect/docs/live/live_vote.md new file mode 100644 index 0000000000..8e2af3f2e5 --- /dev/null +++ b/bb-api-collect/docs/live/live_vote.md @@ -0,0 +1,470 @@ +# 直播投票 + +## 查询投票信息 + +> https://api.live.bilibili.com/xlive/app-room/v1/dm/interaction/votePanel + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| room_id | num | 直播间id | 必要 | 必须为登录信息对应的直播间 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -400:请求错误<br />-101:未登录<br />0:成功 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | 不是登录信息对应的直播间时将为 `null` | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| vote_info | obj | 当前活动的投票信息 | 若当前没有活动的投票将为空对象 | +| templates | arr | 投票模板 | | + +`data.vote_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| status | num | 投票状态 | 见[投票状态](#投票状态)枚举 | +| question | str | 投票问题 | | +| options | arr | 投票选项 | | +| duration | num | 投票持续时间 | 单位:毫秒 | +| result | num | 投票结果偏向哪一方状态 | | +| result_text | str | 投票结果偏向哪一方 | | +| etime_str | str | 投票结束时间 | | +| left_duration | num | 投票剩余时间 | 单位:毫秒,投票结束后不存在 | +| interaction_id | num | 投票互动id | | +| template_id | num | 投票模板id | 使用模板时存在 | + +`data.vote_info.options` 数组: + +| 索引 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| 0 | obj | 投票选项1 | | +| 1 | obj | 投票选项2 | | + +`data.vote_info.options` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| idx | num | 选项id | | +| desc | str | 投票选项描述 | | +| percent | num | 投票选项占比显示 | | + +`data.templates` 数组: + +| 索引 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| 0 | obj | 投票模板信息 | | +| … | obj | 投票模板信息 | | + +`data.templates` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| template_id | num | 模板id | | +| question | str | 投票问题 | | +| option_a | str | 投票选项A | | +| option_b | str | 投票选项B | | + +**示例:** + +查询投票信息 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-room/v1/dm/interaction/votePanel?room_id=1' +``` + +<details> +<summary>查看响应示例:</summary> + +```jsonc +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "vote_info": { + "status": 4, + "question": "醒醒", + "options": [ + { + "idx": 1, + "desc": "醒", + "percent": 0.5 + }, + { + "idx": 2, + "desc": "睡", + "percent": 0.5 + } + ], + "duration": 600000, + "result": 1, + "result_text": "平局", + "etime_str": "08-31 15:44", + "left_duration": 549660, + "interaction_id": 120122595433984 + }, + "templates": [ + { + "template_id": 54339003518976, + "question": "哪边赢", + "option_a": "左", + "option_b": "右" + }, + { + "template_id": 48570973661696, + "question": "只因你太美唱的好吗?", + "option_a": "你干嘛", + "option_b": "哎哟" + }, + // 省略了大部分内容 + { + "template_id": 46203444257280, + "question": "№!", + "option_a": "虾头", + "option_b": "抽象" + }, + { + "template_id": 96177095781888, + "question": "相信奇迹吗", + "option_a": "相信", + "option_b": "必须相信" + }, + { + "template_id": 103827382481920, + "question": "1", + "option_a": "1", + "option_b": "1" + } + ] + } +} +``` + +</details> + +## 查询投票历史 + +> https://api.live.bilibili.com/xlive/app-room/v1/dm/interaction/voteHistory + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| room_id | num | 直播间id | 必要 | 必须为登录信息对应的直播间 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -400:请求错误<br />-101:未登录<br />0:成功 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | 不是登录信息对应的直播间时将为空对象 | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| history | arr | 投票历史列表 | | + +`data.history` 数组: + +| 索引 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| 0 | obj | 投票历史 | 与[查询投票信息](#查询投票信息)`data.vote_info`相同 | +| … | obj | 投票历史 | 与[查询投票信息](#查询投票信息)`data.vote_info`相同 | +| 9 | obj | 投票历史 | 与[查询投票信息](#查询投票信息)`data.vote_info`相同 | + +`data.history` 数组中对象: + +与 [查询投票信息](#查询投票信息) json回复的 `data.vote_info` 相同。 + +**示例:** + +```shell +curl 'https://api.live.bilibili.com/xlive/app-room/v1/dm/interaction/voteHistory?room_id=1' \ + -b 'SESSDATA=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```jsonc +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "history": [ + { + "status": 5, + "question": "醒醒", + "options": [ + { + "idx": 1, + "desc": "醒", + "percent": 0.5 + }, + { + "idx": 2, + "desc": "睡", + "percent": 0.5 + } + ], + "duration": 600000, + "result": 1, + "result_text": "平局", + "etime_str": "08-31 15:44", + "interaction_id": 120122595433984 + }, + { + "status": 5, + "question": "会不会睡死?", + "options": [ + { + "idx": 1, + "desc": "包会的", + "percent": 0.5 + }, + { + "idx": 2, + "desc": "不会的", + "percent": 0.5 + } + ], + "duration": 60000, + "result": 1, + "result_text": "平局", + "etime_str": "08-31 14:57", + "interaction_id": 120117830648832 + }, + { + "status": 5, + "question": "会不会睡着?", + "options": [ + { + "idx": 1, + "desc": "包会的", + "percent": 0.5 + }, + { + "idx": 2, + "desc": "不会的", + "percent": 0.5 + } + ], + "duration": 180000, + "result": 1, + "result_text": "平局", + "etime_str": "08-31 14:53", + "interaction_id": 120117121798656 + }, + { + "status": 5, + "question": "能不能一把过", + "options": [ + { + "idx": 1, + "desc": "能", + "percent": 0.5 + }, + { + "idx": 2, + "desc": "不能", + "percent": 0.5 + } + ], + "duration": 60000, + "result": 1, + "result_text": "平局", + "etime_str": "08-31 14:41", + "interaction_id": 120115796409344, + "template_id": 3109187328000 + } + // 省略其余6项 + ] + } +} +``` + +</details> + +## 投票状态 + +此处列出已发现的投票状态,在投票信息和直播信息流 `DM_INTERACTION` 的类型 `101` 等地方使用。 + +当前状态信息来自混淆代码寻找而来。 + +| 值 | 含义 | 备注 | +| -- | ---- | ---- | +| 0 | | 键名 `NONE` | +| 1 | 等待审核 | 键名 `WAITING_AUDIT` | +| 2 | 审核失败 | 键名 `AUDIT_FAILED` | +| 4 | 投票进行中 | 键名 `DURING` | +| 5 | 投票结束 | 键名 `END` | +| 6 | | 键名 `STOP` | + +## 创建直播投票 + +> https://api.live.bilibili.com/xlive/app-room/v1/dm/interaction/createVote + +*请求方法: POST* + +认证方式: Cookie (SESSDATA) + +鉴权方式: Cookie中`bili_jct`的值正确并与`csrf`相同 + +投票创建完成后,投票信息和审核结果将以直播信息流 `DM_INTERACTION` 的类型 `101` 下发。 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| room_id | num | 直播间id | 必要 | 必须为登录信息对应的直播间 | +| duration | num | 持续时间 | 必要 | 必须为整数,目前范围`0<d<10` | +| question | str | 投票问题 | 必要 | | +| option_a | str | 选项A | 必要 | | +| option_b | str | 选项B | 必要 | | +| template_id | num | 投票模板id | 非必要 | | +| live_key | str | 直播场次key | 非必要 | 需要更多信息 | +| sub_session_key | str | (?) | 非必要 | 需要更多信息 | +| csrf_token | str | CSRF Token(位于cookie) | 非必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | +| visit_id | str | (?) | 非必要 | 作用尚不明确 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -404:不是自己的直播间<br />-400:参数错误<br />-101:未登录<br />-111:csrf校验失败<br />0:成功 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| interaction_id | num | 投票互动id | | + +**示例:** + +创建一个投票 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-room/v1/dm/interaction/createVote' \ + --data-urlencode 'room_id=3' \ + --data-urlencode 'duration=1' \ + --data-urlencode 'question=abcdef' \ + --data-urlencode 'option_a=A' \ + --data-urlencode 'option_b=B' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx;bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data":{ + "interaction_id":120008099262976 + } +} +``` + +</details> + +## 中断直播投票 + +> https://api.live.bilibili.com/xlive/app-room/v1/dm/interaction/terminateVote + +*请求方法: POST* + +认证方式: Cookie (SESSDATA) + +鉴权方式: Cookie中`bili_jct`的值正确并与`csrf`相同 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| interaction_id | num | 投票互动id | 必要 | 必须为该登录信息创建的投票 | +| room_id | num | 直播间id | 必要 | 必须为登录信息对应的直播间 | +| csrf_token | str | CSRF Token(位于cookie) | 非必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | +| visit_id | str | (?) | 非必要 | 作用尚不明确 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | -400:参数错误<br />-101:未登录<br />-111:csrf校验失败<br />0:成功<br />1003402:修改投票状态失败 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | null | 无 | | + +**示例:** + +中断某个投票 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-room/v1/dm/interaction/terminateVote' \ + --data-urlencode 'interaction_id=120122595433984' \ + --data-urlencode 'room_id=1' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx;bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": null +} +``` + +</details> + +## 弹幕投票主播侧界面 + +> https://live.bilibili.com/p/html/live-app-guessing-game/anchor_vote.html + +直接访问此页面存在部分功能不可用的情况。 + +**URL查询参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| room_id | num | 直播间id | 必要 | 必须为自己的直播间 | diff --git a/bb-api-collect/docs/live/manage.md b/bb-api-collect/docs/live/manage.md new file mode 100644 index 0000000000..88d54c138b --- /dev/null +++ b/bb-api-collect/docs/live/manage.md @@ -0,0 +1,742 @@ +# 直播间管理 + +## 开通直播间 + +> https://api.live.bilibili.com/xlive/app-blink/v1/preLive/CreateRoom + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +鉴权方式:Cookie中`bili_jct`的值正确并与`csrf`相同 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | ------------------------ | ------ | -------------------- | +| platform | str | 客户端? | 必要 | 默认值web | +| visit_id | str | 未知 | | 默认空 | +| csrf | str | CSRF Token(位于cookie) | 必要 | | +| csrf_token | str | CSRF Token(位于 cookie) | | | + + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | -------- | ------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />1531193016:已经创建直播间~<br />-400:请求错误 | +| ttl | str | 错误信息 | 默认为1 | +| message | str | 错误信息 | 默认为0 | +| data | array | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | ---------------- | ---------------------- | +| roomID | str | 直播间房间号 | 创建成功返回直播间号 | + +**示例:** + +开通直播间 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/preLive/CreateRoom' \ +--data-urlencode 'platform=web' \ +--data-urlencode 'visit_id=' \ +--data-urlencode 'csrf=xxx' \ +--data-urlencode 'csrf_token=xxx' \ +-b 'SESSDATA=xxx;bili_jct=xx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "roomID": "1234" + } +} +``` + +```json +{ + "code": 1531193016, + "message": "已经创建直播间~", + "ttl": 1, + "data": { + "roomID": "" + } +} +``` + +</details> + + + +## 更新直播间信息 + +> https://api.live.bilibili.com/room/v1/Room/update + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +鉴权方式:Cookie中`bili_jct`的值正确并与`csrf`相同 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | ------------------------ | ------ | -------------------- | +| csrf | str | CSRF Token(位于cookie) | 必要 | | +| csrf_token | str | CSRF Token(位于 cookie) | 非必要 | | +| platform | str | 平台标识 | 非必要 | | +| visit_id | str | (?) | 非必要 | 某种标识? | +| room_id | num | 直播间id | 必要 | 必须为自己的直播间id | +| title | str | 直播间标题 | 非必要 | 上限40个字符 | +| area\_id | num | 直播分区id(子分区id) | 非必要 | 详见[直播分区](live_area.md) | +| add\_tag | str | 要添加的标签 | 非必要 | 开播设置界面上限10个字符 | +| del\_tag | str | 要删除的标签 | 非必要 | 若存在`add_tag`时不起作用 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | -------- | ------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-1:操作太频繁<br />1:错误<br />3:未登录或鉴权失败<br />405:不允许的请求方法<br />60009:分区已下线<br />65530:token错误(登录错误)<br /> | +| msg | str | 错误信息 | 默认为ok | +| message | str | 错误信息 | 默认为ok | +| data | obj | 信息本体 | 部分失败情况下是`[]`(空数组) | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | ---- | ---- | +| sub_session_key | str | 信息变动标识 | | +| audit_info | obj | 标题审核信息 | | + +`data`中的`audit_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------ | ---- | ---- | ---- | +| audit_title_reason | str | 标题审核提示 | | +| audit_title_status | num | 标题审核状态 | | +| audit_title | str | 被审核的标题 | 更新标题时存在 | +| update_title | str | `""` | 作用尚不明确 | + +**示例:** + +修改直播间`10352053`标题为`测试` + +```shell +curl 'https://api.live.bilibili.com/room/v1/Room/update' \ + --data-urlencode 'room_id=10352053' \ + --data-urlencode 'title=测试' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx;bili_jct=xx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code":0, + "msg":"ok", + "message":"ok", + "data":{ + "sub_session_key":"", + "audit_info":{ + "audit_title_reason":"先发后审", + "update_title":"", + "audit_title_status":2, + "audit_title":"测试" + } + } +} +``` + +</details> + +修改直播间`10352053`分区为`40` + +```shell +curl 'https://api.live.bilibili.com/room/v1/Room/update' \ + --data-urlencode 'room_id=10352053' \ + --data-urlencode 'area_id=40' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx;bili_jct=xx' +``` + +<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 'add_tag=测试标签' \ + --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=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> + +## 开始直播 + +> https://api.live.bilibili.com/room/v1/Room/startLive + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +鉴权方式:Cookie中`bili_jct`的值正确并与`csrf`相同 + +开播时必须有分区选择,开播后返回推流地址 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------------------ | ------ | ------------------------------------------------------------ | +| room_id | num | 直播间id | 必要 | 必须为自己的直播间 id | +| area_v2 | num | 直播分区id(子分区 id) | 必要 | 详见[直播分区](live_area.md) | +| platform | str | 直播平台 | 必要 | 可选值:`pc`、`pc_link` (直播姬 PC), `android_link` (直播姬 Android) | +| csrf | str | CSRF Token(位于 cookie) | 必要 | | +| csrf_token | str | CSRF Token(位于 cookie) | 非必要 | | +| version | str | 直播姬版本号 | 非必要 | 建议与 `build` 一同提供,详见下方说明。可从[直播姬版本号获取](#直播姬版本号获取)接口获得。 | +| build | num | 直播姬构建号 | 非必要 | 建议与 `version` 一同提供。 | +| appkey | str | APP密钥 | 条件性必要 | 特定情况下必要,详见下方说明。 | +| sign | str | APP API签名得到的 sign | 条件性必要 | 特定情况下必要,详见下方说明。 | + +**说明**: 截止至 2025 年 7 月 20 日,部分账户不提供 `version` `build` `appkey` `sign` 也可获取推流码,部分账户会返回 `60024` (需要人脸认证),此时请尝试提供 `version` `build`,目前似乎没有校验,提供了就可以。(比如 `version:1.0.0` `build:1234`) 如果仍然返回 `60024`,请尝试提供 `appkey` `sign` 参数。如果你的 `version` 和 `build` 为 `7.19.0.9432` 和 `9432`,必须提供 `appkey` `sign`。 + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0: 成功<br />-400: 请求错误<br />1: 错误<br />60009: 分区不存在<br />60013: 所在地区受实名认证限制无法开播<br />60024: 目标分区需要人脸认证<br />60034: 系统维护仅支持直播姬开播<br />60037: web在线开播已下线<br />65530: token错误 (登录失效)<br />**(其他错误码有待补充)** | +| msg | str | 提示信息 | 默认为空 | +| message | str | 提示信息 | 默认为空 | +| data | obj | 信息本体 | 成功时返回 | + + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | ---------------- | ---------------------- | +| change | num | 是否改变状态 | 0:未改变<br />1:改变 | +| status | str | 直播间状态 | `LIVE` | +| room_type | num | 0 | 作用尚不明确 | +| rtmp | obj | RTMP推流地址信息 | | +| protocols | array | 推流协议、地址、密钥等信息<br />其中地址、密钥与 `rtmp` 字段的内容是一致的 | 协议只见到过 `rtmp` | +| try_time | str | ??? | 作用尚不明确 | +| live_key | str | 标记直播场次的key | | +| sub_session_key | str | 信息变动标识 | | +| notice | obj | ??? | 作用尚不明确 | +| qr | str | `""` | 作用尚不明确 | +| need_face_auth | bool | 需要人脸识别? | 作用尚不明确 | +| service_source | str | ??? | 作用尚不明确 | +| rtmp\_backup | null | ??? | 作用尚不明确 | +| up_stream_extra | obj | 主播推流额外信息? | | + +`data`中的`rtmp`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------------------------------- | ------------ | +| addr | str | RTMP推流(发送)地址 | **重要** | +| code | str | RTMP推流参数(密钥) | **重要** | +| new_link | str | 获取CDN推流ip地址重定向信息的url | 没啥用 | +| provider | str | 推流云服务节点厂商 | `txy`: 腾讯云 | + +`data`中的`protocols`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | ------------ | +| 0 | obj | 与 `rtmp` 字段在地址和密钥上相同的推流协议信息 | | + +`data`中的`protocols`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------------------------------- | ------------ | +| protocol | str | rtmp | 推流协议 | +| addr | str | RTMP推流(发送)地址 | 格式为 `rtmp://<推流节点>/live-bvc/` | +| code | str | RTMP推流参数(密钥) | 格式为 `?streamname=live_<B站UID>_<未知数字>&key=<密钥>&schedule=rtmp&pflag=<开播平台标志>` | +| new_link | str | 获取CDN推流ip地址重定向信息的url | | +| provider | str | 推流云服务节点厂商 | `txy`: 腾讯云 | + +`data`中的`notice`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ---- | ------------ | +| type | num | 1 | 作用尚不明确 | +| status | num | 0 | 作用尚不明确 | +| title | str | 空 | 作用尚不明确 | +| msg | str | 空 | 作用尚不明确 | +| button_text | str | 空 | 作用尚不明确 | +| button_url | str | 空 | 作用尚不明确 | + +`data`中的`up_stream_extra`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| isp | str | 主播的互联网服务提供商 | | + +**示例:** + +以`27`作为分区id开播直播间`10352053` + +其中`"data"."rtmp"."addr"`为推流地址 + +`"data"."rtmp"."code"`为推流参数 + +```shell +curl 'https://api.live.bilibili.com/room/v1/Room/startLive' \ +--data-urlencode 'room_id=10352053' \ +--data-urlencode 'area_v2=27' \ +--data-urlencode 'platform=pc' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx;bili_jct=xx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "data":{ + "change": 1, + "status": "LIVE", + "try_time": "0000-00-00 00:00:00", + "room_type": 0, + "live_key": "608336837537435443", + "sub_session_key": "608336837537435443sub_time:1747292297", + "rtmp":{ + "type": 1, + "addr": "rtmp://live-push.bilivideo.com/live-bvc/", + "code": "?streamname=live_348892132_32373699\u0026key=e03061d4a7529d8eaa322dc4d330ca1c\u0026schedule=rtmp\u0026pflag=11", + "new_link": "https://core.bilivideo.com/video/uplinkcore/selfbuild/schedule?up_rtmp=live-push.bilivideo.com%2Flive-bvc%2F%3Fstreamname%3Dlive_348892132_32373699%26key%3De73061d8a7539d8eaa233dc4d880ca1c%26schedule%3Drtmp%26pflag%3D11\u0026edge=edge", + "provider": "live" + }, + "protocols":[ + { + "protocol": "rtmp", + "addr": "rtmp://live-push.bilivideo.com/live-bvc/","code":"?streamname=live_348892132_32373699\u0026key=e73061d4a1002d8eaa322dc4d880ca1c\u0026schedule=rtmp\u0026pflag=11", + "new_link": "https://core.bilivideo.com/video/uplinkcore/selfbuild/schedule?up_rtmp=live-push.bilivideo.com%2Flive-bvc%2F%3Fstreamname%3Dlive_348892132_32373699%26key%3De10298d4a7539d8eaa322dc4d220ca1c%26schedule%3Drtmp%26pflag%3D11\u0026edge=edge", + "provider": "txy" + } + ], + "notice":{ + "type": 1, + "status": 0, + "title": "", + "msg": "", + "button_text": "", + "button_url": "" + }, + "qr": "", + "need_face_auth": false, + "service_source": "live-streaming", + "rtmp_backup": null, + "up_stream_extra":{ + "isp": "电信" + } + }, + "message": "", + "msg": "" +} +``` + +</details> + +## 关闭直播 + +> https://api.live.bilibili.com/room/v1/Room/stopLive + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +鉴权方式:Cookie中`bili_jct`的值正确并与`csrf`相同 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | ------------------------ | ------ | -------------------- | +| platform | str | 直播平台 | 必要 | 直播姬(pc):pc_link<br />直播姬(android):android_link | +| room_id | num | 直播间id | 必要 | 必须为自己的直播间id | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />65530:token错误(登录错误)<br />-400:没有权限<br />60034: 系统维护仅支持直播姬关播<br />**(其他错误码有待补充)** | +| msg | str | 提示信息 | 默认为空 | +| message | str | 提示信息 | 默认为空 | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ------------ | ---------------------- | +| change | num | 是否改变状态 | 0:未改变<br />1:改变 | +| status | str | 直播间状态 | `PREPARING`、`ROUND` | + +**示例:** + +关闭直播间`10352053`的直播 + +```shell +curl 'https://api.live.bilibili.com/room/v1/Room/stopLive' \ + --data-urlencode 'platform=pc_link' \ + --data-urlencode 'room_id=10352053' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx;bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "msg": "", + "message": "", + "data": { + "change": 1, + "status": "PREPARING" + } +} +``` + +</details> + +## 预更新直播间信息 + +> https://api.live.bilibili.com/xlive/app-blink/v1/preLive/UpdatePreLiveInfo + +*请求方法: POST* + +认证方式:Cookie(SESSDATA) + +鉴权方式:Cookie中`bili_jct`的值正确并与`csrf`相同 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | --- | ---- | ----- | --- | +| csrf | str | CSRF Token(位于cookie) | 必要 | | +| csrf_token | str | CSRF Token(位于cookie) | 必要 | | +| platform | str | 平台标识 | 必要 | 似乎可随意提供<br />网页端: web | +| mobi_app | str | 平台标识? | 必要 | 似乎可随意提供<br />网页端: web | +| build | num | 构建标识? | 必要 | 建议取`1`,似乎可随意提供 | +| cover | str | 直播封面链接 | 非必要 | 图片链接需要在`.hdslb.com`域名下 | +| title | str | 直播间标题 | 非必要 | 参见[更新直播间信息](#更新直播间信息)的title参数 | +| coverVertical | str | (?) | 非必要 | 作用尚不明确 | +| liveDirectionType | num | (?) | 非必要 | `1` | +| visit_id | str | (?) | 非必要 | `""` | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0: 成功<br />1: 错误<br />100402: 图片地址不合法 | +| message | str | 错误信息 | 成功时为`"0"` | +| ttl | num | `1` | | +| data | obj | 内容本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| audit_info | obj | 审核信息 | | + +`data.audit_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| audit_title | str | 被审核的标题 | | +| audit_title_status | num | 标题审核状态 | | +| audit_title_reason | str | 标题审核提示 | | + +**示例:** + +更新直播间封面 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/preLive/UpdatePreLiveInfo' \ + --data-urlencode 'platform=web' \ + --data-urlencode 'mobi_app=web' \ + --data-urlencode 'build=1' \ + --data-urlencode 'cover=https://i0.hdslb.com/bfs/live/59fc254c1f51a962dbf69ae85e4920f2f6fb8dcd.png' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx;bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data":{ + "audit_info":{ + "audit_title": "", + "audit_title_status": 0, + "audit_title_reason": "" + } + } +} +``` + +</details> + +使用此接口更新直播间标题 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/preLive/UpdatePreLiveInfo' \ + --data-urlencode 'platform=web' \ + --data-urlencode 'mobi_app=web' \ + --data-urlencode 'build=1' \ + --data-urlencode 'title=你好你好,我是花火~咱们来找点乐子吧?小灰毛,不要害羞嘛,要大胆的来,一起欢愉吧' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx;bili_jct=xxx' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data":{ + "audit_info":{ + "audit_title": "你好你好,我是花火~咱们来找点乐子吧?小灰毛,不要害羞嘛,要大胆的来,一起欢愉吧", + "audit_title_status": 2, + "audit_title_reason": "先发后审" + } + } +} +``` + +</details> + +## 更新直播间公告 + +> https://api.live.bilibili.com/xlive/app-blink/v1/index/updateRoomNews + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +鉴权方式: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 />65530:token错误(登录错误)<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> + +## PC直播姬版本号获取 +> https://api.live.bilibili.com/xlive/app-blink/v1/liveVersionInfo/getHomePageLiveVersion + +*请求方式:GET* + +认证方式:无 + +鉴权方式:无 + +**请求参数 (Query):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | ------------------------ | ------ | --------------------- | +| appkey | str | APP密钥 | 不必要 |使用PC投稿工具的appkey和appsec| +| sign | str | APP API签名得到的sign | 不必要 | | +| system_version | num | 暂不清楚 | 必要 | 可以直接写2 | +| ts | num | 10位时间戳 | 不必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | ------------------------------------------------------ | +| code | num | 返回值 | 0:成功<br />-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | 作用尚不明确 | +| data | obj | 内容本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | ------------------------ | ---------------------- | +| curr_version | str | 直播姬最新版本号 | | +| build | num | 直播姬构建号 | | +| instruction | str | 更新说明(简要) | | +| file_size | str | 文件大小(字节) | | +| file_md5 | str | 安装包文件MD5 | | +| content | str | HTML格式的更新内容 | | +| download_url | str | 安装包下载链接 | | +| hdiffpatch_switch | num | 增量更新开关? | | + +**示例:** + +获取直播姬最新版本信息 + +```shell +curl 'https://api.live.bilibili.com/xlive/app-blink/v1/liveVersionInfo/getHomePageLiveVersion?appkey=aae92bc66f3edfab&sign=49d289e3ad34c509cc66fbee1c0affec&system_version=2&ts=1752971145' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "curr_version": "7.19.0.9432", + "build": 9432, + "instruction": "\u3010\u65b0\u589e\u3011\u65b0\u589e\u7f8e\u989c\u8c03\u6574\u5165\u53e3\n\u3010\u4f18\u5316\u3011\u5df2\u77e5\u95ee\u9898\u4f18\u5316", + "file_size": "300867136", + "file_md5": "e1619a8e2603aa94b58a58121f94403f", + "content": "<p>\u3010\u65b0\u589e\u3011\u65b0\u589e\u7f8e\u989c\u8c03\u6574\u5165\u53e3<br>\u3010\u4f18\u5316\u3011\u5df2\u77e5\u95ee\u9898\u4f18\u5316</p><p></p><p><br></p>", + "download_url": "https://dl.hdslb.com/bili/bililive/win/Livehime-Win-beta-7.19.0.9432-x64.exe", + "hdiffpatch_switch": 1 + } +} +``` + +</details> + + diff --git a/bb-api-collect/docs/live/message_stream.md b/bb-api-collect/docs/live/message_stream.md new file mode 100644 index 0000000000..be7c355c06 --- /dev/null +++ b/bb-api-collect/docs/live/message_stream.md @@ -0,0 +1,7543 @@ +# 直播间信息流 + +## 获取信息流认证秘钥 + +> https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo + +*请求方法: GET* + +认证方式: Cookie(SESSDATA) + +鉴权方式:[Wbi 签名](../misc/sign/wbi.md), Cookie中的`buvid3`不为空 + +可以选择进行认证,若未认证视作未登录,将会受到限制,详见后续内容。 + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------ | ------ | ---- | +| id | num | 直播间真实id | 必要 | | +| type | num | (?) | 非必要 | 作用尚不明确 | +| web_location | str | (?) | 非必要 | 作用尚不明确 | +| w_rid | str | Wbi 签名 | 必要 | 详见 [Wbi 签名](../misc/sign/wbi.md) | +| wts | num | 当前时间戳 | 必要 | 详见 [Wbi 签名](../misc/sign/wbi.md) | + +注: 从2025年5月26日开始正式强制要求Wbi签名,2025年6月27日开始要求`buvid3`。见[#1295](https://github.com/SocialSisterYi/bilibili-API-collect/issues/1295) + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0: 成功<br />1: 错误<br />65530: token 错误 (登录错误)<br />60009: 分区不存在<br />1002002: 房间号错误<br />**(其他错误码有待补充)** | +| message | str | 错误信息 | 默认为空 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------ | ----- | -------------------- | ---- | +| group | str | live | | +| business_id | num | 0 | | +| refresh_row_factor | num | 0.125 | | +| refresh_rate | num | 100 | | +| max_delay | num | 5000 | | +| token | str | 认证秘钥 | | +| host_list | array | 信息流服务器节点列表 | | + +`data.host_list[n]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ---------- | ---- | +| host | str | 服务器域名 | | +| port | num | TCP 端口 | | +| wss_port | num | WSS 端口 | | +| ws_port | num | WS 端口 | | + +**示例:** + +获得直播间 `1017` 的信息流认证秘钥 + +```shell +curl 'https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo?id=1017&type=0&web_location=444.8&w_rid=cf24f88ea0cbb61e7b29aed0c070187d&wts=1748266797' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data":{ + "group": "live", + "business_id": 0, + "refresh_row_factor": 0.125, + "refresh_rate": 100, + "max_delay": 5000, + "token": "gZ2Pp2T4rIc2HfD0e53FHhQAwKWjb6-QDD84AcxXi8sk3S89XcdvPWOgClZIMZ5mESr19-JKTOFxayX4IjeSQuckWqohE5Y0aHn-agpc2uU7aPXW3-Xmra3QEKljMZS5fM3q2vCf2XcAsjc8Xup7MVAc8SLWWXhQz0s7f1alCkaJBAIPA-i2nS39Ri4O", + "host_list":[ + { + "host": "zj-cn-live-comet.chat.bilibili.com", + "port": 2243, + "wss_port": 2245, + "ws_port": 2244 + }, + { + "host": "zj-cn-live-comet.chat.bilibili.com", + "port": 2243, + "wss_port": 2245, + "ws_port": 2244 + }, + { + "host": "bd-sz-live-comet-14.chat.bilibili.com", + "port": 2243, + "wss_port": 2245, + "ws_port": 2244 + }, + { + "host": "bd-bj-live-comet-09.chat.bilibili.com", + "port": 2243, + "wss_port": 2245, + "ws_port": 2244 + }, + { + "host": "broadcastlv.chat.bilibili.com", + "port": 2243, + "wss_port": 2245, + "ws_port": 2244 + } + ] + } +} +``` + +</details> + +## 数据包格式 + +数据包为 MQ (Message Queue, 消息队列) 使用 WebSocket 或 TCP 连接作为通道, 具体格式为 头部数据 + 正文数据 + +**注: 特别的**, WS 与 WSS 连接地址带有路径 `/sub`, 如 `wss://broadcastlv.chat.bilibili.com:443/sub`. + +**再注:** B 站更新了隐私政策, 连接建立后, 若该连接认证时传入信息来自未登录用户, 会提示 `为保护用户隐私,未注册登陆用户将无法查看他人昵称`, 随后部分数据包(如“弹幕”、“用户交互消息”)的用户 mid 都为 `0`, 用户名部分也使用 `*` 保护, 部分房间受到豁免, 参见 [#732](https://github.com/SocialSisterYi/bilibili-API-collect/issues/732) + +操作流程 (伪代码): + +```javascript +const s = new Socket(uri); +// 认证包 +s.send('verify_hello'); +s.receive('verfiy_reply'); +// 心跳包 +setInterval(() => { + s.send('heartbeat'); + s.receive('heartbeat_reply'); +}, 30000); +// 接收普通包 +while (!s.isclosed()) { + s.receive('normal_package'); +} +``` + +头部格式: + +| 偏移量 | 长度 | 类型 | 含义 | +| ------ | ---- | ------ | ------------------------------------ | +| 0 | 4 | uint32 | 封包总大小 (头部大小 + 正文大小) | +| 4 | 2 | uint16 | 头部大小 (一般为 0x0010, 即 16 字节) | +| 6 | 2 | uint16 | 协议版本:<br />0: 普通包 (正文不使用压缩)<br />1: 心跳及认证包 (正文不使用压缩)<br />2: 普通包 (正文使用 zlib 压缩)<br/>3: 普通包 (使用 brotli 压缩的多个带文件头的普通包) | +| 8 | 4 | uint32 | 操作码 (封包类型) | +| 12 | 4 | uint32 | sequence, 每次发包时向上递增 | + +操作码: + +| 代码 | 含义 | +| ---- | ------------------- | +| 2 | 心跳包 | +| 3 | 心跳包回复 (人气值) | +| 5 | 普通包 (命令) | +| 7 | 认证包 | +| 8 | 认证包回复 | + +*普通包可能包含多条命令, 每个命令有一个头部, 指示该条命令的长度等信息* + +## 数据包 + +### 认证包 + +*方向: 上行* + +注: 连接成功后 5 秒内发送, 否则强制断开连接 + +再注: 若`uid`字段填写的是用户mid,则通过`获取信息流认证密钥`接口使用的认证信息所属用户mid必须与`uid`字段相同,并正确传递认证密钥,否则强制断开连接。 + +**JSON正文:** + +根对象: + +| 字段 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------ | ------ | --------------------------- | +| uid | num | 用户mid | 非必要 | 0 即为游客登录 | +| roomid | num | 加入房间的id | 必要 | 直播间真实id | +| protover | num | 协议版本 | 非必要 | 3, 与数据包头部协议版本无关 | +| platform | str | 平台标识 | 非必要 | `web` | +| type | num | 2 | 非必要 | | +| key | str | 认证秘钥 | 非必要 | | + +**示例:** + +```text +00000000: 0000 00ff 0010 0001 0000 0007 0000 0001 ................ +00000001: 7b22 7569 6422 3a31 3630 3134 3836 3234 {"uid":160148624 +00000002: 2c22 726f 6f6d 6964 223a 3232 3630 3831 ,"roomid":226081 +00000003: 3132 2c22 7072 6f74 6f76 6572 223a 332c 12,"protover":3, +00000004: 2270 6c61 7466 6f72 6d22 3a22 7765 6222 "platform":"web" +00000005: 2c22 7479 7065 223a 322c 226b 6579 223a ,"type":2,"key": +00000006: 2230 7670 5448 5737 7757 556e 6c6f 5270 "0vpTHW7wWUnloRp +00000007: 5251 6b47 764e 626e 7776 7364 6d2d 7159 RQkGvNbnwvsdm-qY +00000008: 4777 4243 5875 2d59 5164 6e57 7653 5547 GwBCXu-YQdnWvSUG +00000009: 7373 4139 7962 4b68 7932 6a78 3952 6f63 ssA9ybKhy2jx9Roc +0000000a: 4150 4651 6d54 4f6b 5277 6b4b 687a 4479 APFQmTOkRwkKhzDy +0000000b: 4839 5054 756f 5468 6834 4630 7562 584c H9PTuoThh4F0ubXL +0000000c: 4964 6e69 3734 5539 304b 4242 6972 3248 Idni74U90KBBir2H +0000000d: 7451 3941 3777 674b 3438 4b7a 495f 5a5a tQ9A7wgK48KzI_ZZ +0000000e: 3838 7557 4e59 6652 4f48 6964 4e6a 3732 88uWNYfROHidNj72 +0000000f: 7061 796e 3479 3071 4268 513d 3d22 7d payn4y0qBhQ=="} +``` + +### 认证包回复 + +*方向: 下行* + +注: 在认证包发送成功后就会收到 JSON 正文, 若失败则返回 HTTP/0.9 的 403 + +**JSON正文:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | ----------- | +| code | num | 返回值 | 0: 认证成功 | + +**示例:** + +```text +00000000: 0000 001a 0010 0001 0000 0008 0000 0001 ................ +00000001: 7b22 636f 6465 223a 307d {"code":0} +``` + +### 心跳包 + +*方向: 上行* + +注: 30 秒左右发送一次, 否则 60 秒后会被强制断开连接 + +**正文:** + +可以为空或任意字符 + +**示例:** + +```text +00000000: 0000 001f 0010 0001 0000 0002 0000 0001 ................ +00000001: 5b6f 626a 6563 7420 4f62 6a65 6374 5d [object Object] +``` + +### 心跳包回复 (人气值) + +*方向: 下行* + +注: 在心跳包发送成功后就会收到 + +**正文:** + +正文分为两个部分 + +- 第一部分: uint32 整数代表的房间当前的人气值 + +- 第二部分: 心跳包正文内容 + +**示例:** + +示例房间内人气值为 2466 (0x000009a2) + +```text +00000000: 0000 0014 0010 0001 0000 0003 0000 0000 ................ +00000001: 0000 09a2 5b6f 626a 6563 7420 4f62 6a65 ....[object Obje +00000002: 6374 5d ct] +``` + +### 普通包 + +*方向: 下行* + +**正文:** + +一般为普通 JSON 数据 + +大多数普通包都经过 zlib 或 brotli 压缩 + +**示例:** + +```text +00000000: 0000 0086 0010 0003 0000 0005 0000 0000 ................ +00000001: 8b38 8000 0000 7200 1000 0000 0000 0500 .8....r......... +00000002: 0000 007b 2263 6d64 223a 2257 4154 4348 ...{"cmd":"WATCH +00000003: 4544 5f43 4841 4e47 4522 2c22 6461 7461 ED_CHANGE","data +00000004: 223a 7b22 6e75 6d22 3a32 3230 3937 2c22 ":{"num":22097," +00000005: 7465 7874 5f73 6d61 6c6c 223a 2232 2e32 text_small":"2.2 +00000006: e4b8 8722 2c22 7465 7874 5f6c 6172 6765 ...","text_large +00000007: 223a 2232 2e32 e4b8 87e4 baba e79c 8be8 ":"2.2.......... +00000008: bf87 227d 7d03 .."}}. +``` + +<!-- 2 年前的索引, 留作纪念, 不会增加新的内容 + +- [弹幕](#弹幕) +- [进场或关注消息](#进场或关注消息) +- [送礼](#送礼) +- [礼物星球点亮](#礼物星球点亮) +- [礼物连击](#礼物连击) +- [通知消息](#通知消息) +- [主播准备中](#主播准备中) +- [直播开始](#直播开始) +- [主播信息更新](#主播信息更新) +- [直播间高能榜](#直播间高能榜) +- [直播间高能用户数量](#直播间高能用户数量) +- [用户到达直播间高能榜前三名的消息](#用户到达直播间高能榜前三名的消息) +- [直播间用户点赞](#直播间用户点赞) +- [直播间点赞数](#直播间点赞数) +- [直播间发红包弹幕](#直播间发红包弹幕) +- [直播间红包](#直播间红包) +- [直播间抢到红包的用户](#直播间抢到红包的用户) +- [直播间看过人数](#直播间看过人数) +- [用户进场特效](#用户进场特效) +- [直播间在所属分区的排名改变](#直播间在所属分区的排名改变) +- [直播间在所属分区排名提升的祝福](#直播间在所属分区排名提升的祝福) +- [直播间信息更改](#直播间信息更改) +- [醒目留言按钮](#醒目留言按钮) +- [顶部横幅](#顶部横幅) +- [下播的直播间](#下播的直播间) +- [未知消息](#未知消息) + +--> + +#### 弹幕 (DANMU_MSG) + +注: 当收到弹幕时接收到此条消息, 10 进制转 16 进制若位数不足则在左侧补 `0` + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ----- | ----------- | ---- | +| cmd | str | `DANMU_MSG` | | +| dm_v2 | str | 空串? | | +| info | array | 弹幕信息 | 感谢 [#1084](https://github.com/SocialSisterYi/bilibili-API-collect/issues/1084) 补充 | +| msg_id | str | 弹幕id? | 极低概率存在 | +| p_is_ack | bool | | 极低概率存在 | +| p_msg_type | num | | 极低概率存在 | +| send_time | num | 发送时间戳 | Unix 毫秒时间戳,极低概率存在 | + +`info` 数组: + +| 项 | 类型 | 内容 | 备注 | +| -- | ----- | ------------------ | ---- | +| 0 | array | 弹幕信息 | 大部分信息可从 `info[0][15].extra` 获取 | +| 1 | str | 弹幕文本 | | +| 2 | array | 发送者信息 | 大部分信息可从 `info[0][15].user` 获取 | +| 3 | array | 发送者粉丝勋章信息 | 若无则为空 | +| 4 | array | 发送者UL等级信息 | | +| 5 | array | ? | | +| 6 | num | 0? | | +| 7 | num | 0? | | +| 8 | null | | | +| 9 | obj | 发送时间戳 | | +| 10 | num | 0? | | +| 11 | num | 0? | | +| 12 | null | | | +| 13 | null | | | +| 14 | num | 0? | | +| 15 | num | ? | | +| 16 | array | ? | | + +`info[0]` 数组: + +| 项 | 类型 | 内容 | 备注 | +| -- | ---- | ------------------------ | ---- | +| 0 | num | | | +| 1 | num | 弹幕模式 | 弹幕的 mode 字段 | +| 2 | num | 弹幕字体大小 | 弹幕的 fontsize 字段 | +| 3 | num | 弹幕颜色 | 弹幕的 color 字段<br />十六进制颜色值的十进制数字 | +| 4 | num | 发送时的 UNIX 毫秒时间戳 | 弹幕的 rnd 字段 | +| 5 | num | | 一个负整数 | +| 6 | num | 0? | | +| 7 | str | 可能为颜色? | 一个 16 进制数 | +| 8 | num | 0? | | +| 9 | num | 0? | | +| 10 | num | 0? | | +| 11 | str | 空串? | | +| 12 | num | 0? | | +| 13 | str | 字符串表示的 JSON Object | 空? | +| 14 | str | 字符串表示的 JSON Object | 空? | +| 15 | obj | 弹幕补充信息 | | +| 16 | obj | 活动相关信息? | | +| 17 | num | 0? | | +| 18 | null | | | + +`info[0][15]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------------- | ---- | ------------ | ---- | +| extra | str | 弹幕信息 | 字符串表示的 JSON | +| mode | num | 弹幕模式? | | +| show_player_type | num | 0? | | +| user | obj | 用户相关信息 | | + +`info[0][15].extra` 表示的对象: + +见下方 JSONC + +```jsonc +{ + "send_from_me": false, // 是否由该接收消息的用户发送 + "mode": 0, // 弹幕模式 (info[0][1]) + "color": 9920249, // 弹幕颜色 (info[0][3]) + "dm_type": 0, + "font_size": 25, // 弹幕字体大小 (info[0][2]) + "player_mode": 1, + "show_player_type": 0, + "content": "白花300块[热]", // 弹幕文本 (info[1]) + "user_hash": "197700816", + "emoticon_unique": "", + "bulge_display": 0, + "recommend_score": 3, + "main_state_dm_color": "", + "objective_state_dm_color": "", + "direction": 0, // 弹幕方向? + "pk_direction": 0, + "quartet_direction": 0, + "anniversary_crowd": 0, + "yeah_space_type": "", + "yeah_space_url": "", + "jump_to_url": "", + "space_type": "", + "space_url": "", + "animation": {}, + "emots": { // 表情相关信息 (用于文本替换) + "[热]": { + "count": 1, + "descript": "[热]", + "emoji": "[热]", + "emoticon_id": 278, + "emoticon_unique": "emoji_278", + "height": 20, + "url": "http://i0.hdslb.com/bfs/live/6df760280b17a6cbac8c1874d357298f982ba4cf.png", + "width": 20 + } + }, + "is_audited": false, + "id_str": "364b06e3c561af3d5921f1253d66c1d575", + "icon": { + "prefix": { + "type": 1, + "resource": "ChronosWealth_4.png" + } + }, + "show_reply": true, // 显示回复? + "reply_mid": 0, + "reply_uname": "", + "reply_uname_color": "", + "reply_is_mystery": false, + "hit_combo": 0 +} +``` + +`info[0][15].user` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ---------- | ---- | +| base | obj | 基本信息 | | +| guard | null | | | +| guard_leader | obj | ? | | +| medal | obj | 粉丝排信息 | 参见 [指定用户的所有粉丝勋章信息](../user/medals.md#指定用户的所有粉丝勋章信息) `data.list[n].uinfo_medal` | +| title | obj | ? | | +| uhead_frame | null | | | +| uid | num | 发送者 mid | | +| wealth | null | | | + +`info[0][15].user.base` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | ---------------- | ------- | +| face | str | 发送者头像 URL | | +| is_mystery | bool | 是否是神秘用户? | | +| name | str | 发送者用户名 | | +| name_color | num | 用户名颜色 | 10 进制 | +| name_color_str | num | 字符串表示的颜色 | | +| offical_info | obj | 认证信息 | 参见 [用户空间详细信息](../user/info.md#用户空间详细信息) `data.official` | +| origin_info | obj | 同 `face` `name` | | +| risk_ctrl_info | null | | | + +`info[0][15].user.title` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------------- | ---- | ----- | ---- | +| old_title_css_id | str | 空串? | | +| title_css_id | str | 空串? | | + +`info[0][16]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ---- | ----- | ---- | +| activity_identity | str | 空串? | | +| activity_source | num | 0? | | +| not_show | num | 0? | | + +`info[2]` 数组: + +| 项 | 类型 | 内容 | 备注 | +| -- | ---- | ------------- | ---- | +| 0 | num | 发送者 mid | 同 `info[0][15].user.uid` | +| 1 | str | 发送者用户名 | 同 `info[0][15].user.base.name` | +| 2 | num | 0? | | +| 3 | num | 0? | | +| 4 | num | 0? | | +| 5 | num | 用户权限等级? | 参见 [用户空间详细信息](../user/info.md#用户空间详细信息) `data.rank` | +| 6 | num | ? | | + +`info[3]` 数组: + +| 项 | 类型 | 内容 | 备注 | +| -- | ---- | ---------------------------------------- | ---- | +| 0 | num | 同 `info[0][15].user.medal.level` | | +| 1 | str | 同 `info[0][15].user.medal.name` | | +| 2 | str | 粉丝牌创建主播名称 | | +| 3 | num | ? | | +| 4 | num | 同 `info[0][15].user.medal.color` | | +| 5 | str | 空串? | | +| 6 | num | 0? | | +| 7 | num | 同 `info[0][15].user.medal.color_border` | | +| 8 | num | 同 `info[0][15].user.medal.color_start` | | +| 9 | num | 同 `info[0][15].user.medal.color_end` | | +| 10 | num | 同 `info[0][15].user.medal.guard_level` | | +| 11 | num | 同 `info[0][15].user.medal.is_light` | | +| 12 | num | 同 `info[0][15].user.medal.ruid` | | + +`info[4]` 数组: + +| 项 | 类型 | 内容 | 备注 | +| -- | ---- | ---- | ---- | +| 0 | num | ? | | +| 1 | num | ? | | +| 2 | num | ? | | +| 3 | num | ? | | +| 4 | num | ? | | + +`info[5]` 数组: + +| 项 | 类型 | 内容 | 备注 | +| -- | ---- | ----- | ---- | +| 0 | str | 空串? | | +| 1 | str | 空串? | | + +`info[9]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | --------------- | +| ct | str | ? | 16 进制 | +| ts | num | 发送时间 | UNIX 秒级时间戳 | + +`info[16]` 数组: + +| 项 | 类型 | 内容 | 备注 | +| -- | ---- | ---- | ---- | +| 0 | num | ? | | + +**示例:** + +<details> +<summary>查看消息示例(带注释):</summary> + +```jsonc +{ + "cmd": "DANMU_MSG", + "dm_v2": "", + "info": [ + [ + 0, + 1, + 25, //字体大小 + 9920249, //弹幕颜色代码(10进制)#975ef9 + 1723979200649, + -1312973962, + 0, + "0bc8acd0", + 0, + 0, + 0, + "", + 0, + "{}", + "{}", + { + "extra": "{\"send_from_me\":false,\"mode\":0,\"color\":9920249,\"dm_type\":0,\"font_size\":25,\"player_mode\":1,\"show_player_type\":0,\"content\":\"白花300块[热]\",\"user_hash\":\"197700816\",\"emoticon_unique\":\"\",\"bulge_display\":0,\"recommend_score\":3,\"main_state_dm_color\":\"\",\"objective_state_dm_color\":\"\",\"direction\":0,\"pk_direction\":0,\"quartet_direction\":0,\"anniversary_crowd\":0,\"yeah_space_type\":\"\",\"yeah_space_url\":\"\",\"jump_to_url\":\"\",\"space_type\":\"\",\"space_url\":\"\",\"animation\":{},\"emots\":{\"[热]\":{\"count\":1,\"descript\":\"[热]\",\"emoji\":\"[热]\",\"emoticon_id\":278,\"emoticon_unique\":\"emoji_278\",\"height\":20,\"url\":\"http://i0.hdslb.com/bfs/live/6df760280b17a6cbac8c1874d357298f982ba4cf.png\",\"width\":20}},\"is_audited\":false,\"id_str\":\"364b06e3c561af3d5921f1253d66c1d575\",\"icon\":{\"prefix\":{\"type\":1,\"resource\":\"ChronosWealth_4.png\"}},\"show_reply\":true,\"reply_mid\":0,\"reply_uname\":\"\",\"reply_uname_color\":\"\",\"reply_is_mystery\":false,\"hit_combo\":0}", + "mode": 0, + "show_player_type": 0, + "user": { + "base": { + "face": "https://i1.hdslb.com/bfs/face/5a9bb9cac3afbb58347c808ae76aaa41ca967d07.jpg", //弹幕发送用户头像 + "is_mystery": false, + "name": "tim1997", //弹幕发送用户名称 + "name_color": 0, + "name_color_str": "", + "official_info": { + "desc": "", + "role": 0, + "title": "", + "type": -1 + }, + "origin_info": { + "face": "https://i1.hdslb.com/bfs/face/5a9bb9cac3afbb58347c808ae76aaa41ca967d07.jpg", + "name": "tim1997" + }, + "risk_ctrl_info": null + }, + "guard": null, + "guard_leader": { + "is_guard_leader": false + }, + "medal": { + "color": 2951253, //粉丝牌颜色(10进制)#2d0855 + "color_border": 16771156, //粉丝牌边框颜色(10进制)#ffe854 + "color_end": 10329087, //粉丝牌渐变颜色结束(10进制)#9d9bff + "color_start": 2951253, //粉丝牌渐变颜色开始(10进制)#2d0855 + "guard_icon": "https://i0.hdslb.com/bfs/live/1d16bf0fcc3b1b768d1179d60f1fdbabe6ab4489.png", //粉丝牌左边的图标 + "guard_level": 1, //类型 1.总督 2.提督 3,舰长 + "honor_icon": "", + "id": 1279130, + "is_light": 1, + "level": 29, //粉丝牌等级 + "name": "果咩吖", //粉丝牌名称 + "ruid": 3546569288714792, //粉丝牌创建者UID + "score": 50427312, + "typ": 0, + "user_receive_count": 0, + "v2_medal_color_border": "#D47AFFFF", //粉丝牌边框颜色(APP) + "v2_medal_color_end": "#9660E5CC", //粉丝牌渐变颜色结束(APP) + "v2_medal_color_level": "#6C00A099", //粉丝牌右边等级数字颜色(APP) + "v2_medal_color_start": "#9660E5CC", //粉丝牌渐变颜色开始(APP) + "v2_medal_color_text": "#FFFFFFFF" //粉丝牌右边圆形颜色(APP) + }, + "title": { + "old_title_css_id": "", + "title_css_id": "" + }, + "uhead_frame": null, + "uid": 6088969, //弹幕发送用户UID + "wealth": null + } + }, + { + "activity_identity": "", + "activity_source": 0, + "not_show": 0 + }, + 0 + ], + "白花300块[热]", //弹幕内容 + [ + 6088969, //同info[0][15].user.uid + "tim1997", //同info[0][15].user.base.name + 0, + 0, + 0, + 10000, + 1, + "" + ], + [ + 29, //同info[0][15].user.medal.level + "果咩吖", //同info[0][15].user.medal.name + "果宝Official", //粉丝牌创建主播名称 + 31180317, + 2951253, //同info[0][15].user.medal.color + "", + 0, + 16771156, //同info[0][15].user.medal.color_border + 2951253, //同info[0][15].user.medal.color_start + 10329087, //同info[0][15].user.medal.color_end + 1, //同info[0][15].user.medal.guard_level + 1, //同info[0][15].user.medal.is_light + 3546569288714792 //同info[0][15].user.medal.ruid + ], + [ + 39, + 0, + 10512625, + 42523, + 2 + ], + [ + "", + "" + ], + 0, + 0, + null, + { + "ct": "AFFF4206", + "ts": 1723979200 //时间戳(秒级) + }, + 0, + 0, + null, + null, + 0, + 1040, + [ + 49 + ], + null + ] +} +``` + +</details> + +#### 交互信息合并 (DM_INTERACTION) + +注: 连续多条相同弹幕时触发 + +**JSON正文:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------------- | ---- | +| cmd | str | `DM_INTERACTION` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------- | ---- | +| id | num | 事件 ID | | +| status | num | 状态 | | +| type | num | 事件类型 | 101:投票<br />102:弹幕<br />103:关注<br />104:送礼<br />105:分享<br />106:点赞 | +| data | str | 事件数据 | 一个JSON字符串 | +| dmsource | num | | | + +`data.data` 字符串对象: + +内容格式取决于`data.type`的类型,下面将按照`data.data(类型)`进行区分标记。 + +温馨提示: 要记得先解析`data.data`内的JSON字符串,不要直接使用哦。 + +`data.data(101)` 对象: (投票) + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| question | str | 投票问题 | | +| options | obj | 投票详细选项 | | +| vote_id | num | 投票id | | +| cnt | num | 弹幕计数 | | +| duration | num | 持续时间 | 单位毫秒 | +| left_duration | num | 剩余时间 | 单位毫秒 | +| fade_duration | num | (?) | | +| waiting_duration | num | (?) | | +| result | num | 投票倾向状态 | | +| result_text | str | 投票倾向提示 | | +| component | str | 投票链接 | | +| natural_die_duration | num | (?) | | +| my_vote | num | (?) | | +| component_anchor | str | 投票控制链接 | | +| audit_reason | str | 审核结果 | | +| combo | obj | 投票状态展示 | | + +`data.data(101).options` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| idx | num | 选项索引 | | +| desc | str | 选项内容 | | +| cnt | num | 票数 | | +| percent | num | 显示占比 | | + +`data.data(101).combo` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| id | num | 标识id | 同`data.data.options`数组中对象的`idx` | +| status | num | 状态 | 同`data.status` | +| content | str | 投票选项内容 | | +| cnt | str | 弹幕计数 | | +| guide | str | (?) | 空字符串 | +| left_duration | num | 剩余时间 | | +| fade_duration | num | (?) | | +| prefix_icon | str | 投票选项图标 | | + +`data.data(102)` 对象: (弹幕) + +| 字段 | 类型 | 内容 | 备注 | +| -------------------- | ----- | -------------------- | ---- | +| combo | array | 连续发送弹幕事件信息 | | +| merge_interval | num | 合并弹幕时间间隔 | | +| card_appear_interval | num | 弹窗出现时间间隔 | | +| send_interval | num | 发送时间间隔 | | + +`data.data(102).combo[n]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | -------------- | ------------- | +| id | num | 标识 ID | | +| status | num | 状态 | | +| content | str | 重复的弹幕内容 | | +| cnt | num | 重复数量 | | +| guide | str | 标题词 | "他们都在说:" | +| left_duration | num | 左移时长 | | +| fade_duration | num | 淡化时长 | | + +`data.data(103)` 对象: (关注) + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| fade\_duration | num | | | +| cnt | num | 关注计数 | | +| card_appear_interval | num | | | +| suffix\_text | str | 提示文本 | `人关注了主播` | +| reset\_cnt | num | | | +| display\_flag | num | | | + +`data.data(104)` 对象: (送礼) + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| fade\_duration | num | | | +| cnt | num | 投喂计数 | | +| card_appear_interval | num | | | +| suffix\_text | str | 提示文本 | `人在投喂` | +| reset\_cnt | num | | | +| display\_flag | num | | | +| gift\_id | num | 礼物 ID | | +| gift_alert_message | str | | | + +`data.data(105)` 对象: (分享) + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| fade\_duration | num | | | +| cnt | num | 分享计数 | | +| card_appear_interval | num | | | +| suffix\_text | str | 提示文本 | `人分享了直播间` | +| reset\_cnt | num | | | +| display\_flag | num | | | + +`data.data(106)` 对象: (点赞) + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| fade\_duration | num | | | +| cnt | num | 点赞计数 | | +| card_appear_interval | num | | | +| suffix\_text | str | 提示文本 | `人正在点赞` | +| reset\_cnt | num | | | +| display\_flag | num | | | + +**示例:** + +<details> +<summary>查看正文示例:</summary> + +type===101 + +```json +{ + "cmd": "DM_INTERACTION", + "data": { + "data": "{\"question\":\"投票\",\"options\":[{\"idx\":1,\"desc\":\"赞成\",\"cnt\":0,\"percent\":0.5},{\"idx\":2,\"desc\":\"弃权\",\"cnt\":0,\"percent\":0.5}],\"vote_id\":98014370742272,\"cnt\":0,\"duration\":60000,\"left_duration\":60000,\"fade_duration\":1000,\"waiting_duration\":-1,\"result\":1,\"result_text\":\"平局\",\"component\":\"https://live.bilibili.com/p/html/live-app-guessing-game/vote.html?is_live_half_webview=1\\u0026hybrid_half_ui=1,3,100p,245,0,0,30,100,12,0;2,2,375,100p,0,0,30,100,12,0;3,3,100p,245,0,0,30,100,12,0;4,2,375,100p,0,0,30,100,12,0;5,3,100p,70p,0,0,30,100,12,0;6,3,100p,70p,0,0,30,100,12,0;7,3,100p,70p,0,0,30,100,12,0;8,3,100p,70p,0,0,30,100,12,0\",\"natural_die_duration\":30000,\"my_vote\":0,\"component_anchor\":\"https://live.bilibili.com/p/html/live-app-guessing-game/anchor_vote.html?pc_ui=390,428,0,3\\u0026is_live_half_webview=1\\u0026hybrid_half_ui=1,3,100p,448,0,0,30,0,12,0;2,2,375,100p,0,0,30,0,12,0;3,3,100p,448,0,0,30,0,12,0;4,2,375,100p,0,0,30,0,12,0;5,3,100p,448,0,0,30,0,12,0;6,2,320,100p,0,0,30,0,12,0;7,2,320,100p,0,0,30,0,12,0;8,2,320,100p,0,0,30,0,12,0#/\",\"audit_reason\":\"您提交的弹幕投票未审核通过,请修改\",\"combo\":[{\"id\":1,\"status\":2,\"content\":\"赞成\",\"cnt\":0,\"guide\":\"\",\"left_duration\":60000,\"fade_duration\":0,\"prefix_icon\":\"http://i0.hdslb.com/bfs/dm/7d7e3682c9116aa3503418abe3cde6b45ed2e91e.png\"},{\"id\":2,\"status\":2,\"content\":\"弃权\",\"cnt\":0,\"guide\":\"\",\"left_duration\":60000,\"fade_duration\":0,\"prefix_icon\":\"http://i0.hdslb.com/bfs/dm/f83c7280b2a90b4f58a68fd8c594ea7d5667e3cb.png\"}]}", + "dmscore": 36, + "id": 98014370742272, + "status": 2, + "type": 101 + } +} +``` + +type===102 + +```json +{ + "cmd": "DM_INTERACTION", + "data": { + "id": 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 + } + } +} +``` + +type===103 + +```json +{ + "cmd": "DM_INTERACTION", + "data": { + "data": "{\"fade_duration\":10000,\"cnt\":6,\"card_appear_interval\":0,\"suffix_text\":\"人关注了主播\",\"reset_cnt\":0,\"display_flag\":1}", + "dmscore": 36, + "id": 94362402889728, + "status": 4, + "type": 103 + } +} +``` + +type===104 + +```json +{ + "cmd": "DM_INTERACTION", + "data": { + "data": "{\"fade_duration\":10000,\"cnt\":5,\"card_appear_interval\":0,\"suffix_text\":\"人在投喂\",\"reset_cnt\":0,\"display_flag\":1,\"gift_id\":33988,\"gift_alert_message\":\"投喂一个%s支持主播\"}", + "dmscore": 36, + "id": 85744481752576, + "status": 5, + "type": 104 + } +} +``` + +type===105 + +```json +{ + "cmd": "DM_INTERACTION", + "data": { + "data": "{\"fade_duration\":10000,\"cnt\":1,\"card_appear_interval\":0,\"suffix_text\":\"人分享了直播间\",\"reset_cnt\":0,\"display_flag\":1}", + "dmscore": 36, + "id": 85743053669888, + "status": 4, + "type": 105 + } +} +``` + +type===106 + +```json +{ + "cmd": "DM_INTERACTION", + "data": { + "data": "{\"fade_duration\":10000,\"cnt\":11,\"card_appear_interval\":0,\"suffix_text\":\"人正在点赞\",\"reset_cnt\":1,\"display_flag\":1}", + "dmscore": 36, + "id": 66159395305984, + "status": 5, + "type": 106 + } +} +``` + +</details> + +#### 用户交互消息 (INTERACT_WORD) + +注: 有用户进入直播间、关注主播、分享直播间时触发 + +已被`INTERACT_WORD_V2`替换。 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `INTERACT_WORD` | | +| data | obj | 用户交互信息 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| contribution | obj | 待调查 | | +| dmscore | num | 待调查 | | +| fans_medal | obj | 粉丝勋章 | | +| identities | num | 待调查 | | +| is_spread | num | 待调查 | | +| msg_type | num | 1为进场,2为关注,3为分享 | | +| roomid | num | 房间号 | | +| is_spread | num | 待调查 | | +| is_spread | num | 待调查 | | +| score | num | 待调查 | | +| spread_desc | str | 待调查 | | +| spread_info | str | 待调查 | | +| tail_icon | num | 待调查 | | +| timestamp | num | 时间戳 | | +| trigger_time | num | 触发时间 | | +| uid | num | 用户ID | | +| uname | str | 用户名称 | | +| uname_color | str | 用户名称颜色 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "INTERACT_WORD", + "data": { + "contribution": { + "grade": 0 + }, + "dmscore": 4, + "fans_medal": { + "anchor_roomid": 890976, + "guard_level": 0, + "icon_id": 0, + "is_lighted": 0, + "medal_color": 6067854, + "medal_color_border": 12632256, + "medal_color_end": 12632256, + "medal_color_start": 12632256, + "medal_level": 1, + "medal_name": "小豆皮", + "score": 134, + "special": "", + "target_id": 6574487 + }, + "identities": [ + 1 + ], + "is_spread": 0, + "msg_type": 1, + "roomid": 24143902, + "score": 1644563948936, + "spread_desc": "", + "spread_info": "", + "tail_icon": 0, + "timestamp": 1644563948, + "trigger_time": 1644563947876475000, + "uid": 335979315, + "uname": "TIM_Init", + "uname_color": "" + } +} +``` + +</details> + +#### 用户交互消息V2 (INTERACT_WORD_V2) + +注: 该cmd已将`INTERACT_WORD`替换 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `INTERACT_WORD_V2` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| dmscore | num | | | +| pb | str | 使用 base64 编码 protobuf 后的数据 | 解析后数据基本与`INTERACT_WORD`的`data`相同 | + +用于解析protobuf数据的proto文件: [#1332(comment)](https://github.com/SocialSisterYi/bilibili-API-collect/issues/1332#issuecomment-3047237367) + +注: 先用 base64 解码 `data.pb` 内的字符串为字节数据pb,再使用proto文件解码pb数据。 + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "INTERACT_WORD_V2", + "data": { + "dmscore": 3, + "pb": "CJTwwNEBEgpTdGFyU2VhMjQ2IgIDASgBMNWgITispaTDBkDUubHe/jJKLAiv8CkQEhoG55Sf5oCBIKS6ngYopLqeBjCkup4GOKS6ngZAAWDVoCFo9JQRYgB4gZ/v1tmc1qcYmgEAsgHPAQiU8MDRARJYCgpTdGFyU2VhMjQ2EkpodHRwczovL2kwLmhkc2xiLmNvbS9iZnMvZmFjZS8xMDliNzg3YzVmMTEzYzRhM2M3NDE1YmI5YmY2YjgyYmMzM2JjNGUyLmpwZxpnCgbnlJ/mgIEQEhikup4GIKS6ngYopLqeBjCkup4GOP/hAUgBUK/wKWD0lBF6CSNEQzZCNkI5OYIBCSNEQzZCNkI5OYoBCSNEQzZCNkI5OZIBCSNGRkZGRkZGRpoBCSM4MTAwMUY5OSICCAkyALoBAA==" + } +} +``` + +</details> + +#### 上舰通知 (GUARD_BUY) + +注: 当有用户购买 舰长 / 提督 / 总督 时 + +**JSON消息:** + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---- | +| cmd | str | `GUARD_BUY` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- |-----|--------------------------|-----| +| uid | num | 用户ID | | +| username | str | 用户名称 | | +| guard_level | num | 大航海等级 | 1: 总督<br />2: 提督<br />3:舰长 | +| num | num | 数量 | | +| price | num | 原金瓜子标价 | 即 CNY\*1000 | +| gift_id | num | 礼物id | | +| gift_name | str | 礼物名称 | | +| start_time | num | 待调查 | | +| end_time | num | 待调查 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "GUARD_BUY", + "data": { + "uid": 14225357, + "username": "妙妙喵喵妙妙喵O_O", + "guard_level": 3, + "num": 1, + "price": 198000, + "gift_id": 10003, + "gift_name": "舰长", + "start_time": 1677069316, + "end_time": 1677069316 + } +} +``` + +</details> + +#### 用户庆祝消息 (USER_TOAST_MSG) + +注: 用户购买 舰长 / 提督 / 总督 后的庆祝消息, 内容包含用户陪伴天数 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------------- | ---- | +| cmd | str | `USER_TOAST_MSG` | | +| data | obj | 信息本体 | | + +`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: 总督<br />2:<br />提督<br />3:舰长 | +| is_group | num | 待调查 | | +| is_show | num | 待调查 | | +| num | num | 上舰个数 | | +| op_type | num | 待调查 | | +| payflow_id | str | 待调查 | | +| price | num | 实际金瓜子标价 | 即 CNY\*1000 | +| 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 +{ + "cmd": "USER_TOAST_MSG", + "data": { + "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> + +#### 醒目留言 (SUPER_CHAT_MESSAGE) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | --------------------- | ---- | +| cmd | str | `SUPER_CHAT_MESSAGE` | | +| data | obj | 信息本体 | | +| roomid | num | 直播间房间号 (非短号) | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- |-----|----------------| --------- | +| background_bottom_color | str | 待调查 | | +| background_color | str | 待调查 | | +| background_color_end | str | 待调查 | | +| background_color_start | str | 待调查 | | +| background_icon | str | 待调查 | | +| background_image | str | 待调查 | | +| background_price_color | str | 待调查 | | +| color_point | num | 待调查 | | +| dmscore | num | 待调查 | | +| end_time | num | 待调查 | | +| gift | obj | 礼物信息 | | +| id | num | 醒目留言 ID | | +| is_ranked | num | 待调查 | | +| is_send_audit | num | 待调查 | | +| medal_info | obj | SC发送用户佩戴的粉丝牌信息 | | +| message | str | sc内容 | | +| message_font_color | str | SC文本颜色 | | +| message_trans | str | 机翻sc内容 | | +| price | num | sc金额 | 为 CNY 价值 | +| rate | num | 待调查 | | +| start_time | num | 待调查 | | +| time | num | sc持续时间 | | +| token | num | 待调查 | | +| trans_mark | num | 待调查 | | +| ts | num | 待调查 | | +| uid | num | 发送用户uid | | +| user_info | obj | 发送用户信息 | | + +`data.gift` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- |-----|------|------| +| gift_id | num | 礼物id | | +| gift_name | str | 礼物名称 | 一般均为"醒目留言" | +| num | num | 数量 | | + +`data.medal_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- |-----|-------------|------| +| anchor_roomid | num | 房间号 | 包含短号 | +| anchor_uname | str | 主播昵称 | | +| guard_level | num | 大航海等级 | 1: 总督<br/>2: 提督<br />3: 舰长 | +| icon_id | num | 待调查 | | +| is_lighted | num | 待调查 | | +| medal_color | str | 待调查 | | +| medal_color_border | num | 待调查 | | +| medal_color_end | num | 待调查 | | +| medal_color_start | num | 待调查 | | +| medal_level | num | 粉丝牌等级 | | +| medal_name | str | 粉丝牌名称 | | +| special | str | 待调查 | | +| target_id | num | 粉丝牌对应的主播mid | | + +`data.user_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- |-----|-------|------| +| face | num | 用户头像 | | +| face_frame | num | 头像边框 | | +| guard_level | num | 大航海等级 | 1: 总督<br />2: 提督<br />3: 舰长 | +| is_main_vip | num | 待调查 | | +| is_svip | num | 待调查 | | +| is_vip | num | 待调查 | | +| level_color | str | 待调查 | | +| manager | num | 待调查 | | +| name_color | str | 待调查 | | +| title | str | 待调查 | | +| uname | str | 用户名称 | | +| user_level | num | 待调查 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "SUPER_CHAT_MESSAGE", + "data": { + "background_bottom_color": "#2A60B2", + "background_color": "#EDF5FF", + "background_color_end": "#405D85", + "background_color_start": "#3171D2", + "background_icon": "", + "background_image": "https://i0.hdslb.com/bfs/live/a712efa5c6ebc67bafbe8352d3e74b820a00c13e.png", + "background_price_color": "#7497CD", + "color_point": 0.7, + "dmscore": 120, + "end_time": 1677069095, + "gift": { + "gift_id": 12000, + "gift_name": "醒目留言", + "num": 1 + }, + "id": 6522809, + "is_ranked": 1, + "is_send_audit": 0, + "medal_info": { + "anchor_roomid": 732, + "anchor_uname": "Asaki大人", + "guard_level": 3, + "icon_id": 0, + "is_lighted": 1, + "medal_color": "#1a544b", + "medal_color_border": 6809855, + "medal_color_end": 5414290, + "medal_color_start": 1725515, + "medal_level": 21, + "medal_name": "ASAKI", + "special": "", + "target_id": 194484313 + }, + "message": "猪播完美预测自己第一个死,这就是鹅鸭杀高玩吗", + "message_font_color": "#A3F6FF", + "message_trans": "", + "price": 30, + "rate": 1000, + "start_time": 1677069035, + "time": 60, + "token": "7BED5681", + "trans_mark": 0, + "ts": 1677069035, + "uid": 294094150, + "user_info": { + "face": "https://i1.hdslb.com/bfs/face/7a11b48e0a3055e220fa8b4c7d938cd4bcac2577.jpg", + "face_frame": "https://i0.hdslb.com/bfs/live/80f732943cc3367029df65e267960d56736a82ee.png", + "guard_level": 3, + "is_main_vip": 1, + "is_svip": 0, + "is_vip": 0, + "level_color": "#969696", + "manager": 0, + "name_color": "#00D1F1", + "title": "0", + "uname": "界原虚", + "user_level": 6 + } + }, + "roomid": 6154037 +} +``` + +</details> + +#### 醒目留言日语 (SUPER_CHAT_MESSAGE_JPN) + +基本同 [醒目留言 (SUPER_CHAT_MESSAGE)](#醒目留言-super_chat_message), 但多了 `message_jpn` 字段 + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "SUPER_CHAT_MESSAGE_JPN", + "data": { + "id": "3790747", + "uid": "394060741", + "price": 30, + "rate": 1000, + "message": "棉花!!转盘中了武器后,上号30抽3武器,救命!!!", + "message_jpn": "", + "is_ranked": 1, + "background_image": "https://i0.hdslb.com/bfs/live/a712efa5c6ebc67bafbe8352d3e74b820a00c13e.png", + "background_color": "#EDF5FF", + "background_icon": "", + "background_price_color": "#7497CD", + "background_bottom_color": "#2A60B2", + "ts": 1650363318, + "token": "24655ABF", + "medal_info": { + "icon_id": 0, + "target_id": 1871001, + "special": "", + "anchor_uname": "棉花大哥哥", + "anchor_roomid": 103, + "medal_level": 24, + "medal_name": "棉花花", + "medal_color": "#1a544b" + }, + "user_info": { + "uname": "改了名真的能中吗", + "face": "http://i1.hdslb.com/bfs/face/e2391f132cd981fb70468a8ce9418513e959eb10.jpg", + "face_frame": "https://i0.hdslb.com/bfs/live/80f732943cc3367029df65e267960d56736a82ee.png", + "guard_level": 3, + "user_level": 11, + "level_color": "#61c05a", + "is_vip": 0, + "is_svip": 0, + "is_main_vip": 1, + "title": "0", + "manager": 0 + }, + "time": 60, + "start_time": 1650363318, + "end_time": 1650363378, + "gift": { + "num": 1, + "gift_id": 12000, + "gift_name": "醒目留言" + } + }, + "roomid": "34348" +} +``` + +</details> + +#### 醒目留言删除 (SUPER_CHAT_MESSAGE_DELETE) + +<!--{ + "gh": [360] +}--> + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `SUPER_CHAT_MESSAGE_DELETE` | | +| data | obj | 消息本体 | | +| roomid | num | 直播间号 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| ids | arr | 待删除的醒目留言 ID 列表 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "SUPER_CHAT_MESSAGE_DELETE", + "data": { + "ids": [ + 3897503 + ] + }, + "roomid": 23708804 +} +``` + +</details> + +#### 送礼 (SEND_GIFT) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---- | +| cmd | str | `SEND_GIFT` | | +| data | obj | 消息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | -------- | ------ | --------- | +| action | str | 礼物操作,一般为"投喂" | | +| batch_combo_id | str | 待调查 | 有时为空字符串 | +| batch_combo_send | obj | 待调查 | 有时为null | +| beatId | str | 待调查 | | +| biz_source | str | 待调查 | | +| blind_gift | | 待调查 | | +| broadcast_id | num | 待调查 | | +| coin_type | str | 标识金银瓜子礼物对应是否付费? | | +| combo_resources_id | num | 待调查 | | +| combo_send | | 待调查 | | +| comber_stay_time | num | 待调查 | | +| combo_total_coin | num | 待调查 | | +| crit_prob | num | 待调查 | | +| demarcation | num | 待调查 | | +| discount_price | num | 待调查 | | +| dmscore | num | 待调查 | | +| draw | num | 待调查 | | +| effect | num | 待调查 | | +| effect_block | num | 待调查 | | +| face | str | 礼物投喂者的头像URL | | +| face_effect_id | num | 待调查 | | +| face_effect_type | num | 待调查 | | +| float_sc_resource_id | num | 待调查 | | +| giftId | num | 礼物ID | | +| giftName | str | 礼物名称 | | +| giftType | num | 待调查 | | +| gold | number | 待调查 | | +| guard_level | num | 待调查 | | +| is_first | bool | 待调查 | | +| is_join_receiver | bool | 待调查 | | +| is_naming | bool | 待调查 | | +| is_special_batch | num | 待调查 | | +| magnification | num | 待调查 | | +| medal_info | obj | 礼物投喂者粉丝奖牌信息 | | +| name_color | str | 待调查 | | +| num | num | 该次投喂的礼物数量 | | +| original_gift_name | str | 待调查 | | +| price | num | 价值 | | +| rcost | num | 待调查 | | +| receive_user_info | obj | 礼物接收者信息,一般是主播 | | +| remain | num | 待调查 | | +| rnd | num | 礼物发送时的时间戳,以及后面9位未知数字 | | +| send_master | | 待调查 | | +| silver | num | 待调查 | | +| super | num | 待调查 | | +| super_batch_gift_num | num | 待调查 | | +| super_gift_num | num | 待调查 | | +| svga_block | num | 待调查 | | +| switch | bool | 待调查 | | +| tag_image | str | 待调查 | | +| tid | num | 礼物发送时的时间戳,以及后面9位未知数字 | 似乎与rnd字段相同 | +| timestamp | num | 礼物发送时的时间戳 | | +| top_list | | 待调查 | | +| total_coin | num | 实际金银瓜子总价值 | 不是总等于 num*price | +| uid | num | 礼物投喂者的UID | | +| uname | str | 礼物投喂者的名称 | | + +`data.batch_combo_send` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | -------- | ------ | --------- | +| action | str | 礼物操作,一般为"投喂" | | +| batch_combo_id | str | 待调查 | | +| batch_combo_num | num | 待调查 | | +| blind_gift | | 待调查 | | +| gift_id | num | 待调查 | | +| gift_name | str | 投喂的礼物名称 | 待调查 | +| gift_num | num | 投喂礼物数量 | 待调查 | +| send_master | | 待调查 | | +| uid | num | 礼物投喂者的UID | | +| uname | str | 礼物投喂者的名称 | | + +`data.medal_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | -------- | ------ | --------- | +| anchor_roomid | num | 待调查 | | +| anchor_uname | str | 待调查 | | +| guard_level | num | 待调查 | | +| icon_id | num | 待调查 | | +| is_lighted | num | 待调查 | | +| medal_color | num | 礼物投喂者的粉丝奖牌颜色 | 十六进制颜色值转为了十进制表示 | +| medal_border_color | num | 礼物投喂者的粉丝奖牌边框颜色 | 十六进制颜色值的十进制表示 | +| medal_color_end | num | 待调查 | | +| medal_color_start | num | 待调查 | | +| medal_level | num | 礼物投喂者的粉丝奖牌等级 | | +| medal_name | str | 礼物投喂者的粉丝奖牌名称 | | +| special | str | 待调查 | | +| target_id | num | 待调查 | | + +`data.receive_user_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | -------- | ------ | --------- | +| uid | num | 礼物接收者的UID | 一般为主播的UID | +| uname | str | 礼物接收者的名称 | 一般为主播的名称 | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "SEND_GIFT", + "data": { + "action": "投喂", + "batch_combo_id": "batch:gift:combo_id:510149209:36047134:31036:1673622464.8445", + "batch_combo_send": { + "action": "投喂", + "batch_combo_id": "batch:gift:combo_id:510149209:36047134:31036:1673622464.8445", + "batch_combo_num": 1, + "blind_gift": null, + "gift_id": 31036, + "gift_name": "小花花", + "gift_num": 1, + "send_master": null, + "uid": 510149209, + "uname": "12138额83121" + }, + "beatId": "", + "biz_source": "live", + "blind_gift": null, + "broadcast_id": 0, + "coin_type": "gold", + "combo_resources_id": 1, + "combo_send": { + "action": "投喂", + "combo_id": "gift:combo_id:510149209:36047134:31036:1673622464.8434", + "combo_num": 1, + "gift_id": 31036, + "gift_name": "小花花", + "gift_num": 1, + "send_master": null, + "uid": 510149209, + "uname": "12138额83121" + }, + "combo_stay_time": 3, + "combo_total_coin": 100, + "crit_prob": 0, + "demarcation": 1, + "discount_price": 100, + "dmscore": 8, + "draw": 0, + "effect": 0, + "effect_block": 0, + "face": "https://i1.hdslb.com/bfs/face/fb79103e8b33547023e2010030b6889bba2b49bf.jpg", + "face_effect_id": 0, + "face_effect_type": 0, + "float_sc_resource_id": 0, + "giftId": 31036, + "giftName": "小花花", + "giftType": 0, + "gold": 0, + "guard_level": 0, + "is_first": true, + "is_join_receiver": false, + "is_naming": false, + "is_special_batch": 0, + "magnification": 1, + "medal_info": { + "anchor_roomid": 0, + "anchor_uname": "", + "guard_level": 0, + "icon_id": 0, + "is_lighted": 0, + "medal_color": 0, + "medal_color_border": 0, + "medal_color_end": 0, + "medal_color_start": 0, + "medal_level": 0, + "medal_name": "", + "special": "", + "target_id": 0 + }, + "name_color": "", + "num": 1, + "original_gift_name": "", + "price": 100, + "rcost": 164536872, + "receive_user_info": { + "uid": 36047134, + "uname": "小霖QL" + }, + "remain": 0, + "rnd": "1673622464121900003", + "send_master": null, + "silver": 0, + "super": 0, + "super_batch_gift_num": 1, + "super_gift_num": 1, + "svga_block": 0, + "switch": true, + "tag_image": "", + "tid": "1673622464121900003", + "timestamp": 1673622464, + "top_list": null, + "total_coin": 100, + "uid": 510149209, + "uname": "12138额83121" + } +} +``` + +</details> + +#### 礼物星球点亮 (GIFT_STAR_PROCESS) + +注: 主播的礼物星球其一点亮之后 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `GIFT_STAR_PROCESS` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | -------- | ------ | --------- | +| status | num | 待调查 | | +| tip | str | 点亮礼物星球的消息文本 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "GIFT_STAR_PROCESS", + "data": { + "status": 1, + "tip": "情书已点亮" + } +} +``` + +</details> + +#### 礼物星球进度更新 (WIDGET_GIFT_STAR_PROCESS) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `WIDGET_GIFT_STAR_PROCESS` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| start_date | num | 开始时间? | 一个年月日数字,格式 `Number(String(年) + String(月) + String(日))`,详见消息示例 | +| process_list | arr | 礼物进度列表 | | +| finished | bool | 是否完成? | | +| ddl_timestamp | num | 截止时间? | Unix 秒时间戳 | +| version | num | 更新时间 | Unix 毫秒时间戳 | +| reward_gift | num | | | +| reward_gift_img | str | | | +| reward_gift_name | str | | | +| level_info | null | (?) | | + +`data.process_list` 数组: + +| 索引 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| 0 | obj | 礼物需求1 | | +| 1 | obj | 礼物需求2 | | +| 2 | obj | 礼物需求3 | | + +`data.process_list` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| gift_id | num | 礼物id | | +| gift_img | str | 礼物图片 | | +| gift_name | str | 礼物名称 | `礼物星球` | +| completed_num | num | 当前数量 | | +| target_num | num | 目标数量 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "WIDGET_GIFT_STAR_PROCESS", + "data": { + "start_date": 20250728, + "process_list": [ + { + "gift_id": 33988, + "gift_img": "https://s1.hdslb.com/bfs/live/7164c955ec0ed7537491d189b821cc68f1bea20d.png", + "gift_name": "礼物星球", + "completed_num": 155, + "target_num": 1000 + }, + { + "gift_id": 31036, + "gift_img": "https://s1.hdslb.com/bfs/live/8b40d0470890e7d573995383af8a8ae074d485d9.png", + "gift_name": "礼物星球", + "completed_num": 123, + "target_num": 500 + }, + { + "gift_id": 34382, + "gift_img": "https://s1.hdslb.com/bfs/live/3a1cc7ca50da48670d9f7aa6c8d3cd874228f7b0.png", + "gift_name": "礼物星球", + "completed_num": 0, + "target_num": 1 + } + ], + "finished": false, + "ddl_timestamp": 1754236800, + "version": 1754030237877, + "reward_gift": 0, + "reward_gift_img": "", + "reward_gift_name": "", + "level_info": null + } +} +``` + +</details> + +#### 礼物连击 (COMBO_SEND) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `COMBO_SEND` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | -------- | ------ | --------- | +| action | str | 礼物操作,一般为"投喂" | | +| batch_combo_id | str | 待调查 | | +| batch_combo_num | num | 连击礼物数量 | | +| combo_id | str | 待调查 | | +| combo_num | str | 连击礼物数量 | | +| combo_total_coin | num | 待调查 | | +| dmscore | num | 待调查 | | +| gift_id | num | 待调查 | | +| gift_name | str | 连击礼物的名称 | | +| gift_num | num | 0 | | +| is_join_receiver | bool | 待调查 | | +| is_naming | bool | 待调查 | | +| is_show | num | 待调查 | | +| medal_info | obj | 礼物投喂者的粉丝勋章信息 | | +| name_color | str | 待调查 | | +| r_uname | str | 主播的名称 | | +| receive_user_info | obj | 主播的UID和名称 | | +| ruid | num | 主播的UID | | +| send_master | | 待调查 | | +| total_num | num | 连击礼物数量 | | +| uid | num | 礼物投喂者的UID | | +| uname | str | 礼物投喂者的名称 | | + +`data.receive_user_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | -------- | ------ | --------- | +| uid | number | 礼物接收者的UID | 一般为主播的UID | +| uname | string | 礼物接收者的名称 | 一般为主播的名称 | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "COMBO_SEND", + "data": { + "action": "投喂", + "batch_combo_id": "batch:gift:combo_id:3493090830584635:29857468:31036:1673774515.6190", + "batch_combo_num": 2, + "combo_id": "gift:combo_id:3493090830584635:29857468:31036:1673774515.6180", + "combo_num": 2, + "combo_total_coin": 200, + "dmscore": 112, + "gift_id": 31036, + "gift_name": "小花花", + "gift_num": 0, + "is_join_receiver": false, + "is_naming": false, + "is_show": 1, + "medal_info": { + "anchor_roomid": 0, + "anchor_uname": "", + "guard_level": 0, + "icon_id": 0, + "is_lighted": 1, + "medal_color": 6067854, + "medal_color_border": 6067854, + "medal_color_end": 6067854, + "medal_color_start": 6067854, + "medal_level": 3, + "medal_name": "爱珞珞", + "special": "", + "target_id": 3493076559465366 + }, + "name_color": "", + "r_uname": "露萌不要雨草", + "receive_user_info": { + "uid": 29857468, + "uname": "露萌不要雨草" + }, + "ruid": 29857468, + "send_master": null, + "total_num": 2, + "uid": 3493090830584635, + "uname": "DOC-Neo" + } +} +``` + +</details> + +#### 特殊礼物 (SPECIAL_GIFT) + +<!--{ + "gh": [360] +}--> + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | ---- | +| cmd | str | `SPECIAL_GIFT` | | +| data | obj | 信息本体 | | + +`data` 对象: + +以 数字 为键, JSON Object 为值的表 + +`data['?']` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | ---- | +| action | str | 操作? | | +| content | str | 内容 | | +| hadJoin | num | 是否加入? | | +| id | str | ? | 字符串表示的数字 | +| num | str | 数量 | | +| storm_gif | str | GIF 动画 URL | | +| time | str | 持续时间? | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "SPECIAL_GIFT", + "data": { + "39": { + "action": "start", + "content": "可爱即正义~~", + "hadJoin": 0, + "id": "3306976431489", + "num": 1, + "storm_gif": "http://static.hdslb.com/live-static/live-room/images/gift-section/mobilegift/2/jiezou.gif?2017011901", + "time": 90 + } + } +} +``` + +</details> + +<!-- +#### 欢迎加入房间 + +#### 欢迎房管加入房间 +--> + +#### 通知消息 (NOTICE_MSG) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `NOTICE_MSG` | | +| id | num | 待调查 | | +| name | str | 通知名 | | +| full | obj | 完整显示信息? | | +| half | obj | 半部显示信息? | | | +| side | obj | 边缘显示信息? | | +| roomid | num | 目标直播间短号 | | +| real_roomid | num | 目标直播间真实ID | | +| msg_common | str | 显示的消息内容 | | +| msg_self | str | 消息内容本身 | 剔除额外文本 | +| link_url | str | 通知消息跳转的URL | | +| msg_type | num | 待调查 | | +| shield_uid | num | 待调查 | | +| business_id | str | 待调查 | | +| scatter | obj | 待调查 | | +| marquee_id | str | 待调查 | | +| notice_type | num | 待调查 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "NOTICE_MSG", + "id": 804, + "name": "人气榜第一名", + "full": { + "head_icon": "https://i0.hdslb.com/bfs/live/f74b09c7fb83123a0dd66c536b6d5b143d271b08.png", + "tail_icon": "https://i0.hdslb.com/bfs/live/822da481fdaba986d738db5d8fd469ffa95a8fa1.webp", + "head_icon_fa": "https://i0.hdslb.com/bfs/live/f74b09c7fb83123a0dd66c536b6d5b143d271b08.png", + "tail_icon_fa": "https://i0.hdslb.com/bfs/live/38cb2a9f1209b16c0f15162b0b553e3b28d9f16f.png", + "head_icon_fan": 1, + "tail_icon_fan": 4, + "background": "#FFE6BD", + "color": "#9D5412", + "highlight": "#FF6933", + "time": 20 + }, + "half": { + "head_icon": "https://i0.hdslb.com/bfs/live/f74b09c7fb83123a0dd66c536b6d5b143d271b08.png", + "tail_icon": "https://i0.hdslb.com/bfs/live/822da481fdaba986d738db5d8fd469ffa95a8fa1.webp", + "background": "#FFE6BD", + "color": "#9D5412", + "highlight": "#FF6933", + "time": 0 + }, + "side": { + "head_icon": "", + "background": "", + "color": "", + "highlight": "", + "border": "" + }, + "roomid": 23919301, + "real_roomid": 23919301, + "msg_common": "恭喜主播<%AG超玩会王者荣耀一诺%>荣获上小时人气榜第<%1%>名!点击传送查看精彩内容!", + "msg_self": "恭喜主播<%AG超玩会王者荣耀一诺%>荣获上小时人气榜第<%1%>名!", + "link_url": "https://live.bilibili.com/23919301?broadcast_type=0&is_room_feed=1&from=28003&extra_jump_from=28003", + "msg_type": 1, + "shield_uid": -1, + "business_id": "", + "scatter": { + "min": 0, + "max": 0 + }, + "marquee_id": "", + "notice_type": 0 +} +``` + +```json +{ + "cmd": "NOTICE_MSG", + "id": 814, + "name": "幻影飞船专用", + "full": { + "head_icon": "https://i0.hdslb.com/bfs/live/08978f1721200e11328d1f7d6231b21bcca20488.gif", + "tail_icon": "https://i0.hdslb.com/bfs/live/822da481fdaba986d738db5d8fd469ffa95a8fa1.webp", + "head_icon_fa": "https://i0.hdslb.com/bfs/live/08978f1721200e11328d1f7d6231b21bcca20488.gif", + "tail_icon_fa": "https://i0.hdslb.com/bfs/live/38cb2a9f1209b16c0f15162b0b553e3b28d9f16f.png", + "head_icon_fan": 1, + "tail_icon_fan": 4, + "background": "#F09153", + "color": "#FFFFFF", + "highlight": "#FFE600", + "time": 15 + }, + "half": { + "head_icon": "https://i0.hdslb.com/bfs/live/08978f1721200e11328d1f7d6231b21bcca20488.gif", + "tail_icon": "", + "background": "#F09153", + "color": "#FFFFFFFF", + "highlight": "#FFE600", + "time": 15 + }, + "side": { + "head_icon": "", + "background": "", + "color": "", + "highlight": "", + "border": "" + }, + "roomid": 25207004, + "real_roomid": 25207004, + "msg_common": "<%咖啡_ミシェル%>投喂<%夜月瓜瓜sukuyi%>1个幻影飞船,向着浩瀚星辰出发!", + "msg_self": "<%咖啡_ミシェル%>投喂<%夜月瓜瓜sukuyi%>1个幻影飞船,向着浩瀚星辰出发!", + "link_url": "https://live.bilibili.com/25207004?broadcast_type=0&is_room_feed=1&from=28003&extra_jump_from=28003&live_lottery_type=1", + "msg_type": 2, + "shield_uid": -1, + "business_id": "32356", + "scatter": { + "min": 0, + "max": 0 + }, + "marquee_id": "", + "notice_type": 0 +} +``` + +</details> + +#### 主播准备中 (PREPARING) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `PREPARING` | | +| round | num | 轮播状态:<br/>1正在轮播<br/>0未轮播 | 开启轮播时存在 | +| roomid | str | 直播间ID | 未知是真实ID还是短号 | 类型似乎从num改为str | +| msg\_id | str | 信息id? | | +| p\_is\_ack | bool | | 未知 | +| p\_msg\_type | num | `1` | 未知 | +| send\_time | num | 发送时间 | UNIX 毫秒时间戳 | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +有启用轮播: + +```json +{ + "cmd": "PREPARING", + "msg_id": "26964930181741056:1000:1000", + "p_is_ack": true, + "p_msg_type": 1, + "roomid": "1899237171", + "round": 1, + "send_time": 1739985402716 +} +``` + +未启用轮播: + +```json +{ + "cmd": "PREPARING", + "msg_id": "27040425357932032:1000:1000", + "p_is_ack": true, + "p_msg_type": 1, + "roomid": "1017", + "send_time": 1740129398337 +} +``` + +</details> + +#### 直播开始 (LIVE) + +注:请求了开始直播接口、开始向服务器推流时下发。 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `LIVE` | | +| live_key | str | 标记直播场次的key | 与开始直播接口获得的live_key相同 | +| voice_background | str | ? | | +| sub_session_key | str | ? | | +| live_platform | str | 开播平台? | 推测由开播接口决定 | +| live_model | num | ? | | +| live_time | num | 开播时间 | UNIX 秒级时间戳,只有请求了开始直播后立刻下发的那个数据包里存在 | +| roomid | num | 直播间号 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "LIVE", + "live_key": "234304209915761953", + "voice_background": "", + "sub_session_key": "234304209915761953sub_time:1651036923", + "live_platform": "pc", + "live_model": 0, + "live_time": 1651036923, + "roomid": 23614753 +} +``` + +</details> + +#### 主播信息更新 (ROOM_REAL_TIME_MESSAGE_UPDATE) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `ROOM_REAL_TIME_MESSAGE_UPDATE` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| roomid | num | 直播间ID | 未知是真实ID还是短号 | +| fans | num | 主播当前粉丝数 | | +| red_notice | num | 待调查 | | +| fans_club | num | 主播粉丝团人数 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "ROOM_REAL_TIME_MESSAGE_UPDATE", + "data": { + "roomid": 8618057, + "fans": 136, + "red_notice": -1, + "fans_club": 8 + } +} +``` + +</details> + +#### 播放链接刷新 (PLAYURL_RELOAD) + +注: 该cmd通常不提供播放链接。 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| cmd | str | `PLAYURL_RELOAD` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| reload_option | obj | 刷新选项? | | +| playurl | obj | 播放链接信息 | | + +`data.reload_option` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| reload_stream_name | arr | 空数组? | | +| reload_format | arr | 空数组? | | +| scatter | num | | | + +`data.playurl` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| cid | num | 直播间真实id | | +| g_qn_desc | arr | 画质描述 | | +| stream | arr | 直播流信息 | | +| p2p_data | obj | P2P信息 | | +| dolby_qn | null | dolby画质信息? | | + +`data.playurl.g_qn_desc` 数组: + +| 索引 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| 0 | obj | 首个画质信息 | | +| … | obj | 多个画质信息 | | +| i | obj | 最后画质信息 | | + +`data.playurl.g_qn_desc` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| qn | num | 画质代码 | | +| desc | str | 画质描述 | | +| hdr_desc | str | | | +| attr_desc | null | | | +| hdr_type | num | | | +| media_base_desc | null 或 obj | 媒体描述 | + +`data.playurl.g_qn_desc[i].media_base_desc` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| detail_desc | obj | 详细? | | +| brief_desc | obj | 简洁? | | + +`data.playurl.g_qn_desc[i].media_base_desc.detail_desc` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| desc | str | 画质描述 | | +| tag | arr | 画质标签 | 字符串数组,部分画质存在 | + +`data.playurl.g_qn_desc[i].media_base_desc.brief_desc` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| desc | str | 画质描述 | | +| badge | str | 画质描述 | 部分画质存在 | + +`data.stream` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| protocol_name | str | 协议名称 | | +| format | arr | 封装格式列表 | | + +`data.stream[i].format` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| format_name | str | 视频封装格式名称 | | +| codec | arr | 编码列表 | | +| master_url | str | | | + +`data.stream[i].format[i].codec` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| codec_name | str | 视频编码名称 | | +| current_qn | num | 当前画质代码? | | +| accept_qn | arr | 允许的画质代码? | 数字数组 | +| base_url | str | | | +| url_info | arr | | | +| hdr_qn | null | | | +| dolby_type | num | | | +| attr_name | str | | | +| hdr_type | num | | | +| drm | bool | | | +| drm_key_systems | null | | | +| video_codecs | obj | 视频编码信息 | 不一定存在 | +| audio_codecs | obj | 音频编码信息 | 不一定存在 | + +`data.stream[i].format[i].codec[i].video_codecs` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| base | str | 编码格式 | | + +`data.stream[i].format[i].codec[i].audio_codecs` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| base | str | 编码格式 | | + +`data.playurl.p2p_data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| p2p | bool | | | +| p2p_type | num | | | +| m_p2p | bool | | | +| m_servers | null | | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "PLAYURL_RELOAD", + "data": { + "reload_option": { + "reload_stream_name": [], + "reload_format": [], + "scatter": 3000 + }, + "playurl": { + "cid": 41682, + "g_qn_desc": [ + { + "qn": 30000, + "desc": "杜比", + "hdr_desc": "", + "attr_desc": null, + "hdr_type": 0, + "media_base_desc": null + }, + { + "qn": 20000, + "desc": "4K", + "hdr_desc": "", + "attr_desc": null, + "hdr_type": 0, + "media_base_desc": null + }, + { + "qn": 10000, + "desc": "原画", + "hdr_desc": "", + "attr_desc": null, + "hdr_type": 0, + "media_base_desc": { + "detail_desc": { + "desc": "1080P 原画", + "tag": [ + "高帧率" + ] + }, + "brief_desc": { + "desc": "1080P", + "badge": "原画" + } + } + }, + { + "qn": 400, + "desc": "蓝光", + "hdr_desc": "", + "attr_desc": null, + "hdr_type": 0, + "media_base_desc": null + }, + { + "qn": 250, + "desc": "超清", + "hdr_desc": "", + "attr_desc": null, + "hdr_type": 0, + "media_base_desc": { + "detail_desc": { + "desc": "720P 超清" + }, + "brief_desc": { + "desc": "720P" + } + } + }, + { + "qn": 150, + "desc": "高清", + "hdr_desc": "", + "attr_desc": null, + "hdr_type": 0, + "media_base_desc": null + }, + { + "qn": 80, + "desc": "流畅", + "hdr_desc": "", + "attr_desc": null, + "hdr_type": 0, + "media_base_desc": null + } + ], + "stream": [ + { + "protocol_name": "http_stream", + "format": [ + { + "format_name": "flv", + "codec": [ + { + "codec_name": "avc", + "current_qn": 10000, + "accept_qn": [ + 10000 + ], + "base_url": "", + "url_info": [], + "hdr_qn": null, + "dolby_type": 0, + "attr_name": "", + "hdr_type": 0, + "drm": false, + "drm_key_systems": null, + "video_codecs": { + "base": "avc1.64002a" + }, + "audio_codecs": { + "base": "mp4a.40.2" + } + }, + { + "codec_name": "hevc", + "current_qn": 250, + "accept_qn": [ + 250 + ], + "base_url": "", + "url_info": [], + "hdr_qn": null, + "dolby_type": 0, + "attr_name": "", + "hdr_type": 0, + "drm": false, + "drm_key_systems": null, + "video_codecs": { + "base": "hvc1.1.6.L120" + }, + "audio_codecs": { + "base": "mp4a.40.2" + } + } + ], + "master_url": "" + } + ] + }, + { + "protocol_name": "http_hls", + "format": [ + { + "format_name": "ts", + "codec": [ + { + "codec_name": "avc", + "current_qn": 10000, + "accept_qn": [ + 10000 + ], + "base_url": "", + "url_info": [], + "hdr_qn": null, + "dolby_type": 0, + "attr_name": "", + "hdr_type": 0, + "drm": false, + "drm_key_systems": null, + "video_codecs": { + "base": "avc1.64002a" + }, + "audio_codecs": { + "base": "mp4a.40.2" + } + }, + { + "codec_name": "hevc", + "current_qn": 250, + "accept_qn": [ + 250 + ], + "base_url": "", + "url_info": [], + "hdr_qn": null, + "dolby_type": 0, + "attr_name": "", + "hdr_type": 0, + "drm": false, + "drm_key_systems": null, + "video_codecs": { + "base": "hvc1.1.6.L120" + }, + "audio_codecs": { + "base": "mp4a.40.2" + } + } + ], + "master_url": "" + }, + { + "format_name": "fmp4", + "codec": [ + { + "codec_name": "avc", + "current_qn": 10000, + "accept_qn": [ + 10000 + ], + "base_url": "", + "url_info": [], + "hdr_qn": null, + "dolby_type": 0, + "attr_name": "", + "hdr_type": 0, + "drm": false, + "drm_key_systems": null, + "video_codecs": { + "base": "avc1.64002a" + }, + "audio_codecs": { + "base": "mp4a.40.2" + } + }, + { + "codec_name": "hevc", + "current_qn": 250, + "accept_qn": [ + 250 + ], + "base_url": "", + "url_info": [], + "hdr_qn": null, + "dolby_type": 0, + "attr_name": "", + "hdr_type": 0, + "drm": false, + "drm_key_systems": null, + "video_codecs": { + "base": "hvc1.1.6.L120" + }, + "audio_codecs": { + "base": "mp4a.40.2" + } + } + ], + "master_url": "" + } + ] + } + ], + "p2p_data": { + "p2p": false, + "p2p_type": 0, + "m_p2p": false, + "m_servers": null + }, + "dolby_qn": null + } + } +} +``` + +</details> + +#### 直播间高能榜 (ONLINE_RANK_V2) + +注: 直播间高能用户数据刷新 + +在线榜已被 `ONLINE_RANK_V3` 替换 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `ONLINE_RANK_V2` | | +| data | obj | 直播间高能用户数据 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| list | array | 在直播间高能用户中的用户信息 | | +| rank_type | str | 榜单类型 | | + +`data.list[n]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| uid | num | 用户 mid | | +| face | str | 用户头像 URL | | +| score | str | 该用户的贡献值 | | +| uname | str | 用户名称 | | +| rank | num | 该用户在高能榜中的排名 | | +| guard_level | num | 大航海等级? | | +| is_mystery | bool | | | +| uinfo | obj | 用户信息 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "ONLINE_RANK_V2", + "data": { + "list": [ + { + "uid": 2082621455, + "face": "https://i2.hdslb.com/bfs/face/9de6050277fa13d830eb97e3453d89843de46a31.jpg", + "score": "20", + "uname": "8级萌新_小华", + "rank": 1, + "guard_level": 0 + }, + { + "uid": 50500335, + "face": "https://i0.hdslb.com/bfs/face/ca722209251478ef0ffb45c3adeafb9dab283c57.jpg", + "score": "20", + "uname": "属官一号", + "rank": 2, + "guard_level": 0 + }, + { + "uid": 29857468, + "face": "https://i1.hdslb.com/bfs/face/7b4ae2e7e950f2dfb2bd969859c813487ce3b64c.jpg", + "score": "12", + "uname": "露萌不要雨草", + "rank": 3, + "guard_level": 0 + } + ], + "rank_type": "gold-rank" + } +} +``` + +</details> + +#### 直播间高能榜V3 (ONLINE_RANK_V3) + +注: 直播间高能用户数据刷新 + +替换 `ONLINE_RANK_V2` + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| cmd | str | `ONLINE_RANK_V3` | | +| data | obj | 数据本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| pb | str | 使用 base64 编码 protobuf 后的数据 | 解析后数据基本与`ONLINE_RANK_V2`的`data`相同 | + +用于解析protobuf数据的proto文件: [#1332(comment)](https://github.com/SocialSisterYi/bilibili-API-collect/issues/1332#issuecomment-3055621742) + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "ONLINE_RANK_V3", + "data": { + "pb": "CgtvbmxpbmVfcmFuaxqqAwi8jscKEkpodHRwczovL2kyLmhkc2xiLmNvbS9iZnMvZmFjZS9iODM3MGMzMGM3ZDg5NDg4YjRjOWYyNWZmMTgyNjc4OTEyYTRiOTA3LmpwZxoCMTIiDOW4jOWwlOWonOWonCgBMAFCwAIIvI7HChKfAgoM5biM5bCU5aic5aicEkpodHRwczovL2kyLmhkc2xiLmNvbS9iZnMvZmFjZS9iODM3MGMzMGM3ZDg5NDg4YjRjOWYyNWZmMTgyNjc4OTEyYTRiOTA3LmpwZypaCgzluIzlsJTlqJzlqJwSSmh0dHBzOi8vaTIuaGRzbGIuY29tL2Jmcy9mYWNlL2I4MzcwYzMwYzdkODk0ODhiNGM5ZjI1ZmYxODI2Nzg5MTJhNGI5MDcuanBnMloKDOW4jOWwlOWonOWonBJKaHR0cHM6Ly9pMi5oZHNsYi5jb20vYmZzL2ZhY2UvYjgzNzBjMzBjN2Q4OTQ4OGI0YzlmMjVmZjE4MjY3ODkxMmE0YjkwNy5qcGc6CyD///////////8BMhcIARITMjAyNS0wNy0yOSAyMzo1OTo1ORrNAwjnyMIDEkpodHRwczovL2kxLmhkc2xiLmNvbS9iZnMvZmFjZS9mZWNhYTQ3ZTQ2ODljOWVmYTg0MzBiNmViNzRmNTM2ZTMxN2ZmODYwLmpwZxoBOCIV5byl6IC26IC26IC26IC26IC26IC2KAIwAkLbAgjnyMIDEroCChXlvKXogLbogLbogLbogLbogLbogLYSSmh0dHBzOi8vaTEuaGRzbGIuY29tL2Jmcy9mYWNlL2ZlY2FhNDdlNDY4OWM5ZWZhODQzMGI2ZWI3NGY1MzZlMzE3ZmY4NjAuanBnKmMKFeW8peiAtuiAtuiAtuiAtuiAtuiAthJKaHR0cHM6Ly9pMS5oZHNsYi5jb20vYmZzL2ZhY2UvZmVjYWE0N2U0Njg5YzllZmE4NDMwYjZlYjc0ZjUzNmUzMTdmZjg2MC5qcGcyYwoV5byl6IC26IC26IC26IC26IC26IC2EkpodHRwczovL2kxLmhkc2xiLmNvbS9iZnMvZmFjZS9mZWNhYTQ3ZTQ2ODljOWVmYTg0MzBiNmViNzRmNTM2ZTMxN2ZmODYwLmpwZzoLIP///////////wEyFwgCEhMyMDI1LTA4LTAzIDIzOjU5OjU5GvUDCMTF4wQSS2h0dHBzOi8vaTEuaGRzbGIuY29tL2Jmcy9mYWNlLzcxMmMzNjExMzg1ZTJlMGRjYmU4MDc2YmRkM2ViNmYwZWNjNmZkYWYud2VicBoBNiIe5oKg5ZOJ55qE6buR5ZCs5aSn546L5aSq5Zuw6L69KAMwA0L5AgjExeMEEtgCCh7mgqDlk4nnmoTpu5HlkKzlpKfnjovlpKrlm7Dovr0SS2h0dHBzOi8vaTEuaGRzbGIuY29tL2Jmcy9mYWNlLzcxMmMzNjExMzg1ZTJlMGRjYmU4MDc2YmRkM2ViNmYwZWNjNmZkYWYud2VicCptCh7mgqDlk4nnmoTpu5HlkKzlpKfnjovlpKrlm7Dovr0SS2h0dHBzOi8vaTEuaGRzbGIuY29tL2Jmcy9mYWNlLzcxMmMzNjExMzg1ZTJlMGRjYmU4MDc2YmRkM2ViNmYwZWNjNmZkYWYud2VicDJtCh7mgqDlk4nnmoTpu5HlkKzlpKfnjovlpKrlm7Dovr0SS2h0dHBzOi8vaTEuaGRzbGIuY29tL2Jmcy9mYWNlLzcxMmMzNjExMzg1ZTJlMGRjYmU4MDc2YmRkM2ViNmYwZWNjNmZkYWYud2VicDoLIP///////////wEyFwgDEhMyMDI1LTA3LTI2IDIzOjU5OjU5GtkDCLzSxwkSSmh0dHBzOi8vaTEuaGRzbGIuY29tL2Jmcy9mYWNlLzAyMGYxOWEwNTNjZDBkNGZjNGMyYmQzOTlmYWNjMTk3YWJiZWY5N2EuanBnGgE2IhjmuLjmiYvlpb3pl7LnmoTmtYXogIHluIgoBDADQuQCCLzSxwkSwwIKGOa4uOaJi+WlvemXsueahOa1heiAgeW4iBJKaHR0cHM6Ly9pMS5oZHNsYi5jb20vYmZzL2ZhY2UvMDIwZjE5YTA1M2NkMGQ0ZmM0YzJiZDM5OWZhY2MxOTdhYmJlZjk3YS5qcGcqZgoY5ri45omL5aW96Zey55qE5rWF6ICB5biIEkpodHRwczovL2kxLmhkc2xiLmNvbS9iZnMvZmFjZS8wMjBmMTlhMDUzY2QwZDRmYzRjMmJkMzk5ZmFjYzE5N2FiYmVmOTdhLmpwZzJmChjmuLjmiYvlpb3pl7LnmoTmtYXogIHluIgSSmh0dHBzOi8vaTEuaGRzbGIuY29tL2Jmcy9mYWNlLzAyMGYxOWEwNTNjZDBkNGZjNGMyYmQzOTlmYWNjMTk3YWJiZWY5N2EuanBnOgsg////////////ATIXCAMSEzIwMjUtMDgtMDQgMjM6NTk6NTkakAMIp9P+CRJKaHR0cHM6Ly9pMS5oZHNsYi5jb20vYmZzL2ZhY2UvZTJkYmM4ZTQ5NzA3NzFiNjlhNWEyYzYzMDI0YTg5NzhjMjc3YWNmMi5qcGcaATYiDOmaj+WFieaykOW9sSgFQqkCCKfT/gkSnwIKDOmaj+WFieaykOW9sRJKaHR0cHM6Ly9pMS5oZHNsYi5jb20vYmZzL2ZhY2UvZTJkYmM4ZTQ5NzA3NzFiNjlhNWEyYzYzMDI0YTg5NzhjMjc3YWNmMi5qcGcqWgoM6ZqP5YWJ5rKQ5b2xEkpodHRwczovL2kxLmhkc2xiLmNvbS9iZnMvZmFjZS9lMmRiYzhlNDk3MDc3MWI2OWE1YTJjNjMwMjRhODk3OGMyNzdhY2YyLmpwZzJaCgzpmo/lhYnmspDlvbESSmh0dHBzOi8vaTEuaGRzbGIuY29tL2Jmcy9mYWNlL2UyZGJjOGU0OTcwNzcxYjY5YTVhMmM2MzAyNGE4OTc4YzI3N2FjZjIuanBnOgsg////////////ATIAGrYDCPWvn4sBEkpodHRwczovL2kxLmhkc2xiLmNvbS9iZnMvZmFjZS80ZTNkYTdmYWJiOWZlMTkyNzRhYmQ0ZTdlYWMyNmQ3MjI4OGQyNmEwLmpwZxoBNiIV5pKS5qyi5YS/55qE5rCU5rOh5YS/KAZCxQII9a+fiwESugIKFeaSkuasouWEv+eahOawlOazoeWEvxJKaHR0cHM6Ly9pMS5oZHNsYi5jb20vYmZzL2ZhY2UvNGUzZGE3ZmFiYjlmZTE5Mjc0YWJkNGU3ZWFjMjZkNzIyODhkMjZhMC5qcGcqYwoV5pKS5qyi5YS/55qE5rCU5rOh5YS/EkpodHRwczovL2kxLmhkc2xiLmNvbS9iZnMvZmFjZS80ZTNkYTdmYWJiOWZlMTkyNzRhYmQ0ZTdlYWMyNmQ3MjI4OGQyNmEwLmpwZzJjChXmkpLmrKLlhL/nmoTmsJTms6HlhL8SSmh0dHBzOi8vaTEuaGRzbGIuY29tL2Jmcy9mYWNlLzRlM2RhN2ZhYmI5ZmUxOTI3NGFiZDRlN2VhYzI2ZDcyMjg4ZDI2YTAuanBnOgsg////////////ATIAGusDCPTXwbEBEkpodHRwczovL2kxLmhkc2xiLmNvbS9iZnMvZmFjZS8yN2RiOGQ5MTY3ZDRhMmUyMDg0NjUzNDJkOGVmZjQzZWUzMGJiOGNlLmpwZxoBNiIc57OW5b+D6JuL6JuLLeWNg+WNg+azoue6r+WGoCgHMANC8QII9NfBsQESzwIKHOezluW/g+ibi+ibiy3ljYPljYPms6Lnuq/lhqASSmh0dHBzOi8vaTEuaGRzbGIuY29tL2Jmcy9mYWNlLzI3ZGI4ZDkxNjdkNGEyZTIwODQ2NTM0MmQ4ZWZmNDNlZTMwYmI4Y2UuanBnKmoKHOezluW/g+ibi+ibiy3ljYPljYPms6Lnuq/lhqASSmh0dHBzOi8vaTEuaGRzbGIuY29tL2Jmcy9mYWNlLzI3ZGI4ZDkxNjdkNGEyZTIwODQ2NTM0MmQ4ZWZmNDNlZTMwYmI4Y2UuanBnMmoKHOezluW/g+ibi+ibiy3ljYPljYPms6Lnuq/lhqASSmh0dHBzOi8vaTEuaGRzbGIuY29tL2Jmcy9mYWNlLzI3ZGI4ZDkxNjdkNGEyZTIwODQ2NTM0MmQ4ZWZmNDNlZTMwYmI4Y2UuanBnOgsg////////////ATIXCAMSEzIwMjUtMDctMjUgMjM6NTk6NTk=" + } +} +``` + +</details> + +#### 直播间高能用户数量 (ONLINE_RANK_COUNT) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `ONLINE_RANK_COUNT` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| count | num | 直播间高能用户数量 | 存在上限 | +| count_text | str | 直播间高能用户数量文本 | | +| online_count | num | 直播间在线用户数量 | 存在上限 | +| online_count_text | str | 直播间在线用户数量文本 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "ONLINE_RANK_COUNT", + "data": { + "count": 1084, + "count_text": "1084", + "online_count": 1084, + "online_count_text": "1084" + } +} +``` + +</details> + +#### 未登录通知 (LOG_IN_NOTICE) + +注:未使用认证信息进行登录将会下发此数据包,通常于认证包回复后下发,在后续时间里也有可能会下发;部分受到豁免的直播间不会下发。 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `LOG_IN_NOTICE` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| notice\_msg | str | 通知内容 | | +| image\_web | str | 在网页端使用的通知图片 | | +| image\_app | str | 在app端使用的图片 | (未确认) | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "LOG_IN_NOTICE", + "data": { + "notice_msg": "为保护用户隐私,未登录无法查看他人昵称", + "image_web": "http://i0.hdslb.com/bfs/dm/75e7c16b99208df259fe0a93354fd3440cbab412.png", + "image_app": "http://i0.hdslb.com/bfs/dm/b632f7dcd3acf47deffb5f9ccc9546ae97a3415b.png" + } +} +``` + +</details> + +#### 用户到达直播间高能榜前三名的消息 (ONLINE_RANK_TOP3) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `ONLINE_RANK_TOP3` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| dmscore | num | 待调查 | | +| list | array | 消息内容和高能榜排名 | | + +`data.list[n]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| msg | str | 消息内容 | | +| rank | num | 该用户的高能榜排名 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "ONLINE_RANK_TOP3", + "data": { + "dmscore": 112, + "list": [ + { + "msg": "恭喜 <%你干嘛哈哈哎哟%> 成为高能用户", + "rank": 1 + } + ] + } +} +``` + +</details> + +#### 直播间在人气榜的排名改变 (POPULAR_RANK_CHANGED) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `POPULAR_RANK_CHANGED` | | +| data | obj | 直播间的人气榜排名信息 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| uid | num | 主播 mid | | +| rank | num | 人气榜排名 | | +| countdown | num | 人气榜下轮结算剩余时长 | | +| timestamp | num | 触发时的Unix时间戳 | | +| cache_key | str | 待调查 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "POPULAR_RANK_CHANGED", + "data": { + "uid": 780791, + "rank": 36, + "countdown": 1927, + "timestamp": 1702578474, + "cache_key": "rank_change:91a4e81ba3034ae894d61e432aa13081" + } +} +``` + +</details> + +#### 直播间限时热门榜排名改变 (HOT_RANK_CHANGED) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `HOT_RANK_CHANGED` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| rank | num | 排名 | | +| trend | num | 趋势? | | +| countdown | num | 剩余时间? | | +| timestamp | num | 当前时间? | UNIX 秒级时间戳 | +| web_url | str | 排行榜 URL | | +| live_url | str | 排行榜 URL | | +| blink_url | str | 排行榜 URL | | +| live_link_url | str | 排行榜 URL | | +| pc_link_url | str | 排行榜 URL | | +| icon | str | 图标 URL | | +| area_name | str | 分区名称 | | +| rank_desc | str | 空? | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "HOT_RANK_CHANGED", + "data": { + "rank": 31, + "trend": 1, + "countdown": 1440, + "timestamp": 1651037760, + "web_url": "https://live.bilibili.com/p/html/live-app-hotrank/index.html?clientType=2&area_id=9&parent_area_id=9&second_area_id=0", + "live_url": "https://live.bilibili.com/p/html/live-app-hotrank/index.html?clientType=1&area_id=9&parent_area_id=9&second_area_id=0&is_live_half_webview=1&hybrid_rotate_d=1&hybrid_half_ui=1,3,100p,70p,f4eefa,0,30,100,12,0;2,2,375,100p,f4eefa,0,30,100,0,0;3,3,100p,70p,f4eefa,0,30,100,12,0;4,2,375,100p,f4eefa,0,30,100,0,0;5,3,100p,70p,f4eefa,0,30,100,0,0;6,3,100p,70p,f4eefa,0,30,100,0,0;7,3,100p,70p,f4eefa,0,30,100,0,0;8,3,100p,70p,f4eefa,0,30,100,0,0", + "blink_url": "https://live.bilibili.com/p/html/live-app-hotrank/index.html?clientType=3&area_id=9&parent_area_id=9&second_area_id=0&is_live_half_webview=1&hybrid_rotate_d=1&is_cling_player=1&hybrid_half_ui=1,3,100p,70p,f4eefa,0,30,100,0,0;2,2,375,100p,f4eefa,0,30,100,0,0;3,3,100p,70p,f4eefa,0,30,100,0,0;4,2,375,100p,f4eefa,0,30,100,0,0;5,3,100p,70p,f4eefa,0,30,100,0,0;6,3,100p,70p,f4eefa,0,30,100,0,0;7,3,100p,70p,f4eefa,0,30,100,0,0;8,3,100p,70p,f4eefa,0,30,100,0,0", + "live_link_url": "https://live.bilibili.com/p/html/live-app-hotrank/index.html?clientType=5&area_id=9&parent_area_id=9&second_area_id=0&is_live_half_webview=1&hybrid_rotate_d=1&is_cling_player=1&hybrid_half_ui=1,3,100p,70p,f4eefa,0,30,100,0,0;2,2,375,100p,f4eefa,0,30,100,0,0;3,3,100p,70p,f4eefa,0,30,100,0,0;4,2,375,100p,f4eefa,0,30,100,0,0;5,3,100p,70p,f4eefa,0,30,100,0,0;6,3,100p,70p,f4eefa,0,30,100,0,0;7,3,100p,70p,f4eefa,0,30,100,0,0;8,3,100p,70p,f4eefa,0,30,100,0,0", + "pc_link_url": "https://live.bilibili.com/p/html/live-app-hotrank/index.html?clientType=4&is_live_half_webview=1&area_id=9&parent_area_id=9&second_area_id=0&pc_ui=338,465,f4eefa,0", + "icon": "https://i0.hdslb.com/bfs/live/63217712edb588864b2c714225992e7f46b0b917.png", + "area_name": "虚拟", + "rank_desc": "" + } +} +``` + +</details> + +#### 当前直播间限时热门榜排名改变V2 (HOT_RANK_CHANGED_V2) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `HOT_RANK_CHANGED_V2` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| rank | num | 排名 | | +| trend | num | 趋势? | | +| countdown | num | 剩余时间? | | +| timestamp | num | 当前时间? | UNIX 秒级时间戳 | +| web_url | str | 排行榜 URL | | +| live_url | str | 排行榜 URL | | +| blink_url | str | 排行榜 URL | | +| live_link_url | str | 排行榜 URL | | +| pc_link_url | str | 排行榜 URL | | +| icon | str | 图标 URL | | +| area_name | str | 分区名称 | | +| rank_desc | str | 排行榜说明 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "HOT_RANK_CHANGED_V2", + "data": { + "rank": 31, + "trend": 0, + "countdown": 1440, + "timestamp": 1651037760, + "web_url": "https://live.bilibili.com/p/html/live-app-hotrank/index.html?clientType=2&area_id=9&parent_area_id=9&second_area_id=371", + "live_url": "https://live.bilibili.com/p/html/live-app-hotrank/index.html?clientType=1&area_id=9&parent_area_id=9&second_area_id=371&is_live_half_webview=1&hybrid_rotate_d=1&hybrid_half_ui=1,3,100p,70p,f4eefa,0,30,100,12,0;2,2,375,100p,f4eefa,0,30,100,0,0;3,3,100p,70p,f4eefa,0,30,100,12,0;4,2,375,100p,f4eefa,0,30,100,0,0;5,3,100p,70p,f4eefa,0,30,100,0,0;6,3,100p,70p,f4eefa,0,30,100,0,0;7,3,100p,70p,f4eefa,0,30,100,0,0;8,3,100p,70p,f4eefa,0,30,100,0,0", + "blink_url": "https://live.bilibili.com/p/html/live-app-hotrank/index.html?clientType=3&area_id=9&parent_area_id=9&second_area_id=371&is_live_half_webview=1&hybrid_rotate_d=1&is_cling_player=1&hybrid_half_ui=1,3,100p,70p,f4eefa,0,30,100,0,0;2,2,375,100p,f4eefa,0,30,100,0,0;3,3,100p,70p,f4eefa,0,30,100,0,0;4,2,375,100p,f4eefa,0,30,100,0,0;5,3,100p,70p,f4eefa,0,30,100,0,0;6,3,100p,70p,f4eefa,0,30,100,0,0;7,3,100p,70p,f4eefa,0,30,100,0,0;8,3,100p,70p,f4eefa,0,30,100,0,0", + "live_link_url": "https://live.bilibili.com/p/html/live-app-hotrank/index.html?clientType=5&area_id=9&parent_area_id=9&second_area_id=371&is_live_half_webview=1&hybrid_rotate_d=1&is_cling_player=1&hybrid_half_ui=1,3,100p,70p,f4eefa,0,30,100,0,0;2,2,375,100p,f4eefa,0,30,100,0,0;3,3,100p,70p,f4eefa,0,30,100,0,0;4,2,375,100p,f4eefa,0,30,100,0,0;5,3,100p,70p,f4eefa,0,30,100,0,0;6,3,100p,70p,f4eefa,0,30,100,0,0;7,3,100p,70p,f4eefa,0,30,100,0,0;8,3,100p,70p,f4eefa,0,30,100,0,0", + "pc_link_url": "https://live.bilibili.com/p/html/live-app-hotrank/index.html?clientType=4&is_live_half_webview=1&area_id=9&parent_area_id=9&second_area_id=371&pc_ui=338,465,f4eefa,0", + "icon": "https://i0.hdslb.com/bfs/live/cb2e160ac4f562b347bb5ae6e635688ebc69580f.png", + "area_name": "虚拟主播", + "rank_desc": "虚拟主播top50" + } +} +``` + +</details> + +#### 限时热门榜上榜信息 (HOT_RANK_SETTLEMENT) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `HOT_RANK_SETTLEMENT` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| area_name | str | 分区名称 | | +| cache_key | str | ? | | +| dm_msg | str | 弹幕提示信息 | | +| dmscore | num | ? | | +| face | str | 主播头像 URL | | +| icon | str | 图标 URL | | +| rank | num | 排名 | | +| timestamp | num | 时间 | UNIX 秒级时间戳 | +| uname | str | 主播用户名 | | +| url | str | 排行榜 URL | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "HOT_RANK_SETTLEMENT", + "data": { + "area_name": "虚拟主播", + "cache_key": "2f8baf923a6b7df5a045df6c7181984c", + "dm_msg": "恭喜主播 <% 白黑卡扣 %> 荣登限时热门榜虚拟主播榜top9! 即将获得热门流量推荐哦!", + "dmscore": 144, + "face": "http://i0.hdslb.com/bfs/face/ddfcd696213e07884ce227c6ba6d23a007a08c02.jpg", + "icon": "https://i0.hdslb.com/bfs/live/63217712edb588864b2c714225992e7f46b0b917.png", + "rank": 9, + "timestamp": 1651041000, + "uname": "白黑卡扣", + "url": "https://live.bilibili.com/p/html/live-app-hotrank/result.html?is_live_half_webview=1&hybrid_half_ui=1,5,250,200,f4eefa,0,30,0,0,0;2,5,250,200,f4eefa,0,30,0,0,0;3,5,250,200,f4eefa,0,30,0,0,0;4,5,250,200,f4eefa,0,30,0,0,0;5,5,250,200,f4eefa,0,30,0,0,0;6,5,250,200,f4eefa,0,30,0,0,0;7,5,250,200,f4eefa,0,30,0,0,0;8,5,250,200,f4eefa,0,30,0,0,0&areaId=9&cache_key=2f8baf923a6b7df5a045df6c7181984c" + } +} +``` + +</details> + +#### 限时热门榜上榜信息V2 (HOT_RANK_SETTLEMENT_V2) + +**JSON消息:** + +基本同 [限时热门榜上榜信息](#限时热门榜上榜信息-hot_rank_settlement), 但没有 `data.dmscore` 字段 + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "HOT_RANK_SETTLEMENT_V2", + "data": { + "rank": 9, + "uname": "白黑卡扣", + "face": "http://i0.hdslb.com/bfs/face/ddfcd696213e07884ce227c6ba6d23a007a08c02.jpg", + "timestamp": 1651040700, + "icon": "https://i0.hdslb.com/bfs/live/cb2e160ac4f562b347bb5ae6e635688ebc69580f.png", + "area_name": "虚拟主播", + "url": "https://live.bilibili.com/p/html/live-app-hotrank/result.html?is_live_half_webview=1&hybrid_half_ui=1,5,250,200,f4eefa,0,30,0,0,0;2,5,250,200,f4eefa,0,30,0,0,0;3,5,250,200,f4eefa,0,30,0,0,0;4,5,250,200,f4eefa,0,30,0,0,0;5,5,250,200,f4eefa,0,30,0,0,0;6,5,250,200,f4eefa,0,30,0,0,0;7,5,250,200,f4eefa,0,30,0,0,0;8,5,250,200,f4eefa,0,30,0,0,0&areaId=371&cache_key=693b7b029b66976a399cf4e3485d265a", + "cache_key": "693b7b029b66976a399cf4e3485d265a", + "dm_msg": "恭喜主播 <% 白黑卡扣 %> 荣登限时热门榜虚拟主播榜top9! 即将获得热门流量推荐哦!" + } +} +``` + +</details> + +#### 直播间用户点赞 (LIKE_INFO_V3_CLICK) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `LIKE_INFO_V3_CLICK` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| show_area | num | 待调查 | | +| msg_type | num | 待调查 | | +| like_icon | str | 点赞图标的URL | | +| uid | num | 点赞的用户的UID | | +| like_text | str | 点赞文本 | | +| uname | str | 点赞的用户的名称 | | +| uname_color | str | 点赞的用户的名称颜色 | | +| identities | array | 待调查 | | +| fans_medal | obj | 点赞的用户的粉丝勋章信息 | | +| contribution_info | obj | 待调查 | | +| dmscore | num | 待调查 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "LIKE_INFO_V3_CLICK", + "data": { + "show_area": 0, + "msg_type": 6, + "like_icon": "https://i0.hdslb.com/bfs/live/23678e3d90402bea6a65251b3e728044c21b1f0f.png", + "uid": 32174213, + "like_text": "为主播点赞了", + "uname": "MeiDngS", + "uname_color": "", + "identities": [ + 1 + ], + "fans_medal": { + "target_id": 0, + "medal_level": 0, + "medal_name": "", + "medal_color": 0, + "medal_color_start": 12632256, + "medal_color_end": 12632256, + "medal_color_border": 12632256, + "is_lighted": 0, + "guard_level": 0, + "special": "", + "icon_id": 0, + "anchor_roomid": 0, + "score": 0 + }, + "contribution_info": { + "grade": 0 + }, + "dmscore": 20 + } +} +``` + +</details> + +#### 直播间点赞数更新 (LIKE_INFO_V3_UPDATE) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `LIKE_INFO_V3_UPDATE` | | +| data | obj | 直播间点赞数 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| click_count | num | 直播间点赞数 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "LIKE_INFO_V3_UPDATE", + "data": { + "click_count": 3227 + } +} +``` + +</details> + +#### 直播间发红包弹幕 (POPULARITY_RED_POCKET_START) + +注: 开始抽取红包 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `POPULARITY_RED_POCKET_START` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | --- | ------ | --------- | +| lot_id | num | 发送的红包的ID | | +| sender_uid | num | 发送者的UID | | +| sender_name | str | 发送者的名称 | | +| sender_face | str | 发送者的头像的URL | | +| join_requirement | num | 待调查 | | +| danmu | str | 用户参与红包时自动发送的弹幕内容 | | +| current_time | num | 服务器发送数据包的Unix时间戳 | | +| start_time | num | 可以开始抢红包的Unix时间戳 | | +| end_time | num | 抢红包的结束时间Unix时间戳 | | +| last_time | num | 红包的持续时间(秒) | start_time - end_time | +| remove_time | num | 待调查 | | +| replace_time | num | 待调查 | | +| lot_status | num | 待调查 | | +| h5_url | str | 红包页面的URL | | +| user_status | num | 用户参与状态,但是不知道是哪个用户 | 1已参与<br />2未参与 | +| awards | array | 红包内包含的礼物的信息 | | +| lot_config_id | num | 待调查 | | +| total_price | num | 内含抽取奖品金瓜子总价值 | 目前红包的 20% 会直接交给主播, 所以 20 电池 (2 CNY) 对应 2000 金瓜子的 80% 是 1600 金瓜子 | +| wait_num | num | 待调查 | | + +`data.awards[n]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | --- | ------ | --------- | +| gift_id | num | 礼物ID | | +| gift_name | str | 礼物名称 | | +| gift_pic | str | 礼物图标URL | | +| num | num | 该礼物的数量 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "POPULARITY_RED_POCKET_START", + "data": { + "lot_id": 2062329, + "sender_uid": 181851309, + "sender_name": "毒瘤老肥仔", + "sender_face": "http://i0.hdslb.com/bfs/face/fed3871b01976ddd35fd3f772ffc2d4949f1391d.jpg", + "join_requirement": 1, + "danmu": "老板大气!点点红包抽礼物!", + "current_time": 1650425344, + "start_time": 1650425343, + "end_time": 1650425523, + "last_time": 180, + "remove_time": 1650425538, + "replace_time": 1650425533, + "lot_status": 1, + "h5_url": "https://live.bilibili.com/p/html/live-app-red-envelope/popularity.html?is_live_half_webview=1&hybrid_half_ui=1,5,100p,100p,000000,0,50,0,0,1;2,5,100p,100p,000000,0,50,0,0,1;3,5,100p,100p,000000,0,50,0,0,1;4,5,100p,100p,000000,0,50,0,0,1;5,5,100p,100p,000000,0,50,0,0,1;6,5,100p,100p,000000,0,50,0,0,1;7,5,100p,100p,000000,0,50,0,0,1;8,5,100p,100p,000000,0,50,0,0,1&hybrid_rotate_d=1&hybrid_biz=popularityRedPacket&lotteryId=2062329", + "user_status": 2, + "awards": [ + { + "gift_id": 31212, + "gift_name": "打call", + "gift_pic": "https://s1.hdslb.com/bfs/live/f75291a0e267425c41e1ce31b5ffd6bfedc6f0b6.png", + "num": 2 + }, + { + "gift_id": 31214, + "gift_name": "牛哇", + "gift_pic": "https://s1.hdslb.com/bfs/live/b8a38b4bd3be120becddfb92650786f00dffad48.png", + "num": 3 + }, + { + "gift_id": 31216, + "gift_name": "i了i了", + "gift_pic": "https://s1.hdslb.com/bfs/live/1157a445487b39c0b7368d91b22290c60fa665b2.png", + "num": 3 + } + ], + "lot_config_id": 3, + "total_price": 1600, + "wait_num": 0 + } +} +``` + +</details> + +#### 直播间红包 (POPULARITY_RED_POCKET_NEW) + +注: 与 [直播间发红包弹幕](#直播间发红包弹幕-popularity_red_pocket_start) 不同, 那个是发红包的弹幕信息, 这个则和 [送礼](#送礼-send_gift) 的信息相似, 但也有前者的一些字段 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------------------- | ---- | +| cmd | str | `POPULARITY_RED_POCKET_NEW` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ------------ | ---- | +| lot_id | num | 红包 ID | | +| start_time | num | 开抢时间 | UNIX 秒级时间戳 | +| current_time | num | 当前时间 | UNIX 秒级时间戳 | +| wait_num | num | 0? | | +| uname | str | 发送者用户名 | | +| uid | num | 发送者的 mid | | +| action | str | 礼物操作 | | +| num | num | 礼物数量 | | +| gift_name | str | `红包` | | +| gift_id | num | 礼物 ID? | | +| price | num | 电池标价 | | +| name_color | str | 用户名颜色 | | +| medal_info | obj | 发送者粉丝牌 | | + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "POPULARITY_RED_POCKET_NEW", + "data": { + "lot_id": 2062329, + "start_time": 1650425343, + "current_time": 1650425343, + "wait_num": 0, + "uname": "毒瘤老肥仔", + "uid": 181851309, + "action": "送出", + "num": 1, + "gift_name": "红包", + "gift_id": 13000, + "price": 20, + "name_color": "#00D1F1", + "medal_info": { + "target_id": 11909915, + "special": "", + "icon_id": 0, + "anchor_uname": "", + "anchor_roomid": 0, + "medal_level": 22, + "medal_name": "伊克拉", + "medal_color": 1725515, + "medal_color_start": 1725515, + "medal_color_end": 5414290, + "medal_color_border": 6809855, + "is_lighted": 1, + "guard_level": 3 + } + } +} +``` + +</details> + +#### 直播间抢到红包的用户 (POPULARITY_RED_POCKET_WINNER_LIST) + +注: 红包中奖列表 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------------------------------- | ---- | +| cmd | str | `POPULARITY_RED_POCKET_WINNER_LIST` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----- | -------- | ---- | +| lot_id | num | 红包 ID | | +| total_num | num | 礼物总数 | | +| winner_info | array | 中奖信息 | | +| awards | obj | 礼物信息 | | +| version | num | | | + +`data.winner_info` 数组: + +| 项 | 类型 | 内容 | 备注 | +| -- | ----- | ------------ | ---- | +| 0 | array | 中奖者 1 | | +| …… | array | …… | | +| n | array | 中奖者 (n+1) | | + +`data.winner_info[n]` 数组: + +| 项 | 类型 | 内容 | 备注 | +| -- | ---- | ---------------------- | ---- | +| 0 | num | 该抢到红包的用户的 mid | | +| 1 | str | 该抢到红包的用户的名称 | | +| 2 | num | bag_id? | | +| 3 | num | 该用户抢到的礼物的 ID | | + +`data.awards` 对象: + +以 礼物 ID 为键, JSON Object 为值的表 + +`data.awards['?']` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ------------ | ---- | +| award_type | num | 奖品类型? | | +| award_name | str | 礼物名称 | | +| award_pic | str | 礼物图标 URL | | +| award_big_pic | str | 礼物大图 URL | | +| award_price | num | 礼物价值 | | + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "POPULARITY_RED_POCKET_WINNER_LIST", + "data": { + "lot_id": 8445764, + "total_num": 8, + "winner_info": [ + [ + 38554435, + "我的0019", + 4581509, + 31212 + ], + [ + 516174930, + "云来海遛鸟大爷", + 4606389, + 31212 + ] + ], + "awards": { + "31212": { + "award_type": 1, + "award_name": "打call", + "award_pic": "https://s1.hdslb.com/bfs/live/461be640f60788c1d159ec8d6c5d5cf1ef3d1830.png", + "award_big_pic": "https://i0.hdslb.com/bfs/live/9e6521c57f24c7149c054d265818d4b82059f2ef.png", + "award_price": 500 + }, + "31214": { + "award_type": 1, + "award_name": "牛哇", + "award_pic": "https://s1.hdslb.com/bfs/live/91ac8e35dd93a7196325f1e2052356e71d135afb.png", + "award_big_pic": "https://i0.hdslb.com/bfs/live/3b74c117b4f265edcea261bc5608a58d3a7c300a.png", + "award_price": 100 + }, + "31216": { + "award_type": 1, + "award_name": "i了i了", + "award_pic": "https://s1.hdslb.com/bfs/live/1157a445487b39c0b7368d91b22290c60fa665b2.png", + "award_big_pic": "https://i0.hdslb.com/bfs/live/cfb9c3d9bdd2c25c95b7d859ebaa590ca9362adb.png", + "award_price": 100 + } + }, + "version": 1 + } +} +``` + +</details> + +#### 直播间看过人数 (WATCHED_CHANGE) + +注: 当前直播历史观众数量, 可替代人气 + +**正文:** + +数据包的正文, 前19字节的信息未知: + +```text +00000001: 8b38 8000 0000 7200 1000 0000 0000 0500 .8....r......... +00000002: 0000 00 ... +``` + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------------- | ---- | +| cmd | str | `WATCHED_CHANGE` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------- | ---- | +| num | num | 看过人数 | | +| text_small | str | 显示文字 (小) | | +| text_large | str | 显示文字 (大) | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "WATCHED_CHANGE", + "data": { + "num": 17903, + "text_small": "1.7万", + "text_large": "1.7万人看过" + } +} +``` + +</details> + +#### 用户进场特效 (ENTRY_EFFECT) + +注: 有进场特效的用户进入直播间 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | ---- | +| cmd | str | `ENTRY_EFFECT` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------------- | ----- | ---------------- | ---- | +| id | num | ? | | +| uid | num | 进场用户 mid | | +| target_id | num | 主播 mid? | | +| mock_effect | num | ? | | +| face | str | 进场用户头像 URL | | +| privilege_type | num | ? | | +| copy_writing | str | 进场欢迎文本 | | +| copy_color | str | 进场欢迎文本颜色 | 16 进制 | +| highlight_color | str | 高亮颜色? | 16 进制 | +| priority | num | 优先级? | | +| basemap_url | str | 进场特效背景 URL | APP 端 | +| show_avatar | num | 是否显示用户头像 | 1: 显示<br/>0: 不显示 | +| effective_time | num | ? | | +| web_basemap_url | str | 进场特效背景 URL | 网页端 | +| web_effective_time | num | 进场特效生存时间 | 网页端 | +| web_effect_close | num | ? | | +| web_close_time | num | ? | | +| business | num | ? | | +| copy_writing_v2 | str | 进场欢迎文本 | APP 端? | +| icon_list | array | 空? | | +| max_delay_time | num | 最大等待时间? | | +| trigger_time | num | 触发时间戳 | UNIX 纳秒时间戳 | +| identities | num | 标识符? | | +| effect_silent_time | num | ? | | +| effective_time_new | num | ? | | +| web_dynamic_url_webp | str | ? | | +| web_dynamic_url_apng | str | ? | | +| mobile_dynamic_url_webp | str | ? | | +| wealthy_info | obj | 荣耀等级信息 | | +| new_style | num | ? | | +| is_mystery | bool | ? | | +| uinfo | obj | 用户信息 | | +| full_cartoon_id | num | ? | | +| priority_level | num | ? | | +| wealth_style_info | obj | 荣耀等级样式信息 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "ENTRY_EFFECT", + "data": { + "id": 380, + "uid": 31382283, + "target_id": 12892411, + "mock_effect": 0, + "face": "https://i0.hdslb.com/bfs/face/876e30e89faa5672858cc17bdb357362ec96bc29.jpg", + "privilege_type": 0, + "copy_writing": "<%WYCBat%> 来了", + "copy_color": "#F7F7F7", + "highlight_color": "#FFFFFF", + "priority": 1, + "basemap_url": "", + "show_avatar": 0, + "effective_time": 0, + "web_basemap_url": "https://i0.hdslb.com/bfs/live/mlive/19e7564ed9d466b02f341abfa979c6e38c2ffffb.png", + "web_effective_time": 4, + "web_effect_close": 1, + "web_close_time": 900, + "business": 6, + "copy_writing_v2": "<%WYCBat%> 来了", + "icon_list": [], + "max_delay_time": 7, + "trigger_time": 1748545763327647435, + "identities": 1, + "effect_silent_time": 0, + "effective_time_new": 0, + "web_dynamic_url_webp": "", + "web_dynamic_url_apng": "", + "mobile_dynamic_url_webp": "", + "wealthy_info": { + "uid": 0, + "level": 17, + "level_total_score": 0, + "cur_score": 0, + "upgrade_need_score": 0, + "status": 0, + "dm_icon_key": "" + }, + "new_style": 1, + "is_mystery": false, + "uinfo": { + "uid": 31382283, + "base": { + "name": "WYCBat", + "face": "https://i0.hdslb.com/bfs/face/876e30e89faa5672858cc17bdb357362ec96bc29.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": null, + "origin_info": null, + "official_info": null, + "name_color_str": "" + }, + "medal": null, + "wealth": { + "level": 17, + "dm_icon_key": "" + }, + "title": null, + "guard": { + "level": 0, + "expired_str": "" + }, + "uhead_frame": null, + "guard_leader": null + }, + "full_cartoon_id": 1802, + "priority_level": 0, + "wealth_style_info": { + "url": "https://i0.hdslb.com/bfs/live/b6f2bf3e27f22b3039594842f0005b05a0dc5dae.png" + } + } +} +``` + +</details> + +#### 必须接受的用户进场特效 (ENTRY_EFFECT_MUST_RECEIVE) + +注: 在部分主播进入自己的直播间时下发。 + +结构与 [用户进场特效 (ENTRY_EFFECT)](#用户进场特效-ENTRY_EFFECT) 完全相同。 + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "ENTRY_EFFECT_MUST_RECEIVE", + "data": { + "id": 135, + "uid": 438160221, + "target_id": 438160221, + "mock_effect": 0, + "face": "https://i0.hdslb.com/bfs/face/member/noface.jpg", + "privilege_type": 0, + "copy_writing": "<%weatfe%> 来了", + "copy_color": "#000000", + "highlight_color": "#FFF100", + "priority": 1, + "basemap_url": "https://i0.hdslb.com/bfs/live/mlive/da6933ea70f31c4df63f4b68b735891284888357.png", + "show_avatar": 1, + "effective_time": 1, + "web_basemap_url": "https://i0.hdslb.com/bfs/live/mlive/da6933ea70f31c4df63f4b68b735891284888357.png", + "web_effective_time": 2, + "web_effect_close": 0, + "web_close_time": 900, + "business": 3, + "copy_writing_v2": "<%weatfe%> 来了", + "icon_list": [], + "max_delay_time": 7, + "trigger_time": 1746031259272981482, + "identities": 1, + "effect_silent_time": 0, + "effective_time_new": 0, + "web_dynamic_url_webp": "", + "web_dynamic_url_apng": "", + "mobile_dynamic_url_webp": "", + "wealthy_info": null, + "new_style": 0, + "is_mystery": false, + "uinfo": { + "uid": 438160221, + "base": { + "name": "weatfe", + "face": "https://i0.hdslb.com/bfs/face/member/noface.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": null, + "origin_info": null, + "official_info": null, + "name_color_str": "" + }, + "medal": { + "name": "粉丝团", + "level": 11, + "color_start": 9272486, + "color_end": 9272486, + "color_border": 9272486, + "color": 9272486, + "id": 2956282, + "typ": 0, + "is_light": 1, + "ruid": 438160221, + "guard_level": 0, + "score": 16000, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#596FE099", + "v2_medal_color_end": "#596FE099", + "v2_medal_color_border": "#596FE099", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + }, + "wealth": { + "level": 5, + "dm_icon_key": "" + }, + "title": null, + "guard": { + "level": 0, + "expired_str": "" + }, + "uhead_frame": null, + "guard_leader": null + }, + "full_cartoon_id": 0, + "priority_level": 0, + "wealth_style_info": { + "url": "https://i0.hdslb.com/bfs/live/24f6ef867c3905064136f5c4e33a8d423d41ebdd.png" + } + } +} +``` + +</details> + +#### 全屏特效 (FULL_SCREEN_SPECIAL_EFFECT) + +**示例:** + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "cmd": "FULL_SCREEN_SPECIAL_EFFECT", + "data": { + "type": 2, + "ids": [ + 514 + ], + "queue": 2, + "platform_in": [ + 1, + 2 + ] + } +} +``` + +</details> + +#### 直播间在所属分区的排名改变 (AREA_RANK_CHANGED) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `AREA_RANK_CHANGED` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ------------------ | ---- | +| conf_id | num | 配置 ID? | | +| rank_name | str | 排行榜名称 | | +| uid | num | 主播 mid | | +| rank | num | 直播间在分区的排名 | 没有上榜则为 0 | +| icon_url_blue | str | 蓝色排名图标 URL | | +| icon_url_pink | str | 粉色排名图标 URL | | +| icon_url_grey | str | 灰色排名图标 URL | | +| action_type | num | ? | | +| timestamp | num | 当前时间 | UNIX 秒级时间戳 | +| msg_id | str | ? | 一串 UUID | +| jump_url_link | str | 排行榜跳转链接 | | +| jump_url_pc | str | 排行榜跳转链接 | | +| jump_url_pink | str | 排行榜跳转链接 | | +| jump_url_web | str | 排行榜跳转链接 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "AREA_RANK_CHANGED", + "data": { + "conf_id": 23, + "rank_name": "手游航海", + "uid": 27717502, + "rank": 4, + "icon_url_blue": "https://i0.hdslb.com/bfs/live/18e2990a546d33368200f9058f3d9dbc4038eb5c.png", + "icon_url_pink": "https://i0.hdslb.com/bfs/live/a6c490c36e88c7b191a04883a5ec15aed187a8f7.png", + "icon_url_grey": "https://i0.hdslb.com/bfs/live/cb7444b1faf1d785df6265bfdc1fcfc993419b76.png", + "action_type": 1, + "timestamp": 1673625610, + "msg_id": "e93c7860-b901-41ca-aad8-fe538a5fac9c", + "jump_url_link": "https://live.bilibili.com/p/html/live-app-hotrank/index.html?clientType=3&ruid=27717502&conf_id=23&is_live_half_webview=1&hybrid_rotate_d=1&is_cling_player=1&hybrid_half_ui=1,3,100p,70p,f4eefa,0,30,100,0,0;2,2,375,100p,f4eefa,0,30,100,0,0;3,3,100p,70p,f4eefa,0,30,100,0,0;4,2,375,100p,f4eefa,0,30,100,0,0;5,3,100p,70p,f4eefa,0,30,100,0,0;6,3,100p,70p,f4eefa,0,30,100,0,0;7,3,100p,70p,f4eefa,0,30,100,0,0;8,3,100p,70p,f4eefa,0,30,100,0,0#/area-rank", + "jump_url_pc": "https://live.bilibili.com/p/html/live-app-hotrank/index.html?clientType=4&ruid=27717502&conf_id=23&pc_ui=338,465,f4eefa,0#/area-rank", + "jump_url_pink": "https://live.bilibili.com/p/html/live-app-hotrank/index.html?clientType=1&ruid=27717502&conf_id=23&is_live_half_webview=1&hybrid_rotate_d=1&is_cling_player=1&hybrid_half_ui=1,3,100p,70p,f4eefa,0,30,100,0,0;2,2,375,100p,f4eefa,0,30,100,0,0;3,3,100p,70p,f4eefa,0,30,100,0,0;4,2,375,100p,f4eefa,0,30,100,0,0;5,3,100p,70p,f4eefa,0,30,100,0,0;6,3,100p,70p,f4eefa,0,30,100,0,0;7,3,100p,70p,f4eefa,0,30,100,0,0;8,3,100p,70p,f4eefa,0,30,100,0,0#/area-rank", + "jump_url_web": "https://live.bilibili.com/p/html/live-app-hotrank/index.html?clientType=2&ruid=27717502&conf_id=23#/area-rank" + } +} +``` + +</details> + +#### 广播通知弹幕信息 (COMMON_NOTICE_DANMAKU) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `COMMON_NOTICE_DANMAKU` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | --- | ------ | --------- | +| biz_id | num | 待调查 | | +| content_segments | array | 文本分段 | | +| danmaku_style | obj | 文本样式信息 | 可能不存在 | +| danmaku_url | str | 待调查 | | +| dmscore | num | 待调查 | | +| terminals | array | 指定显示的终端 | 数字数组 | + +`data.content_segments[n]` 数组中的对象 + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | --- | ------ | --------- | +| background_color | arr 或 null | 背景颜色? | 字符串数组,可能不存在 | +| background_color_dark | arr 或 null | 深色模式背景颜色? | 可能不存在 | +| font_bold | bool | text 字段是否加粗? | 可能不存在 | +| font_color | str | text 字段的十六进制颜色值 | | +| font_color_dark | str | text 字段的十六进制颜色值 | APP端设置为深色模式时使用,可能不存在 | +| highlight_font_color | str | text 字段高亮部分的十六进制颜色值? | 可能不存在 | +| highlight_font_color_dark | str | text 字段高亮部分的十六进制颜色值? | 深色模式时使用,可能不存在 | +| img_height | num | 图片高度 | 可能不存在 | +| img_url | str | 图片链接 | 可能不存在 | +| img_width | str | 图片宽度 | 可能不存在 | +| text | str | 文本 | | +| type | num | 文本组件类型 | 1:普通文本<br />2:图片<br />3:链接 | +| uri | str | 链接 | 文本组件类型为 `3` 时存在 | + +`data.danmaku_style` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | --- | ------ | --------- | +| background_color | str | 文本背景颜色的十六进制颜色值 | | +| background_color_dark | str | 文本背景颜色的十六进制颜色值 | APP端设置为深色模式时使用 | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "COMMON_NOTICE_DANMAKU", + "data": { + "content_segments": [ + { + "font_color": "#FB7299", + "text": "春日限时任务:任务即将结束,抓紧完成获取3元红包奖励吧!未完成任务进度将重置", + "type": 1 + } + ], + "dmscore": 144, + "terminals": [ + 1, + 2, + 3, + 4, + 5 + ] + } +} +``` + +```json +{ + "cmd": "COMMON_NOTICE_DANMAKU", + "data": { + "biz_id": 0, + "content_segments": [ + { + "font_color": "#CCCCCC", + "font_color_dark": "#CCCCCC", + "text": "恭喜主播 时雨ioo ", + "type": 1 + }, + { + "font_color": "#F494AF", + "font_color_dark": "#F494AF", + "text": "成为手游航海当前第5名", + "type": 1 + } + ], + "danmaku_style": { + "background_color": null, + "background_color_dark": null + }, + "danmaku_uri": "", + "dmscore": 144, + "terminals": [ + 1, + 2, + 3 + ] + } +} +``` + +```json +{ + "cmd": "COMMON_NOTICE_DANMAKU", + "data": { + "content_segments": [ + { + "background_color": null, + "background_color_dark": null, + "font_bold": false, + "font_color": "#F294AE", + "font_color_dark": "", + "highlight_font_color": "", + "highlight_font_color_dark": "", + "img_height": 0, + "img_url": "", + "img_width": 0, + "text": "疯狂星期五:疯狂任务今日24点结束,请关注任务完成情况~", + "type": 1 + }, + { + "background_color": [ + "#FA729A" + ], + "background_color_dark": null, + "font_bold": false, + "font_color": "#FFFFFF", + "font_color_dark": "", + "highlight_font_color": "", + "highlight_font_color_dark": "", + "img_height": 0, + "img_url": "", + "img_width": 0, + "text": "立即查看", + "type": 3, + "uri": "https://live.bilibili.com/p/html/bilili-page-gift-intro-container/index.html?is_live_half_webview=1&hybrid_rotate_d=1&hybrid_half_ui=1,3,100p,70p,0,0,30,100,12;2,2,375,100p,0,0,30,100,0;3,3,100p,544,0,0,30,100,12;4,2,375,100p,0,0,30,100,0;5,3,100p,70p,0,0,30,100,0;6,3,100p,70p,0,0,30,100,0;7,3,100p,70p,0,0,30,100,0;8,3,100p,70p,0,0,30,100,0&gift_id=32251&roomId=6154037&anchorId=194484313&sendTargetUid=194484313&active_tab=1" + } + ], + "danmaku_style": { + "background_color": null, + "background_color_dark": null + }, + "dmscore": 1008, + "terminals": [ + 1, + 2, + 3, + 4, + 5 + ] + } +} +``` + +</details> + +#### 直播间信息更改 (ROOM_CHANGE) + +注: 例如直播间标题更改、直播间分区更改 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `ROOM_CHANGE` | | +| data | obj | | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | --- | ------ | --------- | +| title | str | 直播间标题 | | +| area_id | num | 当前直播间所属二级分区的ID | | +| parent_area_id | num | 当前直播间所属一级分区的ID | | +| area_name | str | 当前直播间所属二级分区的名称 | | +| parent_area_name | str | 当前直播间所属一级分区名称 | | +| live_key | str | 标记直播场次的key | 未开播更新直播间信息时为`"0"` | +| sub_session_key | str | 待调查 | 未开播更新直播间信息时为`""`(空字符串) | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +已开播: + +```json +{ + "cmd": "ROOM_CHANGE", + "data": { + "title": "开始白给CS", + "area_id": 371, + "parent_area_id": 9, + "area_name": "虚拟主播", + "parent_area_name": "虚拟主播", + "live_key": "320830629635915849", + "sub_session_key": "320830629635915849sub_time:1673690546" + } +} +``` + +未开播: + +```json +{ + "cmd": "ROOM_CHANGE", + "data": { + "title": "随缘", + "area_id": 216, + "parent_area_id": 6, + "area_name": "我的世界", + "parent_area_name": "单机游戏", + "live_key": "0", + "sub_session_key": "" + } +} +``` + +</details> + +#### 直播间内容审核报告 (ROOM_CONTENT_AUDIT_REPORT) + +注:这个数据包需要更新直播间标题且使用主播的登录信息才会下发,更新直播间标题后一般不会立刻下发。 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `ROOM_CONTENT_AUDIT_REPORT` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| audit_content_type | num | 审核内容类型? | | +| room\_id | num | 直播间ID | 未知是真实ID还是短号 | +| anchor\_uid | num | 主播的用户mid | | +| audit\_status | num | 审核状态? | | +| audit\_title | str | 被审核的直播间标题 | | +| audit\_reason | str | 审核结果 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "ROOM_CONTENT_AUDIT_REPORT", + "data": { + "audit_content_type": 1, + "room_id": 1899237171, + "anchor_uid": 438160221, + "audit_status": 2, + "audit_title": "崩坏学园2", + "audit_reason": "一审通过" + } +} +``` + +</details> + +#### 醒目留言按钮 (SUPER_CHAT_ENTRANCE) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `SUPER_CHAT_ENTRANCE` | | +| data | obj | 醒目留言按钮的信息 | | +| roomid | num | 直播间ID | 未知是短号还是真实ID | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | --- | ------ | --------- | +| status | num | 待调查 | | +| jump_url | str | 按下“醒目留言”按钮后弹出小窗的页面URL | | +| icon | str | “醒目留言”按钮图标的URL | | +| broadcast_type | num | 待调查 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "SUPER_CHAT_ENTRANCE", + "data": { + "status": 1, + "jump_url": "https://live.bilibili.com/p/html/live-app-superchat2/index.html?is_live_half_webview=1&hybrid_half_ui=1,3,100p,70p,ffffff,0,30,100;2,2,375,100p,ffffff,0,30,100;3,3,100p,70p,ffffff,0,30,100;4,2,375,100p,ffffff,0,30,100;5,3,100p,60p,ffffff,0,30,100;6,3,100p,60p,ffffff,0,30,100;7,3,100p,60p,ffffff,0,30,100", + "icon": "https://i0.hdslb.com/bfs/live/0a9ebd72c76e9cbede9547386dd453475d4af6fe.png", + "broadcast_type": 1 + }, + "roomid": "8618057" +} +``` + +</details> + +#### 顶部横幅 (WIDGET_BANNER) + +注: 网页端在直播间标题下面的横幅, 例如 限时任务 等 + +**JSON消息:** + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `WIDGET_BANNER` | | +| data | obj | 横幅信息 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| timestamp | num | 服务器发送数据包时的Unix时间戳 | | +| widget_list | obj | 横幅信息 | 待调查 | + +`data.widget_list` 对象: + +以 横幅 ID 为键, JSON Object 为值的表 + +`data.widget_list['?']` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| id | num | 横幅ID | | +| title | str | 待调查 | | +| cover | str | 待调查 | | +| web_cover | str | 待调查 | | +| tip_text | str | 待调查 | | +| tip_text_color | str | 待调查 | | +| tip_bottom_color | str | 待调查 | | +| jump_url | str | 点击横幅后出现小窗的页面的URL | | +| url | str | 待调查 | | +| stay_time | num | 待调查 | | +| site | num | 待调查 | | +| platform_in | array | 待调查 | | +| type | num | 待调查 | | +| band_id | num | 待调查 | | +| sub_key | str | 待调查 | | +| sub_data | str | 横幅数据 | | +| is_add | bool | 待调查 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "WIDGET_BANNER", + "data": { + "timestamp": 1673684868, + "widget_list": { + "308": { + "id": 308, + "title": "一月限时任务", + "cover": "", + "web_cover": "", + "tip_text": "限时任务", + "tip_text_color": "", + "tip_bottom_color": "", + "jump_url": "https://live.bilibili.com/activity/live-activity-battle/index.html?app_name=time_limited_task_jan_2023&is_live_half_webview=1&hybrid_rotate_d=1&hybrid_half_ui=1,3,100p,70p,0,0,0,0,12,0;2,2,375,100p,0,0,0,0,12,0;3,3,100p,70p,0,0,0,0,12,0;4,2,375,100p,0,0,0,0,12,0;5,3,100p,70p,0,0,0,0,12,0;6,3,100p,70p,0,0,0,0,12,0;7,3,100p,70p,0,0,0,0,12,0;8,3,100p,70p,0,0,0,0,12,0&room_id=8618057&uid=29857468#/", + "url": "", + "stay_time": 5, + "site": 1, + "platform_in": [ + "live", + "blink", + "live_link", + "web", + "pc_link" + ], + "type": 1, + "band_id": 101558, + "sub_key": "", + "sub_data": "%7B%22task_status%22%3A0%2C%22current_val%22%3A10%2C%22target_val%22%3A1200%2C%22timeout%22%3A1673687024%2C%22reward_price%22%3A8%2C%22reward_type%22%3A1%7D", + "is_add": true + } + } + } +} +``` + +</details> + +#### 礼物心愿单进度 (WIDGET_WISH_LIST) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `WIDGET_WISH_LIST` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| wish | array | 礼物心愿单信息 | | +| wish_status | num | ? | | +| sid | num | ? | | +| wish_status_info | array | ? | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "WIDGET_WISH_LIST", + "data": { + "wish": [ + { + "type": 3, + "gift_id": 10003, + "gift_name": "舰长", + "gift_img": "https://i0.hdslb.com/bfs/live/f1be2a2d5b227ce72641de1ad64bcc7f9e4111c3.png", + "gift_price": 198000, + "target_num": 5, + "current_num": 0 + }, + { + "type": 2, + "gift_id": 3, + "gift_name": "B坷垃", + "gift_img": "https://s1.hdslb.com/bfs/live/cc8bfcbc24c8b65937f62ce0d16b31ab987dce47.png", + "gift_price": 9900, + "target_num": 5, + "current_num": 0 + }, + { + "type": 2, + "gift_id": 31039, + "gift_name": "牛哇牛哇", + "gift_img": "https://s1.hdslb.com/bfs/live/b8a38b4bd3be120becddfb92650786f00dffad48.png", + "gift_price": 100, + "target_num": 10, + "current_num": 0 + } + ], + "wish_status": 1, + "sid": 477, + "wish_status_info": [ + { + "wish_status_msg": "设定心 愿", + "wish_status_img": "https://i0.hdslb.com/bfs/live/38f82bac32794e79776f7371269453652bd58a87.png", + "wish_status": 0 + }, + { + "wish_status_msg": "达成", + "wish_status_img": "https://i0.hdslb.com/bfs/live/1dae635924437239fc69e561a1a9467508521249.png", + "wish_status": 2 + }, + { + "wish_status_msg": "收集失败", + "wish_status_img": "https://i0.hdslb.com/bfs/live/3bbd30fdd32d085cc90e9ccd98c65a886dca9a8f.png", + "wish_status": 3 + } + ], + "wish_name": "心愿" + } +} +``` + +</details> + +#### 礼物星球信息 (WIDGET_WISH_INFO) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `WIDGET_WISH_INFO` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| sid | num | (?) | | +| wish | arr | 礼物需求信息 | | +| jump_url | str | 用户端礼物星球界面 | | +| wish_status | num | 礼物星球状态 | | +| card_text | str | 卡片提示文本 | | +| modal_text | str | 需求标题 | | +| button_text | str | 按钮文本 | | +| show_time | num | 显示时间 | 单位秒 | +| ts | num | 发送时间戳 | Unix秒时间戳 | +| tid | num | (?) | | +| wish_status_info | arr | 状态对照信息 | | +| wish_name | str | 礼物星球名称 | | + +`data.wish` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| gift_id | num | 礼物id | | +| target_num | num | 需求数量 | | +| gift_img | str | 礼物图片URL | | +| gift_price | num | 礼物金瓜子标价 | CNY×1000 | +| gift_name | str | 礼物名称 | | +| wish_status | num | 该礼物达成状态 | | + +`data.wish_status_info` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| wish_status_msg | str | 状态提示信息 | | +| wish_status_img | str | 状态图片URL | | +| wish_status | str | 状态 | | +| wish_status_desc | str | 状态描述 | 不一定存在 | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "WIDGET_WISH_INFO", + "data": { + "sid": 658537, + "wish": [ + { + "gift_id": 31036, + "target_num": 1, + "gift_img": "https://s1.hdslb.com/bfs/live/8b40d0470890e7d573995383af8a8ae074d485d9.png", + "gift_price": 100, + "gift_name": "小花花", + "wish_status": 1 + }, + { + "gift_id": 30758, + "target_num": 1, + "gift_img": "https://s1.hdslb.com/bfs/live/3ddb10b055b9d1826829ec0fad93ab56484d4a90.png", + "gift_price": 100, + "gift_name": "这个好诶", + "wish_status": 1 + }, + { + "gift_id": 31039, + "target_num": 1, + "gift_img": "https://s1.hdslb.com/bfs/live/91ac8e35dd93a7196325f1e2052356e71d135afb.png", + "gift_price": 100, + "gift_name": "牛哇牛哇", + "wish_status": 1 + } + ], + "jump_url": "https://live.bilibili.com/p/html/bilili-page-gift-wishes-mix-planet/user.html?is_live_half_webview=1&hybrid_half_ui=1,3,100p,70p,0,0,30,100,15,0;2,2,375,100p,0,0,30,100,15,0;3,3,100p,70p,0,0,30,100,15,0;4,2,375,100p,0,0,30,100,15,0;5,3,100p,70p,0,0,30,100,15,0;6,3,100p,70p,0,0,30,100,15,0;7,3,100p,70p,0,0,30,100,15,0;8,3,100p,70p,0,0,30,100,15,0", + "wish_status": 1, + "card_text": "主播今日心愿还未完成", + "modal_text": "今日心愿礼物", + "button_text": "去助力", + "show_time": 5, + "ts": 1746257134, + "tid": 6585370000, + "wish_status_info": [ + { + "wish_status_msg": "礼物星球待点亮", + "wish_status_img": "https://i0.hdslb.com/bfs/live/e507f8b101289b2ce6741880a28304215a65f5bf.png", + "wish_status": -1 + }, + { + "wish_status_msg": "今日心愿暂未达成", + "wish_status_img": "https://i0.hdslb.com/bfs/live/e507f8b101289b2ce6741880a28304215a65f5bf.png", + "wish_status": 1 + }, + { + "wish_status_msg": "今日心愿已达成", + "wish_status_img": "https://i0.hdslb.com/bfs/live/e507f8b101289b2ce6741880a28304215a65f5bf.png", + "wish_status": 2, + "wish_status_desc": "已完成" + } + ], + "wish_name": "心愿礼物" + } +} +``` + +</details> + +#### 下播的直播间 (STOP_LIVE_ROOM_LIST) + +注: 估计是更新关注的主播直播状态的 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| cmd | str | `STOP_LIVE_ROOM_LIST` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | --------- | +| room_id_list | array | 下播的直播间ID | | + +`data.room_id_list` 数组: + +| 项 | 类型 | 内容 | 备注 | +| -- | ---- | ---- | ---- | +| 0 | num | 第 1 个下播的直播间 ID | | +| 1 | num | 第 2 个下播的直播间 ID | | +| …… | num | …… | | +| n | num | 第 (n+1) 个下播的直播间 ID | | + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "STOP_LIVE_ROOM_LIST", + "data": { + "room_id_list": [ + 14507570, 23963084, 24370437, 24380902, 24889494, + 22735090, 24268758, 24668544, 38325, 24762357, + 3222966, 6684395, 24199566, 24864470, 10224194, + 14953052, 6198131, 898214, 10412034, 22506883, + 23932516, 6768714, 24392281, 1799500, 22392518, + 22976729, 21557043, 24896092, 11718936, 21612704, + 21778117, 24145539, 23178318, 23575414, 24842462, + 22245210, 24895499, 3133873, 1298898, 22175308, + 3600684, 2053035, 270652, 24877480, 3854611, + 21512488, 24393104, 24756457, 4630683, 6955412, + 23199465, 2880481, 23868339, 717791, 24068307, + 24875243, 22777819, 24896061, 24619665 + ] + } +} +``` + +</details> + +#### 系统信息 (SYS_MSG) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `SYS_MSG` | | +| msg | str | 提示信息 | | +| url | str | 跳转 URL | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "SYS_MSG", + "msg": "争夺开启,时间周五20点至周日20点,逾期不候哟!", + "url": "" +} +``` + +</details> + +#### 警告 (WARNING) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `WARNING` | | +| msg | str | 警告信息 | | +| roomid | num | 直播间 ID | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "WARNING", + "msg": "图片内容不适宜,请立即调整", + "roomid": 22195814 +} +``` + +</details> + +#### 切断 (CUT_OFF) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `CUT_OFF` | | +| msg | str | 切断原因 | | +| roomid | num | 直播间 ID | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "CUT_OFF", + "msg": "违反直播言论规范,请立即调整", + "roomid": 23993070 +} +``` + +</details> + +#### 切断V2 (CUT_OFF_V2) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `CUT_OFF_V2` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cut_off_scene | num | | | +| timestamp | num | 操作时间戳 | UNIX 秒时间戳 | +| cut_off_version | num | 切断提示信息版本? | | +| cut_off_data | obj | 切断提示信息 | | + +`data.cut_off_data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cut_off_title | str | 对话框窗口标题 | | +| cut\_off\_message\_list | array | 对话框正文列表 | | +| cut\_off\_tip\_list | array | 对话框提示信息列表 | | +| cut\_off\_button\_list | array | 对话框按钮列表 | | + +`data.cut_off_data.cut_off_message_list` 数组: + +| 索引 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| 0 | obj | 首个正文信息 | | +| … | obj | 单个正文信息 | | +| i | obj | 最后正文信息 | | + +`data.cut_off_data.cut_off_message_list[i]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| type | num | 显示类别 | `1`:一个“`label`:`content`”格式的信息 | +| label | str | 标签 | | +| content | str | 内容 | | + +`data.cut_off_data.cut_off_tip_list` 数组: + +| 索引 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| 0 | obj | 首个提示行信息 | | +| … | obj | 单个提示行信息 | | +| i | obj | 最后提示行信息 | | + +`data.cut_off_data.cut_off_tip_list[i]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| show\_platform | array | 要在哪个客户端显示的指代 | | +| message_list | array | 提示信息列表 | | + +`data.cut_off_data.cut_off_tip_list[i].message_list` 数组: + +| 索引 | 类型 | 内容 | 备注 | +|:---:| --- | --- | --- | +| 0 | obj | 首个提示组件信息 | | +| … | obj | 单个提示组件信息 | | +| i1 | obj | 最后提示组件信息 | | + +`data.cut_off_data.cut_off_tip_list[i].message_list[i1]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| type | num | 显示类型 | `1`:纯文本<br />`2`:链接 | +| content | str | 显示文本 | | +| link_url | str | 链接 | type为2时有内容 | + +`data.cut_off_data.cut_off_button_list` 数组: + +| 索引 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| 0 | obj | 首个按钮信息 | | +| … | obj | 单个按钮信息 | | +| i | obj | 最后按钮信息 | | + +`data.cut_off_data.cut_off_button_list[i]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| show_platform | array | 要在那个客户端显示的指代 | `1`和`2`可能是手机直播姬<br />`3`和`4`可能是pc直播姬或网页直播姬 | +| button\_text | str | 按钮文本 | | +| button\_action | num | 按钮操作 | `1`:关闭窗口?<br />`2`:跳转到链接? | +| button_link_url | str | 跳转链接 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "CUT_OFF_V2", + "data": { + "cut_off_scene": 1, + "timestamp": 1731590280, + "cut_off_version": 1, + "cut_off_data": { + "cut_off_title": "违规提示", + "cut_off_message_list": [ + { + "type": 1, + "label": "处罚结果", + "content": "切断本场直播" + }, + { + "type": 1, + "label": "违规原因", + "content": "您本场直播存在挂机、录播等消极直播行为,因此直播被切断,请您及时整改" + }, + { + "type": 1, + "label": "处罚时间", + "content": "2024年11月14日21时17分" + } + ], + "cut_off_tip_list": [ + { + "show_platform": [ + 3, + 4 + ], + "message_list": [ + { + "type": 1, + "content": "请在", + "link_url": "" + }, + { + "type": 2, + "content": "【处罚中心】", + "link_url": "https://link.bilibili.com/p/center/index?my-room/violation-records#/my-room/violation-records" + }, + { + "type": 1, + "content": "查看你的违规记录", + "link_url": "" + } + ] + } + ], + "cut_off_button_list": [ + { + "show_platform": [ + 1, + 2 + ], + "button_text": "了解详情", + "button_action": 2, + "button_link_url": "https://live.bilibili.com/p/html/live-anchor-galaxy/violation_records/mobile.html?-Abrowser=live&is_live_webview=1" + }, + { + "show_platform": [ + 3, + 4 + ], + "button_text": "我知道了", + "button_action": 1, + "button_link_url": "" + } + ] + } + } +} +``` + +</details> + +#### 直播对话框 (ANCHOR_ECOLOGY_LIVING_DIALOG) + +注:推测在自动检测到画面不怎么变化且没人聊天时警告下发,见[#1139(issue正文)](https://github.com/SocialSisterYi/bilibili-API-collect/issues/1139#issue-2657488653)。 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `ANCHOR_ECOLOGY_LIVING_DIALOG` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| dialog\_scene | num | | | +| timestamp | num | 触发时间戳 | UNIX 秒时间戳 | +| valid_timestamp | num | | | +| dialog\_top\_vertical\_img | str | | | +| dialog\_top\_landscape_img | str | | | +| dialog\_title | str | 对话框标题 | | +| dialog_message_list | array | 对话框正文列表 | 参见`CUT_OFF_V2` | +| dialog_tip_list | array | 对话框提示信息列表 | 参见`CUT_OFF_V2` | +| dialog_button_list | array | 对话框按钮列表 | 参见`CUT_OFF_V2` | + +`data.dialog_message_list` 数组: + +同`CUT_OFF_V2`的`data.cut_off_data.cut_off_message_list`数组。 + +`data.dialog_tip_list` 数组: + +同`CUT_OFF_V2`的`data.cut_off_data.cut_off_tip_list`数组。 + +`data.dialog_button_list` 数组: + +同`CUT_OFF_V2`的`data.cut_off_data.cut_off_button_list`数组。 + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "ANCHOR_ECOLOGY_LIVING_DIALOG", + "data": { + "dialog_scene": 1, + "timestamp": 1731504845, + "valid_timestamp": 0, + "dialog_top_vertical_img": "https://i0.hdslb.com/bfs/live/ee359d3e89bb044914f72a557a4ac2d3b5ba4004.png", + "dialog_top_landscape_img": "https://i0.hdslb.com/bfs/live/ee359d3e89bb044914f72a557a4ac2d3b5ba4004.png", + "dialog_title": "直播间违规", + "dialog_message_list": [ + { + "type": 1, + "label": "处罚结果", + "content": "警告" + }, + { + "type": 1, + "label": "违规原因", + "content": "您本场直播存在挂机、录播等消极直播行为,请及时整改" + }, + { + "type": 1, + "label": "处罚时间", + "content": "2024年11月13日21时34分" + } + ], + "dialog_tip_list": [ + { + "show_platform": [ + 1, + 2 + ], + "message_list": [ + { + "type": 1, + "content": "请在", + "link_url": "" + }, + { + "type": 2, + "content": "【处罚中心】", + "link_url": "https://live.bilibili.com/p/html/live-anchor-galaxy/violation_records/mobile.html?is_live_half_webview=1u0026hybrid_rotate_d=1u0026is_cling_player=1u0026hybrid_half_ui=1,3,100p,70p,0,1,30,100;2,2,375,100p,0,1,30,100;3,3,100p,70p,0,1,30,100;4,2,375,100p,0,1,30,100;5,3,100p,70p,0,1,30,100;6,3,100p,70p,0,1,30,100;7,3,100p,70p,0,1,30,100;8,3,100p,70p,0,1,30,100#/" + }, + { + "type": 1, + "content": "查看你的违规记录", + "link_url": "" + } + ] + }, + { + "show_platform": [ + 3, + 4 + ], + "message_list": [ + { + "type": 1, + "content": "请在", + "link_url": "" + }, + { + "type": 2, + "content": "【处罚中心】", + "link_url": "https://link.bilibili.com/#/my-room/violation-records?jump_type=browser&app_common=open" + }, + { + "type": 1, + "content": "查看你的违规记录", + "link_url": "" + } + ] + } + ], + "dialog_button_list": [ + { + "show_platform": [ + 1, + 2, + 3, + 4 + ], + "button_text": "我知道了", + "button_action": 1, + "button_link_url": "" + } + ] + } +} +``` + +</details> + +#### 直播间背景图片修改 (CHANGE_ROOM_INFO) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `CHANGE_ROOM_INFO` | | +| background | str | 背景图 URL | | +| roomid | num | 直播间 ID | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "CHANGE_ROOM_INFO", + "background": "https://i0.hdslb.com/bfs/live/2388faed3728f3396052273ad4c3c9af21c411fc.jpg", + "roomid": 23993070 +} +``` + +</details> + +#### 直播间皮肤变更 (ROOM_SKIN_MSG) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `ROOM_SKIN_MSG` | | +| skin_id | num | 皮肤 ID | | +| status | num | 状态? | | +| end_time | num | 皮肤结束时间? | UNIX 秒级时间戳 | +| current_time | num | 当前时间 | UNIX 秒级时间戳 | +| only_local | bool | 仅在本地显示? | | +| scatter | obj | ? | | +| skin_config | obj | 皮肤配置 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "ROOM_SKIN_MSG", + "skin_id": 353, + "status": 1, + "end_time": 1652620669, + "current_time": 1652015870, + "only_local": false, + "scatter": { + "min": 1, + "max": 200 + }, + "skin_config": { + "android": { + "1": { + "zip": "https://i0.hdslb.com/bfs/live/fab943a5d7eeb871ecf06413283d17536e67ab91.zip", + "md5": "011EBB3E14192212FD50852245DC74FA" + } + }, + "ios": { + "1": { + "zip": "https://i0.hdslb.com/bfs/live/e7d8768dcb3975d82d794fe6b39756317916a7fe.zip", + "md5": "B1223577FE9C5C248EC1326CDACF8379" + } + }, + "ipad": { + "1": { + "zip": "https://i0.hdslb.com/bfs/live/0856e17be073d75b70098609ae26572ba1534605.zip", + "md5": "481AE75FFD0E0DE91EAFB5B6E0F8936B" + } + }, + "web": { + "1": { + "zip": "https://i0.hdslb.com/bfs/live/0b3770980e600f23629c8445fd211d4a12ec4b6f.zip", + "md5": "8F98F79F02DEFE8B69EE2F6DE7416DFF", + "platform": "web", + "version": "1", + "headInfoBgPic": "https://i0.hdslb.com/bfs/live/d293e69b70af34df0fef086a86552b1761a33a75.jpg", + "giftControlBgPic": "https://i0.hdslb.com/bfs/live/1a124c5547c784f41dc3d7f65f446c56c4cbb73e.jpg", + "rankListBgPic": "https://i0.hdslb.com/bfs/live/af8580a956d0eac6ea1d2cc97ea743d435a86874.jpg", + "mainText": "#FFffffff", + "normalText": "#FFffffff", + "highlightContent": "#FFffd119", + "border": "#FFaec2ff", + "buttonText": "#FF123ab2" + } + } + } +} +``` + +</details> + +#### 开启等级禁言 (ROOM_SILENT_ON) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| data | obj | 信息本体 | | +| cmd | str | `ROOM_SILENT_ON` | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| type | str | 类型? | | +| level | num | 等级? | | +| second | num | 时间? | UNIX 秒级时间戳 | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "data": { + "type": "member", + "level": 1, + "second": 1651000426 + }, + "cmd": "ROOM_SILENT_ON" +} +``` + +</details> + +#### 关闭等级禁言 (ROOM_SILENT_OFF) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| data | obj | 信息本体 | | +| cmd | str | `ROOM_SILENT_OFF` | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| type | str | 空 | | +| level | num | 0 | | +| second | num | 0 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "data": { + "type": "", + "level": 0, + "second": 0 + }, + "cmd": "ROOM_SILENT_OFF" +} +``` + +</details> + +#### 指定观众禁言 (ROOM_BLOCK_MSG) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `ROOM_BLOCK_MSG` | | +| data | obj | 详细信息 | | +| uid | num | 禁言用户 mid | | +| uname | str | 禁言用户名 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| dmscore | num | 弹幕分数? | | +| operator | num | 操作者? | | +| uid | num | 禁言用户 mid | | +| uname | str | 禁言用户名 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "ROOM_BLOCK_MSG", + "data": { + "dmscore": 30, + "operator": 2, + "uid": 37903025, + "uname": "玉麟珑" + }, + "uid": "37903025", + "uname": "玉麟珑" +} +``` + +</details> + +#### 房管列表 (ROOM_ADMINS) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `ROOM_ADMINS` | | +| uids | array | 房管 mid 列表 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "ROOM_ADMINS", + "uids": [ 898424, 384203692, 1309513, 30816752, 23931549, 223134 ] +} +``` + +</details> + +#### 设立房管 (room_admin_entrance) + +注: 此处 cmd 内容为小写 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `room_admin_entrance` | | +| dmscore | num | 弹幕分数? | | +| level | num | 等级? | | +| msg | str | 提示信息 | | +| uid | num | 用户 mid | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "room_admin_entrance", + "dmscore": 45, + "level": 1, + "msg": "系统提示:你已被主播设为房管", + "uid": 223134 +} +``` + +</details> + +#### 撤销房管 (ROOM_ADMIN_REVOKE) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `ROOM_ADMIN_REVOKE` | | +| msg | str | 提示信息 | | +| uid | num | 用户 mid | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "ROOM_ADMIN_REVOKE", + "msg": "撤销房管", + "uid": 6791627 +} +``` + +</details> + +#### 多个直播视角信息 (LIVE_MULTI_VIEW_NEW_INFO) + +部分活动直播间会下发。 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `LIVE_MULTI_VIEW_NEW_INFO` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| title | str | 活动标题 | 活动结束后为`""` | +| room_id | num | 主直播间id | 活动结束后为`0` | +| copy_writing | str | 提示文本 | 活动结束后为`""` | +| bg_image | str | 背景图片 | 活动结束后为`""` | +| sub_slt_color | str | 切换按钮颜色? | 活动结束后为`""` | +| sub_bg_color | str | 切换按钮背景颜色? | 活动结束后为`""` | +| sub_text_color | str | 切换按钮文本颜色? | 活动结束后为`""` | +| view_type | num | | | +| room_list | arr | 房间列表 | 不包括“未直播”状态的直播间,活动结束后为`null` | +| relation_view | arr | 详细关系? | 不包括“未直播”状态的直播间,活动结束后为`null` | +| view_pattern | num | | | +| gather_room_list | arr | 空数组? | 活动结束后为`null` | + +`data.room_list` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| order_id | num | 顺序id | | +| room_id | num | 直播间id | 似乎是长号 | +| room_name | str | 主播名称 | | +| live_status | num | 直播状态 | 1:直播中<br />2:轮播中 | +| jump_url | str | 加入直播间的链接 | | + +`data.relation_view` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| order_id | num | 顺序id | | +| view_type | num | | | +| view_id | num | 直播间id | | +| view_name | str | 主播名称 | | +| title | str | 直播间标题 | | +| cover | str | 直播间封面 | | +| jump_url | str | 加入直播间的链接 | | +| switch | bool | | | +| num | num | 看过人数 | | +| watch_icon | str | 看过图标 | | +| live_status | num | 直播状态 | 同`data.room_list[i].live_status` | +| text_small | str | 看过人数文本 | | +| use_view_vt | bool | | | +| anchor_face | str | 主播头像 | | +| match_live_room | bool | | | +| match_info | null | | | +| duration | num | | | +| up_name | str | `""` | | +| pub_date | str | | | +| gather_id | num | | | +| sub_name | str | | | + +**示例:** + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "cmd": "LIVE_MULTI_VIEW_NEW_INFO", + "data": { + "title": "战地风云6公开测试", + "room_id": 5050, + "copy_writing": "更多视角", + "bg_image": "https://i0.hdslb.com/bfs/live/edaa9477a1d8325dd0c36c419b6fd5f9646b2419.png", + "sub_slt_color": "#FFFFFF", + "sub_bg_color": "#333333", + "sub_text_color": "#FFFFFF", + "view_type": 0, + "room_list": [ + { + "order_id": 2, + "room_id": 6154037, + "room_name": "Asaki大人", + "live_status": 2, + "jump_url": "https://live.bilibili.com/6154037?broadcast_type=0&is_room_feed=1&live_from=28022" + }, + { + "order_id": 4, + "room_id": 1521765, + "room_name": "南云鸟羽", + "live_status": 1, + "jump_url": "https://live.bilibili.com/1521765?broadcast_type=0&is_room_feed=1&live_from=28022" + }, + { + "order_id": 8, + "room_id": 24065, + "room_name": "闻香识", + "live_status": 1, + "jump_url": "https://live.bilibili.com/24065?broadcast_type=0&is_room_feed=1&live_from=28022" + }, + { + "order_id": 14, + "room_id": 38528, + "room_name": "乔伊奥斯托雷", + "live_status": 1, + "jump_url": "https://live.bilibili.com/38528?broadcast_type=0&is_room_feed=1&live_from=28022" + }, + { + "order_id": 15, + "room_id": 21263282, + "room_name": "Yommyko", + "live_status": 2, + "jump_url": "https://live.bilibili.com/21263282?broadcast_type=0&is_room_feed=1&live_from=28022" + }, + { + "order_id": 16, + "room_id": 5513659, + "room_name": "狙佬-zuener", + "live_status": 1, + "jump_url": "https://live.bilibili.com/5513659?broadcast_type=0&is_room_feed=1&live_from=28022" + }, + { + "order_id": 18, + "room_id": 146007, + "room_name": "Kisflow", + "live_status": 1, + "jump_url": "https://live.bilibili.com/146007?broadcast_type=0&is_room_feed=1&live_from=28022" + }, + { + "order_id": 19, + "room_id": 1163043, + "room_name": "人形鹿头自走炮", + "live_status": 1, + "jump_url": "https://live.bilibili.com/1163043?broadcast_type=0&is_room_feed=1&live_from=28022" + }, + { + "order_id": 20, + "room_id": 3343118, + "room_name": "版尤黑紫", + "live_status": 1, + "jump_url": "https://live.bilibili.com/3343118?broadcast_type=0&is_room_feed=1&live_from=28022" + }, + { + "order_id": 21, + "room_id": 25212992, + "room_name": "贝施汀", + "live_status": 1, + "jump_url": "https://live.bilibili.com/25212992?broadcast_type=0&is_room_feed=1&live_from=28022" + }, + { + "order_id": 22, + "room_id": 11313, + "room_name": "丧心病狂的魔笑", + "live_status": 1, + "jump_url": "https://live.bilibili.com/11313?broadcast_type=0&is_room_feed=1&live_from=28022" + }, + { + "order_id": 24, + "room_id": 902302, + "room_name": "LF叶绿", + "live_status": 1, + "jump_url": "https://live.bilibili.com/902302?broadcast_type=0&is_room_feed=1&live_from=28022" + } + ], + "relation_view": [ + { + "order_id": 2, + "view_type": 0, + "view_id": 6154037, + "view_name": "Asaki大人", + "title": "猪猪猪", + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/87e0332a5c3c8cd73fa7616045111b90b0199087.jpg", + "jump_url": "https://live.bilibili.com/6154037?broadcast_type=0&is_room_feed=1&live_from=28022", + "switch": true, + "num": 2305, + "watch_icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "live_status": 2, + "text_small": "2305", + "use_view_vt": false, + "anchor_face": "https://i1.hdslb.com/bfs/face/84a861facfa041b46f7a30897e9ed3f2e05e0519.jpg", + "match_live_room": false, + "match_info": null, + "duration": 0, + "up_name": "", + "pub_date": "", + "gather_id": 0, + "sub_name": "" + }, + { + "order_id": 4, + "view_type": 0, + "view_id": 1521765, + "view_name": "南云鸟羽", + "title": "【战地6B测】下午四点开!聊天摸鱼", + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/a8216e0b5469949fcbcc72458c7955b562838a89.jpg", + "jump_url": "https://live.bilibili.com/1521765?broadcast_type=0&is_room_feed=1&live_from=28022", + "switch": true, + "num": 36987, + "watch_icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "live_status": 1, + "text_small": "3.6万", + "use_view_vt": false, + "anchor_face": "https://i1.hdslb.com/bfs/face/f4744b6346ddaccb4642a0f05f25d798fb5d8474.jpg", + "match_live_room": false, + "match_info": null, + "duration": 0, + "up_name": "", + "pub_date": "", + "gather_id": 0, + "sub_name": "" + }, + { + "order_id": 8, + "view_type": 0, + "view_id": 24065, + "view_name": "闻香识", + "title": "4点战地6!!", + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/6e309306fcb7bdeeb5e72f8b4c2d1ed7ba7e1e29.jpg", + "jump_url": "https://live.bilibili.com/24065?broadcast_type=0&is_room_feed=1&live_from=28022", + "switch": true, + "num": 32408, + "watch_icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "live_status": 1, + "text_small": "3.2万", + "use_view_vt": false, + "anchor_face": "https://i0.hdslb.com/bfs/face/df21869b067816e03c517bc774f6ebf5a86563de.jpg", + "match_live_room": false, + "match_info": null, + "duration": 0, + "up_name": "", + "pub_date": "", + "gather_id": 0, + "sub_name": "" + }, + { + "order_id": 14, + "view_type": 0, + "view_id": 38528, + "view_name": "乔伊奥斯托雷", + "title": "[战地六B测]捞薯条,吃薯条,谁是薯条?", + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/a89ebcd8b4f3e841ddb7cb53fbdc6013a9956013.jpg", + "jump_url": "https://live.bilibili.com/38528?broadcast_type=0&is_room_feed=1&live_from=28022", + "switch": true, + "num": 3660, + "watch_icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "live_status": 1, + "text_small": "3660", + "use_view_vt": false, + "anchor_face": "https://i1.hdslb.com/bfs/face/82ef4b09c26751649da2a48960d23fd87baa6db5.jpg", + "match_live_room": false, + "match_info": null, + "duration": 0, + "up_name": "", + "pub_date": "", + "gather_id": 0, + "sub_name": "" + }, + { + "order_id": 15, + "view_type": 0, + "view_id": 21263282, + "view_name": "Yommyko", + "title": "和广东双马尾搏斗!禁闭求生2", + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/86ac43cf0c1db277b92a5e83324558ceab2bb108.jpg", + "jump_url": "https://live.bilibili.com/21263282?broadcast_type=0&is_room_feed=1&live_from=28022", + "switch": true, + "num": 1583, + "watch_icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "live_status": 2, + "text_small": "1583", + "use_view_vt": false, + "anchor_face": "https://i2.hdslb.com/bfs/face/9718e4c59c2cfcc9f8b747ad8ea5006fad78a76a.jpg", + "match_live_room": false, + "match_info": null, + "duration": 0, + "up_name": "", + "pub_date": "", + "gather_id": 0, + "sub_name": "" + }, + { + "order_id": 16, + "view_type": 0, + "view_id": 5513659, + "view_name": "狙佬-zuener", + "title": "战地6!开玩!七年之约已到!", + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/b1779156686031460633d31362205456d1bb53df.jpg", + "jump_url": "https://live.bilibili.com/5513659?broadcast_type=0&is_room_feed=1&live_from=28022", + "switch": true, + "num": 30035, + "watch_icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "live_status": 1, + "text_small": "3.0万", + "use_view_vt": false, + "anchor_face": "https://i0.hdslb.com/bfs/face/bdb4b214d3446aca7c11b408ae6f35c89f52a5cc.jpg", + "match_live_room": false, + "match_info": null, + "duration": 0, + "up_name": "", + "pub_date": "", + "gather_id": 0, + "sub_name": "" + }, + { + "order_id": 18, + "view_type": 0, + "view_id": 146007, + "view_name": "Kisflow", + "title": "战地6 BETA 战场老登职业哥", + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/0007988a93c06215f0ffd96f7a4e3834d1396408.jpg", + "jump_url": "https://live.bilibili.com/146007?broadcast_type=0&is_room_feed=1&live_from=28022", + "switch": true, + "num": 7839, + "watch_icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "live_status": 1, + "text_small": "7839", + "use_view_vt": false, + "anchor_face": "https://i1.hdslb.com/bfs/face/5761dbf3f03b1a31ad8a6aec01452c97e93c16c0.jpg", + "match_live_room": false, + "match_info": null, + "duration": 0, + "up_name": "", + "pub_date": "", + "gather_id": 0, + "sub_name": "" + }, + { + "order_id": 19, + "view_type": 0, + "view_id": 1163043, + "view_name": "人形鹿头自走炮", + "title": "神秘远光84男", + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/cea622fe174d8c3fd26e58ea5a7e3b709fd8aee4.jpg", + "jump_url": "https://live.bilibili.com/1163043?broadcast_type=0&is_room_feed=1&live_from=28022", + "switch": true, + "num": 20796, + "watch_icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "live_status": 1, + "text_small": "2.0万", + "use_view_vt": false, + "anchor_face": "https://i2.hdslb.com/bfs/face/259c1f3b485ad5e2182446246fccb87114701ed8.jpg", + "match_live_room": false, + "match_info": null, + "duration": 0, + "up_name": "", + "pub_date": "", + "gather_id": 0, + "sub_name": "" + }, + { + "order_id": 20, + "view_type": 0, + "view_id": 3343118, + "view_name": "版尤黑紫", + "title": "爽玩!战地6B测", + "cover": "https://i0.hdslb.com/bfs/live/user_cover/039be5f223d26d4108941f1f056ee5842e3e5720.jpg", + "jump_url": "https://live.bilibili.com/3343118?broadcast_type=0&is_room_feed=1&live_from=28022", + "switch": true, + "num": 1704, + "watch_icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "live_status": 1, + "text_small": "1704", + "use_view_vt": false, + "anchor_face": "https://i2.hdslb.com/bfs/face/3cdcbc8945d18575279ac55c75f4da9f0a7dbc9e.jpg", + "match_live_room": false, + "match_info": null, + "duration": 0, + "up_name": "", + "pub_date": "", + "gather_id": 0, + "sub_name": "" + }, + { + "order_id": 21, + "view_type": 0, + "view_id": 25212992, + "view_name": "贝施汀", + "title": "战地6还没开服,先直播剪会儿视频聊聊天", + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/fb0227b71dca8555588c9c6c0af329cf250123a9.jpg", + "jump_url": "https://live.bilibili.com/25212992?broadcast_type=0&is_room_feed=1&live_from=28022", + "switch": true, + "num": 2207, + "watch_icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "live_status": 1, + "text_small": "2207", + "use_view_vt": false, + "anchor_face": "https://i0.hdslb.com/bfs/face/7242e856562166a27e8be4a184e4cddbaed8177f.jpg", + "match_live_room": false, + "match_info": null, + "duration": 0, + "up_name": "", + "pub_date": "", + "gather_id": 0, + "sub_name": "" + }, + { + "order_id": 22, + "view_type": 0, + "view_id": 11313, + "view_name": "丧心病狂的魔笑", + "title": "等待测试开启!但是先直播周边开箱!", + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/48fb912da0f665427eb230ef3273defdb1a33fa4.jpg", + "jump_url": "https://live.bilibili.com/11313?broadcast_type=0&is_room_feed=1&live_from=28022", + "switch": true, + "num": 2924, + "watch_icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "live_status": 1, + "text_small": "2924", + "use_view_vt": false, + "anchor_face": "https://i2.hdslb.com/bfs/face/e672848bc2718b79ca2f44eb447e84282c6f806d.jpg", + "match_live_room": false, + "match_info": null, + "duration": 0, + "up_name": "", + "pub_date": "", + "gather_id": 0, + "sub_name": "" + }, + { + "order_id": 24, + "view_type": 0, + "view_id": 902302, + "view_name": "LF叶绿", + "title": "《田 野 打 架 6》", + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/3b18086f9e70f719917c5d4561c25defdd13cd82.jpg", + "jump_url": "https://live.bilibili.com/902302?broadcast_type=0&is_room_feed=1&live_from=28022", + "switch": true, + "num": 1897, + "watch_icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "live_status": 1, + "text_small": "1897", + "use_view_vt": false, + "anchor_face": "https://i2.hdslb.com/bfs/face/5e3570095f5af77d20188ea45d45da216a31e52d.jpg", + "match_live_room": false, + "match_info": null, + "duration": 0, + "up_name": "", + "pub_date": "", + "gather_id": 0, + "sub_name": "" + } + ], + "view_pattern": 1, + "gather_room_list": [] + } +} +``` + +</details> + +#### 天选时刻合法检查 (ANCHOR_LOT_CHECKSTATUS) + +**示例:** + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "cmd": "ANCHOR_LOT_CHECKSTATUS", + "data": { + "id": 2553641, + "reject_reason": "由于奖品格式不合格,请仔细检查后再提交哦", + "status": 5, + "uid": 1827176970 + } +} +``` + +</details> + +#### 天选时刻开始 (ANCHOR_LOT_START) + +**示例:** + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "cmd": "ANCHOR_LOT_START", + "data": { + "asset_icon": "https://i0.hdslb.com/bfs/live/627ee2d9e71c682810e7dc4400d5ae2713442c02.png", + "award_image": "", + "award_name": "艺术头像绘制", + "award_num": 1, + "cur_gift_num": 0, + "current_time": 1651037946, + "danmu": "卡宝下午好", + "gift_id": 3, + "gift_name": "B坷垃", + "gift_num": 1, + "gift_price": 9900, + "goaway_time": 180, + "goods_id": 15, + "id": 2553648, + "is_broadcast": 1, + "join_type": 1, + "lot_status": 0, + "max_time": 600, + "require_text": "当前主播粉丝勋章至少1级", + "require_type": 2, + "require_value": 1, + "room_id": 23614753, + "send_gift_ensure": 0, + "show_panel": 1, + "start_dont_popup": 0, + "status": 1, + "time": 599, + "url": "https://live.bilibili.com/p/html/live-lottery/anchor-join.html?is_live_half_webview=1&hybrid_biz=live-lottery-anchor&hybrid_half_ui=1,5,100p,100p,000000,0,30,0,0,1;2,5,100p,100p,000000,0,30,0,0,1;3,5,100p,100p,000000,0,30,0,0,1;4,5,100p,100p,000000,0,30,0,0,1;5,5,100p,100p,000000,0,30,0,0,1;6,5,100p,100p,000000,0,30,0,0,1;7,5,100p,100p,000000,0,30,0,0,1;8,5,100p,100p,000000,0,30,0,0,1", + "web_url": "https://live.bilibili.com/p/html/live-lottery/anchor-join.html" + } +} +``` + +</details> + +#### 天选时刻结束 (ANCHOR_LOT_END) + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "ANCHOR_LOT_END", + "data": { + "id": 2553648 + } +} +``` + +</details> + +#### 天选时刻中奖者 (ANCHOR_LOT_AWARD) + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "ANCHOR_LOT_AWARD", + "data": { + "award_dont_popup": 1, + "award_image": "", + "award_name": "艺术头像绘制", + "award_num": 1, + "award_users": [ + { + "uid": 8318700, + "uname": "桥下念喬", + "face": "http://i0.hdslb.com/bfs/face/dfde2ffc6286c2c5189592cc84fd70bcf977b143.jpg", + "level": 21, + "color": 5805790 + } + ], + "id": 2553648, + "lot_status": 2, + "url": "https://live.bilibili.com/p/html/live-lottery/anchor-join.html?is_live_half_webview=1&hybrid_biz=live-lottery-anchor&hybrid_half_ui=1,5,100p,100p,000000,0,30,0,0,1;2,5,100p,100p,000000,0,30,0,0,1;3,5,100p,100p,000000,0,30,0,0,1;4,5,100p,100p,000000,0,30,0,0,1;5,5,100p,100p,000000,0,30,0,0,1;6,5,100p,100p,000000,0,30,0,0,1;7,5,100p,100p,000000,0,30,0,0,1;8,5,100p,100p,000000,0,30,0,0,1", + "web_url": "https://live.bilibili.com/p/html/live-lottery/anchor-join.html" + } +} +``` + +</details> + +#### 天选时刻通知 (ANCHOR_LOT_NOTICE) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `ANCHOR_LOT_NOTICE` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| notice\_type | num | 通知卡片类型? | | +| lottery\_card | obj | 通知卡片内容 | | + +`data.lottery_card` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| show\_time | num | 显示时间? | | +| button\_text | str | 按钮文本? | | +| icon | str | 图标 | | +| title | str | 标题? | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "data": { + "notice_type": 1, + "lottery_card": { + "show_time": 30, + "button_text": "去发奖", + "icon": "https://i0.hdslb.com/bfs/live/95970204111233f181fc28622502aaf1a9359b9a.png", + "title": "发天选有助于人气累积" + } + }, + "cmd": "ANCHOR_LOT_NOTICE" +} +``` + +</details> + +#### 语音连麦开关 (VOICE_JOIN_SWITCH) + +在直播姬开关连麦功能时下发。 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `VOICE_JOIN_SWITCH` | | +| data | obj | 信息本体 | | +| room_id | num | 直播间id | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| room_id | num | 直播间id | | +| room_status | num | 连麦开关状态 | | +| root_status | num | 连麦开关状态 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +开: + +```json +{ + "cmd": "VOICE_JOIN_SWITCH", + "data": { + "room_id": 1899237171, + "room_status": 1, + "root_status": 1 + }, + "room_id": 1899237171 +} +``` + +关: + +```json +{ + "cmd": "VOICE_JOIN_SWITCH", + "data": { + "room_id": 1899237171, + "room_status": 0, + "root_status": 0 + }, + "room_id": 1899237171 +} +``` + +</details> + +#### 邀请视频连线 (VIDEO_CONNECTION_JOIN_START) + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "VIDEO_CONNECTION_JOIN_START", + "data": { + "status": 1, + "invited_uid": 351686170, + "channel_id": "72057594038132685", + "invited_uname": "小妹睡不醒", + "invited_face": "http://i1.hdslb.com/bfs/face/828562203e620f711fb4c786f05996357857ed4d.jpg", + "start_at": 1651237440, + "current_time": 1651237440 + }, + "roomid": 12401854 +} +``` + +</details> + +#### 视频连线信息 (VIDEO_CONNECTION_MSG) + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "VIDEO_CONNECTION_MSG", + "data": { + "channel_id": "72057594038132685", + "current_time": 1651237440, + "dmscore": 4, + "toast": "主播发起了视频连线" + } +} +``` + +</details> + +#### 结束视频连线 (VIDEO_CONNECTION_JOIN_END) + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "VIDEO_CONNECTION_JOIN_END", + "data": { + "channel_id": "72057594038132685", + "start_at": 1651238384, + "toast": "主播 结束了与小妹睡不醒的连线.", + "current_time": 1651238384 + }, + "roomid": 22195814 +} +``` + +</details> + +#### 重连直播间? (REENTER_LIVE_ROOM) + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "REENTER_LIVE_ROOM", + "data": { + "room_id": 22195814, + "request_random_sec_range": 10, + "reason": 1 + }, + "roomid": 22195814 +} +``` + +</details> + +#### 连线礼物信息 (UNIVERSAL_EVENT_GIFT) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `UNIVERSAL_EVENT_GIFT` | | +| data | obj | 信息本体 | | +| msg_id | str | | | +| p_is_ack | bool | | | +| p_msg_type | num | | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| anchor_uid | num | 主播uid | | +| info | obj | 连线信息 | | +| room_id | num | 直播间id | | + +`data.info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| biz_session_id | str | 连线会话id? | | +| business_label | str | | | +| interact_channel_id | str | 频道id? | | +| interact_connect_type | num | | | +| interact_max_users | num | 最大连线数? | | +| interact_mode | obj | | | +| interact_template | obj | 展示模板 | | +| invoking_time | num | | | +| members | arr | 连线成员 | 参见 `UNIVERSAL_EVENT_GIFT_V2` 的 `data.members` ,缺少部分字段 | +| members_version | num | | | +| multi_conn_info | obj | 连线信息 | | +| room_owner | num | 发起者uid | | +| room_start_at | str | | | +| room_start_at_ts | num | | | +| room_status | num | | | +| session_start_at | str | | | +| session_start_at_ts | num | | | +| session_status | num | | | +| system_time_unix | num | 服务器时间戳 | Unix 秒时间戳 | +| trace_id | str | | | +| version | num | 数据版本 | Unix 毫秒时间戳 | + +`data.info.interact_mode` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| apply_timeout | num | 超时? | | +| interact_mode_type | num | | | +| invite_timeout | num | 邀请超时? | | +| join_types | arr | 加入类型? | 数字数组 | +| position_mode | num | | | + +`data.info.interact_template` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| is_variable_layout | bool | 布局是否可变? | | +| layout_data | obj | 布局信息 | | +| layout_id | str | 布局id | | +| layout_list | null | ? | | +| show_interact_ui | bool | 显示交互UI? | | +| template_id | str | 模板id? | | + +`data.info.interact_template.layout_data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| best_area_show_pos | num | | | +| cells | arr | 具体布局信息 | | +| default_cell | obj | | | +| height | num | | | +| rtc_resolution | obj | | | +| width | num | | | + +`data.info.interact_template.layout_data.cells` 数组中对象: + +与 `data.info.interact_template.layout_data.default_cell` 对象相同 + +`data.info.interact_template.layout_data.default_cell` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| can_zoom | num | | | +| default_open | num | | | +| height | num | | | +| mobile_avatar_size | num | | | +| mobile_font_size | num | | | +| pc_web_avatar_size | num | | | +| pc_web_font_size | num | | | +| position | num | 定位? | | +| width | num | | | +| x | num | | | +| y | num | | | +| z_index | num | | | + +`data.info.interact_template.layout_data.rtc_resolution` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code_rate_init | num | | | +| code_rate_max | num | | | +| code_rate_min | num | | | +| horizontal_height | num | | | +| horizontal_width | num | | | +| vertical_height | num | | | +| vertical_width | num | | | + +`data.info.members` 数组中对象: + +参见 [`UNIVERSAL_EVENT_GIFT_V2`](#连线礼物信息v2-universal_event_gift_v2) 的 `data.members` 数组中对象,本cmd缺少部分字段。 + +`data.info.multi_conn_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| room_owner | num | 发起人uid | | +| scores | arr | 礼物信息 | | +| show_score | num | 是否显示? | | + +`data.info.multi_conn_info.scores` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| price | num | 礼物累计价值 | CNY × 100 | +| price_text | str | 礼物累计价值文本 | | +| uid | num | 对应主播uid | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "UNIVERSAL_EVENT_GIFT", + "data": { + "anchor_uid": 1950658, + "info": { + "biz_session_id": "17545643420522077733317", + "business_label": "universal_multi_conn", + "interact_channel_id": "4679025140177408", + "interact_connect_type": 0, + "interact_max_users": 9, + "interact_mode": { + "apply_timeout": 20, + "interact_mode_type": 0, + "invite_timeout": 30, + "join_types": [ + 1, + 2 + ], + "position_mode": 0 + }, + "interact_template": { + "is_variable_layout": true, + "layout_data": { + "best_area_show_pos": 0, + "cells": [ + { + "can_zoom": 2, + "default_open": 0, + "height": 48, + "mobile_avatar_size": 64, + "mobile_font_size": 0, + "pc_web_avatar_size": 112, + "pc_web_font_size": 0, + "position": 0, + "width": 30, + "x": 0, + "y": 0, + "z_index": 0 + }, + { + "can_zoom": 1, + "default_open": 0, + "height": 0, + "mobile_avatar_size": 0, + "mobile_font_size": 0, + "pc_web_avatar_size": 0, + "pc_web_font_size": 0, + "position": 1, + "width": 0, + "x": 30, + "y": 0, + "z_index": 0 + }, + { + "can_zoom": 1, + "default_open": 0, + "height": 0, + "mobile_avatar_size": 0, + "mobile_font_size": 0, + "pc_web_avatar_size": 0, + "pc_web_font_size": 0, + "position": 2, + "width": 0, + "x": 45, + "y": 0, + "z_index": 0 + }, + { + "can_zoom": 1, + "default_open": 0, + "height": 0, + "mobile_avatar_size": 0, + "mobile_font_size": 0, + "pc_web_avatar_size": 0, + "pc_web_font_size": 0, + "position": 3, + "width": 0, + "x": 30, + "y": 16, + "z_index": 0 + }, + { + "can_zoom": 1, + "default_open": 0, + "height": 0, + "mobile_avatar_size": 0, + "mobile_font_size": 0, + "pc_web_avatar_size": 0, + "pc_web_font_size": 0, + "position": 4, + "width": 0, + "x": 45, + "y": 16, + "z_index": 0 + }, + { + "can_zoom": 1, + "default_open": 0, + "height": 0, + "mobile_avatar_size": 0, + "mobile_font_size": 0, + "pc_web_avatar_size": 0, + "pc_web_font_size": 0, + "position": 5, + "width": 0, + "x": 30, + "y": 32, + "z_index": 0 + }, + { + "can_zoom": 1, + "default_open": 0, + "height": 0, + "mobile_avatar_size": 0, + "mobile_font_size": 0, + "pc_web_avatar_size": 0, + "pc_web_font_size": 0, + "position": 6, + "width": 0, + "x": 45, + "y": 32, + "z_index": 0 + } + ], + "default_cell": { + "can_zoom": 0, + "default_open": 1, + "height": 16, + "mobile_avatar_size": 40, + "mobile_font_size": 10, + "pc_web_avatar_size": 72, + "pc_web_font_size": 14, + "position": 0, + "width": 15, + "x": 0, + "y": 0, + "z_index": 0 + }, + "height": 48, + "rtc_resolution": { + "code_rate_init": 500, + "code_rate_max": 700, + "code_rate_min": 375, + "horizontal_height": 400, + "horizontal_width": 500, + "vertical_height": 576, + "vertical_width": 360 + }, + "width": 60 + }, + "layout_id": "left1_right6", + "layout_list": null, + "show_interact_ui": true, + "template_id": "multi_conn_grid" + }, + "invoking_time": 1, + "members": [ + { + "face": "https://i1.hdslb.com/bfs/face/2ddb513f600c203f21aefb9725ab0eb84f093943.jpg", + "gender": 0, + "join_time": 1754564992, + "link_id": "44479117", + "position": 0, + "room_id": 41682, + "uid": 1950658, + "uname": "早稻叽" + }, + { + "face": "https://i1.hdslb.com/bfs/face/5958bb6814f25d832775ca37043d38f893b4a478.jpg", + "gender": -1, + "join_time": 1754564347, + "link_id": "44478459", + "position": 1, + "room_id": 26376408, + "uid": 2077733317, + "uname": "烛不遥" + }, + { + "face": "https://i0.hdslb.com/bfs/face/7c862b4ad1a29cdd2b849bcea3c3812b67770d21.jpg", + "gender": 0, + "join_time": 1754564347, + "link_id": "44478460", + "position": 2, + "room_id": 1774970222, + "uid": 1035559935, + "uname": "新砂Athia" + }, + { + "face": "https://i0.hdslb.com/bfs/face/81c1f45b45958c19523bb7cbae7fc3fa99b4aae1.jpg", + "gender": -1, + "join_time": 1754564361, + "link_id": "44478500", + "position": 3, + "room_id": 31361500, + "uid": 3546581471070432, + "uname": "颂温暖_Swanna" + }, + { + "face": "https://i2.hdslb.com/bfs/face/eceb8fa58c41b7cd733bebafcd7c1f3e33b37b07.jpg", + "gender": 0, + "join_time": 1754564385, + "link_id": "44478528", + "position": 4, + "room_id": 1937830041, + "uid": 3546768203582225, + "uname": "暴躁小辣jo" + }, + { + "face": "https://i0.hdslb.com/bfs/face/12c1cd0df2ee6e6bb09b279b0553cdc9ae4af4f0.jpg", + "gender": -1, + "join_time": 1754564774, + "link_id": "44478875", + "position": 5, + "room_id": 23090250, + "uid": 475912512, + "uname": "抵抗Resistance" + } + ], + "members_version": 3974722551, + "multi_conn_info": { + "room_owner": 2077733317, + "scores": [ + { + "price": 82900, + "price_text": "829", + "uid": 1950658 + }, + { + "price": 21200, + "price_text": "212", + "uid": 2077733317 + }, + { + "price": 30400, + "price_text": "304", + "uid": 1035559935 + }, + { + "price": 675600, + "price_text": "6756", + "uid": 3546581471070432 + }, + { + "price": 96800, + "price_text": "968", + "uid": 3546768203582225 + }, + { + "price": 79200, + "price_text": "792", + "uid": 475912512 + } + ], + "show_score": 1 + }, + "room_owner": 2077733317, + "room_start_at": "", + "room_start_at_ts": 0, + "room_status": 1, + "session_start_at": "", + "session_start_at_ts": 0, + "session_status": 1, + "system_time_unix": 1754568295, + "trace_id": "", + "version": 1754568295428 + }, + "room_id": 41682 + }, + "msg_id": "34610565842749442:1000:1000", + "p_is_ack": true, + "p_msg_type": 1, + "send_time": 1754568295441 +} +``` + +</details> + +#### 连线礼物信息V2 (UNIVERSAL_EVENT_GIFT_V2) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `UNIVERSAL_EVENT_GIFT_V2` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| biz_session_id | str | 连线会话id? | | +| interact_channel_id | str | 频道id? | | +| interact_template | obj | 交互模板信息 | | +| members | arr | 连线成员 | | +| stream_control | null | | | +| version | num | 数据版本 | Unix 毫秒时间戳 | +| session_status | num | | | +| business_label | str | | | +| invoking_time | num | | | +| members_version | num | | | +| room_status | num | | | +| system_time_unix | num | 服务器时间戳 | Unix 秒时间戳 | +| room_owner | num | 发起人uid | | +| session_start_at | str | 会话开始时间 | | +| session_start_at_ts | num | 会话经过时间 | | +| room_start_at | str | 当前直播间加入会话时间 | | +| room_start_at_ts | num | 当前直播间自加入会话开始经过的时间 | | +| trace_id | str | 追踪id? | | +| biz_extra_data | obj | | | +| channel_users | arr | 当前连线频道内uid列表 | | + +`data.interact_template` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| template_id | str | 模板id? | | +| show_interact_ui | bool | 显示交互UI? | | +| layout_id | str | 样式id? | | + +`data.members` 数组中对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| uid | num | 连线主播uid | | +| uname | str | 连线主播名称 | | +| face | str | 连线主播头像 | | +| position | num | 位置? | | +| join_time | num | 加入时间 | Unix 秒时间戳 | +| link_id | str | | | +| gender | num | | | +| room_id | num | 连线主播直播间id | | +| fans_num | num | | | +| display_name | str | 显示名称 | | +| biz_extra_data | obj | | | +| join_time_ts | num | | | + +`data.members[i].biz_extra_data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| multi_conn | obj | | | + +`data.members[i].biz_extra_data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| price | num | 礼物累计价值 | CNY × 100 | +| price_text | str | 礼物累计价值文本 | | + +`data.biz_extra_data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| multi_conn | obj | | | + +`data.biz_extra_data.multi_conn` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| show_score | num | | | +| support_full_zoom | num | | | + +`data.channel_users` 数组: + +| 索引 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| 0 | num | 主播uid | | +| … | num | 主播uid | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "UNIVERSAL_EVENT_GIFT_V2", + "data": { + "biz_session_id": "17545643420522077733317", + "interact_channel_id": "4679025140177408", + "interact_template": { + "template_id": "multi_conn_grid", + "show_interact_ui": true, + "layout_id": "left1_right6" + }, + "members": [ + { + "uid": 1950658, + "uname": "早稻叽", + "face": "https://i1.hdslb.com/bfs/face/2ddb513f600c203f21aefb9725ab0eb84f093943.jpg", + "position": 0, + "join_time": 1754564992, + "link_id": "44479117", + "gender": 0, + "room_id": 41682, + "fans_num": 0, + "display_name": "本房主播", + "biz_extra_data": { + "multi_conn": { + "price": 82900, + "price_text": "829" + } + }, + "join_time_ts": 0 + }, + { + "uid": 2077733317, + "uname": "烛不遥", + "face": "https://i1.hdslb.com/bfs/face/5958bb6814f25d832775ca37043d38f893b4a478.jpg", + "position": 1, + "join_time": 1754564347, + "link_id": "44478459", + "gender": -1, + "room_id": 26376408, + "fans_num": 0, + "display_name": "烛不遥", + "biz_extra_data": { + "multi_conn": { + "price": 21200, + "price_text": "212" + } + }, + "join_time_ts": 0 + }, + { + "uid": 1035559935, + "uname": "新砂Athia", + "face": "https://i0.hdslb.com/bfs/face/7c862b4ad1a29cdd2b849bcea3c3812b67770d21.jpg", + "position": 2, + "join_time": 1754564347, + "link_id": "44478460", + "gender": 0, + "room_id": 1774970222, + "fans_num": 0, + "display_name": "新砂Athia", + "biz_extra_data": { + "multi_conn": { + "price": 30400, + "price_text": "304" + } + }, + "join_time_ts": 0 + }, + { + "uid": 3546581471070432, + "uname": "颂温暖_Swanna", + "face": "https://i0.hdslb.com/bfs/face/81c1f45b45958c19523bb7cbae7fc3fa99b4aae1.jpg", + "position": 3, + "join_time": 1754564361, + "link_id": "44478500", + "gender": -1, + "room_id": 31361500, + "fans_num": 0, + "display_name": "颂温暖_Swanna", + "biz_extra_data": { + "multi_conn": { + "price": 675600, + "price_text": "6756" + } + }, + "join_time_ts": 0 + }, + { + "uid": 3546768203582225, + "uname": "暴躁小辣jo", + "face": "https://i2.hdslb.com/bfs/face/eceb8fa58c41b7cd733bebafcd7c1f3e33b37b07.jpg", + "position": 4, + "join_time": 1754564385, + "link_id": "44478528", + "gender": 0, + "room_id": 1937830041, + "fans_num": 0, + "display_name": "暴躁小辣jo", + "biz_extra_data": { + "multi_conn": { + "price": 96800, + "price_text": "968" + } + }, + "join_time_ts": 0 + }, + { + "uid": 475912512, + "uname": "抵抗Resistance", + "face": "https://i0.hdslb.com/bfs/face/12c1cd0df2ee6e6bb09b279b0553cdc9ae4af4f0.jpg", + "position": 5, + "join_time": 1754564774, + "link_id": "44478875", + "gender": -1, + "room_id": 23090250, + "fans_num": 0, + "display_name": "抵抗Resistance", + "biz_extra_data": { + "multi_conn": { + "price": 79200, + "price_text": "792" + } + }, + "join_time_ts": 0 + } + ], + "stream_control": null, + "version": 1754568295421, + "session_status": 1, + "business_label": "universal_multi_conn", + "invoking_time": 2, + "members_version": 1262102210, + "room_status": 1, + "system_time_unix": 1754568295, + "room_owner": 2077733317, + "session_start_at": "2025-08-07 18:59:06", + "session_start_at_ts": 3949, + "room_start_at": "2025-08-07 19:09:52", + "room_start_at_ts": 3303, + "trace_id": "55df19c042f09f5c625d7b8b60689496", + "biz_extra_data": { + "multi_conn": { + "show_score": 1, + "support_full_zoom": 2 + } + }, + "channel_users": [ + 1950658, + 2077733317, + 1035559935, + 3546581471070432, + 3546768203582225, + 475912512 + ] + } +} +``` + +</details> + +#### ??? (PLAY_TOGETHER) + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "PLAY_TOGETHER", + "data": { + "ruid": 29857468, + "roomid": 8618057, + "action": "switch_off", + "uid": 0, + "timestamp": 1673690546, + "message": "", + "message_type": 0, + "jump_url": "", + "web_url": "", + "apply_number": 0, + "refresh_tool": false, + "cur_fleet_num": 0, + "max_fleet_num": 0 + } +} +``` + +```json +{ + "cmd": "PLAY_TOGETHER", + "data": { + "ruid": 29857468, + "roomid": 8618057, + "action": "switch_off", + "uid": 0, + "timestamp": 1673690549, + "message": "系统提示:主播已切换分区", + "message_type": 3, + "jump_url": "", + "web_url": "", + "apply_number": 0, + "refresh_tool": true, + "cur_fleet_num": 0, + "max_fleet_num": 0 + } +} +``` + +</details> + +#### ??? (PLAYTOGETHER_ICON_CHANGE) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `PLAYTOGETHER_ICON_CHANGE` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| area_id | num | 直播分区id | | +| has_perm | num | | | +| show_count | num | | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "PLAYTOGETHER_ICON_CHANGE", + "data": { + "area_id": 40, + "has_perm": 0, + "show_count": 0 + } +} +``` + +</details> + +#### 直播小助手? (ANCHOR_BROADCAST) + +第一次达到了某种条件下发。 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `ANCHOR_BROADCAST` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| sender | str | 标题? | `直播小助手` | +| msg | str | 提示消息 | | +| platform | num | 平台标识? | `0` | +| button\_info | obj | 按钮信息? | | +| milestone\_type | str | 里程碑类型? | `session_livetime`,`first_share`,`session_share` | +| milestone\_value | num | 里程值? | | +| milestone\_index | num | 里程碑类型的索引? | `1`,`5`,`6`,`7` | + +`data.button_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| button\_name | str | | | +| blink_button_type | str | | | +| blink_button_target | str | | | +| blink_button_extra | str | | | +| blink_button_label | num | | | +| hime_button_type | str | | | +| hime_button_target | str | | | +| hime_button_extra | str | | | +| hime\_button\_h5\_type | str | | | +| hime_button_label | num | | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "ANCHOR_BROADCAST", + "data": { + "sender": "直播小助手", + "msg": "恭喜你,开播时长达到180分钟!", + "platform": 0, + "button_info": { + "button_name": "", + "blink_button_type": "", + "blink_button_target": "", + "blink_button_extra": "", + "blink_button_label": 0, + "hime_button_type": "", + "hime_button_target": "", + "hime_button_extra": "", + "hime_button_h5_type": "", + "hime_button_label": 0 + }, + "milestone_type": "session_livetime", + "milestone_value": 10800, + "milestone_index": 6 + } +} +``` + +</details> + +#### 直播小助手? (ANCHOR_HELPER_DANMU) + +几乎与`ANCHOR_BROADCAST`一同下发。 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `ANCHOR_HELPER_DANMU` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| sender | str | 标题? | `直播小助手` | +| msg | str | 提示消息 | | +| platform | num | 平台标识? | | +| button\_platform | num | | | +| button\_name | str | | | +| button\_target | str | | | +| button\_label | num | | | +| report\_type | str | 上报类型? | | +| report | str | | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "ANCHOR_HELPER_DANMU", + "data": { + "sender": "直播小助手", + "msg": "恭喜你,开播时长达到150分钟!", + "platform": 3, + "button_platform": 0, + "button_name": "", + "button_target": "", + "button_label": 0, + "report_type": "milestone", + "report": "session_livetime:5:9000" + } +} +``` + +</details> + +#### 直播进度条节点标签 (PLAY_TAG) + +注: 在特定直播间的特定情况下发。 + +例如: 在[直播间6](https://live.bilibili.com/6)内,有人打出了某种操作。 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `PLAY_TAG` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| tag\_id | num | 标签 ID | | +| pic | str | 标签图标 | 通常显示于进度条之上 | +| timestamp | num | UNIX 秒时间戳 | | +| type | str | 操作类型 | `ADD`:添加 | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "PLAY_TAG", + "data": { + "tag_id": 367751, + "pic": "https://i0.hdslb.com/bfs/live/0e04525fee9ea6ea6973e8bd1116d9f1f6501d37.png", + "timestamp": 1740319807, + "type": "ADD" + } +} +``` + +</details> + +#### 冲榜提示卡 (POPULAR_RANK_GUIDE_CARD) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `POPULAR_RANK_GUIDE_CARD` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| ruid | num | 主播uid | | +| title | str | 提示标题 | | +| sub_text | str | 提示副标题 | | +| icon_img | str | 提示卡图标 | 主播头像 | +| gift_id | num | 礼物id | | +| countdown | num | 显示时间 | | +| popup_title | str | 提示文本 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "POPULAR_RANK_GUIDE_CARD", + "data": { + "ruid": 194484313, + "title": "目前人气榜NO.1", + "sub_text": "帮我投喂人气票冲榜吧~", + "icon_img": "https://i1.hdslb.com/bfs/face/84a861facfa041b46f7a30897e9ed3f2e05e0519.jpg", + "gift_id": 33988, + "countdown": 10, + "popup_title": "投喂一个人气票帮助主播打榜~" + } +} +``` + +</details> + +#### ??? (RECALL_DANMU_MSG) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `RECALL_DANMU_MSG` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| recall_type | num | 类型? | `2` | +| target_id | num | | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "RECALL_DANMU_MSG", + "data": { + "recall_type": 2, + "target_id": 525503743 + } +} +``` + +</details> + +#### 直播剪辑 (OTHER_SLICE_LOADING_RESULT) + +注: 点击剪辑按钮后的几秒内下发,目前只有网页端有这个按钮,且部分直播间可用(2025-02-20记录)。 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `OTHER_SLICE_LOADING_RESULT` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| data | array | 剪辑片段数据 | | +| live_key | str | 标记直播场次的key | 未验证真实性 | + +`data.data` 数组: + +| 索引 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| 0 | obj | 单个片段数据 | | + +`data.data[i]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| start\_time | num | 片段开始时间时间戳 | UNIX 秒时间戳 | +| end\_time | num | 片段结束时间时间戳 | UNIX 秒时间戳 | +| stream | str | 从开始时间到结束时间内的直播视频片段 | 需要使用浏览器用户代理字符串,特别是m3u文件内的视频链接 | +| type | num | 类型? | | +| ban\_ec | bool | ? | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "OTHER_SLICE_LOADING_RESULT", + "data": { + "data": [ + { + "start_time": 1740037738, + "end_time": 1740038916, + "stream": "https://jssz-boss.hdslb.com/live2arc_anchor_video/vod_579433011406177273.m3u?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=y4zI4XTQzlOkmSKg%2F20250220%2Fjssz%2Fs3%2Faws4_request&X-Amz-Date=20250220T080858Z&X-Amz-Expires=7200&X-Amz-SignedHeaders=host&X-Amz-Signature=52be315e8e7def8e11f86d3c6d4952362725c3c087a433780926bc0e8c88c2e1", + "type": 0, + "ban_ec": false + } + ], + "live_key": "579433011406177273" + } +} +``` + +</details> + +#### 有人购买主播推荐商品 (GOTO_BUY_FLOW) + +用户昵称会打星号(`*`)显示。 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `GOTO_BUY_FLOW` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| text | str | 去购买提示 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "GOTO_BUY_FLOW", + "data": { + "text": "回**正在去买" + } +} +``` + +</details> + +#### 热抢提示 (HOT_BUY_NUM) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `HOT_BUY_NUM` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| num | num | 热抢数量 | | +| goods_id | str | 商品id | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "HOT_BUY_NUM", + "data": { + "num": 81, + "goods_id": "1817875296579985408" + } +} +``` + +</details> + +#### 荣耀等级通知 (WEALTH_NOTIFY) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `WEALTH_NOTIFY` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| flag | num | 标志? | | +| info | obj | 信息 | | + +`data.info`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| effect_key | num | (?) | | +| has_items_changed | num | (?) | | +| level | num | 达到的等级 | | +| send_time | num | 发送时间 | UNIX 毫秒时间戳 | +| status | num | 状态? | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "WEALTH_NOTIFY", + "data": { + "flag": 3, + "info": { + "effect_key": 1073, + "has_items_changed": 1, + "level": 5, + "send_time": 1743337942833, + "status": 1 + } + } +} +``` + +</details> + +#### ??? (USER_PANEL_RED_ALARM) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `USER_PANEL_RED_ALARM` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| module | str | (?) | | +| alarm_num | num | (?) | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "USER_PANEL_RED_ALARM", + "data": { + "module": "user_head_dot", + "alarm_num": 1 + } +} +``` + +</details> + +#### ??? (GIFT_BOARD_RED_DOT) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `GIFT_BOARD_RED_DOT` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| categoryL1 | str | (?) | 作用尚不明确 | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "GIFT_BOARD_RED_DOT", + "data": { + "categoryL1": "3" + } +} +``` + +</details> + +#### 粉丝勋章更新 (MESSAGEBOX_USER_MEDAL_CHANGE) + +升级或点亮时下发。 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `MESSAGEBOX_USER_MEDAL_CHANGE` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| type | num | 提示类型 | 1:升级<br />2:点亮 | +| uid | num | 用户mid | | +| up_uid | num | 主播mid | | +| medal_level | num | 粉丝勋章等级 | | +| medal_name | str | 粉丝勋章名称 | | +| medal_color_start | num | 十进制粉丝勋章起始颜色 | | +| medal_color_end | num | 十进制粉丝勋章结束颜色 | | +| medal_color_border | num | 十进制粉丝勋章边框颜色 | | +| is_lighted | num | 是否点亮? | 1:点亮? | +| is_lighted_v2 | bool | 是否点亮v2? | | +| guard_level | num | 大航海等级 | | +| unlock | num | (?) | | +| unlock_level | num | (?) | | +| multi_unlock_level | str | (?) | | +| upper_bound_content | str | 提示内容 | | +| uinfo_medal | obj | 粉丝勋章信息 | 参见 [指定用户的所有粉丝勋章信息](../user/medals.md#指定用户的所有粉丝勋章信息) `data.list[n].uinfo_medal` 对象 | +| effect_id | num | (?) | | + +`data.uinfo_medal` 对象: + +参见 [指定用户的所有粉丝勋章信息](../user/medals.md#指定用户的所有粉丝勋章信息) json回复的 `data.list[n].uinfo_medal` 对象。 + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "MESSAGEBOX_USER_MEDAL_CHANGE", + "data": { + "type": 2, + "uid": 438160221, + "up_uid": 407045223, + "medal_level": 3, + "medal_name": "研究猿", + "medal_color_start": 6067854, + "medal_color_end": 6067854, + "medal_color_border": 6067854, + "is_lighted": 1, + "is_lighted_v2": true, + "guard_level": 0, + "unlock": 0, + "unlock_level": 0, + "multi_unlock_level": "", + "upper_bound_content": "", + "uinfo_medal": { + "name": "研究猿", + "level": 3, + "color_start": 6067854, + "color_end": 6067854, + "color_border": 6067854, + "color": 0, + "id": 0, + "typ": 0, + "is_light": 1, + "ruid": 407045223, + "guard_level": 0, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#5762A799", + "v2_medal_color_end": "#5762A799", + "v2_medal_color_border": "#5762A799", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + }, + "effect_id": 1861 + } +} +``` + +</details> + +#### 获得粉丝勋章 (MESSAGEBOX_USER_GAIN_MEDAL) + +获得时下发。 + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `MESSAGEBOX_USER_GAIN_MEDAL` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| type | num | 类型 | 0 | +| uid | num | 用户mid | | +| up_uid | num | 主播uid | | +| medal_id | num | 勋章id | | +| medal_name | str | 勋章名称 | | +| medal_level | num | 勋章等级 | | +| medal_color | num | 勋章颜色 | | +| medal_color_start | num | 十进制勋章起始颜色 | | +| medal_color_end | num | 十进制勋章结束颜色 | | +| medal_color_border | num | 十进制勋章边框颜色 | | +| msg_title | str | 消息标题 | | +| msg_content | str | 消息内容 | | +| normal_color | num | (?) | | +| highlight_color | num | (?) | | +| intimacy | num | 当前亲密度 | | +| next_intimacy | num | 升级所需亲密度 | | +| today_feed | num | 今日亲密度 | | +| day_limit | num | 今日亲密度上限 | | +| is_wear | num | (?) | | +| guard_level | num | 大航海等级 | | +| is_received | num | (?) | | +| is_lighted | num | 是否点亮? | 1:点亮? | +| is_lighted_v2 | bool | 是否点亮v2? | | +| toast | str | 提示 | | +| fan_name | str | 粉丝名称 | | +| uinfo_medal | obj | 粉丝勋章信息 | 参见 [指定用户的所有粉丝勋章信息](../user/medals.md#指定用户的所有粉丝勋章信息) `data.list[n].uinfo_medal` 对象 | + +`data.uinfo_medal` 对象: + +参见 [指定用户的所有粉丝勋章信息](../user/medals.md#指定用户的所有粉丝勋章信息) json回复的 `data.list[n].uinfo_medal` 对象。 + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "MESSAGEBOX_USER_GAIN_MEDAL", + "data": { + "type": 0, + "uid": 438160221, + "up_uid": 11602644, + "medal_id": 19252517, + "medal_name": "广药", + "medal_level": 1, + "medal_color": 6067854, + "medal_color_start": 6067854, + "medal_color_end": 6067854, + "medal_color_border": 6067854, + "msg_title": "恭喜你获得【WuGuangYao】的粉丝勋章~", + "msg_content": "获得100点亲密度\n你的粉丝勋章达到1级", + "normal_color": 7697781, + "highlight_color": 16478873, + "intimacy": 100, + "next_intimacy": 201, + "today_feed": 100, + "day_limit": 2000, + "is_wear": 0, + "guard_level": 0, + "is_received": 1, + "is_lighted": 1, + "is_lighted_v2": true, + "toast": "成功入团并关注主播,得1级大礼包", + "fan_name": "weatfe", + "uinfo_medal": { + "name": "广药", + "level": 1, + "color_start": 6067854, + "color_end": 6067854, + "color_border": 6067854, + "color": 6067854, + "id": 19252517, + "typ": 0, + "is_light": 1, + "ruid": 11602644, + "guard_level": 0, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#5762A799", + "v2_medal_color_end": "#5762A799", + "v2_medal_color_border": "#5762A799", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + } + } +} +``` + +</details> + +#### 粉丝团戳一戳礼物通知 (FANS_CLUB_POKE_GIFT_NOTICE) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `FANS_CLUB_POKE_GIFT_NOTICE` | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| icon | str | 图标 | | +| uface | str | 头像 | | +| bg_img_url | str | 背景图片 | | +| text | str | 提示文本 | | +| highlight_text | str | 高亮文本? | | +| button_text | str | 按钮文本 | | +| display_duration | num | 显示时间? | | +| room_id | num | 房间号 | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "FANS_CLUB_POKE_GIFT_NOTICE", + "data": { + "icon": "https://i0.hdslb.com/bfs/live/37a2fe03f2af95928c67cbac889e10dab6f7d42a.png", + "uface": "https://i0.hdslb.com/bfs/face/member/noface.jpg", + "bg_img_url": "https://i0.hdslb.com/bfs/live/fbe99002b5914157d783f8e07f021e2fd6ba5c1b.png", + "text": "主播戳了戳你~投喂礼物获5倍亲密度加成", + "highlight_text": "5倍亲密度加成", + "button_text": "去投喂", + "display_duration": 8, + "room_id": 1899237171 + } +} +``` + +</details> + +#### ??? (master_qn_strategy_chg) + +**JSON消息:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| cmd | str | `master_qn_strategy_chg` | | +| data | str | 信息本体 | JSON文本 | + +`data` JSON解析后对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| mtime | num | (?) | Unix秒时间戳 | +| scatter | arr | (?) | | + +**示例:** + +<details> +<summary>查看消息示例:</summary> + +```json +{ + "cmd": "master_qn_strategy_chg", + "data": "{\"mtime\":1744380444,\"scatter\":[0,300]}" +} +``` + +</details> diff --git a/bb-api-collect/docs/live/recommend.md b/bb-api-collect/docs/live/recommend.md new file mode 100644 index 0000000000..edbf016c4c --- /dev/null +++ b/bb-api-collect/docs/live/recommend.md @@ -0,0 +1,717 @@ +# 直播推荐 + +## 主页获取直播推荐 + +> https://api.live.bilibili.com/xlive/web-interface/v1/webMain/getMoreRecList + +*请求方法: GET* + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------ | ------ | ---------- | ------ | ---- | +| platform | string | 平台类型 | 必要 | 默认为 `web`, 实测可为任意非空串 | +| web_location | string | `333.1007` | 非必要 | | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | -------- | ---- | +| code | number | 返回值 | 0: 成功 | +| message | string | 错误信息 | 默认为 `0` | +| ttl | number | 1 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------- | ------ | ------------- | -------- | +| recommend_room_list | Array | 推荐房间列表 | 套了个娃 | +| top_room_id | number | 置顶直播间号? | | + +`data` 对象中 `recommend_room_list` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------------------- | -------------- | ---------------- | ---- | +| head_box | object \| null | 头像框 | 无则为 `null` | +| area_v2_id | number | 分区 ID | | +| area_v2_parent_id | number | 父分区 ID | | +| area_v2_name | string | 分区名称 | | +| area_v2_parent_name | string | 父分区名称 | | +| broadcast_type | number | 广播类型? | | +| cover | string | 封面 URL | | +| link | string | 直播间链接 | 仅 `pathname` 与 `query` 部分 | +| online | number | 观看人数 | | +| pendant_Info | object | ??? | 作用尚不明确 | +| roomid | number | 直播间 ID | | +| title | string | 直播间标题 | | +| uname | string | 主播用户名 | | +| face | string | 主播头像 URL | | +| verify | object | 认证信息 | 参见 [用户基本信息](../user/info.md) | +| uid | number | 主播用户 mid | | +| keyframe | string | 关键帧 URL | | +| is_auto_play | number | 是否自动播放? | | +| head_box_type | number | 头像框类型? | | +| flag | number | 标记? | 作用尚不明确 | +| session_id | string | 会话 ID? | 格式为: 本次请求相同的小写无分隔 UUID + 下划线 + 大写以连字符分隔的 UUID | +| show_callback | string | 展示回调 URL? | | +| click_callback | string | 点击回调 URL? | | +| special_id | number | 特殊 ID? | 作用尚不明确 | +| watched_show | object | 观看展示 | 见下 | +| is_nft | number | 是否为 NFT 头像? | | +| nft_dmark | string | ??? | 作用尚不明确 | +| is_ad | boolean | 是否为广告 | | +| ad_transparent_content | unknown | ??? | 作用尚不明确 | +| show_ad_icon | boolean | 显示广告图标 | | +| status | boolean | 状态? | 作用尚不明确 | +| followers | number | 0 | 作用尚不明确 | + +`recommend_room_list` 数组中的对象中的 `watched_show` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ------- | -------- | ---- | +| switch | boolean | ??? | 作用尚不明确 | +| num | number | 看过人数 | | +| text_small | string | 小文本 | xxx | +| text_large | string | 大文本 | xxx人看过 | +| icon | string | 图标 URL | 浅色线条眼睛图标 | +| icon_location | number | 0 | | +| icon_web | string | 图标 URL | 深色线条眼睛图标 (Web 端) | + +**示例:** + +```shell +curl -G 'https://api.live.bilibili.com/xlive/web-interface/v1/webMain/getMoreRecList' \ +--url-query 'platform=web' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "recommend_room_list": [ + { + "head_box": null, + "area_v2_id": 237, + "area_v2_parent_id": 6, + "area_v2_name": "怀旧游戏", + "area_v2_parent_name": "单机游戏", + "broadcast_type": 0, + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/34aedc9409c0abaf622fdb9c6137896b8a9f95d0.jpg", + "link": "/923833?hotRank=0", + "online": 262700, + "pendant_Info": {}, + "roomid": 923833, + "title": "融合版斗蛐蛐s3.5赛季!", + "uname": "沉默寡言白河愁", + "face": "https://i0.hdslb.com/bfs/face/14169798ca31108e4441e790c14b24706def67a3.jpg", + "verify": { + "role": 1, + "desc": "bilibili 知名游戏UP主、直播高能主播", + "type": 0 + }, + "uid": 34646754, + "keyframe": "https://i0.hdslb.com/bfs/live-key-frame/keyframe02071535000000923833okbn8y.jpg", + "is_auto_play": 1, + "head_box_type": 0, + "flag": 0, + "session_id": "4b58e9bf85ef0539525f1c7b1467a5b8_9A44BEBD-CAEB-46AD-8FD7-B91BA8471EAA", + "group_id": 1000217, + "show_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_9A44BEBD-CAEB-46AD-8FD7-B91BA8471EAA&group_id=1000217&biz=live&event_id=live_card_show&rule_key=&special_id=0&roomid=923833&parent_id=6&area_id=237&page=0&position=1&platform=web", + "click_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_9A44BEBD-CAEB-46AD-8FD7-B91BA8471EAA&group_id=1000217&biz=live&event_id=live_card_click&rule_key=&special_id=0&roomid=923833&parent_id=6&area_id=237&page=0&position=1&platform=web", + "special_id": 0, + "watched_show": { + "switch": true, + "num": 30460, + "text_small": "3.0万", + "text_large": "3.0万人看过", + "icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "icon_location": 0, + "icon_web": "https://i0.hdslb.com/bfs/live/8d9d0f33ef8bf6f308742752d13dd0df731df19c.png" + }, + "is_nft": 0, + "nft_dmark": "", + "is_ad": false, + "ad_transparent_content": null, + "show_ad_icon": false, + "status": false, + "followers": 0 + }, + { + "head_box": { + "name": "大乱斗乱斗之王", + "value": "https://i0.hdslb.com/bfs/live/fc28a2a4123154012e0ce3da1273de5f17e81b24.png", + "desc": "" + }, + "area_v2_id": 817, + "area_v2_parent_id": 5, + "area_v2_name": "男声电台", + "area_v2_parent_name": "电台", + "broadcast_type": 0, + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/b15e3a1045321a7ffa7da08a47a276ca37557ef1.jpg", + "link": "/32190922?hotRank=0", + "online": 45487, + "pendant_Info": { + "2": { + "type": "mobile_index_badge", + "name": "福佑嘉年", + "position": 2, + "text": "省级亚军", + "bg_color": "#FB9E60", + "bg_pic": "http://i0.hdslb.com/bfs/live/13819a59895263cb25cc2ead3fecfaa3e864aac8.png", + "pendant_id": 1750, + "priority": 200, + "created_at": 1738512313 + } + }, + "roomid": 32190922, + "title": "我想我们会幸福美满", + "uname": "黑羊Klein", + "face": "https://i2.hdslb.com/bfs/face/307c62a8b30a6dcfc02e9670e5dc10d0ecec6921.jpg", + "verify": { + "role": 0, + "desc": "", + "type": -1 + }, + "uid": 1989648419, + "keyframe": "https://i0.hdslb.com/bfs/live-key-frame/keyframe02071536000032190922ma6cnx.jpg", + "is_auto_play": 0, + "head_box_type": 1, + "flag": 0, + "session_id": "4b58e9bf85ef0539525f1c7b1467a5b8_178A3B8F-86C1-4831-9DBB-9788C2445752", + "group_id": 1000217, + "show_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_178A3B8F-86C1-4831-9DBB-9788C2445752&group_id=1000217&biz=live&event_id=live_card_show&rule_key=&special_id=0&roomid=32190922&parent_id=5&area_id=817&page=0&position=2&platform=web", + "click_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_178A3B8F-86C1-4831-9DBB-9788C2445752&group_id=1000217&biz=live&event_id=live_card_click&rule_key=&special_id=0&roomid=32190922&parent_id=5&area_id=817&page=0&position=2&platform=web", + "special_id": 0, + "watched_show": { + "switch": true, + "num": 491, + "text_small": "491", + "text_large": "491人看过", + "icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "icon_location": 0, + "icon_web": "https://i0.hdslb.com/bfs/live/8d9d0f33ef8bf6f308742752d13dd0df731df19c.png" + }, + "is_nft": 0, + "nft_dmark": "", + "is_ad": false, + "ad_transparent_content": null, + "show_ad_icon": false, + "status": false, + "followers": 0 + }, + { + "head_box": null, + "area_v2_id": 654, + "area_v2_parent_id": 2, + "area_v2_name": "诛仙世界", + "area_v2_parent_name": "网游", + "broadcast_type": 0, + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/fdad2cfb408510df56a01af66254f630ee4b86b8.jpg", + "link": "/25959685?hotRank=0", + "online": 2151, + "pendant_Info": {}, + "roomid": 25959685, + "title": "免费接所有职业,死灵渊!只要收益", + "uname": "哦-是大一啊", + "face": "https://i1.hdslb.com/bfs/face/f83290ab5667f9c1ed778fb9c7c9cf6bf7624d4e.jpg", + "verify": { + "role": 0, + "desc": "", + "type": -1 + }, + "uid": 361517464, + "keyframe": "https://i0.hdslb.com/bfs/live-key-frame/keyframe02071535000025959685tx1grb.jpg", + "is_auto_play": 1, + "head_box_type": 0, + "flag": 0, + "session_id": "4b58e9bf85ef0539525f1c7b1467a5b8_FB0DABE2-6A09-4EB7-8D2B-A4F892243A96", + "group_id": 1000217, + "show_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_FB0DABE2-6A09-4EB7-8D2B-A4F892243A96&group_id=1000217&biz=live&event_id=live_card_show&rule_key=&special_id=0&roomid=25959685&parent_id=2&area_id=654&page=0&position=3&platform=web", + "click_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_FB0DABE2-6A09-4EB7-8D2B-A4F892243A96&group_id=1000217&biz=live&event_id=live_card_click&rule_key=&special_id=0&roomid=25959685&parent_id=2&area_id=654&page=0&position=3&platform=web", + "special_id": 0, + "watched_show": { + "switch": true, + "num": 269, + "text_small": "269", + "text_large": "269人看过", + "icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "icon_location": 0, + "icon_web": "https://i0.hdslb.com/bfs/live/8d9d0f33ef8bf6f308742752d13dd0df731df19c.png" + }, + "is_nft": 0, + "nft_dmark": "", + "is_ad": false, + "ad_transparent_content": null, + "show_ad_icon": false, + "status": false, + "followers": 0 + }, + { + "head_box": { + "name": "钻石传说", + "value": "https://i0.hdslb.com/bfs/live/2007dc239982e909a3c9971c27968e5c0a872917.png", + "desc": "" + }, + "area_v2_id": 192, + "area_v2_parent_id": 5, + "area_v2_name": "聊天电台", + "area_v2_parent_name": "电台", + "broadcast_type": 0, + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/22f1fcac8d9764901005ae5867a8c6b589b93ac5.jpg", + "link": "/31169918?hotRank=0", + "online": 27764, + "pendant_Info": {}, + "roomid": 31169918, + "title": "东北最后的温柔", + "uname": "关关-苏苏冠", + "face": "https://i2.hdslb.com/bfs/face/14f5102417107a6535c11ec9ad99050f7d712a17.jpg", + "verify": { + "role": 0, + "desc": "", + "type": -1 + }, + "uid": 3537120278874479, + "keyframe": "https://i0.hdslb.com/bfs/live-key-frame/keyframe02071532000031169918qep44l.jpg", + "is_auto_play": 0, + "head_box_type": 1, + "flag": 0, + "session_id": "4b58e9bf85ef0539525f1c7b1467a5b8_3E272538-AA76-4953-BF21-5BB19ECFEE28", + "group_id": 1000217, + "show_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_3E272538-AA76-4953-BF21-5BB19ECFEE28&group_id=1000217&biz=live&event_id=live_card_show&rule_key=&special_id=0&roomid=31169918&parent_id=5&area_id=192&page=0&position=4&platform=web", + "click_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_3E272538-AA76-4953-BF21-5BB19ECFEE28&group_id=1000217&biz=live&event_id=live_card_click&rule_key=&special_id=0&roomid=31169918&parent_id=5&area_id=192&page=0&position=4&platform=web", + "special_id": 0, + "watched_show": { + "switch": true, + "num": 297, + "text_small": "297", + "text_large": "297人看过", + "icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "icon_location": 0, + "icon_web": "https://i0.hdslb.com/bfs/live/8d9d0f33ef8bf6f308742752d13dd0df731df19c.png" + }, + "is_nft": 0, + "nft_dmark": "", + "is_ad": false, + "ad_transparent_content": null, + "show_ad_icon": false, + "status": false, + "followers": 0 + }, + { + "head_box": null, + "area_v2_id": 82, + "area_v2_parent_id": 2, + "area_v2_name": "剑网3", + "area_v2_parent_name": "网游", + "broadcast_type": 0, + "cover": "https://i0.hdslb.com/bfs/live/user_cover/9551fbb571b35bac3702c47e955177f17cab5cd2.jpg", + "link": "/2849730?hotRank=0", + "online": 4008, + "pendant_Info": {}, + "roomid": 2849730, + "title": "午间陪伴花间刷币", + "uname": "o诡墨o", + "face": "https://i1.hdslb.com/bfs/face/43ab308f836eb352aa4d541b55aafab2fa4435aa.jpg", + "verify": { + "role": 0, + "desc": "", + "type": -1 + }, + "uid": 71574442, + "keyframe": "https://i0.hdslb.com/bfs/live-key-frame/keyframe02071535000002849730qo0792.jpg", + "is_auto_play": 1, + "head_box_type": 0, + "flag": 0, + "session_id": "4b58e9bf85ef0539525f1c7b1467a5b8_4BAFD91A-DDED-4655-BE47-064A6152BF9B", + "group_id": 1000217, + "show_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_4BAFD91A-DDED-4655-BE47-064A6152BF9B&group_id=1000217&biz=live&event_id=live_card_show&rule_key=&special_id=0&roomid=2849730&parent_id=2&area_id=82&page=0&position=5&platform=web", + "click_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_4BAFD91A-DDED-4655-BE47-064A6152BF9B&group_id=1000217&biz=live&event_id=live_card_click&rule_key=&special_id=0&roomid=2849730&parent_id=2&area_id=82&page=0&position=5&platform=web", + "special_id": 0, + "watched_show": { + "switch": true, + "num": 204, + "text_small": "204", + "text_large": "204人看过", + "icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "icon_location": 0, + "icon_web": "https://i0.hdslb.com/bfs/live/8d9d0f33ef8bf6f308742752d13dd0df731df19c.png" + }, + "is_nft": 0, + "nft_dmark": "", + "is_ad": false, + "ad_transparent_content": null, + "show_ad_icon": false, + "status": false, + "followers": 0 + }, + { + "head_box": { + "name": "迷梦幻境头像框", + "value": "https://i0.hdslb.com/bfs/garb/open/d272c8cdb2ab737f5aa3c1cf5a27db274e0ce034.png", + "desc": "" + }, + "area_v2_id": 744, + "area_v2_parent_id": 9, + "area_v2_name": "虚拟Singer", + "area_v2_parent_name": "虚拟主播", + "broadcast_type": 0, + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/6e68e5c4f3d720e6f14952174be848383b879dad.jpg", + "link": "/21603945?hotRank=0", + "online": 10606, + "pendant_Info": {}, + "roomid": 21603945, + "title": "听歌碎碎念!~", + "uname": "Minicatty", + "face": "https://i0.hdslb.com/bfs/face/812d9ea6f3420d5c58ff455408275563f03fb861.jpg", + "verify": { + "role": 7, + "desc": "bilibili 直播高能主播", + "type": 0 + }, + "uid": 423902976, + "keyframe": "https://i0.hdslb.com/bfs/live-key-frame/keyframe02071535000021603945pekr70.jpg", + "is_auto_play": 0, + "head_box_type": 2, + "flag": 0, + "session_id": "4b58e9bf85ef0539525f1c7b1467a5b8_56778C3F-4B14-4C78-8DF8-53721196E8D8", + "group_id": 1000217, + "show_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_56778C3F-4B14-4C78-8DF8-53721196E8D8&group_id=1000217&biz=live&event_id=live_card_show&rule_key=&special_id=0&roomid=21603945&parent_id=9&area_id=744&page=0&position=6&platform=web", + "click_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_56778C3F-4B14-4C78-8DF8-53721196E8D8&group_id=1000217&biz=live&event_id=live_card_click&rule_key=&special_id=0&roomid=21603945&parent_id=9&area_id=744&page=0&position=6&platform=web", + "special_id": 0, + "watched_show": { + "switch": true, + "num": 235, + "text_small": "235", + "text_large": "235人看过", + "icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "icon_location": 0, + "icon_web": "https://i0.hdslb.com/bfs/live/8d9d0f33ef8bf6f308742752d13dd0df731df19c.png" + }, + "is_nft": 0, + "nft_dmark": "", + "is_ad": false, + "ad_transparent_content": null, + "show_ad_icon": false, + "status": false, + "followers": 0 + }, + { + "head_box": null, + "area_v2_id": 80, + "area_v2_parent_id": 2, + "area_v2_name": "吃鸡行动", + "area_v2_parent_name": "网游", + "broadcast_type": 0, + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/fa7292a8741a40a612a1c466da58b7f9cc08f363.jpg", + "link": "/22976905?hotRank=0", + "online": 8536, + "pendant_Info": {}, + "roomid": 22976905, + "title": "全是细节!", + "uname": "菠萝鸽", + "face": "https://i1.hdslb.com/bfs/face/f073d24cbb992b4589825896de3fb9bc559ba180.jpg", + "verify": { + "role": 1, + "desc": "bilibili 知名游戏UP主、直播高能主播", + "type": 0 + }, + "uid": 1849164526, + "keyframe": "https://i0.hdslb.com/bfs/live-key-frame/keyframe020715350000229769056wy0mu.jpg", + "is_auto_play": 1, + "head_box_type": 0, + "flag": 0, + "session_id": "4b58e9bf85ef0539525f1c7b1467a5b8_CE3B32EC-E84D-4545-A693-97882454E0ED", + "group_id": 1000217, + "show_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_CE3B32EC-E84D-4545-A693-97882454E0ED&group_id=1000217&biz=live&event_id=live_card_show&rule_key=&special_id=0&roomid=22976905&parent_id=2&area_id=80&page=0&position=7&platform=web", + "click_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_CE3B32EC-E84D-4545-A693-97882454E0ED&group_id=1000217&biz=live&event_id=live_card_click&rule_key=&special_id=0&roomid=22976905&parent_id=2&area_id=80&page=0&position=7&platform=web", + "special_id": 0, + "watched_show": { + "switch": true, + "num": 919, + "text_small": "919", + "text_large": "919人看过", + "icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "icon_location": 0, + "icon_web": "https://i0.hdslb.com/bfs/live/8d9d0f33ef8bf6f308742752d13dd0df731df19c.png" + }, + "is_nft": 0, + "nft_dmark": "", + "is_ad": false, + "ad_transparent_content": null, + "show_ad_icon": false, + "status": false, + "followers": 0 + }, + { + "head_box": null, + "area_v2_id": 646, + "area_v2_parent_id": 10, + "area_v2_name": "生活杂谈", + "area_v2_parent_name": "生活", + "broadcast_type": 0, + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/833e4d5449bcb4e425eb6399e0ef71f06903d083.jpg", + "link": "/21291747?hotRank=0", + "online": 38125, + "pendant_Info": {}, + "roomid": 21291747, + "title": "哪吒抢了封神票房?", + "uname": "陈哥惜命天涯", + "face": "https://i1.hdslb.com/bfs/face/d2c7e9c9b918ec969b2e15a5f2194bae3acd966e.jpg", + "verify": { + "role": 0, + "desc": "", + "type": -1 + }, + "uid": 286563388, + "keyframe": "https://i0.hdslb.com/bfs/live-key-frame/keyframe0207153000002129174742tpke.jpg", + "is_auto_play": 0, + "head_box_type": 0, + "flag": 0, + "session_id": "4b58e9bf85ef0539525f1c7b1467a5b8_63BEC7F6-172E-46FC-BBAD-8CD3547AE6C1", + "group_id": 1000217, + "show_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_63BEC7F6-172E-46FC-BBAD-8CD3547AE6C1&group_id=1000217&biz=live&event_id=live_card_show&rule_key=&special_id=0&roomid=21291747&parent_id=10&area_id=646&page=0&position=8&platform=web", + "click_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_63BEC7F6-172E-46FC-BBAD-8CD3547AE6C1&group_id=1000217&biz=live&event_id=live_card_click&rule_key=&special_id=0&roomid=21291747&parent_id=10&area_id=646&page=0&position=8&platform=web", + "special_id": 0, + "watched_show": { + "switch": true, + "num": 3107, + "text_small": "3107", + "text_large": "3107人看过", + "icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "icon_location": 0, + "icon_web": "https://i0.hdslb.com/bfs/live/8d9d0f33ef8bf6f308742752d13dd0df731df19c.png" + }, + "is_nft": 0, + "nft_dmark": "", + "is_ad": false, + "ad_transparent_content": null, + "show_ad_icon": false, + "status": false, + "followers": 0 + }, + { + "head_box": { + "name": "Lirin兔耳娘 收藏集", + "value": "https://i2.hdslb.com/bfs/garb/open/41e2a2e3693f49e0b721c443fd784aa533456c49.png", + "desc": "" + }, + "area_v2_id": 745, + "area_v2_parent_id": 9, + "area_v2_name": "虚拟Gamer", + "area_v2_parent_name": "虚拟主播", + "broadcast_type": 0, + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/b444bc87fbe1b346184f061efaffff21b24371f1.jpg", + "link": "/23797026?hotRank=0", + "online": 13294, + "pendant_Info": {}, + "roomid": 23797026, + "title": "日v 萌新玩玩三角洲♡", + "uname": "樱咲奈央_Official", + "face": "https://i2.hdslb.com/bfs/face/163330968a4a5fc8f31e9da9e919bbc258ecf40c.jpg", + "verify": { + "role": 7, + "desc": "bilibili直播高能主播", + "type": 0 + }, + "uid": 1880188304, + "keyframe": "https://i0.hdslb.com/bfs/live-key-frame/keyframe020715310000237970260gnmn1.jpg", + "is_auto_play": 0, + "head_box_type": 2, + "flag": 0, + "session_id": "4b58e9bf85ef0539525f1c7b1467a5b8_691E1F11-4960-4707-92EF-0F0D996E434C", + "group_id": 1000217, + "show_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_691E1F11-4960-4707-92EF-0F0D996E434C&group_id=1000217&biz=live&event_id=live_card_show&rule_key=&special_id=0&roomid=23797026&parent_id=9&area_id=745&page=0&position=9&platform=web", + "click_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_691E1F11-4960-4707-92EF-0F0D996E434C&group_id=1000217&biz=live&event_id=live_card_click&rule_key=&special_id=0&roomid=23797026&parent_id=9&area_id=745&page=0&position=9&platform=web", + "special_id": 0, + "watched_show": { + "switch": true, + "num": 999, + "text_small": "999", + "text_large": "999人看过", + "icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "icon_location": 0, + "icon_web": "https://i0.hdslb.com/bfs/live/8d9d0f33ef8bf6f308742752d13dd0df731df19c.png" + }, + "is_nft": 0, + "nft_dmark": "", + "is_ad": false, + "ad_transparent_content": null, + "show_ad_icon": false, + "status": false, + "followers": 0 + }, + { + "head_box": null, + "area_v2_id": 624, + "area_v2_parent_id": 10, + "area_v2_name": "电子榨菜", + "area_v2_parent_name": "生活", + "broadcast_type": 0, + "cover": "https://i0.hdslb.com/bfs/live/user_cover/a8a7681eaf20e43e16444e502106a436eb0e454c.jpg", + "link": "/1831473323?hotRank=0", + "online": 6510, + "pendant_Info": {}, + "roomid": 1831473323, + "title": "粤语片-法证1", + "uname": "曦曦每天都开心呀", + "face": "https://i1.hdslb.com/bfs/face/aa2112252080ec2298ea51b129c842fea7ed58f5.jpg", + "verify": { + "role": 0, + "desc": "", + "type": -1 + }, + "uid": 1434707683, + "keyframe": "https://i0.hdslb.com/bfs/live-key-frame/keyframe020715350018314733230k1dhu.jpg", + "is_auto_play": 0, + "head_box_type": 0, + "flag": 0, + "session_id": "4b58e9bf85ef0539525f1c7b1467a5b8_947BC1A4-E0F4-4ECE-AE40-9D9817848F9A", + "group_id": 1000217, + "show_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_947BC1A4-E0F4-4ECE-AE40-9D9817848F9A&group_id=1000217&biz=live&event_id=live_card_show&rule_key=&special_id=0&roomid=1831473323&parent_id=10&area_id=624&page=0&position=10&platform=web", + "click_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_947BC1A4-E0F4-4ECE-AE40-9D9817848F9A&group_id=1000217&biz=live&event_id=live_card_click&rule_key=&special_id=0&roomid=1831473323&parent_id=10&area_id=624&page=0&position=10&platform=web", + "special_id": 0, + "watched_show": { + "switch": true, + "num": 1446, + "text_small": "1446", + "text_large": "1446人看过", + "icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "icon_location": 0, + "icon_web": "https://i0.hdslb.com/bfs/live/8d9d0f33ef8bf6f308742752d13dd0df731df19c.png" + }, + "is_nft": 0, + "nft_dmark": "", + "is_ad": false, + "ad_transparent_content": null, + "show_ad_icon": false, + "status": false, + "followers": 0 + }, + { + "head_box": { + "name": "帕里", + "value": "https://i0.hdslb.com/bfs/garb/item/7c9cd30bfab66e9490d8a03fc48754cdb12b4901.png", + "desc": "" + }, + "area_v2_id": 745, + "area_v2_parent_id": 9, + "area_v2_name": "虚拟Gamer", + "area_v2_parent_name": "虚拟主播", + "broadcast_type": 0, + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/bd898138564a7e892e05dd1ff9cf9c34bdd9cb5b.jpg", + "link": "/42512?hotRank=0", + "online": 11612, + "pendant_Info": {}, + "roomid": 42512, + "title": "【文明7】使臣,你去死一下,然后我发兵", + "uname": "优礼子Ghaast", + "face": "https://i0.hdslb.com/bfs/face/e3f05d5b7bf56c57f55026676da71cc487d93988.jpg", + "verify": { + "role": 7, + "desc": "bilibili直播高能主播", + "type": 0 + }, + "uid": 6141432, + "keyframe": "https://i0.hdslb.com/bfs/live-key-frame/keyframe020715350000000425126wxphk.jpg", + "is_auto_play": 0, + "head_box_type": 2, + "flag": 0, + "session_id": "4b58e9bf85ef0539525f1c7b1467a5b8_0517EBF3-EE5C-4967-A77A-9DB3F89A58A8", + "group_id": 1000217, + "show_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_0517EBF3-EE5C-4967-A77A-9DB3F89A58A8&group_id=1000217&biz=live&event_id=live_card_show&rule_key=&special_id=0&roomid=42512&parent_id=9&area_id=745&page=0&position=11&platform=web", + "click_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_0517EBF3-EE5C-4967-A77A-9DB3F89A58A8&group_id=1000217&biz=live&event_id=live_card_click&rule_key=&special_id=0&roomid=42512&parent_id=9&area_id=745&page=0&position=11&platform=web", + "special_id": 0, + "watched_show": { + "switch": true, + "num": 1998, + "text_small": "1998", + "text_large": "1998人看过", + "icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "icon_location": 0, + "icon_web": "https://i0.hdslb.com/bfs/live/8d9d0f33ef8bf6f308742752d13dd0df731df19c.png" + }, + "is_nft": 0, + "nft_dmark": "", + "is_ad": false, + "ad_transparent_content": null, + "show_ad_icon": false, + "status": false, + "followers": 0 + }, + { + "head_box": { + "name": "百人舰队主播头像", + "value": "https://i0.hdslb.com/bfs/vc/071eb10548fe9bc482ff69331983d94192ce9507.png", + "desc": "" + }, + "area_v2_id": 102, + "area_v2_parent_id": 2, + "area_v2_name": "最终幻想14", + "area_v2_parent_name": "网游", + "broadcast_type": 0, + "cover": "https://i0.hdslb.com/bfs/live/new_room_cover/9370e1bbda854c8ac3b9a2a9a6e960106f307580.jpg", + "link": "/1897222?hotRank=0", + "online": 80052, + "pendant_Info": { + "1": { + "type": "mobile_index_badge", + "name": "百人成就", + "position": 1, + "text": "", + "bg_color": "#FB9E60", + "bg_pic": "https://i0.hdslb.com/bfs/live/539ce26c45cd4019f55b64cfbcedc3c01820e539.png", + "pendant_id": 426, + "priority": 1, + "created_at": 1738857680 + } + }, + "roomid": 1897222, + "title": "鸟区pvp", + "uname": "猫姐姐nya", + "face": "https://i1.hdslb.com/bfs/face/acc5559db9494af780b05fbf05c158995c48d023.jpg", + "verify": { + "role": 1, + "desc": "bilibili 知名游戏UP主", + "type": 0 + }, + "uid": 41377819, + "keyframe": "https://i0.hdslb.com/bfs/live-key-frame/keyframe020715360000018972225sqtbh.jpg", + "is_auto_play": 1, + "head_box_type": 1, + "flag": 0, + "session_id": "4b58e9bf85ef0539525f1c7b1467a5b8_93F5FBE6-4F84-40C9-AEA1-149E9D5D366E", + "group_id": 1000217, + "show_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_93F5FBE6-4F84-40C9-AEA1-149E9D5D366E&group_id=1000217&biz=live&event_id=live_card_show&rule_key=&special_id=0&roomid=1897222&parent_id=2&area_id=102&page=0&position=12&platform=web", + "click_callback": "https://live-trace.bilibili.com/xlive/data-interface/v1/index/log?sessionID=4b58e9bf85ef0539525f1c7b1467a5b8_93F5FBE6-4F84-40C9-AEA1-149E9D5D366E&group_id=1000217&biz=live&event_id=live_card_click&rule_key=&special_id=0&roomid=1897222&parent_id=2&area_id=102&page=0&position=12&platform=web", + "special_id": 0, + "watched_show": { + "switch": true, + "num": 2930, + "text_small": "2930", + "text_large": "2930人看过", + "icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "icon_location": 0, + "icon_web": "https://i0.hdslb.com/bfs/live/8d9d0f33ef8bf6f308742752d13dd0df731df19c.png" + }, + "is_nft": 0, + "nft_dmark": "", + "is_ad": false, + "ad_transparent_content": null, + "show_ad_icon": false, + "status": false, + "followers": 0 + } + ], + "top_room_id": 0 + } +} +``` + +</details> diff --git a/bb-api-collect/docs/live/redpocket.md b/bb-api-collect/docs/live/redpocket.md new file mode 100644 index 0000000000..aafb1ffc02 --- /dev/null +++ b/bb-api-collect/docs/live/redpocket.md @@ -0,0 +1,126 @@ +# 直播间人气红包 + +## 获取指定直播间的红包信息 + +> https://api.live.bilibili.com/xlive/lottery-interface/v1/lottery/getLotteryInfoWeb + +*请求方式:GET* + +认证方式(可选):Cookie(SESSDATA) + +如果不携带Cookie信息,user_status将始终返回2(未参与)。 + +如果所查询的直播间无红包,popularity_red_pocket为null。 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | ---------------- | ------ | ---- | +| roomid | str | 直播间id | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | ---------- | ------------- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | 0:成功 | +| ttl | num | TimeToLive | 正常为1 | +| data | object | 返回数据 | | + +`data`对象: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---- | +| popularity_red_pocket | array | 人气红包信息 | | +| …… | ...... | …… | …… | + +`popularity_red_pocket`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------- | ---- | +| lot_id | num | 红包id | | +| sender_uid | num | 红包发送者uid | | +| sender_name | str | 红包发送者昵称 | | +| sender_face | str | 红包发送者头像 | | +| join_requirement | num | 参与条件? | | +| danmu | str | 参与红包时自动发送的弹幕内容 | | +| awards | array | 红包内容 | | +| lot_status | num | 未知 | | +| h5_url | str | 红包界面 | | +| user_status | num | 用户是否已参与 | 1:已参与 2:未参与 | +| lot_config_id | num | 未知 | | +| total_price | num | 红包总计价格 | | + +**示例:** + +查询房间号为24146996的直播间红包信息: + +```shell +curl -G 'https://api.live.bilibili.com/xlive/lottery-interface/v1/lottery/getLotteryInfoWeb?roomid=24146996' +``` + +<details> +<summary>查看响应示例:</summary> + +```json + +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "pk": null, + "guard": null, + "gift": null, + "storm": null, + "silver": null, + "activity_box": { + "ACTIVITY_ID": 0, + "ACTIVITY_PIC": "" + }, + "danmu": null, + "anchor": null, + "red_pocket": null, + "popularity_red_pocket": [{ + "lot_id": 622474, + "sender_uid": 1651908873, + "sender_name": "九泽糖糖の小蘑菇", + "sender_face": "http://i0.hdslb.com/bfs/face/c932c5c8b1607fe2e1da22b9780af19662dac939.jpg", + "join_requirement": 1, + "danmu": "老板大气!点点红包抽礼物!", + "awards": [{ + "gift_id": 31212, + "num": 2, + "gift_name": "打call", + "gift_pic": "https://s1.hdslb.com/bfs/live/f75291a0e267425c41e1ce31b5ffd6bfedc6f0b6.png" + }, { + "gift_id": 31214, + "num": 3, + "gift_name": "牛哇", + "gift_pic": "https://s1.hdslb.com/bfs/live/23475a7a6170e0d94ba52720e23060dc7604b735.png" + }, { + "gift_id": 31216, + "num": 3, + "gift_name": "i了i了", + "gift_pic": "https://s1.hdslb.com/bfs/live/1157a445487b39c0b7368d91b22290c60fa665b2.png" + }], + "start_time": 1645358104, + "end_time": 1645358284, + "last_time": 180, + "remove_time": 1645358299, + "replace_time": 1645358294, + "current_time": 1645358231, + "lot_status": 1, + "h5_url": "https://live.bilibili.com/p/html/live-app-red-envelope/popularity.html?is_live_half_webview=1\u0026hybrid_half_ui=1,5,100p,100p,000000,0,50,0,0,1;2,5,100p,100p,000000,0,50,0,0,1;3,5,100p,100p,000000,0,50,0,0,1;4,5,100p,100p,000000,0,50,0,0,1;5,5,100p,100p,000000,0,50,0,0,1;6,5,100p,100p,000000,0,50,0,0,1;7,5,100p,100p,000000,0,50,0,0,1;8,5,100p,100p,000000,0,50,0,0,1\u0026hybrid_rotate_d=1\u0026hybrid_biz=popularityRedPacket\u0026lotteryId=622474", + "user_status": 1, + "lot_config_id": 3, + "total_price": 1600 + }], + "activity_box_info": null + } +} +``` + +</details> diff --git a/bb-api-collect/docs/live/report.md b/bb-api-collect/docs/live/report.md new file mode 100644 index 0000000000..0dd3ec5682 --- /dev/null +++ b/bb-api-collect/docs/live/report.md @@ -0,0 +1,66 @@ +# 直播心跳上报 + +## 直播心跳 (Web端) + +> https://live-trace.bilibili.com/xlive/rdata-interface/v1/heartbeat/webHeartBeat + +*请求方式: GET* + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | --------- | ----------- | ----------------- | +| hb | str | heartbeat 正文 | 不必要 | 使用 base64 编码 | +| pf | str | 平台名称 | 不必要 | 可为 `web` | + +`hb` 解码参数: + +| 项 | 类型 | 内容 | 备注 | +| -- | ---- | ---- | ---- | +| 0 | num | 上次返回的 next_interval 值 | 默认 60 | +| 1 | num | 真实直播间号 | | +| 2 | num | 1 | 作用尚不明确 | +| 3 | num | 0 | 作用尚不明确 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | num | 返回值 | | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| next_interval | num | 下次心跳间隔 | | + +**示例:** + +上报直播间 26863308 的心跳 + +```shell +curl -G "https://live-trace.bilibili.com/xlive/rdata-interface/v1/heartbeat/webHeartBeat" \ +--data-urlencode "hb=$(echo "60|26863308|1|0" | base64 -)" \ +--data-urlencode "pf=web" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "next_interval": 60 + } +} +``` + +</details> diff --git a/bb-api-collect/docs/live/silent_user_manage.md b/bb-api-collect/docs/live/silent_user_manage.md new file mode 100644 index 0000000000..59502de7d9 --- /dev/null +++ b/bb-api-collect/docs/live/silent_user_manage.md @@ -0,0 +1,219 @@ +# 直播间禁言相关 API + +## 禁言观众 + +> https://api.live.bilibili.com/xlive/web-ucenter/v1/banned/AddSilentUser + +*请求方式:post* + +认证方式:Cookie(SESSDATA) + +鉴权方式:Cookie中`bili_jct`的值正确并与`csrf`相同 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | --- | ---------- | --- | ------------------ | +| room_id | str | 直播间Id | 必要 | | +| tuid | str | 要禁言的uid | 必要 | | +| msg | str | 要禁言的弹幕内容 | 非必要 | | +| mobile_app | str | web | 必要 | 定值"web"即可 | +| hour | num | 禁言时长 | 必要 | -1为永久,0为本场直播 | +| 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* + +认证方式:Cookie(SESSDATA) + +鉴权方式:Cookie中`bili_jct`的值正确并与`csrf`相同 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | --- | ---------- | --- | ------------------ | +| room_id | str | 直播间Id | 必要 | | +| ps | 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* + +认证方式:Cookie(SESSDATA) + +鉴权方式: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> diff --git a/bb-api-collect/docs/live/user.md b/bb-api-collect/docs/live/user.md new file mode 100644 index 0000000000..560998e99e --- /dev/null +++ b/bb-api-collect/docs/live/user.md @@ -0,0 +1,1248 @@ +# 直播间用户实用 API + +## 获取自己持有的粉丝勋章信息 + +> ~~https://api.live.bilibili.com/fans_medal/v5/live_fans_medal/iApiMedal~~ (旧) +> https://api.live.bilibili.com/xlive/app-ucenter/v1/user/GetMyMedals + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +**url 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | ------------ | ------ | ------------------------------------------------- | +| page_size | num | 每页的数量 | 必要 | 最大为 10,超出 `1002002:参数异常` | +| page | num | 返回结果页数 | 必要 | 两个参数不填返回空,只 page 不填或错误则 500 异常 | + +**json 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------------------------------- | +| code | num | 返回值 | 0:成功<br />-1002002:参数异常<br />-500:服务器异常 | +| message | str | 错误信息 | 默认为 "0" | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | ---------------- | ---- | +| count | num | 勋章数量 | | +| items | array | 粉丝勋章信息本体 | | +| page_info | obj | 页码信息 | | + +`items`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------ | ------ | -------------------- | -------------------------------------- | +| can_delete | bool | 可否删除 | | +| day_limit | num | 日经验上限(原力值) | eg: 1500 | +| guard_level | num | | | +| guard_medal_title | str | 加成状态 | | +| intimacy | num | 当前已得亲密度 | | +| is_lighted | num | 是否点亮 | 0:未点亮<br />1:点亮 | +| level | num | 勋章等级 | | +| medal_name | str | 勋章名 | | +| medal_color_border | num | 勋章边框颜色信息 | 颜色数值为 10 进制的 16 进制值(下同) | +| medal_color_start | num | 勋章起始颜色 | 从右往左渐变(20 级+勋章) | +| medal_color_end | num | 勋章结束颜色 | 从右往左渐变(20 级+勋章) | +| medal_id | num | 粉丝勋章 id | | +| next_intimacy | num | 升级所需经验 | | +| today_feed | num | 本日亲密度 | | +| roomid | num | 直播间房间号 | | +| status | num | | | +| target_id | number | up 主 mid | | +| target_name | str | up 主用户名 | | +| uname | str | up 主用户名 | | + +`page_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | -------------- | ---- | +| total_page | num | 页码总长度 | | +| cur_page | num | 当前返回的页码 | | + +**示例:** + +```shell +curl https://api.live.bilibili.com/xlive/app-ucenter/v1/user/GetMyMedals?page=1&page_size=10 \ +-b "SESSDATA=xxx" +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "items": [ + { + "can_deleted": true, + "day_limit": 1500, + "guard_level": 0, + "guard_medal_title": "未开启加成", + "intimacy": 9617, + "is_lighted": 0, + "level": 11, + "medal_name": "锦依卫", + "medal_color_border": 12632256, + "medal_color_end": 12632256, + "medal_color_start": 12632256, + "medal_id": 29245, + "next_intimacy": 10000, + "today_feed": 0, + "roomid": 1546736, + "status": 0, + "target_id": 36081646, + "target_name": "洛天依", + "uname": "洛天依" + } + ], + "page_info": { + "cur_page": 1, + "total_page": 1 + }, + "count": 1 + } +} +``` + +</details> + + +## 佩戴勋章 + +> https://api.live.bilibili.com/xlive/web-room/v1/fansMedal/wear + +*请求方式:POST* + +**表单参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ----------------------- | ------ | ---- | +| medal_id | num | 勋章 id | 必要 | | +| csrf | num | cookie 中 bili_jct 字段 | 必要 | | +| csrf_token | num | 同上 | 必要 | | + +**json 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | -------------- | +| code | num | 返回值 | 0:成功 | +| ttl | num | 1 | | +| message | str | 错误信息 | 默认为佩戴成功 | +| data | obj | 信息本体 | 默认为无 | + +**示例:** + +佩戴勋章 id 为 1 的勋章 + +```JavaScript +var madelForm = new FormData(); +madelForm.append("medal_id", 1); +madelForm.append("csrf", bili_jct); +madelForm.append("csrf_token", bili_jct); +$.ajax({ + url: "https://api.live.bilibili.com/xlive/web-room/v1/fansMedal/wear", + type: "POST", + data: madelForm, + dataType: "JSON", + processData: false, + contentType: false, + cache: false, + xhrFields: { + withCredentials: true + }, + success: function (){ + + } +}) +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "佩戴成功", + "ttl": 1, + "data": {} +} +``` + +</details> + +## ~~直播签到(已下线)~~ + +> https://api.live.bilibili.com/xlive/web-ucenter/v1/sign/DoSign + +_请求方式:GET_ + +认证方式:Cookie(SESSDATA)或 APP + +**json 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------ | +| code | num | 返回值 | 0:成功<br />1:参数错误 | +| ttl | num | 1 | | +| message | str | 错误信息 | 默认为当日签到奖励内容 | +| data | obj | 信息本体 | 默认为空 | + +(目前已下线) + +<details> +<summary>查看响应示例(下线后):</summary> + +```json +{ + "code": 1, + "message": "签到活动已下线,无法使用。", + "ttl": 1, + "data": null +} +``` + +</details> + + +## 本月直播签到信息 + +> https://api.live.bilibili.com/xlive/web-ucenter/v1/sign/WebGetSignInfo + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +**json 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功 | +| ttl | num | 1 | | +| message | str | 错误信息 | 默认为0 | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ----- | ---------------------------- | ------------------------ | +| text | str | 今日签到奖励信息 | 默认为空 | +| specialText | str | 连续签到奖励信息 | 默认为空 | +| status | num | 签到状态 | 0:未签到<br />1:已签到 | +| allDays | num | 当月天数 | | +| curMonth | num | 当前月 | | +| curYear | num | 当前年 | | +| curDay | num | 当前日 | | +| curData | str | 当前日期(格式化) | eg: 2023-2-19 | +| hadSignDays | num | 当月已签到天数 | 默认为0 | +| newTask | num | 作用未知 | 默认为0 | +| signDaysList | array | 当月已签到日列表 | 默认为空 | +| signBonusDaysList | array | 当月已签到且有特殊奖励日列表 | 默认为空 | + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "text": "3000点用户经验,2根辣条", + "specialText": "再签到7天可以获得50根辣条", + "status": 1, + "allDays": 28, + "curMonth": 2, + "curYear": 2023, + "curDay": 19, + "curDate": "2023-2-19", + "hadSignDays": 13, + "newTask": 0, + "signDaysList": [ + 2, + 3, + 4, + 5, + 6, + 7, + 11, + 13, + 14, + 15, + 17, + 18, + 19 + ], + "signBonusDaysList": [ + 6 + ] + } +} +``` + +</details> + +## 上月直播签到信息 + +> https://api.live.bilibili.com/sign/getLastMonthSignDays + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +**json 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功 | +| ttl | num | 1 | | +| message | str | 错误信息 | 默认为0 | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ----- | ---------------------------- | -------- | +| days | num | 上月天数 | | +| month | num | 上月月份值 | | +| hadSignDays | num | 上月已签到天数 | 默认为0 | +| signDaysList | array | 上月已签到日列表 | 默认为空 | +| signBonusDaysList | array | 上月已签到且有特殊奖励日列表 | 默认为空 | + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "month": 1, + "days": 31, + "hadSignDays": 20, + "signDaysList": [ + 1, + 2, + 3, + 6, + 7, + 8, + 10, + 12, + 13, + 14, + 15, + 18, + 20, + 23, + 24, + 25, + 26, + 27, + 30, + 31 + ], + "signBonusDaysList": [ + 7, + 31 + ] + } +} +``` + +</details> + +## 查询直播间贡献榜 + +> https://api.live.bilibili.com//xlive/general-interface/v1/rank/getOnlineGoldRank + +*请求方式:GET* + +认证方式:无 + +**url 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | -------------- | ------ | ------ | +| roomId | num | 房间号 | 必要 | | +| page | num | 返回结果页数 | 必要 | | +| pageSize | num | 返回结果页大小 | 必要 | 最大50 | +| ruid | num | 主播uid | 必要 | | + +**json 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---- | +| code | num | 返回值 | | +| message | str | 错误信息 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | + + + + + +`data`中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ----- | ------------ | ---- | +| onlineNum | num | 在线观众数量 | | +| OnlineRankItem | array | 结果 | | | + +`OnlineRankItem`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ------------ | ---- | +| userRank | num | 贡献值排名 | | +| uid | num | 用户id | | | +| name | str | 用户名字 | | | +| face | str | 用户头像 | | | +| score | num | 贡献值 | | | +| medalInfo | obj | 粉丝牌对象 | | | +| guard_level | num | 大航海类型 | | | +| wealth_level | num | 荣耀等级 | | | +| guard_level | num | 大航海类型 | | | +| uinfo | obj | 用户详细信息 | | | + +`uinfo`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ------------ | ---- | +| uid | num | 用户uid | | +| base | obj | 用户基本信息 | | | +| medal | obj | 用户粉丝牌 | | | +| face | str | 用户头像 | | | +| guard | obj | 大航海 | | | + +`guard`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | -------------- | ---- | +| level | num | 大航海类型 | | +| expired_str | str | 大航海到期时间 | | | + + +**示例:** + +查询`23174842`直播间的大航海成员 + + +```shell +curl 'https://api.live.bilibili.com//xlive/general-interface/v1/rank/getOnlineGoldRank?roomId=26854650&ruid=3493118494116797&page=3&pageSize=20' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "onlineNum": 45, + "OnlineRankItem": [ + { + "userRank": 1, + "uid": 36136895, + "name": "四月hallu", + "face": "https://i2.hdslb.com/bfs/face/5e5166ecc4c17d4dbc7a09dbb6bb749d9f537985.jpg", + "score": 3768, + "medalInfo": { + "guardLevel": 3, + "medalColorStart": 2951253, + "medalColorEnd": 10329087, + "medalColorBorder": 6809855, + "medalName": "钢板鹿", + "level": 29, + "targetId": 3493118494116797, + "isLight": 1 + }, + "guard_level": 3, + "wealth_level": 41, + "is_mystery": false, + "uinfo": { + "uid": 36136895, + "base": { + "name": "四月hallu", + "face": "https://i2.hdslb.com/bfs/face/5e5166ecc4c17d4dbc7a09dbb6bb749d9f537985.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": { + "name": "四月hallu", + "face": "https://i2.hdslb.com/bfs/face/5e5166ecc4c17d4dbc7a09dbb6bb749d9f537985.jpg" + }, + "origin_info": { + "name": "四月hallu", + "face": "https://i2.hdslb.com/bfs/face/5e5166ecc4c17d4dbc7a09dbb6bb749d9f537985.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": { + "name": "钢板鹿", + "level": 29, + "color_start": 2951253, + "color_end": 10329087, + "color_border": 6809855, + "color": 2951253, + "id": 0, + "typ": 0, + "is_light": 1, + "ruid": 3493118494116797, + "guard_level": 3, + "score": 50422604, + "guard_icon": "https://i0.hdslb.com/bfs/live/143f5ec3003b4080d1b5f817a9efdca46d631945.png", + "honor_icon": "", + "v2_medal_color_start": "#9660E5CC", + "v2_medal_color_end": "#9660E5CC", + "v2_medal_color_border": "#D47AFFFF", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#6C00A099", + "user_receive_count": 0 + }, + "wealth": { + "level": 41, + "dm_icon_key": "ChronosWealth_4.png" + }, + "title": null, + "guard": { + "level": 3, + "expired_str": "2025-07-07 23:59:59" + }, + "uhead_frame": null, + "guard_leader": null + } + }, + { + "userRank": 2, + "uid": 1182882611, + "name": "重生指令", + "face": "https://i2.hdslb.com/bfs/face/6762c39b424e6de5bf0292fd12a019201a501fb9.jpg", + "score": 1546, + "medalInfo": { + "guardLevel": 0, + "medalColorStart": 12632256, + "medalColorEnd": 12632256, + "medalColorBorder": 12632256, + "medalName": "雪狐咕", + "level": 24, + "targetId": 477792, + "isLight": 0 + }, + "guard_level": 3, + "wealth_level": 22, + "is_mystery": false, + "uinfo": { + "uid": 1182882611, + "base": { + "name": "重生指令", + "face": "https://i2.hdslb.com/bfs/face/6762c39b424e6de5bf0292fd12a019201a501fb9.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": { + "name": "重生指令", + "face": "https://i2.hdslb.com/bfs/face/6762c39b424e6de5bf0292fd12a019201a501fb9.jpg" + }, + "origin_info": { + "name": "重生指令", + "face": "https://i2.hdslb.com/bfs/face/6762c39b424e6de5bf0292fd12a019201a501fb9.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": { + "name": "雪狐咕", + "level": 24, + "color_start": 12632256, + "color_end": 12632256, + "color_border": 12632256, + "color": 1725515, + "id": 0, + "typ": 0, + "is_light": 0, + "ruid": 477792, + "guard_level": 0, + "score": 50010220, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#919298CC", + "v2_medal_color_end": "#919298CC", + "v2_medal_color_border": "#919298CC", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#6C6C7299", + "user_receive_count": 0 + }, + "wealth": { + "level": 22, + "dm_icon_key": "" + }, + "title": null, + "guard": { + "level": 3, + "expired_str": "2025-06-29 23:59:59" + }, + "uhead_frame": null, + "guard_leader": null + } + }, + { + "userRank": 3, + "uid": 35007043, + "name": "_单推哈鹿halluの狐狸", + "face": "https://i1.hdslb.com/bfs/face/6373a98189480661fc725494ab5ab68253522b8f.jpg", + "score": 1543, + "medalInfo": { + "guardLevel": 2, + "medalColorStart": 2951253, + "medalColorEnd": 10329087, + "medalColorBorder": 16771156, + "medalName": "钢板鹿", + "level": 29, + "targetId": 3493118494116797, + "isLight": 1 + }, + "guard_level": 2, + "wealth_level": 40, + "is_mystery": false, + "uinfo": { + "uid": 35007043, + "base": { + "name": "_单推哈鹿halluの狐狸", + "face": "https://i1.hdslb.com/bfs/face/6373a98189480661fc725494ab5ab68253522b8f.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": { + "name": "_单推哈鹿halluの狐狸", + "face": "https://i1.hdslb.com/bfs/face/6373a98189480661fc725494ab5ab68253522b8f.jpg" + }, + "origin_info": { + "name": "_单推哈鹿halluの狐狸", + "face": "https://i1.hdslb.com/bfs/face/6373a98189480661fc725494ab5ab68253522b8f.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": { + "name": "钢板鹿", + "level": 29, + "color_start": 2951253, + "color_end": 10329087, + "color_border": 16771156, + "color": 2951253, + "id": 0, + "typ": 0, + "is_light": 1, + "ruid": 3493118494116797, + "guard_level": 2, + "score": 50360413, + "guard_icon": "https://i0.hdslb.com/bfs/live/98a201c14a64e860a758f089144dcf3f42e7038c.png", + "honor_icon": "", + "v2_medal_color_start": "#9660E5CC", + "v2_medal_color_end": "#9660E5CC", + "v2_medal_color_border": "#D47AFFFF", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#6C00A099", + "user_receive_count": 0 + }, + "wealth": { + "level": 40, + "dm_icon_key": "ChronosWealth_4.png" + }, + "title": null, + "guard": { + "level": 2, + "expired_str": "2025-07-30 23:59:59" + }, + "uhead_frame": null, + "guard_leader": null + } + }, + { + "userRank": 7, + "uid": 44152084, + "name": "_柚_子_hallu", + "face": "https://i1.hdslb.com/bfs/face/137498c2c6a3231e5b6047af12a64bbd19627dcb.jpg", + "score": 324, + "medalInfo": { + "guardLevel": 3, + "medalColorStart": 398668, + "medalColorEnd": 6850801, + "medalColorBorder": 6809855, + "medalName": "钢板鹿", + "level": 26, + "targetId": 3493118494116797, + "isLight": 1 + }, + "guard_level": 3, + "wealth_level": 32, + "is_mystery": false, + "uinfo": { + "uid": 44152084, + "base": { + "name": "_柚_子_hallu", + "face": "https://i1.hdslb.com/bfs/face/137498c2c6a3231e5b6047af12a64bbd19627dcb.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": { + "name": "_柚_子_hallu", + "face": "https://i1.hdslb.com/bfs/face/137498c2c6a3231e5b6047af12a64bbd19627dcb.jpg" + }, + "origin_info": { + "name": "_柚_子_hallu", + "face": "https://i1.hdslb.com/bfs/face/137498c2c6a3231e5b6047af12a64bbd19627dcb.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": { + "name": "钢板鹿", + "level": 26, + "color_start": 398668, + "color_end": 6850801, + "color_border": 6809855, + "color": 398668, + "id": 0, + "typ": 0, + "is_light": 1, + "ruid": 3493118494116797, + "guard_level": 3, + "score": 50057285, + "guard_icon": "https://i0.hdslb.com/bfs/live/143f5ec3003b4080d1b5f817a9efdca46d631945.png", + "honor_icon": "", + "v2_medal_color_start": "#4775EFCC", + "v2_medal_color_end": "#4775EFCC", + "v2_medal_color_border": "#58A1F8FF", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + }, + "wealth": { + "level": 32, + "dm_icon_key": "" + }, + "title": null, + "guard": { + "level": 3, + "expired_str": "2025-06-27 23:59:59" + }, + "uhead_frame": null, + "guard_leader": null + } + }, + { + "userRank": 8, + "uid": 8242366, + "name": "翟赧hallu", + "face": "https://i1.hdslb.com/bfs/face/9b312f4146ca2c8a1d2e5468e345ecfb60be3874.jpg", + "score": 276, + "medalInfo": { + "guardLevel": 3, + "medalColorStart": 398668, + "medalColorEnd": 6850801, + "medalColorBorder": 6809855, + "medalName": "钢板鹿", + "level": 28, + "targetId": 3493118494116797, + "isLight": 1 + }, + "guard_level": 3, + "wealth_level": 35, + "is_mystery": false, + "uinfo": { + "uid": 8242366, + "base": { + "name": "翟赧hallu", + "face": "https://i1.hdslb.com/bfs/face/9b312f4146ca2c8a1d2e5468e345ecfb60be3874.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": { + "name": "翟赧hallu", + "face": "https://i1.hdslb.com/bfs/face/9b312f4146ca2c8a1d2e5468e345ecfb60be3874.jpg" + }, + "origin_info": { + "name": "翟赧hallu", + "face": "https://i1.hdslb.com/bfs/face/9b312f4146ca2c8a1d2e5468e345ecfb60be3874.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": { + "name": "钢板鹿", + "level": 28, + "color_start": 398668, + "color_end": 6850801, + "color_border": 6809855, + "color": 398668, + "id": 0, + "typ": 0, + "is_light": 1, + "ruid": 3493118494116797, + "guard_level": 3, + "score": 50208414, + "guard_icon": "https://i0.hdslb.com/bfs/live/143f5ec3003b4080d1b5f817a9efdca46d631945.png", + "honor_icon": "", + "v2_medal_color_start": "#4775EFCC", + "v2_medal_color_end": "#4775EFCC", + "v2_medal_color_border": "#58A1F8FF", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + }, + "wealth": { + "level": 35, + "dm_icon_key": "" + }, + "title": null, + "guard": { + "level": 3, + "expired_str": "2025-08-05 23:59:59" + }, + "uhead_frame": null, + "guard_leader": null + } + }, + { + "userRank": 9, + "uid": 418232, + "name": "lug7", + "face": "http://i2.hdslb.com/bfs/face/5d2c92beb774a4bb30762538bb102d23670ae9c0.gif", + "score": 171, + "medalInfo": { + "guardLevel": 3, + "medalColorStart": 398668, + "medalColorEnd": 6850801, + "medalColorBorder": 6809855, + "medalName": "钢板鹿", + "level": 26, + "targetId": 3493118494116797, + "isLight": 1 + }, + "guard_level": 3, + "wealth_level": 28, + "is_mystery": false, + "uinfo": { + "uid": 418232, + "base": { + "name": "lug7", + "face": "http://i2.hdslb.com/bfs/face/5d2c92beb774a4bb30762538bb102d23670ae9c0.gif", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": { + "name": "lug7", + "face": "http://i2.hdslb.com/bfs/face/5d2c92beb774a4bb30762538bb102d23670ae9c0.gif" + }, + "origin_info": { + "name": "lug7", + "face": "http://i2.hdslb.com/bfs/face/5d2c92beb774a4bb30762538bb102d23670ae9c0.gif" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": { + "name": "钢板鹿", + "level": 26, + "color_start": 398668, + "color_end": 6850801, + "color_border": 6809855, + "color": 398668, + "id": 0, + "typ": 0, + "is_light": 1, + "ruid": 3493118494116797, + "guard_level": 3, + "score": 50050050, + "guard_icon": "https://i0.hdslb.com/bfs/live/143f5ec3003b4080d1b5f817a9efdca46d631945.png", + "honor_icon": "", + "v2_medal_color_start": "#4775EFCC", + "v2_medal_color_end": "#4775EFCC", + "v2_medal_color_border": "#58A1F8FF", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + }, + "wealth": { + "level": 28, + "dm_icon_key": "" + }, + "title": null, + "guard": { + "level": 3, + "expired_str": "2025-06-15 23:59:59" + }, + "uhead_frame": null, + "guard_leader": null + } + }, + { + "userRank": 10, + "uid": 452228643, + "name": "很糊的小龔鬱hallu", + "face": "https://i0.hdslb.com/bfs/face/996fa85fe42d582dd013dcb435de3f3ff4d33f6c.jpg", + "score": 35, + "medalInfo": { + "guardLevel": 0, + "medalColorStart": 6126494, + "medalColorEnd": 6126494, + "medalColorBorder": 6126494, + "medalName": "牧斯", + "level": 6, + "targetId": 3493087074585126, + "isLight": 1 + }, + "guard_level": 3, + "wealth_level": 35, + "is_mystery": false, + "uinfo": { + "uid": 452228643, + "base": { + "name": "很糊的小龔鬱hallu", + "face": "https://i0.hdslb.com/bfs/face/996fa85fe42d582dd013dcb435de3f3ff4d33f6c.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": { + "name": "很糊的小龔鬱hallu", + "face": "https://i0.hdslb.com/bfs/face/996fa85fe42d582dd013dcb435de3f3ff4d33f6c.jpg" + }, + "origin_info": { + "name": "很糊的小龔鬱hallu", + "face": "https://i0.hdslb.com/bfs/face/996fa85fe42d582dd013dcb435de3f3ff4d33f6c.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": { + "name": "牧斯", + "level": 6, + "color_start": 6126494, + "color_end": 6126494, + "color_border": 6126494, + "color": 6126494, + "id": 0, + "typ": 0, + "is_light": 1, + "ruid": 3493087074585126, + "guard_level": 0, + "score": 3400, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#5866C799", + "v2_medal_color_end": "#5866C799", + "v2_medal_color_border": "#5866C799", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + }, + "wealth": { + "level": 35, + "dm_icon_key": "" + }, + "title": null, + "guard": { + "level": 3, + "expired_str": "2025-06-19 23:59:59" + }, + "uhead_frame": null, + "guard_leader": null + } + }, + { + "userRank": 11, + "uid": 164871173, + "name": "奶浴-bllss", + "face": "https://i2.hdslb.com/bfs/face/f48dd7c1e432eb91e5fd286757c4e2600930f4c5.jpg", + "score": 26, + "medalInfo": null, + "guard_level": 3, + "wealth_level": 36, + "is_mystery": false, + "uinfo": { + "uid": 164871173, + "base": { + "name": "奶浴-bllss", + "face": "https://i2.hdslb.com/bfs/face/f48dd7c1e432eb91e5fd286757c4e2600930f4c5.jpg", + "name_color": 0, + "is_mystery": false, + "risk_ctrl_info": { + "name": "奶浴-bllss", + "face": "https://i2.hdslb.com/bfs/face/f48dd7c1e432eb91e5fd286757c4e2600930f4c5.jpg" + }, + "origin_info": { + "name": "奶浴-bllss", + "face": "https://i2.hdslb.com/bfs/face/f48dd7c1e432eb91e5fd286757c4e2600930f4c5.jpg" + }, + "official_info": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "name_color_str": "" + }, + "medal": null, + "wealth": { + "level": 36, + "dm_icon_key": "" + }, + "title": null, + "guard": { + "level": 3, + "expired_str": "2025-07-20 23:59:59" + }, + "uhead_frame": null, + "guard_leader": null + } + }, + ], + "ownInfo": { + "uid": 0, + "name": "", + "face": "", + "rank": -1, + "needScore": 0, + "score": 0, + "guard_level": 0, + "wealth_level": 0, + "is_mystery": false, + "uinfo": null + }, + "tips_text": "投喂、点赞、发弹幕、持续观看均可上榜", + "value_text": "贡献值", + "ab": { + "guard_accompany_list": 1 + }, + "onlineNumText": "45" + } +} +``` +</details> + +## 查询自己在某直播间观看时长 + +> https://api.live.bilibili.com/xlive/general-interface/v1/guard/GuardActive + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +**url 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------- | ------ | ---- | +| platform | str | android | 必要 | | +| ruid | num | 主播uid | 必要 | | + +**json 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---- | +| code | num | 返回值 | | +| message | str | 错误信息 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + + + + + +`data`中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | -------------- | ----------------------------- | +| ruid | num | 主播uid | | +| rusername | str | 主播用户名 | | +| rface | str | 主播头像 | | +| username | str | 自己的用户名 | | +| accomany | int | 大航海陪伴天数 | 似乎b站程序员把这个单词拼错了 | +| rusername | str | 主播用户名 | | +| watch_time | num | 观看时长 | 单位是秒 | +| up_medal | obj | 粉丝牌 | | +| guard_num_3 | num | 主播舰长数量 | +| guard_num_2 | num | 主播提督数量 | | +| guard_num_1 | num | 主播总督数量 | | +| is_live | num | 直播状态 | | + + + +## 查询用户在直播间的信息 + +> https://api.live.bilibili.com/xlive/app-ucenter/v2/card/user + +*请求方式:GET* + +认证方式:无 + +**url 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| uid | num | 目标用户uid | 必要 | | +| ruid | num | 主播uid | 必要 | | + +**json 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---- | +| code | num | 返回值 | | +| message | str | 错误信息 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | + + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ------------------ | ------------------------------ | +| uid | num | 目标用户id | | +| uname | str | 目标用户名 | | +| desc | str | 目标用户认证信息 | | +| face | str | 目标用户头像 | | +| follow_num | num | 目标用户粉丝数 | | +| attention_num | num | 目标用户关注数 | +| main_vip | num | 目标用户大会员状态 | 0:无 2:大会员 | +| is_block | num | 是否被拉黑? | 始终为0? | +| is_admin | num | 是否房管 | | +| is_black | num | 是否被关小黑屋 | | +| wealth_info | obj | 荣耀等级 | | +| fans_medal | obj | 粉丝牌 | 如果目标用户隐藏粉丝牌则为null | + +`wealth_info`对象: +| 字段 | 类型 | 内容 | 备注 | +| ------------------ | ---- | -------------------------- | ---- | +| level | num | 荣耀等级 | | +| level_total_score | num | 下一等级的荣耀值 | | +| cur_score | num | 当前荣耀值 | | +| upgrade_need_score | num | 升到下一等级还差多少荣耀值 | | + +**示例:** + +```shell +curl 'https://api.live.bilibili.com/xlive/app-ucenter/v2/card/user?ruid=504140200&uid=504140200' +``` + +<details> +<summary>查看响应示例:</summary> + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "uid": 504140200, + "uname": "软软riu", + "face": "https://i1.hdslb.com/bfs/face/2d083d686b704eb7010e3d94595d47f5a89c8aef.jpg", + "verify_type": 0, + "desc": "bilibili UP主认证:bilibili 知名虚拟UP主、直播高能主播", + "uname_color": 2171169, + "room_id": 23174842, + "pendant": "https://i1.hdslb.com/bfs/garb/open/8806f97581082d68edcf2207368290b3fb3491bb.png", + "pendant_from": 2, + "follow_num": 214882, + "attention_num": 202, + "relation_status": 1, + "privilege_type": 3, + "fans_medal": null, + "title_sum": 10, + "wearing_title": "", + "main_vip": 0, + "is_block": 0, + "is_admin": 0, + "fans_medal_list_url": "https://live.bilibili.com/p/html/live-fansmedal-wall/index.html?tId=504140200#/medal", + "wearing": {}, + "is_black": 0, + "admin_level": 0, + "head_picture": "http://i0.hdslb.com/bfs/live/3f536f59e337a731c5367f623bca79b32197ddd5.png", + "head_text": "大航海舰长", + "head_url": "", + "head_business": 1, + "head_skin_icon": "http://i0.hdslb.com/bfs/live/d44e103f424f5ae01ef3d0133ef812f8241d15b0.png", + "privilege_center": {}, + "is_nft": 0, + "nft_dmark": "https://i0.hdslb.com/bfs/live/9f176ff49d28c50e9c53ec1c3297bd1ee539b3d6.gif", + "is_real_fans": false, + "wealth_info": { + "uid": 504140200, + "level": 35, + "level_total_score": 6000000, + "cur_score": 5012900, + "upgrade_need_score": 987100, + "status": 1, + "dm_icon_key": "" + }, + "guard": { + "accompany": 0, + "accompany_slake": 0 + }, + "chat_url_android": "activity://im/conversation/?conversation_type=1&reciveid=504140200", + "chat_url_ios": "bilibili://link/chat?session_id=s504140200", + "gift_star": null, + "is_mystery": false, + "text_control": null, + "uinfo_medal": null, + "guard_attire": {}, + "flash_buy": 0, + "flash_buy_url": "" + } +} +``` +</details> \ No newline at end of file diff --git a/bb-api-collect/docs/login/cookie_refresh.md b/bb-api-collect/docs/login/cookie_refresh.md new file mode 100644 index 0000000000..e1b22fa211 --- /dev/null +++ b/bb-api-collect/docs/login/cookie_refresh.md @@ -0,0 +1,574 @@ +# 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) [Kotlin](#kotlin) [Java](#java) [Go](#go) 以及 [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)) +``` + +```text +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)) +``` + +```text +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) } +} +``` + +```text +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 +} +``` + +```text +97759947aa357ed5d88cf9bf1172737570b7bba2d6788d39006f082b2b25ddf53b581f1f0c61ed8573317485ef525d2789faa25a277b4602a4b9cbf837681093a03e96cb9773a11df4bb1e20f1587180b3e958194de922d7dd94d0a2f0b9b0ef74e426e8041f99b99e7c02407ef4ab38040e61be81e4fdfbdb73461e3a2ad810 +``` + +### Java + +```Java +import javax.crypto.Cipher; +import javax.crypto.spec.OAEPParameterSpec; +import javax.crypto.spec.PSource; +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.PublicKey; +import java.security.spec.MGF1ParameterSpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; + +public class CookieRefresh { + private static final String PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n" + + "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLgd2OAkcGVtoE3ThUREbio0Eg\n" + + "Uc/prcajMKXvkCKFCWhJYJcLkcM2DKKcSeFpD/j6Boy538YXnR6VhcuUJOhH2x71\n" + + "nzPjfdTcqMz7djHum0qSZA0AyCBDABUqCrfNgCiJ00Ra7GmRj+YCK1NJEuewlb40\n" + + "JNrRuoEUXpabUzGB8QIDAQAB\n" + + "-----END PUBLIC KEY-----"; + + public static void main(String[] args) { + try { + String correspondPath = getCorrespondPath(String.format("refresh_%d", System.currentTimeMillis()), PUBLIC_KEY); + System.out.println(correspondPath); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static String getCorrespondPath(String plaintext, String publicKeyStr) throws Exception { + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + publicKeyStr = publicKeyStr + .replace("-----BEGIN PUBLIC KEY-----", "") + .replace("-----END PUBLIC KEY-----", "") + .replace("\n", "") + .trim(); + byte[] publicBytes = Base64.getDecoder().decode(publicKeyStr); + X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicBytes); + PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec); + + String algorithm = "RSA/ECB/OAEPPadding"; + Cipher cipher = Cipher.getInstance(algorithm); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + + // Encode the plaintext to bytes + byte[] plaintextBytes = plaintext.getBytes("UTF-8"); + + // Add OAEP padding to the plaintext bytes + OAEPParameterSpec oaepParams = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT); + cipher.init(Cipher.ENCRYPT_MODE, publicKey, oaepParams); + // Encrypt the padded plaintext bytes + byte[] encryptedBytes = cipher.doFinal(plaintextBytes); + // Convert the encrypted bytes to a Base64-encoded string + return new BigInteger(1, encryptedBytes).toString(16); + } +} +``` + +```text +f87666152da692735123f4e49053e5a98c16854673b2e632f31a3ff0c029640772873661a9a8412db6be447a0bfa03a295d15548cbfd2bb35634e98ba5f25b1205519d6e6119b483f4c516c1e106d45b04ff98c73560949d379d3edaf3c0ecd10a1d46134fb9ca443122ab33c16d1dd48280496f949ed960a2fbcd65f10935e +``` + +#### 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 + + + +
b0cc8411ded2f9db2cff2edb3123acac
+
+ + + + + + +``` + +所以当前账号的实时刷新口令`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:成功
-101:账号未登录
-111:csrf 校验失败
86095:refresh_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' +``` + +
+查看响应示例: + +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" + } +} +``` + +
+ +## 确认更新 + +> 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:成功
-101:账号未登录
-111:csrf 校验失败
-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' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
diff --git a/bb-api-collect/docs/login/exit.md b/bb-api-collect/docs/login/exit.md new file mode 100644 index 0000000000..8ba5e14277 --- /dev/null +++ b/bb-api-collect/docs/login/exit.md @@ -0,0 +1,68 @@ +# 退出账号登录 + +## 退出登录(web端) + +> https://passport.bilibili.com/login/exit/v2 + +_请求方式:POST_ + +认证方式:Cookie + +验证登录成功后会使用`set-cookie`字段清空以下 cookie 项: + +`DedeUserID` `DedeUserID__ckMd5` `SESSDATA` `bili_jct` + +并在服务器注销该登录 Token (SESSDATA),该 Token 即失效 + +请求必须包含以下cookie项:`DedeUserID` `bili_jct` `SESSDATA` + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ---------------------------------------- | ------ | --------------------------------- | +| biliCSRF | str | CSRF Token (位于 cookie 中的 `bili_jct`) | 必要 | | +| gourl | str | 成功后跳转到的页面 | 非必要 | 默认为`javascript:history.go(-1)` | + +**json 回复:** + +如果 cookie 已经失效则输出登录页 html + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----------- | -------- | --------------------------------- | +| code | num | 返回值 | 0:成功
2202:csrf 请求非法 | +| status | bool | 返回值 | `true`:成功 | +| ts | num | 时间戳 | | +| message | str | 错误信息 | 成功时不存在 | +| data | 有效时:obj | 信息本体 | 失败时不存在 | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ---------- | ---- | +| redirectUrl | str | 重定向 url | | + +**示例:** + +```shell +curl -L -X POST 'https://passport.bilibili.com/login/exit/v2' \ +-H 'Cookie: DedeUserID=xxx; bili_jct=xxx; SESSDATA=xxx' \ +-H 'Content-Type: application/x-www-form-urlencoded' \ +--data-urlencode 'biliCSRF=xxxxxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "status": true, + "ts": 1663034005, + "data": { + "redirectUrl": "https://passport.biligame.com/crossDomain?DedeUserID=&DedeUserID__ckMd5=&SESSDATA=&bili_jct=&gourl=javascript%3Ahistory.go%28-1%29" + } +} +``` +
\ No newline at end of file diff --git a/bb-api-collect/docs/login/login_action/QR.md b/bb-api-collect/docs/login/login_action/QR.md new file mode 100644 index 0000000000..ecee7fd965 --- /dev/null +++ b/bb-api-collect/docs/login/login_action/QR.md @@ -0,0 +1,652 @@ +# 二维码登录 + + + +## 扫码登录流程(伪代码) + +```python +token, url = 申请二维码() +生成二维码(url) # 等待客户端扫码 +while True: + status, cookie = 扫码登录(token) + match status: + case 未扫描: + continue + case 二维码超时 | 二维码失效: + 提示('二维码失效或超时') # 需要用户重新操作 + break + case 已扫描未确认: + 提示('扫描成功') + case 登录成功: + 提示('扫描成功') + 存储cookie(cookie) + SSO登录页面跳转() + break +``` + +## web端扫码登录 + +### 申请二维码(web端) + +> https://passport.bilibili.com/x/passport-login/web/qrcode/generate + +*请求方式:GET* + +密钥超时为180秒 + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|------| +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +|------------|-----|------------------|--------| +| url | str | 二维码内容 (登录页面 url) | | +| qrcode_key | str | 扫码登录秘钥 | 恒为32字符 | + +**示例:** + +`url`中的值生成二维码,等待手机客户端扫描,并将`qrcode_key`保存备用 + +```shell +curl 'https://passport.bilibili.com/x/passport-login/web/qrcode/generate' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "url": "https://passport.bilibili.com/h5-app/passport/login/scan?navhide=1\u0026qrcode_key=8587cf8106a0b863c46d6bab913537f6\u0026from=", + "qrcode_key": "8587cf8106a0b863c46d6bab913537f6" + } +} +``` + +
+ +### 扫码登录(web端) + +> https://passport.bilibili.com/x/passport-login/web/qrcode/poll + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|------------|-----|--------|-----|-----| +| qrcode_key | str | 扫码登录秘钥 | 必要 | | + + +密钥超时为180秒 + +验证登录成功后会进行设置以下cookie项: + +`DedeUserID` `DedeUserID__ckMd5` `SESSDATA` `bili_jct` + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|------| +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | | +| data | obj | 信息本体 | | + +data 对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------------|-----|----------------------------------------------------------------|------------------------| +| url | str | 游戏分站跨域登录 url | 未登录为空 | +| refresh_token | str | 刷新`refresh_token` | 未登录为空 | +| timestamp | num | 登录时间 | 未登录为`0`
时间戳 单位为毫秒 | +| code | num | 0:扫码登录成功
86038:二维码已失效
86090:二维码已扫码未确认
86101:未扫码 | | +| message | str | 扫码状态信息 | | + +**示例:** + +使用扫描秘钥`c3bd5286a2b40a822f5f60e9bf3f602e`登录 + +```shell +curl -G "https://passport.bilibili.com/x/passport-login/web/qrcode/poll"\ +--data-urlencode 'qrcode_key=c3bd5286a2b40a822f5f60e9bf3f602e' \ +-c 'cookie.txt' +``` + +当密钥正确时但未扫描时`code`为`86101` + +
+查看响应示例: + + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "url": "", + "refresh_token": "", + "timestamp": 0, + "code": 86101, + "message": "未扫码" + } +} +``` + +
+ +扫描成功但手机端未确认时`code`为`86090` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "url": "", + "refresh_token": "", + "timestamp": 0, + "code": 86090, + "message": "二维码已扫码未确认" + } +} +``` + +
+ +扫描成功手机端确认登录后,`code`为`0`,并向浏览器写入cookie + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "url": "https://passport.biligame.com/crossDomain?DedeUserID=***\u0026DedeUserID__ckMd5=***\u0026Expires=***\u0026SESSDATA=***\u0026bili_jct=***\u0026gourl=https%3A%2F%2Fpassport.bilibili.com", + "refresh_token": "***", + "timestamp": 1662363009601, + "code": 0, + "message": "" + } +} +``` + +
+ +**响应头部抓包信息:** + +可明显看见设置了几个cookie + +
+查看响应示例: + +```http +HTTP/1.1 200 OK +Date: Mon, 05 Sep 2022 07:30:09 GMT +Expires: Mon, 05 Sep 2022 07:30:08 GMT +Cache-control: no-cache +Content-encoding: br +Content-type: application/json; charset=utf-8 +bili-status-code: 0 +bili-trace-id: 0d23fe044a6315a5 +set-cookie: SESSDATA=***; Path=/; Domain=bilibili.com; Expires=Sat, 04 Mar 2023 07:30:09 GMT; HttpOnly; Secure +set-cookie: bili_jct=***; Path=/; Domain=bilibili.com; Expires=Sat, 04 Mar 2023 07:30:09 GMT +set-cookie: DedeUserID=***; Path=/; Domain=bilibili.com; Expires=Sat, 04 Mar 2023 07:30:09 GMT +set-cookie: DedeUserID__ckMd5=***; Path=/; Domain=bilibili.com; Expires=Sat, 04 Mar 2023 07:30:09 GMT +set-cookie: sid=***; Path=/; Domain=bilibili.com; Expires=Sat, 04 Mar 2023 07:30:09 GMT +x-bili-trace-id: 2fbd8abd97dbd4db0d23fe044a6315a5 +x-cache-webcdn: BYPASS from blzone02 +``` + +
+ +二维码失效时`code`为`86038` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "url": "", + "refresh_token": "", + "timestamp": 0, + "code": 86038, + "message": "二维码已失效" + } +} +``` + +
+ +## web端扫码登录-旧版 + +以下为旧版扫码登录 API,部分可正常访问 + +### 申请二维码(web端-旧版) + +> https://passport.bilibili.com/qrcode/getLoginUrl + +*请求方式:GET* + +密钥超时为180秒 + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------|------|------|--------| +| code | num | 返回值 | 0:成功 | +| status | bool | true | 作用尚不明确 | +| ts | num | 请求时间 | 时间戳 | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +|----------|-----|------------------|--------| +| url | str | 二维码内容 (登录页面 url) | | +| oauthKey | str | 扫码登录秘钥 | 恒为32字符 | + +**示例:** + +`url`中的值生成二维码,等待手机客户端扫描,并将`oauthKey`保存备用 + +```shell +curl 'https://passport.bilibili.com/qrcode/getLoginUrl' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "status": true, + "ts": 1583314311, + "data": { + "url": "https://passport.bilibili.com/qrcode/h5/login?oauthKey=c3bd5286a2b40a822f5f60e9bf3f602e", + "oauthKey": "c3bd5286a2b40a822f5f60e9bf3f602e" + } +} +``` + +
+ +### 扫码登录(web端-旧版) + +**接口已失效,请求结果始终为 `{ code: 20000, message: '该版本已不支持当前功能,请升级新版本!' }`** + +> ~~https://passport.bilibili.com/qrcode/getLoginInfo~~ + +*请求方式:POST* + +
+内容已过时: + +密钥超时为180秒 + +验证登录成功后会进行设置以下cookie项: + +`DedeUserID` `DedeUserID__ckMd5` `SESSDATA` `bili_jct` + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|----------|-----|--------|-----|----------------------------| +| oauthKey | str | 扫码登录秘钥 | 必要 | | +| gourl | str | 跳转url | 非必要 | 默认为http://www.bilibili.com | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|----------------------|---------------------------|---------------------------------------------------------| +| code | num | 返回值 | 0:成功,
20000:该版本已不支持当前功能,请升级新版本! | +| message | str | | 正确无 | +| ts | num | 扫码时间 | 错误无 | +| status | bool | 扫码是否成功 | true:成功
false:未成功 | +| data | 正确时:obj
错误时:num | 正确时:游戏分站url
错误时:错误代码 | 未成功时:
-1:密钥错误
-2:密钥超时
-4:未扫描
-5:未确认 | + +data 对象: + +| 字段 | 类型 | 内容 | 备注 | +|-----|-----|--------------|-----| +| url | str | 游戏分站跨域登录 url | | + +**示例:** + +使用扫描秘钥`c3bd5286a2b40a822f5f60e9bf3f602e`登录 + +```shell +curl "https://passport.bilibili.com/qrcode/getLoginInfo"\ +--data-urlencode 'oauthKey=c3bd5286a2b40a822f5f60e9bf3f602e' \ +-c 'cookie.txt' +``` + +当密钥正确时但未扫描时`status`为`false`,`data`为`-4` + +
+查看响应示例: + +```json +{ + "status":false, + "data":-4, + "message":"Can't scan~" +} +``` + +
+ +扫描成功但手机端未确认时`status`为`false`,`data`为`-5` + +
+查看响应示例: + +```json +{ + "status":false, + "data":-5, + "message":"Can't confirm~" +} +``` + +
+ +扫描成功手机端确认登录后,`status`为`true`,`data`为对象,并向浏览器写入cookie + +
+查看响应示例: + +```json +{ + "code": 0, + "status": true, + "ts": 1583315474, + "data": { + "url": "https://passport.biligame.com/crossDomain?DedeUserID=***&DedeUserID__ckMd5=***&Expires=***&SESSDATA=***&bili_jct=***&gourl=http%3A%2F%2Fwww.bilibili.com" + } +} +``` + +
+ +**响应头部抓包信息:** + +可明显看见设置了几个cookie + +
+查看响应示例: + +```http +HTTP/1.1 200 OK +Date: Wed, 04 Mar 2020 10:36:37 GMT +Content-Type: application/json;charset=UTF-8 +Transfer-Encoding: chunked +Connection: keep-alive +Server: Apache-Coyote/1.1 +Set-Cookie: sid=***; Domain=.bilibili.com; Expires=Thu, 04-Mar-2021 10:36:37 GMT; Path=/ +Set-Cookie: DedeUserID=***; Domain=.bilibili.com; Expires=Mon, 31-Aug-2020 10:19:57 GMT; Path=/ +Set-Cookie: DedeUserID__ckMd5=***; Domain=.bilibili.com; Expires=Mon, 31-Aug-2020 10:19:57 GMT; Path=/ +Set-Cookie: SESSDATA=***; Domain=.bilibili.com; Expires=Mon, 31-Aug-2020 10:19:57 GMT; Path=/; HttpOnly +Set-Cookie: bili_jct=***; Domain=.bilibili.com; Expires=Mon, 31-Aug-2020 10:19:57 GMT; Path=/ +Expires: Wed, 04 Mar 2020 10:36:36 GMT +Cache-Control: no-cache +X-Cache-Webcdn: BYPASS from ks-sxhz-dx-w-01 +``` + +
+ +
+ +## TV端扫码登录 + +### 申请二维码(TV端) + +> https://passport.snm0516.aisee.tv/x/passport-tv-login/qrcode/auth_code +> +> https://passport.bilibili.com/x/passport-tv-login/qrcode/auth_code + +*请求方式:POST* + +鉴权方式:appkey + +密钥超时为180秒 + +本接口可申请用于TV端APP方式登录的`access_key` + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ---------- | ------------ | -------------------------- | +| appkey | str | APP 密钥 | APP 方式必要 | [可用](#appkey-可用列表) | +| local_id | num | TV 端 id | TV 端必要 | 可为`0` | +| ts | num | 当前时间戳 | APP 方式必要 | | +| sign | str | APP 签名 | APP 方式必要 | | +| mobi_app | str | 平台标识 | 非必要 | 会被拼接到返回的 url query | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|---------------------------------------| +| code | num | 返回值 | 0:成功
-3:API校验密匙错误
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | -------------- | ------------ | +| url | str | 二维码内容 url | | +| auth_code | str | 扫码登录秘钥 | 恒为 32 字符 | + +**示例:** + +```shell +curl 'https://passport.snm0516.aisee.tv/x/passport-tv-login/qrcode/auth_code' \ +--data-urlencode 'appkey=4409e2ce8ffd12b8' \ +--data-urlencode 'local_id=0' \ +--data-urlencode 'ts=0' \ +--data-urlencode 'sign=e134154ed6add881d28fbdf68653cd9c' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "url": "https://passport.bilibili.com/x/passport-tv-login/h5/qrcode/auth?auth_code=0eeb635a64526709d70cb4c854a3b001", + "auth_code": "0eeb635a64526709d70cb4c854a3b001" + } +} +``` + +
+ +### 扫码登录(TV端) + +> https://passport.snm0516.aisee.tv/x/passport-tv-login/qrcode/poll +> +> https://passport.bilibili.com/x/passport-tv-login/qrcode/poll + +*请求方式:POST* + +鉴权方式:appkey + +密钥超时为180秒 + +验证登录成功后会返回可用于APP方式登录的`access_key`以及`refresh_token` + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|-----------|-----|-------|---------|-----------------------| +| appkey | str | APP密钥 | APP方式必要 |[可用](#appkey-可用列表) | +| auth_code | str | 扫码秘钥 | 必要 | | +| local_id | num | TV端id | TV端必要 | 可为0 | +| ts | num | 当前时间戳 | APP方式必要 | | +| sign | str | APP签名 | APP方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----------------------|------|--------------------------------------------------------------------------------------------------------------| +| code | num | 返回值 | 0:成功
-3:API校验密匙错误
-400:请求错误
-404:啥都木有
86038:二维码已失效
86039:二维码尚未确认
86090:二维码已扫码未确认 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 有效时:obj
无效时:null | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------------|-----|------------|---------------------| +| mid | num | 登录用户mid | | +| access_token | str | APP登录Token | | +| refresh_token | str | APP刷新Token | | +| expires_in | num | 有效时间 | 默认:15552000秒,等于180天 | + +**示例:** + +使用扫描秘钥`6214464b3025541abf6f654cf7569a01`进行验证登录 + +```shell +curl 'https://passport.snm0516.aisee.tv/x/passport-tv-login/qrcode/poll' \ +--data-urlencode 'appkey=4409e2ce8ffd12b8' \ +--data-urlencode 'auth_code=6214464b3025541abf6f654cf7569a01' \ +--data-urlencode 'local_id=0' \ +--data-urlencode 'ts=0' \ +--data-urlencode 'sign=87de3d0fee7c3f4facd244537238914e' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "is_new": false, + "mid": 10086, + "access_token": "********************************", + "refresh_token": "********************************", + "expires_in": 15552000, + "token_info": { + "mid": 10086, + "access_token": "********************************", + "refresh_token": "********************************", + "expires_in": 15552000 + }, + "cookie_info": { + "cookies": [ + { + "name": "SESSDATA", + "value": "********************************", + "http_only": 1, + "expires": 1679988973, + "secure": 0 + }, + { + "name": "bili_jct", + "value": "********************************", + "http_only": 0, + "expires": 1679988973, + "secure": 0 + }, + { + "name": "DedeUserID", + "value": "*******", + "http_only": 0, + "expires": 1679988973, + "secure": 0 + }, + { + "name": "DedeUserID__ckMd5", + "value": "****************", + "http_only": 0, + "expires": 1679988973, + "secure": 0 + }, + { + "name": "sid", + "value": "********", + "http_only": 0, + "expires": 1679988973, + "secure": 0 + } + ], + "domains": [ + ".bilibili.com", + ".biligame.com", + ".bigfun.cn", + ".bigfunapp.cn", + ".dreamcast.hk" + ] + }, + "sso": [ + "https://passport.bilibili.com/api/v2/sso", + "https://passport.biligame.com/api/v2/sso", + "https://passport.bigfunapp.cn/api/v2/sso" + ] + } +} +``` + +
+ +### appkey 可用列表 + +**仅覆盖 [docs/misc/sign/APPKey](../../misc/sign/APPKey.md) 中包含的 appkey** + +| APPKEY | APPSEC | platform | APP类型 | neuronAppId | mobi_app2 | 备注 | +| :--------------: | :------------------------------: | :------------------: | :----------------: | :---------------------: | :------------------: | :----------------------------------------: | +| 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` 使用。 diff --git a/bb-api-collect/docs/login/login_action/SMS.md b/bb-api-collect/docs/login/login_action/SMS.md new file mode 100644 index 0000000000..bd8abe5ec6 --- /dev/null +++ b/bb-api-collect/docs/login/login_action/SMS.md @@ -0,0 +1,453 @@ +# 短信登录 + +web端短信登录流程: + +1. [完成人机验证](readme.md) +2. 发送短信,使用国际地区代码`cid`+手机号码`tel`+登录密钥`token`+极验`challenge`+验证结果`validate`+验证结果`seccode` +3. 提交短信验证码以验证登录操作,使用国际地区代码`cid`+手机号码`tel`+短信验证码`code` + +## 获取国际冠字码_web端 + +> https://passport.bilibili.com/web/generic/country/list + +*请求方式:GET* + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功 | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ----- | ------------- | ---- | +| common | array | 常用国家&地区 | | +| others | array | 其他国家&地区 | | + +`data`中的`common`和`others`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | ---- | +| 0 | obj | 国家&地区1 | | +| n | obj | 国家&地区(n+1) | | +| …… | obj | …… | …… | + +`common`和`others`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------- | ---- | +| id | num | 国际代码值 | | +| cname | str | 国家&地区名 | | +| country_id | str | 国家&地区区号 | | + +**示例:** + +```shell +curl 'https://passport.bilibili.com/web/generic/country/list' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "data": { + "common": [ + { + "id": 1, + "cname": "中国大陆", + "country_id": "86" + }, + { + "id": 5, + "cname": "中国香港特别行政区", + "country_id": "852" + }, + ………… + ], + "others": [ + { + "id": 22, + "cname": "阿富汗", + "country_id": "93" + }, + { + "id": 20, + "cname": "阿尔巴尼亚", + "country_id": "355" + }, + ………… + ] + } +} +``` + +
+ + +## 发送短信验证码_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:成功
-400:请求错误
1002:手机号格式错误
86203:短信发送次数已达上限
1003:验证码已经发送
1025:该手机号在哔哩哔哩有过永久封禁记录,无法再次注册或绑定新账号
2400:登录秘钥错误
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}" +} +``` + +
+查看响应示例: + +```json +{"code":0, + "message":"0", + "ttl":1, + "data":{ + "captcha_key":"7542f109c3318d74847626495c68c321", + "recaptcha_url":"...." + } +} +``` + +
+ +## 发送短信验证码_web端 + +> https://passport.bilibili.com/x/passport-login/web/sms/send + +*请求方式:POST* + +同手机号短信发送 CD 时间为 60s + +短信验证码 timeout 为 5min + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --- | --- | --- | --- | --- | +| cid | num | 国际冠字码 | 必要 | 可以从[获取国际冠字码](#获取国际冠字码-web端)获取 | +| tel | num | 手机号码 | 必要 | | +| source | str | 登录来源 | 必要 | `main_web`:独立登录页
`main_mini`:小窗登录 | +| token | str | 登录 API token | 必要 | 在[申请 captcha 验证码](readme.md#申请captcha验证码)接口处获取 | +| challenge | str | 极验 challenge | 必要 | 在[申请 captcha 验证码](readme.md#申请captcha验证码)接口处获取 | +| validate | str | 极验 result | 必要 | 极验验证后得到 | +| seccode | str | 极验 result +`\|jordan` | 必要 | 极验验证后得到 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | -------- | --------- | +| code | num | 返回值 | 0:成功
-400:请求错误
1002:手机号格式错误
86203:短信发送次数已达上限
1003:验证码已经发送
1025:该手机号在哔哩哔哩有过永久封禁记录,无法再次注册或绑定新账号
2400:登录秘钥错误
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/web/sms/send' \ +--data-urlencode 'tel=13888888888' \ +--data-urlencode 'cid=1' \ +--data-urlencode 'source=main_web' \ +--data-urlencode 'token=aabbccdd' \ +--data-urlencode 'challenge=2333' \ +--data-urlencode 'validate=666666' \ +--data-urlencode 'seccode=666666|jordan' +``` + +
+查看响应示例: + +```json +{"code":0, + "message":"0", + "ttl":1, + "data":{ + "captcha_key":"7542f109c3318d74847626495c68c321" + } +} +``` + +
+ +## 使用短信验证码登录_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:成功
-400:请求错误
1006:请输入正确的短信验证码
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' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "data": { + "token_info": { + "mid": "...", + "expires_in": "114514", + "access_token": "", + "refresh_token": "" + //... + }, + "cookie_info":[ + //... + ], + "message": "0" + } +} +``` + +
+ +**响应头部抓包信息:** + +可明显看见设置了几个cookie(填入浏览器即可成功登录) + +
+查看响应示例: + +```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 + +``` + +
+ + +## 使用短信验证码登录_web端 + +> https://passport.bilibili.com/x/passport-login/web/login/sms + +*请求方式:POST* + +验证登录成功后会进行设置以下cookie项: + + `DedeUserID` `DedeUserID__ckMd5` `SESSDATA` `bili_jct` + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --- | --- | --- | --- | --- | +| cid | num | 国际冠字码 | 必要 | 可以从[获取国际冠字码](#获取国际冠字码-web端)获取 | +| tel | num | 手机号码 | 必要 | | +| code | num | 短信验证码 | 必要 | timeout 为 5min | +| source | str | 登录来源 | 必要 | `main_web`:独立登录页
`main_mini`:小窗登录 | +| captcha_key | str | 短信登录 token | 必要 | 从[上述API](#发送短信验证码-web端)请求成功后返回 | +| go_url | str | 跳转url | 非必要 | 默认为 https://www.bilibili.com | +| keep | bool | 是否记住登录 | 非必要 | `true`:记住登录
`false`:不记住登录 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0:成功
-400:请求错误
1006:请输入正确的短信验证码
1007:短信验证码已过期 | +| message | str | 错误信息 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| is_new | bool | 是否为新注册用户 | false:非新注册用户
true:新注册用户 | +| status | num | 0 | 未知,可能0就是成功吧 | +| url | str | 跳转 url | 默认为 https://www.bilibili.com | + +**示例:** + +使用手机号`13888888888`,短信验证码为`123456`,进行验证登录操作 + +```shell +curl 'https://passport.bilibili.com/x/passport-login/web/login/sms' +--data-urlencode 'cid=1' \ +--data-urlencode 'tel=13888888888' \ +--data-urlencode 'code=123456' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "data": { + "is_new": false, + "status": 0, + "url": "https://space.bilibili.com" + } +} +``` + +
+ +**响应头部抓包信息:** + +可明显看见设置了几个cookie(填入浏览器即可成功登录) + +
+查看响应示例: + +```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 + +``` + +
diff --git a/bb-api-collect/docs/login/login_action/password.md b/bb-api-collect/docs/login/login_action/password.md new file mode 100644 index 0000000000..ffc3d0149e --- /dev/null +++ b/bb-api-collect/docs/login/login_action/password.md @@ -0,0 +1,788 @@ +# 密码登录 + +## 密码登录流程(伪代码) + +```python +账号 = '2333333' +密码字符串 = 'password' + +# 1.人机验证步骤 +token, gt, challenge = 获取验证码() +validate = 填写验证码(gt, challenge) # 这一步填写验证码 (访问极验API,得到validate) + +# 2.密码加密步骤 +pubkey, salt = 获取公钥和盐() +加密后的密码 = RSA公钥加密(pubkey, salt+密码字符串) # 盐需要加在密码字符串前 +base64编码后的密文 = base64编码(加密后的密码) + +# 3.开始登录 +cookie = 密码登录(账号, base64编码后的密文, token, challenge, validate) +存储cookie(cookie) +SSO登录页面跳转() +``` + +## web端密码登录 + +### 获取公钥&盐(web端) + +> https://passport.bilibili.com/x/passport-login/web/key + +*请求方式:GET* + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|------| +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +|------|-----|--------|------------------------------------------| +| hash | str | 密码盐值 | 有效时间为 20s
恒为 16 字符
需要拼接在明文密码之前 | +| key | str | rsa 公钥 | PEM 格式编码
加密密码时需要使用 | + +**示例:** + +```shell +curl 'https://passport.bilibili.com/x/passport-login/web/key' +``` + +
+查看响应示例: + + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "hash": "9333681c87fd8d6e", + "key": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjb4V7EidX/ym28t2ybo0U6t0n\n6p4ej8VjqKHg100va6jkNbNTrLQqMCQCAYtXMXXp2Fwkk6WR+12N9zknLjf+C9sx\n/+l48mjUU8RqahiFD1XT/u2e0m2EN029OhCgkHx3Fc/KlFSIbak93EH/XlYis0w+\nXl69GV6klzgxW6d2xQIDAQAB\n-----END PUBLIC KEY-----\n" + } +} +``` + +
+ +### 登录操作(web端) + +> https://passport.bilibili.com/x/passport-login/web/login + +*请求方式:POST* + +验证登录成功后会进行设置以下 cookie 项: + +`sid` `DedeUserID` `DedeUserID__ckMd5` `SESSDATA` `bili_jct` + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | ---------------------- | ------ | ------------------------------------------------------------ | +| username | str | 用户登录账号 | 必要 | 手机号或邮箱地址 | +| password | str | 加密后的带盐密码 | 必要 | base64 格式 | +| keep | num | 0 | 必要 | | +| token | str | 登录 token | 必要 | 在[申请 captcha 验证码](readme.md#申请captcha验证码)接口处获取 | +| challenge | str | 极验 challenge | 必要 | 在[申请 captcha 验证码](readme.md#申请captcha验证码)接口处获取 | +| validate | str | 极验 result | 必要 | 极验验证后得到 | +| seccode | str | 极验 result +`\|jordan` | 必要 | 极验验证后得到 | +| go_url | str | 跳转 url | 非必要 | 默认为 https://www.bilibili.com | +| source | str | 登录来源 | 非必要 | `main_web`:独立登录页
`main_mini`:小窗登录 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----------------------|------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| code | num | 返回值 | 0:成功
-105:验证码错误
-400:请求错误
-629:账号或密码错误
-653:用户名或密码不能为空
-662:提交超时,请重新提交
-2001:缺少必要的的参数
-2100:需验证手机号或邮箱
2400:登录秘钥错误
2406:验证极验服务出错
86000:RSA解密失败 | +| message | str | 错误信息 | | +| data | 成功时:obj
失败时:null | 数据本体 | | + +data 对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------------|-----|-------------------|------------------------| +| message | str | 扫码状态信息 | 若提示 `本次登录环境存在风险, 需使用手机号进行验证或绑定`, 参见 [手机号验证](#手机号验证) | +| refresh_token | str | 刷新`refresh_token` | | +| status | num | 0 | | +| timestamp | num | 登录时间 | 未登录为`0`
时间戳 单位为毫秒 | +| url | str | 游戏分站跨域登录 url | | + +**示例:** + +例如用户账号为`12345678900`,加密后的密码为`xxx`,登录秘钥为`aabbccdd`,极验challenge为`2333`,极验结果为`666666`,进行验证登录操作 + +```shell +curl 'https://passport.bilibili.com/x/passport-login/web/login' \ +--data-urlencode 'username=12345678900' \ +--data-urlencode 'password=xxx' \ +--data-urlencode 'keep=0' \ +--data-urlencode 'source=main_web' \ +--data-urlencode 'token=aabbccdd' \ +--data-urlencode 'challenge=2333' \ +--data-urlencode 'validate=666666' \ +--data-urlencode 'seccode=666666|jordan' +``` + +
+查看响应示例: + + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "status": 0, + "message": "", + "url": "https://passport.biligame.com/crossDomain?DedeUserID=***&DedeUserID__ckMd5=***&Expires=***&SESSDATA=***&bili_jct=***&gourl=https%3A%2F%2Fwww.bilibili.com%2F", + "refresh_token": "***", + "timestamp": 1662452570273 + } +} + +``` + +
+ +**响应头部抓包信息:** + +可明显看见设置了几个 cookie + +
+查看响应示例: + +```http +HTTP/1.1 200 OK +Date: Mon, 13 Jul 2020 06:56:00 GMT +Content-Type: application/json;charset=UTF-8 +Content-Length: 273 +Connection: keep-alive +Server: Apache-Coyote/1.1 +Set-Cookie: DedeUserID=***; Domain=.bilibili.com; Expires=Sat, 09-Jan-2021 06:39:43 GMT; Path=/ +Set-Cookie: DedeUserID__ckMd5=***; Domain=.bilibili.com; Expires=Sat, 09-Jan-2021 06:39:43 GMT; Path=/ +Set-Cookie: SESSDATA=***; Domain=.bilibili.com; Expires=Sat, 09-Jan-2021 06:39:43 GMT; Path=/; HttpOnly +Set-Cookie: bili_jct=***; Domain=.bilibili.com; Expires=Sat, 09-Jan-2021 06:39:43 GMT; Path=/ +Content-Security-Policy-Report-Only: default-src 'self' data: *.bilibili.com *.hdslb.com; style-src 'self' 'unsafe-inline' *.hdslb.com static.geetest.com; img-src 'self' data: blob: *.bilibili.com *.hdslb.com http://*.hdslb.com static.geetest.com; script-src 'self' 'unsafe-inline' 'unsafe-eval' *.bilibili.com *.hdslb.com api.geetest.com static.geetest.com; object-src 'self' *.hdslb.com; media-src 'self' *.acgvideo.com http://*.acgvideo.com *.ksyungslb.com; connect-src 'self' data: wss://*.bilibili.com:* *.bilibili.com *.hdslb.com *.biliapi.net *.biliapi.com; frame-ancestors 'self' *.bilibili.com *.biligame.com; report-uri https://security.bilibili.com/csp_report +Expires: Mon, 13 Jul 2020 06:55:59 GMT +Cache-Control: no-cache +X-Cache-Webcdn: BYPASS from jd-sxhz-dx-w-01 +``` + +
+ +## web端密码登录-旧版 + +以下为密码扫码登录 API,尚可正常访问 + +### 获取公钥&盐(web端-旧版) + +> https://passport.bilibili.com/login?act=getkey + +*请求方式:GET* + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|------|-----|--------|------------------------------------------| +| hash | str | 密码盐值 | 有效时间为 20s
恒为 16 字符
需要拼接在明文密码之前 | +| key | str | rsa 公钥 | PEM 格式编码
加密密码时需要使用 | + +**示例:** + +```shell +curl 'https://passport.bilibili.com/login?act=getkey' +``` + +
+查看响应示例: + +```json +{ + "hash":"07c6501690c1af85", + "key":"-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjb4V7EidX/ym28t2ybo0U6t0n\n6p4ej8VjqKHg100va6jkNbNTrLQqMCQCAYtXMXXp2Fwkk6WR+12N9zknLjf+C9sx\n/+l48mjUU8RqahiFD1XT/u2e0m2EN029OhCgkHx3Fc/KlFSIbak93EH/XlYis0w+\nXl69GV6klzgxW6d2xQIDAQAB\n-----END PUBLIC KEY-----\n" +} +``` + +
+ +### 登录操作(web端-旧版) + + +> https://passport.bilibili.com/web/login/v2 + +*请求方式:POST* + +验证登录成功后会进行设置以下cookie项: + +`sid` `DedeUserID` `DedeUserID__ckMd5` `SESSDATA` `bili_jct` + +**正文参数 (application/x-www-form-urlencoded):** + + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----------- | ---- | ---------------------- | ------ | ------------------------------------------------------------ | +| captchaType | num | 6 | 必要 | 必须为`6` | +| username | str | 用户登录账号 | 必要 | 手机号或邮箱地址 | +| password | str | 加密后的带盐密码 | 必要 | base64 格式 | +| keep | bool | 是否记住登录 | 必要 | `true`:记住登录
`false`:不记住登录 | +| key | str | 登录 token | 必要 | 在[申请 captcha 验证码](readme.md#申请captcha验证码)接口处获取 | +| challenge | str | 极验 challenge | 必要 | 在[申请 captcha 验证码](readme.md#申请captcha验证码)接口处获取 | +| validate | str | 极验 result | 必要 | 极验验证后得到 | +| seccode | str | 极验 result +`\|jordan` | 必要 | 极验验证后得到 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|-------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| code | num | 返回值 | 0:成功
-400:请求错误
-629:账号或密码错误
-653:用户名或密码不能为空
-662:提交超时,请重新提交
-2001:缺少必要的的参数
-2100:需验证手机号或邮箱
2400:登录秘钥错误
2406:验证极验服务出错
86000:RSA解密失败 | +| ts | num | 当前时间戳 | 成功时无此项 | +| message | str | 错误信息 | 默认为0 | +| data | obj | 数据本体 | 成功时有此项 | + +`data`对象: + +**未登录时:** + +| 字段 | 类型 | 内容 | 备注 | +|-------------|-----|--------------|-----| +| redirectUrl | str | 游戏分站跨域登录 url | | + +**已登录时:** + +| 字段 | 类型 | 内容 | 备注 | +|---------|------|--------------------------|-----| +| isLogin | bool | true | | +| goUrl | str | https://www.bilibili.com | | + +**需验证手机号或邮箱时** + +| 字段 | 类型 | 内容 | 备注 | +|----------|-----|--------------------------|------------| +| mid | num | 用户 mid | | +| tel | str | 绑定的手机号 | 星号隐藏部分信息 | +| email | str | 绑定的邮箱 | 星号隐藏部分信息 | +| sorce | num | 0 | **作用尚不明确** | +| keeptime | num | 1 | **作用尚不明确** | +| goUrl | str | https://www.bilibili.com | | + +**示例:** + +例如用户账号为`12345678900`,加密后的密码为`xxx`,登录秘钥为`aabbccdd`,极验challenge为`2333`,极验结果为`666666`,进行验证登录操作 + +```shell +curl 'https://passport.bilibili.com/web/login/v2' \ +--data-urlencode 'captchaType=6' \ +--data-urlencode 'username=12345678900' \ +--data-urlencode 'password=xxx' \ +--data-urlencode 'keep=true' \ +--data-urlencode 'token=aabbccdd' \ +--data-urlencode 'challenge=2333' \ +--data-urlencode 'validate=666666' \ +--data-urlencode 'seccode=666666|jordan' +``` + +
+查看响应示例: + + +```json +{ + "code": 0, + "data": { + "redirectUrl": "https://passport.biligame.com/crossDomain?DedeUserID=***&DedeUserID__ckMd5=***&Expires=15551000&SESSDATA=***&bili_jct=***&gourl=https%3A%2F%2Fwww.bilibili.com" + } +} +``` + +
+ +**响应头部抓包信息:** + +可明显看见设置了几个 cookie + +
+查看响应示例: + +```http +HTTP/1.1 200 OK +Date: Mon, 13 Jul 2020 06:56:00 GMT +Content-Type: application/json;charset=UTF-8 +Content-Length: 273 +Connection: keep-alive +Server: Apache-Coyote/1.1 +Set-Cookie: DedeUserID=***; Domain=.bilibili.com; Expires=Sat, 09-Jan-2021 06:39:43 GMT; Path=/ +Set-Cookie: DedeUserID__ckMd5=***; Domain=.bilibili.com; Expires=Sat, 09-Jan-2021 06:39:43 GMT; Path=/ +Set-Cookie: SESSDATA=***; Domain=.bilibili.com; Expires=Sat, 09-Jan-2021 06:39:43 GMT; Path=/; HttpOnly +Set-Cookie: bili_jct=***; Domain=.bilibili.com; Expires=Sat, 09-Jan-2021 06:39:43 GMT; Path=/ +Content-Security-Policy-Report-Only: default-src 'self' data: *.bilibili.com *.hdslb.com; style-src 'self' 'unsafe-inline' *.hdslb.com static.geetest.com; img-src 'self' data: blob: *.bilibili.com *.hdslb.com http://*.hdslb.com static.geetest.com; script-src 'self' 'unsafe-inline' 'unsafe-eval' *.bilibili.com *.hdslb.com api.geetest.com static.geetest.com; object-src 'self' *.hdslb.com; media-src 'self' *.acgvideo.com http://*.acgvideo.com *.ksyungslb.com; connect-src 'self' data: wss://*.bilibili.com:* *.bilibili.com *.hdslb.com *.biliapi.net *.biliapi.com; frame-ancestors 'self' *.bilibili.com *.biligame.com; report-uri https://security.bilibili.com/csp_report +Expires: Mon, 13 Jul 2020 06:55:59 GMT +Cache-Control: no-cache +X-Cache-Webcdn: BYPASS from jd-sxhz-dx-w-01 +``` + +
+ +## APP端密码登录 + +### 获取公钥&盐(APP端) + +> http://passport.bilibili.com/api/oauth2/getKey + +*请求方式:POST* + +鉴权方式:appkey + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|--------|-----|-------|---------|-----| +| appkey | str | APP密钥 | APP方式必要 | | +| sign | str | APP签名 | APP方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|------|-----|--------|------------------------------------------| +| hash | str | 密码盐值 | 有效时间为 20s
恒为 16 字符
需要拼接在明文密码之前 | +| key | str | rsa 公钥 | PEM 格式编码
加密密码时需要使用 | + +**示例:** + +```shell +curl 'https://passport.bilibili.com/api/oauth2/getKey' \ +--data-urlencode 'appkey=1d8b6e7d45233436' \ +--data-urlencode 'sign=17004c193f688f0b5665c1068e733aff' +``` + +
+查看响应示例: + +```json +{ + "hash": "07c6501690c1af85", + "key": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjb4V7EidX/ym28t2ybo0U6t0n\n6p4ej8VjqKHg100va6jkNbNTrLQqMCQCAYtXMXXp2Fwkk6WR+12N9zknLjf+C9sx\n/+l48mjUU8RqahiFD1XT/u2e0m2EN029OhCgkHx3Fc/KlFSIbak93EH/XlYis0w+\nXl69GV6klzgxW6d2xQIDAQAB\n-----END PUBLIC KEY-----\n" +} +``` + +
+ +### 登录操作(APP端) + +TODO + +## 登录密码的加密实例 + +以下实例使用 Python 语言,在任何平台(web、APP)使用密码登录都需要如下加密步骤 + +首先在需拉取 RSA PubKey 和 salt 备用 + +```python +import requests + +resp = requests.get('https://passport.bilibili.com/x/passport-login/web/key').json()['data'] +print('salt =', resp['hash']) +print('PubKey =', resp['key']) +``` + +`hash`字段为 salt,长度固定为 16 字符,timeout 时间只有 20s + +`key`字段为 RSA PubKey,为 PEM 格式,加密需要使用 + +``` +salt = 9773d106a67e27d6 +PubKey = -----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjb4V7EidX/ym28t2ybo0U6t0n +6p4ej8VjqKHg100va6jkNbNTrLQqMCQCAYtXMXXp2Fwkk6WR+12N9zknLjf+C9sx +/+l48mjUU8RqahiFD1XT/u2e0m2EN029OhCgkHx3Fc/KlFSIbak93EH/XlYis0w+ +Xl69GV6klzgxW6d2xQIDAQAB +-----END PUBLIC KEY----- +``` + +例如登录密码为`BiShi22332323`,现在对它进行加盐并使用获取的 PubKey 加密 + +```python +import rsa +password = 'BiShi22332323' + +pubKey = rsa.PublicKey.load_pkcs1_openssl_pem(resp['key']) # 读取 PEM 密钥 +encryptedPassword = rsa.encrypt((resp['hash']+password).encode(), pubKey) # 盐需要加在明文密码之前,一并加密 +print(encryptedPassword) +``` + +下面将输出一段 bytes 数据: + +``` +b'}\x9c\xd4\xcd\x88\x92\xa7\xde\x85\xdb\xabm\xd7\xd3\x08\x02@xo\x85\xa4\xe1\x11\xd0o\x80\x03.$\xc8l\xbe\xba;\xfe\xee\xa7(\xf8S\x95\x1e\x9106\xa4\x1d\xcf\x8e\xbe\x8d\x94A\x86s\xf9"\x12\x0c\x135\xbb\xbc\xe1\xde\x1b\x90\t)P\xeb\xa9\x8fXY]\x83\x18\x81f\n:\xdb\xe1\xbe\xe8\x1e\xba\x1c D8d}B\x17\xf9\x8a\xf0i\'1\xa5\xc4\x05&\xaa;n\xf8{\xa02\xffY\xcelU\xd5\xaf\x8aJK\xdc\xf1@\xbc\x93' +``` + +接下来需要把加密后的结果进行 base64 编码 + +```python +import base64 +b64Password = base64.b64encode(encryptedPassword).decode() +print('result =', b64Password) +``` + +以下为最终加密结果,可直接向 API 请求体传参以登录: + +因为 RSA 公钥加密的**无法解密性**,故无法本地验证,仅可请求 API 验证(略... + +``` +result = fZzUzYiSp96F26tt19MIAkB4b4Wk4RHQb4ADLiTIbL66O/7upyj4U5UekTA2pB3Pjr6NlEGGc/kiEgwTNbu84d4bkAkpUOupj1hZXYMYgWYKOtvhvugeuhwgRDhkfUIX+YrwaScxpcQFJqo7bvh7oDL/Wc5sVdWvikpL3PFAvJM= +``` + +以下为密码加密的Java实现: + +```java +package com.ho.test; + +import cn.hutool.core.codec.Base64; + +import javax.crypto.Cipher; +import java.security.KeyFactory; +import java.security.PublicKey; +import java.security.spec.X509EncodedKeySpec; + +public class Test3 { + public static void main(String[] args) throws Exception { + //用户密码 + String password = "abcdef"; + //获取到的证书内容 + String key = "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjb4V7EidX/ym28t2ybo0U6t0n\n6p4ej8VjqKHg100va6jkNbNTrLQqMCQCAYtXMXXp2Fwkk6WR+12N9zknLjf+C9sx\n/+l48mjUU8RqahiFD1XT/u2e0m2EN029OhCgkHx3Fc/KlFSIbak93EH/XlYis0w+\nXl69GV6klzgxW6d2xQIDAQAB\n-----END PUBLIC KEY-----\n"; + //获取到的盐值 + String hash = "bb73382121594c46"; + String[] split = key.strip().split("\n"); + String newKey = split[1] + split[2] + split[3] + split[4]; + //进行加密 + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decode(newKey)); + PublicKey publicKey = keyFactory.generatePublic(keySpec); + Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); + cipher.init(Cipher.PUBLIC_KEY, publicKey); + byte[] bytes = cipher.doFinal((hash + password).getBytes()); + String encode = Base64.encode(bytes); + System.out.println(encode); + } +} + +``` + +## 手机号验证 + +### 简述 + +有时使用密码登录时, 无论使用网页端还是手机端接口, 由于 请求头缺失/请求频率高/请求IP 等原因, 会返回如下内容, 此时需要进行手机号验证或绑定 + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "is_new": false, + "status": 2, + "message": "本次登录环境存在风险, 需使用手机号进行验证或绑定", + "url": "https://passport.bilibili.com/h5-app/passport/risk/verify?tmp_token=imtmptk&request_id=imreqid&source=risk", + "refresh_token": "", + "timestamp": 0, + "hint": "", + "in_reg_audit": 0 + } +} +``` + +### 获取 captcha + +> https://passport.bilibili.com/x/safecenter/captcha/pre + +*请求方法: POST* + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | ---- | ---- | ---- | ---- | +| source | str | risk | 不必要 | | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0: 成功 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| recaptcha_type | str | 验证码类型 | 目前仅 `geetest` | +| recaptcha_token | str | 验证码 token | | +| gee_challenge | str | 极验 challenge | | +| gee_gt | str | 极验 gt | | + +**示例:** + +```shell +curl -X POST 'https://passport.bilibili.com/x/safecenter/captcha/pre' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "recaptcha_type": "geetest", + "recaptcha_token": "8a418aa9eebe411599d759fc318d55e1", + "gee_challenge": "4e5353e7ab9f9aef0c97fa5a5b1ad101", + "gee_gt": "ac597a4506fee079629df5d8b66dd4fe" + } +} +``` + +
+ +### 发送验证码 + +> https://passport.bilibili.com/x/safecenter/common/sms/send + +*请求方法: POST* + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | - | ---- | ---- | ---- | +| tmp_code| str | url query 中的 tmp_code | 必要 | 参见 [简述](#简述) 中 JSON 示例中的 `url` | +| sms_type | str | `loginTelCheck` | 必要 | | +| recaptcha_token | str | 验证码 token | 必要 | 参见 [获取 captcha](#获取-captcha) | +| gee_challenge | str | 极验 challenge | 必要 | 参见 [获取 captcha](#获取-captcha) | +| gee_validate | str | 极验 validate | 必要 | 验证后获得 | +| gee_seccode | str | 极验 seccode | 必要 | 验证后获得 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0: 成功 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | -- | - | +| captcha_key | str | 验证码 key | | + +**示例:** + +假设 `tmp_code` 为 `imtmptk`, +`recaptcha_token` 为 `kfc`, +`gee_challenge` 为 `crazythursday`, +`gee_validate` 为 `vivo50`, +`gee_seccode` 为 `vivo50|jordan` + +```shell +curl -X POST 'https://passport.bilibili.com/x/safecenter/common/sms/send' \ +--data-urlencode 'tmp_code=imtmptk' \ +--data-urlencode 'sms_type=loginTelCheck' \ +--data-urlencode 'recaptcha_token=kfc' \ +--data-urlencode 'gee_challenge=crazythursday' \ +--data-urlencode 'gee_validate=vivo50' \ +--data-urlencode 'gee_seccode=vivo50|jordan' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "captcha_key": "42403fb08ed2cd97afff14edefbae482" + } +} +``` + +
+ +### 验证手机验证码 + +> https://passport.bilibili.com/x/safecenter/login/tel/verify + +*请求方法: POST* + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | - | ---- | ---- | ---- | +| tmp_code | str | url query 中的 tmp_code | 必要 | 参见 [简述](#简述) 中 JSON 示例中的 `url` | +| captcha_key | str | 验证码 key | 必要 | 参见 [发送验证码](#发送验证码) | +| type | str | `loginTelCheck` | 必要 | | +| code | num | 接收到的验证码 | 必要 | | +| request_id | str | url query 中的 request_id | 必要 | 参见 [简述](#简述) 中 JSON 示例中的 `url` | +| source | str | risk | 必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0: 成功 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | str | 交换代码 | 用于后面 [交换 Cookie](#交换-cookie) | + +**示例:** + +假设 `tmp_code` 为 `imtmptk`, +`captcha_key` 为 `42403fb08ed2cd97afff14edefbae482`, +`code` 为 `114514`, +`request_id` 为 `imreqid` + +```shell +curl -X POST 'https://passport.bilibili.com/x/safecenter/login/tel/verify' \ +--data-urlencode 'tmp_code=imtmptk' \ +--data-urlencode 'captcha_key=42403fb08ed2cd97afff14edefbae482' \ +--data-urlencode 'type=loginTelCheck' \ +--data-urlencode 'code=114514' \ +--data-urlencode'request_id=imreqid' \ +--data-urlencode'source=risk' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "code": "6eadf783c55a387b143773282b217682" + } +} +``` + +
+ +### 交换 Cookie + +> https://passport.bilibili.com/x/passport-login/web/exchange_cookie + +*请求方法: POST* + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | - | ---- | ---- | ---- | +| source | str | risk | 必要 | | +| code | str | 交换代码 | 必要 | 参见 [验证手机验证码](#验证手机验证码) | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0: 成功 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | - | - | +| url | str | 游戏分站跨域登录 url | | +| refresh_token | str | 刷新 token | | + +**示例:** + +假设 `code` 为 `6eadf783c55a387b143773282b217682` + +```shell +curl -X POST 'https://passport.bilibili.com/x/passport-login/web/exchange_cookie' \ +--data-urlencode 'code=6eadf783c55a387b143773282b217682' \ +--data-urlencode'source=risk' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "url": "https://passport.biligame.com/x/passport-login/web/crossDomain?DedeUserID=645769214&DedeUserID__ckMd5=653409864bf9e200&Expires=1739265009&SESSDATA=11d97d2a,1739265009,928d7*82CjCKOhDRm5gROpSfgQ7B2axGVMWm5LuwNTkNDK2vjeGl7xvAsfsCINKmczXvO_Z45FsSVlJ1NHdlYlpSei1lYjdqUXRMaUpuRk9GbjVPS0psc3ZTcDFGRjhnNGhIbHRlZ0ZQRWQ1MUlUY2pnQ0lkTVRYNjlabmlUWGxHcVdkV3hrcElpa0ZEZEZRIIEC&bili_jct=3cdee5b84eb48d4f08bcfd57b58cf40b&gourl=https%3A%2F%2Fwww.bilibili.com%2F&first_domain=.bilibili.com", + "refresh_token": "43de156ad241864640f9d9721656a682" + } +} +``` + +
+ +
+查看响应头部示例: + +```http +HTTP/2 200 OK +date: Thu, 15 Aug 2024 09:10:09 GMT +content-type: application/json; charset=utf-8 +access-control-allow-credentials: true +access-control-allow-methods: GET,POST,PUT,DELETE +access-control-allow-origin: https://passport.bilibili.com +bili-status-code: 0 +bili-trace-id: 175262647666bdc5 +set-cookie: SESSDATA=xxxxxxx; Path=/; Domain=bilibili.com; Expires=Tue, 11 Feb 2025 09:10:09 GMT; HttpOnly; Secure +set-cookie: bili_jct=xxxxxxxxxxxxxxxxxxxxxxxxx; Path=/; Domain=bilibili.com; Expires=Tue, 11 Feb 2025 09:10:09 GMT +set-cookie: DedeUserID=114514191; Path=/; Domain=bilibili.com; Expires=Tue, 11 Feb 2025 09:10:09 GMT +set-cookie: DedeUserID__ckMd5=0123456789abcdef; Path=/; Domain=bilibili.com; Expires=Tue, 11 Feb 2025 09:10:09 GMT +set-cookie: sid=xxxxxxxx; Path=/; Domain=bilibili.com; Expires=Tue, 11 Feb 2025 09:10:09 GMT +vary: Origin +x-bili-trace-id: 60f0305e2abc511d175262647666bdc5 +access-control-allow-headers: Origin,No-Cache,X-Requested-With,If-Modified-Since,Pragma,Last-Modified,Cache-Control,Expires,Content-Type,Access-Control-Allow-Credentials,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Cache-Webcdn,x-bilibili-key-real-ip,x-backend-bili-real-ip,x-risk-header +cross-origin-resource-policy: cross-origin +access-control-expose-headers: X-Bili-Gaia-Vvoucher,X-Bili-Trace-Id +expires: Thu, 15 Aug 2024 09:10:08 GMT +cache-control: no-cache +x-cache-webcdn: BYPASS from blzone01 +content-encoding: br +X-Firefox-Spdy: h2 +``` + +
diff --git a/bb-api-collect/docs/login/login_action/readme.md b/bb-api-collect/docs/login/login_action/readme.md new file mode 100644 index 0000000000..f8915313fc --- /dev/null +++ b/bb-api-collect/docs/login/login_action/readme.md @@ -0,0 +1,164 @@ +# 登录操作 + +人机验证方式登录包含**账号密码登录**与**手机短信验证码登录** + +**注:扫码登录**不需要进行**人机验证**,故**不使用**以下接口 + +## 扫码登录 + +- [扫码登录](QR.md) + +## 验证登录 + +人机验证流程: + +1. 请求验证码参数,得到登录密钥`key`与极验id`gt`和极验KEY`challenge` +2. 进行滑动or点击验证 +3. 返回验证结果`validate`与`seccode`,进行短信或密码登录 + +### 申请captcha验证码 + +> https://passport.bilibili.com/x/passport-login/captcha?source=main_web + +*请求方式:GET* + +注: 另外参见 [密码登录-手机号验证-获取 captcha](password.md#获取-captcha) + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | -------- | --------- | +| code | num | 返回值 | 0:成功 | +| message | str | 返回信息 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ----- | ------ | -------- | +| geetest | obj | 极验captcha数据 | | +| tencent | obj | (?) | **作用尚不明确** | +| token | str | 登录 API token | 与 captcha 无关,与登录接口有关 | +| type | str | 验证方式 | 用于判断使用哪一种验证方式,目前所见只有极验
geetest:极验 | + +`geetest`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ----- | ------ | -------- | +| gt | str | 极验id | 一般为固定值 | +| challenge | str | 极验KEY | 由B站后端产生用于人机验证 | + +**示例:** + +```shell +curl 'https://passport.bilibili.com/x/passport-login/captcha?source=main_web' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "type": "geetest", + "token": "00fbe75cc2864ba0af969231f193a974", + "geetest": { + "challenge": "a57d9be17505d4a15ed84694c48fbf74", + "gt": "ac597a4506fee079629df5d8b66dd4fe" + }, + "tencent": { + "appid": "" + } + } +} +``` + +
+ +### 申请captcha验证码 (旧版) + +> http://passport.bilibili.com/web/captcha/combine + +*请求方式:GET* + +该接口曾从文档移除过, 经过测试仍可正常使用 + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------ | ------ | ---- | +| plat | num | 平台类型 | 必要 | 默认为 6 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | -------- | --------- | +| code | num | 返回值 | 0:成功 | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ----- | ------ | -------- | +| result | obj | 套了个娃 | | +| type | num | 1 | **作用尚不明确** | + +`result`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ----- | ------ | -------- | +| success | num | 1 | **作用尚不明确** | +| gt | str | 极验id | 一般为固定值 | +| challenge | str | 极验KEY | 由B站后端产生用于人机验证 | +| key | str | 登录秘钥 | 与 captcha 无关, 与登录接口有关, 亦作 token | + +**示例:** + +```shell +curl 'https://passport.bilibili.com/web/captcha/combine?plat=6' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "data": { + "result": { + "success": 1, + "gt": "bd111e81eda1cbb9f54425aafc0908ac", + "challenge": "2903a8eb967a1d990444cb23ea42f417", + "key": "76fb59fbd83a4d9d816162c5156fc964" + }, + "type": 1 + } +} +``` + +
+ +### 进行验证 + +本文档为 Bilibili 文档,验证码为 [geetest 极验](https://docs.geetest.com/sensebot/start/) 提供,故不提供相关 API + +附: [手动验证器](https://kuresaru.github.io/geetest-validator/) +[及其源码](https://github.com/kuresaru/geetest-validator) + +1. 打开手动验证器,在1、2分别填入上面API返回的`gt`和`challenge` +2. 点击按钮3,稍等加载验证码,点击按钮4进行验证 +3. 验证完成后,点击按钮5生成验证结果 +4. 使用最开始获得到的`key`、`challenge`和刚获得到的`validate`、`seccode`继续之后的登录操作 + +### 继续登录 + +- [短信登录](SMS.md) +- [密码登录](password.md) diff --git a/bb-api-collect/docs/login/login_info.md b/bb-api-collect/docs/login/login_info.md new file mode 100644 index 0000000000..c87c4b5b0b --- /dev/null +++ b/bb-api-collect/docs/login/login_info.md @@ -0,0 +1,645 @@ +# 登录基本信息 + +## 导航栏用户信息 + +> ~~https://api.bilibili.com/nav(带有转义)~~ (已失效) +> +> https://api.bilibili.com/x/web-interface/nav(原始数据) + +*请求方式:GET* + +认证方式:仅可Cookie(SESSDATA) + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------------- | ---- | ---------------- | ------------------------------------------------- | +| isLogin | bool | 是否已登录 | false:未登录
true:已登录 | +| email_verified | num | 是否验证邮箱地址 | 0:未验证
1:已验证 | +| face | str | 用户头像 url | | +| level_info | obj | 等级信息 | | +| mid | num | 用户 mid | | +| mobile_verified | num | 是否验证手机号 | 0:未验证
1:已验证 | +| money | num | 拥有硬币数 | | +| moral | num | 当前节操值 | 上限为70 | +| official | obj | 认证信息 | | +| officialVerify | obj | 认证信息 2 | | +| pendant | obj | 头像框信息 | | +| scores | num | (?) | | +| uname | str | 用户昵称 | | +| vipDueDate | num | 会员到期时间 | 毫秒 时间戳 | +| vipStatus | num | 会员开通状态 | 0:无
1:有 | +| vipType | num | 会员类型 | 0:无
1:月度大会员
2:年度及以上大会员 | +| vip_pay_type | num | 会员开通状态 | 0:无
1:有 | +| vip_theme_type | num | (?) | | +| vip_label | obj | 会员标签 | | +| vip_avatar_subscript | num | 是否显示会员图标 | 0:不显示
1:显示 | +| vip_nickname_color | str | 会员昵称颜色 | 颜色码 | +| wallet | obj | B币钱包信息 | | +| has_shop | bool | 是否拥有推广商品 | false:无
true:有 | +| shop_url | str | 商品推广页面 url | | +| allowance_count | num | (?) | | +| answer_status | num | (?) | | +| is_senior_member | num | 是否硬核会员 | 0:非硬核会员
1:硬核会员 | +| wbi_img | obj | Wbi 签名实时口令 | 该字段即使用户未登录也存在 | +| is_jury | bool | 是否风纪委员 | true:风纪委员
false:非风纪委员 | + +`data`中的`level_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ------------------------ | ---- | +| current_level | num | 当前等级 | | +| current_min | num | 当前等级经验最低值 | | +| current_exp | num | 当前经验 | | +| next_exp | 小于6级时:num
6级时:str | 升级下一等级需达到的经验 |当用户等级为Lv6时,值为`--`,代表无穷大 | + +`data`中的`official`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | -------- | ------------------------------------------------- | +| role | num | 认证类型 | 见[用户认证类型一览](../user/official_role.md) | +| title | str | 认证信息 | 无为空 | +| desc | str | 认证备注 | 无为空 | +| type | num | 是否认证 | -1:无
0:认证 | + +`data`中的`official_verify`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ------------------- | +| type | num | 是否认证 | -1:无
0:认证 | +| desc | str | 认证信息 | 无为空 | + +`data`中的`pendant`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ----------- | ---- | +| pid | num | 挂件id | | +| name | str | 挂件名称 | | +| image | str | 挂件图片url | | +| expire | num | (?) | | + +`data`中的`vip_label`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | -------- | ------------------------------------------------------------ | +| path | str | (?) | | +| text | str | 会员名称 | | +| label_theme | str | 会员标签 | vip:大会员
annual_vip:年度大会员
ten_annual_vip:十年大会员
hundred_annual_vip:百年大会员 | + +`data`中的`wallet`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | ------------- | ---- | +| 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/x/web-interface/nav' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "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": 172.4, + "moral": 70, + "official": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "officialVerify": { + "type": -1, + "desc": "" + }, + "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": 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", + "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 + } +} +``` + +
+ +**未登录状态:** + +```shell +curl 'https://api.bilibili.com/x/web-interface/nav' +``` + +
+查看响应示例: + +```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" + }, + } +} +``` + +
+ +## ~~登录用户信息仅部分(已弃用)~~ + +
+查看折叠内容 + +> https://account.bilibili.com/home/userInfo + +*请求方式:GET* + +认证方式:仅可Cookie(SESSDATA) + +鉴权方式:Cookie中`DedeUserID`存在且不为0 + +带有转义 + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| status | bool | true | 作用尚不明确 | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ---- | ----------------- | ------------------------------- | +| level_info | obj | 等级信息 | | +| bCoins | num | 拥有B币数 | | +| coins | num | 拥有硬币数 | | +| face | str | 登录用户头像url | | +| nameplate_current | null | ??? | 作用尚不明确 | +| nameplate_current | str | 登录用户勋章url | | +| pendant_current | str | 登录用户头像框url | | +| uname | str | 登录用户昵称 | | +| userStatus | str | 登录用户状态 | | +| vipType | num | 大会员类型 | 0:无
1:月度
2:年度 | +| vipStatus | num | 会员开通状态 | 0:无
1:有 | +| official_verify | num | 是否认证 | -1:无
0:认证 | +| pointBalance | num | 0 | 作用尚不明确 | + +`data`中的`level_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ------------------------ | ---- | +| current_level | num | 当前等级 | | +| current_min | num | 当前等级经验最低值 | | +| current_exp | num | 当前经验 | | +| next_exp | num | 升级下一等级需达到的经验 | | + +**示例:** + +```shell +curl 'https://account.bilibili.com/home/userInfo' \ +-b 'SESSDATA=xxx;DedeUserID=1;' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "status": true, + "data": { + "level_info": { + "current_level": 5, + "current_min": 10800, + "current_exp": 14270, + "next_exp": 28800 + }, + "bCoins": 10, + "coins": 2.5, + "face": "http:\/\/i2.hdslb.com\/bfs\/face\/480e2e98513aaeb65d2f2c76dbae750c4de722e9.jpg", + "nameplate_current": null, + "pendant_current": "http:\/\/i0.hdslb.com\/bfs\/face\/6550f53324c330f201a528e70ef305cb10ac2c01.png", + "uname": "\u793e\u4f1a\u6613\u59d0QwQ", + "userStatus": "\u6b63\u5f0f\u4f1a\u5458", + "vipType": 2, + "vipStatus": 1, + "official_verify": -1, + "pointBalance": 0 + } +} +``` + +
+ +
+ +## 登录用户信息(APP端) + +> https://app.bilibili.com/x/v2/account/myinfo + +*请求方式:GET* + +认证方式:仅可APP + +鉴权方式:appkey + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | ---- | +| access_key | str | APP登录Token | APP方式必要 | | +| appkey | str | APP密钥 | APP方式必要 | | +| ts | num | 当前时间戳 | APP方式必要 | | +| sign | str | APP签名 | APP方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-3:API校验密匙错误
-101:账号未登录
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | ---------------- | ----------------------------- | +| mid | num | 用户mid | | +| name | str | 用户昵称 | | +| sign | str | 用户签名 | | +| coins | num | 拥有硬币数 | | +| birthday | str | 用户生日 | YYYY-MM-DD | +| face | str | 用户头像url | | +| sex | num | 用户性别 | 0:私密
1:男
2:女 | +| level | num | 用户等级 | 0-6 | +| rank | num | 1000 | **作用尚不明确** | +| silence | num | 用户是否被封禁 | 0:正常
1:封禁 | +| vip | obj | 会员信息 | | +| email_status | num | 是否验证邮箱地址 | 0:未验证
1:已验证 | +| tel_status | num | 是否验证手机号 | 0:未验证
1:已验证 | +| official | obj | 认证信息 | | +| identification | num | 1 | **作用尚不明确** | +| invite | obj | | | +| is_tourist | num | 0 | **作用尚不明确** | +| pin_prompting | num | 0 | **作用尚不明确** | + +`data`中的`vip`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------------- | ---- | ---------------- | ------------------------------- | +| type | num | 大会员类型 | 0:无
1:月度
2:年度 | +| status | num | 会员开通状态 | 0:无
1:有 | +| due_date | num | 大会员到期时间 | 毫秒 时间戳 | +| vip_pay_type | num | 会员开通状态 | 0:无
1:有 | +| theme_type | num | 会员开通状态 | 0:无
1:有 | +| label | obj | 大会员信息 | | +| avatar_subscript | num | 是否显示会员图标 | 0:不显示
1:显示 | +| nickname_color | str | 会员昵称颜色 | 颜色码 | + +`vip`中的`label`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ------------ | ---------------- | +| path | str | 空 | **作用尚不明确** | +| text | str | 会员类型文字 | | +| label_theme | str | 会员类型 | | + +`data`中的`official`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | -------- | ------------------------------------------------- | +| role | num | 认证类型 | 0:无
1 2 7:个人认证
3 4 5 6:机构认证 | +| title | str | 认证信息 | 无为空 | +| desc | str | 认证备注 | 无为空 | +| type | num | 认证备注 | 无为空 | + +`data`中的`invite`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ---- | ---------------- | +| invite_remind | num | 1 | **作用尚不明确** | +| display | bool | true | **作用尚不明确** | + +**示例:** + +```shell +curl -G 'https://app.bilibili.com/x/v2/account/myinfo' \ +--data-urlencode 'access_key=xxx' \ +--data-urlencode 'appkey=4409e2ce8ffd12b8' \ +--data-urlencode 'ts=0' \ +--data-urlencode 'sign=b8fb8480049c525994be6507a97ae0b6' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "mid": 293793435, + "name": "社会易姐QwQ", + "sign": "高中技术宅一枚,爱好MC&电子&8-bit音乐&数码&编程,资深猿厨,粉丝群:1136462265", + "coins": 33.4, + "birthday": "2002-03-05", + "face": "http://i1.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg", + "sex": 1, + "level": 5, + "rank": 10000, + "silence": 0, + "vip": { + "type": 2, + "status": 1, + "due_date": 1612454400000, + "vip_pay_type": 1, + "theme_type": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299" + }, + "email_status": 1, + "tel_status": 1, + "official": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "identification": 1, + "invite": { + "invite_remind": 1, + "display": true + }, + "is_tourist": 0, + "pin_prompting": 0 + } +} +``` + +
+ + +## 登录用户状态数(双端) + +> https://api.bilibili.com/x/web-interface/nav/stat + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | ---- | +| access_key | str | APP登录Token | APP方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ---------- | ---- | +| following | num | 关注数 | | +| follower | num | 粉丝数 | | +| dynamic_count | num | 发布动态数 | | + +**示例:** + +当前登录用户的状态数为粉丝596,关注754,发送的动态252 + +Cookie方式: + +```shell +curl 'https://api.bilibili.com/x/web-interface/nav/stat' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "following": 754, + "follower": 596, + "dynamic_count": 252 + } +} +``` + +
+ +APP方式: + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/nav/stat' \ +--data-urlencode 'access_key=d907f51122c59599d580ade2315af971' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "following": 754, + "follower": 596, + "dynamic_count": 252 + } +} +``` + +
+ +## 获取硬币数 + +> https://account.bilibili.com/site/getCoin + +*请求方式:GET* + +认证方式:仅可Cookie(SESSDATA) + +鉴权方式:Cookie中` DedeUserID `存在且不为0 + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| status | bool | true | 作用尚不明确 | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | -------------------------------------- | ---------- | ---- | +| money | 硬币为正数时:num
硬币为0时:null | 当前硬币数 | | + +**示例:** + +```shell +curl 'https://account.bilibili.com/site/getCoin' \ +-b 'SESSDATA=xxx;DedeUserID=1;' +``` + +
+查看响应示例: + + +```json +{ + "code": 0, + "status": true, + "data": { + "money": 42.4 + } +} +``` + +
diff --git a/bb-api-collect/docs/login/login_notice.md b/bb-api-collect/docs/login/login_notice.md new file mode 100644 index 0000000000..720c0a24f2 --- /dev/null +++ b/bb-api-collect/docs/login/login_notice.md @@ -0,0 +1,269 @@ +# 登录记录 + +## 查询登录记录 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---------- | ------ | ------------------------------------------------------------ | +| mid | num | 用户mid | 必要 | 必须为自己的mid | +| buvid | str | 设备虚拟id | 非必要 | web端为操作登录接口时Cookie中的`buvid3`
若登录设备无`buvid`则留空 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误
-403:访问权限不足 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ----------- | -------------------------- | +| mid | num | 登录用户mid | | +| device_name | str | 登录设备 | 依靠操作登录接口时的UA决定 | +| login_type | str | 登录方式 | 根据登录接口决定 | +| login_time | str | 登录时间 | YYYY-MM-DD hh:mm:ss | +| location | str | 登录位置 | 依靠ip决定 | +| ip | str | 登录ip | 部分用`*`打码 | + +**示例:** + +查询用户`293793435`设备id为`fuck_chenrui`的登录记录 + +```shell +curl -G 'https://api.bilibili.com/x/safecenter/login_notice' \ + --data-urlencode 'mid=293793435' \ + --data-urlencode 'buvid=fuck_chenrui' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "mid": 293793435, + "device_name": "Chrome浏览器", + "login_type": "扫码登录", + "login_time": "2020-10-02 22:42:38", + "location": "中国陕西渭南", + "ip": "36.40.***.**" + } +} +``` + +
+ +## 最近一周的登录情况 + +> + +*请求方式: GET* + +认证方式: Cookie (SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---------- | ------ | -------- | +| jsonp | str | 回调函数名? | 非必要 | 默认 jsonp | +| web_location | str | 网页位置? | 非必要 | 默认 333.33 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------------ | ----- | +| count | num | 记录总数 | | +| list | arr | 登录记录列表 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | ---- | +| 0 | obj | 登录记录1 | | +| …… | obj | …… | | +| n | obj | 登录记录(n+1) | | + +`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------------- | ---- | +| ip | str | 登录 IP | IPv4:末 2 位以 `*` 打码
IPv6:末 5 位以 `*` 打码 | +| time | num | 登录时间 | UNIX 秒级时间戳 | +| time_at | str | 登录时间 | 格式为 `yyyy-MM-dd HH:mm:ss` | +| status | bool | 是否登录成功? | | +| type | num | 登录方式? | | +| geo | str | 登录地理位置 | | + +**示例:** + +查询本用户最近一周的登录情况 + +```shell +curl -G "https://api.bilibili.com/x/member/web/login/log" \ + -b "SESSDATA=xxx" +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "count": 15, + "list": [ + { + "ip": "240e:*:*:*:*:*:*:*", + "time": 1746038055, + "time_at": "2025-05-01 02:34:15", + "status": true, + "type": 0, + "geo": "中国广西梧州电信" + }, + { + "ip": "108.181.*.*", + "time": 1722036741, + "time_at": "2024-07-27 07:32:21", + "status": true, + "type": 0, + "geo": "美国加利福尼亚州洛杉矶telus.com" + }, + { + "ip": "104.28.*.*", + "time": 1722040653, + "time_at": "2024-07-27 08:37:33", + "status": true, + "type": 0, + "geo": "巴西" + }, + { + "ip": "104.28.*.*", + "time": 1721950332, + "time_at": "2024-07-26 07:32:12", + "status": true, + "type": 0, + "geo": "新加坡cloudflare.com" + }, + { + "ip": "104.28.*.*", + "time": 1721964627, + "time_at": "2024-07-26 11:30:27", + "status": true, + "type": 0, + "geo": "美国弗吉尼亚州雷斯顿cloudflare.com" + }, + { + "ip": "143.92.*.*", + "time": 1721861861, + "time_at": "2024-07-25 06:57:41", + "status": true, + "type": 0, + "geo": "中国香港特别行政区" + }, + { + "ip": "143.92.*.*", + "time": 1721861855, + "time_at": "2024-07-25 06:57:35", + "status": true, + "type": 0, + "geo": "中国香港特别行政区" + }, + { + "ip": "104.28.*.*", + "time": 1721709514, + "time_at": "2024-07-23 12:38:34", + "status": true, + "type": 0, + "geo": "日本千叶县成田市cloudflare.com" + }, + { + "ip": "104.28.*.*", + "time": 1721709618, + "time_at": "2024-07-23 12:40:18", + "status": true, + "type": 0, + "geo": "日本千叶县成田市cloudflare.com" + }, + { + "ip": "143.92.*.*", + "time": 1721636125, + "time_at": "2024-07-22 16:15:25", + "status": true, + "type": 0, + "geo": "中国香港特别行政区" + }, + { + "ip": "143.92.*.*", + "time": 1721636111, + "time_at": "2024-07-22 16:15:11", + "status": true, + "type": 0, + "geo": "中国香港特别行政区" + }, + { + "ip": "104.28.*.*", + "time": 1721539870, + "time_at": "2024-07-21 13:31:10", + "status": true, + "type": 0, + "geo": "美国加利福尼亚州东洛杉矶cloudflare.com" + }, + { + "ip": "104.28.*.*", + "time": 1721539965, + "time_at": "2024-07-21 13:32:45", + "status": true, + "type": 0, + "geo": "美国加利福尼亚州东洛杉矶cloudflare.com" + }, + { + "ip": "42.2.*.*", + "time": 1721477962, + "time_at": "2024-07-20 20:19:22", + "status": true, + "type": 0, + "geo": "中国香港特别行政区pccw.com" + }, + { + "ip": "42.2.*.*", + "time": 1721477960, + "time_at": "2024-07-20 20:19:20", + "status": true, + "type": 0, + "geo": "中国香港特别行政区pccw.com" + } + ] + } +} +``` + +
diff --git a/bb-api-collect/docs/login/member_center.md b/bb-api-collect/docs/login/member_center.md new file mode 100644 index 0000000000..7763e5bae6 --- /dev/null +++ b/bb-api-collect/docs/login/member_center.md @@ -0,0 +1,862 @@ +# 个人中心 + +## 获取我的信息 + +> https://api.bilibili.com/x/member/web/account + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | ---- | +| access_key | str | APP登录Token | APP方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | -------------- | --------------------------------------- | +| mid | num | 我的mid | | +| uname | str | 我的昵称 | | +| userid | str | 我的用户名 | | +| sign | str | 我的签名 | | +| birthday | str | 我的生日 | YYYY-MM-DD | +| sex | str | 我的性别 | 男 女 保密 | +| nick_free | bool | 是否未设置昵称 | false:设置过昵称
true:未设置昵称 | +| rank | str | 我的会员等级 | | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/member/web/account' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code":0, + "message":"0", + "ttl":1, + "data":{ + "mid":293793435, + "uname":"社会易姐QwQ", + "userid":"bili_84675323391", + "sign":"高中技术宅一枚,爱好MC&电子&8-bit音乐&数码&编程,资深猿厨,粉丝群:1136462265", + "birthday":"2002-03-05", + "sex":"男", + "nick_free":false, + "rank":"正式会员" + } +} +``` + +
+ +## 查询每日奖励状态 + +> https://api.bilibili.com/x/member/web/exp/reward + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | ---- | +| access_key | str | APP登录Token | APP方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | -------------------- | ------------------------------------------------------------ | +| login | bool | 每日登录 | false:未完成
true:已完成
完成奖励5经验 | +| watch | bool | 每日观看 | false:未完成
true:已完成
完成奖励5经验 | +| coins | num | 每日投币所奖励的经验 | 上限为50
注:该值更新存在延迟
[另外一个专门API](#查询每日投币获得经验数) | +| share | bool | 每日分享 | false:未完成
true:已完成
完成奖励5经验 | +| email | bool | 绑定邮箱 | false:未完成
true:已完成
首次完成奖励20经验 | +| tel | bool | 绑定手机号 | false:未完成
true:已完成
首次完成奖励100经验 | +| safe_question | bool | 设置密保问题 | false:未完成
true:已完成
首次完成奖励30经验 | +| identify_card | bool | 实名认证 | false:未完成
true:已完成
首次完成奖励50经验 | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/member/web/exp/reward' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "login": true, + "watch": true, + "coins": 30, + "share": true, + "email": true, + "tel": true, + "safe_question": true, + "identify_card": true + } +} +``` + +
+ +## 查询每日投币获得经验数 + +> ~~https://www.bilibili.com/plus/account/exp.php~~ (已失效) +> +> https://api.bilibili.com/x/web-interface/coin/today/exp + +*请求方式:GET* + +认证方式:仅可Cookie(SESSDATA) + +该接口实时更新,未发现延迟 + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------------------- | ----------- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | 默认为0 | +| data | num | 每日投币所奖励的经验 | 上限为50 | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/web-interface/coin/today/exp' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": 20 +} +``` + +
+ +## 查询大会员状态 + +> https://api.bilibili.com/x/vip/web/user/info + +*请求方式:GET* + +认证方式:仅可Cookie(SESSDATA) + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ---------------- | ------------------------------------------------------------ | +| mid | num | 我的mid | | +| vip_type | num | 大会员类型 | 0:无
1:月度
2:年度 | +| vip_status | num | 大会员状态 | 1:正常
2:由于IP地址更换过于频繁,服务被冻结
3:你的大会员账号风险过高,大会员功能已被锁定 | +| vip_due_date | num | 大会员到期时间 | 时间戳 毫秒 | +| vip_pay_type | num | 是否已购买大会员 | 0:未购买
1:已购买 | +| theme_type | num | 0 | 作用尚不明确 | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/vip/web/user/info' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "mid": 293793435, + "vip_type": 2, + "vip_status": 1, + "vip_due_date": 1612454400000, + "vip_pay_type": 1, + "theme_type": 0 + } +} +``` + +
+ +## 查询账号安全情况 + +> https://passport.bilibili.com/web/site/user/info + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +鉴权方式:如用Cookie方式认证时Cookie中`DedeUserID`存在且不为0 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | ---- | +| access_key | str | APP登录Token | APP方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ---------------- | ---- | +| account_info | obj | 账号绑定信息 | | +| account_safe | obj | 密码安全信息 | | +| account_sns | obj | 互联登录绑定信息 | | +| account_other | obj | | | + +`data`中的`account_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------ | ---- | -------------- | ------------------------------- | +| hide_tel | str | 绑定的手机号 | 星号隐藏部分信息 | +| hide_mail | str | 绑定的邮箱 | 星号隐藏部分信息 | +| bind_tel | bool | 是否绑定手机号 | false:未绑定
true:已绑定 | +| bind_mail | bool | 是否绑定邮箱 | false:未绑定
true:已绑定 | +| tel_verify | bool | 是否验证手机号 | false:未验证
true:已验证 | +| mail_verify | bool | 是否验证邮箱 | false:未验证
true:已验证 | +| unneeded_check | bool | 是否未设置密码 | false:已设置
true:未设置 | +| realname_certified | bool | 是否实名认证 | false:未认证
true:已认证 | + +`data`中的`account_safe`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ---------------- | ----------------------------- | +| Score | num | 账号安全等级 | 0-100
已弃用? | +| score_new | num | 新版账号安全等级 | 0-100 | +| pwd_level | num | 当前密码强度等级 | 1:弱
2:中
3:强 | +| security | bool | 当前密码是否安全 | false:不安全
true:安全 | + +`data`中的`account_sns`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ------------ | ------------------------ | +| weibo_bind | num | 是否绑定微博 | 0:未绑定
1:已绑定 | +| qq_bind | num | 是否绑定qq | 0:未绑定
1:已绑定 | +| wechat_bind | num | 是否绑定微信 | 0:未绑定
1:已绑定 | + +`data`中的`account_other`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ----- | ------------ | +| skipVerify | bool | false | 作用尚不明确 | + +**示例:** + +```shell +curl 'https://passport.bilibili.com/web/site/user/info' \ +-b 'SESSDATA=xxx;DedeUserID=1;' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "data": { + "account_info": { + "hide_tel": "153*****056", + "hide_mail": "144****@qq.com", + "bind_tel": true, + "bind_mail": true, + "tel_verify": true, + "mail_verify": true, + "unneeded_check": false, + "realname_certified": true + }, + "account_safe": { + "Score": 90, + "score_new": 100, + "pwd_level": 3, + "security": true + }, + "account_sns": { + "weibo_bind": 1, + "qq_bind": 1, + "wechat_bind": 1 + }, + "account_other": { + "skipVerify": false + } + } +} +``` + +
+ +## 查询账号实名认证状态 + +> https://api.bilibili.com/x/member/realname/status + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | ---- | +| access_key | str | APP登录Token | APP方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ------------ | ------------------------ | +| status | num | 实名认证状态 | 0:未认证
1:已认证 | + +**示例:** + +当前状态为已认证 + +```shell +curl 'https://api.bilibili.com/x/member/realname/status' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "status": 1 + } +} +``` + +
+ +## 查询实名认证详细信息 + +> https://api.bilibili.com/x/member/realname/apply/status + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | ---- | +| access_key | str | APP登录Token | APP方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | ------------------------------------------------------------ | +| status | num | 认证状态 | 1:已认证
3:未认证 | +| remark | str | 驳回信息 | 默认为空 | +| realname | str | 实名姓名 | 星号隐藏完全信息 | +| card | str | 证件号码 | 星号隐藏部分信息 | +| card_type | num | 证件类型代码 | 0:身份证
2:港澳居民来往内地通行证
3:台湾居民来往大陆通行证
4:护照(中国签发)
5:外国人永久居留证
6:其他国家或地区身份证明 | + +```shell +curl 'https://api.bilibili.com/x/member/realname/apply/status' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "status": 1, + "remark": "", + "realname": "***", + "card": "6****************7", + "card_type": 0 + } +} +``` + +
+ +## 查询硬币变化情况 + +> https://api.bilibili.com/x/member/web/coin/log + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +仅能查询最近一周的情况 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | ---- | +| access_key | str | APP登录Token | APP方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ------ | ---------------- | ---- | +| list | array | 变化记录条目列表 | | +| count | num | 变化记录条目数 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------------- | ---- | +| 0 | obj | 变化记录条目1 | | +| n | obj | 变化记录条目(n+1) | | +| …… | obj | …… | …… | + +`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | -------- | ---------------------- | +| time | str | 变化时间 | YYYY-MM-DD HH:MM:SS | +| delta | num | 变化量 | 正值为收入,负值为支出 | +| reason | str | 变化说明 | | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/member/web/coin/log' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "time": "2020-05-19 23:58:29", + "delta": -1, + "reason": "给视频 BV1j5411s7M8 打赏" + }, + { + "time": "2020-05-19 16:02:53", + "delta": -1, + "reason": "给视频 BV1Ht4y117A1 打赏" + }, + { + "time": "2020-05-19 15:38:42", + "delta": 0.1, + "reason": "给视频 BV1nb411C7aa 打赏" + }, + { + "time": "2020-05-19 02:19:20", + "delta": 1, + "reason": "登录奖励" + }, + { + "time": "2020-05-18 22:34:04", + "delta": -1, + "reason": "给视频 BV1Bp4y1Q7uw 打赏" + }, + { + "time": "2020-05-18 22:33:59", + "delta": -1, + "reason": "给视频 BV1j5411s7M8 打赏" + }, + { + "time": "2020-05-18 02:45:53", + "delta": 1, + "reason": "登录奖励" + }, + { + "time": "2020-05-17 03:02:38", + "delta": 1, + "reason": "登录奖励" + }, + { + "time": "2020-05-16 01:57:02", + "delta": 1, + "reason": "登录奖励" + }, + { + "time": "2020-05-15 11:10:35", + "delta": 0.2, + "reason": "给视频 BV1Yt41137T6 打赏" + }, + { + "time": "2020-05-15 00:34:27", + "delta": 1, + "reason": "登录奖励" + }, + { + "time": "2020-05-14 02:11:37", + "delta": 1, + "reason": "登录奖励" + }, + { + "time": "2020-05-13 02:12:28", + "delta": 1, + "reason": "登录奖励" + } + ], + "count": 13 + } +} +``` + +
+ +## 修改个人签名 + +> https://api.bilibili.com/x/member/web/sign/update + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或APP + +修改签名不会立即生效,会等待审核队列稍后生效 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | -------------------------------------------- | +| access_key | str | APP登录Token | APP方式必要 | | +| user_sign | str | 要设置的签名内容 | 非必要 | 删除签名留空或省去即可
最多支持70个字符 | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-111:csrf校验失败
40015:签名包含敏感词
40021:签名不能包含表情图片
40022:签名过长 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +更新个人标签为`高中技术宅一枚,爱好MC&电子&8-bit音乐&数码&编程,资深猿厨,粉丝群:1136462265` + +```shell +curl 'https://api.bilibili.com/x/member/web/sign/update' \ +--data-urlencode 'user_sign=高中技术宅一枚,爱好MC&电子&8-bit音乐&数码&编程,粉丝群:1136462265' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code":0, + "message":"0", + "ttl":1 +} +``` + +
+ +## 最近一周的经验记录 + +> https://api.bilibili.com/x/member/web/exp/log + +*请求方式: GET* + +认证方式: Cookie (SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---------- | ------ | -------- | +| jsonp | str | 回调函数名? | 非必要 | 默认 jsonp | +| web_location | str | 网页位置? | 非必要 | 默认 333.33 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---- | +| code | num | 返回值 | 0: 成功
-101: 账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ------ | ---------------- | ---- | +| list | array | 经验记录条目列表 | | +| count | num | 经验记录条目数 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----- | ---- | +| 0 | obj | 记录1 | | +| …… | obj | …… | …… | +| n | obj | 记录(n+1) | | + +`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | -------- | ---- | +| delta | num | 经验值 | | +| time | str | 记录时间 | 格式为 yyyy-MM-dd HH:mm:ss | +| reason | str | 记录原因 | | + +**示例:** + +```shell +curl -G "https://api.bilibili.com/x/member/web/exp/log" \ +-b "SESSDATA=xxx" +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "delta": 5, + "time": "2024-07-27 15:08:23", + "reason": "分享视频奖励" + }, + { + "delta": 5, + "time": "2024-07-27 08:28:21", + "reason": "登录奖励" + }, + { + "delta": 5, + "time": "2024-07-27 08:28:21", + "reason": "观看视频奖励" + }, + { + "delta": 5, + "time": "2024-07-26 12:44:19", + "reason": "登录奖励" + }, + { + "delta": 5, + "time": "2024-07-26 12:44:19", + "reason": "观看视频奖励" + }, + { + "delta": 20, + "time": "2024-07-25 06:58:49", + "reason": "视频投币奖励" + }, + { + "delta": 5, + "time": "2024-07-25 06:58:30", + "reason": "观看视频奖励" + }, + { + "delta": 5, + "time": "2024-07-25 06:58:30", + "reason": "登录奖励" + }, + { + "delta": 5, + "time": "2024-07-23 18:47:48", + "reason": "观看视频奖励" + }, + { + "delta": 5, + "time": "2024-07-23 18:47:48", + "reason": "登录奖励" + } + ], + "count": 10 + } +} +``` + +
+ +## 最近一周的节操记录 + +> https://api.bilibili.com/x/member/web/moral/log + +*请求方式: GET* + +认证方式: Cookie (SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---------- | ------ | -------- | +| jsonp | str | 回调函数名? | 非必要 | 默认 jsonp | +| web_location | str | 网页位置? | 非必要 | 默认 333.33 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---- | +| code | num | 返回值 | 0: 成功
-101: 账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ------ | ---------------- | ---- | +| moral | num | 节操值 | | +| list | array | 记录条目列表 | | +| count | num | 记录条目数 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----- | ---- | +| 0 | obj | 记录1 | | +| …… | obj | …… | …… | +| n | obj | 记录(n+1) | | + +`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ------ | ---------------- | ---- | +| time | string | 时间 | | +| delta | number | 变化 | | +| origin | string | 原因 | | +| reason | string | 说明 | | + +**示例:** + +```shell +curl -G "https://api.bilibili.com/x/member/web/moral/log" \ +-b "SESSDATA=xxx" +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "moral": 70, + "list": [], + "count": 0 + } +} +``` + +
diff --git a/bb-api-collect/docs/manga/Activity.md b/bb-api-collect/docs/manga/Activity.md new file mode 100644 index 0000000000..6a3d812a65 --- /dev/null +++ b/bb-api-collect/docs/manga/Activity.md @@ -0,0 +1,76 @@ +# 漫画任务操作 + +## 分享漫画 + +> https://manga.bilibili.com/twirp/activity.v1.Activity/ShareComic + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)/ APP + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ---- | ------ | ------- | +| platform | str | 平台 | 必要 | android | + +**json 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | --------- | -------- | ------------------------------------------------------- | +| code | num / str | 返回值 | 见对应表格 | +| msg | str | 错误信息 | | +| meta | obj | 错误信息 | invalid_argument 时存在,例如 `{"argument":"platform"}` | +| data | obj | | `code` 为 0,`msg` 为空时存在 | + +`code` - `msg` 对应表: + +| code | code 类型 | msg | 备注 | +| ---------------- | --------- | ------------------ | --------------------------- | +| 0 | num | 空 | 分享成功,`data` 存在 | +| 0 | num | 今日已分享 | | +| invalid_argument | str | xxxx must be valid | xxxx 字段为必须,`meta`存在 | +| unauthenticated | str | must login | 必须登录才能分享 | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | -------- | ---- | +| point | num | 获取积分 | | + +**示例:** + +```bash +curl -X POST https://manga.bilibili.com/twirp/activity.v1.Activity/ShareComic \ +-b "SESSDATA=xxxxx" \ +--data-urlencode 'platform=android' +``` + +
+分享成功: + +```json +{ + "code": 0, + "msg": "", + "data": { + "point": 5 + } +} +``` + +
+ +
+今日已分享: + +```json +{ + "code": 0, + "msg": "今日已分享" +} +``` + +
diff --git a/bb-api-collect/docs/manga/ClockIn.md b/bb-api-collect/docs/manga/ClockIn.md new file mode 100644 index 0000000000..36681ed3b0 --- /dev/null +++ b/bb-api-collect/docs/manga/ClockIn.md @@ -0,0 +1,217 @@ +# 签到 + +> https://manga.bilibili.com/twirp/activity.v1.Activity/ClockIn + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)/ APP + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|----------|-----|----|-----|---------| +| platform | str | 平台 | 必要 | android | +| device | str | 平台 | 非必要 | h5 | + +**正文参数( application/json ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|------|-----|------|-----|-------| +| type | num | | 非必要 | 补签时使用 | +| date | str | 补签日期 | 必要 | 补签时使用 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|------|-----------|------|--------------------------------------------| +| code | num / str | 返回值 | 0:成功
invalid_argument:今日已签到 | +| msg | str | 错误信息 | 成功:空
已签到:clockin clockin is duplicate | +| meta | obj | 错误信息 | 今日已签到时存在 | +| data | obj | | | + +**示例:** + +普通签到: + +```bash +curl -L -X POST 'https://manga.bilibili.com/twirp/activity.v1.Activity/ClockIn' \ +-H 'Cookie: SESSDATA=xxx' \ +-H 'Content-Type: application/x-www-form-urlencoded' \ +--data-urlencode 'platform=android' +``` + +
+签到成功: + +```json +{ + "code": 0, + "msg": "", + "data": {} +} +``` + +
+ +
+今日已签到: + +```json +{ + "code": "invalid_argument", + "msg": "clockin clockin is duplicate", + "meta": { + "argument": "clockin" + } +} +``` + +
+ +补签: + +```bash +curl -L 'https://manga.bilibili.com/twirp/activity.v1.Activity/ClockIn?platform=android' \ +-H 'Cookie: SESSDATA=xxx' \ +-H 'content-type: application/json;charset=UTF-8' \ +-d '{"type":0,"date":"2023-02-15"}' +``` + +
+补签成功: + +```json +{ + "code": 0, + "msg": "", + "data": {} +} +``` + +
+ +# 查询签到状态 + +> https://manga.bilibili.com/twirp/activity.v1.Activity/GetClockInInfo + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)/ APP + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|------|-----|------|------| +| code | num | 返回值 | 0:成功 | +| msg | str | 错误信息 | 空 | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------------|-------|------------------|------------------| +| day_count | num | 连续签到天数 | | +| status | num | 今日是否已签到 | 0:未签到
1:已签到 | +| credit_icon | str | | | +| sign_before_icon | str | | | +| sign_today_icon | str | | | +| breathe_icon | str | | | +| new_credit_x_icon | str | | | +| coupon_pic | str | | | +| points | array | 一次签到周期中每次签到可获得点数 | | +| point_infos | array | | | + +`point_infos`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------------|------|---------|----| +| point | num | 签到可获取积分 | | +| origin_point | num | | | +| is_activity | bool | | | +| title | str | 签到奖励描述 | | + +**示例:** + +```bash +curl -L -X POST 'https://manga.bilibili.com/twirp/activity.v1.Activity/GetClockInInfo' \ +-H 'Cookie: SESSDATA=xxx' +``` + +
+成功: + +```json +{ + "code": 0, + "msg": "", + "data": { + "day_count": 58, + "status": 1, + "points": [ + 10, + 20, + 20, + 10, + 10, + 10, + 30 + ], + "credit_icon": "https://i0.hdslb.com/bfs/static/manga/artifact/sign-resource/v2/9da6QImiK_w192_h192.png", + "sign_before_icon": "https://i0.hdslb.com/bfs/static/manga/artifact/sign-resource/v2/BuA6z3lhN_w192_h192.png", + "sign_today_icon": "https://i0.hdslb.com/bfs/static/manga/artifact/sign-resource/v2/TWSLUHbbg_w192_h192.png", + "breathe_icon": "http://i0.hdslb.com/bfs/static/manga/artifact/sign-resource/anime.breathe.svga", + "point_infos": [ + { + "point": 10, + "origin_point": 10, + "is_activity": false, + "title": "10积分" + }, + { + "point": 20, + "origin_point": 20, + "is_activity": false, + "title": "20积分" + }, + { + "point": 20, + "origin_point": 20, + "is_activity": false, + "title": "20积分" + }, + { + "point": 10, + "origin_point": 10, + "is_activity": false, + "title": "10积分" + }, + { + "point": 10, + "origin_point": 10, + "is_activity": false, + "title": "10积分" + }, + { + "point": 10, + "origin_point": 10, + "is_activity": false, + "title": "10积分" + }, + { + "point": 30, + "origin_point": 30, + "is_activity": false, + "title": "30积分+福利券" + } + ], + "new_credit_x_icon": "https://i0.hdslb.com/bfs/static/manga/artifact/sign-resource/v2/QP5DsW2S_w192_h192.png", + "coupon_pic": "https://i0.hdslb.com/bfs/static/manga/artifact/sign-resource/v2/Yalqqoiz_w402_h162.png" + } +} +``` + +
\ No newline at end of file diff --git a/bb-api-collect/docs/manga/Comic.md b/bb-api-collect/docs/manga/Comic.md new file mode 100644 index 0000000000..af9d4bb1a1 --- /dev/null +++ b/bb-api-collect/docs/manga/Comic.md @@ -0,0 +1,4223 @@ +# 购买漫画章节 + +> https://manga.bilibili.com/twirp/comic.v1.Comic/BuyEpisode + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)/ APP + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | ------------------------------------------------------------ | +| access_key | str | APP登录凭证 | 必要 | 使用APP鉴权方式时必填 | +| appkey | str | cc8617fd6961e070 | 非必要 | | +| mobi_app | str | android_comic | 非必要 | | +| version | str | 4.13.0 | 非必要 | | +| build | str | 36413002 | 非必要 | | +| channel | str | bilicomic | 非必要 | | +| platform | str | android | 必要 | | +| device | str | android | 非必要 | | +| buvid | str | | 非必要 | | +| machine | str | samsung+SM-G9730 | 非必要 | | +| is_teenager | num | 0 | 非必要 | | +| no_recommend | num | 0 | 非必要 | | +| ts | num | 秒级时间戳 | 非必要 | | + +**正文参数( application/json ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------------------ | ------ | ------------------------------------------------- | +| epId | num | 章节id | 必要 | | +| buyMethod | num | 购买方式 | 必要 | 2:漫读券
4:新人等免
5:通用券 | +| couponId | num | 漫读券id | 必要 | | +| comicId | num | 漫画id | 可选 | buyMethod:4为必要| +| autoPayGoldStatus | num | 2 | 可选 | buyMethod:2,5 为必要
buyMethod:4为不必要 | +| isPresale | num | 0 | 可选 | buyMethod:2,5 为必要
buyMethod:4为不必要 | + +漫读券购买 + +``` +{ + "epId": 484366, + "buyMethod": 2, + "couponId": 7461430, + "autoPayGoldStatus": 2, + "isPresale": 0 +} +``` + +等就免费(新人等免) +``` +{ + "ep_id": 321913, + "comic_id": 26564, + "buy_method": 4 +} +``` + +通用券购买 + +``` +{ + "epId": 484366, + "buyMethod": 5, + "couponId": 0, + "autoPayGoldStatus": 2, + "payAmount": 1, + "isPresale": 0 +} +``` + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
0:本话无需购买
1:没有足够的卡券使用次数
| +| msg | str | 错误信息 | | + +**示例:** + +```bash +curl -L -X POST 'https://manga.bilibili.com/twirp/comic.v1.Comic/BuyEpisode?platform=android' \ +-H 'Cookie: SESSDATA=xxx;' \ +-H 'Content-Type: application/json' \ +--data-raw '{ + "epId": 484366, + "buyMethod": 2, + "couponId": 7461430, + "autoPayGoldStatus": 2, + "isPresale": 0 +}' +``` + +
+购买成功: + +```json +{ + "code": 0, + "msg": "", + "data": { + "auto_use_item": "" + } +} +``` + +
+ +# 获取漫画详情 + +> https://manga.bilibili.com/twirp/comic.v1.Comic/ComicDetail + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)/ APP + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | ------------------------------------------------------------ | +| access_key | str | APP登录凭证 | 非必要 | 可不登录访问 | +| appkey | str | cc8617fd6961e070 | 非必要 | | +| mobi_app | str | android_comic | 非必要 | | +| version | str | 4.13.0 | 非必要 | | +| build | str | 36413002 | 非必要 | | +| channel | str | bilicomic | 非必要 | | +| platform | str | android | 非必要 | 可选值:web/android | +| device | str | android | 必要 | 如不填则不会获取ep_list信息,可选值:pc/android | +| buvid | str | | 非必要 | | +| machine | str | samsung+SM-G9730 | 非必要 | | +| is_teenager | num | 0 | 非必要 | | +| no_recommend | num | 0 | 非必要 | | +| ts | num | 秒级时间戳 | 非必要 | | + +**正文参数( application/json ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------------------ | ------ | ------------------------------------------------- | +| comicId | num | 漫画id | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功 | +| msg | str | 错误信息 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| id | num | 漫画id | | +| title | str | 漫画名称 | | +| comic_type | num | 0,1 | | +| page_default | num | 0,1,2,4,8 | | +| page_allow | num | | | +| horizontal_cover | str | 横板封面 | | +| square_cover | str | 方形封面 | | +| vertical_cover | str | 竖版封面 | | +| author_name | array | 作者列表 | | +| styles | array | | | +| last_ord | num | 最新一话序号 | | +| is_finish | num | 完结状态
0:未完结 1:已完结 | | +| status | num | -1,0 | | +| fav | num | | | +| read_order | num | | | +| evaluate | num | 漫画简介 | | +| total | num | 总话数 | | +| ep_list | array | 章节信息 | | +| release_time | str | | | +| is_limit | num | | | +| read_epid | num | | | +| last_read_time | str | | | +| is_download | num | | | +| read_short_title | str | | | +| styles2 | array | | | +| renewal_time | str | | | +| last_short_title | str | 最新一话短标题 | | +| discount_type | num | | | +| discount | num | | | +| discount_end | str | | | +| no_reward | bool | | | +| batch_discount_type | num | | | +| ep_discount_type | num | | | +| has_fav_activity | bool | | | +| fav_free_amount | num | | | +| allow_wait_free | bool | 是否等就免费 | | +| wait_hour | num | 等待时间(小时) | | +| wait_free_at | num | 等待时间(小时) | | +| no_danmaku | num | | | +| auto_pay_status | num | | | +| no_month_ticket | bool | | | +| immersive | bool | | | +| no_discount | bool | | | +| show_type | num | | | +| pay_mode | num | | | +| chapters | array | | | +| classic_lines | str | 漫画简介 | | +| pay_for_new | num | | | +| fav_comic_info | obj | | | +| serial_status | num | | | +| series_info | obj | | | +| album_count | num | | | +| wiki_id | num | | | +| disable_coupon_amount | num | | | +| japan_comic | bool |是否为日本漫画 | | +| interact_value | num | | | +| temporary_finish_time | str | | | +| video | | | | +| introduction | str | 介绍| | +| comment_status | num | | | +| no_screenshot | bool | | | +| type | num | | | +| vomic_cvs | array | | | +| no_rank | bool | | | +| presale_eps | array | | | +| presale_text | str | | | +| presale_discount | num | | | +| no_leaderboard | bool | | | + +`ep_list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| id | num | 章节id | | +| ord | num | 章节序号,最新章节排在前面 | | +| read | num | 是否阅读过,0:没有 1:阅读过 | | +| pay_mode | num | | | +| is_locked | bool | 是否处于锁定状态 | | +| pay_gold | num | 解锁所需漫币 | | +| size | num | 文件大小(字节) | | +| short_title | str | 短标题 | | +| is_in_free | bool | | | +| title | str | 标题 | | +| cover | str | 封面 | | +| pub_time | str | 发布日期 | | +| comments | num | 评论数 | | +| unlock_expire_at | str | | | +| unlock_type | num | | | +| allow_wait_free | bool | | | +| progress | str | | | +| like_count | num | 点赞数 | | +| chapter_id | num | | | +| type | num | | | +| extra | num | | | + +`styles2`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| id | num | 漫画风格id | | +| name | str | 漫画风格名称 | | + +`fav_comic_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| has_fav_activity | bool | | | +| fav_free_amount | num | | | +| fav_coupon_type | num | | | + +`series_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| id | num | | | +| comics | array | | | + +**示例:** + +```bash +curl -L -X POST 'https://manga.bilibili.com/twirp/comic.v1.Comic/ComicDetail?device=pc' \ +-H 'Content-Type: application/json' \ +--data-raw '{ + "comicId": 28500 +}' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "", + "data": { + "id": 28500, + "title": "夏日重现", + "comic_type": 1, + "page_default": 4, + "page_allow": 15, + "horizontal_cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "square_cover": "http://i0.hdslb.com/bfs/manga-static/35fa9fa6190aa528f26f6e1341d9ee80b66b535f.jpg", + "vertical_cover": "https://i0.hdslb.com/bfs/manga-static/965cdb5c83e0b2066b4b60973ba7f4242f592967.jpg", + "author_name": [ + "田中靖规", + "集英社" + ], + "styles": [ + "悬疑灵异" + ], + "last_ord": 152, + "is_finish": 1, + "status": 0, + "fav": 0, + "read_order": 0, + "evaluate": "【此漫画的翻译由版权方提供】青梅竹马的潮死了——。听闻这个悲报,慎平回到了阔别已久的故乡和歌山市·日都岛与家人再会并出席葬礼。但是岛上貌似陡生异变,充斥着不寻常的气息……?\n夏日孤岛上的悬疑剧!!\n\n", + "total": 167, + "ep_list": [ + { + "id": 779804, + "ord": 152, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 17973126, + "short_title": "后篇(4)", + "is_in_free": false, + "title": "2026未然凶宅-后篇(4)", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-12 00:00:00", + "comments": 218, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 458, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 779788, + "ord": 151, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 17654401, + "short_title": "后篇(3)", + "is_in_free": false, + "title": "2026未然凶宅-后篇(3)", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-12 00:00:00", + "comments": 31, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 171, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 779782, + "ord": 150, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 18250988, + "short_title": "后篇(2)", + "is_in_free": false, + "title": "2026未然凶宅-后篇(2)", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-12 00:00:00", + "comments": 39, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 179, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 779752, + "ord": 149, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 19374429, + "short_title": "后篇(1)", + "is_in_free": false, + "title": "2026未然凶宅-后篇(1)", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-12 00:00:00", + "comments": 41, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 174, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 779751, + "ord": 148, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 20993207, + "short_title": "前篇(3)", + "is_in_free": false, + "title": "2026未然凶宅-前篇(3)", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-12 00:00:00", + "comments": 52, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 187, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 779749, + "ord": 147, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 17048075, + "short_title": "前篇(2)", + "is_in_free": false, + "title": "2026未然凶宅-前篇(2)", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-12 00:00:00", + "comments": 60, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 191, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 779748, + "ord": 146, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 21462932, + "short_title": "前篇(1)", + "is_in_free": false, + "title": "2026未然凶宅-前篇(1)", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-12 00:00:00", + "comments": 151, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 233, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 546499, + "ord": 145, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 26980054, + "short_title": "139", + "is_in_free": false, + "title": "第139话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2021-02-01 12:00:00", + "comments": 1314, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 3241, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 543783, + "ord": 144, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 33822142, + "short_title": "138", + "is_in_free": false, + "title": "第138话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2021-01-25 12:00:00", + "comments": 232, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 514, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 539917, + "ord": 143, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 20551895, + "short_title": "137", + "is_in_free": false, + "title": "第137话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2021-01-11 12:00:00", + "comments": 124, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 461, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 529960, + "ord": 142, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 18729857, + "short_title": "136", + "is_in_free": false, + "title": "第136话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-12-28 12:00:00", + "comments": 112, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 432, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 526882, + "ord": 141, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 9528871, + "short_title": "135", + "is_in_free": false, + "title": "第135话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-12-21 12:00:00", + "comments": 64, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 397, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 524737, + "ord": 140, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 4658617, + "short_title": "记录", + "is_in_free": false, + "title": "023", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-12-14 12:00:00", + "comments": 63, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 368, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 520819, + "ord": 139, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 19569820, + "short_title": "134", + "is_in_free": false, + "title": "第134话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-12-07 12:00:00", + "comments": 234, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 411, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 518563, + "ord": 138, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 0, + "short_title": "133", + "is_in_free": false, + "title": "第133话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-11-30 12:00:00", + "comments": 52, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 404, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 516460, + "ord": 137, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 16923412, + "short_title": "132", + "is_in_free": false, + "title": "第132话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-11-23 12:00:00", + "comments": 66, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 408, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 513494, + "ord": 136, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 22397411, + "short_title": "131", + "is_in_free": false, + "title": "第131话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-11-16 00:00:00", + "comments": 73, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 385, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 509309, + "ord": 135, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 11417949, + "short_title": "130", + "is_in_free": false, + "title": "第130话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-11-02 12:00:00", + "comments": 121, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 415, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 507403, + "ord": 134, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 13421937, + "short_title": "129", + "is_in_free": false, + "title": "第129话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-26 00:00:00", + "comments": 108, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 382, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 505464, + "ord": 133, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 0, + "short_title": "128", + "is_in_free": false, + "title": "第128话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 101, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 414, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 504084, + "ord": 132, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 714738, + "short_title": "记录", + "is_in_free": false, + "title": "022", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 38, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 327, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 503749, + "ord": 131, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 13733489, + "short_title": "127", + "is_in_free": false, + "title": "第127话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 87, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 383, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 498378, + "ord": 130, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 0, + "short_title": "126", + "is_in_free": false, + "title": "第126话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 83, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 392, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 496100, + "ord": 129, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 17044238, + "short_title": "125", + "is_in_free": false, + "title": "第125话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 59, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 378, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494999, + "ord": 128, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 19000950, + "short_title": "124", + "is_in_free": false, + "title": "第124话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 53, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 369, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494997, + "ord": 127, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 757788, + "short_title": "记录", + "is_in_free": false, + "title": "021", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 73, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 295, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494996, + "ord": 126, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 25583325, + "short_title": "123", + "is_in_free": false, + "title": "第123话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 88, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 341, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494995, + "ord": 125, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 22945986, + "short_title": "122", + "is_in_free": false, + "title": "第122话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 114, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 382, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494994, + "ord": 124, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 22007815, + "short_title": "121", + "is_in_free": false, + "title": "第121话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 60, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 336, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494992, + "ord": 123, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 14200387, + "short_title": "120", + "is_in_free": false, + "title": "第120话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 98, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 349, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494990, + "ord": 122, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 20253075, + "short_title": "119", + "is_in_free": false, + "title": "第119话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 153, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 352, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494986, + "ord": 121, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 34545559, + "short_title": "118", + "is_in_free": false, + "title": "第118话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 97, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 353, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494983, + "ord": 120, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 26875814, + "short_title": "117", + "is_in_free": false, + "title": "第117话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 38, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 326, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494982, + "ord": 119, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 24302773, + "short_title": "116", + "is_in_free": false, + "title": "第116话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 60, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 311, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494981, + "ord": 118, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 22563845, + "short_title": "115", + "is_in_free": false, + "title": "第115话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 103, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 332, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494979, + "ord": 117, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 26357441, + "short_title": "114", + "is_in_free": false, + "title": "第114话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 190, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 325, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494978, + "ord": 116, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 3055913, + "short_title": "记录", + "is_in_free": false, + "title": "020", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 27, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 303, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494977, + "ord": 115, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 27213199, + "short_title": "113", + "is_in_free": false, + "title": "第113话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 131, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 344, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494876, + "ord": 114, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 27036215, + "short_title": "112", + "is_in_free": false, + "title": "第112话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 84, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 306, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494872, + "ord": 113, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 18077367, + "short_title": "111", + "is_in_free": false, + "title": "第111话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 66, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 317, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494852, + "ord": 112, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 6547152, + "short_title": "记录", + "is_in_free": false, + "title": "019", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 20, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 286, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494849, + "ord": 111, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 17709563, + "short_title": "110", + "is_in_free": false, + "title": "第110话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 42, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 326, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494848, + "ord": 110, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 0, + "short_title": "109", + "is_in_free": false, + "title": "第109话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 42, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 325, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494847, + "ord": 109, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 20356850, + "short_title": "108", + "is_in_free": false, + "title": "第108话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 52, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 322, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494846, + "ord": 108, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 21075013, + "short_title": "107", + "is_in_free": false, + "title": "第107话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 29, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 314, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494698, + "ord": 107, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 19078032, + "short_title": "106", + "is_in_free": false, + "title": "第106话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 81, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 320, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494696, + "ord": 106, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 21291294, + "short_title": "105", + "is_in_free": false, + "title": "第105话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 56, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 350, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494691, + "ord": 105, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 22030863, + "short_title": "104", + "is_in_free": false, + "title": "第104话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 56, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 305, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494690, + "ord": 104, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 17400960, + "short_title": "103", + "is_in_free": false, + "title": "第103话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 33, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 304, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494688, + "ord": 103, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 0, + "short_title": "102", + "is_in_free": false, + "title": "第102话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 53, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 329, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 552061, + "ord": 102.5, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 1922541, + "short_title": "记录", + "is_in_free": false, + "title": "018", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-12 00:00:00", + "comments": 8, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 30, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494682, + "ord": 102, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 20268719, + "short_title": "101", + "is_in_free": false, + "title": "第101话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 92, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 317, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494666, + "ord": 101, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 17542840, + "short_title": "100", + "is_in_free": false, + "title": "第100话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 48, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 323, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494665, + "ord": 100, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 27598387, + "short_title": "99", + "is_in_free": false, + "title": "第99话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 109, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 350, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494664, + "ord": 99, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 24852154, + "short_title": "98", + "is_in_free": false, + "title": "第98话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 64, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 326, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494663, + "ord": 98, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 20721168, + "short_title": "97", + "is_in_free": false, + "title": "第97话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 57, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 309, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494656, + "ord": 97, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 15000137, + "short_title": "96", + "is_in_free": false, + "title": "第96话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 126, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 339, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 552060, + "ord": 96.5, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 3910437, + "short_title": "记录", + "is_in_free": false, + "title": "017", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-12 00:00:00", + "comments": 5, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 30, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494650, + "ord": 96, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 25062481, + "short_title": "95", + "is_in_free": false, + "title": "第95话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 89, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 360, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494645, + "ord": 95, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 19376143, + "short_title": "94", + "is_in_free": false, + "title": "第94话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 82, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 397, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494638, + "ord": 94, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 34661163, + "short_title": "93", + "is_in_free": false, + "title": "第93话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 64, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 352, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494637, + "ord": 93, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 33798923, + "short_title": "92", + "is_in_free": false, + "title": "第92话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 55, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 350, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494632, + "ord": 92, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 19784232, + "short_title": "91", + "is_in_free": false, + "title": "第91话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 81, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 387, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494627, + "ord": 91, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 18532096, + "short_title": "90", + "is_in_free": false, + "title": "第90话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 121, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 371, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 494009, + "ord": 90, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 19527018, + "short_title": "89", + "is_in_free": false, + "title": "第89话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 57, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 330, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 552059, + "ord": 89.5, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 2034891, + "short_title": "记录", + "is_in_free": false, + "title": "016", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-12 00:00:00", + "comments": 14, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 33, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 493979, + "ord": 89, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 18494693, + "short_title": "88", + "is_in_free": false, + "title": "第88话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 87, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 351, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 493950, + "ord": 88, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 17416462, + "short_title": "87", + "is_in_free": false, + "title": "第87话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 71, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 343, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 493944, + "ord": 87, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 0, + "short_title": "86", + "is_in_free": false, + "title": "第86话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 88, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 357, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 552058, + "ord": 86.5, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 4837743, + "short_title": "记录", + "is_in_free": false, + "title": "015", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-10 00:00:00", + "comments": 9, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 42, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491230, + "ord": 86, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 21039936, + "short_title": "85", + "is_in_free": false, + "title": "第85话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 59, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 319, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491229, + "ord": 85, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 14463535, + "short_title": "84", + "is_in_free": false, + "title": "第84话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 87, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 344, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 552057, + "ord": 84.5, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 11625156, + "short_title": "记录", + "is_in_free": false, + "title": "014", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-10 00:00:00", + "comments": 12, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 46, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491228, + "ord": 84, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 15900351, + "short_title": "83", + "is_in_free": false, + "title": "第83话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 71, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 347, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491227, + "ord": 83, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 19182670, + "short_title": "82", + "is_in_free": false, + "title": "第82话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 67, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 355, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491226, + "ord": 82, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 18627336, + "short_title": "81", + "is_in_free": false, + "title": "第81话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 45, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 347, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491225, + "ord": 81, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 15574642, + "short_title": "80", + "is_in_free": false, + "title": "第80话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 51, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 346, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491224, + "ord": 80, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 24885059, + "short_title": "79", + "is_in_free": false, + "title": "第79话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 79, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 350, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491223, + "ord": 79, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 22427296, + "short_title": "78", + "is_in_free": false, + "title": "第78话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 80, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 356, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 552056, + "ord": 78.5, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 1551067, + "short_title": "记录", + "is_in_free": false, + "title": "013", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-12 00:00:00", + "comments": 5, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 38, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491222, + "ord": 78, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 18725322, + "short_title": "77", + "is_in_free": false, + "title": "第77话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 100, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 354, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491221, + "ord": 77, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 16185606, + "short_title": "76", + "is_in_free": false, + "title": "第76话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 59, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 341, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491220, + "ord": 76, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 18886387, + "short_title": "75", + "is_in_free": false, + "title": "第75话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 88, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 370, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491215, + "ord": 75, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 19228812, + "short_title": "74", + "is_in_free": false, + "title": "第74话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 106, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 343, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 552054, + "ord": 74.5, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 1106084, + "short_title": "记录", + "is_in_free": false, + "title": "012", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-12 00:00:00", + "comments": 9, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 43, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491214, + "ord": 74, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 17213820, + "short_title": "73", + "is_in_free": false, + "title": "第73话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 105, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 358, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 552053, + "ord": 73.5, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 1510250, + "short_title": "记录", + "is_in_free": false, + "title": "011", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-10 00:00:00", + "comments": 7, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 46, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491213, + "ord": 73, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 12514556, + "short_title": "72", + "is_in_free": false, + "title": "第72话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 38, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 356, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491212, + "ord": 72, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 24337518, + "short_title": "71", + "is_in_free": false, + "title": "第71话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 45, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 353, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491211, + "ord": 71, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 22329539, + "short_title": "70", + "is_in_free": false, + "title": "第70话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 45, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 343, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491210, + "ord": 70, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 12721444, + "short_title": "69", + "is_in_free": false, + "title": "第69话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 59, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 363, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491209, + "ord": 69, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 14948018, + "short_title": "68", + "is_in_free": false, + "title": "第68话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 48, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 363, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491208, + "ord": 68, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 19604576, + "short_title": "67", + "is_in_free": false, + "title": "第67话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 97, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 370, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491207, + "ord": 67, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 18529368, + "short_title": "66", + "is_in_free": false, + "title": "第66话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 136, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 386, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491206, + "ord": 66, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 19616688, + "short_title": "65", + "is_in_free": false, + "title": "第65话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 79, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 350, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 491205, + "ord": 65, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 17889729, + "short_title": "64", + "is_in_free": false, + "title": "第64话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 77, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 369, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 552052, + "ord": 64.5, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 1729726, + "short_title": "记录", + "is_in_free": false, + "title": "010", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-10 00:00:00", + "comments": 47, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 47, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485887, + "ord": 64, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 24816564, + "short_title": "63", + "is_in_free": false, + "title": "第63话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 96, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 363, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485886, + "ord": 63, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 21990493, + "short_title": "62", + "is_in_free": false, + "title": "第62话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 161, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 377, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485885, + "ord": 62, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 16121252, + "short_title": "61", + "is_in_free": false, + "title": "第61话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 35, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 338, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485884, + "ord": 61, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 23868117, + "short_title": "60", + "is_in_free": false, + "title": "第60话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 54, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 353, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485883, + "ord": 60, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 14907334, + "short_title": "59", + "is_in_free": false, + "title": "第59话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 57, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 360, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485882, + "ord": 59, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 21003716, + "short_title": "58", + "is_in_free": false, + "title": "第58话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 49, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 362, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485881, + "ord": 58, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 21336454, + "short_title": "57", + "is_in_free": false, + "title": "第57话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 43, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 335, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485880, + "ord": 57, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 15975510, + "short_title": "56", + "is_in_free": false, + "title": "第56话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 43, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 346, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485879, + "ord": 56, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 16073891, + "short_title": "55", + "is_in_free": false, + "title": "第55话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 48, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 352, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 552051, + "ord": 55.5, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 1380370, + "short_title": "记录", + "is_in_free": false, + "title": "009", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-12 00:00:00", + "comments": 8, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 49, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485878, + "ord": 55, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 13480749, + "short_title": "54", + "is_in_free": false, + "title": "第54话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 56, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 357, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485877, + "ord": 54, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 21882584, + "short_title": "53", + "is_in_free": false, + "title": "第53话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 38, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 372, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485853, + "ord": 53, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 23862198, + "short_title": "52", + "is_in_free": false, + "title": "第52话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 56, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 388, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485852, + "ord": 52, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 23267613, + "short_title": "51", + "is_in_free": false, + "title": "第51话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 43, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 370, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485851, + "ord": 51, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 17028529, + "short_title": "50", + "is_in_free": false, + "title": "第50话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 63, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 380, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485850, + "ord": 50, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 21963399, + "short_title": "49", + "is_in_free": false, + "title": "第49话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 122, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 418, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 552050, + "ord": 49.5, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 1650224, + "short_title": "记录", + "is_in_free": false, + "title": "008", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-12 00:00:00", + "comments": 15, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 57, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485849, + "ord": 49, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 0, + "short_title": "48", + "is_in_free": false, + "title": "第48话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 71, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 392, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485848, + "ord": 48, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 18582327, + "short_title": "47", + "is_in_free": false, + "title": "第47话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 64, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 401, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485847, + "ord": 47, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 28025152, + "short_title": "46", + "is_in_free": false, + "title": "第46话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 78, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 444, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485846, + "ord": 46, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 18644930, + "short_title": "45", + "is_in_free": false, + "title": "第45话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 27, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 402, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485845, + "ord": 45, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 17555220, + "short_title": "44", + "is_in_free": false, + "title": "第44话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 71, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 418, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485844, + "ord": 44, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 23713922, + "short_title": "43", + "is_in_free": false, + "title": "第43话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 41, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 392, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485842, + "ord": 43, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 22048242, + "short_title": "42", + "is_in_free": false, + "title": "第42话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 36, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 400, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485841, + "ord": 42, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 17956496, + "short_title": "41", + "is_in_free": false, + "title": "第41话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 45, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 423, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485840, + "ord": 41, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 20461324, + "short_title": "40", + "is_in_free": false, + "title": "第40话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 102, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 441, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485839, + "ord": 40, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 16463871, + "short_title": "39", + "is_in_free": false, + "title": "第39话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 38, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 404, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485836, + "ord": 39, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 18664684, + "short_title": "38", + "is_in_free": false, + "title": "第38话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 42, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 403, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485835, + "ord": 38, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 17811979, + "short_title": "37", + "is_in_free": false, + "title": "第37话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 46, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 422, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 552049, + "ord": 37.5, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 4923840, + "short_title": "记录", + "is_in_free": false, + "title": "005~007", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-12 00:00:00", + "comments": 9, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 59, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485834, + "ord": 37, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 22221360, + "short_title": "36", + "is_in_free": false, + "title": "第36话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 78, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 410, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485833, + "ord": 36, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 19204738, + "short_title": "35", + "is_in_free": false, + "title": "第35话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 42, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 397, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485832, + "ord": 35, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 17688181, + "short_title": "34", + "is_in_free": false, + "title": "第34话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 43, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 407, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485831, + "ord": 34, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 14314953, + "short_title": "33", + "is_in_free": false, + "title": "第33话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 138, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 430, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 485826, + "ord": 33, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 15190983, + "short_title": "32", + "is_in_free": false, + "title": "第32话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 80, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 409, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484535, + "ord": 32, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 21701429, + "short_title": "31", + "is_in_free": false, + "title": "第31话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 81, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 408, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484534, + "ord": 31, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 15619952, + "short_title": "30", + "is_in_free": false, + "title": "第30话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 61, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 429, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484528, + "ord": 30, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 18250579, + "short_title": "29", + "is_in_free": false, + "title": "第29话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 60, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 435, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484526, + "ord": 29, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 27051218, + "short_title": "28", + "is_in_free": false, + "title": "第28话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 59, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 406, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484514, + "ord": 28, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 0, + "short_title": "27", + "is_in_free": false, + "title": "第27话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 63, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 420, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484507, + "ord": 27, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 17113482, + "short_title": "26", + "is_in_free": false, + "title": "第26话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 98, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 447, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484500, + "ord": 26, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 14359689, + "short_title": "25", + "is_in_free": false, + "title": "第25话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 63, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 407, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484483, + "ord": 25, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 15182223, + "short_title": "24", + "is_in_free": false, + "title": "第24话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 55, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 421, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484478, + "ord": 24, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 20914179, + "short_title": "23", + "is_in_free": false, + "title": "第23话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 75, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 447, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484474, + "ord": 23, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 17764811, + "short_title": "22", + "is_in_free": false, + "title": "第22话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 65, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 434, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484461, + "ord": 22, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 27296421, + "short_title": "21", + "is_in_free": false, + "title": "第21话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 51, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 441, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484443, + "ord": 21, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 15462050, + "short_title": "记录", + "is_in_free": false, + "title": "004", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 115, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 455, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484433, + "ord": 20, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 20824911, + "short_title": "20", + "is_in_free": false, + "title": "第20话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 127, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 497, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484422, + "ord": 19, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 25714866, + "short_title": "19", + "is_in_free": false, + "title": "第19话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 106, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 537, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484395, + "ord": 18, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 24927577, + "short_title": "18", + "is_in_free": false, + "title": "第18话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 94, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 527, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484387, + "ord": 17, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 0, + "short_title": "17", + "is_in_free": false, + "title": "第17话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 48, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 493, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484377, + "ord": 16, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 19775909, + "short_title": "16", + "is_in_free": false, + "title": "第16话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 70, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 503, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 552046, + "ord": 15.5, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 3261603, + "short_title": "记录", + "is_in_free": false, + "title": "003", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2021-02-18 13:17:06", + "comments": 39, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 385, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484376, + "ord": 15, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 23101595, + "short_title": "15", + "is_in_free": false, + "title": "第15话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 97, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 510, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484375, + "ord": 14, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 21456269, + "short_title": "14", + "is_in_free": false, + "title": "第14话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 130, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 510, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484373, + "ord": 13, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 22942430, + "short_title": "13", + "is_in_free": false, + "title": "第13话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 64, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 522, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484372, + "ord": 12, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 20225389, + "short_title": "12", + "is_in_free": false, + "title": "第12话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 67, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 499, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 552048, + "ord": 11.5, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 1569935, + "short_title": "记录", + "is_in_free": false, + "title": "002", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-12 00:00:00", + "comments": 10, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 52, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484369, + "ord": 11, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 18897621, + "short_title": "11", + "is_in_free": false, + "title": "第11话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 82, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 566, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484367, + "ord": 10, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 28021344, + "short_title": "10", + "is_in_free": false, + "title": "第10话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 65, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 519, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484366, + "ord": 9, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 14198049, + "short_title": "9", + "is_in_free": false, + "title": "第9话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 72, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 544, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484365, + "ord": 8, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 14137875, + "short_title": "8", + "is_in_free": false, + "title": "第8话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 92, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 575, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 552047, + "ord": 7.5, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 1794952, + "short_title": "记录", + "is_in_free": false, + "title": "001", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2022-05-12 00:00:00", + "comments": 23, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 80, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484360, + "ord": 7, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 20283011, + "short_title": "7", + "is_in_free": false, + "title": "第7话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 83, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 589, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484351, + "ord": 6, + "read": 0, + "pay_mode": 1, + "is_locked": true, + "pay_gold": 49, + "size": 18898536, + "short_title": "6", + "is_in_free": false, + "title": "第6话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 43, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 626, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484350, + "ord": 5, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 18623472, + "short_title": "5", + "is_in_free": false, + "title": "第5话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 86, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 1017, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484347, + "ord": 4, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 15209423, + "short_title": "4", + "is_in_free": false, + "title": "第4话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 85, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 976, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484345, + "ord": 3, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 15210025, + "short_title": "3", + "is_in_free": false, + "title": "第3话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 72, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 972, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484344, + "ord": 2, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 26269998, + "short_title": "2", + "is_in_free": false, + "title": "第2话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 147, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 1001, + "chapter_id": 0, + "type": 0, + "extra": 0 + }, + { + "id": 484342, + "ord": 1, + "read": 0, + "pay_mode": 0, + "is_locked": false, + "pay_gold": 0, + "size": 81495763, + "short_title": "1", + "is_in_free": false, + "title": "第1话", + "cover": "http://i0.hdslb.com/bfs/manga-static/94dcf91d49253ab62b601a72772a00fddb5d0c32.jpg", + "pub_time": "2020-10-21 00:00:00", + "comments": 407, + "unlock_expire_at": "0000-00-00 00:00:00", + "unlock_type": 0, + "allow_wait_free": false, + "progress": "", + "like_count": 1283, + "chapter_id": 0, + "type": 0, + "extra": 0 + } + ], + "release_time": "2020.10.21", + "is_limit": 0, + "read_epid": 0, + "last_read_time": "", + "is_download": 1, + "read_short_title": "", + "styles2": [ + { + "id": 1081, + "name": "悬疑灵异" + } + ], + "renewal_time": "", + "last_short_title": "后篇(4)", + "discount_type": 0, + "discount": 0, + "discount_end": "0001-01-01 00:00:00", + "no_reward": false, + "batch_discount_type": 0, + "ep_discount_type": 0, + "has_fav_activity": false, + "fav_free_amount": 0, + "allow_wait_free": false, + "wait_hour": 0, + "wait_free_at": "0000-00-00 00:00:00", + "no_danmaku": 0, + "auto_pay_status": 0, + "no_month_ticket": false, + "immersive": false, + "no_discount": false, + "show_type": 0, + "pay_mode": 1, + "chapters": [], + "classic_lines": "【此漫画的翻译由版权方提供】青梅竹马的潮死了——。听闻这个悲报,慎平回到了阔别已久的故乡和歌山市·日都岛与家人再会并出席葬礼。但是岛上貌似陡生异变,充斥着不寻常的气息……?\n夏日孤岛上的悬疑剧!!\n\n", + "pay_for_new": 0, + "fav_comic_info": { + "has_fav_activity": false, + "fav_free_amount": 0, + "fav_coupon_type": 0 + }, + "serial_status": 0, + "series_info": { + "id": 0, + "comics": [] + }, + "album_count": 0, + "wiki_id": 131075, + "disable_coupon_amount": 2, + "japan_comic": true, + "interact_value": "57514", + "temporary_finish_time": "", + "video": null, + "introduction": "最聪明的男主打最聪明的反派!", + "comment_status": 1, + "no_screenshot": true, + "type": 0, + "vomic_cvs": [], + "no_rank": true, + "presale_eps": [], + "presale_text": "", + "presale_discount": 0, + "no_leaderboard": true + } +} +``` + +
diff --git a/bb-api-collect/docs/manga/Download.md b/bb-api-collect/docs/manga/Download.md new file mode 100644 index 0000000000..fea8a8fa62 --- /dev/null +++ b/bb-api-collect/docs/manga/Download.md @@ -0,0 +1,256 @@ +# 获取当前话全部图片地址 + +> https://manga.bilibili.com/twirp/comic.v1.Comic/GetImageIndex + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)/ APP + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | ------------------------------------------------------------ | +| access_key | str | APP登录凭证 | 必要 | 使用APP鉴权方式时必填 | +| appkey | str | cc8617fd6961e070 | 非必要 | | +| mobi_app | str | android_comic | 非必要 | | +| version | str | 4.21.0 | 非必要 | | +| build | str | 36421000 | 非必要 | | +| channel | str | bilicomic | 非必要 | | +| platform | str | android | 非必要 | | +| device | str | android | 非必要 | | +| buvid | str | XY118701XXXXXXXXX104911DXXXXXCAEXXXXE | 非必要 | 长度为37 | +| machine | str | | 非必要 | 手机品牌+型号 | +| is_teenager | num | 0 | 非必要 | | +| no_recommend | num | 0 | 非必要 | | +| ts | num | 秒级时间戳 | 非必要 | + +**正文参数( application/json ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------------------ | ------ | ------------------------------------------------- | +| epId(ep_id) | num | 当前话的id | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功 | +| msg | str | 错误信息 | | +| data | obj | | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| path | str | .index 文件路径 | | +| images | array | 本话图片信息 | | +| last_modified | str | 本话信息最后修改时间 | | +| host | str | `https://manga.hdslb.com` | | +| video | obj | | | + +`images` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| path | str | 图片的路径 | 不包含host | +| x | num | 图片宽度 | 单位:像素px | +| y | num | 图片高度 | 单位:像素px | +| video_path | str | | | +| video_size | str | | | + +`video` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| svid | str | | | +| filename | str | | | +| route | str | | | +| resource | array | | | +| raw_width | str | | | +| raw_height | str | | | +| raw_rotate | str | | | +| img_urls | array | | | +| bin_url | str | | | +| img_x_len | num | | | +| img_x_size | num | | | +| img_y_len | num | | | +| img_y_size | num | | | + + +**示例:** + +```bash +curl -L -X POST 'https://manga.bilibili.com/twirp/comic.v1.Comic/GetImageIndex' \ +-H 'Cookie: SESSDATA=xxx;' \ +-H 'Content-Type: application/json' \ +--data-raw '{ + "ep_id": 321912 +}' +``` + +
+查看响应示例: + + +```json +{ + "code": 0, + "msg": "", + "data": { + "path": "/bfs/manga/26564/321912/data.index?token=80eab62fef85c1c134a6399f817a938f&ts=63404145", + "images": [ + { + "path": "/bfs/manga/11e404e602fa9f709bfb89d692ac56d2e17f974d.jpg", + "x": 1600, + "y": 2268, + "video_path": "", + "video_size": "0" + }, + { + "path": "/bfs/manga/bf1c48540b68f473b429317d8f6fa8cdb6eed3a5.jpg", + "x": 1600, + "y": 2268, + "video_path": "", + "video_size": "0" + }, + { + "path": "/bfs/manga/a46cfe90cfb49c67a4dbfc0002e5bc3d87d02963.jpg", + "x": 1600, + "y": 2268, + "video_path": "", + "video_size": "0" + } + ], + "last_modified": "2019-05-13 21:15:53", + "host": "https://manga.hdslb.com", + "video": { + "svid": "", + "filename": "", + "route": "", + "resource": [], + "raw_width": "0", + "raw_height": "0", + "raw_rotate": "0", + "img_urls": [], + "bin_url": "", + "img_x_len": 10, + "img_x_size": 160, + "img_y_len": 10, + "img_y_size": 90 + } + } +} +``` + +
+ +# 获取某一图片的token + +> https://manga.bilibili.com/twirp/comic.v1.Comic/ImageToken + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)/ APP + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------ | ---- | ------------------------------------- | ------ | --------------------- | +| access_key | str | APP登录凭证 | 必要 | 使用APP鉴权方式时必填 | +| appkey | str | cc8617fd6961e070 | 非必要 | | +| mobi_app | str | android_comic | 非必要 | | +| version | str | 4.21.0 | 非必要 | | +| build | str | 36421000 | 非必要 | | +| channel | str | bilicomic | 非必要 | | +| platform | str | android | 非必要 | | +| device | str | android | 非必要 | | +| buvid | str | XY118701XXXXXXXXX104911DXXXXXCAEXXXXE | 非必要 | 长度为37 | +| machine | str | samsung+SM-G9730 | 非必要 | 手机品牌+型号 | +| is_teenager | num | 0 | 非必要 | | +| no_recommend | num | 0 | 非必要 | | +| ts | num | 秒级时间戳 | 非必要 | | + +**正文参数( application/json ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------- | ------ | ------------------------------------------------------------ | +| urls | str | 请求token的图片地址 | 必要 | `[\"https://i0.hdslb.com{path}\"]`
{path}代表图片的相对网站路径,支持jpg和webp | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ----- | -------- | ------- | +| code | num | 返回值 | 0:成功 | +| msg | str | 错误信息 | | +| data | array | | | + +`data` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ------------------- | ------------------------------------ | +| url | str | 图片下载的地址 | 此时网址开头 https://manga.hdslb.com | +| token | str | 图片下载需要的token | | + +**示例:** + +```bash +curl -L -X POST 'https://manga.bilibili.com/twirp/comic.v1.Comic/ImageToken' \ +-H 'Cookie: SESSDATA=xxx;' \ +-H 'Content-Type: application/json' \ +--data-raw '{ + "urls": "[\"https://i0.hdslb.com/bfs/manga/11e404e602fa9f709bfb89d692ac56d2e17f974d.jpg\"]" +}' +``` + +
+查看响应示例: + + + +```json +{ + "code": 0, + "msg": "", + "data": [ + { + "url": "https://manga.hdslb.com/bfs/manga/11e404e602fa9f709bfb89d692ac56d2e17f974d.jpg", + "token": "36931815abb35857627a22c347dc1c86&ts=634045c2" + } + ] +} +``` + +
+ +# 下载图片 + +*请求方式:GET* + +在上一步获取token的基础上,构建如下的url + +例如获取到此token + +``` +{ + "code": 0, + "msg": "", + "data": [ + { + "url": "https://manga.hdslb.com/bfs/manga/11e404e602fa9f709bfb89d692ac56d2e17f974d.jpg", + "token": "36931815abb35857627a22c347dc1c86&ts=634045c2" + } + ] +} +``` + +则访问以下网址即可,注意需要添加`?token=`。此网址有效期较短 + +``` +https://manga.hdslb.com/bfs/manga/11e404e602fa9f709bfb89d692ac56d2e17f974d.jpg?token=36931815abb35857627a22c347dc1c86&ts=634045c2 +``` + +**注**:若不加取图 Token 直接访问 `https://(i0|i1).hdslb.com/bfs/(manga|new_dyn|archive)/11e404e602fa9f709bfb89d692ac56d2e17f974d.jpg`均无法获取 diff --git a/bb-api-collect/docs/manga/Season.md b/bb-api-collect/docs/manga/Season.md new file mode 100644 index 0000000000..7f59df671b --- /dev/null +++ b/bb-api-collect/docs/manga/Season.md @@ -0,0 +1,435 @@ +# 漫画赛季 + +**注**:漫画赛季仅在 app 端可见,但可以使用 Cookie 鉴权 + +## 获取赛季信息 + +> https://manga.bilibili.com/twirp/user.v1.Season/GetSeasonInfo + +*请求方式:POST* + +**注**:接口不鉴权可查看基本信息,鉴权后可查看赛季个人信息和赛季规则。 + +认证方式:Cookie(SESSDATA)/ APP + +**json 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| code | num | 返回值 | | +| msg | str | 错误信息 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------ | ----- | ------------------ | -------------------------- | +| current_time | str | 当前时间字符串 | ISO 8601 | +| start_time | str | 赛季开始 | ISO 8601 | +| end_time | str | 赛季结束 | ISO 8601 | +| remain_amount | num | 拥有积分 | 未登录为 `0` | +| season_id | str | 第几个赛季 | | +| tasks | array | 待领取奖励的任务 | 未登录/没有可领取时为 `[]` | +| welfare | array | 赛季奖励 | | +| next | obj | 未知 | 未登录为 `null` | +| cover | str | 版头图片 | | +| today_tasks | array | 今日的任务完成情况 | | +| text | obj | 赛季相关文案 | 未登录为 `null` | +| season_clock_in | obj | | | +| announcement | obj | 未知 | 未登录为 `null` | +| lottery | obj | | | +| mission_point_rate | str | | | +| season_title | str | 赛季标题 | | +| point_rate | obj | | | +| rank | obj | | | + +`data` 对象的 `rank`: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ----- | ---- | +| is_visible | bool | false | | + +`data` 对象的 `tasks`: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ---------- | ----------------------- | +| title | str | 任务描述 | | +| id | str | | | +| status | num | 任务状态 | 应该都是`1`:待领取奖励 | +| type | num | | 与 today_tasks 的一致 | +| amount | num | 可获取积分 | | +| ctime | str | 完成时间 | ISO 8601 | + +`data` 对象的 `next`: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ---- | ---- | +| title | str | 空 | | +| amount | num | 0 | | +| gap_time | num | 0 | | +| current_time | num | 0 | | + +`data` 对象的 `text`: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ------------ | ---- | +| notice | str | 赛季公告 | | +| clonckInRule | str | 赛季签到规则 | | + +`data` 对象的 `announcement`: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ----- | ---- | +| title | str | 空 | | +| jump_url | str | 空 | | +| enable | bool | false | | + +`data` 对象的 `point_rate`: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ---- | ---- | +| sign_in | num | 0 | | +| game | num | 0 | | +| daily_mission | num | 0 | | +| week_mission | num | 0 | | + +`data` 对象的 `lottery`: + +| 字段 | 类型 | 内容 | 备注 | +| ---------------------- | ---- | ------------ | ---- | +| lottery_act_id | str | '0' | | +| enable_lottery | bool | 是否开启抽奖 | | +| lottery_id | str | '0' | | +| advance_lottery_act_id | str | '0' | | +| advance_pool_id | str | '0' | | + +`data` 对象的 `season_clock_in`: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ---- | ---------------- | ---- | +| is_super_luck | bool | | | +| draw_luck_time | str | | | +| prize_type | num | | | +| prize_title | str | | | +| add_up_sign | num | 赛季连续签到天数 | | +| title | str | 签到标题 | | +| sign_old_amount | num | | | +| preluck_amount | num | | | +| continuous_days | num | 连续签到天数 | | +| address_id | str | | | +| has_super_prize | bool | | | +| subtitle | str | 签到子标题 | | +| prize_image | str | | | +| prize_target_days | num | | | +| prize_amount | num | | | +| tomorrow_amount | num | 明日签到积分 | | +| entrance_tag | str | | | + +`data` 对象的 `today_tasks`: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---------- | ------------ | ------------------------------------------- | +| type | num | | | +| title | str | 任务标题 | 可能为空字符串 | +| amount | num | 可获得积分 | | +| status | num | 完成状态 | 0:未完成
1:待领取奖励
2:已完成 | +| duration | num | 耗时(分) | 直接完成的为 0 | +| comics | comic 数组 | 任务指定漫画 | 仅`type=22`时有内容,所有账号是一致的 | +| page_url | str | 空 | | +| progress | num | 已完成进度 | | +| sub_id | num | | `type` 一致时有效 | +| share_type | num | `0` | | + +`today_tasks`对象的 `comics`: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | -------- | -------- | ---- | +| comic_id | num | 漫画 id | | +| title | str | 漫画名称 | | +| vertical_cover | str | 漫画封面 | | +| styles | str 数组 | 漫画类型 | | + +`data` 对象的 `welfare`: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | ------------ | --------------------------------------------------------- | +| type | num | 奖励类型 | 200-限免卡
202-漫读券
203-优惠券
205-最终宝箱 | +| success | num | 兑换状态 | 0-未兑换
2-已兑换 | +| exchange_amount | num | 积分消耗 | | +| boss_welfare | bool | 最终奖励 | | +| boss_remain | num | 最终奖励剩余 | | +| rank | num | 顺序 | | +| title | str | 空 | | +| url | str | 空 | | +| kind_address_id | str | '0' | | + +**示例:** + +```bash +curl -X POST https://manga.bilibili.com/twirp/user.v1.Season/GetSeasonInfo +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "", + "data": { + "current_time": "2022-11-30T15:12:00+08:00", + "start_time": "2022-11-14T00:00:00+08:00", + "end_time": "2022-12-11T23:59:00+08:00", + "remain_amount": 0, + "season_id": "35", + "tasks": [], + "welfare": [ + { + "type": 200, + "success": 0, + "exchange_amount": 100, + "boss_welfare": false, + "boss_remain": 0, + "rank": 1, + "title": "", + "url": "", + "kind_address_id": "0" + }, + // 中间的省略 + { + "type": 205, + "success": 0, + "exchange_amount": 0, + "boss_welfare": true, + "boss_remain": 0, + "rank": 21, + "title": "", + "url": "", + "kind_address_id": "0" + } + ], + "next": null, + "cover": "https://i0.hdslb.com/bfs/manga-static/b81fcd291cff74965b71d67e7df261de5790c2cd.png", + "today_tasks": [ + { + "type": 18, + "title": "", + "amount": 20, + "status": 0, + "duration": 30, + "comics": [], + "page_url": "", + "progress": 0, + "sub_id": 1, + "share_type": 0 + }, + { + "type": 20, + "title": "", + "amount": 20, + "status": 0, + "duration": 3, + "comics": [], + "page_url": "", + "progress": 0, + "sub_id": 1, + "share_type": 0 + }, + { + "type": 22, + "title": "", + "amount": 50, + "status": 0, + "duration": 15, + "comics": [ + { + "comic_id": 32190, + "title": "我的成就有点多", + "vertical_cover": "https://i0.hdslb.com/bfs/manga-static/efc403e323656fad24335aef007af5f318879597.png", + "styles": ["都市"] + }, + { + "comic_id": 30538, + "title": "我知道你的秘密", + "vertical_cover": "https://i0.hdslb.com/bfs/manga-static/607f2c13afcf82ebba98f18213033d93bba7d58a.jpg", + "styles": ["悬疑"] + }, + { + "comic_id": 25874, + "title": "桃花宝典", + "vertical_cover": "http://i0.hdslb.com/bfs/manga-static/bb1d33004af7dfbf197572cb9ef1c5fdd19e17a8.jpg", + "styles": ["都市"] + } + ], + "page_url": "", + "progress": 0, + "sub_id": 1, + "share_type": 0 + }, + { + "type": 17, + "title": "阅读3分钟", + "amount": 10, + "status": 0, + "duration": 3, + "comics": [], + "page_url": "", + "progress": 0, + "sub_id": 1, + "share_type": 0 + }, + { + "type": 17, + "title": "阅读5分钟", + "amount": 10, + "status": 0, + "duration": 5, + "comics": [], + "page_url": "", + "progress": 0, + "sub_id": 2, + "share_type": 0 + }, + { + "type": 17, + "title": "阅读10分钟", + "amount": 20, + "status": 0, + "duration": 10, + "comics": [], + "page_url": "", + "progress": 0, + "sub_id": 3, + "share_type": 0 + }, + { + "type": 17, + "title": "阅读20分钟", + "amount": 40, + "status": 0, + "duration": 20, + "comics": [], + "page_url": "", + "progress": 0, + "sub_id": 4, + "share_type": 0 + }, + { + "type": 17, + "title": "阅读30分钟", + "amount": 60, + "status": 0, + "duration": 30, + "comics": [], + "page_url": "", + "progress": 0, + "sub_id": 5, + "share_type": 0 + }, + { + "type": 19, + "title": "每日首次玩猜拳", + "amount": 5, + "status": 0, + "duration": 1, + "comics": [], + "page_url": "", + "progress": 0, + "sub_id": 1, + "share_type": 0 + }, + { + "type": 1, + "title": "打开系统通知", + "amount": 5, + "status": 0, + "duration": 0, + "comics": [], + "page_url": "", + "progress": 0, + "sub_id": 0, + "share_type": 0 + }, + { + "type": 2, + "title": "设置个人偏好", + "amount": 5, + "status": 0, + "duration": 0, + "comics": [], + "page_url": "", + "progress": 0, + "sub_id": 0, + "share_type": 0 + } + ], + "text": null, + "season_clock_in": { + "is_super_luck": false, + "draw_luck_time": "", + "prize_type": 0, + "prize_title": "", + "add_up_sign": 0, + "title": "", + "sign_old_amount": 0, + "preluck_amount": 0, + "continuous_days": 0, + "address_id": "0", + "has_super_prize": false, + "subtitle": "", + "prize_image": "", + "prize_target_days": 0, + "prize_amount": 0, + "tomorrow_amount": 0, + "entrance_tag": "" + }, + "announcement": null, + "lottery": { + "lottery_act_id": "0", + "enable_lottery": true, + "lottery_id": "0", + "advance_lottery_act_id": "0", + "advance_pool_id": "0" + }, + "mission_point_rate": 0, + "season_title": "初冬赛季", + "point_rate": { "sign_in": 0, "game": 0, "daily_mission": 0, "week_mission": 0 }, + "rank": { "is_visible": false } + } +} +``` + +
+ +## 赛季奖励领取 + +> https://manga.bilibili.com/twirp/user.v1.Season/TakeSeasonGifts + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)/ APP + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | ------- | ------ | --------------- | +| season_id | num | 赛季 id | 必要 | 必须为本赛季 id | + +**json 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| code | num | 返回值 | | +| msg | str | 错误信息 | | + +`code` - `msg` 对照表: + +| code | msg | 备注 | +| ---- | ------------------------------------ | ---------------------------- | +| 0 | | 领取成功 | +| 2 | 当前没有正在进行的赛季,无法兑换奖励 | season_id 字段不正确 | +| 7 | 任务已领取或者未完成 | 没有已经完成的 `today_tasks` | diff --git a/bb-api-collect/docs/manga/User.md b/bb-api-collect/docs/manga/User.md new file mode 100644 index 0000000000..7118a32736 --- /dev/null +++ b/bb-api-collect/docs/manga/User.md @@ -0,0 +1,712 @@ +# 漫画用户信息 + +## 获取拥有的漫读券列表 + +> https://manga.bilibili.com/twirp/user.v1.User/GetCoupons + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)/ APP + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | ------------------------------------------------------------ | +| access_key | str | APP登录凭证 | 必要 | 使用APP鉴权方式时必填 | + +**正文参数 (application/json):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------------------ | ------ | ------------------------------------------------- | +| pageNum | num | 页数 | 必要 | | +| pageSize | num | 分页大小 | 必要 | 默认20,取值范围[1,100] | +| notExpired | bool | true | 非必要 | | +| tabType | num | 1 | 非必要 | | +| type | num | 0 | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功 | +| msg | str | 错误信息 | | +| data | obj | | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| total_remain_amount | num | | | +| user_coupons | array | | | +| coupon_info | obj | | | + +`user_coupons` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| ID | num | 漫读券id | | +| remain_amount | num | 漫读券剩余数 | | +| expire_time | num | 过期时间 | | +| reason | num | 获取方式 | | +| type | num | 类型 | | +| ctime | num | 获取时间 | | +| total_amount | num | 漫读券总数 | | +| limits | array | (?) | | +| type_num | num | 7:福利券 | | +| will_expire | num | 是否即将过期?
0:否
1:是 | | +| discount | num | 0 | | +| discount_limit | num | 0 | | +| is_from_card | num | 0 | | +| valid_time | str | 0001-01-01 | | +| discount_base | num | 0 | | + +`coupon_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| new_coupon_num | num | | | +| coupon_will_expire | num | | | +| rent_will_expire | num | | | +| new_rent_num | num | | | +| discount_will_expire | num | | | +| new_discount_num | num | | | +| month_ticket_will_expire | num | | | +| new_month_ticket_num | num | | | +| silver_will_expire | num | | | +| new_silver_num | num | | | +| remain_item | num | | | +| remain_discount | num | | | +| remain_coupon | num | 拥有的漫读券数量 | | +| remain_silver | num | 拥有的通用券数量 | | +| remain_shop_coupon | num | 拥有的商城优惠券数量 | | +| new_shop_num | num | | | +| shop_will_expire | num | | | +| new_suit_id | num | | | +| remain_suit_coupon | num | | | +| new_suit_num | num | | | +| suit_will_expire | num | | | +| vip_priv_coupon | bool | | | + + +**示例:** + +```bash +curl -L -X POST 'https://manga.bilibili.com/twirp/user.v1.User/GetCoupons' \ +-H 'Cookie: SESSDATA=xxx;' \ +-H 'Content-Type: application/json' \ +--data-raw '{ + "notExpired": true, + "pageNum": 1, + "pageSize": 20, + "tabType": 1, + "type": 0 +}' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "", + "data": { + "total_remain_amount": 1, + "user_coupons": [ + { + "ID": 7473503, + "remain_amount": 1, + "expire_time": "2022-05-24 12:00:33", + "reason": "积分兑换", + "type": "福利券", + "ctime": "2022-05-17 12:00:33", + "total_amount": 1, + "limits": [], + "type_num": 7, + "will_expire": 0, + "discount": 0, + "discount_limit": 0, + "is_from_card": 0, + "valid_time": "0001-01-01", + "discount_base": 0 + } + ], + "coupon_info": { + "new_coupon_num": 0, + "coupon_will_expire": 0, + "rent_will_expire": 0, + "new_rent_num": 0, + "discount_will_expire": 0, + "new_discount_num": 0, + "month_ticket_will_expire": 0, + "new_month_ticket_num": 0, + "silver_will_expire": 0, + "new_silver_num": 0, + "remain_item": 0, + "remain_discount": 0, + "remain_coupon": 1, + "remain_silver": 8, + "remain_shop_coupon": 1, + "new_shop_num": 0, + "shop_will_expire": 0, + "new_suit_id": 60007, + "remain_suit_coupon": 0, + "new_suit_num": 0, + "suit_will_expire": 0, + "vip_priv_coupon": false + } + } +} +``` + +
+ +## 获取已购漫画 + +> https://manga.bilibili.com/twirp/user.v1.User/GetAutoBuyComics + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)/ APP + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ---- | ------ | ---- | +| device | str | 设备 | 非必要 | | +| platform | str | 平台 | 非必要 | | + +**正文参数 (application/json):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------------------ | ------ | ------------------------------------------------- | +| page_num | num | 页数 | 必要 | | +| page_size | num | 分页大小 | 必要 | 默认15 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---------- | -------- | ------- | +| code | num | 返回值 | 0:成功 | +| msg | str | 错误信息 | | +| data | obj(array) | | | + +`data`array中的对象 + +| 字段 | 类型 | 内容 | 备注 | +| ---------------- | ---- | ---------------- | ---- | +| id | num | 内部id | | +| comic_id | str | 漫画id | | +| comic_title | str | 漫画标题 | | +| hcover | str | 横版头图 | | +| scover | str | 方形头图 | | +| vcover | str | 竖版封面图 | | +| bought_ep_count | num | 已购章节数 | | +| gold_status | num | | | +| coupon_status | num | | | +| comic_status | num | 漫画状态 | | +| last_ord | num | 最后一话 | | +| ctime | str | 获取时间 | | +| last_short_title | str | 最后一话的短标题 | | +| bug_type | num | 购买类型 | | +| ep_for_chapters | num | | | +| orders | obj | 自动扣费顺序 | | +| enable_auto_pay | bool | 是否开启自动付费 | | +| type | num | | | + +**示例:** + +```bash +curl -L -X POST 'https://manga.bilibili.com/twirp/user.v1.User/GetAutoBuyComics' \ +-H "Cookie: xxxxx" \ +-H 'Content-Type: application/json;charset=UTF-8' \ +-H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36' \ +-d '{"page_num": 1,"page_size": 15}' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "", + "data": [ + { + "id": 20276887, + "comic_id": 26554, + "comic_title": "擅长捉弄的(原)高木同学", + "hcover": "http://i0.hdslb.com/bfs/manga-static/443b4a49be1e92cd204af1472e2a7f41c1df7336.png", + "scover": "http://i0.hdslb.com/bfs/manga-static/e29eb39aed0971851efe5998d3b9c156ba52bb4e.jpg", + "vcover": "http://i0.hdslb.com/bfs/manga-static/9536b3d6c6eaef5992986d6b06d35188c20f4366.jpg", + "bought_ep_count": 13, + "gold_status": 2, + "coupon_status": 2, + "comic_status": 0, + "last_ord": 235, + "ctime": "2022-01-26 21:39:33", + "last_short_title": "235", + "buy_type": 0, + "ep_for_chapters": 0, + "orders": [ + { + "id": 2, + "title": "漫读券" + }, + { + "id": 3, + "title": "通用券" + }, + { + "id": 1, + "title": "漫币" + } + ], + "enable_auto_pay": false, + "type": 0 + }, + { + "id": 15129353, + "comic_id": 29726, + "comic_title": "NEW GAME!", + "hcover": "https://i0.hdslb.com/bfs/manga-static/586df1c03978ef01eac9e6a670f26395f6495ead.jpg", + "scover": "https://i0.hdslb.com/bfs/manga-static/7110c8751fef26b082b5452bd515736a78bf0670.jpg", + "vcover": "https://i0.hdslb.com/bfs/manga-static/d3aa1477dcc9720f9bcee19c775849baad6b4e66.jpg", + "bought_ep_count": 4, + "gold_status": 2, + "coupon_status": 2, + "comic_status": 0, + "last_ord": 180, + "ctime": "2021-06-21 16:29:27", + "last_short_title": "180", + "buy_type": 0, + "ep_for_chapters": 0, + "orders": [ + { + "id": 2, + "title": "漫读券" + }, + { + "id": 3, + "title": "通用券" + }, + { + "id": 1, + "title": "漫币" + } + ], + "enable_auto_pay": false, + "type": 0 + }, + { + "id": 13525712, + "comic_id": 28080, + "comic_title": "终将成为你", + "hcover": "https://i0.hdslb.com/bfs/manga-static/bed69097d5fdc68bff87fce1e168b810448ee145.jpg", + "scover": "https://i0.hdslb.com/bfs/manga-static/855e851b58c805b05b347fddb80a46dcb260afac.jpg", + "vcover": "https://i0.hdslb.com/bfs/manga-static/10e8243b502bd19947cd49a6ac2ea0a9b8c5daa3.jpg", + "bought_ep_count": 5, + "gold_status": 2, + "coupon_status": 2, + "comic_status": 0, + "last_ord": 45, + "ctime": "2021-04-09 08:26:41", + "last_short_title": "第45话", + "buy_type": 9, + "ep_for_chapters": 0, + "orders": [], + "enable_auto_pay": false, + "type": 0 + }, + { + "id": 13469083, + "comic_id": 28198, + "comic_title": "米诺斯的牛肉100%", + "hcover": "http://i0.hdslb.com/bfs/manga-static/75931d991ddd40bc49c655ff3fca770d45eac9aa.jpg", + "scover": "http://i0.hdslb.com/bfs/manga-static/ee37104f5d97bb486e69d660d9a93242a1c2817a.jpg", + "vcover": "http://i0.hdslb.com/bfs/manga-static/be5400d37c1428ecc98a8e2d1772175991a262ed.jpg", + "bought_ep_count": 1, + "gold_status": 2, + "coupon_status": 2, + "comic_status": 0, + "last_ord": 6, + "ctime": "2021-04-06 12:21:20", + "last_short_title": "6", + "buy_type": 0, + "ep_for_chapters": 0, + "orders": [], + "enable_auto_pay": false, + "type": 0 + }, + { + "id": 13436048, + "comic_id": 27545, + "comic_title": "宝石之国", + "hcover": "http://i0.hdslb.com/bfs/manga-static/94637fff52eca04a8f32e19ed0c2f676b9bee96e.png", + "scover": "http://i0.hdslb.com/bfs/manga-static/e538ce332a639809aea70c8e30a19645e9b2ae3e.jpg", + "vcover": "http://i0.hdslb.com/bfs/manga-static/91e03718b03b7d3a2dca53c461b4b84953ce8cb0.jpg", + "bought_ep_count": 11, + "gold_status": 2, + "coupon_status": 2, + "comic_status": 0, + "last_ord": 96, + "ctime": "2021-04-05 00:09:17", + "last_short_title": "96", + "buy_type": 0, + "ep_for_chapters": 0, + "orders": [ + { + "id": 2, + "title": "漫读券" + }, + { + "id": 3, + "title": "通用券" + }, + { + "id": 1, + "title": "漫币" + } + ], + "enable_auto_pay": false, + "type": 0 + }, + { + "id": 13237163, + "comic_id": 27877, + "comic_title": "极主夫道", + "hcover": "https://i0.hdslb.com/bfs/manga-static/5a8b7bd678e2ae135415af31493417ae77bc83dd.png", + "scover": "http://i0.hdslb.com/bfs/manga-static/aa36b8cff89e42c1820e43c483d483ed3eb8d938.png", + "vcover": "http://i0.hdslb.com/bfs/manga-static/96a6b07bcea58955efed4df876bc8f1b5df9d5cc.jpg", + "bought_ep_count": 6, + "gold_status": 2, + "coupon_status": 2, + "comic_status": 0, + "last_ord": 96, + "ctime": "2021-03-27 12:28:27", + "last_short_title": "96", + "buy_type": 0, + "ep_for_chapters": 0, + "orders": [ + { + "id": 2, + "title": "漫读券" + }, + { + "id": 3, + "title": "通用券" + }, + { + "id": 1, + "title": "漫币" + } + ], + "enable_auto_pay": false, + "type": 0 + }, + { + "id": 12913068, + "comic_id": 25519, + "comic_title": "四月是你的谎言", + "hcover": "http://i0.hdslb.com/bfs/manga-static/33cda8ed8e6c89691d5397dc47f8c7c7945a54c4.png", + "scover": "http://i0.hdslb.com/bfs/manga-static/a6ed17ddac9bb568cefeb4eda8f8f3298db6c8cd.jpg", + "vcover": "http://i0.hdslb.com/bfs/manga-static/6d82d75a9a2817a18e16e2b82f76312d0fd02d06.jpg", + "bought_ep_count": 36, + "gold_status": 2, + "coupon_status": 2, + "comic_status": 0, + "last_ord": 44, + "ctime": "2021-03-11 23:58:50", + "last_short_title": "44", + "buy_type": 0, + "ep_for_chapters": 0, + "orders": [ + { + "id": 2, + "title": "漫读券" + }, + { + "id": 3, + "title": "通用券" + }, + { + "id": 1, + "title": "漫币" + } + ], + "enable_auto_pay": false, + "type": 0 + }, + { + "id": 12793711, + "comic_id": 28537, + "comic_title": "前男友成为了那样的男子", + "hcover": "https://i0.hdslb.com/bfs/manga-static/33440f7675a424dcce35459e2392e23e9d345531.jpg", + "scover": "http://i0.hdslb.com/bfs/manga-static/3de961215ad2a96ccf5dbb45d85db88934b545cb.jpg", + "vcover": "https://i0.hdslb.com/bfs/manga-static/77feff2a5f1aab93060e8ce5105e5616cb7313a7.jpg", + "bought_ep_count": 3, + "gold_status": 2, + "coupon_status": 2, + "comic_status": 0, + "last_ord": 54, + "ctime": "2021-03-06 19:20:03", + "last_short_title": "44", + "buy_type": 0, + "ep_for_chapters": 0, + "orders": [ + { + "id": 2, + "title": "漫读券" + }, + { + "id": 3, + "title": "通用券" + }, + { + "id": 1, + "title": "漫币" + } + ], + "enable_auto_pay": false, + "type": 0 + }, + { + "id": 12751111, + "comic_id": 26009, + "comic_title": "辉夜大小姐想让我告白 ~天才们的恋爱头脑战~", + "hcover": "https://i0.hdslb.com/bfs/manga-static/7fe349fd5a3d9522546e1582ad03604e82b1ff41.png", + "scover": "http://i0.hdslb.com/bfs/manga-static/b0ac1e3379e940c47b31209edf016e32e8bcee37.jpg", + "vcover": "https://i0.hdslb.com/bfs/manga-static/6188cad7ec7ac2b0555c0a815f9d2afbe7c0c5cb.jpg", + "bought_ep_count": 2, + "gold_status": 2, + "coupon_status": 2, + "comic_status": 0, + "last_ord": 259, + "ctime": "2021-03-05 00:16:13", + "last_short_title": "269", + "buy_type": 0, + "ep_for_chapters": 0, + "orders": [ + { + "id": 2, + "title": "漫读券" + }, + { + "id": 3, + "title": "通用券" + }, + { + "id": 1, + "title": "漫币" + } + ], + "enable_auto_pay": false, + "type": 0 + }, + { + "id": 12479079, + "comic_id": 27867, + "comic_title": "邪神与厨二病少女", + "hcover": "https://i0.hdslb.com/bfs/manga-static/96594b34528640f51ef5062648b55c871f4d4b1b.jpg", + "scover": "https://i0.hdslb.com/bfs/manga-static/54a7f8d35024ef46dc270dc758d882bc98c4a1c5.jpg", + "vcover": "https://i0.hdslb.com/bfs/manga-static/1b07c3be74d65cbb707934de190af10ca81588f3.jpg", + "bought_ep_count": 194, + "gold_status": 2, + "coupon_status": 2, + "comic_status": 0, + "last_ord": 216.5, + "ctime": "2021-02-23 00:18:06", + "last_short_title": "216.5", + "buy_type": 0, + "ep_for_chapters": 0, + "orders": [ + { + "id": 2, + "title": "漫读券" + }, + { + "id": 3, + "title": "通用券" + }, + { + "id": 1, + "title": "漫币" + } + ], + "enable_auto_pay": false, + "type": 0 + }, + { + "id": 11749927, + "comic_id": 29119, + "comic_title": "足艺少女小村同学", + "hcover": "https://i0.hdslb.com/bfs/manga-static/30b7917fd7d8b0afe6d913f09bab31e5eafae8b6.jpg", + "scover": "https://i0.hdslb.com/bfs/manga-static/f4ec445bc209ad473cdf9127528c09e271535617.jpg", + "vcover": "https://i0.hdslb.com/bfs/manga-static/8f83793c06dc0f59cab3a6acf4b978dc3c0a01f9.jpg", + "bought_ep_count": 13, + "gold_status": 2, + "coupon_status": 2, + "comic_status": 0, + "last_ord": 58, + "ctime": "2021-01-31 11:04:31", + "last_short_title": "最终话", + "buy_type": 0, + "ep_for_chapters": 0, + "orders": [ + { + "id": 2, + "title": "漫读券" + }, + { + "id": 3, + "title": "通用券" + }, + { + "id": 1, + "title": "漫币" + } + ], + "enable_auto_pay": false, + "type": 0 + }, + { + "id": 11605399, + "comic_id": 29053, + "comic_title": "如果是理想中的女儿,就算是世界最强也能受到宠爱吗?", + "hcover": "https://i0.hdslb.com/bfs/manga-static/5a7886e2b94515ea75a3ea34d9c77db3f2487b59.jpg", + "scover": "https://i0.hdslb.com/bfs/manga-static/88f6d08fed2998aba96cedbfdffba555bef4d1c1.jpg", + "vcover": "https://i0.hdslb.com/bfs/manga-static/517a155372e7de966cca2f5f42edabd31a90b169.jpg", + "bought_ep_count": 5, + "gold_status": 2, + "coupon_status": 2, + "comic_status": 0, + "last_ord": 28, + "ctime": "2021-01-25 19:40:15", + "last_short_title": "28", + "buy_type": 0, + "ep_for_chapters": 0, + "orders": [ + { + "id": 2, + "title": "漫读券" + }, + { + "id": 3, + "title": "通用券" + }, + { + "id": 1, + "title": "漫币" + } + ], + "enable_auto_pay": false, + "type": 0 + }, + { + "id": 11386175, + "comic_id": 28656, + "comic_title": "就算这样,“步”还是靠了过来", + "hcover": "http://i0.hdslb.com/bfs/manga-static/c95456b2d00f84293bda62b12539d19172b45db1.jpg", + "scover": "http://i0.hdslb.com/bfs/manga-static/2601c1474cd214d28797381e70b2c19ac7d67869.jpg", + "vcover": "https://i0.hdslb.com/bfs/manga-static/3a556ed655ddf84c7930b3ce180fbdbf8f1d8112.jpg", + "bought_ep_count": 2, + "gold_status": 2, + "coupon_status": 2, + "comic_status": 0, + "last_ord": 160, + "ctime": "2021-01-17 10:48:29", + "last_short_title": "160", + "buy_type": 0, + "ep_for_chapters": 0, + "orders": [ + { + "id": 2, + "title": "漫读券" + }, + { + "id": 3, + "title": "通用券" + }, + { + "id": 1, + "title": "漫币" + } + ], + "enable_auto_pay": false, + "type": 0 + }, + { + "id": 11356706, + "comic_id": 26731, + "comic_title": "在魔王城说晚安", + "hcover": "https://i0.hdslb.com/bfs/manga-static/061f63826f1aa24a5b9346f79b915999004b13da.jpg", + "scover": "http://i0.hdslb.com/bfs/manga-static/94ae037dae4cc61d580c5c3c42702ccf10d977dc.jpg", + "vcover": "https://i0.hdslb.com/bfs/manga-static/2958043a10024ddebfafc4fd47d3566043689300.jpg", + "bought_ep_count": 148, + "gold_status": 2, + "coupon_status": 2, + "comic_status": 0, + "last_ord": 292, + "ctime": "2021-01-16 11:25:47", + "last_short_title": "292", + "buy_type": 0, + "ep_for_chapters": 0, + "orders": [ + { + "id": 2, + "title": "漫读券" + }, + { + "id": 3, + "title": "通用券" + }, + { + "id": 1, + "title": "漫币" + } + ], + "enable_auto_pay": false, + "type": 0 + }, + { + "id": 11079049, + "comic_id": 27355, + "comic_title": "堀与宫村", + "hcover": "https://i0.hdslb.com/bfs/manga-static/b51b905707664415dab91cf81fb0373f970b54b5.jpg", + "scover": "https://i0.hdslb.com/bfs/manga-static/6ac604dfd0ad6c486a520519983212d74c340f28.jpg", + "vcover": "https://i0.hdslb.com/bfs/manga-static/c29ba3ce67613539666582d31d42b40fb48cc3c7.jpg", + "bought_ep_count": 119, + "gold_status": 2, + "coupon_status": 2, + "comic_status": 0, + "last_ord": 126, + "ctime": "2021-01-05 12:52:59", + "last_short_title": "page.122", + "buy_type": 0, + "ep_for_chapters": 0, + "orders": [ + { + "id": 2, + "title": "漫读券" + }, + { + "id": 3, + "title": "通用券" + }, + { + "id": 1, + "title": "漫币" + } + ], + "enable_auto_pay": false, + "type": 0 + } + ] +} +``` + +
\ No newline at end of file diff --git a/bb-api-collect/docs/manga/index_file.md b/bb-api-collect/docs/manga/index_file.md new file mode 100644 index 0000000000..8e552f8386 --- /dev/null +++ b/bb-api-collect/docs/manga/index_file.md @@ -0,0 +1,269 @@ +# data.index + +## data.index文件解析 + +本解密及数据解析例程以《在魔王城说晚安 第 1 话 不眠之城的公主》为例 + +本话链接:https://manga.bilibili.com/mc26731/329893 (mcid=`26731`, epid=`329893`) + +使用 Python 语言为例 + +### 获取data.index + +直接使用 GET 方法请求该话对应的 data.index 文件地址,就会得到一个二进制文件 + +```bash +curl -s 'https://manga.hdslb.com/bfs/manga/26731/329893/data.index?token=4b93ced19dc5ade671064804232ef4f5&ts=634e1943' | hexdump -C +``` + +data.index 文件内容的 HEX 如下 + +首部有 9 Byte 作为 File Magic 内容是 ASCII 编码的 `BILICOMIC` + +``` +00000000 42 49 4c 49 43 4f 4d 49 43 f5 43 06 04 7f 68 08 |BILICOMIC.C...h.| +00000010 00 ad 08 05 00 6b 68 00 00 a5 08 05 00 6b 68 00 |.....kh......kh.| +00000020 00 a5 08 0c 00 6b 68 69 6e c1 6d 7d 2e 0f 09 74 |.....khin.m}...t| +00000030 ec 33 c3 8f 5c 2c 64 86 df 40 a4 82 58 9c 42 f5 |.3..\,d..@..X.B.| +00000040 ab 21 51 4d aa f9 f1 e0 84 84 9b 40 12 58 87 1e |.!QM.......@.X..| +00000050 ba 28 29 7d ce 89 04 03 d9 91 8d fd 7e 31 1d be |.()}........~1..| +00000060 ba d8 35 ef cb a0 83 db 71 5e f1 ee f1 90 19 43 |..5.....q^.....C| +00000070 03 dd 32 f7 b8 7a b7 07 7f b9 3f 7d 3a d5 54 7e |..2..z....?}:.T~| +00000080 5f fa e2 bd c1 90 bb 0f 9c 7d 34 e4 f0 49 2f 17 |_........}4..I/.| +00000090 39 1b c0 cc 45 25 47 72 76 34 13 12 b9 12 f9 f3 |9...E%Grv4......| +000000a0 8b b9 56 13 72 be 60 5e 55 27 5f 98 e0 3e 41 78 |..V.r.`^U'_..>Ax| +000000b0 d5 af 56 d0 82 3c d5 e0 55 94 70 d0 0c 16 5f 33 |..V..<..U.p..._3| +000000c0 c5 bb 14 d7 e9 e5 4a 7c 7f db 04 ea 7b 9b 90 94 |......J|....{...| +000000d0 fd 53 e1 d2 f8 86 1b 7c ea 97 dd 0b 22 33 75 39 |.S.....|...."3u9| +000000e0 24 76 39 38 6d 58 a4 ed b4 14 8f 71 49 95 9c cb |$v98mX.....qI...| +000000f0 eb 42 eb ec df a2 22 ae 39 0c 3d 03 95 43 27 55 |.B....".9.=..C'U| +00000100 c1 c8 b2 37 2c 01 b0 f4 22 7c 51 1a 93 b5 ab 6d |...7,..."|Q....m| +00000110 72 95 0c 33 9a ed 2d d6 22 f0 08 b6 5c bb f6 b5 |r..3..-."...\...| +00000120 07 5f cf a1 3a 66 c8 30 41 29 31 dd 17 63 46 85 |._..:f.0A)1..cF.| +00000130 ea 53 20 a0 aa 89 65 91 78 37 ac 4b 06 e6 59 7a |.S ...e.x7.K..Yz| +00000140 c2 b7 10 56 cc a0 2e 85 94 09 01 89 83 43 82 a4 |...V.........C..| +00000150 db 60 91 89 15 83 aa 45 aa d6 5f fd 6a 64 f9 1c |.`.....E.._.jd..| +00000160 9d ef c3 6c 34 85 e7 49 8a a7 c3 bc 32 09 eb b8 |...l4..I....2...| +00000170 ef 70 ab d6 6a d2 7f f6 96 b1 9a 75 eb f8 47 34 |.p..j......u..G4| +00000180 db 1d 99 78 57 58 04 4e e0 c4 a4 58 d8 81 f5 02 |...xWX.N...X....| +00000190 3c 42 7e 1c 27 98 3c 70 df 04 13 33 fa ff 21 3b | +查看json内容: + +```json +{ + "clips": [ + {"r": 1600, "b": 2300, "t": 0, "l": 0, "pic": 0}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 1}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 2}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 3}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 4}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 5}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 6}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 7}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 8}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 9}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 10}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 11}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 12}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 13}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 14}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 15}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 16}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 17}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 18}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 19}, + {"r": 1600, "b": 2468, "t": 0, "l": 0, "pic": 20}, + {"r": 846, "b": 1200, "t": 0, "l": 0, "pic": 21} + ], + "pics": [ + "/bfs/manga/fc655fa220dfab74bb91b9b6e308e92e1f74fc4b.jpg", + "/bfs/manga/cb3c882f5a72c45385541e65dba6ac7689c24ebc.jpg", + "/bfs/manga/9f79683a30a1f165a6abcd2550066bd0f9bce719.jpg", + "/bfs/manga/592702a6411a8739d041d50cff9ac52ccc3e0ab1.jpg", + "/bfs/manga/52fb305a77f80d4078469c67ca4c4d8031722acc.jpg", + "/bfs/manga/d3bb31ca1943c2558eca9df9a44b7fb52d927f1e.jpg", + "/bfs/manga/2ac06b8dbaae0499edf7fb6cd99c1fe4b424a96f.jpg", + "/bfs/manga/98f63f139ecf30e3b037635fc1f59fb40388e947.jpg", + "/bfs/manga/55099ea5e0e198482ea6d216a5e41b02835701b7.jpg", + "/bfs/manga/ee60daaf9ca659bb0df7d45402c86c79a1f64739.jpg", + "/bfs/manga/8620f9742fddc97d4179f18fd2b9f1b1420138dd.jpg", + "/bfs/manga/0490a9d8bdb6312ac56baa24ed0595a2465d98dc.jpg", + "/bfs/manga/bc3234cb0ba2be2b724b1a640a418f1db7b2ac43.jpg", + "/bfs/manga/0d16c5e9779f187916e4b173e7a6447b14707ece.jpg", + "/bfs/manga/58f3985afc3f2cf57052725dfea47af5634ac1c8.jpg", + "/bfs/manga/de09b30d952566c2c1308f5da59a2ffb3b2deb5c.jpg", + "/bfs/manga/36ecc5565340605883cb000f513b49bfc91e0d3e.jpg", + "/bfs/manga/120f3174def02b3dd908ee69b427d094506b884d.jpg", + "/bfs/manga/fdbe3bd0d446c0129557bd19037785456e55f12c.jpg", + "/bfs/manga/813a1bb68c3f89616583c8662fa81984d6a907db.jpg", + "/bfs/manga/fd3a53f04831e577707e4c873e2fc205e71d5cde.jpg", + "/bfs/manga/50e1c513336e0685ca01723d64c712294e534ca0.jpg" + ], + "sizes": [ + {"cx": 1600, "cy": 2300}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 1600, "cy": 2468}, + {"cx": 846, "cy": 1200} + ] +} +``` + + + +## data.index内容 + +以下内容为解密后的 JSON 数据定义 + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ----- | -------- | ---- | +| clips | array | 尺寸信息 | | +| pics | array | 图片路径 | | +| sizes | array | 尺寸信息 | | + +根对象中的`clips`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | obj | 第 1 页信息 | | +| n | obj | 第 (n+1) 页信息 | | +| …… | obj | …… | …… | + +`clips`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------ | ------------- | +| r | num | 图片宽度 | | +| b | num | 图片高度 | | +| t | num | (?) | | +| l | num | (?) | | +| pic | num | 图片页码序号 | 从 0 开始递增 | + +根对象中的`pics`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------------- | ------------------------------ | +| 0 | str | 第 1 图片路径 | 图片不能直接访问,需要二次鉴权 | +| n | str | 第 (n+1) 图片路径 | | +| …… | str | …… | …… | + +根对象中的`sizes`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | obj | 第 1 页信息 | | +| n | obj | 第 (n+1) 页信息 | | +| …… | obj | …… | …… | + +`clips`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| cx | num | 图片宽度 | | +| cy | num | 图片高度 | | diff --git a/bb-api-collect/docs/manga/light_card.md b/bb-api-collect/docs/manga/light_card.md new file mode 100644 index 0000000000..405daa4c2d --- /dev/null +++ b/bb-api-collect/docs/manga/light_card.md @@ -0,0 +1,200 @@ +# 获取轻享卡信息 + +> https://manga.bilibili.com/twirp/card.v1.Card/GetUserLightCard + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)/ APP + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|------------|-----|----------------|-----|-----------------| +| access_key | str | 登录`access_key` | | 与`SESSDATA`二选其一 | + +**json回复:** + +根对象: + +| 字段名 | 类型 | 内容 | 备注 | +|------|-----|------|------| +| code | num | 响应码 | 0:成功 | +| msg | str | | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段名 | 类型 | 内容 | 备注 | +|--------------------|-------|----------------|---------------------------------| +| state | num | 轻享卡开通状态 | 0:未开通
1:已开通 | +| show_state | num | | | +| expire_date | str | 轻享卡到期时间 | | +| receive_amount | num | 已领取数量 | | +| save_money | num | 已节省漫币 | | +| index | num | 默认选择签到周期 | | +| week | array | 一个领取周期内的领取状态信息 | | +| month_reward_state | num | 是否可选择全勤奖 | 0:不可领取
1:可领取
2:不可领取(灰色) | +| month_reward | num | | | +| cur_month_end | str | 全勤奖领取剩余时间 | | +| server_time | str | 当前服务器时间 | | + +`week`数组中的对象: + +| 字段名 | 类型 | 内容 | 备注 | +|-------------------|-----|-------------|------------------------------------------------| +| index | num | 第几领取周期 | 从`1`开始 | +| start_time | str | 本周期领取开始时间 | 1:待领取
2:已领取
3:明日可领
4:已失效
5:可领取 | +| end_time | str | 本周期领取结束时间 | `同上` | +| first | num | 本周期第1天的领取状态 | `同上` | +| second | num | 本周期第2天的领取状态 | `同上` | +| third | num | 本周期第3天的领取状态 | `同上` | +| fourth | num | 本周期第4天的领取状态 | `同上` | +| full_reward_state | num | 周期全勤奖领取状态 | 1:不可领取
2:可领取
3:已领取 | + +**示例:** + +`SESSDATA`方式: + +```shell +curl -L -X POST 'https://manga.bilibili.com/twirp/card.v1.Card/GetUserLightCard' \ +-H 'Cookie: SESSDATA=xxx' +``` + +`access_key`方式: + +```shell +curl -L -X POST 'https://manga.bilibili.com/twirp/card.v1.Card/GetUserLightCard?access_key=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "", + "data": { + "state": 1, + "show_state": 1, + "expire_date": "2023-03-09T23:59:59+08:00", + "receive_amount": 18, + "save_money": 890, + "index": 1, + "week": [ + { + "index": 1, + "start_time": "2023-02-10T00:00:00+08:00", + "end_time": "2023-02-16T23:59:59+08:00", + "first": 5, + "second": 1, + "third": 1, + "fourth": 1, + "full_reward_state": 1 + }, + { + "index": 2, + "start_time": "2023-02-17T00:00:00+08:00", + "end_time": "2023-02-23T23:59:59+08:00", + "first": 1, + "second": 1, + "third": 1, + "fourth": 1, + "full_reward_state": 1 + }, + { + "index": 3, + "start_time": "2023-02-24T00:00:00+08:00", + "end_time": "2023-03-02T23:59:59+08:00", + "first": 1, + "second": 1, + "third": 1, + "fourth": 1, + "full_reward_state": 1 + }, + { + "index": 4, + "start_time": "2023-03-03T00:00:00+08:00", + "end_time": "2023-03-09T23:59:59+08:00", + "first": 1, + "second": 1, + "third": 1, + "fourth": 1, + "full_reward_state": 1 + } + ], + "month_reward_state": 0, + "month_reward": 0, + "cur_month_end": "2023-03-10T00:00:00+08:00", + "server_time": "2023-02-10T10:59:43+08:00" + } +} +``` + +
+ +# 领取轻享卡奖励 + +> https://manga.bilibili.com/twirp/card.v1.Card/GetLightCoupon + +*请求方式:POST* + +是否需要登录:`是` + +认证方式:Cookie(SESSDATA)/ APP + +Content-Type:`application/json` + +**URL参数:** + +| 参数名 | 类型 | 必填 | 内容 | 备注 | +|------------|-----|----|-----------------|----| +| access_key | str | | 与`SESSDATA`二选其一 | | + +**正文参数( application/json ):** + +| 参数名 | 类型 | 必填 | 内容 | 备注 | +|-----------|-----|----|------|----------------------| +| weekIndex | num | √ | 第几周 | 从`1`开始 | +| type | num | √ | 领取类型 | 1:领取漫读券
2:领取限免卡 | + +**json回复:** + +根对象: + +| 字段名 | 类型 | 内容 | 备注 | +|------|-----|-----|-------------------------------------------------------------------| +| code | num | 响应码 | 0:成功
3:今日已领取,请明日再来
3:还未满足领取条件
4:找不到数据~
6:你点击太快了哦~ | +| msg | str | | | +| data | obj | | | + +**示例:** + +`SESSDATA`方式: + +```shell +curl -L -X POST 'https://manga.bilibili.com/twirp/card.v1.Card/GetLightCoupon' \ +-H 'content-type: application/json; charset=utf-8' \ +-H 'Cookie: SESSDATA=xxx' \ +--data-raw '{"type":1,"weekIndex":1}' +``` + +`access_key`方式: + +```shell +curl -L -X POST 'https://manga.bilibili.com/twirp/card.v1.Card/GetLightCoupon?access_key=xxx' \ +-H 'content-type: application/json; charset=utf-8' \ +--data-raw '{"type":1,"weekIndex":1}' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "", + "data": {} +} +``` + +
\ No newline at end of file diff --git a/bb-api-collect/docs/manga/point_shop.md b/bb-api-collect/docs/manga/point_shop.md new file mode 100644 index 0000000000..97d628c73a --- /dev/null +++ b/bb-api-collect/docs/manga/point_shop.md @@ -0,0 +1,443 @@ +# 积分商城 + +**注**:积分商城由web页面提供功能,地址为 https://manga.bilibili.com/eden/credits-exchange.html + +## 获取当前持有点数 + +> https://manga.bilibili.com/twirp/pointshop.v1.Pointshop/GetUserPoint + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)/ APP + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | | +| msg | str | 错误信息 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------- | ------------ | +| point | str | 点数 | 不登录时为0 | + +**示例:** + +```bash +curl 'https://manga.bilibili.com/twirp/pointshop.v1.Pointshop/GetUserPoint' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + + +```json +{ + "code": 0, + "msg": "", + "data": { + "point": "66666" + } +} +``` + +
+ +## 获取兑换奖品列表 + +> https://manga.bilibili.com/twirp/pointshop.v1.Pointshop/ListProduct + +*请求方式:POST* + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | | +| msg | str | 错误信息 | | +| data | array | 奖品列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---- | +| 0 | obj | 奖品1 | | +| n | obj | 奖品(n+1) | | +| …… | obj | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------- | ------------ | +| id | num | 物品id | | +| type | num | 物品类型 | 0:商城相关
3:限免券
7:福利券 | +| title | str | 物品名 | | +| image | str | 显示的图像 | 福利券为空 | +| amount | num | 库存总量 | | +| cost | num | 兑换所需点数(原价) | | +| real_cost | num | 兑换所需点数(现价) | | +| remain_amount | num | 库存剩余数 | | +| comic_id | num | 相关漫画id | | +| limits | array | 限定使用范围(漫画) | 限免券所适用的漫画 | +| discount | num | (?) | 目前恒为0 | +| product_type | num | 物品类型 | 1:限免券、福利券
4:商城满99立减10元券、商城5元无门槛券
5:商城5魔晶 | +| pendant_url | str | (?) | | +| pendant_expire | num | (?) | 0:限免券、福利券
7:商城满99立减10元券、商城5元无门槛券、商城5魔晶 | +| exchange_limit | num | 兑换次数限制 | | +| address_deadline | str | (?) | | +| act_type | num | (?) | 目前恒为0 | +| has_exchanged | bool | 是否兑换过该物品 | | +| main_coupon_deadline | str | 兑换后使用截止时间 | | +| deadline | str | 兑换后使用截止时间 | | +| point | str | (?) | 目前恒为0 | + +**示例:** + +```bash +curl 'https://manga.bilibili.com/twirp/pointshop.v1.Pointshop/ListProduct' +``` + +
+查看响应示例: + + +```json +{ + "code": 0, + "msg": "", + "data": [ + { + "id": 195, + "type": 7, + "title": "积分兑换", + "image": "", + "amount": 15999, + "cost": 200, + "real_cost": 100, + "remain_amount": 0, + "comic_id": 0, + "limits": [], + "discount": 0, + "product_type": 1, + "pendant_url": "", + "pendant_expire": 7, + "exchange_limit": 0, + "address_deadline": "0001-01-01T00:00:00Z", + "act_type": 0, + "has_exchanged": false, + "main_coupon_deadline": "0001-01-01T00:00:00Z", + "deadline": "", + "point": "0" + }, + { + "id": 1009, + "type": 0, + "title": "商城5魔晶", + "image": "", + "amount": 500, + "cost": 260, + "real_cost": 30, + "remain_amount": 0, + "comic_id": 0, + "limits": [], + "discount": 0, + "product_type": 5, + "pendant_url": "", + "pendant_expire": 0, + "exchange_limit": 1, + "address_deadline": "0001-01-01T00:00:00Z", + "act_type": 0, + "has_exchanged": false, + "main_coupon_deadline": "2022-03-22T23:59:59+08:00", + "deadline": "2022-03-22T23:59:59+08:00", + "point": "0" + }, + { + "id": 1008, + "type": 0, + "title": "商城满99立减10元券", + "image": "", + "amount": 400, + "cost": 2000, + "real_cost": 400, + "remain_amount": 390, + "comic_id": 0, + "limits": [], + "discount": 0, + "product_type": 4, + "pendant_url": "", + "pendant_expire": 0, + "exchange_limit": 1, + "address_deadline": "0001-01-01T00:00:00Z", + "act_type": 0, + "has_exchanged": false, + "main_coupon_deadline": "2022-03-22T23:59:59+08:00", + "deadline": "2022-03-22T23:59:59+08:00", + "point": "0" + }, + { + "id": 1007, + "type": 0, + "title": "商城5元无门槛券", + "image": "", + "amount": 200, + "cost": 1000, + "real_cost": 200, + "remain_amount": 134, + "comic_id": 0, + "limits": [], + "discount": 0, + "product_type": 4, + "pendant_url": "", + "pendant_expire": 0, + "exchange_limit": 1, + "address_deadline": "0001-01-01T00:00:00Z", + "act_type": 0, + "has_exchanged": false, + "main_coupon_deadline": "2022-03-22T23:59:59+08:00", + "deadline": "2022-03-22T23:59:59+08:00", + "point": "0" + }, + { + "id": 1536, + "type": 3, + "title": "白兔糖", + "image": "http://i0.hdslb.com/bfs/manga-static/c3369754789a77b5d0b15cc31c75538ac035b3aa.jpg", + "amount": 4000, + "cost": 100, + "real_cost": 75, + "remain_amount": 3991, + "comic_id": 27164, + "limits": [ + { + "type": 1, + "id": 27164, + "title": "白兔糖" + } + ], + "discount": 0, + "product_type": 1, + "pendant_url": "", + "pendant_expire": 7, + "exchange_limit": 0, + "address_deadline": "0001-01-01T00:00:00Z", + "act_type": 0, + "has_exchanged": false, + "main_coupon_deadline": "0001-01-01T00:00:00Z", + "deadline": "", + "point": "0" + } + ] +} +``` + +
+ + +## 兑换物品 + +> https://manga.bilibili.com/twirp/pointshop.v1.Pointshop/Exchange + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)/ APP + +**正文参数( application/x-www-form-urlencoded 或 application/json):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | ------------------------------------------------------------ | +| product_id | str | 物品id | 必要 | | +| product_num | num | 兑换个数 | 必要 | | +| point | num | 物品所需点数 | 必要 | 现价(real_cost) | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:兑换成功
1:积分不足
1:您点的太快了~
2:库存不足
3:product point mismatch(point填写错误)
3:超过用户最大可兑换数量
4:现在抢票的人太多啦,再点一下有机会优先上车喔 ε=ε=(ノ≧∇≦)ノ | +| message | str | 错误信息 | | + +**示例:** + +```bash +curl 'https://manga.bilibili.com/twirp/pointshop.v1.Pointshop/Exchange' \ +--data-urlencode 'product_id=195' \ +--data-urlencode 'product_num=1' \ +--data-urlencode 'point=real_cost' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "" +} +``` + +
+ +## 获取兑换历史记录 + +> https://manga.bilibili.com/twirp/activity.v1.Activity/GetPrizeList + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)/ APP + +**正文参数( application/x-www-form-urlencoded 或 application/json):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | ------------------------------------------------------------ | +| act_id | num | 固定值:90018 | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | | +| msg | str | 错误信息 | | | +| data | obj | 信息本体 | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | -------- | ---- | +| prizes | obj | 兑换记录 | | +| addr | obj | (?) | | + +`data`中的`prizes`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------- | ------------ | +| user_prize_id | str | 兑换id? | | +| prize_id | num | 兑换的物品id | | +| ctime | str | 兑换时间 | | +| addr | null | (?) | | +| deadline | str | 过期时间 | | +| type | num | 类型 | 1:限免券、福利券
8:商城5魔晶 | +| name | str | 物品名 | | + +**示例:** + +```bash +curl 'https://manga.bilibili.com/twirp/activity.v1.Activity/GetPrizeList' \ +--data-urlencode 'act_id=90018' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "", + "data": { + "prizes": [ + { + "user_prize_id": "55117444", + "prize_id": 1009, + "ctime": "2022-03-21T12:22:53+08:00", + "addr": null, + "deadline": "0001-01-01T00:00:00Z", + "type": 8, + "name": "商城5魔晶" + }, + { + "user_prize_id": "2594073385420523088", + "prize_id": 1536, + "ctime": "2022-03-21T12:07:24+08:00", + "addr": null, + "deadline": "0001-01-01T00:00:00Z", + "type": 1, + "name": "白兔糖限免卡" + }, + { + "user_prize_id": "4899916394614914913", + "prize_id": 195, + "ctime": "2021-12-24T12:01:08+08:00", + "addr": null, + "deadline": "0001-01-01T00:00:00Z", + "type": 1, + "name": "积分兑换" + }, + { + "user_prize_id": "1152921504636496551", + "prize_id": 195, + "ctime": "2021-12-13T12:05:13+08:00", + "addr": null, + "deadline": "0001-01-01T00:00:00Z", + "type": 1, + "name": "积分兑换" + } + ], + "addr": { + "name": "", + "phone": "", + "address": "", + "id_card": "" + } + } +} +``` + +
+ +## 获取玩法说明 + +> https://manga.bilibili.com/twirp/pointshop.v1.Pointshop/GetExchangeRule + +*请求方式:POST* + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| code | num | 返回值 | | +| msg | str | 错误信息 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| rule | str | 玩法说明 | | + +**示例:** + +```bash +curl 'https://manga.bilibili.com/twirp/pointshop.v1.Pointshop/GetExchangeRule' +``` + +
+查看响应示例: + + +```json +{ + "code": 0, + "msg": "", + "data": { + "rule": "日常兑换说明:\n1、赛季积分达到一定数量可兑换积分商城内相应的商品;\n2、日常兑换奖品的刷新时间为每日中午12点,每天可兑换的奖品总数有限(具体可见商品页面展示),请尽快兑换。\n3、兑换的福利券&限免卡奖品有效期详见兑换框内显示或卡券包内详情说明哦,请及时在有效期内使用。\n4、赛季积分有效期为当前赛季时长(每期赛季时长详见福利中心页面倒计时显示),请及时在有效期内进行使用。\n5、赛季积分可在福利中心完成特定任务获取,具体详情可至福利中心查看(部分活动也可获取赛季积分,可随时关注活动信息哦)。" + } +} +``` + +
diff --git a/bb-api-collect/docs/message/msg.md b/bb-api-collect/docs/message/msg.md new file mode 100644 index 0000000000..488b8cc996 --- /dev/null +++ b/bb-api-collect/docs/message/msg.md @@ -0,0 +1,258 @@ +# 通知消息 + +## 获取未读消息数 + +> + +> (新接口) + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +本接口不会返回未读的私信数,要获取未读的私信数请参阅[未读私信数](private_msg.md#未读私信数)相关说明 + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ---------------- | ------ | ------------------------- | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | -------------------- | --------------------------- | +| at | num | 未读at数(旧) | | +| chat | num | 0 | 仅旧接口,**作用尚不明确** | +| coin | num | 未读投币数 | | +| danmu | num | 未读弹幕数 | | +| favorite | num | 未读收藏数 | | +| like | num | 未读点赞数(旧) | | +| recv\_like | num | 未读收到喜欢数(新) | 同 `like` | +| recv\_reply | num | 未读回复与@数(新) | 即 `reply` 与 `at` 的值之和 | +| reply | num | 未读回复数(旧) | | +| sys\_msg | num | 未读系统通知数 | | +| sys\_msg\_style | num | 1 | 仅新接口, **作用尚不明确** | +| up | num | 未读UP主助手信息数 | | + +**示例:** + +以下信息代表了未读点赞数为10,未读回复数为4,未读at消息数为3,未读系统通知数为2,未读UP主助手信息数为1 + +```shell +curl 'https://api.vc.bilibili.com/x/im/web/msgfeed/unread' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "at": 3, + "chat": 0, + "coin": 0, + "danmu": 0, + "favorite": 0, + "like": 10, + "recv_like": 10, + "recv_reply": 4, + "reply": 4, + "sys_msg": 2, + "sys_msg_style": 1, + "up": 1 + } +} +``` + +
+ + +## 获取"回复我的"信息 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------ | ---- | ---------------- | ------ | ------------- | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | +| id | num | 起始 id | 非必要 | 详情见返回 | +| reply_time | num | 起始时间 | 非必要 | 详情见返回 | +| platform | str | 平台标识 | 非必要 | 可为 `web` 等 | +| web_location | str | 暂时不知道是啥 | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ----- | ----------- | ------------------------------ | +| cursor | obj | 光标 | 下一次查询的指针 | +| items | array | 通知列表 | 数组,每个元素代表一条回复通知 | +| last_view_at | num | unix 时间戳 | 上次查看的时间 | + +`cursor` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ----------- | ---------------------------------------------- | +| is_end | bool | 是否结束 | `false` 表示还有更多数据 | +| id | num | 通知 id | 最后(旧)一条通知的 id,用作下次查询的起始 id | +| time | num | unix 时间戳 | 最后一条通知的时间 | + +`items` 数组中的对象(每条通知): + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | -------------------- | ---------------------------- | +| id | num | 通知 id | | +| user | obj | **回复者**的用户信息 | | +| item | obj | 通知详情 | | +| counts | num | 通知计数 | 固定为 `1`,可能表示单条通知 | +| is_multi | num | 是否多回复 | 固定为 `0`,可能表示单条回复 | +| reply_time | num | unix 时间戳 | 回复时间 | + +`user` 对象(回复者信息): + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------------- | ------------------------------ | +| mid | num | 用户 mid | | +| fans | num | 粉丝数 | 固定为 `0`,可能不返回实际数据 | +| nickname | str | 用户昵称 | | +| avatar | str | 头像 URL | | +| mid_link | str | 用户主页链接 | 固定为空字符串 | +| follow | bool | 是否关注该用户 | `false` 表示未关注 | + +`item` 对象(通知详情): + +| 字段 | 类型 | 内容 | 备注 | +| -------------------- | ----- | ---------------- | ----------------------------- | +| subject_id | num | 主体 id | | +| root_id | num | 根评论 id | 最顶层的评论 ID | +| source_id | num | 源评论 id | 直接回复的评论 ID | +| target_id | num | 目标评论 id | 被回复的评论 ID | +| type | str | 通知类型 | 固定为 `"reply"`(回复类型) | +| business_id | num | 业务类型 id | `1`=视频评论,`11`=动态评论 | +| business | str | 业务名称 | `"评论"` 或 `"视频"` | +| title | str | 通知标题 | 摘要文本 | +| desc | str | 描述 | 固定为空字符串 | +| image | str | 图片 URL | 固定为空字符串 | +| uri | str | 跳转链接 | web 端跳转链接 | +| native_uri | str | 客户端跳转链接 | 客户端专用跳转链接 | +| detail_title | str | 详细标题 | 固定为空字符串 | +| root_reply_content | str | 根评论内容 | 最顶层评论的文本内容 | +| source_content | str | 源评论内容 | 直接回复的评论内容 | +| target_reply_content | str | 目标评论内容 | 被回复的评论内容 | +| at_details | array | @的用户列表 | 数组,每个元素是被@的用户对象 | +| topic_details | array | 话题详情 | 固定为空数组 | +| hide_reply_button | bool | 是否隐藏回复按钮 | | +| hide_like_button | bool | 是否隐藏点赞按钮 | | +| like_state | num | 点赞状态 | `0`=未点赞 | +| danmu | null | 弹幕信息 | 固定为 `null` | +| message | str | 消息内容 | 固定为空字符串 | + +`at_details` 数组中的对象(被@的用户): + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------------- | ------------------ | +| mid | num | 用户 mid | | +| fans | num | 粉丝数 | 固定为 `0` | +| nickname | str | 用户昵称 | | +| avatar | str | 头像 URL | | +| mid_link | str | 用户主页链接 | 固定为空字符串 | +| follow | bool | 是否关注该用户 | `false` 表示未关注 | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/msgfeed/reply' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "data": { + "cursor": { + "is_end": true, + "id": 823260581625886, + "time": 1749474709 + }, + "items": [{ + "id": 823260581625886, + "user": { + "mid": 3546910497441845, + "fans": 0, + "nickname": "佘总累了", + "avatar": "https://i2.hdslb.com/bfs/face/e45c62bd47729e07dd01a788988be865ed3d210e.jpg", + "mid_link": "", + "follow": false + }, + "item": { + "subject_id": 1073543151725051921, + "root_id": 0, + "source_id": 265141324256, + "target_id": 0, + "type": "dynamic", + "business_id": 17, + "business": "动态", + "title": "我已成为哔哩哔哩第245743680位转正会员,挑战转正答题考试获得60分。", + "desc": "", + "image": "", + "uri": "https://www.bilibili.com/opus/1073543151725051921#reply265141324256", + "native_uri": "bilibili://opus/detail/1073543151725051921?comment_root_id=265141324256&comment_on=1", + "detail_title": "", + "root_reply_content": "", + "source_content": "60", + "target_reply_content": "", + "at_details": [], + "topic_details": [], + "hide_reply_button": false, + "hide_like_button": false, + "like_state": 0, + "danmu": null, + "message": "" + }, + "counts": 1, + "is_multi": 0, + "reply_time": 1749474709 + }], + "last_view_at": 1749474724 + } +} +``` + +
diff --git a/bb-api-collect/docs/message/private_msg.md b/bb-api-collect/docs/message/private_msg.md new file mode 100644 index 0000000000..0baf0b4283 --- /dev/null +++ b/bb-api-collect/docs/message/private_msg.md @@ -0,0 +1,2077 @@ +# 私信 + +## 对象与常量说明 + +### 会话对象 + +| 字段 | 类型 | 内容 | 备注 | +| -------------------- | ---- | -------------------------------- | --------------------------------------------------- | +| talker_id | num | 聊天对象的id | `session_type` 为 `1` 时表示用户 mid,为 `2` 时表示粉丝团 id | +| session_type | num | 聊天对象的类型 | 1:用户
2:粉丝团 | +| at_seqno | num | 最近一次未读at自己的消息的序列号 | 在粉丝团会话中有效,若没有未读的 at 自己的消息则为 `0` | +| top_ts | num | 置顶该会话的时间 | 微秒级时间戳;若未置顶该会话则为 `0`;用于判断是否置顶了会话 | +| group_name | str | 粉丝团名称 | 在粉丝团会话中有效,其他会话中为空字符串 | +| group_cover | str | 粉丝团头像 | 在粉丝团会话中有效,其他会话中为空字符串 | +| is_follow | num | 是否关注了对方 | 在用户会话中有效,系统会话中为 `1`, 其他会话中为 `0` | +| is_dnd | num | 是否对会话设置了免打扰 | | +| ack_seqno | num | 最近一次已读的消息序列号 | 用于快速跳转到首条未读的消息 | +| ack_ts | num | 最近一次已读时间 | 微秒级时间戳 | +| session_ts | num | 会话时间 | 微秒级时间戳 | +| unread_count | num | 未读消息数 | | +| last_msg | 有效时:obj
无效时:null | 最近的一条消息 | 详见[私信主体对象](#私信主体对象) | +| group_type | num | 粉丝团类型 | 在粉丝团时有效
0:应援团
2:官方群(如:ID 为 10 的粉丝团) | +| can_fold | num | 会话是否可被折叠入未关注人消息 | 在用户会话中有效 | +| status | num | 会话状态 | 详细信息有待补充 | +| max_seqno | num | 最近一条消息的序列号 | | +| new_push_msg | num | 是否有新推送的消息 | | +| setting | num | 推送设置 | 0:接收推送
1:不接收推送
2:(?) | +| is_guardian | num | 自己是否为对方的骑士(?) | 在用户会话中有效
0:否
2:是(?) | +| is_intercept | num | 会话是否被拦截 | | +| is_trust | num | 是否信任此会话 | 若为 `1`,则表示此会话之前被拦截过,但用户选择信任本会话 | +| system_msg_type | num | 系统会话类型 | 0:非系统会话
1:主播小助手
5:系统通知(?)
7:UP主小助手
8:客服消息
9:支付小助手 | +| account_info | obj | 会话信息 | 仅在系统会话中出现 | +| live_status | num | 用户是否正在直播 | 在用户会话中有效,其他会话中为 `0` | +| biz_msg_unread_count | num | 未读通知消息数 | | +| user_label | null | (?) | **作用尚不明确** | + +`account_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---- | +| name | str | 会话名称 | | +| pic_url | str | 会话头像 | | + +### 私信主体对象 + +注:私信主体对象≠[私信内容对象](private_msg_content.md) + +| 字段 | 类型 | 内容 | 备注 | +| ---------------- | ---- | -------------- | -------------------------------------------------------------- | +| sender_uid | num | 发送者mid | | +| receiver_type | num | 接收者类型 | 1:用户
2:粉丝团 | +| receiver_id | num | 接收者id | `receiver_type` 为 `1` 时表示用户 mid,为 `2` 时表示粉丝团 id | +| msg_type | num | 消息类型 | 详见[私信消息类型、内容说明](private_msg_content.md) | +| content | str | 消息内容 | [私信内容对象](private_msg_content.md)**经过 JSON 序列化后的文本** | +| msg_seqno | num | 消息序列号 | 按照时间顺序从小到大 | +| timestamp | num | 消息发送时间 | 秒级时间戳 | +| at_uids | 有效时:array
无效时:null | at的成员mid | 在粉丝团时有效;此项为 `null` 或 `[0]` 均表示没有 at 成员 | +| msg_key | num | 消息唯一id | 部分库在解析JSON对象中的大数时存在数值的精度丢失问题,因此在处理此字段时可能会出现问题,建议使用修复了这一问题的库(如将大数转换成文本) | +| msg_status | num | 消息状态 | 0:正常
1:被撤回(接口仍能返回被撤回的私信内容)
2:被系统撤回(如:消息被举报;私信将不会显示在前端,B站接口也不会返回被系统撤回的私信的信息)
50:图片已失效(私信内容为一张提示“图片出现问题”的图片) | +| sys_cancel | bool | 是否为系统撤回 | 仅当 `msg_type` 为 `5` 且此项值为 `true` 时有此项;若此项值为 `true`,表示目标消息是被系统撤回的,此时前端将不显示该私信且没有提示 | +| notify_code | str | 通知代码 | 发送通知时使用,以下划线 `_` 分割,第 1 项表示主业务 id,第 2 项表示子业务 id;若这条私信非通知则为空文本;详细信息有待补充 | +| new_face_version | num | 表情包版本 | 为 `0` 或无此项表示旧版表情包,此时 B 站会自动转换成新版表情包,例如 `[doge]` -> `[tv_doge]`;`1` 为新版 | +| msg_source | num | 消息来源 | 见[消息来源列表](#消息来源列表msg_source) | + +`私信主体对象`中的`at_uids`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ------- | +| 0 | num | 用户1 | 成员mid | +| n | num | 用户(n+1) | | +| …… | num | …… | …… | + +### 消息来源列表(`msg_source`) + +| 代码 | 含义 | 备注 | +| ---- | ------------------------- | ----------------------------------- | +| 0 | 未知来源 | 在以前发送的部分私信的来源代码 | +| 1 | iOS | | +| 2 | Android | | +| 3 | H5 | | +| 4 | PC客户端 | | +| 5 | 官方推送消息 | 包括:官方向大多数用户自动发送的私信(如:UP主小助手的推广)等 | +| 6 | 推送/通知消息 | 包括:特别关注时稿件的自动推送、因成为契约者而自动发送的私信、包月充电回馈私信、官方发送的特定于自己的消息(如:UP主小助手的稿件审核状态通知)等 | +| 7 | Web | | +| 8 | 自动回复 - 被关注回复 | B站前端会显示“此条消息为自动回复” | +| 9 | 自动回复 - 收到消息回复 | B站前端会显示“此条消息为自动回复” | +| 10 | 自动回复 - 关键词回复 | B站前端会显示“此条消息为自动回复” | +| 11 | 自动回复 - 大航海上船回复 | B站前端会显示“此条消息为自动回复” | +| 12 | 自动推送 - UP 主赠言 | 在以前稿件推送消息与其附带的 UP 主赠言是 2 条不同的私信(其中 UP 主赠言的消息来源代码为 12),现在 UP 主赠言已并入为[稿件自动推送消息](private_msg_content.md#视频推送消息msg_type11)的一部分(`attach_msg`) | +| 13 | 粉丝团系统提示 | 如:粉丝团中的提示信息“欢迎xxx入群” | +| 16 | 系统 | 目前仅在 `msg_type` 为 `51` 时使用该代码 | +| 17 | 互相关注 | 互相关注时自动发送的私信“我们已互相关注,开始聊天吧~” | +| 18 | 系统提示 | 目前仅在 `msg_type` 为 `18` 时使用该代码,如:“对方主动回复或关注你前,最多发送1条消息” | +| 19 | AI | 如:给[搜索AI助手测试版](https://space.bilibili.com/1400565964/)发送私信时对方的自动回复 | + +## 会话相关 + +### 获取未读私信数 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +注: 该接口默认每 2 分钟请求一次;该接口不会返回[未读粉丝团私信数](#获取未读粉丝团私信数) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------------ | ---- | -------------------------- | ------ | -------------------------------------------------------------------------- | +| unread_type | num | 未读类型 | 非必要 | 0:所有
1:仅已关注
2:仅未关注
3:仅被拦截 (须同时设置参数 `show_dustbin=1`)
默认为 `0` | +| show_unfollow_list | num | 是否返回未关注人推送消息数 | 非必要 | 0:否
1:是 | +| show_dustbin | num | 是否返回被拦截私信数 | 非必要 | 0:否
1:是 | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| msg | str | 错误信息 | 默认为0 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------------- | ---- | ------------------------ | ---------------- | +| unfollow_unread | num | 未读未关注用户私信数 | | +| follow_unread | num | 未读已关注用户私信数 | | +| unfollow_push_msg | num | 未读未关注用户推送消息数 | | +| dustbin_push_msg | num | 未读被拦截的推送消息数 | | +| dustbin_unread | num | 未读被拦截的私信数 | | +| biz_msg_unfollow_unread | num | 未读未关注用户通知数 | | +| biz_msg_follow_unread | num | 未读已关注用户通知数 | | +| custom_unread | num | 未读客服消息数 | | + +**示例:** + +以下信息代表未读未关注用户私信数为 `1` 条,未读已关注用户私信数为 `6` 条 + +```shell +curl -G 'https://api.vc.bilibili.com/session_svr/v1/session_svr/single_unread' \ + --data-urlencode 'unread_type=0' \ + --data-urlencode 'show_unfollow_list=1' \ + --data-urlencode 'show_dustbin=1' \ + --data-urlencode 'build=0' \ + --data-urlencode 'mobi_app=web' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": { + "unfollow_unread": 1, + "follow_unread": 6, + "unfollow_push_msg": 0, + "dustbin_push_msg": 0, + "dustbin_unread": 0, + "biz_msg_unfollow_unread": 0, + "biz_msg_follow_unread": 0, + "custom_unread": 0 + } +} +``` + +
+ +### 获取未读粉丝团私信数 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ---------------- | ------ | ------------- | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| msg | str | 错误信息 | 默认为0 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ---------------- | ---------------- | +| unread_count | num | 未读粉丝团私信数 | | + +**示例:** + +以下信息代表未读粉丝团私信数为 `497` 条 + +```shell +curl -G 'https://api.vc.bilibili.com/session_svr/v1/session_svr/my_group_unread' \ + --data-urlencode 'build=0' \ + --data-urlencode 'mobi_app=web' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": { + "unread_count": 497 + } +} +``` + +
+ +### 获取指定类型会话列表 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------- | ---- | -------------------- | ------ | ------------------------- | +| session_type | num | 会话类型 | 必要 | 1:用户与系统
2:未关注人
3:粉丝团
4:所有
5:被拦截
6:花火商单
7:所有系统消息
8:陌生人(与 “未关注人” 不同,不包含官方消息)
9:关注的人与系统 | +| group_fold | num | 是否折叠粉丝团消息 | 非必要 | 0:否
1:是 | +| unfollow_fold | num | 是否折叠未关注人消息 | 非必要 | 0:否
1:是 | +| sort_rule | num | 排序方式 | 非必要 | 仅当 `session_type` 不为 `4`、`7` 时有效
1、2:按会话时间逆向排序
3:按已读时间逆向排序
其他:用户与系统按会话时间逆向排序,粉丝团按加入时间正向排序 | +| begin_ts | num | 起始时间 | 非必要 | 微秒级时间戳 | +| end_ts | num | 终止时间 | 非必要 | 微秒级时间戳 | +| size | num | 返回的会话数 | 非必要 | 默认为 `20`,最大为 `100` | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误
2:非法参数 | +| msg | str | 错误信息 | 默认为0 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------------- | ---- | ---------------------------- | ------------------------ | +| session_list | 有会话时:array
无会话时:null | 会话列表 | | +| has_more | num | 是否有更多会话 | | +| anti_distrub_cleaning | bool | 是否开启了“一键防骚扰”功能 | | +| is_address_list_empty | num | 0 | **作用尚不明确** | +| system_msg | obj | 系统会话列表 | 仅当存在系统会话时有此项 | +| show_level | bool | 是否在会话列表中显示用户等级 | 目前恒为 `true` | + +`data`对象中的`session_list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ------------------------- | +| 0 | obj | 会话1 | 详见[会话对象](#会话对象) | +| n | obj | 会话(n+1) | | +| …… | obj | …… | …… | + +`data`对象中的`system_msg`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------ | ---- | ---------- | ---------------------------------------------------------- | +| {系统会话类型代码} | num | 系统会话id | 详见[会话对象](#会话对象)中对 `system_msg_type` 字段的说明 | + +**示例:** + +获取所有类型的会话列表: + +```shell +curl -G 'https://api.vc.bilibili.com/session_svr/v1/session_svr/get_sessions' \ + --data-urlencode 'session_type=4' \ + --data-urlencode 'group_fold=0' \ + --data-urlencode 'unfollow_fold=0' \ + --data-urlencode 'sort_rule=2' \ + --data-urlencode 'size=3' \ + --data-urlencode 'build=0' \ + --data-urlencode 'mobi_app=web' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": { + "session_list": [ + { + "talker_id": 844424930131966, + "session_type": 1, + "at_seqno": 0, + "top_ts": 0, + "group_name": "", + "group_cover": "", + "is_follow": 1, + "is_dnd": 0, + "ack_seqno": 1238729956474887, + "ack_ts": 1709536924979884, + "session_ts": 1712305278098351, + "unread_count": 4, + "last_msg": { + "sender_uid": 844424930131966, + "receiver_type": 1, + "receiver_id": 425503913, + "msg_type": 10, + "content": "{\"title\":\"流量奖励到账通知\",\"text\":\"恭喜您已获得2000流量曝光奖励,快来投稿使用吧。\",\"jump_text\":\"\",\"jump_uri\":\"\",\"modules\":null,\"jump_text_2\":\"\",\"jump_uri_2\":\"\",\"jump_text_3\":\"\",\"jump_uri_3\":\"\",\"notifier\":null,\"jump_uri_config\":{\"all_uri\":\"https://member.bilibili.com/york/flow-reward?navhide=1\\u0026from=msgrecall\",\"text\":\"\"},\"jump_uri_2_config\":{\"text\":\"\"},\"jump_uri_3_config\":{\"text\":\"\"},\"biz_content\":null}", + "msg_seqno": 1285290404823041, + "timestamp": 1712305278, + "at_uids": null, + "msg_key": 7354295169819585966, + "msg_status": 0, + "notify_code": "2091_253", + "new_face_version": 1, + "msg_source": 6 + }, + "group_type": 0, + "can_fold": 0, + "status": 0, + "max_seqno": 1285290404823041, + "new_push_msg": 1, + "setting": 0, + "is_guardian": 0, + "is_intercept": 0, + "is_trust": 0, + "system_msg_type": 7, + "account_info": { + "name": "UP主小助手", + "pic_url": "https://message.biliimg.com/bfs/im/489a63efadfb202366c2f88853d2217b5ddc7a13.png" + }, + "live_status": 0, + "biz_msg_unread_count": 0, + "user_label": null + }, + { + "talker_id": 293793435, + "session_type": 1, + "at_seqno": 0, + "top_ts": 0, + "group_name": "", + "group_cover": "", + "is_follow": 1, + "is_dnd": 0, + "ack_seqno": 1236306587877408, + "ack_ts": 1709536984481314, + "session_ts": 1709385615744065, + "unread_count": 0, + "last_msg": { + "sender_uid": 293793435, + "receiver_type": 1, + "receiver_id": 425503913, + "msg_type": 11, + "content": "{\"title\":\"OHHHHHH家人们,我分数终于破w了!紫框了这下确实不好意思说自己是只打红谱的萌新了\",\"times\":14,\"cover\":\"http://i0.hdslb.com/bfs/archive/8821c03ab27a0bcf2bf32af814e758ab17a1e27e.png\",\"rid\":1951316064,\"type_\":8,\"desc\":\"OHHHHHH家人们,我分数终于破w了!紫框了这下确实不好意思说自己是只打红谱的萌新了\",\"bvid\":\"BV1zC411p7JN\",\"view\":452,\"danmaku\":0,\"pub_date\":1709385603,\"attach_msg\":null}", + "msg_seqno": 1236306587877408, + "timestamp": 1709385615, + "at_uids": null, + "msg_key": 7341755312943193481, + "msg_status": 0, + "notify_code": "", + "new_face_version": 1, + "msg_source": 6 + }, + "group_type": 0, + "can_fold": 0, + "status": 0, + "max_seqno": 1236306587877408, + "new_push_msg": 0, + "setting": 0, + "is_guardian": 0, + "is_intercept": 0, + "is_trust": 0, + "system_msg_type": 0, + "live_status": 0, + "biz_msg_unread_count": 0, + "user_label": null + }, + { + "talker_id": 221082140, + "session_type": 2, + "at_seqno": 0, + "top_ts": 0, + "group_name": "社会易姐QwQ的应援团", + "group_cover": "http://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg", + "is_follow": 0, + "is_dnd": 0, + "ack_seqno": 20, + "ack_ts": 1695011620552332, + "session_ts": 1693626568439784, + "unread_count": 0, + "last_msg": { + "sender_uid": 0, + "receiver_type": 2, + "receiver_id": 221082140, + "msg_type": 306, + "content": "{\"group_id\":221082140,\"content\":\"欢迎罗板栗入群\"}", + "msg_seqno": 20, + "timestamp": 1693626568, + "at_uids": null, + "msg_key": 7274070721607234847, + "msg_status": 0, + "notify_code": "", + "msg_source": 13 + }, + "group_type": 0, + "can_fold": 0, + "status": 0, + "max_seqno": 20, + "new_push_msg": 0, + "setting": 0, + "is_guardian": 0, + "is_intercept": 0, + "is_trust": 0, + "system_msg_type": 0, + "live_status": 0, + "biz_msg_unread_count": 0, + "user_label": null + } + ], + "has_more": 1, + "anti_disturb_cleaning": false, + "is_address_list_empty": 0, + "system_msg": { + "1": 844424930131967, + "7": 844424930131966, + "9": 844424930131965 + }, + "show_level": true + } +} +``` + +
+ +### 获取新会话列表 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +获取指定时间之后的新会话列表 + +注:该接口默认每 20 秒请求一次 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ---------------- | ------ | ------------------------- | +| begin_ts | num | 起始时间 | 非必要 | 微秒级时间戳 | +| size | num | 返回的会话数 | 非必要 | 默认为 `20`,最大为 `100` | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| msg | str | 错误信息 | 默认为0 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------------- | ---- | ---------------------------- | ---------------------- | +| session_list | 有会话时:array
无会话时:null | 会话列表 | 按发送时间顺序逆向排序 | +| has_more | num | 是否有更多会话 | | +| anti_distrub_cleaning | bool | 是否开启了“一键防骚扰”功能 | | +| is_address_list_empty | num | 0 | **作用尚不明确** | +| show_level | bool | 是否在会话列表中显示用户等级 | 目前恒为 `false` | + +`data`对象中的`session_list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ------------------------- | +| 0 | obj | 会话1 | 详见[会话对象](#会话对象) | +| n | obj | 会话(n+1) | | +| …… | obj | …… | …… | + +**示例:** + +获取`begin_ts=1712420213519391`之后的新会话列表: + +```shell +curl -G 'https://api.vc.bilibili.com/session_svr/v1/session_svr/new_sessions' \ + --data-urlencode 'begin_ts=1712420213519391' \ + --data-urlencode 'size=3' \ + --data-urlencode 'build=0' \ + --data-urlencode 'mobi_app=web' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": { + "session_list": [ + { + "talker_id": 844424930131966, + "session_type": 1, + "at_seqno": 0, + "top_ts": 0, + "group_name": "", + "group_cover": "", + "is_follow": 1, + "is_dnd": 0, + "ack_seqno": 1238729956474887, + "ack_ts": 1709536924979884, + "session_ts": 1712305278098351, + "unread_count": 4, + "last_msg": { + "sender_uid": 844424930131966, + "receiver_type": 1, + "receiver_id": 425503913, + "msg_type": 10, + "content": "{\"title\":\"流量奖励到账通知\",\"text\":\"恭喜您已获得2000流量曝光奖励,快来投稿使用吧。\",\"jump_text\":\"\",\"jump_uri\":\"\",\"modules\":null,\"jump_text_2\":\"\",\"jump_uri_2\":\"\",\"jump_text_3\":\"\",\"jump_uri_3\":\"\",\"notifier\":null,\"jump_uri_config\":{\"all_uri\":\"https://member.bilibili.com/york/flow-reward?navhide=1\\u0026from=msgrecall\",\"text\":\"\"},\"jump_uri_2_config\":{\"text\":\"\"},\"jump_uri_3_config\":{\"text\":\"\"},\"biz_content\":null}", + "msg_seqno": 1285290404823041, + "timestamp": 1712305278, + "at_uids": null, + "msg_key": 7354295169819585966, + "msg_status": 0, + "notify_code": "2091_253", + "new_face_version": 1, + "msg_source": 6 + }, + "group_type": 0, + "can_fold": 0, + "status": 0, + "max_seqno": 1285290404823041, + "new_push_msg": 1, + "setting": 0, + "is_guardian": 0, + "is_intercept": 0, + "is_trust": 0, + "system_msg_type": 7, + "account_info": { + "name": "UP主小助手", + "pic_url": "https://message.biliimg.com/bfs/im/489a63efadfb202366c2f88853d2217b5ddc7a13.png" + }, + "live_status": 0, + "biz_msg_unread_count": 0, + "user_label": null + }, + { + "talker_id": 293793435, + "session_type": 1, + "at_seqno": 0, + "top_ts": 0, + "group_name": "", + "group_cover": "", + "is_follow": 1, + "is_dnd": 0, + "ack_seqno": 1236306587877408, + "ack_ts": 1709536984481314, + "session_ts": 1709385615744065, + "unread_count": 0, + "last_msg": { + "sender_uid": 293793435, + "receiver_type": 1, + "receiver_id": 425503913, + "msg_type": 11, + "content": "{\"title\":\"OHHHHHH家人们,我分数终于破w了!紫框了这下确实不好意思说自己是只打红谱的萌新了\",\"times\":14,\"cover\":\"http://i0.hdslb.com/bfs/archive/8821c03ab27a0bcf2bf32af814e758ab17a1e27e.png\",\"rid\":1951316064,\"type_\":8,\"desc\":\"OHHHHHH家人们,我分数终于破w了!紫框了这下确实不好意思说自己是只打红谱的萌新了\",\"bvid\":\"BV1zC411p7JN\",\"view\":452,\"danmaku\":0,\"pub_date\":1709385603,\"attach_msg\":null}", + "msg_seqno": 1236306587877408, + "timestamp": 1709385615, + "at_uids": null, + "msg_key": 7341755312943193481, + "msg_status": 0, + "notify_code": "", + "new_face_version": 1, + "msg_source": 6 + }, + "group_type": 0, + "can_fold": 0, + "status": 0, + "max_seqno": 1236306587877408, + "new_push_msg": 0, + "setting": 0, + "is_guardian": 0, + "is_intercept": 0, + "is_trust": 0, + "system_msg_type": 0, + "live_status": 0, + "biz_msg_unread_count": 0, + "user_label": null + }, + { + "talker_id": 221082140, + "session_type": 2, + "at_seqno": 0, + "top_ts": 0, + "group_name": "社会易姐QwQ的应援团", + "group_cover": "http://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg", + "is_follow": 0, + "is_dnd": 0, + "ack_seqno": 20, + "ack_ts": 1695011620552332, + "session_ts": 1693626568439784, + "unread_count": 0, + "last_msg": { + "sender_uid": 0, + "receiver_type": 2, + "receiver_id": 221082140, + "msg_type": 306, + "content": "{\"group_id\":221082140,\"content\":\"欢迎罗板栗入群\"}", + "msg_seqno": 20, + "timestamp": 1693626568, + "at_uids": null, + "msg_key": 7274070721607234847, + "msg_status": 0, + "notify_code": "", + "msg_source": 13 + }, + "group_type": 0, + "can_fold": 0, + "status": 0, + "max_seqno": 20, + "new_push_msg": 0, + "setting": 0, + "is_guardian": 0, + "is_intercept": 0, + "is_trust": 0, + "system_msg_type": 0, + "live_status": 0, + "biz_msg_unread_count": 0, + "user_label": null + } + ], + "has_more": 0, + "anti_disturb_cleaning": false, + "is_address_list_empty": 0, + "show_level": false + } +} +``` + +
+ +### 获取会话详细信息 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +若从未与该会话聊过天,则返回 1000004 `入口节点已存在` 错误 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------ | ---- | ---------------- | ------ | ------------------------------------------------------ | +| talker_id | num | 聊天对象的id | 必要 | `session_type` 为 `1` 时表示用户 mid,为 `2` 时表示粉丝团 id | +| session_type | num | 聊天对象的类型 | 必要 | 1:用户
2:粉丝团 | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误
1000004:入口节点已存在 | +| msg | str | 错误信息 | 默认为0 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 有效时:obj
无效时:null | 数据本体 | 详见[会话对象](#会话对象) | + +**示例:** + +获取会话`talker_id=293793435&session_type=1`的详细信息: + +```shell +curl -G 'https://api.vc.bilibili.com/session_svr/v1/session_svr/session_detail' \ + --data-urlencode 'talker_id=293793435' \ + --data-urlencode 'session_type=1' \ + --data-urlencode 'build=0' \ + --data-urlencode 'mobi_app=web' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": { + "talker_id": 293793435, + "session_type": 1, + "at_seqno": 0, + "top_ts": 0, + "group_name": "", + "group_cover": "", + "is_follow": 1, + "is_dnd": 0, + "ack_seqno": 1236306587877408, + "ack_ts": 1709536984481314, + "session_ts": 1709385615744065, + "unread_count": 0, + "last_msg": { + "sender_uid": 293793435, + "receiver_type": 1, + "receiver_id": 425503913, + "msg_type": 11, + "content": "{\"title\":\"OHHHHHH家人们,我分数终于破w了!紫框了这下确实不好意思说自己是只打红谱的萌新了\",\"times\":14,\"cover\":\"http://i0.hdslb.com/bfs/archive/8821c03ab27a0bcf2bf32af814e758ab17a1e27e.png\",\"rid\":1951316064,\"type_\":8,\"desc\":\"OHHHHHH家人们,我分数终于破w了!紫框了这下确实不好意思说自己是只打红谱的萌新了\",\"bvid\":\"BV1zC411p7JN\",\"view\":452,\"danmaku\":0,\"pub_date\":1709385603,\"attach_msg\":null}", + "msg_seqno": 1236306587877408, + "timestamp": 1709385615, + "at_uids": null, + "msg_key": 7341755312943193481, + "msg_status": 0, + "notify_code": "", + "new_face_version": 1, + "msg_source": 6 + }, + "group_type": 0, + "can_fold": 0, + "status": 0, + "max_seqno": 1236306587877408, + "new_push_msg": 0, + "setting": 0, + "is_guardian": 0, + "is_intercept": 0, + "is_trust": 0, + "system_msg_type": 0, + "live_status": 0, + "biz_msg_unread_count": 0, + "user_label": null + } +} +``` + +
+ +### 获取会话限制状态 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +仅支持用户会话 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| uid | num | 聊天对象mid | 必要 | | +| type | num | 1 | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
2:非法参数
-101:账号未登录
-400:请求错误 | +| msg | str | 错误信息 | 默认为0 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ------------------------ | ---------------------------- | +| is_limit | num | 用户是否被封禁 | | +| report_limit | num | 自己是否被限制举报该会话 | 常见于自己被封禁时出现该情况 | + +**示例:** + +获取`uid=123`的限制状态: + +```shell +curl -G 'https://api.vc.bilibili.com/link_setting/v1/link_setting/is_limit' \ + --data-urlencode 'uid=123' \ + --data-urlencode 'type=1' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": { + "is_limit": 0, + "report_limit": 0 + } +} +``` + +
+ +### 获取会话免打扰状态 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | ---------------- | ------ | ----------------------- | +| own_uid | num | 自己的mid | 必要 | | +| uids | num | 用户mid | 非必要 | 仅支持填入 **1 个** mid | +| group_ids | num | 粉丝团id | 非必要 | 仅支持填入 **1 个** id | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
2:非法参数
-101:账号未登录
-400:请求错误 | +| msg | str | 错误信息 | 默认为0 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ----- | ---------------- | ------------------------------------- | +| uid_settings | array | 用户免打扰状态 | 仅当请求参数 `uids` 存在时有此项 | +| group_settings | array | 粉丝团免打扰状态 | 仅当请求参数 `group_ids` 存在时有此项 | + +`data`对象中的`uid_settings`、`group_settings`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | --------------------------------- | +| 0 | obj | 会话免打扰状态 | 仅有1项 | + +`uid_settings`、`group_settings`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ----------------- | -------------------------------- | +| id | num | 用户mid或粉丝团id | | +| setting | num | 免打扰状态 | 0:关闭免打扰
1:开启免打扰 | + +**示例:** + +获取会话`uids=2`与`group_ids=221082140`的免打扰状态: + +```shell +curl -G 'https://api.vc.bilibili.com/link_setting/v1/link_setting/get_msg_dnd' \ + --data-urlencode 'own_uid=425503913' \ + --data-urlencode 'uids=2' \ + --data-urlencode 'group_ids=221082140' \ + --data-urlencode 'build=0' \ + --data-urlencode 'mobi_app=web' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": { + "uid_settings": [{ + "id": 2, + "setting": 0 + }], + "group_settings": [{ + "id": 221082140, + "setting": 0 + }] + } +} +``` + +
+ +### 获取会话推送设置 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +仅支持用户会话 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ---------------- | ------ | ------------- | +| talker_uid | num | 聊天对象mid | 必要 | | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
2:非法参数
-101:账号未登录
-400:请求错误 | +| msg | str | 错误信息 | 默认为0 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ---- | ---------------------- | ----------------------------------- | +| follow_status | num | 对方对于自己的关注属性 | 0:未关注
~~1:悄悄关注(现已下线)~~
2:已关注
6:已互粉
128:已拉黑 | +| special | num | 自己是否特别关注了对方 | | +| push_setting | num | 推送设置 | 0:接收推送
1:不接收推送 | +| show_push_setting | num | 是否显示推送设置 | | + +**示例:** + +获取`talker_uid=123`的推送设置: + +```shell +curl -G 'https://api.vc.bilibili.com/link_setting/v1/link_setting/get_session_ss' \ + --data-urlencode 'talker_uid=123' \ + --data-urlencode 'build=0' \ + --data-urlencode 'mobi_app=web' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": { + "follow_status": 6, + "special": 1, + "push_setting": 0, + "show_push_setting": 1 + } +} +``` + +
+ +### 设置会话为已读 + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +将指定会话中的指定消息及以前的消息设置为已读 + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------ | ---- | ------------------------ | ------ | ---------------------------------------------------- | +| talker_id | num | 聊天对象的id | 必要 | `session_type` 为 `1` 时表示用户 mid,为 `2` 时表示粉丝团 id | +| session_type | num | 聊天对象的类型 | 必要 | 1:用户
2:粉丝团 | +| ack_seqno | num | 设置为已读的消息序列号 | 非必要 | 留空表示最新的消息 | +| csrf_token | str | CSRF Token(位于cookie) | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| msg | str | 错误信息 | 成功时为0 | +| message | str | 错误信息 | 成功时为0 | +| ttl | num | | 默认为1 | +| data | 有效时:obj
无效时:不存在该项 | 信息本体 | 空对象 | + +**示例:** + +将`talker_id=293793435`、`session_type=1`的`ack_seqno=1236306587877408`消息及之前的消息设置为已读 + +```shell +curl 'https://api.vc.bilibili.com/session_svr/v1/session_svr/update_ack' \ + --data-urlencode 'talker_id=293793435' \ + --data-urlencode 'session_type=1' \ + --data-urlencode 'ack_seqno=1236306587877408' \ + --data-urlencode 'csrf=xxx' \ + --data-urlencode 'csrf_token=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": {} +} +``` + +
+ +### 移除指定会话 + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +将指定会话从会话列表中移除,不会删除聊天记录 + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------ | ---- | ------------------------ | ------ | ---------------------------------------------------- | +| talker_id | num | 聊天对象的id | 必要 | `session_type` 为 `1` 时表示用户 mid,为 `2` 时表示粉丝团 id | +| session_type | num | 聊天对象的类型 | 必要 | 1:用户
2:粉丝团 | +| csrf_token | str | CSRF Token(位于cookie) | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| msg | str | 错误信息 | 成功时为0 | +| message | str | 错误信息 | 成功时为0 | +| ttl | num | | 默认为1 | +| data | 有效时:obj
无效时:不存在该项 | 信息本体 | 空对象 | + +**示例:** + +移除会话`talker_id=2&session_type=1` + +```shell +curl 'https://api.vc.bilibili.com/session_svr/v1/session_svr/remove_session' \ + --data-urlencode 'talker_id=2' \ + --data-urlencode 'session_type=1' \ + --data-urlencode 'csrf=xxx' \ + --data-urlencode 'csrf_token=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": {} +} +``` + +
+ +### 修改会话置顶状态 + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------ | ---- | ------------------------ | ------ | ---------------------------------------------------- | +| talker_id | num | 聊天对象的id | 必要 | `session_type` 为 `1` 时表示用户 mid,为 `2` 时表示粉丝团 id | +| session_type | num | 聊天对象的类型 | 必要 | 1:用户
2:粉丝团 | +| op_type | num | 操作类型 | 必要 | 0:置顶
1:取消置顶 | +| csrf_token | str | CSRF Token(位于cookie) | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| msg | str | 错误信息 | 成功时为0 | +| message | str | 错误信息 | 成功时为0 | +| ttl | num | | 默认为1 | +| data | 有效时:obj
无效时:不存在该项 | 信息本体 | 空对象 | + +**示例:** + +置顶会话`talker_id=293793435&session_type=1` + +```shell +curl 'https://api.vc.bilibili.com/session_svr/v1/session_svr/set_top' \ + --data-urlencode 'talker_id=293793435' \ + --data-urlencode 'session_type=1' \ + --data-urlencode 'op_type=0' \ + --data-urlencode 'csrf=xxx' \ + --data-urlencode 'csrf_token=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": {} +} +``` + +
+ +### 修改会话免打扰状态 + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------ | ---- | ------------------------ | ------------ | -------------------------------- | +| uid | num | 自己的mid | 非必要 | | +| setting | num | 免打扰设置 | 必要 | 0:取消免打扰
1:开启免打扰 | +| dnd_uid | num | 用户mid | 必要(可选) | 当聊天对象为用户时有效 | +| dnd_group_id | num | 粉丝团id | 必要(可选) | 当聊天对象为粉丝团时有效 | +| csrf_token | str | CSRF Token(位于cookie) | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| msg | str | 错误信息 | 成功时为0 | +| message | str | 错误信息 | 成功时为0 | +| ttl | num | | 默认为1 | +| data | 有效时:obj
无效时:不存在该项 | 信息本体 | 空对象 | + +**示例:** + +对会话`dnd_uid=2`开启免打扰 + +```shell +curl 'https://api.vc.bilibili.com/link_setting/v1/link_setting/set_msg_dnd' \ + --data-urlencode 'uid=425503913' \ + --data-urlencode 'setting=1' \ + --data-urlencode 'dnd_uid=2' \ + --data-urlencode 'csrf=xxx' \ + --data-urlencode 'csrf_token=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": {} +} +``` + +
+ +### 修改会话推送设置 + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +仅支持用户会话 + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | ------ | ------------------------------ | +| talker_uid | num | 聊天对象mid | 必要 | | +| setting | num | 推送设置 | 必要 | 0:接收推送
1:不接收推送 | +| csrf_token | str | CSRF Token(位于cookie) | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| msg | str | 错误信息 | 成功时为0 | +| message | str | 错误信息 | 成功时为0 | +| ttl | num | | 默认为1 | +| data | 有效时:obj
无效时:不存在该项 | 信息本体 | 空对象 | + +**示例:** + +修改`talker_uid=2`的推送设置为不接收推送 + +```shell +curl 'https://api.vc.bilibili.com/link_setting/v1/link_setting/set_push_ss' \ + --data-urlencode 'talker_uid=2' \ + --data-urlencode 'setting=1' \ + --data-urlencode 'csrf=xxx' \ + --data-urlencode 'csrf_token=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": {} +} +``` + +
+ +### 修改会话拦截状态 + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +仅支持用户会话 + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | ------ | ---------------------------- | +| talker_id | num | 聊天对象mid | 必要 | | +| status | num | 拦截状态 | 必要 | 0:取消拦截
1:设置拦截 | +| csrf_token | str | CSRF Token(位于cookie) | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| msg | str | 错误信息 | 成功时为0 | +| message | str | 错误信息 | 成功时为0 | +| ttl | num | | 默认为1 | +| data | 有效时:obj
无效时:不存在该项 | 信息本体 | 空对象 | + +**示例:** + +对会话`talker_id=2`取消拦截状态 + +```shell +curl 'https://api.vc.bilibili.com/session_svr/v1/session_svr/update_intercept' \ + --data-urlencode 'talker_id=2' \ + --data-urlencode 'status=0' \ + --data-urlencode 'csrf=xxx' \ + --data-urlencode 'csrf_token=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": {} +} +``` + +
+ +### 设置所有拦截会话为已读 + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | ------ | ------------- | +| csrf_token | str | CSRF Token(位于cookie) | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| msg | str | 错误信息 | 成功时为0 | +| message | str | 错误信息 | 成功时为0 | +| ttl | num | | 默认为1 | +| data | 有效时:obj
无效时:不存在该项 | 信息本体 | 空对象 | + +**示例:** + +```shell +curl 'https://api.vc.bilibili.com/session_svr/v1/session_svr/batch_update_dustbin_ack' \ + --data-urlencode 'csrf=xxx' \ + --data-urlencode 'csrf_token=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": {} +} +``` + +
+ +### 移除所有拦截会话 + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | ------ | ------------- | +| csrf_token | str | CSRF Token(位于cookie) | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| msg | str | 错误信息 | 成功时为0 | +| message | str | 错误信息 | 成功时为0 | +| ttl | num | | 默认为1 | +| data | 有效时:obj
无效时:不存在该项 | 信息本体 | 空对象 | + +**示例:** + +```shell +curl 'https://api.vc.bilibili.com/session_svr/v1/session_svr/batch_rm_dustbin' \ + --data-urlencode 'csrf=xxx' \ + --data-urlencode 'csrf_token=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": {} +} +``` + +
+ +## 私信消息相关 + +### 查询私信消息记录 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +仅调用该接口不会设置会话为已读,详见[设置会话为已读](#设置会话为已读) + +此接口有设计缺陷,可以获取已经撤回(`msg_status` 为 `1`)的私信内容 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----------------- | ---- | ---------------- | ------ | ------------------------------------------------------ | +| talker_id | num | 聊天对象的id | 必要 | `session_type` 为 `1` 时表示用户 mid,为 `2` 时表示粉丝团 id | +| session_type | num | 聊天对象的类型 | 必要 | 1:用户
2:粉丝团 | +| size | num | 返回消息数量 | 非必要 | 默认为 0,最大为 2000
当本参数为 `0` 或不存在时,只返回系统提示 | +| begin_seqno | num | 开始的序列号 | 非必要 | 提供本参数时返回以本序列号开始(不包括本序列号)的消息 | +| end_seqno | num | 结束的序列号 | 非必要 | 提供本参数时返回以本序列号结束(不包括本序列号)的消息 | +| sender_device_id | num | 发送者设备 | 非必要 | 默认为 `1` | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等;**若本参数值为 `web`,则返回新版表情包** | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
2:非法参数
-101:账号未登录
-400:请求错误
700013:已解散QAQ,无法执行此操作
700014:你已不在此同萌中QAQ,无法执行此操作 | +| msg | str | 错误信息 | 默认为0 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | ------------------------------ | ----------------------------------- | +| messages | 有私信时:array
无私信时:null | 私信列表 | 按发送时间顺序逆向排序 | +| has_more | num | 是否有更多私信 | | +| min_seqno | num | 所有消息中最小的序列号(最早) | 若无私信则为 `18446744073709551615` | +| max_seqno | num | 所有消息中最大的序列号(最晚) | 若无私信则为 `0` | +| e_infos | array | 聊天表情列表 | 若私信列表中无表情则无此项 | + +`data`对象中的`messages`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | --------------------------------- | +| 0 | obj | 私信1 | 详见[私信主体对象](#私信主体对象) | +| n | obj | 私信(n+1) | | +| …… | obj | …… | …… | + +`data`对象中的`e_infos`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---- | +| 0 | obj | 表情1 | | +| n | obj | 表情(n+1) | | +| …… | obj | …… | …… | + +`data`对象中的`e_infos`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ----------- | ----------------------------------- | +| text | str | 表情名称 | 包括左右两侧的中括号,如`[tv_doge]` | +| uri | str | 表情链接 | | +| size | num | 表情尺寸 | 1:小
2:大 | +| gif_url | str | 表情GIF链接 | 仅部分表情存在此项,如小电视表情 | + +**示例:** + +获取与目标用户`mid=123`的私信记录: + +```shell +curl -G 'https://api.vc.bilibili.com/svr_sync/v1/svr_sync/fetch_session_msgs' \ + --data-urlencode 'talker_id=123' \ + --data-urlencode 'session_type=1' \ + --data-urlencode 'size=20' \ + --data-urlencode 'sender_device_id=1' \ + --data-urlencode 'build=0' \ + --data-urlencode 'mobi_app=web' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": { + "messages": [ + { + "sender_uid": 2239814, + "receiver_type": 1, + "receiver_id": 123, + "msg_type": 1, + "content": "{\"content\":\"[口罩]\"}", + "msg_seqno": 309675413389322, + "timestamp": 1654154093, + "at_uids": [ + 0 + ], + "msg_key": 7104537732714964358, + "msg_status": 0, + "notify_code": "", + "new_face_version": 1, + "msg_source": 2 + }, + { + "sender_uid": 2239814, + "receiver_type": 1, + "receiver_id": 123, + "msg_type": 5, + "content": "{\"content\":\"1\"}", + "msg_seqno": 308302399586307, + "timestamp": 1654072255, + "at_uids": [ + 0 + ], + "msg_key": 7104186240789226795, + "msg_status": 0, + "notify_code": "", + "msg_source": 7 + + }, + ], + "has_more": 0, + "min_seqno": 308188515844097, + "max_seqno": 309675413389322, + "e_infos": [ + { + "text": "[口罩]", + "url": "http://i0.hdslb.com/bfs/emote/3ad2f66b151496d2a5fb0a8ea75f32265d778dd3.png", + "size": 1 + } + ] + } +} +``` + +
+ +### 获取多个视频、番剧、专栏的信息 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +可用于获取私信中分享或推送的多个视频、番剧、专栏的信息 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----------- | ---- | ---------------- | ----------- | --------------------------------------------------------------------------------------------- | +| aids | nums | 视频AV号列表 | 必要 (可选) | `aids`、`ep_ids` 与 `article_ids` 中须至少存在一个参数,每个成员间用 `,` 分隔,最多 50 个成员 | +| ep_ids | nums | 番剧epid列表 | 必要 (可选) | `aids`、`ep_ids` 与 `article_ids` 中须至少存在一个参数,每个成员间用 `,` 分隔,最多 50 个成员 | +| article_ids | nums | 专栏CV号列表 | 必要 (可选) | `aids`、`ep_ids` 与 `article_ids` 中须至少存在一个参数,每个成员间用 `,` 分隔,无成员限制 | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ----- | ------------ | --------------------------------------- | +| archive | array | 视频信息列表 | 仅在指定了 `aids` 参数时存在此项 | +| article | array | 专栏信息列表 | 仅在指定了 `article_ids` 参数时存在此项 | +| pgc | array | 番剧信息列表 | 仅在指定了 `ep_ids` 参数时存在此项 | + +`archive`、`article`、`pgc`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---- | +| 0 | obj | 信息1 | | +| n | obj | 信息(n+1) | | +| …… | obj | …… | …… | + +`archive`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------ | ------------------------------ | +| bvid | str | 视频BV号 | | +| aid | num | 视频AV号 | | +| title | str | 视频标题 | 若视频失效则为 `内容已失效` | +| pic | str | 视频封面 | 若视频失效则为空文本 | +| param | str | 提供的参数 | 即 AV 号的文本形式 | +| uri | str | 跳转url | `bilibili://video/{视频AV号}` | +| goto | str | `av` | | +| duration | num | 视频时长 | 以秒为单位,若视频失效则为 `0` | +| up_name | str | 视频UP主昵称 | | +| view | num | 视频播放量 | | +| danmaku | num | 视频弹幕数 | | +| status | num | 视频状态 | 0:正常
-1:已失效 | +| is_started | num | 1 | **作用尚不明确** | + +`article`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----- | ------------ | --------------------------- | +| id | num | 专栏CV号 | | +| title | str | 专栏标题 | 若专栏失效则为 `内容已失效` | +| summary | str | 专栏内容概要 | 若专栏失效则为空文本 | +| template_id | num | (?) | **作用尚不明确** | +| up_name | str | 专栏UP主昵称 | 若专栏失效则为空文本 | +| image_urls | array | 专栏封面列表 | 若专栏失效则为空数组 | +| view_num | num | 专栏观看数 | 若专栏失效则为 `0` | +| like_num | num | 专栏点赞数 | 若专栏失效则为 `0` | +| reply_num | num | 专栏评论数 | 若专栏失效则为 `0` | +| status | num | 专栏状态 | 0:正常
-1:已失效 | + +`image_urls`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---- | +| 0 | str | 封面1 | | +| n | str | 封面(n+1) | | +| …… | str | …… | …… | + +`pgc`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------------ | --------------------------- | +| ep_id | num | 番剧epid | | +| cover | str | 番剧封面url | | +| title | str | 番剧分享标题 | 如 `《{番剧名}》 第{n}话 {单集标题}`、`《{番剧名}》 {备注}` 等 | +| duration | num | 番剧时长 | 以秒为单位 | +| view | num | 番剧播放量 | | +| danmaku | num | 番剧弹幕数 | | +| url | str | 跳转url | `https://www.bilibili.com/bangumi/play/ep{番剧epid}` | + +**示例:** + +获取`aids=170001&ep_ids=780019&article_ids=1`的信息 + +```shell +curl -G 'https://api.vc.bilibili.com/x/im/feed/infoweb' \ + --data-urlencode 'aids=170001' \ + --data-urlencode 'ep_ids=780019' \ + --data-urlencode 'article_ids=1' \ + --data-urlencode 'build=0' \ + --data-urlencode 'mobi_app=web' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "archive": [ + { + "bvid": "BV17x411w7KC", + "aid": 170001, + "title": "【MV】保加利亚妖王AZIS视频合辑", + "pic": "http://i2.hdslb.com/bfs/archive/1ada8c32a9d168e4b2ee3e010f24789ba3353785.jpg", + "param": "170001", + "uri": "bilibili://video/170001?player_height=288&player_rotate=0&player_width=512", + "goto": "av", + "duration": 2412, + "up_name": "冰封.虾子", + "view": 44809333, + "danmaku": 913266, + "status": 0, + "is_started": 1 + } + ], + "article": [ + { + "id": 1, + "title": "未知的光", + "summary": "天空像是倾倒出的墨水,黑得静谧而深邃。黎明还远,光亮全无。夜不能寐。披衣,起床。茶香的弥漫,一盏灯的相伴。夜,你是我久别重逢的朋友,那一刹那的相见,带给了我久违的安思。如果不是梦魇的皮闹,我本不该投入", + "template_id": 4, + "up_name": "健行见远渐忘", + "image_urls": [ + "https://i0.hdslb.com/bfs/article/d2eedf1fd338bceca10099e2f7b33fa9017c859b.jpg" + ], + "view_num": 1608818, + "like_num": 32247, + "reply_num": 14143, + "status": 0 + } + ], + "pgc": [ + { + "ep_id": 780019, + "cover": "http://i0.hdslb.com/bfs/archive/ee28c04d15fb133a9c70c502fabfbdc7e5051ffe.png", + "title": "《铃芽之旅》 新海诚集大成之作", + "duration": 7283, + "view": 22088209, + "danmaku": 93069, + "url": "https://www.bilibili.com/bangumi/play/ep780019" + } + ] + } +} +``` + +
+ +### 发送私信(web端) + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +鉴权方式:[Wbi 签名](../misc/sign/wbi.md) + +**仅支持发送 `msg[msg_type]` 为 `1`、`2` 或 `5` 的私信** + +调用该接口会将该会话设置为已读 + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------- | ---- | --------------- | ------ | ------------------------------------ | +| w_sender_uid | num | 发送者mid | 非必要 | 同正文参数 `msg[sender_uid]` | +| w_receiver_id | num | 接收者id | 非必要 | 同正文参数 `msg[receiver_id]` | +| w_dev_id | str | 设备id | 非必要 | 同正文参数 `msg[dev_id]` | +| w_rid | str | Wbi 签名 | 非必要 | 参见 [Wbi 签名](../misc/sign/wbi.md) | +| wts | str | UNIX 秒级时间戳 | 非必要 | 参见 [Wbi 签名](../misc/sign/wbi.md) | + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----------------------- | ---- | ------------------------ | ------ | ---------------------------------------------------- | +| msg\[sender_uid\] | num | 发送者mid | 必要 | 必须为自己的 mid | +| msg\[receiver_id\] | num | 接收者id | 必要 | `msg[receiver_type]` 为 `1` 时表示用户 mid,为 `2` 时表示粉丝团 id | +| msg\[receiver_type\] | num | 接收者类型 | 必要 | 1:用户
2:粉丝团 | +| msg\[msg_type\] | num | 消息类型 | 必要 | 详见[私信消息类型、内容说明](private_msg_content.md)
**此接口仅支持传入 `1`、`2` 或 `5`** | +| msg\[msg_status\] | num | 消息状态 | 非必要 | 恒为 `0` | +| msg\[dev_id\] | str | 设备id | 必要 | 实质上即 UUID(版本 4),**生成方式见下** | +| msg\[timestamp\] | num | 当前时间戳(秒) | 必要 | | +| msg\[new_face_version\] | num | 表情包版本 | 非必要 | 提供 `0` 或者未提供本参数表示旧版表情包,此时 B 站会自动转换成新版表情包,例如 `[doge]` -> `[tv_doge]`;`1` 为新版 | +| msg\[content\] | str | 消息内容 | 必要 | 详见[私信消息类型、内容说明](private_msg_content.md),接受最多2000字节的内容 | +| csrf_token | str | CSRF Token(位于cookie) | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +--- + +**dev_id 的生成:** + +dev_id 实质上就是 UUID(版本 4) + +
+查看生成 UUID 的代码 + +#### Python + +```python +import uuid + +dev_id = str(uuid.uuid4()) +``` + +#### JavaScript + +以下代码适用于较新版的 JS 引擎(Chrome≥92,Firefox≥95,Safari≥15.4,Node.js≥19.0.0): + +```js +const dev_id = crypto.randomUUID(); +``` + +以下为通用代码(来自 [andywang425/BLTH](https://github.com/andywang425/BLTH/blob/45fe93e31754ca8bf07059d46266398e787dbf45/B%E7%AB%99%E7%9B%B4%E6%92%AD%E9%97%B4%E6%8C%82%E6%9C%BA%E5%8A%A9%E6%89%8B.js#L6618)): + +```js +const dev_id = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (function (name) { + const randomInt = 16 * Math.random() | 0; + return ("x" === name ? randomInt : 3 & randomInt | 8).toString(16).toUpperCase(); +})); +``` + +#### Java + +```java +import java.util.UUID; + +public class Main { + private String getDevId() { + UUID uuid = UUID.randomUUID(); + return uuid.toString(); + } +} +``` + +
+ +--- + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-3:系统错误
-101:账号未登录
-400:请求错误
10005:msgkey不存在
21007:消息过长,无法发送
21015:为了维护社区的良好秩序,只有绑定手机号的账号才能发送消息
21020:你发送消息频率过快,请稍后再发~
21026:不能给自己发送消息哦~
21028:由于系统升级,暂无法发送,敬请谅解
21035:该类消息暂时无法发送
21037:图片格式不合法,不要调戏接口啦
21041:消息已超期,不能撤回了哦
21042:消息已经撤回了哦
21046:你发消息的频率太高了,请在24小时后再发吧~
21047:对方主动回复或关注你前,最多发送1条消息~
25003:因对方隐私设置,暂无法给他发送聊天消息
25005:你已拉黑了对方,请先将对方移出黑名单后才能聊天
700013:已解散QAQ,无法执行此操作
700014:你已不在此同萌中QAQ,无法执行此操作 | +| message | str | 错误信息 | 成功时为0 | +| ttl | num | | 默认为1 | +| data | 有效时:obj
无效时:null | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ----- | ---------- | --------------------------------------------------------------------- | +| msg_key | num | 消息唯一id | | +| e_infos | array | 表情列表 | 仅当请求参数 `msg[msg_type]` 为 `1`,且私信内容中有表情时有此项 | +| msg_content | str | 发送的私信内容 | 一般同请求参数 `msg[content]` 的值,仅当请求参数 `msg[msg_type]` 为 `1` 时有此项 | +| key_hit_infos | obj | 触发的提示 | 仅当请求参数 `msg[msg_type]` 为 `1` 且 `msg[receiver_type]` 为 `1` 时有此项 | + +`e_infos`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---- | +| 0 | obj | 表情1 | | +| n | obj | 表情(n+1) | | +| …… | obj | …… | …… | + +`e_infos`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ----------- | ----------------------------------- | +| text | str | 表情名称 | 包括左右两侧的中括号,如 `[tv_doge]` | +| uri | str | 表情链接 | | +| size | num | 表情尺寸 | 1:小
2:大 | +| gif_url | str | 表情GIF链接 | 仅部分表情存在此项,如小电视表情 | + +`key_hit_infos`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | ------------ | -------------------------------------- | +| toast | str | 提示信息文字 | 当触发了提示时有此项 | +| rule_id | num | 触发的规则id | 当触发了提示时有此项,详细信息有待补充 | +| high_text | array | 高亮的文本 | 当触发了提示时有此项 | + +`high_text`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---------------- | +| 0 | obj | 高亮文本1 | 详细信息有待补充 | +| n | obj | 高亮文本(n+1) | | +| …… | obj | …… | …… | + +**示例:** + +给目标用户`mid=1`发一条文字私信: + +> up主你好,
催更\[doge\] + +```shell +curl 'https://api.vc.bilibili.com/web_im/v1/web_im/send_msg' \ + --data-urlencode 'msg[sender_uid]=293793435' \ + --data-urlencode 'msg[receiver_id]=1' \ + --data-urlencode 'msg[receiver_type]=1' \ + --data-urlencode 'msg[msg_type]=1' \ + --data-urlencode 'msg[msg_status]=0' \ + --data-urlencode 'msg[dev_id]=372778FD-E359-461D-86A3-EA2BCC6FF52A' \ + --data-urlencode 'msg[timestamp]=1626181379' \ + --data-urlencode 'msg[new_face_version]=1' \ + --data-urlencode 'msg[content]={"content":"up主你好,\n催更[doge]"}' \ + --data-urlencode 'csrf=xxx' \ + --data-urlencode 'csrf_token=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "msg_key": 6984393491767669026, + "e_infos": [ + { + "text": "[doge]", + "url": "https://i0.hdslb.com/bfs/emote/3087d273a78ccaff4bb1e9972e2ba2a7583c9f11.png", + "size": 1 + } + ], + "msg_content": "{\"content\":\"up主你好,\\n催更[doge]\"}", + "key_hit_infos": {} + } +} +``` + +
+ +给目标用户`mid=1`发一条图片私信: + +> + +```shell +curl 'https://api.vc.bilibili.com/web_im/v1/web_im/send_msg' \ + --data-urlencode 'msg[sender_uid]=293793435' \ + --data-urlencode 'msg[receiver_id]=1' \ + --data-urlencode 'msg[receiver_type]=1' \ + --data-urlencode 'msg[msg_type]=2' \ + --data-urlencode 'msg[msg_status]=0' \ + --data-urlencode 'msg[dev_id]=372778FD-E359-461D-86A3-EA2BCC6FF52A' \ + --data-urlencode 'msg[timestamp]=1626181379' \ + --data-urlencode 'msg[content]={"url":"https://i1.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg","height":300,"width":300,"imageType":"jpeg","original":1,"size":54.144}' \ + --data-urlencode 'csrf=xxx' \ + --data-urlencode 'csrf_token=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "data": { + "msg_key": 6852570013146024354 + } +} +``` + +
+ +给目标用户`mid=1`发送会触发提示的私信: + +> 支付宝 + +```shell +curl 'https://api.vc.bilibili.com/web_im/v1/web_im/send_msg' \ + --data-urlencode 'msg[sender_uid]=293793435' \ + --data-urlencode 'msg[receiver_id]=1' \ + --data-urlencode 'msg[receiver_type]=1' \ + --data-urlencode 'msg[msg_type]=1' \ + --data-urlencode 'msg[msg_status]=0' \ + --data-urlencode 'msg[dev_id]=372778FD-E359-461D-86A3-EA2BCC6FF52A' \ + --data-urlencode 'msg[timestamp]=1626181379' \ + --data-urlencode 'msg[content]={"content":"支付宝"}' \ + --data-urlencode 'csrf=xxx' \ + --data-urlencode 'csrf_token=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "msg_key": 6984393491767669026, + "msg_content": "{\"content\":\"支付宝\"}", + "key_hit_infos": { + "toast": "【温馨提示】为保障消费者权益,根据平台规则,如创作者在与消费者沟通中进行发布要求非法转账、欺诈转账等违规行为,平台有权对此进行处罚,感谢您的理解。", + "rule_id": 2, + "high_text": [{}] + } + } +} +``` + +
diff --git a/bb-api-collect/docs/message/private_msg_content.md b/bb-api-collect/docs/message/private_msg_content.md new file mode 100644 index 0000000000..21a5debfd9 --- /dev/null +++ b/bb-api-collect/docs/message/private_msg_content.md @@ -0,0 +1,627 @@ +# 私信消息类型、内容说明 + +## 通用消息类型 + +以下消息类型适用于大多数会话 + +### 文字消息(`msg_type=1`) + +在发送私信时,请确保下面的对象合法且 `content` 项的值为非空文本,否则会提示 `请求错误` + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---- | +| content | str | 私信内容 | | + +**示例:** + +内容为 `Hello` 的文字消息 + +```json +{ + "content": "Hello" +} +``` + +### 图片消息(`msg_type=2`) + +在发送私信时,请确保下面的对象合法且 `url` 项的值为 B 站的图床 url,否则会报 21037 `图片格式不合法,不要调戏接口啦` 错误 + +建议设置 `height` 与 `width` 属性为图片的尺寸,否则可能会导致消息显示异常 + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ---------- | ------------------------- | +| url | str | 图片url | 一般为 B 站图床 url | +| height | num | 图片高度 | 单位:像素(非必要) | +| width | num | 图片宽度 | 单位:像素(非必要) | +| imageType | str | 图片格式 | (非必要) | +| original | num | 是否为原图 | 当本参数值为 `1` 时,APP上会出现“下载原图”按钮(非必要) | +| size | num | 文件大小 | 单位:千字节(非必要) | + +**示例:** + +图片 `https://message.biliimg.com/bfs/im_new/c161fdf51d901c1607a15e30f10116dd425503913.jpg` + +```json +{ + "url": "https://message.biliimg.com/bfs/im_new/c161fdf51d901c1607a15e30f10116dd425503913.jpg", + "height": 300, + "width": 300, + "imageType": "jpeg", + "original": 1, + "size": 55.443 +} +``` + +### 撤回消息(`msg_type=5`) + +内容为目标私信的 `msg_key` + +请确保目标私信存在、在撤回有效期(120 秒)里,且与发送的私信在同一会话内,只能撤回自己发送的私信 + +成功发送此私信后,目标私信的 `msg_status` 会变成 `1`(在前端会显示目标私信被撤回) + +**示例:** + +假如存在 `msg_key` 为 `7345551441311046575` 的私信 A,用户发送了 `msg_type` 为 `5` 且 `content` 为以下内容的私信 B: + +```json +7345551441311046575 +``` + +若发送成功,则私信 A 会被撤回(在前端显示该消息被撤回),并且其 `msg_status` 也会变成 `1` + +### 自定义表情消息(`msg_type=6`) + +结构同[图片消息](#图片消息msg_type2) + +### 分享消息(`msg_type=7`) + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ---------------- | -------------------------------------------------------------- | +| author | str | 分享内容作者 | 此项不实时更新,在发送私信时设置(非必要) | +| headline | str | 分享内容主标题 | 比 `title` 更突出;此项不实时更新,在发送私信时设置(非必要) | +| id | num | 分享内容id | | +| source | num | 分享内容类型 | ~~1:小视频~~(已弃用)
2:相簿
3:纯文字
4:直播(此类型不常用,见[分享其他内容消息](#分享其他内容消息msg_type14))
5:视频
6:专栏
7:番剧(`id` 为 season_id)
8:音乐
9:国产动画(`id` 为 AV 号)
10:图片
11:动态
16:番剧(`id` 为 epid)
17:番剧 | +| source_desc | str | 分享内容类型说明 | 仅当 `source` 值为 `16` 时有此项 | +| thumb | str | 分享内容封面 | 此项不实时更新,在发送私信时设置 | +| title | str | 分享内容标题 | 此项不实时更新,在发送私信时设置 | +| url | str | 分享内容url | (非必要) | +| bvid | str | 视频BV号 | 当 `source` 值为 `5` 时有效(非必要) | + +**示例:** + +分享 UP 主 “社会易姐QwQ” 的视频 av246551172/BV16v411e7CW + +```json +{ + "author": "社会易姐QwQ", + "headline": "", + "id": 246551172, + "source": 5, + "thumb": "http://i2.hdslb.com/bfs/archive/14ba78056f946ece8c954a10677ef6b073edb178.jpg", + "title": "合 成 大 東 瓜", + "bvid": "BV16v411e7CW" +} +``` + +### ~~系统撤回消息(`msg_type=8`)~~ + +~~此消息类型由于存在安全问题,已被弃用~~ + +
+查看此消息类型说明 + +此类型消息在接收时的 `msg_type` 的值为 `5`(而不是 `8`)且 `sys_cancel` 的值为 `true`,**仅在用户会话中有效;目前已不可直接发送** + +内容为目标私信的 `msg_key` + +请确保目标私信存在,且与发送的私信在同一会话内,只能撤回自己发送的私信;**不限制目标私信的发送时间** + +成功发送此私信后,目标私信的 `msg_status` 会变成 `2`(在前端会直接隐藏目标私信,且后端也不会返回目标私信的任何信息) + +
+ +### 小程序消息(`msg_type=9`) + +由于 B 站并没有对外公开小程序,此消息类型不常用 + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ------------ | ------------------------- | +| avatar | str | 小程序图标 | | +| cover | str | 小程序封面 | | +| id | str | 小程序id | | +| jump_uri | str | 小程序链接 | | +| label_cover | str | 标签图标 | | +| label_name | str | 标签文字内容 | 一般为 `小程序` | +| name | str | 小程序名称 | | +| title | str | 小程序标题 | | + +**示例:** + +分享 “主站测试专用小程序” + +```json +{ + "avatar": "http://i0.hdslb.com/bfs/mall/mall/7b/dd/7bdd072290de017593791b52e937ca29.png", + "cover": "http://i0.hdslb.com/bfs/mall/mall/7b/dd/7bdd072290de017593791b52e937ca29.png", + "id": "bili91e3e7e93af281f9", + "jump_uri": "https://mall.bilibili.com/miniapp/bili91e3e7e93af281f9/pages/main?___timestamp=1689526821040&_biliFrom=about_bili_message&share_medium=android&share_source=bili_message&bbid=XU8CE838022AF6625C64B2153A3EF1E571AFF&ts=1689526821048", + "label_cover": "https://i0.hdslb.com/bfs/mall/mall/ae/0e/ae0ee4a857df5e307e1d04b5d420cb5b.png", + "label_name": "小程序", + "name": "主站测试专用小程序", + "title": "主站测试专用小程序" +} +``` + +### 通知消息(`msg_type=10`) + +此类型消息仅可接收,**不可直接发送** + +**按钮显示逻辑说明:** + +- **按钮的url**:首先尝试读取 `jump_uri_config`、`jump_uri_2_config`、`jump_uri_3_config` 对象中表示当前设备类型的 url(如 `web_uri`、`android_uri` 等);若为空值,则尝试读取 `jump_uri_config`、`jump_uri_2_config`、`jump_uri_3_config` 对象中 `all_uri` 的值;若仍为空值,则读取根对象中 `jump_uri`、`jump_uri_2`、`jump_uri_3` 的值;若仍为空值,则不显示该按钮(无论提示文字是否为空) +- **按钮提示文字**:若按钮是可见的,则先尝试读取 `jump_uri_config`、`jump_uri_2_config`、`jump_uri_3_config` 对象中 `text` 的值;若为空值,则读取根对象中 `jump_text`、`jump_text_2`、`jump_text_3` 的值;若仍为空值,则提示文字为 `查看详情` + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ----- | ------------- | ------------------------- | +| title | str | 通知标题 | | +| text | str | 通知内容 | | +| jump_text | str | 按钮1提示文字 | 若按钮1不存在则为空;若按钮1存在,此项也可能为空,此时前端显示文字为 `查看详情` | +| jump_uri | str | 按钮1跳转链接 | 若按钮1不存在则为空 | +| modules | 有效时:array
无效时:null | 详细信息 | | +| jump_text_2 | str | 按钮2提示文字 | 若按钮2不存在则为空;若按钮2存在,此项也可能为空,此时前端显示文字为 `查看详情` | +| jump_uri_2 | str | 按钮2跳转链接 | 若按钮2不存在则为空 | +| jump_text_3 | str | 按钮3提示文字 | 若按钮3不存在则为空;若按钮3存在,此项也可能为空,此时前端显示文字为 `查看详情` | +| jump_uri_3 | str | 按钮3跳转链接 | 若按钮3不存在则为空 | +| notifier | 有效时:obj
无效时:null | 发送者信息 | | +| jump_uri_config | obj | 按钮1配置 | | +| jump_uri_2_config | obj | 按钮2配置 | | +| jump_uri_3_config | obj | 按钮3配置 | | +| biz_content | 有效时:obj
无效时:null | 扩展信息 | | + +`modules`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---- | +| 0 | obj | 详细信息1 | | +| n | obj | 详细信息(n+1) | | +| …… | obj | …… | …… | + +`modules`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ---- | ---- | +| title | str | 标题 | | +| detail | str | 内容 | | + +`notifier`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ---------- | ------ | +| avatar_url | str | 发送者头像 | | +| nickname | str | 发送者名称 | | +| jump_url | str | 发送者链接 | 可为空 | + +`jump_uri_config`、`jump_uri_2_config`、`jump_uri_3_config`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ----------------------- | -------------------- | +| all_uri | str | 所有设备的跳转链接 | 若按钮不存在则无此项 | +| android_uri | str | Android客户端的跳转链接 | 若按钮不存在则无此项 | +| iphone_uri | str | iPhone客户端的跳转链接 | 若按钮不存在则无此项 | +| ipad_uri | str | iPad客户端的跳转链接 | 若按钮不存在则无此项 | +| web_uri | str | 网页上的跳转链接 | 若按钮不存在则无此项 | +| text | str | 按钮提示文字 | 若按钮不存在则为空 | + +`biz_content`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ----------- | ---------------- | +| cover | str | 封面url | | +| backup_cover | str | 备用封面url | | +| refresh_type | num | (?) | **作用尚不明确** | +| biz_type | num | (?) | **作用尚不明确** | +| biz_id1 | str | (?) | **作用尚不明确** | +| biz_id2 | str | (?) | **作用尚不明确** | +| biz_status | num | (?) | **作用尚不明确** | + +**示例:** + +直播开始提醒 + +```json +{ + "title": "直播开始提醒", + "text": "你预约的直播已开始,快来围观吧~", + "jump_text": "进入直播间", + "jump_uri": "https://live.bilibili.com/22747055?broadcast_type=0&is_room_feed=1&live_from=27040", + "modules": [{ + "title": "预约主题", + "detail": "2024哔哩哔哩拜年纪" + }, { + "title": "开播时间", + "detail": "2024-02-09 19:32" + }, { + "title": "UP主", + "detail": "哔哩哔哩拜年纪" + }], + "jump_text_2": "", + "jump_uri_2": "", + "jump_text_3": "", + "jump_uri_3": "", + "notifier": null, + "jump_uri_config": { + "all_uri": "https://live.bilibili.com/22747055?broadcast_type=0&is_room_feed=1&live_from=27040", + "text": "进入直播间" + }, + "jump_uri_2_config": { + "text": "" + }, + "jump_uri_3_config": { + "text": "" + }, + "biz_content": { + "cover": "", + "backup_cover": "http://i0.hdslb.com/bfs/live/new_room_cover/bdae2665883ec8aa4e79aca16f3c5ee2df1da64f.jpg", + "refresh_type": 1, + "biz_type": 2, + "biz_id1": "1868902080", + "biz_id2": "473923647994271663", + "biz_status": 0 + } +} +``` + +### 视频推送消息(`msg_type=11`) + +此类型消息仅可接收,**不可直接发送**;有小概率会出现即使视频存在,也只会出现 `rid`、`type`(值为 `11` 或 `8`,注意其名称后面没有下划线)和 `attach_msg` 三项的现象 + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------ | ------------------------------------------------------ | +| title | str | 视频标题 | 接收私信时实时更新此项,若视频失效则为空文本 | +| times | num | 视频时长 | 以秒为单位,接收私信时实时更新此项,若视频失效则为 `0` | +| cover | str | 视频封面 | 接收私信时实时更新此项,若视频失效则为空文本 | +| rid | num | 视频AV号 | | +| type_ | num | (?) | **作用尚不明确** | +| desc | str | 视频简介 | 接收私信时实时更新此项,若视频失效则为空文本 | +| bvid | str | 视频BV号 | | +| view | num | 视频播放量 | 接收私信时实时更新此项,若视频失效则为 `0` | +| danmaku | num | 视频弹幕数 | 接收私信时实时更新此项,若视频失效则为 `0` | +| pub_date | num | 视频发布时间 | 秒级时间戳,若视频失效则为 `0` | +| attach_msg | 有效时:obj
无效时:null | UP主赠言 | | + +`attach_msg`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------------------------------------------- | +| id | num | 赠言id | | +| content | str | 赠言内容 | 会自动加上 `UP主赠言:` 前缀,可能包含私信表情 | + +**示例:** + +推送视频 av740817783/BV1Dk4y1E7MZ + +```json +{ + "title": "【2023嵌入式大赛】浅浅测试一下龙芯开发板", + "times": 308, + "cover": "http://i2.hdslb.com/bfs/archive/880c937de9af758451aa94ee29771e0264c1903a.jpg", + "rid": 740817783, + "type_": 8, + "desc": "最近把龙芯开发板部分(任务一)程序完成了,时间非常紧迫,就不知道为啥突然给省赛加个(本来国赛的题\n从硬件焊接开始,到软件整完不过5天啊喂,肝疼,过几天比赛完发硬件制作过程\n硬件使用龙芯一号(LS1B010)SOC,软件使用 C 语言+FreeRTOS+VSCode 开发", + "bvid": "BV1Dk4y1E7MZ", + "view": 13492, + "danmaku": 5, + "pub_date": 1683381582, + "attach_msg": null +} +``` + +### 专栏推送消息(`msg_type=12`) + +此类型消息仅可接收,**不可直接发送**;有小概率会出现即使专栏存在,也只会出现 `rid`、`type`(值为 `12`)和 `attach_msg` 三项的现象 + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ------------ | ------------------------------------------------------ | +| rid | num | 专栏CV号 | | +| title | str | 专栏标题 | 接收私信时实时更新此项,若专栏失效则为 `内容已失效` | +| summary | str | 专栏内容概要 | 接收私信时实时更新此项,若专栏失效则为空文本 | +| author | str | 专栏UP主昵称 | 接收私信时实时更新此项,若专栏失效则为空文本 | +| view | num | 专栏观看数 | 接收私信时实时更新此项,若专栏失效则为 `0` | +| like | num | 专栏点赞数 | 接收私信时实时更新此项,若专栏失效则为 `0` | +| reply | num | 专栏评论数 | 接收私信时实时更新此项,若专栏失效则为 `0` | +| template_id | num | (?) | **作用尚不明确** | +| image_urls | 有效时:array
无效时:null | 专栏封面列表 | 接收私信时实时更新此项,若专栏失效则为 `null` | +| attach_msg | 有效时:obj
无效时:null | UP主赠言 | | +| pub_date | num | 专栏发布时间 | 秒级时间戳,若专栏失效则为 `0` | + +`image_urls`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---- | +| 0 | str | 封面1 | | +| n | str | 封面(n+1) | | +| …… | str | …… | …… | + +`attach_msg`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------------------------------------------- | +| id | num | 赠言id | | +| content | str | 赠言内容 | 会自动加上 `UP主赠言:` 前缀,可能包含私信表情 | + +**示例:** + +推送专栏 cv18275013 + +```json +{ + "rid": 18275013, + "title": "【单片机】遛弯捕捉到野生U盾,点亮它!", + "summary": "前一阵在学校那会,偶然的机会晚上饭后出去遛弯,在路边看到个被抛弃的 U盾,这么一想应该是附近拆迁搬东西时丢出去的,随即捕捉它。作为一个啥都折腾的捡垃圾技术宅肯定要去研究一波(笑是个建行的 U盾,按键部分还有点老灰,屏幕的尺寸盲猜 128x64,不可能再大了背面除了序列号没有别的东西,顶部有个盖子,像极了上古时期的 U盘插上充电宝可以正常点亮,至少屏没坏拆解&分析电路直接开拆,用刀片沿着四周缝隙插入并挑开卡扣内部结构挺简单,只有两颗较大的芯片,屏幕的 FPC 排线直接焊接在 PCB 上中间的这颗是", + "author": "社会易姐QwQ", + "view": 872, + "like": 38, + "reply": 7, + "template_id": 4, + "image_urls": [ + "https://i0.hdslb.com/bfs/article/c7c60e018c43c5c3a6e1520239021ea2753b2880.jpg" + ], + "attach_msg": null, + "pub_date": 1661358081 +} +``` + +### 图片卡片消息(`msg_type=13`) + +此类型消息仅可接收,**不可直接发送** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------------------- | -------------------- | +| pic_url | str | 图片url | | +| jump_url | str | 点击图片跳转到的url | | +| title | str | 文字说明 | 显示在聊天列表的文字 | + +**示例:** + +```json +{ + "pic_url": "http://i0.hdslb.com/bfs/location/9e57aff7245c226c05ba46ddd1e82667f74d5a06.png", + "jump_url": "https://www.bilibili.com/h5/mall/suit/detail?navhide=1&id=66359&from=Banner", + "title": "原神,启动!" +} +``` + +### 分享其他内容消息(`msg_type=14`) + +常见于分享直播 + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ---------------- | -------------------------------- | +| author | str | 分享内容作者 | 此项不实时更新,在发送私信时设置 | +| cover | str | 分享内容封面 | 此项不实时更新,在发送私信时设置 | +| desc | str | 分享内容简介 | 此项不实时更新,在发送私信时设置 | +| source | str | 分享内容类型说明 | 常见的值为 `直播` | +| title | str | 分享内容标题 | 此项不实时更新,在发送私信时设置 | +| url | str | 分享内容url | | + +**示例:** + +分享直播 ID 21738461 + +```json +{ + "author": "哔哩哔哩晚会", + "cover": "https://i1.hdslb.com/bfs/face/1b593d28fcd0cf63837c3ea80ac96d01bb85ec3b.jpg", + "desc": "主播:哔哩哔哩晚会 https://live.bilibili.com/21738461", + "source": "直播", + "title": "2023最美的夜 bilibili晚会", + "url": "https://live.bilibili.com/21738461?broadcast_type=0&is_room_feed=1&live_from=41000&share_medium=android&share_source=bili_message&bbid=XU8CE838022AF6625C64B2153A3EF1E571AFF&ts=1704038936971" +} +``` + +### 被关注时的自动推送消息(`msg_type=16`) + +一般仅在开启了 B 站的 “被关注回复” 功能与勾选 “被关注后,向关注我的人推送我的往期作品” 选项(仅部分用户会显示此选项)时才会发送此类型消息,紧接在自动发送的文字消息后面 + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ----- | ---------------- | -------------------------------------------- | +| main_title | str | 主标题 | 一般为 `更多宝藏内容` | +| reply_content | str | 自动回复文字内容 | 仅在聊天列表中的消息概要中显示此内容,在私信内容中不显示 | +| sub_cards | array | 推送的稿件列表 | 一般为3个 | + +`sub_cards`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---- | +| 0 | obj | 稿件1 | | +| n | obj | 稿件(n+1) | | +| …… | obj | …… | …… | + +`sub_cards`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | -------------------------------- | +| card_id | num | 稿件AV号 | | +| card_type | num | 稿件类型 | 一般为 `1` | +| jump_url | str | 稿件链接 | | +| cover_url | str | 稿件封面url | 此项不实时更新,在发送私信时设置 | +| field1 | str | 稿件标题 | 此项不实时更新,在发送私信时设置 | +| field2 | str | 稿件发布时间 | 格式:`YYYY-MM-DD` | +| field3 | str | 字段3 | 此项不实时更新,在发送私信时设置 | +| icon3 | num | 图标3类型 | 1:播放量
3:弹幕数
5:收藏量 | +| field4 | str | 字段4 | 此项不实时更新,在发送私信时设置 | +| icon4 | num | 图标4类型 | 1:播放量
3:弹幕数
5:收藏量 | + +**示例:** + +```json +{ + "main_title": "更多宝藏内容", + "reply_content": "感谢大佬关注哦~[doge][脱单doge][doge]\n这里是科技区底边小UP,日常瞎折腾,软硬件电路程序网络服务器都折腾,视频月更风格硬核略小众,咕咕咕.....\n老大二了,就不中二了\n有什么好的建议欢迎私信", + "sub_cards": [{ + "card_id": 379743801, + "card_type": 1, + "jump_url": "https://b23.tv/BV1hZ4y197Cz", + "cover_url": "http://i2.hdslb.com/bfs/archive/bfb87f033272926efe6ff4caee8e6c49c07ff6fe.jpg", + "field1": "【宿舍评测】性能与便携两全 华为matebook E 2022深度体验及伪开箱", + "field2": "2021-12-10", + "field3": "20万", + "icon3": 1, + "field4": "479", + "icon4": 3 + }, { + "card_id": 768716232, + "card_type": 1, + "jump_url": "https://b23.tv/BV13r4y187R8", + "cover_url": "http://i1.hdslb.com/bfs/archive/bb1d41ef0c17c2df25c8b6ef98f01466bdee0c1f.jpg", + "field1": "【BadApple】使用古董示波器Aron BS-601播放BadApple!!!", + "field2": "2022-05-03", + "field3": "15万", + "icon3": 1, + "field4": "297", + "icon4": 3 + }, { + "card_id": 524989935, + "card_type": 1, + "jump_url": "https://b23.tv/BV17M411E7Kq", + "cover_url": "http://i1.hdslb.com/bfs/archive/17335854dfad9d7990943d8cc6dc07c85912b103.jpg", + "field1": "【拆解】华为 Matebook E 更换固态硬盘:从未见过如此好拆的二合一", + "field2": "2023-02-24", + "field3": "5万", + "icon3": 1, + "field4": "102", + "icon4": 3 + }] +} +``` + +### 系统提示消息(`msg_type=18`) + +此类型消息仅可接收,**不可直接发送**;由系统自动发送,但仅自己可见 + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | -------------------------- | +| content | str | 提示列表 | **经过序列化后**的JSON数组 | + +`content`文本经JSON解析后的数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---- | +| 0 | obj | 提示1 | | +| n | obj | 提示(n+1) | | +| …… | obj | …… | …… | + +`content`文本经JSON解析后的数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------------------ | ----------- | +| text | str | 提示文字 | | +| color_day | str | 浅色模式下的提示文字颜色 | HEX颜色代码 | +| color_nig | str | 深色模式下的提示文字颜色 | HEX颜色代码 | +| jump_url | str | 点击提示跳转到的url | (非必要) | + +**示例:** + +若自己与对方从未聊过天,且对方未关注自己,则会有系统提示 + +```json +{ + "content": "[{\"text\":\"对方主动回复或关注你前,最多发送1条消息\",\"color_day\":\"#9499A0\",\"color_nig\":\"#9499A0\"}]" +} +``` + +### AI 消息(`msg_type=19`) + +此消息类型尚未得到广泛使用 + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------- | ---- | -------------------- | ---------------- | +| content | obj | 富文本内容 | | +| show_like | bool | 是否显示点赞按钮 | | +| show_change | bool | 是否显示修改内容按钮 | | +| gpt_session_id | num | GPT 会话 id | | +| gpt_bind_query | str | (?) | **作用尚不明确** | +| session_closed_line | str | (?) | **作用尚不明确** | +| voice_url | str | 语音 url(?) | | +| sub_type | num | 子类型(?) | | +| voice_time | num | 语音时长(?) | | + +`content`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | -------- | ---------------- | +| paragraphs | array | 段落列表 | 详细信息有待补充 | + +**示例:** + +由于 B 站尚未公开此消息类型,暂无示例 + +## 粉丝团消息类型 + +以下消息类型仅常见于粉丝团中的系统消息(`receiver_type` 为 `2` 且 `sender_uid` 为 `0`) + +### 成员入群消息(`msg_type=301`) + +### 成员退群消息(`msg_type=302`) + +### 粉丝团冻结消息(`msg_type=303`) + +### 粉丝团解散消息(`msg_type=304`) + +### 粉丝团开通消息(`msg_type=305`) + +### 成员入群消息(`msg_type=306`) + +以上 6 种类型的消息均为以下数据类型结构 + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------- | ---------- | +| group_id | num | 粉丝团id | (非必要) | +| content | str | 提示文字 | | + +**示例:** + +`社会易姐QwQ的应援团` 开通的消息(`msg_type=305`) + +```json +{ + "group_id": 221082140, + "content": "社会易姐QwQ的应援团开通啦 (>▽<)" +} +``` + +成员 `wuziqian211` 进入 `社会易姐QwQ的应援团` 的消息(`msg_type=306`) + +```json +{ + "group_id": 221082140, + "content": "欢迎wuziqian211入群" +} +``` diff --git a/bb-api-collect/docs/message/settings.md b/bb-api-collect/docs/message/settings.md new file mode 100644 index 0000000000..5bedfb3a9f --- /dev/null +++ b/bb-api-collect/docs/message/settings.md @@ -0,0 +1,830 @@ +# 消息设置 + +## 获取用户偏好设置 + +> + +*请求方式:GET 或 POST* + +认证方式:Cookie(SESSDATA) + +**url参数(GET)或 正文参数(application/x-www-form-urlencoded,POST):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------------- | ---- | -------------------------------- | ------------ | ------------------------- | +| msg_notify | num | 是否显示 “消息提醒” 设置 | 非必要 | 若此项为任意整数,则返回数据中有 `msg_notify` 项 | +| show_unfollowed_msg | num | 是否显示 “收起未关注人消息” 设置 | 非必要 | 若此项为任意整数,则返回数据中有 `show_unfollowed_msg` 项 | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | +| csrf_token | str | CSRF Token(位于cookie) | POST方式必要 | | +| csrf | str | CSRF Token(位于cookie) | POST方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| msg | str | 错误信息 | 默认为0 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------------ | ---- | -------------------- | --------------------------------------------------------------------------- | +| show_unfollowed_msg | num | 收起未关注人消息 | 请求参数 `show_unfollowed_msg` 为整数时显示此项
0:不收起
1:收起 | +| msg_notify | num | 消息提醒 | 请求参数 `msg_notify` 为整数时显示此项
1:接收
3:不接收 | +| set_like | num | 收到的赞提醒(旧) | 0:接收
5:不接收 | +| set_comment | num | 回复我的提醒(旧) | 0:所有人
1:关注的人
2:不接受任何消息提醒 | +| set_at | num | @ 我的提醒 (旧) | 0:所有人
1:关注的人
2:不接受任何消息提醒 | +| is_group_fold | num | 收起应援团消息 | 0:不收起
1:收起 | +| should_receive_group | num | 接收应援团消息 | 0:不接收
1:接收 | +| receive_unfollow_msg | num | 接收未关注人消息 | 前端隐藏此开关
0:不接收
1:接收 | +| followed_reply | num | 被关注回复 | 0:关闭
1:开启 | +| keys_reply | num | 关键词回复 | 0:关闭
1:开启 | +| recv_reply | num | 收到消息回复 | 0:关闭
1:开启 | +| voyage_reply | num | 大航海上船回复 | 0:关闭
1:开启 | +| recommend_followed_reply | num | 被关注时自动推送作品 | 0:关闭
1:开启 | +| ai_intercept | num | 私信智能拦截 | 0:关闭
1:开启 | +| anti_harassment | null | 防骚扰和互动人群设置 | 此接口恒返回 `null` | +| set_recv_reply | num | 回复与@提醒(新) | 0:所有人
1:关注的人
2:不接受任何消息提醒 | +| set_recv_like | num | 收到喜欢提醒(新) | 0:接收
2:不接收 | +| set_new_follow | num | 新增粉丝提醒(新) | 0:接收
2:不接收 | + +**示例:** + +```shell +curl -G 'https://api.vc.bilibili.com/link_setting/v1/link_setting/get' \ + --data-urlencode 'msg_notify=1' \ + --data-urlencode 'show_unfollowed_msg=1' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": { + "show_unfollowed_msg": 0, + "msg_notify": 1, + "set_like": 0, + "set_comment": 0, + "set_at": 0, + "is_group_fold": 0, + "should_receive_group": 1, + "receive_unfollow_msg": 1, + "followed_reply": 1, + "keys_reply": 0, + "recv_reply": 1, + "voyage_reply": 0, + "recommend_followed_reply": 1, + "ai_intercept": 1, + "anti_harassment": null, + "set_recv_reply": 0, + "set_recv_like": 0, + "set_new_follow": 0 + } +} +``` + +
+ +## 修改用户偏好设置 + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +参数名称与值基本同「[获取用户偏好设置](#获取用户偏好设置)」中的 `data` 对象,修改设置时只需提供修改的设置对应的参数即可 + +开启自动回复功能需要 1000 粉丝及以上,否则会提示 700009 `权限不足` + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------------------ | ---- | ------------------------ | ------ | ----------------------------------------------------- | +| show_unfollowed_msg | num | 收起未关注人消息 | 非必要 | 0:不收起
1:收起 | +| msg_notify | num | 消息提醒 | 非必要 | 1:接收
3:不接收 | +| set_like | num | 收到的赞提醒 | 非必要 | 0:接收
5:不接收 | +| set_comment | num | 回复我的提醒 | 非必要 | 0:所有人
1:关注的人
2:不接受任何消息提醒 | +| set_at | num | @ 我的提醒 | 非必要 | 0:所有人
1:关注的人
2:不接受任何消息提醒 | +| is_group_fold | num | 收起应援团消息 | 非必要 | 0:不收起
1:收起 | +| should_receive_group | num | 接收应援团消息 | 非必要 | 0:不接收
1:接收 | +| receive_unfollow_msg | num | 接收未关注人消息 | 非必要 | 0:不接收
1:接收 | +| followed_reply | num | 被关注回复 | 非必要 | 需要有自动回复权限
0:关闭
1:开启 | +| keys_reply | num | 关键词回复 | 非必要 | 需要有自动回复权限
0:关闭
1:开启 | +| recv_reply | num | 收到消息回复 | 非必要 | 需要有自动回复权限
0:关闭
1:开启 | +| voyage_reply | num | 大航海上船回复 | 非必要 | 需要有自动回复权限
0:关闭
1:开启 | +| recommend_followed_reply | num | 被关注时自动推送作品 | 非必要 | 需要有自动回复权限
0:关闭
1:开启 | +| ai_intercept | num | 私信智能拦截 | 非必要 | 0:关闭
1:开启 | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | +| csrf_token | str | CSRF Token(位于cookie) | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | -------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
2:非法参数
700009:权限不足 | +| msg | str | 错误信息 | 默认为0 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | 空对象 | + +**示例:** + +开启接收消息提醒 + +```shell +curl 'https://api.vc.bilibili.com/link_setting/v1/link_setting/set' \ + --data-urlencode 'msg_notify=1' \ + --data-urlencode 'build=0' \ + --data-urlencode 'mobi_app=web' \ + --data-urlencode 'csrf_token=xxx' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": {} +} +``` + +
+ +## 获取消息屏蔽词 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ---------------- | ------ | ------------- | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| msg | str | 错误信息 | 默认为0 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ------------------------------- | ------------------ | ---------------- | +| words | 有效时:array
无效时:null | 消息屏蔽词列表 | | +| message | str | (?) | **作用尚不明确** | +| max_word_length | num | 单个屏蔽词最大长度 | 目前为 `20` | +| max_words_size | num | 屏蔽词最大数量 | 目前为 `200` | + +`data` 中的 `words` 数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---- | +| 0 | obj | 屏蔽词1 | | +| n | obj | 屏蔽词(n+1) | | +| …… | obj | …… | …… | + +`words` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------------- | ---------- | +| content | str | 屏蔽词内容 | | +| ctime | num | 屏蔽词添加时间 | 秒级时间戳 | + +**示例:** + +```shell +curl -G 'https://api.vc.bilibili.com/x/im/link_setting/get_block_words' \ + --data-urlencode 'build=0' \ + --data-urlencode 'mobi_app=web' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": { + "words": [ + { + "content": "屏蔽词", + "ctime": 1746422088 + } + ], + "message": "", + "max_word_length": 20, + "max_words_size": 200 + } +} +``` + +
+ +## 添加消息屏蔽词 + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | ------ | -------------- | +| content | str | 屏蔽词内容 | 必要 | 最多 20 个字符 | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | +| csrf_token | str | CSRF Token(位于cookie) | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误
1900004:添加失败,屏蔽词限制最多20个字
1900005:添加失败,最多可以添加200个屏蔽词
1900006:添加失败,屏蔽词重复
1900007:添加失败,屏蔽词不支持空格 | +| msg | str | 错误信息 | 默认为0 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | 空对象 | + +**示例:** + +```shell +curl 'https://api.vc.bilibili.com/x/im/link_setting/add_block_word' \ + --data-urlencode 'content=屏蔽词' \ + --data-urlencode 'build=0' \ + --data-urlencode 'mobi_app=web' \ + --data-urlencode 'csrf_token=xxx' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": {} +} +``` + +
+ +## 删除消息屏蔽词 + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | ------ | ------------- | +| content | str | 屏蔽词内容 | 必要 | | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | +| csrf_token | str | CSRF Token(位于cookie) | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| msg | str | 错误信息 | 默认为0 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | 空对象 | + +**示例:** + +```shell +curl 'https://api.vc.bilibili.com/x/im/link_setting/del_block_word' \ + --data-urlencode 'content=屏蔽词' \ + --data-urlencode 'build=0' \ + --data-urlencode 'mobi_app=web' \ + --data-urlencode 'csrf_token=xxx' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": {} +} +``` + +
+ +## 获取自动回复文本/关键词回复规则 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ---------------- | ------ | ---------------------------------------------------------------------------- | +| type\[\] | num | 自动回复类型 | 必要 | 1:被关注回复
2:关键词回复
3:收到消息回复
5:大航海上船回复 | +| uid | num | 自己的mid | 非必要 | | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
2:非法参数 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ----- | ------------ | -------------------------------------- | +| texts | array | 自动回复文本 | 若未设置此类型自动回复文本,则没有此项 | + +`data` 中的 `texts` 数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | -------------------------------- | +| 0 | obj | 文本1 | | +| n | obj | 文本(n+1) | 当类型为 “关键词回复” 时可有多项 | +| …… | obj | …… | …… | + +`texts` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | -------------- | -------------------------------------------------------------------------- | +| id | num | 自动回复规则id | | +| uid | num | 自己的mid | | +| type | num | 自动回复类型 | 同请求参数 `type[]` | +| title | str | 规则名称 | 当类型为 “关键词回复” 时有效,否则为空文本 | +| key1 | str | 精确匹配关键词 | 当类型为 “关键词回复” 时有效,否则为空文本
以中文逗号分隔每一个关键词 | +| key2 | str | 模糊匹配关键词 | 当类型为 “关键词回复” 时有效,否则为空文本
以中文逗号分隔每一个关键词 | +| reply | str | 回复内容 | | + +**示例:** + +获取关键词回复规则 + +```shell +curl -G 'https://api.vc.bilibili.com/x/im/auto_reply/get_reply_text' \ + --data-urlencode 'type[]=2' \ + --data-urlencode 'uid=425503913' \ + --data-urlencode 'build=0' \ + --data-urlencode 'mobi_app=web' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "texts": [ + { + "id": 201321, + "uid": 425503913, + "type": 2, + "title": "谢谢", + "key1": "谢谢,Thank you", + "key2": "感谢", + "reply": "我也感谢您对我的支持 (=・ω・=)" + }, + { + "id": 201320, + "uid": 425503913, + "type": 2, + "title": "哭2", + "key1": "哭", + "key2": "", + "reply": "我是不会哭的 (=・ω・=)" + }, + { + "id": 201318, + "uid": 425503913, + "type": 2, + "title": "哭", + "key1": "", + "key2": "哭", + "reply": "别哭了[tv_微笑]摸摸您 (^・ω・^)" + } + ] + } +} +``` + +
+ +## 修改自动回复文本/关键词回复规则 + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +仅调用本接口不会开启或关闭自动回复功能,请使用 “[修改用户偏好设置](#修改用户偏好设置)” 接口 + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | ---------------------- | ---------------------------------------------------------------------------- | +| type | num | 自动回复类型 | 必要 | 1:被关注回复
2:关键词回复
3:收到消息回复
5:大航海上船回复 | +| reply | str | 回复内容 | 必要 | 最多 500 个字符 | +| id | str | 规则id | 非必要 | 当类型为 “关键词回复” 时有效
为 `0` 或为空时新增回复规则,否则修改 id 对应的回复规则 | +| title | str | 规则名称 | 关键词回复必要 | 当类型为 “关键词回复” 时有效,最多 30 个字符 | +| key1 | str | 精确匹配关键词 | 关键词回复必要(可选) | 当类型为 “关键词回复” 时有效,`key1` 与 `key2` 须至少填一个参数
以中文逗号分隔每一个关键词,最多 20 项 | +| key2 | str | 模糊匹配关键词 | 关键词回复必要(可选) | 当类型为 “关键词回复” 时有效,`key1` 与 `key2` 须至少填一个参数
以中文逗号分隔每一个关键词,最多 20 项 | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | +| csrf_token | str | CSRF Token(位于cookie) | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
27011:请求参数错误
1500001:自动回复内容太长
1500002:规则数量已达上限,请删除后新建
1500003:您保存的内容含敏感信息,请修改后重试 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | 空对象 | + +**示例:** + +修改关键词回复规则 `id=201321`,规则名称为 `谢谢`,精确匹配关键词为 `谢谢,Thank you,感谢`,回复内容为 `嗯嗯,不用谢[tv_微笑]` + +```shell +curl 'https://api.vc.bilibili.com/x/im/auto_reply/set_reply_text' \ + --data-urlencode 'type=2' \ + --data-urlencode 'reply=嗯嗯,不用谢[tv_微笑]' \ + --data-urlencode 'id=201321' \ + --data-urlencode 'title=谢谢' \ + --data-urlencode 'key1=谢谢,Thank you,感谢' \ + --data-urlencode 'key2=' \ + --data-urlencode 'build=0' \ + --data-urlencode 'mobi_app=web' \ + --data-urlencode 'csrf_token=xxx' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": {} +} +``` + +
+ +## 删除关键词回复规则 + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | ------ | ------------- | +| id | str | 规则id | 必要 | | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | +| csrf_token | str | CSRF Token(位于cookie) | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-500:服务器错误
1003:不能删除别人的规则 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | 空对象 | + +**示例:** + +删除关键词回复规则 `id=201321` + +```shell +curl 'https://api.vc.bilibili.com/x/im/auto_reply/del_reply_text' \ + --data-urlencode 'id=201321' \ + --data-urlencode 'build=0' \ + --data-urlencode 'mobi_app=web' \ + --data-urlencode 'csrf_token=xxx' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": {} +} +``` + +
+ +## 获取系统设置 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +此接口中的设置一般不能由用户随意更改 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ---------------- | ------ | ------------------------- | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| msg | str | 错误信息 | 默认为0 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------------------------- | ---- | ---------------------------------------------------------------------------------------- | -------------------------- | +| is_create_group_available | num | 是否可创建粉丝团 | 粉丝数达到 1000 后开启 | +| is_auto_reply_available | num | 是否可使用自动回复功能 | 粉丝数达到 1000 后开启 | +| vc_hint_title | str | 稿件自动推送小灰条内容 | `我为什么会收到此类消息` | +| vc_hint_title_button | str | 稿件自动推送小灰条旁的按钮内容 | `了解更多` | +| vc_hint_detail | str | 稿件自动推送详细信息小灰条内容 | `您【特别关注】的UP主更新视频或专栏后,会第一时间在私信推送给您。如有需要可点击右上角设置关闭推送。` | +| vc_hint_detail_button | str | 关闭稿件自动推送按钮内容 | `关闭推送` | +| auto_reply_html | str | 自动回复H5页面url | `https://message.bilibili.com/h5/app/auto-reply` | +| is_receive_unfollow_wl | num | 是否显示限制接收未关注人消息功能 | | +| is_voyage | num | 是否在自动回复页面显示 “大航海自动回复” 选项 | 仅部分用户开启 | +| is_auto_reply_recommend_available | num | 是否在自动回复中的 “被关注回复” 页面显示 “被关注后,向关注我的人推送我的往期作品” 复选框 | 仅部分用户开启 | +| is_discuss_style_im_page | num | (?) | **作用尚不明确** | +| discuss_unread_style_im_page | num | (?) | **作用尚不明确** | +| old_up_assistant_door | obj | 原 “UP主小助手” 入口相关信息 | | +| is_new_up_assistant_effective | num | 新 “UP主小助手” 是否启用 | | +| is_archive_gray | bool | 是否不显示 “私信存档” 按钮 | | +| session_cfg | obj | 特定私信会话配置信息 | | +| migrate_session_api | bool | (?) | **作用尚不明确** | +| game_msg | obj | (?) | **作用尚不明确**;仅当请求参数 `mobi_app` 不为 `web` 时有其中的项目 | +| auto_reply_msg_desc | str | 指示消息为自动回复消息的提示内容 | `此条消息为自动回复` | +| huahuo_group_icon_new | str | 浅色模式下的花火图标url | | +| huahuo_group_icon_dark_new | str | 深色模式下的花火图标url | | +| im_disabled_input_hint | str | 某UP主禁用私信功能时的提示内容 | `请到UP主空间发起咨询` | + +`data` 中的 `old_up_assistant_door` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------------- | ---- | ---------------------------- | ------------ | +| show_old_up_door | num | 是否显示原 “UP主小助手” 入口 | 目前恒为 `0` | +| title | str | 原 “UP主小助手” 入口标题 | 目前为空文本 | +| sub_title | str | 原 “UP主小助手” 入口子标题 | 目前为空文本 | + +`data` 中的 `session_cfg` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ---------------- | ---- | +| {用户mid} | obj | 该会话的配置信息 | | + +`session_cfg` 中的 `{用户mid}` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------------- | ---- | -------------------- | ------------------- | +| hidden_emote_btn | bool | 是否隐藏表情按钮 | | +| hidden_pic_btn | bool | 是否隐藏发送图片按钮 | | +| max_height | num | 最大高度(?) | **作用尚不明确** | +| hint_text | str | 私信输入框的提示内容 | `你想问什么问题呢?` | +| hidden_top_hint | bool | (?) | **作用尚不明确** | +| is_gpt_account | bool | 是否为AI会话 | | + +`data` 中的 `game_msg` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ---- | ------------------------------------------------------------- | +| show_install | bool | true | **作用尚不明确**;仅当请求参数 `mobi_app` 不为 `web` 时有此项 | + +**示例:** + +```shell +curl 'https://api.vc.bilibili.com/link_setting/v1/link_setting/get_sys_setting' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": { + "is_create_group_available": 1, + "is_auto_reply_available": 1, + "vc_hint_title": "我为什么会收到此类消息", + "vc_hint_title_button": "了解更多", + "vc_hint_detail": "您【特别关注】的UP主更新视频或专栏后,会第一时间在私信推送给您。如有需要可点击右上角设置关闭推送。", + "vc_hint_detail_button": "关闭推送", + "auto_reply_html": "https://message.bilibili.com/h5/app/auto-reply", + "is_receive_unfollow_wl": 0, + "is_voyage": 1, + "is_auto_reply_recommend_available": 0, + "is_discuss_style_im_page": 0, + "discuss_unread_style_im_page": 0, + "old_up_assistant_door": { + "show_old_up_door": 0, + "title": "", + "sub_title": "" + }, + "is_new_up_assistant_effective": 1, + "is_archive_gray": true, + "session_cfg": { + "100000000000001": { + "hidden_emote_btn": true, + "hidden_pic_btn": true, + "max_height": 62, + "hint_text": "你想问什么问题呢?", + "hidden_top_hint": true, + "is_gpt_account": true + }, + "100000000000002": { + "hidden_emote_btn": true, + "hidden_pic_btn": true, + "max_height": 62, + "hint_text": "你想问什么问题呢?", + "hidden_top_hint": true, + "is_gpt_account": true + }, + "1400565964": { + "hidden_emote_btn": true, + "hidden_pic_btn": true, + "max_height": 62, + "hint_text": "你想问什么问题呢?", + "hidden_top_hint": true, + "is_gpt_account": true + } + }, + "migrate_session_api": false, + "game_msg": { + "show_install": true + }, + "auto_reply_msg_desc": "此条消息为自动回复", + "huahuo_group_icon_new": "http://i0.hdslb.com/bfs/kfptfe/floor/e2e3829e514ebccab1705636b0354ec89446a4b5.png", + "huahuo_group_icon_dark_new": "http://i0.hdslb.com/bfs/kfptfe/floor/d09bc8c0716a15938ec427db5fa962733703f3ce.png", + "im_disabled_input_hint": "请到UP主空间发起咨询" + } +} +``` + +
+ +## 获取创建粉丝团按钮可见性 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ---------------- | ------ | ------------------------- | +| build | num | 客户端内部版本号 | 非必要 | 默认为 `0` | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web` 等 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| msg | str | 错误信息 | 默认为0 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------------------- | ---------------------- | +| show | num | 是否显示创建粉丝团按钮 | 粉丝数达到 1000 后显示 | + +**示例:** + +```shell +curl 'https://api.vc.bilibili.com/link_group/v1/member/show_create_group_icon' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": { + "show": 1 + } +} +``` + +
diff --git a/bb-api-collect/docs/misc/b23tv.md b/bb-api-collect/docs/misc/b23tv.md new file mode 100644 index 0000000000..e395d7e965 --- /dev/null +++ b/bb-api-collect/docs/misc/b23tv.md @@ -0,0 +1,127 @@ +# b23.tv 短链 + +## 简述 + +b23.tv 是由 Bilibili 提供的短链服务, 主要用于站内长链接缩短便于分享, 目前仅在手机客户端生成 + +### 格式 + +目前已知的 b23.tv 短链格式有以下 3 种 + +- 任意短链, 路径由7位数字或大小写英文字母组成, 为防止滥用似乎有时效限制, 如 https://b23.tv/pigt3PQ + +- 视频短链(AV号), 路径由字符串 `av` 尾随 视频 aid 组成, 如 https://b23.tv/av80433022 + +- 视频短链(BV号), 路径由字符串 `BV` 尾随 视频 bvid 组成, 如 https://b23.tv/BV1GJ411x7h7 + +## 生成 + +### 视频短链 + +1. 直接手动拼接字符串即可 + +2. 参见[任意短链](#任意短链) + +### 任意短链 + +> https://api.bilibili.com/x/share/click +> https://api.biliapi.net/x/share/click + +*请求方式: POST* + +认证方式: 仅APP, 但实际上形同虚设 + +注: 该接口参数对照表基本失效, 基本无实用价值, 已被注释, 参见 [#979](https://github.com/SocialSisterYi/bilibili-API-collect/issues/979) [Nemo2011/bilibili-api#720](https://github.com/Nemo2011/bilibili-api/pull/720) + +**正文参数(application/x-www-form-urlencoded):** + +必要: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------- | ------ | ---- | +| buvid | str | 设备 BUVID | 必要 | 实际任意非空字符串即可 | +| build | num | 客户端版本号 | 必要 | 大于 `5520400` 的任意有效整数, 如 `7710300` | +| platform | str | 客户端平台 | 必要 | 实际任意非空字符串即可 | +| share_channel | str | 分享方式? | 必要 | COPY | +| share_mode | num | 分享模式? | 必要 | 任意有效正整数, 常见 `1`, `3`, `4` | +| share_id | str | 分享 ID | 必要 | 见下方对照表 | +| share_origin | str | 分享来源? | 部分必要 | 见下方对照表 | +| oid | num | 对象 ID | 必要 | 见下方对照表 | + +不必要: + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------ | ---- | ---- | +| object_extra_fields| obj | 额外字段? | 非必要 | 如 `{"jumpfrom_id":30104}` `{"epid":"409808","cid":"1398781253"}` `{"season_type":"1","season_id":"39481","epid":"425006","dubbing_support":false,"background_audio":false,"role_audio_list":false}` | +| panel_type | num | 面板类型? | 非必要 | 1 | +| share_title | str | 分享标题? | 非必要 | 分享标题 | +| share_content | str | 分享内容? | 非必要 | 分享内容, 当 oid 存在时无意义(可是 oid 不可能不存在啊) | +| share_pattern | num | 分享模式? | 非必要 | 0 | +| share_session_id | str | 分享会话 ID? | 非必要 | 各部分用 `-` 分隔的小写的一串 UUID | +| ts | num | UNIX 秒级时间戳 | 非必要 | | + +对照表: + +| 类型 | 分享 ID (share_id) | 对象 ID (oid) | 分享来源? (share_origin) | 备注 | +| --- | ------------------ | ------------- | ----------------------- | ---- | +| 视频 | `main.ugc-video-detail.0.0.pv` | 视频 aid | 非必要 | | +| 动态/图文 | `dt.dt-detail.0.0.pv` | 动态/图文 id | `dynamic` | | +| 专栏 | `read.column-detail.roof.8.click` | 文章 cvid | 非必要 | | +| 文集 | `read.column-readlist.share.0.click` | 文集 rlid | 非必要 | | +| 用户 | `main.space-total.more.0.click` | 用户 mid | 非必要 | | +| 课程 | `pugv.pugv-video-detail.0.0.pv` | 课程 id? | `vinfo_player` 或 `vinfo_share` | | +| 链接 | `public.webview.0.0.pv` | 任意站內链接 | 非必要 | 需填写完整链接,且域名必需为 `*.bilibili.com` | + + + + +**JSON回复:** + +根对象: + +| 字段名 | 类型 | 内容 | 备注 | +| ------ | ---- | -------- | ---- | +| code | num | 0 | 恒为 0 | +| message | str | 0 | 恒为 0 | +| ttl | num | 1 | 恒为 1 | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段名 | 类型 | 内容 | 备注 | +| ------ | ---- | -------- | ---- | +| content | str | 短链内容 | 若失败则不存在 | +| count | num | 0 | 恒为 0 | + +**示例:** + +为 `av80433022` 生成 b23.tv 短链 + +```shell +curl -X POST "http://api.biliapi.net/x/share/click" \ +--data-urlencode "platform=unix" \ +--data-urlencode "share_channel=COPY" \ +--data-urlencode "share_id=main.ugc-video-detail.0.0.pv" \ +--data-urlencode "share_mode=4" \ +--data-urlencode "oid=80433022" \ +--data-urlencode "buvid=qwq" \ +--data-urlencode "build=6114514" +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "content": "【【官方 MV】Never Gonna Give You Up - Rick Astley-哔哩哔哩】 https://b23.tv/5x4wy5f", + "count": 0 + } +} +``` + +
diff --git a/bb-api-collect/docs/misc/buvid3_4.md b/bb-api-collect/docs/misc/buvid3_4.md new file mode 100644 index 0000000000..99dc3c1dc1 --- /dev/null +++ b/bb-api-collect/docs/misc/buvid3_4.md @@ -0,0 +1,132 @@ +# 获取 buvid3 / buvid4 / b_nut + +## 仅获取 buvid3 + +> https://api.bilibili.com/x/web-frontend/getbuvid + +*请求方式: GET* + + + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | -------- | +| code | num | 返回值 | 0:成功 | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | ---- | +| buvid | str | buvid3 | 需手动存放至 cookie 中 | + +**示例:** + +注: 不要复制 + +```shell +curl -G 'https://api.bilibili.com/x/web-frontend/getbuvid' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "data": { + "buvid": "54E5EFC1-3C8F-F690-2261-439E4F6A20A979439infoc" + } +} +``` + +
+ +## 接口获取 buvid3 / buvid4 + +> https://api.bilibili.com/x/frontend/finger/spi + +*请求方式: GET* + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | -------- | +| code | num | 返回值 | 0:成功 | +| message | str | 信息 | ok: 成功 | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | ---- | +| b_3 | str | buvid3 | 需手动存放至 cookie 中 | +| b_4 | str | buvid4 | 同上 | + +**示例:** + +注: 建议自行生成, 不要复制本处示例的 buvid3 / buvid4. + +```shell +curl -G 'https://api.bilibili.com/x/frontend/finger/spi' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "data": { + "b_3": "D9656DA8-9BEF-F464-5B72-C4849AFD336379044infoc", + "b_4": "F6E0FD4B-520C-1902-4F7B-E461D8D1F5AB79044-024072309-666onEZSnlHVPjoRp4kDYg==" + }, + "message": "ok" +} +``` + +
+ +## 从响应头获取 buvid3 / b_nut + +使用 `GET` 或 `HEAD` 方法请求 `https://www.bilibili.com/`, 且请求头中 `User-Agent` 字段不包含 `curl` `python` `awa` 等敏感子字符串, 且相同 `User-Agent` 字段不得短时多次请求. 在响应头中的 `Set-Cookie` 字段中, 即可找到 `buvid3` 和 `b_nut`. + +若不带任何 Cookie 请求, 则 `b_nut` 为响应生成时刻的 UNIX 秒级时间戳. +若请求 Cookie 仅带有 `buvid3`, 则 `b_nut` 为 `100`. +若请求 Cookie 仅带有 `b_nut`, 则与不带任何 Cookie 的响应相同. +若请求 Cookie 仅带有 `buvid3` 和 `b_nut`, 则响应无 `Set-Cookie` 字段. +若请求 Cookie 带有其他字段, 无影响. + +**示例:** + +```shell +curl -I "https://www.bilibili.com/" -A "awa" +``` + +
+查看响应示例: + +```http +HTTP/2 200 +date: Fri, 26 Jul 2024 06:38:43 GMT +content-type: text/html; charset=utf-8 +support: nantianmen +set-cookie: buvid3=805E4894-96A2-0684-6F00-C6EA1FFB911023315infoc; path=/; expires=Sat, 26 Jul 2025 06:38:43 GMT; domain=.bilibili.com +set-cookie: b_nut=1721975923; path=/; expires=Sat, 26 Jul 2025 06:38:43 GMT; domain=.bilibili.com +vary: Origin,Accept-Encoding +idc: shjd +expires: Fri, 26 Jul 2024 06:38:42 GMT +cache-control: no-cache +x-cache-webcdn: MISS from blzone01 +x-cache-time: 0 +x-save-date: Fri, 26 Jul 2024 06:38:43 GMT +``` + +
diff --git a/bb-api-collect/docs/misc/bvid_desc.md b/bb-api-collect/docs/misc/bvid_desc.md new file mode 100644 index 0000000000..d9e3346552 --- /dev/null +++ b/bb-api-collect/docs/misc/bvid_desc.md @@ -0,0 +1,850 @@ + +# 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 的字符串,前 3 个固定为“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 + + + + +```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')); +``` + + + + + +```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(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')); +``` + + + +### 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 + +参考 + +### 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")) +``` + +### Java + +```java +import java.math.BigInteger; + +/** + * @author cctyl + */ +public class AVBVConverter { + + private static final BigInteger XOR_CODE = BigInteger.valueOf(23442827791579L); + private static final BigInteger MASK_CODE = BigInteger.valueOf(2251799813685247L); + private static final BigInteger MAX_AID = BigInteger.ONE.shiftLeft(51); + private static final int BASE = 58; + + private static final String DATA = "FcwAPNKTMug3GV5Lj7EJnHpWsx4tb8haYeviqBz6rkCy12mUSDQX9RdoZf"; + + public static String av2bv(long aidParam) { + BigInteger aid = BigInteger.valueOf(aidParam); + char[] bytes = {'B', 'V', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0'}; + int bvIndex = bytes.length - 1; + BigInteger tmp = MAX_AID.or(aid).xor(XOR_CODE); + while (tmp.compareTo(BigInteger.ZERO) > 0) { + bytes[bvIndex] = DATA.charAt(tmp.mod(BigInteger.valueOf(BASE)).intValue()); + tmp = tmp.divide(BigInteger.valueOf(BASE)); + bvIndex--; + } + swap(bytes, 3, 9); + swap(bytes, 4, 7); + return new String(bytes); + } + + public static long bv2av(String bvid) { + char[] bvidArr = bvid.toCharArray(); + swap(bvidArr, 3, 9); + swap(bvidArr, 4, 7); + String adjustedBvid = new String(bvidArr, 3, bvidArr.length - 3); + BigInteger tmp = BigInteger.ZERO; + for (char c : adjustedBvid.toCharArray()) { + tmp = tmp.multiply(BigInteger.valueOf(BASE)).add(BigInteger.valueOf(DATA.indexOf(c))); + } + BigInteger xor = tmp.and(MASK_CODE).xor(XOR_CODE); + return xor.longValue(); + } + + + private static void swap(char[] array, int i, int j) { + char temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } + + public static void main(String[] args) { + + final int aid1 = 643755790; + final String bv1 = "BV1bY4y1j7RA"; + + final int aid2 = 305988942; + final String bv2 = "BV1aP411K7it"; + + //av ==> bv + assert av2bv(aid1).equals(bv1); + assert av2bv(aid2).equals(bv2); + + //bv ==>av + assert bv2av(bv1) == aid1; + assert bv2av(bv2) == aid2; + } +} +``` + +### Golang + +```go +package main + +import ( + "fmt" + "strings" +) + +var ( + XOR_CODE = int64(23442827791579) + MAX_CODE = int64(2251799813685247) + CHARTS = "FcwAPNKTMug3GV5Lj7EJnHpWsx4tb8haYeviqBz6rkCy12mUSDQX9RdoZf" + PAUL_NUM = int64(58) +) + +func swapString(s string, x, y int) string { + chars := []rune(s) + chars[x], chars[y] = chars[y], chars[x] + return string(chars) +} + +func Bvid2Avid(bvid string) (avid int64) { + s := swapString(swapString(bvid, 3, 9), 4, 7) + bv1 := string([]rune(s)[3:]) + temp := int64(0) + for _, c := range bv1 { + idx := strings.IndexRune(CHARTS, c) + temp = temp*PAUL_NUM + int64(idx) + } + avid = (temp & MAX_CODE) ^ XOR_CODE + return +} + +func Avid2Bvid(avid int64) (bvid string) { + arr := [12]string{"B", "V", "1"} + bvIdx := len(arr) - 1 + temp := (avid | (MAX_CODE + 1)) ^ XOR_CODE + for temp > 0 { + idx := temp % PAUL_NUM + arr[bvIdx] = string(CHARTS[idx]) + temp /= PAUL_NUM + bvIdx-- + } + raw := strings.Join(arr[:], "") + bvid = swapString(swapString(raw, 3, 9), 4, 7) + return +} + +func main() { + avid := int64(1054803170) + bvid := "BV1mH4y1u7UA" + resAvid := Bvid2Avid(bvid) + resBvid := Avid2Bvid(avid) + + fmt.Printf("convert bvid to avid: %v\tvalue:%v\n", avid == resAvid, resAvid) + fmt.Printf("convert avid to bvid: %v\tvalue:%v\n", bvid == resBvid, resBvid) + +} + +``` + + +### C++ +```cpp +#include +#include +#include +#include + +constexpr int64_t XOR_CODE = 0x1552356C4CDB; +constexpr int64_t MAX_AID = 0x8000000000000; +constexpr int64_t MASK_CODE = MAX_AID - 1; +constexpr int64_t BASE = 58; +constexpr char Table[BASE + 1] = "FcwAPNKTMug3GV5Lj7EJnHpWsx4tb8haYeviqBz6rkCy12mUSDQX9RdoZf"; +constexpr char ReverseTable[128] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x2c, 0x2d, 0x0b, 0x1a, 0x0e, 0x27, 0x11, 0x1d, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x25, 0x2a, 0x31, 0x12, 0x00, 0x0c, 0x15, 0x00, 0x13, 0x06, 0x0f, 0x08, 0x05, 0x00, + 0x04, 0x32, 0x35, 0x30, 0x07, 0x2f, 0x0d, 0x17, 0x33, 0x20, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1f, 0x1c, 0x01, 0x36, 0x21, 0x39, 0x0a, 0x1e, 0x23, 0x10, 0x29, 0x00, 0x2e, 0x14, 0x37, + 0x16, 0x24, 0x28, 0x18, 0x1b, 0x09, 0x22, 0x02, 0x19, 0x2b, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +std::string Av2bv(const int64_t Avid) { + assert(Avid > 0 && "Avid must be greater than 0"); + std::string bv = "BV1"; + bv.resize(12, '\0'); + + int64_t tmp = (Avid | MAX_AID) ^ XOR_CODE; + for (size_t i = bv.size() - 1; tmp > 0 && i > 2; --i) { + bv[i] = Table[tmp % BASE]; + tmp /= BASE; + } + std::ranges::swap(bv.at(3), bv.at(9)); + std::ranges::swap(bv.at(4), bv.at(7)); + return bv; +} + +int64_t Bv2av(const std::string &Bvid) { + assert(Bvid.starts_with("BV1") && "Bvid must start with 'BV1'"); + + auto Bvid_ = Bvid; + std::ranges::swap(Bvid_.at(3), Bvid_.at(9)); + std::ranges::swap(Bvid_.at(4), Bvid_.at(7)); + + int64_t tmp = 0; + for (int i = 3; i < Bvid_.size(); ++i) { + tmp = ReverseTable[Bvid_.at(i)] + BASE * tmp; + } + return (tmp & MASK_CODE) ^ XOR_CODE; +} + +int main() { + assert(Av2bv(1004871019) == "BV16x4y1H7M1"); + assert(Bv2av("BV16x4y1H7M1") == 1004871019); +} +``` + + + +## 老版算法存档 + +**以下算法已失效**,编解码函数值域有限,不推荐使用,在此仅作为存档 + +
+查看折叠内容: + +算法参考自[【揭秘】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 C TypeScript Java Kotlin Golang 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 +#include +#include +#include + +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 = {}; // 反查码表 + 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 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() + private val mp2 = HashMap() + + //现在,定义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")); +``` + +
diff --git a/bb-api-collect/docs/misc/device_identity.md b/bb-api-collect/docs/misc/device_identity.md new file mode 100644 index 0000000000..03358484d9 --- /dev/null +++ b/bb-api-collect/docs/misc/device_identity.md @@ -0,0 +1,104 @@ +# 设备各类标识算法(APP 端) + +## 设备唯一标识 BUVID + +注意区分于 Web 端的 [buvid3, buvid4](buvid3_4.md). + +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 中 +// 如果 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`|东南亚版本| diff --git a/bb-api-collect/docs/misc/errcode.md b/bb-api-collect/docs/misc/errcode.md new file mode 100644 index 0000000000..3fe8264bd3 --- /dev/null +++ b/bb-api-collect/docs/misc/errcode.md @@ -0,0 +1,62 @@ +# 公共错误码 + +下表为大部分接口返回值中`code`字段值中公共的错误代码 + +## 权限类 + +| 代码 | 含义 | +| ---- | -------------------------- | +| -1 | 应用程序不存在或已被封禁 | +| -2 | Access Key 错误 | +| -3 | API 校验密匙错误 | +| -4 | 调用方对该 Method 没有权限 | +| -101 | 账号未登录 | +| -102 | 账号被封停 | +| -103 | 积分不足 | +| -104 | 硬币不足 | +| -105 | 验证码错误 | +| -106 | 账号非正式会员或在适应期 | +| -107 | 应用不存在或者被封禁 | +| -108 | 未绑定手机 | +| -110 | 未绑定手机 | +| -111 | csrf 校验失败 | +| -112 | 系统升级中 | +| -113 | 账号尚未实名认证 | +| -114 | 请先绑定手机 | +| -115 | 请先完成实名认证 | + +## 请求类 + +| 代码 | 含义 | +| ---- | --------------------- | +| -304 | 木有改动 | +| -307 | 撞车跳转 | +| -352 | 风控校验失败 (UA 或 wbi 参数不合法) | +| -400 | 请求错误 | +| -401 | 未认证 (或非法请求) | +| -403 | 访问权限不足 | +| -404 | 啥都木有 | +| -405 | 不支持该方法 | +| -409 | 冲突 | +| -412 | 请求被拦截 (客户端 ip 被服务端风控) | +| -500 | 服务器错误 | +| -503 | 过载保护,服务暂不可用 | +| -504 | 服务调用超时 | +| -509 | 超出限制 | +| -616 | 上传文件不存在 | +| -617 | 上传文件太大 | +| -625 | 登录失败次数太多 | +| -626 | 用户不存在 | +| -628 | 密码太弱 | +| -629 | 用户名或密码错误 | +| -632 | 操作对象数量限制 | +| -643 | 被锁定 | +| -650 | 用户等级太低 | +| -652 | 重复的用户 | +| -658 | Token 过期 | +| -662 | 密码时间戳过期 | +| -688 | 地理区域限制 | +| -689 | 版权限制 | +| -701 | 扣节操失败 | +| -799 | 请求过于频繁,请稍后再试 | +| -8888 | 对不起,服务器开小差了~ (ಥ﹏ಥ) | diff --git a/bb-api-collect/docs/misc/mathjax.md b/bb-api-collect/docs/misc/mathjax.md new file mode 100644 index 0000000000..545f7c2bff --- /dev/null +++ b/bb-api-collect/docs/misc/mathjax.md @@ -0,0 +1,54 @@ +# 表达式渲染 + +## LaTeX + +> https://api.bilibili.com/x/web-frontend/mathjax/tex + +*请求方法: GET* + +暂未发现对跨源使用 `` 标签使用该接口的限制 + + + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ------ | ---- | ------ | ----- | +| formula | string | 公式 | 非必要 | LaTeX | + +**SVG 回复:** + +一个完整的 SVG (image/svg+xml) 文件, 可直接用于 HTML `` 或 Markdown `![]()` + +**示例:** + +```markdown +![](https://api.bilibili.com/x/web-frontend/mathjax/tex?formula=\pi=3.14159265358979323846...) + +![](https://api.bilibili.com/x/web-frontend/mathjax/tex?formula=E=mc^2) + +![](https://api.bilibili.com/x/web-frontend/mathjax/tex?formula=\ce{Fe+%2B+CuSO4+=+Cu+%2B+FeSO4}) + +![](https://api.bilibili.com/x/web-frontend/mathjax/tex?formula=\ce{N2(g)+%2B+3H2(g)+<=>[\text{高温、高压、催化剂}]+2NH3(g)}) + +![](https://api.bilibili.com/x/web-frontend/mathjax/tex?formula=S=\frac{1}{3}Sh) + +![](https://api.bilibili.com/x/web-frontend/mathjax/tex?formula=y+=+\frac{1}{\dfrac{1}{x}+%2B+1} ) +``` + +
+查看渲染结果: + +![](https://api.bilibili.com/x/web-frontend/mathjax/tex?formula=\pi=3.14159265358979323846...) + +![](https://api.bilibili.com/x/web-frontend/mathjax/tex?formula=E=mc^2) + +![](https://api.bilibili.com/x/web-frontend/mathjax/tex?formula=\ce{Fe+%2B+CuSO4+=+Cu+%2B+FeSO4}) + +![](https://api.bilibili.com/x/web-frontend/mathjax/tex?formula=\ce{N2(g)+%2B+3H2(g)+<=>[\text{高温、高压、催化剂}]+2NH3(g)}) + +![](https://api.bilibili.com/x/web-frontend/mathjax/tex?formula=S=\frac{1}{3}Sh) + +![](https://api.bilibili.com/x/web-frontend/mathjax/tex?formula=y+=+\frac{1}{\dfrac{1}{x}+%2B+1} ) + +
diff --git a/bb-api-collect/docs/misc/picture.md b/bb-api-collect/docs/misc/picture.md new file mode 100644 index 0000000000..646487dac0 --- /dev/null +++ b/bb-api-collect/docs/misc/picture.md @@ -0,0 +1,97 @@ +# 图片格式化 + +已知 `*.hdslb.com` `*.biliimg.com` 等域名作用等效, 对于请求头 `Referer` 要求留空或在 `.bilibili.com` 等 B 站域名下 + +对于以上域名的 `/bfs/` 下的图片文件都可以使用以下可选格式化参数 + +使用 `@` 开始参数 (无论格式如何, 无论是否有参数, 通过计算 HASH 发现, 使用 `@` 均会导致返回图片不同), 多个参数以 `_` 分隔, 图片格式无需分隔且必须放在最后 + +参见: [#191](https://github.com/SocialSisterYi/bilibili-API-collect/issues/191) + +注: jpg 即 jpeg, 二者等效. 网页端常用 AVIF, WebP. + +| 参数 | 格式 | 含义 | 备注 | +| ---- | ------- | ---------------- | ---------------- | +| w | ${int}w | 图片最大限制宽度 | 范围 [1, 9223372036854775807] | +| h | ${int}h | 图片最大限制高度 | 范围 [1, 9223372036854775807] | +| s | ${int}s | 作用尚不明确 | 不影响输出结果, 范围 [1, 9223372036854775807] | +| e | ${int}e | 改变大小 | 0: 保留比例取其小, 1: 保留比例取其大, 2: 不保留原比例 | +| p | ${int}p | 缩放倍数 | 默认100, 范围 [1, 1000] | +| o | ${int}o | 作用尚不明确 | 不影响输出结果 范围 [0, 1] | +| q | ${int}q | 图片质量百分比 | 仅限webp/jpeg/avif | +| c | ${int}c | 裁切图片(如果宽高允许) | 0: 不裁切但会修改图片, 1: 上传时的预设规则(若无则右下), 2: 左上, 3: 右上 | +| f | ${int}f | 作用尚不明确 | [0, 1]: 不改变图片, 2: 会改变图片 | +| progressive | progressive | 图片编码方式 | 仅限 jpeg(无: baseline, 有: progressive)/png(无:non-interlaced, 有: interlaced) | +| ! | !${str} | 加载来源 | web-home-carousel-cover, header, web-dynamic, web-avatar-space-header, ... | +| . | .${str} | 图片格式 | 仅限 png/jpeg/webp/avif/[avg_color](#avg_color格式说明) | + +**示例:** + +
+查看示例: + +原始图片 + +https://i1.hdslb.com/bfs/archive/e5fff1472bad1c0c6bcb3004205f9be23b58ffc0.jpg + + + +高度限制为100 + +https://i1.hdslb.com/bfs/archive/e5fff1472bad1c0c6bcb3004205f9be23b58ffc0.jpg@100h + + + +宽度限制为100 + +https://i1.hdslb.com/bfs/archive/e5fff1472bad1c0c6bcb3004205f9be23b58ffc0.jpg@100w + + + +转换格式为webp + +https://i1.hdslb.com/bfs/archive/e5fff1472bad1c0c6bcb3004205f9be23b58ffc0.jpg@.webp + + + +转换为webp图片质量为1% + +https://i1.hdslb.com/bfs/archive/e5fff1472bad1c0c6bcb3004205f9be23b58ffc0.jpg@1q.webp + + +
+ +## avg_color格式说明 + +当图片格式化输出格式为`avg_color`时 + +> /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' +``` + +
+查看响应示例: + +```json +{ + "RGB": "#7d6f6c" +} +``` + +
diff --git a/bb-api-collect/docs/misc/sign/APP.md b/bb-api-collect/docs/misc/sign/APP.md new file mode 100644 index 0000000000..8b51c05419 --- /dev/null +++ b/bb-api-collect/docs/misc/sign/APP.md @@ -0,0 +1,289 @@ +# 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)、[C++](#cplusplus) 语言例程 + +使用 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 params) { + // 为请求参数进行 APP 签名 + params.put("appkey", APP_KEY); + // 按照 key 重排参数 + Map sortedParams = new TreeMap<>(params); + // 序列化参数 + StringBuilder queryBuilder = new StringBuilder(); + for (Map.Entry 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 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 + +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.. 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 + + + +### CplusPlus + +需要 c++ 23 标准库,[cpr](https://github.com/libcpr/cpr)、[cryptopp](https://github.com/weidai11/cryptopp)、[nlohmann/json](https://github.com/nlohmann/json) 等依赖 + +```c++ +#include // std::println + +/// thrid party libraries +#include // cpr::util::urlEncode() +#include +#include +#include + +/* + * 注意,假定不会发生错误! + */ + +/* 获取 md5 hex(lower) */ +std::string Get_md5_hex(const std::string &Input_str) { + CryptoPP::Weak1::MD5 hash; + std::string md5_hex; + + CryptoPP::StringSource ss(Input_str, true, + new CryptoPP::HashFilter(hash, + new CryptoPP::HexEncoder( + new CryptoPP::StringSink(md5_hex) + ) + ) + ); + + std::ranges::for_each(md5_hex, [](char &x) { x = std::tolower(x); }); + return md5_hex; +} + +/* 将 json 转换为 url 编码字符串 */ +std::string Json_to_url_encode_str(const nlohmann::json &Json) { + std::string encode_str; + for (const auto &[key, value]: Json.items()) { + encode_str.append(key).append("=").append(cpr::util::urlEncode(value.is_string() ? value.get() : to_string(value))).append("&"); + } + + // remove the last '&' + encode_str.resize(encode_str.size() - 1, '\0'); + return encode_str; +} + +std::string App_sign(nlohmann::json &Params, const std::string &App_key, const std::string &App_sec) { + Params["appkey"] = App_key; + Params["sign"] = Get_md5_hex(Json_to_url_encode_str(Params) + App_sec); + return Json_to_url_encode_str(Params); +} + +int main() { + nlohmann::json Params; + Params["id"] = 114514; + Params["str"] = "1919810"; + Params["test"] = "いいよ,こいよ"; + + constexpr auto App_key = "1d8b6e7d45233436"; + constexpr auto App_sec = "560c52ccd288fed045859ed18bffd973"; + std::string sign = App_sign(Params, App_key, App_sec); + std::println("{}", to_string(Params)); + std::println("{}", sign); +} +``` + +```text +{"appkey":"1d8b6e7d45233436","id":114514,"sign":"01479cf20504d865519ac50f33ba3a7d","str":"1919810","test":"いいよ,こいよ"} +appkey=1d8b6e7d45233436&id=114514&sign=01479cf20504d865519ac50f33ba3a7d&str=1919810&test=%E3%81%84%E3%81%84%E3%82%88%EF%BC%8C%E3%81%93%E3%81%84%E3%82%88 +``` + diff --git a/bb-api-collect/docs/misc/sign/APPKey.md b/bb-api-collect/docs/misc/sign/APPKey.md new file mode 100644 index 0000000000..0203970d2c --- /dev/null +++ b/bb-api-collect/docs/misc/sign/APPKey.md @@ -0,0 +1,55 @@ +# APPKey + +以下为已知的 APPkey / APPSec,及部分使用场景参数信息,均来自抓包与逆向工程 + +| APPKEY | APPSEC | platform2 | APP类型 | neuronAppId1 | mobi_app2 | 备注 | +| :--------------: | :------------------------------: | :------------------: | :----------------: | :---------------------: | :------------------: | :----------------------------------------: | +| 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 投稿工具&PC直播姬| - | ? | | +| bca7e84c2d947ac6 | 60698ba2f68e01ce44738920a0ffe768 | ? | login | - | ? | | +| h9Ejat5tFh81cq8V | BdiI92bjmZ9QRcjJBWv2EEssyjekAGKt | | | | | bilibili游戏 web端 游戏详情页API | + +注释: + +1 `neuronAppId`,产品编号,由数据平台分配,详情如下: + +- 粉(国内版)=1 +- 白(GooglePlay 版)=2 +- 蓝(东南亚版)=3 +- 直播姬=4 +- HD=5 +- 海外=6 +- OTT=7 +- 漫画=8 +- TV野版=9 +- 小视频=10 +- 网易漫画=11 +- 网易漫画lite=12 +- 网易漫画HD=13, +- 国际版=14 + +2 `platform`, `mobi_app` 仅供参考, 具体值需要抓包确定. diff --git a/bb-api-collect/docs/misc/sign/bili_ticket.md b/bb-api-collect/docs/misc/sign/bili_ticket.md new file mode 100644 index 0000000000..c0ed0d82c8 --- /dev/null +++ b/bb-api-collect/docs/misc/sign/bili_ticket.md @@ -0,0 +1,304 @@ +# BiliTicket + +## 简述 + +`bili_ticket` 位于请求头 Cookie 中, 非必需, 但存在可降低风控概率 + +由 [@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" +} +``` + +## 算法 + +1. 获取 UNIX 秒级时间戳存入变量如 `timestamp` +2. 计算变量 `hexsign` 值,使用 `hmac_sha256` 算法,密钥为 `XgwSnGZ1p`,消息为字符串 `"ts"` 与变量 `timestamp` 值拼接 +3. 构造请求参数,`key_id` 为 `ec02`,`hexsign` 为变量 `hexsign` 值,`context[ts]` 为变量 `timestamp` 值,`csrf` 为 cookie 中的 `bili_jct` 值也可为空 +4. 发送 `POST` 请求,获取 `data` 字段中的 `ticket` 字段的值即为所求 + +## 接口 + +> https://api.bilibili.com/bapis/bilibili.api.ticket.v1.Ticket/GenWebTicket + +*请求方式: POST* + +鉴权方式: 请求头 `Referer` 为空或 `.bilibili.com` 子域下任意页 + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----- | ---- | ---- | ------ | ---- | +| key_id | str | ec02 | 必要 | | +| hexsign | str | 由 `hmac_sha256` 算法计算的 `hexsign` 值 | 必要 | | +| context[ts] | num | UNIX 秒级时间戳 | 必要 | | +| csrf | str | cookie 中的 `bili_jct` 值 | 非必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | num | 返回值 | 0: 成功
400: 参数错误 | +| message | str | 返回消息 | OK: 成功 | +| data | obj | 数据本体 | | +| ttl | num | 1 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| ticket | str | bili_ticket | | +| created_at | num | 创建时间 | UNIX 秒级时间戳 | +| ttl | num | 有效时长 | 259200 秒 (3 天) | +| context | obj | 空 | | +| nav | obj | wbi_img 相关 | 参见 [WBI 签名](./wbi.md) | + +`nav` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| img | str | img_key 值 | 参见 [WBI 签名](./wbi.md) | +| sub | str | sub_key 值 | 参见 [WBI 签名](./wbi.md) | + +**示例:** + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "OK", + "data": { + "ticket": "eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MjM2OTMwODAsImlhdCI6MTcyMzQzMzgyMCwicGx0IjotMX0.efOwv7i4m0ykABrXEDHGAechU2AByMcP_-3EYpQrNKs", + "created_at": 1723433820, + "ttl": 259200, + "context": {}, + "nav": { + "img": "https://i0.hdslb.com/bfs/wbi/7cd084941338484aae1ad9425b84077c.png", + "sub": "https://i0.hdslb.com/bfs/wbi/4932caff0ff746eab6f01bf08b70ac45.png" + } + }, + "ttl": 1 +} +``` + +
+ +## Demo + +此处提供 [Python](#python), [Java](#java), [JavaScript (Node.js)](#javascript-nodejs) 的示例代码 + +### Python + +需要 `requests` 依赖 + +```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() + print(resp) +``` + +### Java + +无需第三方依赖 + +```java +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URI; +import java.nio.charset.StandardCharsets; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +public class BiliTicketDemo { + + /** + * Convert a byte array to a hex string. + * + * @param bytes The byte array to convert. + * @return The hex string representation of the given byte array. + */ + public static String bytesToHex(byte[] bytes) { + StringBuilder sb = new StringBuilder(); + for (byte b : bytes) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + sb.append('0'); + } + sb.append(hex); + } + return sb.toString(); + } + + /** + * Generate a HMAC-SHA256 hash of the given message string using the given key + * string. + * + * @param key The key string to use for the HMAC-SHA256 hash. + * @param message The message string to hash. + * @throws Exception If an error occurs during the HMAC-SHA256 hash generation. + * @return The HMAC-SHA256 hash of the given message string using the given key + * string. + */ + public static String hmacSha256(String key, String message) throws Exception { + Mac mac = Mac.getInstance("HmacSHA256"); + SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); + mac.init(secretKeySpec); + byte[] hash = mac.doFinal(message.getBytes(StandardCharsets.UTF_8)); + return bytesToHex(hash); + } + + /** + * Get a Bilibili web ticket for the given CSRF token. + * + * @param csrf The CSRF token to use for the web ticket, can be {@code null} or + * empty. + * @return The Bilibili web ticket raw response for the given CSRF token. + * @throws Exception If an error occurs during the web ticket generation. + * @see https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/misc/sign/bili_ticket.md + */ + public static String getBiliTicket(String csrf) throws Exception { + // params + long ts = System.currentTimeMillis() / 1000; + String hexSign = hmacSha256("XgwSnGZ1p", "ts" + ts); + StringBuilder url = new StringBuilder( + "https://api.bilibili.com/bapis/bilibili.api.ticket.v1.Ticket/GenWebTicket"); + url.append('?'); + url.append("key_id=ec02").append('&'); + url.append("hexsign=").append(hexSign).append('&'); + url.append("context[ts]=").append(ts).append('&'); + url.append("csrf=").append(csrf == null ? "" : csrf); + // request + HttpURLConnection conn = (HttpURLConnection) new URI(url.toString()).toURL().openConnection(); + conn.setRequestMethod("POST"); + conn.addRequestProperty("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0"); + InputStream in = conn.getInputStream(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int b; + while ((b = in.read()) != -1) { + out.write(b); + } + return new String(out.toByteArray(), StandardCharsets.UTF_8); + } + + /** + * Main method to test the BiliTicketDemo class. + * + * @param args The command line arguments (not used). + */ + public static void main(String[] args) { + try { + System.out.println(getBiliTicket("")); // use empty CSRF here + } catch (Exception e) { + e.printStackTrace(); + } + } + +} +``` + +### JavaScript (Node.js) + +```javascript +const crypto = require('crypto'); + +/** + * Generate HMAC-SHA256 signature + * @param {string} key The key string to use for the HMAC-SHA256 hash + * @param {string} message The message string to hash + * @returns {string} The HMAC-SHA256 signature as a hex string + */ +function hmacSha256(key, message) { + const hmac = crypto.createHmac('sha256', key); + hmac.update(message); + return hmac.digest('hex'); +} + +/** + * Get Bilibili web ticket + * @param {string} csrf CSRF token, can be empty or null + * @returns {Promise} Promise of the ticket response in JSON format + */ +async function getBiliTicket(csrf) { + const ts = Math.floor(Date.now() / 1000); + const hexSign = hmacSha256('XgwSnGZ1p', `ts${ts}`); + const url = 'https://api.bilibili.com/bapis/bilibili.api.ticket.v1.Ticket/GenWebTicket'; + const params = new URLSearchParams({ + key_id: 'ec02', + hexsign: hexSign, + 'context[ts]': ts, + csrf: csrf || '' + }); + const response = await fetch(`${url}?${params.toString()}`, { + method: 'POST', + headers: { + 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0' + } + }); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return response.json(); +} + +(async () => { + try { + const ticketResponse = await getBiliTicket(''); // use empty CSRF here + console.log(ticketResponse); + } catch (e) { + console.error('Failed to get BiliTicket:', e); + } +})(); +``` diff --git a/bb-api-collect/docs/misc/sign/v_voucher.md b/bb-api-collect/docs/misc/sign/v_voucher.md new file mode 100644 index 0000000000..3804c80083 --- /dev/null +++ b/bb-api-collect/docs/misc/sign/v_voucher.md @@ -0,0 +1,179 @@ +# v_voucher 验证 + +## 简述 + +当同一接口在短时间内被同一用户/IP/UA多次请求或异常时, 会触发风控, 如接口返回 `code` 为 `-352` 即 `风控校验失败`, 同时 `data` 中出现 `v_voucher` 字段, 响应头出现 `x-bili-gaia-vvoucher` + +`v_voucher` 结构为字符串 `voucher_` 尾随一串以 `-` 为分隔符的小写 UUID + +`v_voucher` 可用于申请 captcha 验证码, 若无意外发生, 根据验证结果使用 `validate` 接口获取 `grisk_id` 作为被风控接口的 `gaia_vtoken` 与 Cookie 中的 `x-bili-gaia-vtoken`, 即可恢复正常访问 + +若该情况出现在使用 Wbi 签名的接口中, 建议先检查 Wbi 签名是否正确. 若已检查 Wbi 签名或无需签名, 检查请求头中 `User-Agent` `Referer` 是否正常, 以及 `Cookie` 中 [`bili_ticket`](bili_ticket.md) [`b_nut` `buvid3` `buvid4`](../buvid3_4.md) 等是否存在. 使用 captcha 是最后的选择, 因为 captcha 验证需要用户操作 + +参见 [#1067](https://github.com/SocialSisterYi/bilibili-API-collect/issues/1067) + +**注意: 不是所有风控都可以使用本方式通过 captcha 解决** + +## 操作流程 + +1. 快速以不正确的姿势请求接口, 直到返回 `v_voucher` 字段如下. 若 `data` 中没有 `v_voucher` 字段, 则检查响应头 `x-bili-gaia-vvoucher` + + ```json + { + "code": -352, + "message": "风控校验失败", + "ttl": 1, + "data": { + "v_voucher": "voucher_84a8c3ce-33f5-4551-9552-9c6b13aa7938" + } + } + ``` + +2. [请求 `register` 接口](#从-v_voucher-申请-captcha), 请求体传入 `csrf` 及 `v_voucher`, 该接口返回与 [申请captcha验证码](../../login/login_action/readme.md#申请captcha验证码) 部分相同, 记录此处返回的 `token` `challenge` + +3. 按照 [验证captcha验证码](../../login/login_action/readme.md#验证captcha验证码) 进行验证, 记下验证结果的 `validate` 与 `seccode` + +4. [请求 `validate` 接口](#从验证结果获取-grisk_id), 请求体传入 `challenge` `token` `validate` `seccode` `csrf`, 该接口返回 `grisk_id` 即 `gaia_vtoken` 与 `x-bili-gaia-vtoken` + +5. 重新请求原接口, 原 URL 参数加入 `gaia_vtoken`, Cookie 加入 `x-bili-gaia-vtoken`, 即恢复正常 + +## 接口列表 + +### 从 v_voucher 申请 captcha + +> https://api.bilibili.com/x/gaia-vgate/v1/register + +注: 同一有效 `v_voucher` 只能请求一次, 请求完毕请立即 [进行验证](../../login/login_action/readme.md#进行验证) 防止过期失效 + +*请求方式: POST* + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------- | ------ | ---- | +| csrf | str | CSRF Token (位于 Cookie 的 bili_jct) | 非必要 | | +| v_voucher | str | v_voucher | 必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ------ | ---- | +| code | num | 返回值 | 0:成功
100000: 验证码获取失败 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ------ | ---- | +| type | str | 验证码类型 | 目前只有 `geetest` | +| token | str | 验证码 token | 用于验证 | +| geetest | obj | 极验信息 | 若为 null 则说明该风控无法通过 captcha 解除 | +| biliword | null | | | +| phone | null | | | +| sms | null | | | + +`geetest` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ----- | ------ | -------- | +| gt | str | 极验id | 一般为固定值 | +| challenge | str | 极验KEY | 由B站后端产生用于人机验证 | + +**示例:** + +假设此处 `v_voucher` 为 `voucher_ecca35e6-36da-4f38-bd84-b3f420ea08c1` + +```shell +curl -X POST "https://api.bilibili.com/x/gaia-vgate/v1/register" \ +--data-urlencode "v_voucher=voucher_ecca35e6-36da-4f38-bd84-b3f420ea08c1" +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "type": "geetest", + "token": "e7abdb050c3d4609979f1685137e3bc0", + "geetest": { + "challenge": "85118f8714875ca4c6d5641bb0ce9ddf", + "gt": "ac597a4506fee079629df5d8b66dd4fe" + }, + "biliword": null, + "phone": null, + "sms": null + } +} +``` + +
+ +## 从验证结果获取 grisk_id + +> https://api.bilibili.com/x/gaia-vgate/v1/validate + +*请求方式: POST* + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------ | ---- | ---- | +| csrf | str | CSRF Token (位于 Cookie 的 bili_jct) | 非必要 | 若登陆则必要 | +| challenge | str | 验证码 challenge | 必要 | | +| token | str | 验证码 token | 必要 | | +| validate | str | 验证结果 validate | 必要 | | +| seccode | str | 验证结果 seccode | 必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ------ | ---- | +| code | num | 返回值 | 0:成功
-111: csrf 校验失败
100003: 验证码过期 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ------ | ---- | +| is_valid | num | 验证结果 | 1:验证成功 | +| grisk_id | str | gaia_vtoken | 用于恢复正常访问 | + +**示例:** + +```shell +curl -X POST "https://api.bilibili.com/x/gaia-vgate/v1/validate" \ +--data-urlencode "challenge=e4fcb337b8c0427b56320f97e1064210" \ +--data-urlencode "csrf=xxxxxxxxxxxxxxx" \ +--data-urlencode "seccode=360f7b9cf75c74c68fbb7475416d0e0d|jordan" \ +--data-urlencode "token=0e1e58bdff3d4b8aa298e346fed07eeb" \ +--data-urlencode "validate=360f7b9cf75c74c68fbb7475416d0e0d" +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "is_valid": 1, + "grisk_id": "2e91cf2b67172ca8432fe7c9ab66a5c4" + } +} +``` + +
diff --git a/bb-api-collect/docs/misc/sign/wbi.md b/bb-api-collect/docs/misc/sign/wbi.md new file mode 100644 index 0000000000..a28a204ec0 --- /dev/null +++ b/bb-api-collect/docs/misc/sign/wbi.md @@ -0,0 +1,1481 @@ +# 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`](v_voucher.md),如: + +```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)。 + +最新进展: [#919](https://github.com/SocialSisterYi/bilibili-API-collect/issues/919) + +## WBI 签名算法 + +1. 获取实时口令 `img_key`、`sub_key` + + 从 [nav 接口](../../login/login_info.md#导航栏用户信息) 中获取 `img_url`、`sub_url` 两个字段的参数。 + 或从 [bili_ticket 接口](bili_ticket.md#接口) 中获取 `img` `sub` 两个字段的参数。 + + **注:`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`,暂不清楚原因及影响。 + 同时, 部分页面会在 SSR 的 `__INITIAL_STATE__` 包含 `wbiImgKey` 与 `wbiSubKey`, 具体可用性与区别尚不明确 + +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::>(); + 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` 约定编码为 `+`), 具体正确行为可参考 [encodeURIComponent 函数](https://tc39.es/ecma262/multipage/global-object.html#sec-encodeuricomponent-uricomponent) + + 例如: + + ```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)、[Kotlin](#kotlin)、[Swift](#swift)、[C++](#cplusplus)、[Rust](#rust)、[Haskell](#haskell) 语言编写的 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' + headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3', + 'Referer': 'https://www.bilibili.com/' + } + resp = requests.get('https://api.bilibili.com/x/web-interface/nav', headers=headers) + 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 + +需要 `fetch`(浏览器、NodeJS等环境自带)、`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', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3', + Referer: 'https://www.bilibili.com/'//对于直接浏览器调用可能不适用 + } + }) + 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() +``` + + + + + +```typescript +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: string) => + mixinKeyEncTab + .map((n) => orig[n]) + .join("") + .slice(0, 32); + +// 为请求参数进行 wbi 签名 +function encWbi( + params: { [key: string]: string | number | object }, + img_key: string, + sub_key: string +) { + 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(SESSDATA: string) { + const res = await fetch('https://api.bilibili.com/x/web-interface/nav', { + headers: { + // SESSDATA 字段 + Cookie: `SESSDATA=${SESSDATA}`, + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3', + Referer: 'https://www.bilibili.com/'//对于直接浏览器调用可能不适用 + } + }) + const { + data: { + wbi_img: { img_url, sub_url }, + }, + } = (await res.json()) as { + data: { + wbi_img: { img_url: string; sub_url: string }; + }; + }; + + 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("SESSDATA的值") + 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 + +无第三方库 + +```go +package main + +import ( + "bytes" + "crypto/md5" + "encoding/hex" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "strconv" + "strings" + "time" +) + +func main() { + u, err := url.Parse("https://api.bilibili.com/x/space/wbi/acc/info?mid=1850091") + if err != nil { + panic(err) + } + fmt.Printf("orig: %s\n", u.String()) + err = Sign(u) + if err != nil { + panic(err) + } + fmt.Printf("signed: %s\n", u.String()) + + // 获取 wbi 时未修改 header + // 但实际使用签名后的 url 时发现风控较为严重 +} + +// Sign 为链接签名 +func Sign(u *url.URL) error { + return wbiKeys.Sign(u) +} + +// Update 无视过期时间更新 +func Update() error { + return wbiKeys.Update() +} + +func Get() (wk WbiKeys, err error) { + if err = wk.update(false); err != nil { + return WbiKeys{}, err + } + return wbiKeys, nil +} + +var wbiKeys WbiKeys + +type WbiKeys struct { + Img string + Sub string + Mixin string + lastUpdateTime time.Time +} + +// Sign 为链接签名 +func (wk *WbiKeys) Sign(u *url.URL) (err error) { + if err = wk.update(false); err != nil { + return err + } + + values := u.Query() + + values = removeUnwantedChars(values, '!', '\'', '(', ')', '*') // 必要性存疑? + + values.Set("wts", strconv.FormatInt(time.Now().Unix(), 10)) + + // [url.Values.Encode] 内会对参数排序, + // 且遍历 map 时本身就是无序的 + hash := md5.Sum([]byte(values.Encode() + wk.Mixin)) // Calculate w_rid + values.Set("w_rid", hex.EncodeToString(hash[:])) + u.RawQuery = values.Encode() + return nil +} + +// Update 无视过期时间更新 +func (wk *WbiKeys) Update() (err error) { + return wk.update(true) +} + +// update 按需更新 +func (wk *WbiKeys) update(purge bool) error { + if !purge && time.Since(wk.lastUpdateTime) < time.Hour { + return nil + } + + // 测试下来不用修改 header 也能过 + resp, err := http.Get("https://api.bilibili.com/x/web-interface/nav") + if err != nil { + return err + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + nav := Nav{} + err = json.Unmarshal(body, &nav) + if err != nil { + return err + } + + if nav.Code != 0 && nav.Code != -101 { // -101 未登录时也会返回两个 key + return fmt.Errorf("unexpected code: %d, message: %s", nav.Code, nav.Message) + } + img := nav.Data.WbiImg.ImgUrl + sub := nav.Data.WbiImg.SubUrl + if img == "" || sub == "" { + return fmt.Errorf("empty image or sub url: %s", body) + } + + // https://i0.hdslb.com/bfs/wbi/7cd084941338484aae1ad9425b84077c.png + imgParts := strings.Split(img, "/") + subParts := strings.Split(sub, "/") + + // 7cd084941338484aae1ad9425b84077c.png + imgPng := imgParts[len(imgParts)-1] + subPng := subParts[len(subParts)-1] + + // 7cd084941338484aae1ad9425b84077c + wbiKeys.Img = strings.TrimSuffix(imgPng, ".png") + wbiKeys.Sub = strings.TrimSuffix(subPng, ".png") + + wbiKeys.mixin() + wbiKeys.lastUpdateTime = time.Now() + return nil +} + +func (wk *WbiKeys) mixin() { + var mixin [32]byte + wbi := wk.Img + wk.Sub + for i := range mixin { // for i := 0; i < len(mixin); i++ { + mixin[i] = wbi[mixinKeyEncTab[i]] + } + wk.Mixin = string(mixin[:]) +} + +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, +} + +func removeUnwantedChars(v url.Values, chars ...byte) url.Values { + b := []byte(v.Encode()) + for _, c := range chars { + b = bytes.ReplaceAll(b, []byte{c}, nil) + } + s, err := url.ParseQuery(string(b)) + if err != nil { + panic(err) + } + return s +} + +type Nav struct { + Code int `json:"code"` + Message string `json:"message"` + Ttl int `json:"ttl"` + Data struct { + WbiImg struct { + ImgUrl string `json:"img_url"` + SubUrl string `json:"sub_url"` + } `json:"wbi_img"` + + // ...... + } `json:"data"` +} +``` + +### 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 EncWbi(Dictionary 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() + { + var httpClient = new HttpClient(); + httpClient.DefaultRequestHeaders.Add("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"); + httpClient.DefaultRequestHeaders.Referrer = new Uri("https://www.bilibili.com/"); + + 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 signedParams = EncWbi( + parameters: new Dictionary + { + { "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 + +```java +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.*; +import java.util.stream.Collectors; + +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 + }; + + private static final char[] hexDigits = "0123456789abcdef".toCharArray(); + + public static String md5(String input) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] messageDigest = md.digest(input.getBytes(StandardCharsets.UTF_8)); + char[] result = new char[messageDigest.length * 2]; + for (int i = 0; i < messageDigest.length; i++) { + result[i * 2] = hexDigits[(messageDigest[i] >> 4) & 0xF]; + result[i * 2 + 1] = hexDigits[messageDigest[i] & 0xF]; + } + return new String(result); + } catch (NoSuchAlgorithmException e) { + return null; + } + } + + 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 String encodeURIComponent(Object o) { + return URLEncoder.encode(o.toString(), StandardCharsets.UTF_8).replace("+", "%20"); + } + + public static void main(String[] args) { + String imgKey = "653657f524a547ac981ded72ea172057"; + String subKey = "6e4909c702f846728e64f6007736a338"; + String mixinKey = getMixinKey(imgKey, subKey); + System.out.println(mixinKey); // 72136226c6a73669787ee4fd02a74c27 + + // 用TreeMap自动排序 + TreeMap map = new TreeMap<>(); + map.put("foo", "one one four"); + map.put("bar", "五一四"); + map.put("baz", 1919810); + map.put("wts", System.currentTimeMillis() / 1000); + String param = map.entrySet().stream() + .map(it -> String.format("%s=%s", it.getKey(), encodeURIComponent(it.getValue()))) + .collect(Collectors.joining("&")); + String s = param + mixinKey; + + String wbiSign = md5(s); + System.out.println(wbiSign); + String finalParam = param + "&w_rid=" + wbiSign; + System.out.println(finalParam); + } +} +``` + +### Kotlin + +说明: 为了便于使用和缓存, 重新编写为实体类形式, 并拆分了多个文件. 使用官方的JSON序列化. (可以根据需要换成其他的) + +WbiParams.kt + +```kotlin +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.jsonPrimitive + +private fun JsonElement?.get(): String { + check(this != null) { "No contents found" } + return this.jsonPrimitive.content.split('/').last().removeSuffix(".png") +} + +private val mixinKeyEncTab = intArrayOf( + 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 +) + +@Serializable +data class WbiParams( + val imgKey: String, + val subKey: String, +) { + // 此处整合了切分参数(直接传入{img_url:string, sub_url:string}即可), 不需要可以删掉 + constructor(wbiImg: JsonObject) : this(wbiImg["img_url"].get(), wbiImg["sub_url"].get()) + + private val mixinKey: String + get() = (imgKey + subKey).let { s -> + buildString { + repeat(32) { + append(s[mixinKeyEncTab[it]]) + } + } + } + + // 创建对象(GET获取或者读缓存, 比如Redis)之后, 直接调用此函数处理 + fun enc(params: Map): String { + val sorted = params.filterValues { it != null }.toSortedMap() + return buildString { + append(sorted.toQueryString()) + val wts = System.currentTimeMillis() / 1000 + sorted["wts"] = wts + append("&wts=") + append(wts) + append("&w_rid=") + append((sorted.toQueryString() + mixinKey).toMD5()) + } + } +} +``` + +Extensions.kt + +```kotlin +import java.security.MessageDigest + +private val hexDigits = "0123456789abcdef".toCharArray() + +fun ByteArray.toHexString() = buildString(this.size shl 1) { + this@toHexString.forEach { byte -> + append(hexDigits[byte.toInt() ushr 4 and 15]) + append(hexDigits[byte.toInt() and 15]) + } +} + +fun String.toMD5(): String { + val md = MessageDigest.getInstance("MD5") + val digest = md.digest(this.toByteArray()) + return digest.toHexString() +} + +fun Map.toQueryString() = this.filterValues { it != null }.entries.joinToString("&") { (k, v) -> + "${k.encodeURIComponent()}=${v!!.encodeURIComponent()}" +} +``` + +获取和使用案例略 + +### PHP + +来自[SocialSisterYi/bilibili-API-collect#813](https://github.com/SocialSisterYi/bilibili-API-collect/issues/813) + +```php +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[]="Referer:https://www.bilibili.com/"; + $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() + .take(32) + .map(|&i| orig[i] as char) + .collect::() +} + +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::() +} + +// 为请求参数进行 wbi 签名 +fn encode_wbi(params: Vec<(&str, String)>, (img_key, sub_key): (String, String)) -> String { + let cur_time = match SystemTime::now().duration_since(UNIX_EPOCH) { + Ok(t) => t.as_secs(), + Err(_) => panic!("SystemTime before UNIX EPOCH!"), + }; + _encode_wbi(params, (img_key, sub_key), cur_time) +} + +fn _encode_wbi( + mut params: Vec<(&str, String)>, + (img_key, sub_key): (String, String), + timestamp: u64, +) -> String { + let mixin_key = get_mixin_key((img_key + &sub_key).as_bytes()); + // 添加当前时间戳 + params.push(("wts", timestamp.to_string())); + // 重新排序 + params.sort_by(|a, b| a.0.cmp(b.0)); + // 拼接参数 + let query = params + .iter() + .map(|(k, v)| format!("{}={}", get_url_encoded(k), get_url_encoded(v))) + .collect::>() + .join("&"); + // 计算签名 + let web_sign = format!("{:?}", md5::compute(query.clone() + &mixin_key)); + // 返回最终的 query + 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") + .header("Referer","https://www.bilibili.com/") + // SESSDATA=xxxxx + .header("Cookie", "SESSDATA=xxxxx") + .send() + .await? + .json::() + .await?; + Ok(( + take_filename(wbi_img.img_url).unwrap(), + take_filename(wbi_img.sub_url).unwrap(), + )) +} + +fn take_filename(url: String) -> Option { + url.rsplit_once('/') + .and_then(|(_, s)| s.rsplit_once('.')) + .map(|(s, _)| s.to_string()) +} + +#[tokio::main] +async fn main() { + let keys = get_wbi_keys().await.unwrap(); + let params = vec![ + ("foo", String::from("114")), + ("bar", String::from("514")), + ("baz", String::from("1919810")), + ]; + let query = encode_wbi(params, keys); + println!("{}", query); +} + +// 取自文档描述的测试用例 +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_get_filename() { + assert_eq!( + take_filename( + "https://i0.hdslb.com/bfs/wbi/7cd084941338484aae1ad9425b84077c.png".to_string() + ), + Some("7cd084941338484aae1ad9425b84077c".to_string()) + ); + } + + #[test] + fn test_get_mixin_key() { + let concat_key = + "7cd084941338484aae1ad9425b84077c".to_string() + "4932caff0ff746eab6f01bf08b70ac45"; + assert_eq!( + get_mixin_key(concat_key.as_bytes()), + "ea1db124af3c7062474693fa704f4ff8" + ); + } + + #[test] + fn test_encode_wbi() { + let params = vec![ + ("foo", String::from("114")), + ("bar", String::from("514")), + ("zab", String::from("1919810")), + ]; + assert_eq!( + _encode_wbi( + params, + ( + "7cd084941338484aae1ad9425b84077c".to_string(), + "4932caff0ff746eab6f01bf08b70ac45".to_string() + ), + 1702204169 + ), + "bar=514&foo=114&wts=1702204169&zab=1919810&w_rid=8f6f2b5b3d485fe1886cec6a0be8c5d4" + .to_string() + ) + } +} +``` + +### Swift + +需要 [Alamofire](https://github.com/Alamofire/Alamofire) 和 [SwiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON) 库 + +```swift +import Alamofire +import CommonCrypto +import Foundation +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 = Int(Date().timeIntervalSince1970) + params["wts"] = currTime + let query = params.sorted { + $0.key < $1.key + }.map { (key, value) -> String in + let stringValue: String + if let doubleValue = value as? Double, doubleValue.truncatingRemainder(dividingBy: 1) == 0 { + stringValue = String(Int(doubleValue)) + } else { + stringValue = String(describing: value) + } + let filteredValue = stringValue.filter { !"!'()*".contains($0) } + return "\(key)=\(filteredValue)" + }.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) { + let headers: HTTPHeaders = [ + "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", + "Referer": "https://www.bilibili.com/" + ] + + AF.request("https://api.bilibili.com/x/web-interface/nav", headers: headers).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]() + for pair in spdParam { + 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) + } + } +} + +// 使用示例 +biliWbiSign(param: "bar=514&foo=114&zab=1919810") { + signedQuery in + if let signedQuery = signedQuery { + print("签名后的参数: \(signedQuery)") + } else { + print("签名失败") + } +} + +RunLoop.main.run()//程序类型为命令行程序时需要添加这行代码 + +``` + +```text +签名后的参数: bar=514&wts=1741082093&foo=114&zab=1919810&w_rid=04775bb3debbb45bab86a93a1c08d12a +``` + + +### CPlusPlus + +需要 c++ 23 标准库,[cpr](https://github.com/libcpr/cpr)、[cryptopp](https://github.com/weidai11/cryptopp)、[nlohmann/json](https://github.com/nlohmann/json) 等依赖 + +```c++ +#include // std::array +#include // std::locale +#include // std::println + +/// thrid party libraries +#include +#include +#include +#include + +/* + * 注意,假定不会发生错误! + */ +class Wbi { + constexpr static std::array MIXIN_KEY_ENC_TAB_ = { + 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 + }; + + /* 获取 md5 hex(lower) */ + static std::string Get_md5_hex(const std::string &Input_str) { + CryptoPP::Weak1::MD5 hash; + std::string md5_hex; + + CryptoPP::StringSource ss(Input_str, true, + new CryptoPP::HashFilter(hash, + new CryptoPP::HexEncoder( + new CryptoPP::StringSink(md5_hex) + ) + ) + ); + + std::ranges::for_each(md5_hex, [](char &x) { x = std::tolower(x); }); + return md5_hex; + } + +public: + /* 将 json 转换为 url 编码字符串 */ + static std::string Json_to_url_encode_str(const nlohmann::json &Json) { + std::string encode_str; + for (const auto &[key, value]: Json.items()) { + encode_str.append(key).append("=").append(cpr::util::urlEncode(value.is_string() ? value.get() : to_string(value))).append("&"); + } + + // remove the last '&' + encode_str.resize(encode_str.size() - 1, '\0'); + return encode_str; + } + + /* 获取 wbi key */ + static std::pair Get_wbi_key() { + const auto url = cpr::Url {"https://api.bilibili.com/x/web-interface/nav"}; + const auto cookie = cpr::Cookies { + {"SESSDATA", "xxxxxxxxxxxx"}, + }; + const auto header = cpr::Header { + {"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"}, + {"Referer", "https://www.bilibili.com/"}, + }; + const auto response = cpr::Get(url, cookie, header); + + nlohmann::json json = nlohmann::json::parse(response.text); + + const std::string img_url = json["data"]["wbi_img"]["img_url"]; + const std::string sub_url = json["data"]["wbi_img"]["sub_url"]; + + std::string img_key = img_url.substr(img_url.find("wbi/") + 4, img_url.find(".png") - img_url.find("wbi/") - 4); + std::string sub_key = sub_url.substr(sub_url.find("wbi/") + 4, sub_url.find(".png") - sub_url.find("wbi/") - 4); + return {img_key, sub_key}; + } + + /* 获取 mixin key */ + static std::string Get_mixin_key(const std::string &Img_key, const std::string &Sub_key) { + std::string raw_wbi_key_str = Img_key + Sub_key; + std::string result; + + std::ranges::for_each(MIXIN_KEY_ENC_TAB_, [&result, &raw_wbi_key_str](const uint8_t x) { + result.push_back(raw_wbi_key_str.at(x)); + }); + + return result.substr(0, 32); + } + + /* 计算签名(w_rid) */ + static std::string Calc_sign(nlohmann::json &Params, const std::string &Mixin_key) { + Params["wts"] = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + + const std::string encode_str = Json_to_url_encode_str(Params).append(Mixin_key); + return Get_md5_hex(encode_str); + } +}; + + +int main() { + nlohmann::json Params; + // qn=32&fnver=0&fnval=4048&fourk=1&avid=1755630705&cid=1574294582 + Params["qn"] = 32; + Params["fnver"] = 0; + Params["fnval"] = 4048; + Params["fourk"] = 1; + Params["avid"] = 1755630705; + Params["cid"] = 1574294582; + + auto [img_key, sub_key] = Wbi::Get_wbi_key(); + const auto mixin_key = Wbi::Get_mixin_key(img_key, sub_key); + const auto w_rid = Wbi::Calc_sign(Params, mixin_key); + std::println("{}", Wbi::Json_to_url_encode_str(Params) + "&w_rid=" + w_rid); +} +``` + +```text +avid=1755630705&cid=1574294582&fnval=4048&fnver=0&fourk=1&qn=32&wts=1717922933&w_rid=43571b838a1611fa121189083cfc1784 +``` + +### Haskell + +无第三方依赖: `base`, `Cabal-syntax`, `bytestring`, `containers`
+注: 此处使用自写的 URI 编码模块, 实际可用别的第三方库替代 + +`Main.hs`: +```hs +module Main (wbi, main) where + +import Data.ByteString.Char8 (pack) +import qualified Data.Map.Strict as Map +import Distribution.Utils.MD5 (md5, showMD5) +import URIEncoder (encodeURIComponent) +import Data.Time.Clock.System (getSystemTime, systemSeconds) + +mixinKeyEncTab :: [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 + ] + +getMixinKey :: String -> String -> String +getMixinKey imgKey subKey = + let s = imgKey ++ subKey + in map (\i -> s !! (mixinKeyEncTab !! i)) [0..31] + +join :: [String] -> String -> String +join arr ins = concatMap (++ ins) (init arr) ++ last arr + +wbi :: String -> String -> Integer -> Map.Map String String -> String +wbi imgKey subKey wts params = + let orig = join (map (\(k, v) -> encodeURIComponent k ++ "=" ++ encodeURIComponent v) (Map.toList $ Map.insert "wts" (show wts) params)) "&" + in orig ++ "&w_rid=" ++ showMD5 (md5 $ pack $ orig ++ getMixinKey imgKey subKey) + +main :: IO () +main = do -- hard encode for test + let params1 = Map.fromList [("aid", "2")] + params2 = Map.fromList [("foo", "114") + ,("bar", "514") + ,("hello", "世 界") + ] + imgKey = "7cd084941338484aae1ad9425b84077c" + subKey = "4932caff0ff746eab6f01bf08b70ac45" + wts1 <- getSystemTime + putStrLn $ wbi imgKey subKey (toInteger $ systemSeconds wts1) params1 + wts2 <- getSystemTime + putStrLn $ wbi imgKey subKey (toInteger $ systemSeconds wts2) params2 +``` + +`URIEncoder.hs`: +```hs +module URIEncoder (encodeURIComponent) where + +import Data.Char (ord, chr, intToDigit) +import Data.Bits (shiftL, shiftR, (.&.)) +import Data.List (isInfixOf) + +-- ES 19.2.6.4 encodeURIComponent ( uriComponent ) +encodeURIComponent :: String -> String +encodeURIComponent input = case encode input "" of + Right result -> result + Left err -> error err + +-- ES 19.2.6.5 Encode ( string, extraUnescaped ) +encode :: String -> String -> Either String String +encode string extraUnescaped = loop 0 string + where + alwaysUnescaped = ['A'..'Z'] ++ ['a'..'z'] ++ ['0'..'9'] ++ "-.!~*'()" + unescapedSet = alwaysUnescaped ++ extraUnescaped + + loop k str + | k >= length str = Right [] + | otherwise = case codePointAt str k of + (Nothing, _) -> Left "Unpaired surrogate" + (Just (cp, _), newK) -> + if [str !! k] `isInfixOf` unescapedSet + then (str !! k :) <$> loop (k + 1) str + else do + bytes <- utf8Encode cp + let escaped = concatMap percentEncode bytes + rest <- loop newK str + Right (escaped ++ rest) + +codePointAt :: String -> Int -> (Maybe (Int, Int), Int) +codePointAt s k + | k >= length s = (Nothing, k) + | otherwise = + let c1 = ord (s !! k) + in if 0xD800 <= c1 && c1 <= 0xDBFF && k+1 < length s + then let c2 = ord (s !! (k+1)) + in if 0xDC00 <= c2 && c2 <= 0xDFFF + then ( Just (0x10000 + ((c1 - 0xD800) `shiftL` 10) + (c2 - 0xDC00), 2) + , k + 2 ) + else (Just (c1, 1), k + 1) + else (Just (c1, 1), k + 1) + +utf8Encode :: Int -> Either String [Int] +utf8Encode cp + | cp < 0 = Left "Invalid code point" + | cp <= 0x007F = Right [cp] + | cp <= 0x07FF = Right + [ 0xC0 + (cp `shiftR` 6) + , 0x80 + (cp .&. 0x3F) ] + | cp <= 0xFFFF = Right + [ 0xE0 + (cp `shiftR` 12) + , 0x80 + ((cp `shiftR` 6) .&. 0x3F) + , 0x80 + (cp .&. 0x3F) ] + | cp <= 0x10FFFF = Right + [ 0xF0 + (cp `shiftR` 18) + , 0x80 + ((cp `shiftR` 12) .&. 0x3F) + , 0x80 + ((cp `shiftR` 6) .&. 0x3F) + , 0x80 + (cp .&. 0x3F) ] + | otherwise = Left "Code point out of range" + +percentEncode :: Int -> String +percentEncode byte = '%' : toHex byte + where + toHex n = [hexDigit (n `div` 16), hexDigit (n `mod` 16)] + hexDigit x + | x < 10 = intToDigit x + | otherwise = chr (x - 10 + ord 'A') +``` + +输出: +```text +aid=2&wts=1744823207&w_rid=a3cd246bd42c066932752b24694eaf0d +bar=514&foo=114&hello=%E4%B8%96%20%E7%95%8C&wts=1744823207&w_rid=93acf59d85f74453e40cea00056c3daf +``` diff --git a/bb-api-collect/docs/misc/time_stamp.md b/bb-api-collect/docs/misc/time_stamp.md new file mode 100644 index 0000000000..58e07097df --- /dev/null +++ b/bb-api-collect/docs/misc/time_stamp.md @@ -0,0 +1,127 @@ +# 获取当前时间戳 + +## 获取当前时间戳 + +> https://api.bilibili.com/x/report/click/now +> https://api.bilibili.com/x/click-interface/click/now + +*请求方式:GET* + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------ | ---- | +| now | num | 当前的时间戳 | | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/report/click/now' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "now": 1592666471 + } +} +``` + +
+ +## 获取适用于 RTC 的时间戳 + +> https://api.live.bilibili.com/xlive/open-interface/v1/rtc/getTimestamp + +*请求方法: GET* + + + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | - | - | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | - | - | +| timestamp | num | 服务器端UTC时间戳 | | +| microtime | num | 服务器端UTC时间戳 (毫秒) | | + +**示例:** + +```shell +curl 'https://api.live.bilibili.com/xlive/open-interface/v1/rtc/getTimestamp' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "timestamp": 1723899823, + "microtime": 1723899823683 + } +} +``` + +
+ +## 获取服务器端UTC时间 + +> https://interface.bilibili.com/serverdate.js + +*请求方式:GET* + +**js回复:** + +```js +window.serverdate = Date.UTC(YYYY, M, D, h, m, s); +``` + +**示例:** + +```shell +curl 'https://interface.bilibili.com/serverdate.js' +``` + +
+查看响应示例: + +```js +window.serverdate = Date.UTC(2021, 4, 16, 17, 31, 8); +``` + +
diff --git a/bb-api-collect/docs/newbie_exam/action.md b/bb-api-collect/docs/newbie_exam/action.md new file mode 100644 index 0000000000..d75967a0a0 --- /dev/null +++ b/bb-api-collect/docs/newbie_exam/action.md @@ -0,0 +1,445 @@ +# 操作 + +## 提交答题 + +### 提交基础题 + +> https://api.bilibili.com/x/answer/v4/base/check + +*请求方式:POST* + +认证方式:APP或Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----------- | ---- | ------------------------ | -------------- | ------------------------------------------ | +| question_id | num | 题目id | 必要 | 从[拉取基础题api](fetch.md#拉取基础题)获得 | +| ans_hash | str | 选项hash | 必要 | 从[拉取基础题api](fetch.md#拉取基础题)获得 | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误
41014:答题过快或错误太多
41012:用户答题提交题目id不合法
41020:用户基础题已通过
41023:用户答题记录不存在 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ------------ | ----------------------------------- | +| passed | bool | 选项是否正确 | true:选项正确
false:选项错误 | + +**示例:** + +提交题目id为`104`的题,选项hash为`cb4c8cc9424fc771f7c1598e74de498f` + +```shell +curl 'https://api.bilibili.com/x/answer/v4/base/check' \ +--data-urlencode 'question_id=104' \ +--data-urlencode 'ans_hash=cb4c8cc9424fc771f7c1598e74de498f' \ +--data-urlencode 'csrf=xxxx' \ +-b 'SESSDATA=xxxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "passed": true + } +} +``` + +
+ +### 提交附加题 + +> https://api.bilibili.com/x/answer/v4/base/check + +*请求方式:POST* + +认证方式:APP或Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----------- | ---- | ------------------------ | -------------- | ------------------------------------------ | +| question_id | num | 题目id | 必要 | 从[拉取基础题api](fetch.md#拉取基础题)获得 | +| ans_hash | str | 选项hash | 必要 | 从[拉取基础题api](fetch.md#拉取基础题)获得 | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误
41014:答题过快或错误太多
41012:用户答题提交题目id不合法
41023:用户答题记录不存在 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ------------ | ----------------------------------- | +| passed | bool | 选项是否正确 | true:选项正确
false:选项错误 | + +**示例:** + +提交题目id为`104`的题,选项hash为`cb4c8cc9424fc771f7c1598e74de498f` + +```shell +curl 'https://api.bilibili.com/x/answer/v4/base/check' \ +--data-urlencode 'question_id=104' \ +--data-urlencode 'ans_hash=cb4c8cc9424fc771f7c1598e74de498f' \ +--data-urlencode 'csrf=xxxx' \ +-b 'SESSDATA=xxxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "passed": true + } +} +``` + +
+ +### 提交自选题 + +> https://api.bilibili.com/x/answer/v4/pro/check + +*请求方式:POST* + +认证方式:APP或Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----------- | ---- | ------------------------ | -------------- | ------------------------------------------ | +| question_id | num | 题目id | 必要 | 从[拉取基础题api](fetch.md#拉取基础题)获得 | +| ans_hash | str | 选项hash | 必要 | 从[拉取基础题api](fetch.md#拉取基础题)获得 | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误
41014:答题过快或错误太多
41012:用户答题提交题目id不合法
41023:用户答题记录不存在
41026:获取用户DB题目信息异常 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ---- | ---------- | +| passed | bool | true | 恒为`true` | + +**示例:** + +提交题目id为`2935`的题,选项hash为`ffd55cbe0624f466bee2ea3eb576a4d0` + +```shell +curl -G 'https://api.bilibili.com/x/answer/v4/pro/check' \ +--data-urlencode 'question_id=2935' \ +--data-urlencode 'ans_hash=ffd55cbe0624f466bee2ea3eb576a4d0' \ +--data-urlencode 'csrf=xxxx' \ +-b 'SESSDATA=xxxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "passed": true + } +} +``` + +
+ +## 获取验证码 + +> https://api.bilibili.com/x/answer/v4/captcha + +*请求方式:GET* + +认证方式:APP或Cookie(SESSDATA) + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误
41010:用户答题非法访问
41014:答题过快或错误太多
41020:用户基础题已通过
41021:用户基础题未通过 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ----------- | ------------- | +| type | str | 验证码类型? | geetest:极验 | +| gt | str | 极验id | | +| challenge | str | 极验key | | +| token | str | (?) | | +| url | str | (?) | | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/answer/v4/captcha' \ +-b 'SESSDATA=xxxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "type": "geetest", + "gt": "abc55d1fb914cb110cfb4c232a4b4c35", + "challenge": "90a6e03e626e13ee186ddae0107c3ae2", + "token": "", + "url": "" + } +} +``` + +
+ +## 提交验证码 + +> https://api.bilibili.com/x/answer/v4/captcha/check + +*请求方式:POST* + +认证方式:APP或Cookie(SESSDATA) + +**注:** + +旧版`edition=0`同时提交自选题分类以及验证码 + +新版`edition=2`仅仅提交验证码 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----------------- | ---- | ---------------------- | -------------- | ---------------- | +| types | nums | 自选题分类(旧版) | 非必要 | 新版不需要此字段 | +| type | str | 验证码类型 | 非必要 | | +| bilibili_token | str | | 非必要 | | +| bilibili_code | str | | 非必要 | | +| geetest_challenge | str | 极验key | 非必要 | | +| geetest_seccode | str | 极验结果+\|jordan | 非必要 | | +| geetest_validate | str | 极验结果 | 非必要 | | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-105:验证码错误
-400:请求错误
41010:用户答题非法访问
41014:答题过快或错误太多
41021:用户基础题未通过
41031:自选题未通过 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/answer/v4/captcha/check' \ +--data-urlencode 'types=' \ +--data-urlencode 'type=geetest' \ +--data-urlencode 'bilibili_token=' \ +--data-urlencode 'bilibili_code=' \ +--data-urlencode 'geetest_challenge=3f809a7a9c51edca751fd26c032c182d' \ +--data-urlencode 'geetest_seccode=513ec576a275a3eb250829202d4dce46|jordan' \ +--data-urlencode 'geetest_validate=513ec576a275a3eb250829202d4dce46' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
+ +## 提交自选题分类 + +> https://api.bilibili.com/x/answer/v4/pro/type/check + +*请求方式:POST* + +认证方式:APP或Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---------------------- | -------------- | ---- | +| types | nums | 自选题分类(新版) | 必要 | | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误
41010:用户答题非法访问
41014:答题过快或错误太多
41021:用户基础题未通过
41031:自选题未通过
41052:用户题目类型不合法
41055:基础附加题未通过 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +选择`游戏` `影视` `科教/知识` `动画/动漫`分类 + +```shell +curl 'https://api.bilibili.com/x/answer/v4/pro/type/check' \ +--data-urlencode 'types=1,2,3,4' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
+ +## 提前交卷 + +> https://api.bilibili.com/x/answer/v4/submit + +*请求方式:POST* + +认证方式:APP或Cookie(SESSDATA) + +当当前得分>=60时,可请求本接口提前完成答题 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---------------------- | -------------- | ---- | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误
41014:答题过快或错误太多
41023:用户答题记录不存在
41031:自选题未通过 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ---------------- | -------------------------------------------- | +| hid | num | 答题会话id | | +| mid | num | 答题用户mid | | +| score | num | 得分 | | +| status | num | 0 | | +| number | num | 0 | | +| result | str | succeed | | +| stage | str | result | | +| version | str | 版本 | 目前为`v4` | +| start_time | num | 本次答题开始时间 | 时间戳 | +| first_answer | num | 0 | | +| progress | str | | | +| text | str | | | +| url | str | | | +| in_reg_audit | bool | | | +| edition | num | 答题版本 | 0:旧版(40+10+50)
2:新版(40+30+30) | +| rewards | null | | | +| captcha | num | 1 | | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/answer/v4/submit' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "hid": 1623207905520705, + "mid": 293793435, + "score": 63, + "status": 3, + "number": 0, + "result": "succeed", + "stage": "result", + "version": "v4", + "start_time": 1636889218, + "first_answer": 0, + "progress": "", + "text": "", + "url": "", + "in_reg_audit": false, + "edition": 0, + "rewards": null, + "captcha": 1 + } +} +``` + +
diff --git a/bb-api-collect/docs/newbie_exam/fetch.md b/bb-api-collect/docs/newbie_exam/fetch.md new file mode 100644 index 0000000000..f5fbd747ec --- /dev/null +++ b/bb-api-collect/docs/newbie_exam/fetch.md @@ -0,0 +1,257 @@ +# 拉取题目 + +## 拉取基础题 + +> https://api.bilibili.com/x/answer/v4/base + +*请求方式:GET* + +认证方式:Cookie或APP + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
41014:答题过快或错误太多
41020:用户基础题已通过
41023:用户答题记录不存在 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------- | ---- | +| question | obj | 题目内容 | | + +`data`中的`question`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | ------------------ | ------------------------------------------------------------ | +| id | num | 问题id | **问题id不代表题图,因为选项是打乱的** | +| number | num | 当前题号 | | +| q_height | num | 问题部分总高度 | | +| q_coord_y | num | 问题部分Y裁剪起始 | 当然是0 | +| image | str | 题图url | 题目文字+所有的选项文字排版成一张图,存储在bfs中 | +| from | str | 问题来源页面url | 如:“xx弹幕是否违规”所在的视频页 | +| options | array | 选项列表 | | +| type_id | num | 题目父类型id | 见[查询自选题分类](info.md#查询自选题分类)
**注:36为基础题** | +| type_name | str | 分院小电视提示文案 | 如:xx小电视 | +| type_image | str | 分院小电视图标url | | + +`question`中的`options`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----- | ---------------------- | +| 0 | obj | 选项A | | +| 1 | obj | 选项B | 选项至少2个 | +| 2 | obj | 选项C | 数组长度取决于选项个数 | +| 3 | obj | 选项D | | + +`question`中的`options`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ----------------- | ------------------------ | +| number | num | 选项序号 | 如:1为A 2为B | +| high | num | 选项部分总高度 | | +| coord_y | num | 选项部分Y裁剪起始 | | +| hash | str | 选项hash | 作为提交对应选项时应传参 | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/answer/v4/base' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "question": { + "id": 6511, + "number": 1, + "q_height": 38.4, + "q_coord_y": 0, + "image": "https://i0.hdslb.com/bfs/member/9d7f1f1f0b7478a621d1b998a5a98982.png", + "from": "", + "options": [ + { + "number": 1, + "high": 42, + "coord_y": 38.4, + "hash": "f7619d6c2040d44f39dc87a7aa34fb9e" + }, + { + "number": 2, + "high": 42, + "coord_y": 80.4, + "hash": "dce5140040f40ca4030783585684369d" + } + ], + "type_id": 36, + "type_name": "小电视校长", + "type_image": "https://i0.hdslb.com/bfs/face/7b67c0c0da64a6ab059ff49bb0d4b92988b91806.png" + } + } +} +``` +
+ +## 拉取附加题 + +> https://api.bilibili.com/x/answer/v4/extra + +*请求方式:GET* + +认证方式:Cookie或APP + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
41014:答题过快或错误太多
41021:用户基础题未通过
41023:用户答题记录不存在
41054:用户附加题已通过 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +同[拉取基础题](#拉取基础题)的`data`对象 + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/answer/v4/extra' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "question": { + "id": 11492, + "number": 44, + "q_height": 76.8, + "q_coord_y": 0, + "image": "https://i0.hdslb.com/bfs/member/b6c846613bd0b44cd7c8af1d83e3f0c2.png", + "from": "https://www.bilibili.com/video/av14659093", + "options": [ + { + "number": 1, + "high": 42, + "coord_y": 76.8, + "hash": "ca15e6009047cf82358c50ab90fd8d9e" + }, + { + "number": 2, + "high": 42, + "coord_y": 118.8, + "hash": "60e86a1c736c68da3462f66377e4e8ca" + } + ], + "type_id": 36, + "type_name": "小电视校长", + "type_image": "https://i0.hdslb.com/bfs/face/7b67c0c0da64a6ab059ff49bb0d4b92988b91806.png" + } + } +} +``` +
+ +## 拉取自选题 + +> https://api.bilibili.com/x/answer/v4/pro + +*请求方式:GET* + +认证方式:Cookie或APP + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
41014:答题过快或错误太多
41021:用户基础题未通过
41023:用户答题记录不存在
41051:用户答题验证码未通过
41055:基础附加题未通过 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +同[拉取基础题](#拉取基础题)的`data`对象 + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/answer/v4/pro' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "question": { + "id": 824, + "number": 54, + "q_height": 38.4, + "q_coord_y": 0, + "image": "https://i0.hdslb.com/bfs/member/417e02be5652f79d0312fa2fcee28869.png", + "from": "", + "options": [ + { + "number": 1, + "high": 42, + "coord_y": 38.4, + "hash": "c4574c23cf728c19abeab3e7525258d4" + }, + { + "number": 2, + "high": 42, + "coord_y": 80.4, + "hash": "ffd48760758fbb8a2c183d1d04f692f8" + }, + { + "number": 3, + "high": 42, + "coord_y": 122.4, + "hash": "898d414dff49fe20c4a1da1e148fadb2" + }, + { + "number": 4, + "high": 42, + "coord_y": 164.4, + "hash": "09018443f09d8ef4f6fec5e96e082270" + } + ], + "type_id": 1, + "type_name": "游戏小电视", + "type_image": "https://i0.hdslb.com/bfs/face/6590bee26086fed66ee7cc5bac26a32d2f733037.png" + } + } +} +``` + +
+ diff --git a/bb-api-collect/docs/newbie_exam/info.md b/bb-api-collect/docs/newbie_exam/info.md new file mode 100644 index 0000000000..b200aa4dea --- /dev/null +++ b/bb-api-collect/docs/newbie_exam/info.md @@ -0,0 +1,550 @@ +# 查询信息 + +## 查询答题状态 + +> https://api.bilibili.com/x/answer/v4/status + +*请求方式:GET* + +认证方式:Cookie或APP + +**json回复:** + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
41014:答题过快或错误太多 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ------------------ | ------------------------------------------------------------ | +| hid | num | 答题会话id | | +| mid | num | 答题用户mid | | +| score | num | 当前得分 | | +| status | num | 答题状态 | 0:未答题
2:答题中
3:已通过 | +| number | num | 当前题号 | | +| result | str | 是否通过答题 | failed:未通过
succeed:已通过 | +| stage | str | 当前答题阶段 | base:基础题
extra:附加题
pro_type:等待选择自选题类型
pro:自选题
complete:已完成 | +| version | str | 答题版本 | 当前为`v4` | +| start_time | num | 本次答题开始时间 | 时间戳 | +| first_answer | num | (?) | | +| progress | str | 当前答题进度 | 百分比
60分为100% | +| text | str | 提示文案 | | +| url | str | 答题页面url | | +| in_reg_audit | bool | 是否为第一次答题 | | +| edition | num | 答题版本 | 0:旧版(40+10+50)
2:新版(40+30+30) | +| rewards | null | (?) | | +| captcha | num | 是否已经提交验证码 | 1:已提交
仅新版提交验证码后存在 | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/answer/v4/status' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "hid": 1623207905520705, + "mid": 293793435, + "score": 2, + "status": 2, + "number": 2, + "result": "failed", + "stage": "base", + "version": "v4", + "start_time": 1623207905, + "first_answer": 2, + "progress": "3", + "text": "继续答题", + "url": "https://www.bilibili.com/h5/newbie/entry?navhide=1", + "in_reg_audit": false, + "edition": 0, + "rewards": null + } +} +``` + +
+ +## 查询自选题分类 + +> https://api.bilibili.com/x/answer/v4/pro/type + +*请求方式:GET* + +认证方式:Cookie或APP + +当字段`edition`的值不同时,该接口返回的数据也不同 + +**json回复:** + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | ---------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
41014:答题过快或错误太多
41021:用户基础题未通过
41031:自选题未通过
41055:基础附加题未通过 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | array | 父分类列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---- | +| 0 | obj | 父分类1 | | +| n | obj | 父分类(n+1) | | +| …… | obj | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ----- | ---------- | ---- | +| id | num | 父分类id | | +| name | str | 父分类名 | | +| fields | array | 子分类列表 | | + +`data`数组中的对象中的`fields`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---- | +| 0 | obj | 子分类1 | | +| n | obj | 子分类(n+1) | | +| …… | obj | …… | …… | + +`fields`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| id | num | 子分类id | | +| name | str | 子分类名 | | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/answer/v4/pro/type' \ +-b 'SESSDATA=xxx' +``` + +旧版`edition=0`返回: + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "id": 1, + "name": "游戏", + "fields": [ + { + "id": 8, + "name": "动作射击" + }, + { + "id": 9, + "name": "冒险格斗" + }, + { + "id": 12, + "name": "策略模拟 " + }, + { + "id": 13, + "name": "角色扮演 " + }, + { + "id": 14, + "name": "音乐体育 " + } + ] + }, + { + "id": 2, + "name": "影视", + "fields": [ + { + "id": 15, + "name": "纪录片 " + }, + { + "id": 16, + "name": "电影 " + }, + { + "id": 17, + "name": "电视剧 " + } + ] + }, + { + "id": 3, + "name": "科技", + "fields": [ + { + "id": 18, + "name": "军事 " + }, + { + "id": 19, + "name": "地理 " + }, + { + "id": 20, + "name": "历史 " + }, + { + "id": 21, + "name": "文学 " + }, + { + "id": 22, + "name": "数学 " + }, + { + "id": 23, + "name": "物理 " + }, + { + "id": 24, + "name": "化学 " + }, + { + "id": 25, + "name": "生物 " + }, + { + "id": 26, + "name": "数码科技 " + } + ] + }, + { + "id": 4, + "name": "动画", + "fields": [ + { + "id": 27, + "name": "动画声优 " + }, + { + "id": 28, + "name": "动漫内容 " + } + ] + }, + { + "id": 5, + "name": "艺术", + "fields": [ + { + "id": 29, + "name": "ACG音乐 " + }, + { + "id": 30, + "name": "三次元音乐 " + }, + { + "id": 31, + "name": "绘画 " + } + ] + }, + { + "id": 6, + "name": "流行前线", + "fields": [ + { + "id": 32, + "name": "娱乐 " + }, + { + "id": 33, + "name": "时尚 " + }, + { + "id": 34, + "name": "运动 " + } + ] + }, + { + "id": 7, + "name": "鬼畜", + "fields": [ + { + "id": 35, + "name": "鬼畜 " + } + ] + } + ] +} +``` + +
+ +新版`edition=2`返回: + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "id": 1, + "name": "游戏", + "fields": [ + { + "id": 1, + "name": "游戏" + } + ] + }, + { + "id": 2, + "name": "影视", + "fields": [ + { + "id": 2, + "name": "影视" + } + ] + }, + { + "id": 3, + "name": "科教/知识", + "fields": [ + { + "id": 3, + "name": "科教/知识" + } + ] + }, + { + "id": 4, + "name": "动画/动漫", + "fields": [ + { + "id": 4, + "name": "动画/动漫" + } + ] + }, + { + "id": 5, + "name": "音乐/舞蹈", + "fields": [ + { + "id": 5, + "name": "音乐/舞蹈" + } + ] + }, + { + "id": 32, + "name": "明星/娱乐", + "fields": [ + { + "id": 32, + "name": "明星/娱乐" + } + ] + }, + { + "id": 35, + "name": "鬼畜", + "fields": [ + { + "id": 35, + "name": "鬼畜" + } + ] + }, + { + "id": 42, + "name": "时尚/健身", + "fields": [ + { + "id": 42, + "name": "时尚/健身" + } + ] + } + ] +} +``` + +
+ + +## 查询答题结果 + +> https://api.bilibili.com/x/answer/v4/result + +*请求方式:GET* + +认证方式:无 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---------- | ------ | ---- | +| hid | num | 答题会话id | 必要 | | + +**json回复:** + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
41023:用户答题记录不存在 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ----- | ------------------------ | ----------------------------------- | +| hid | num | 答题会话id | | +| mid | num | 答题用户mid | | +| member | num | | | +| score | num | 得分 | | +| level | num | 用户等级 | | +| first_pass | num | | | +| uname | str | 用户昵称 | | +| face | str | 用户头像url | | +| status | str | 答题结果 | failed:未通过
succeed:已通过 | +| question_types | array | 已选择的自选题列表 | | +| power | array | 自选题分类得分情况 | | +| start_time | num | 开始答题时间 | 时间戳 | +| share | obj | | | +| can_show_rank_btn | bool | | | +| is_same_user | bool | | | +| view_more | str | | | +| video_info | obj | | | +| main_tids | array | | | +| sub_tids | array | | | +| power_result | null | | | +| score_rate | num | 分数超过平均用户的百分比 | | +| permission | obj | | | +| rewards | null | | | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/answer/v4/result' \ +--data-urlencode 'hid=1615088061307609' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "hid": 1615088061307609, + "mid": 1386643599, + "member": 0, + "score": 70, + "level": 0, + "first_pass": 0, + "uname": "眉凭铱ひ前非", + "face": "http://i0.hdslb.com/bfs/face/cd83d4cdbfb521455c168eaa181915b40cb664d1.jpg", + "status": "succeed", + "question_types": [ + { + "id": 12, + "name": "策略模拟 " + }, + { + "id": 13, + "name": "角色扮演 " + }, + { + "id": 14, + "name": "音乐体育 " + }, + { + "id": 8, + "name": "动作射击" + }, + { + "id": 9, + "name": "冒险格斗" + } + ], + "power": [ + { + "score": 0, + "name": "动画" + }, + { + "score": 0, + "name": "艺术" + }, + { + "score": 5, + "name": "游戏" + }, + { + "score": 0, + "name": "科技" + }, + { + "score": 0, + "name": "影视" + }, + { + "score": 0, + "name": "鬼畜" + } + ], + "start_time": 1615088061, + "share": { + "content": "", + "short_content": "" + }, + "can_show_rank_btn": false, + "is_same_user": true, + "view_more": "", + "video_info": { + "url": "", + "name": "", + "img": "", + "watch_num": "", + "up_num": "" + }, + "main_tids": [], + "sub_tids": [], + "power_result": null, + "score_rate": 84, + "permission": { + "reply": true, + "color_dm": true + } + } +} +``` + +
\ No newline at end of file diff --git a/bb-api-collect/docs/note/action.md b/bb-api-collect/docs/note/action.md new file mode 100644 index 0000000000..15c40e99a7 --- /dev/null +++ b/bb-api-collect/docs/note/action.md @@ -0,0 +1,131 @@ +# 笔记操作 + +## 保存视频笔记 + +> https://api.bilibili.com/x/note/add + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------ | ---- | ------------------------ | ------ | ------------------------------------------------------------ | +| oid | num | 目标id | 必要 | | +| oid_type | num | 目标id类型 | 必要 | `0`视频(oid=avid) | +| note_id | num | 笔记id | 非必要 | 创建时无需此项 | +| title | str | 笔记标题 | 必要 | | +| summary | str | 笔记预览文本 | 必要 | | +| content | str | 笔记正文json序列 | 必要 | 格式见[附表](readme.md#附表-笔记正文序列格式) | +| tags | str | 笔记跳转标签列表 | 非必要 | | +| cls | num | 1 | 非必要 | 作用尚不明确 | +| from | str | 提交类型 | 非必要 | `auto`自动提交
`save`手动提交
`close`关闭时自动提交 | +| cont_len | num | 正文字数 | 非必要 | | +| platform | str | 平台 | 非必要 | 可为`web` | +| publish | num | 是否公开笔记 | 非必要 | `0`不公开
`1`公开 | +| auto_comment | num | 是否添加到评论区 | 非必要 | `0`不添加
`1`添加 | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | `0`成功
`-101`账号未登录
`-111`csrf校验失败
`-400`请求错误
`79508`该稿件已存在笔记,无法新增
`79513`笔记所属视频不合法 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ------------ | ---- | +| note_id | num | 笔记id | | + +**示例:** + +保存内容为加粗的STRONG的笔记`3809605586518023`于`av970322090` + +```shell +curl 'https://api.bilibili.com/x/note/add' \ +--data-urlencode 'oid=970322090' \ +--data-urlencode 'oid_type=0' \ +--data-urlencode 'note_id=3809605586518023' +--data-urlencode 'title=周刊哔哩哔哩排行榜#543' +--data-urlencode 'summary=STRONG' +--data-urlencode 'content=[{"attributes":{"bold":true},"insert":"STRONG"},{"insert":"\n"}]' +--data-urlencode 'tags=' +--data-urlencode 'cls=1' +--data-urlencode 'from=save' +--data-urlencode 'csrf=xxx' +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "note_id": 3809605586518023 + } +} +``` + +
+ +## 删除视频笔记 + +> https://api.bilibili.com/x/note/del + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | ------------------------ | ------ | ---- | +| oid | num | 目标稿件avid | 必要 | | +| note_id | num | 笔记id | 非必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-111:csrf校验失败
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +删除稿件`av457253380`下的笔记`4075968478576647` + +```shell +curl 'https://api.bilibili.com/x/note/del' \ +--data-urlencode 'oid=457253380' \ +--data-urlencode 'note_id=4075968478576647' \ +--data-urlencode 'csrf=xxx' +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
diff --git a/bb-api-collect/docs/note/info.md b/bb-api-collect/docs/note/info.md new file mode 100644 index 0000000000..5793ee33c8 --- /dev/null +++ b/bb-api-collect/docs/note/info.md @@ -0,0 +1,309 @@ +# 笔记详细信息 + +## 查询该稿件是否禁止笔记 + +> https://api.bilibili.com/x/note/is_forbid + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| aid | num | 稿件avid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | `0`成功
`-400`请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------------- | ---- | ------------ | ----------------------------------- | +| forbid_note_entrance | bool | 是否禁止笔记 | `true`禁止笔记
`false`允许笔记 | + +**示例:** + +查询视频稿件`av338677252`是否禁止笔记 + +```shell +curl 'https://api.bilibili.com/x/note/info' \ +--data-urlencode 'aid=338677252' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "forbid_note_entrance": false + } +} +``` + +
+ +## 查询私有笔记内容 + +> https://api.bilibili.com/x/note/info + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | ---------- | ----------- | -------- | +| oid | num | 目标id | 必要 | | +| oid_type | num | 目标id类型 | 必要 | `0`视频(oid=avid) | +| note_id | num | 笔记id | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | `0`成功
`-400`请求错误
`-101`账号未登录
`79502`笔记详情未找到
`79503`笔记正文未找到 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ----- | ---------------- | -------------- | +| arc | obj | 对应视频稿件信息 | | +| audit_status | num | 0 | 作用暂不明确 | +| cid_count | num | 视频分P数 | | +| content | str | 笔记正文json序列 | 格式见[附表](readme.md#附表-笔记正文序列格式) | +| forbid_note_entrance | bool | | | +| pub_reason | str | 公开笔记相关原因 | | +| pub_status | num | 公开笔记状态 | `1`未公开
`2`已公开
`4`退回 | +| pub_version | num | | | +| summary | str | 笔记预览文本 | | +| tags | array | 笔记跳转标签列表 | | +| title | str | 笔记标题 | | + +`data`中的`arc`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ---------- | ----------------- | +| oid | num | 目标id | | +| oid_type | num | 目标id类型 | `0`视频(oid=avid) | +| title | str | 视频标题 | | +| pic | str | 视频封面 | | +| status | num | | | +| desc | str | 视频简介 | | + +`data`中的`tags`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---------------- | +| 0 | obj | 标签1 | | +| n | obj | 标签(n+1) | 按照笔记中位置排列 | +| …… | obj | …… | …… | + +`tags`中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ----------------- | ------------ | +| cid | num | 视频cid | | +| status | num | 0 | 作用尚不明确 | +| index | num | 在稿件中的分P索引 | | +| seconds | num | 视频进度 | | +| pos | num | 笔记中位置 | | + +**示例:** + +查询视频`av338677252`中笔记`24508729145690112`的内容 + +```shell +curl 'https://api.bilibili.com/x/note/info' \ +--data-urlencode 'oid=338677252' \ +--data-urlencode 'oid_type=0' \ +--data-urlencode 'note_id=24508729145690112' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "title": "2022哔哩哔哩拜年纪", + "summary": " ...", + "content": "[{"insert":"\n"}]", + "cid_count": 0, + "audit_status": 0, + "pub_status": 0, + "pub_reason": "", + "pub_version": 0, + "forbid_note_entrance": false, + "tags": [], + "arc": { + "oid": 338677252, + "title": "2022哔哩哔哩拜年纪", + "status": 0, + "oid_type": 0, + "pic": "http://i2.hdslb.com/bfs/archive/1e683a5363f35aa0a65419dbf145177099e38f90.jpg", + "desc": "" + } + } +} +``` + +
+ +## 查询公开笔记内容 + +> https://api.bilibili.com/x/note/publish/info + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------ | ------ | -------- | +| cvid | num | 笔记对应的专栏cvid | 必要 | 非笔记id | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------------------------------------------------------- | +| code | num | 返回值 | `0`成功
`-400`请求错误
`79514`公开笔记详情未找到 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------------- | ----- | ---------------------- | --------------------------------------------- | +| cvid | num | 公开笔记对应的专栏cvid | | +| note_id | num | 笔记id | | +| title | str | 笔记标题 | | +| summary | str | 笔记预览 | | +| content | str | 笔记正文json序列 | 格式见[附表](readme.md#附表-笔记正文序列格式) | +| cid_count | num | (?) | | +| pub_status | num | 公开状态 | | +| tags | array | | | +| arc | obj | 稿件信息 | | +| author | obj | 作者信息 | | +| forbid_note_entrance | bool | | | + +`data`中的`arc`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ---------- | ----------------- | +| oid | num | 目标id | | +| oid_type | num | 目标id类型 | `0`视频(oid=avid) | +| title | str | 标题 | | +| status | num | (?) | | +| pic | str | 封面url | | +| desc | str | 简介 | | + +`data`中的`author`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ---------- | ---- | +| mid | num | 用户mid | | +| name | str | 昵称 | | +| face | str | 头像url | | +| level | num | 用户等级 | | +| vip_info | obj | 会员信息 | | +| pendant | obj | 头像框信息 | | + +**示例:** + +查看公开笔记`cv15160286`的信息 + +```shell +curl 'https://api.bilibili.com/x/note/publish/info' \ +--data-urlencode 'cvid=15160286' +``` + +
+查看响应示例: + + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "cvid": 15160286, + "note_id": 24114044116402190, + "title": "2022哔哩哔哩拜年纪", + "summary": "我决定再重新做一个系列,叫做影评系列 那么我们这一次是影系列的第n期 我也不知道是多少期,到时候回去统计一下 今天的影评是写,2022年哔哩哔哩拜年纪 【...", + "content": "[{"insert":"我决定再重新做一个系列,叫做影评系列\n那么我们这一次是影系列的第n期\n我也不知道是多少期,到时候回去统计一下\n今天的影评是写,2022年哔哩哔哩拜年纪\n【以及往年的拜年祭,会提一下】\n看完哔哩哔哩拜年纪之后,我的触动真的很大,那今天就先写哔哩哔哩拜年纪吧。\n字数同样有点长,希望看过2022哔哩哔哩拜年纪的人可以认真看完吧!也可以说说你的想法啊!\n\n首先先说一说它的时间,因为每次都在除夕夜播放而出现要和家人看春晚,又要去抢红包之类的,所以每次都看不了直播。这一点就很糟心了。\n所以说这次同往年一样,我也是看的回放。\n一\n一开始是2233跳舞,因为我不太关注这些二次元,所以说就不详细评述了\n但是这个和去年的不问天,应该是一个系列的。都是2233在一起出镜,然后配的是一首歌,但是我觉得这首歌确实没有不问天那么惊艳我了。\n【我觉得很大的可能是今年的作曲没有泡泡老师,去年,前年的泡泡老师作的曲都真的非常的好听,而且今年的拜年纪的预告片上也有一个三首他写的歌的串烧。真的很不错。】\n二\n然后就说一下\n今年以及往年的动画\n这个主体动画真的每年做的都很不错。就是既有意义,又有故事,还有深度,同时还介绍了风俗人情和乡土民俗,真的都是非常非常好的动画,并且动画制作也很精良。\n真的想知道这些动画的主创人员都是谁,可是每次都没有标注。\n【既然谈到动画,就来说一下去年预告的一个动画叫盒中之海。其实我本来是去年看拜年纪的时候是没有看到这个预告片的\n但是今年的评论区底下,几乎每一个评论区中都在催盒中之海,于是我便去看了一下。我发现这个真的变得更有意义和深度了。\n他讲的是一个游戏,还有海神等等\n虽然感觉到它的预告片很乱,但是总觉得其中有什么联系?就是很悬疑又很惊恐但一看就很有深度的动画了!\n所以我也期待着了!】\n今年讲的是哔哩楼的故事,我觉得他的那个创意真的很好,就是自助餐厅的创意\n可以让每一个人都尝到厨师的快乐,\n但又不是真正去做厨师,如果真的能有这样一家店就好了!\n然后拜年纪传统的视频串烧节目就不说了吧。\n三\n再后来就是新春小记,俗称的是拜年曲\n去年的拜年曲是吉祥话,我觉得两个都很好听,但是说去年的都是我认识并且比较喜欢的歌手,可以今年的歌手一个都不认识了[em]e107[/em]\n但是近两年的但连许都用了说话开篇,然后其中高潮的时候都是顶针的方式来演唱,可能这也是一个习俗吧,但真的还比较好听!\n四\n一些没有触动的作品就不说了\n所以接下来是灯火!\n我没有想到今年过年能再一次听到\n《灯火里的中国》!\n因为今年春晚没有周深还有些遗憾呢!\n但虽然这首歌不是周深唱的,但也温暖人心!\n这个应该与去年的《我的祖国》是一个系列的!\n五\n四迹老师的动画一如既往的有意思\n【但就是少了灵魂快板……】\n去年和前年的快板真的深入人心了!\n所以我还是最喜欢去年的\n“这个好诶!”\n六\n邪教老师好几年没有写燃曲了哈哈哈哈哈哈\n但这个风灵玉秀和拜年祭一起做的动画挺好的\n虽然我不知道风灵玉秀是什么动画\n但武侠版的这个动画的动作做的很细致\n又不是很快,看的舒服又清晰\n配上音乐……\n【我不在想再说还不错了哈哈哈哈哈哈哈】\n七\n终于到我最喜欢的一首人演唱的歌曲\n【哈哈哈哈哈为了不与卡农冲突】\n《快乐手帐》\n我要把纳兰寻风的词吹爆!!!!!!!!!\n“跟着我,哒哒哒哒,搭个舞台\n跟着我,哒哒哒哒,大步迈开”\n“生活就是平平淡淡,偶尔磕磕绊绊\n让脑筋多转转,往好处看看!”\n真的好温暖!积极向上!向前看!\n这个初音未来的声音也没有不适感了!\n这个真的好棒!\n八\n然后是沃玛!\n沃玛的脑回路真的很独特!\n他的这个系列是视频真的很独特又新奇!\n这个不好描述……自己去看吧!\n沃玛的声音也好听!哈哈哈哈哈哈哈\n九\n魔术跳过吧\n上面是这次拜年级我最喜欢的一个节目,第大调卡农。\n这个真的很温暖,还有小提琴和钢琴的两个二重奏,就是非常的震撼人心,很感动。\n再配上他的画面,从一个小孩儿到最后的老人,感觉这一生都可以用这首歌来概括。所以说真的很感动又很温暖,\n而且这个节目的副标题是:\n致敬一生中每一个重要时刻\n所以更感动了!\n十\n拜年祭燃曲《弈》\n意境真的很扩大,不看注释完全看不懂词啊\n但去还比较好听,但感觉没有去年的《万象霜天》惊艳\n那我在b站上面看到一个视频,把这八年的八个燃曲在一起放,然后《弈》真的听起来很明显,很明显。\n高潮很高,很好听!\n所以苍穹是sv还是v啊?\n十一\n这次cilicili的《另一个我》没有做好\n可能是因为去年是《时光盲盒》真的太棒了!!!!\n“一遍遍,我回来了!……辛苦了!”\n反而今年的歌没有触动\n这是我唯一一个跳过了大约一分钟的节目\n十二\n后面几个节目都具有讽刺意义\n但那个三年都放的那个讽刺动画系列\n我属实看不懂哈哈哈哈哈哈哈哈\n梗太多了哈哈哈哈哈哈真有些看不懂\n十三\n终于到《除夕》了\n音阙诗听第二次上拜年祭!\n第一次安安和镜子演唱《与梦盛开》\n第二次是音阙诗听团队创作《除夕》\n同样是音阙诗听味啊!\n这次的词写的还不错!\n所以,节日系列开更!\n【但A-SOUL究竟是什么组合,根本没听说过啊】\n十四\n最后一个节目。\n流年如歌,是前年的最后一个节目,但是我那时候还不习惯听V曲,所以说几乎完全就跳过了,那个节目没有听。\n但是这个纳兰寻风作的词,以及这个西门振作的曲,真的配合起来好好听。\n还是要再吹一下纳兰寻风老师的词真的好棒,然后同样和上一个说的一样,温暖,感动,就有积极向上的那种乐观。\n“你是冰雪消融唤醒万物第一缕花香……”\n“湖面上小船儿晃晃岁月长……”\n【但是纳兰寻风老师究竟是做什么的?\n好像经常调教也能看到他哈哈哈哈哈哈\n没有特别关注】\n然后我每次听一听的是泠鸢翻唱的版本,这一次是让刷牙老师来唱的,男声和女声唱有有别样的风味\n这真的就像《难忘今宵》一样,要待在每一场拜年纪嘛?\n新年的那一天晚上都随着流年如歌,进入梦乡!\n人生如梦,流年似水,岁月如歌,\n春夏秋冬,年复一年\n唯有自己不变\n去下一个十年找到属于自己的答案吧!\n哔哩哔哩乾杯!\n\n\n十五【正好是十五哈哈哈哈哈】\n《五十》这个节目是很晚的时候看的\n有些悬疑,甚至有些恐怖,但引起了许多思考\n写太多了,就不详说了……\n【再次期待艾导的《盒中之海》!】\n\n哔哩哔哩( ゜ -゜)つロ 乾杯~​\n——今日发布于Q,转到哔哩哔哩!\n"}]", + "cid_count": 0, + "pub_status": 2, + "tags": [], + "arc": { + "oid": 338677252, + "title": "2022哔哩哔哩拜年纪", + "status": 0, + "oid_type": 0, + "pic": "http://i2.hdslb.com/bfs/archive/1e683a5363f35aa0a65419dbf145177099e38f90.jpg", + "desc": "" + }, + "author": { + "mid": 523870870, + "name": "夜达星xxxxxxx", + "face": "http://i1.hdslb.com/bfs/face/2cdfd277e63b6bb1f400ed616b5caf0a04196f28.jpg", + "level": 3, + "vip_info": { + "type": 0, + "status": 0, + "due_date": 0, + "vip_pay_type": 0, + "theme_type": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + } + }, + "forbid_note_entrance": false + } +} +``` + +
diff --git a/bb-api-collect/docs/note/list.md b/bb-api-collect/docs/note/list.md new file mode 100644 index 0000000000..d0d3851ae6 --- /dev/null +++ b/bb-api-collect/docs/note/list.md @@ -0,0 +1,653 @@ +# 笔记列表 + +## 查询稿件私有笔记 + +> https://api.bilibili.com/x/note/list/archive + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +该接口只能查询私有笔记,无法查询公开笔记 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ------------------------ | ------ | ----------------- | +| oid | num | 目标id | 必要 | | +| oid_type | num | 目标id类型 | 必要 | `0`视频(oid=avid) | +| csrf | str | CSRF Token(位于cookie) | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | -------------------------------------------------- | +| noteIds | array | 笔记列表 | 无笔记则无此项
可能后续会允许视频添加多个笔记 | + +`data`中的`noteIds`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | ---- | +| 0 | str | 笔记id | | + +**示例:** + +查询视频`av970322090`的笔记id + +```shell +curl 'https://api.bilibili.com/x/note/list/archive' \ +--data-urlencode 'oid=970322090' \ +--data-urlencode 'oid_type=0' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code":0, + "message":"0", + "ttl":1, + "data":{ + "noteIds":[ + "3809605586518023" + ] + } +} +``` + +
+ +## 查询用户私有笔记 + +> https://api.bilibili.com/x/note/list + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | ------------ | ----------- | ------------------------------------------------------- | +| ps | num | 每页项数 | 必要 | | +| pn | num | 页码 | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | -------- | ------------ | +| list | array | 明细列表 | | +| page | obj | 页面信息 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---------------- | +| 0 | obj | 笔记1 | | +| n | obj | 笔记(n+1) | 按照创建顺序排列 | +| …… | obj | …… | …… | + +`list`中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------------- | ---- | ------------ | ------------------------- | +| title | str | 笔记标题 | | +| summary | str | 笔记预览文本 | | +| mtime | str | 提交时间 | YYYY-MM-DD hh:mm | +| arc | obj | 视频信息 | | +| note_id | num | 笔记id | | +| audit_status | num | 0 | 作用尚不明确 | +| web_url | str | 笔记h5页url | | +| note_id_str | str | 笔记id str | | +| message | str | 更新信息 | "更新于 YYYY-MM-DD hh:mm" | +| forbid_note_entrance | bool | (?) | | +| likes | num | 点赞数 | | +| has_like | bool | 是否点赞 | | + +`list`中的`arc`中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ------------ | ---------------------- | +| oid | num | 目标id | | +| bvid | str | 稿件bvid | | +| pic | str | 稿件封面图片url | | +| desc | str | 视频简介 | | +| status | num | 0 | | +| oid_type | num | 目标id类型 | `0`视频(oid=avid) | +| aid | num | 稿件avid | | + +`data`中的`page`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ------------ | -------------------- | +| total | num | 笔记总数 | | +| size | num | 每页项数 | | +| num | num | 页码 | | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/note/list' \ +--data-urlencode 'ps=10' \ +--data-urlencode 'pn=1' +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "title": "2022哔哩哔哩拜年纪", + "summary": " ...", + "mtime": "2022-02-16 16:46", + "arc": { + "oid": 338677252, + "bvid": "BV1fR4y1T7aV", + "pic": "http://i2.hdslb.com/bfs/archive/1e683a5363f35aa0a65419dbf145177099e38f90.jpg", + "desc": "愿大家看的开心!新年快乐,虎年大吉,欧气十足,万事顺意!ヾ(≧▽≦*)o", + "status": 0, + "oid_type": 0, + "aid": 338677252 + }, + "note_id": 24508729145690110, + "audit_status": 0, + "web_url": "https://www.bilibili.com/h5/note-app?oid=338677252&oid_type=0&pagefrom=fullpage&navhide=1&-Bct.statusbar.mode=0", + "note_id_str": "24508729145690112", + "message": "更新于 2022-02-16 16:46", + "forbid_note_entrance": false, + "likes": 0, + "has_like": false + } + ], + "page": { + "total": 1, + "size": 10, + "num": 1 + } + } +} +``` + +
+ +## 查询稿件公开笔记 + +> https://api.bilibili.com/x/note/publish/list/archive + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ---------- | ------ | ----------------- | +| oid | num | 目标id | 必要 | | +| oid_type | num | 目标id类型 | 必要 | `0`视频(oid=avid) | +| ps | num | 每页项数 | 必要 | | +| pn | num | 页码 | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------------- | ----- | ------------ | ---- | +| list | array | 公开笔记列表 | | +| page | obj | 页面信息 | | +| show_public_note | bool | | | +| message | str | | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---------------- | +| 0 | obj | 笔记1 | | +| n | obj | 笔记(n+1) | 按照创建顺序排列 | +| …… | obj | …… | …… | + +`list`中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ---------------------- | ------------------------- | +| cvid | num | 公开笔记对应的专栏cvid | | +| title | str | 笔记标题 | | +| summary | str | 笔记预览 | | +| pubtime | str | 发布时间 | YYYY-MM-DD hh:mm | +| web_url | str | 笔记h5页url | | +| message | str | 更新信息 | "更新于 YYYY-MM-DD hh:mm" | +| author | obj | 作者信息 | | +| likes | num | 点赞数 | | +| has_like | bool | 是否点赞 | 需要登录(Cookie) | + +`list`中的对象中的`author`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ---------- | ---- | +| mid | num | 用户mid | | +| name | str | 昵称 | | +| face | str | 头像url | | +| level | num | 用户等级 | | +| vip_info | obj | 会员信息 | | +| pendant | obj | 头像框信息 | | + +**示例:** + +查询视频`av338677252`的公开笔记列表 + +```shell +curl 'https://api.bilibili.com/x/note/publish/list/archive' \ +--data-urlencode 'oid=338677252' \ +--data-urlencode 'oid_type=0' \ +--data-urlencode 'ps=10' \ +--data-urlencode 'pn=1' +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "cvid": 15160286, + "title": "2022哔哩哔哩拜年纪", + "summary": "我决定再重新做一个系列,叫做影评系列 那么我们这一次是影系列的第n期 我也不知道是多少期,到时候回去统计一下 今天的影评是写,2022年哔哩哔哩拜年纪 【...", + "pubtime": "2022-02-07 23:44", + "web_url": "https://www.bilibili.com/h5/note-app/view?cvid=15160286&pagefrom=ugcvideo", + "message": "更新于 2022-02-07 23:44", + "author": { + "mid": 523870870, + "name": "夜达星xxxxxxx", + "face": "http://i1.hdslb.com/bfs/face/2cdfd277e63b6bb1f400ed616b5caf0a04196f28.jpg", + "level": 3, + "vip_info": { + "type": 0, + "status": 0, + "due_date": 0, + "vip_pay_type": 0, + "theme_type": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + } + }, + "likes": 7, + "has_like": false + }, + { + "cvid": 15086217, + "title": "2022哔哩哔哩拜年纪", + "summary": "节目表,多图预警,方便各位时间戳跳转…… 01:20 New Day [图片] 06:32 重返哔哩楼1 [图片] 11:06 嗨,...", + "pubtime": "2022-02-01 20:07", + "web_url": "https://www.bilibili.com/h5/note-app/view?cvid=15086217&pagefrom=ugcvideo", + "message": "更新于 2022-02-01 20:07", + "author": { + "mid": 3810985, + "name": "Remレム22", + "face": "http://i1.hdslb.com/bfs/face/4cce970eb1b9fb8b322d49133a11caa630178728.jpg", + "level": 6, + "vip_info": { + "type": 2, + "status": 1, + "due_date": 1694880000000, + "vip_pay_type": 1, + "theme_type": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299", + "role": 3, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + } + }, + "likes": 22, + "has_like": false + }, + { + "cvid": 15080841, + "title": "2022哔哩哔哩拜年纪", + "summary": "2022哔哩哔哩拜年纪从厨师的角度开始了故事,而厨师象征着每个人,每一道菜都是每个厨师用汗水耕耘出来的,并且在主线故事中穿插这不同的小故事,代表了近几年生...", + "pubtime": "2022-02-01 10:10", + "web_url": "https://www.bilibili.com/h5/note-app/view?cvid=15080841&pagefrom=ugcvideo", + "message": "更新于 2022-02-01 10:10", + "author": { + "mid": 482114483, + "name": "沐曦mornal", + "face": "http://i2.hdslb.com/bfs/face/cf1ef9c2045e317dfe6dbe8659b6f7a69c7572d5.jpg", + "level": 4, + "vip_info": { + "type": 1, + "status": 1, + "due_date": 1646755200000, + "vip_pay_type": 1, + "theme_type": 0, + "label": { + "path": "", + "text": "大会员", + "label_theme": "vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "nickname_color": "", + "role": 1, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + } + }, + "likes": 7, + "has_like": false + }, + { + "cvid": 15080246, + "title": "2022哔哩哔哩拜年纪", + "summary": "niumniumnium~~~33是我的菜了! 这次的跨年纪呢确实不同于以往。我发现现代技术确实给类似的活动提供了平台与支持,但是不可否认的是bilibi...", + "pubtime": "2022-02-01 08:59", + "web_url": "https://www.bilibili.com/h5/note-app/view?cvid=15080246&pagefrom=ugcvideo", + "message": "更新于 2022-02-01 08:59", + "author": { + "mid": 1049943541, + "name": "吃瓜的DINGBALL", + "face": "http://i1.hdslb.com/bfs/face/93e7a3826586338e15e5703f9d49bb3bbd0adfa5.jpg", + "level": 2, + "vip_info": { + "type": 1, + "status": 0, + "due_date": 1641744000000, + "vip_pay_type": 0, + "theme_type": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + } + }, + "likes": 10, + "has_like": false + }, + { + "cvid": 15077197, + "title": "2022哔哩哔哩拜年纪", + "summary": "23333333333333333333333333333333333333333333333333333333333333333333333333333...", + "pubtime": "2022-01-31 22:53", + "web_url": "https://www.bilibili.com/h5/note-app/view?cvid=15077197&pagefrom=ugcvideo", + "message": "更新于 2022-01-31 22:53", + "author": { + "mid": 433136442, + "name": "KiBi_3", + "face": "http://i0.hdslb.com/bfs/face/4c11d1419316f14b8b0f5c146d0cd34627955244.jpg", + "level": 2, + "vip_info": { + "type": 0, + "status": 0, + "due_date": 0, + "vip_pay_type": 0, + "theme_type": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "" + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + } + }, + "likes": 2, + "has_like": false + }, + { + "cvid": 15077019, + "title": "2022哔哩哔哩拜年纪", + "summary": "2022加油吖!~~~~~~~~~~~~~~~~~~~~~2022加油吖!2022加油吖!2022加油吖!2022加油吖!2022加油吖!2022加油吖!...", + "pubtime": "2022-01-31 22:36", + "web_url": "https://www.bilibili.com/h5/note-app/view?cvid=15077019&pagefrom=ugcvideo", + "message": "更新于 2022-01-31 22:36", + "author": { + "mid": 11283554, + "name": "zhen_____", + "face": "http://i0.hdslb.com/bfs/baselabs/381fcc3865daf85bd6a1ddc4b6dfbd11ba937dc9.jpg", + "level": 6, + "vip_info": { + "type": 2, + "status": 1, + "due_date": 1730736000000, + "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": "" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299", + "role": 3, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png" + }, + "pendant": { + "pid": 5459, + "name": "星座系列:巨蟹座", + "image": "http://i2.hdslb.com/bfs/garb/item/a6e5b6b36a4a6c00ca8881ecc837c2aa9ebcb53d.png", + "expire": 0, + "image_enhance": "http://i2.hdslb.com/bfs/garb/item/a6e5b6b36a4a6c00ca8881ecc837c2aa9ebcb53d.png", + "image_enhance_frame": "" + } + }, + "likes": 5, + "has_like": false + } + ], + "page": { + "total": 6, + "size": 10, + "num": 1 + }, + "show_public_note": true, + "message": "" + } +} +``` + +
+ +## 查询用户公开笔记 + +> https://api.bilibili.com/x/note/publish/list/user + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------ | ------ | ---- | +| ps | num | 每页项数 | 必要 | | +| pn | num | 页码 | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ----- | -------- | ---- | +| list | array | 明细列表 | | +| page | obj | 页面信息 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---------------- | +| 0 | obj | 笔记1 | | +| n | obj | 笔记(n+1) | 按照创建顺序排列 | +| …… | obj | …… | …… | + +`data`中的`page`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | -------- | ---- | +| total | num | 笔记总数 | | +| size | num | 每页项数 | | +| num | num | 页码 | | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/note/publish/list/user' \ +--data-urlencode 'ps=10' \ +--data-urlencode 'pn=1' +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "page": { + "total": 0, + "size": 10, + "num": 1 + } + } +} +``` + +
diff --git a/bb-api-collect/docs/note/readme.md b/bb-api-collect/docs/note/readme.md new file mode 100644 index 0000000000..dbf0223e12 --- /dev/null +++ b/bb-api-collect/docs/note/readme.md @@ -0,0 +1,159 @@ +# 视频笔记 + +2020-11-16 B站推出了测试版的功能——"视频笔记",与视频稿件关联,为富文本模式,可供记录观看视频时的感悟以及视频中的重要内容,目前只可在web端操作 + +笔记分为私有笔记和公开笔记,一个稿件只能添加一篇私有笔记,但可以公开多篇笔记 + +公开笔记与【专栏】性质相同,使用`cvid`寻址相应的公开笔记 + +--- + +**继续查看:** + +- [笔记列表](list.md) +- [笔记详细信息](info.md) +- [笔记操作](action.md) + +--- + +## 附表-笔记正文序列格式 + +根数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---- | +| 0 | obj | 第1个元素 | | +| n | obj | 第(n+1)个元素 | | +| …… | obj | …… | …… | + +根数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------ | ------------------- | +| attributes | obj | 元素属性 | 无属性无此项 | +| insert | str | 元素内容 | 为跳转/图片时无此项 | +| insert | obj | 元素跳转信息 | 非跳转/图片时无此项 | + +对象中的`attributes`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ---------- | ------------------------------ | +| bold | bool | 是否加粗 | | +| strike | bool | 是否删除线 | | +| underline | bool | 是否下划线 | | +| background | str | 背景颜色 | | +| color | str | 文字颜色 | | +| list | str | 列表属性 | ordered有序列表/bullet无序列表 | +| size | str | 文字字号 | | + +对象中的`insert`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | -------- | ------ | +| tag | obj | 跳转标签 | 二选一 | +| imageUpload | obj | 笔记图片 | 二选一 | + +`insert`中的`tag`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ----------------- | ------------ | +| cid | num | 视频cid | | +| status | num | 0 | 作用尚不明确 | +| index | num | 在稿件中的分P索引 | | +| seconds | num | 视频进度 | | +| cidCount | num | 稿件总分P数 | | +| key | str | 标签创建时间戳 | | +| title | str | output | 作用尚不明确 | + +`insert`中的`imageUpload`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ---------- | ------------ | +| url | str | 图片链接 | | +| status | str | done | 作用尚不明确 | +| width | num | 图片宽度-2 | | + +示例: + +以下笔记正文序列包含`字号`、`加粗`、`高亮`、`普通文本`格式 + +```json +[ + { + "attributes": { + "size": "24px", + "bold": true + }, + "insert": "关掉" + }, + { + "attributes": { + "size": "24px" + }, + "insert": "," + }, + { + "attributes": { + "size": "24px", + "bold": true + }, + "insert": "关掉" + }, + { + "insert": "," + }, + { + "attributes": { + "background": "#fff359" + }, + "insert": "一定要" + }, + { + "attributes": { + "background": "#fff359", + "bold": true + }, + "insert": "关掉" + }, + { + "insert": "\n再不关掉那些" + }, + { + "attributes": { + "bold": true + }, + "insert": "网络游戏" + }, + { + "insert": ",小孩哪有" + }, + { + "attributes": { + "bold": true + }, + "insert": "美好的未来" + }, + { + "insert": ",哪有" + }, + { + "attributes": { + "bold": true + }, + "insert": "美好的前程" + }, + { + "insert": ",祖国哪有" + }, + { + "attributes": { + "bold": true + }, + "insert": "栋梁之才" + }, + { + "insert": "\n" + } +] +``` + diff --git a/bb-api-collect/docs/opus/detail.md b/bb-api-collect/docs/opus/detail.md new file mode 100644 index 0000000000..6af39335b9 --- /dev/null +++ b/bb-api-collect/docs/opus/detail.md @@ -0,0 +1,2739 @@ +# 图文详细 + +## 获取图文详细信息 + +> https://api.bilibili.com/x/polymer/web-dynamic/v1/opus/detail + +*请求方法: GET* + +鉴权方式: `Cookie` 中 `buvid3` 存在且不为空 + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------------- | ------ | -------- | ------ | ---- | +| id | string | 动态 id | 必要 | 数字 | +| timezone_offset | number | 时区偏移 | 非必要 | 如 `-480` | +| features | string | 功能 | 非必要(部分专栏要求htmlNewStyle) | `onlyfansVote,onlyfansAssetsV2,decorationCard,htmlNewStyle,ugcDelete,editable,opusPrivateVisible,tribeeEdit,avatarAutoTheme,avatarTypeOpus` | + +**JSON 回复(旧版专栏未携带htmlNewStyle feature时)** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | number | 返回值 | 0: 成功
-352: 风控校验失败 | +| data | object | 数据本体 | | +| message | string | 错误信息 | 成功时为 `0` | +| ttl | number | `1` | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| fallback | object | 回退的内容信息 | | + +`fallback` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| id | number | 回退的内容ID | | +| type | number | 回退的内容类型 | 已知2为专栏 | + +**JSON 回复(正常返回情况):** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | number | 返回值 | 0: 成功
-352: 风控校验失败 | +| data | object | 数据本体 | | +| message | string | 错误信息 | 成功时为 `0` | +| ttl | number | `1` | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| item | object | 项 | 套了个娃 | + +`data.item` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| basic | object | 基本信息 | | +| id_str | string | 动态 id | | +| modules | object[] | 模块信息 | 参见 [功能模块](features.md) | +| type | number | 类型 | | +| fallback | number | 回滚信息 | 请检查请求参数 `features` | + +`data.item.basic` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| comment_id_str | string | 评论对象 id 字符串 | | +| comment_type | number | 评论区类型 | | +| like_icon | object | 点赞图标? | | +| rid_str | string | 关联 id 字符串 | | +| title | string | 图文标题 | | +| uid | number | 作者 mid (UID) | | + +`data.item.basic.like_icon` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| action_url | string | | | +| end_url | string | | | +| id | number | | | +| start_url | string | | | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/polymer/web-dynamic/v1/opus/detail' \ +--url-query 'id=933099353259638816' \ +--url-query 'features=onlyfansVote,onlyfansAssetsV2,decorationCard,htmlNewStyle,ugcDelete,editable,opusPrivateVisible,tribeeEdit,avatarAutoTheme,avatarTypeOpus' \ +-b 'buvid3=awa' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "data": { + "item": { + "basic": { + "comment_id_str": "34646640", + "comment_type": 12, + "like_icon": { + "action_url": "", + "end_url": "", + "id": 0, + "start_url": "" + }, + "rid_str": "34646640", + "title": "【服务搭建】零开销在线运行代码!glot.io服务私有化部署 - 哔哩哔哩", + "uid": 293793435 + }, + "id_str": "933099353259638816", + "modules": [ + { + "module_title": { + "text": "【服务搭建】零开销在线运行代码!glot.io服务私有化部署" + }, + "module_type": "MODULE_TYPE_TITLE" + }, + { + "module_author": { + "avatar": { + "container_size": { + "height": 1.375, + "width": 1.375 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/4f8f3f1f2d47f0dad84f66aa57acd4409ea46361.png" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + }, + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "var(--bg1)", + "border": "2px solid var(--bg1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 1, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "layers": [ + { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.787, + "width": 0.787 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + { + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.6875, + "axis_y": 0.6875, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1.375, + "width": 1.375 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": {} + } + }, + "resource": { + "res_animation": { + "webp_src": { + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i0.hdslb.com/bfs/garb/item/fe0b83b53e2342b16646f6e7a9370d8a867decdb.webp" + }, + "src_type": 1 + } + }, + "res_type": 4 + }, + "visible": true + } + ] + }, + { + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.7560000000000001, + "axis_y": 0.7726666666666667, + "coordinate_pos": 1 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 0.41666666666666663, + "width": 0.41666666666666663 + } + }, + "layer_config": { + "tags": { + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "background-color": "var(--bg1)", + "border": "2px solid var(--bg1)", + "borderRadius": "50%", + "boxSizing": "border-box" + } + } + }, + "ICON_LAYER": {} + } + }, + "resource": { + "res_image": { + "image_src": { + "local": 1, + "src_type": 2 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + } + ], + "mid": "293793435" + }, + "decorate_card": { + "big_card_url": "https://i0.hdslb.com/bfs/garb/item/c0cf2235089ed314d92f30efa855c9b5611fa2cd.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/garb/item/c0cf2235089ed314d92f30efa855c9b5611fa2cd.png", + "fan": { + "color": "#07b6d5", + "color_format": { + "colors": [ + "#07b6d5FF", + "#07b6d5FF" + ], + "end_point": "0,100", + "gradients": [ + 0, + 100 + ], + "start_point": "0,0" + }, + "is_fan": 1, + "name": "初音未来周年纪念", + "num_desc": "005638", + "number": 5638 + }, + "id": 2513, + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/c0cf2235089ed314d92f30efa855c9b5611fa2cd.png", + "item_id": 2513, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=2513&isdiy=0&part=card&from=post&f_source=garb&vmid=293793435&native.theme=1&navhide=1", + "name": "初音未来粉丝专属" + }, + "face": "https://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/293793435", + "label": "", + "mid": 293793435, + "more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "name": "社会易姐QwQ", + "official": { + "desc": "", + "role": 0, + "title": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "https://i0.hdslb.com/bfs/garb/item/4f8f3f1f2d47f0dad84f66aa57acd4409ea46361.png", + "image_enhance": "https://i0.hdslb.com/bfs/garb/item/fe0b83b53e2342b16646f6e7a9370d8a867decdb.webp", + "image_enhance_frame": "https://i0.hdslb.com/bfs/garb/item/127c507ec8448be30cf5f79500ecc6ef2fd32f2c.png", + "n_pid": 2511, + "name": "初音未来13周年", + "pid": 2511 + }, + "pub_location_text": "", + "pub_time": "编辑于 2024年05月19日 12:18", + "pub_ts": 1716092523, + "views_text": "", + "vip": { + "avatar_icon": { + "icon_resource": {}, + "icon_type": 1 + }, + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": 1770825600000, + "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": "http://i0.hdslb.com/bfs/vip/label_annual.png", + "text": "年度大会员", + "text_color": "#FFFFFF", + "use_img_label": true + }, + "nickname_color": "#FB7299", + "role": 3, + "status": 1, + "theme_type": 0, + "tv_due_date": 1640793600, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 2, + "vip_pay_type": 0 + } + }, + "module_type": "MODULE_TYPE_AUTHOR" + }, + { + "module_content": { + "paragraphs": [ + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "感谢 " + } + }, + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "color": "#ff968d", + "font_size": 17, + "style": {}, + "words": "来笙云 Laysense.cn" + } + }, + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": " 提供算力" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "作为一个全栈工程师,开发、维护和测试一些软件系统时,必然会涉及到多种编程语言,有时还需要测试一些编程语言的安全特性,常常需要敏捷地了解它们并立即上手。在朋友的推荐和社区分享下,我了解到一个名叫 glot.io 的开源项目。" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "它支持40多种编程语言,无论是热门的 Python、Go、Rust、Kotlin,还是冷门的 COBOL、Erlang、Haskell 只需在网页上选择对应的语言,即可开始编写。为使用者提供了一个 Sandbox(沙箱)和 Playground(游乐场)环境,既不需要配置它们的 Runtime(运行环境)和 IDE(集成开发环境),也不需要担心误操作对系统产生破坏性,还不会占用任何用户端的系统资源,实现真正的零开销运行代码。" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": 1120, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/article/06582181a80a3f367ae0486aec34759f293793435.png", + "width": 1776 + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "在代码编写界面,可以创建多个源码文件,完成后点击Run就能执行它并得到输出,类似我们平时编程那样,将输出打在终端上。整个过程不会生成任何可执行文件,所以它的应用场景不是在线编译,而是在线运行代码片段。" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "\n" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/bb4e8fc35a33ba0b771478f4bc5aaca7293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "glot.io 这个网站提供了公开的代码片段执行和分享功能,任何人在注册后都可以分享自己的代码片段,并使用它的 API。但有时为了安全性和访问速度考量,需要自行搭建这个开源平台,这篇文章将介绍 Glot 的私有化部署。" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 24, + "style": { + "bold": true + }, + "words": "Glot是什么" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "根据项目 README 上的一句介绍:" + } + } + ] + } + }, + { + "align": 0, + "para_type": 4, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "an open source pastebin with runnable snippets and API." + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "这是一个开源的共享剪切板和代码片段执行器,并提供 API。它使用 MIT 协议开源,代码托管于 github 之上。" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "https://github.com/glotcode/glot" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "Glot 并不是一个独立的工程,它分为多个组件,这样设计底层架构有利于业务解耦,降低后期维护和升级开发的难度,它们之间的逻辑关系如下:" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "\n" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/808dd5fa58016f392b15a36a0df27a29293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "由下面这些组件构成,也全部使用 MIT 协议开源,均托管于 Github:" + } + } + ] + } + }, + { + "align": 0, + "list": { + "items": [ + { + "level": 1, + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "color": "#ff968d", + "font_size": 17, + "style": {}, + "words": "glot-www" + } + }, + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": ":提供 B/S 前端应用" + } + } + ], + "order": 1 + }, + { + "level": 1, + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "color": "#ff968d", + "font_size": 17, + "style": {}, + "words": "docker-run" + } + }, + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": ":提供执行 glot-images 镜像能力的微服务" + } + } + ], + "order": 2 + }, + { + "level": 1, + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "color": "#ff968d", + "font_size": 17, + "style": {}, + "words": "glot-images" + } + }, + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": ":按需构建的执行器镜像" + } + } + ], + "order": 3 + }, + { + "level": 1, + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "color": "#ff968d", + "font_size": 17, + "style": {}, + "words": "code-runner" + } + }, + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": ":容器内的执行调度器" + } + } + ], + "order": 4 + } + ], + "style": 2 + }, + "para_type": 5 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "其中 glot-www 是一个 B/S 架构应用的服务器,用来提供一个面向用户的 WebUI(网站),它包含前后端的组件,后端使用 Haskell 语言编写。实现代码片段保存和共享、用户登录、以及共享剪切板所的功能,由 pgSQL 提供存储支持。与此同时,它与实际的代码执行业务互相解耦,使用 RestAPI 进行 RPC 调用,可做到前端服务器和后端代码执行服务器逻辑上隔离。" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "Glot 的代码执行沙箱基于 Docker,在容器中编译和运行,不但与宿主机隔离,且容器之间也相互隔离,还能对运行资源进行限制,防止宿主机被不信任的代码破坏。当然,各编程语言的执行容器构成不尽相同,这样才能在节约存储空间的同时最大保持运行效率,比如 C 和 C++ 共用了glot/clang这个镜像,C" + } + }, + { + "rich": { + "jump_url": "//search.bilibili.com/all?keyword=%20%E5%92%8C%20F", + "orig_text": "# 和 F#", + "text": "# 和 F#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" + }, + "type": "TEXT_NODE_TYPE_RICH" + }, + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": " 的镜像都有 mono 这个依赖……这些 Docker 镜像由 glot-images 项目进行生成,它并非使用传统的 Dockerfile,而是使用了 nix 进行构建,支持多种主流编程语言。" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "\n" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/8627bd181a4c0ef3f5985f2d80ed49a5293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "宿主机与沙箱的通讯,实际上就构建并将代码传入容器。这个传递方式不使用文件,而使用 stdi(基本输入)的方式传递 json,例如这样的形式:" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "echo '{\n "language": "python",\n "files": [\n {\n "name": "main.py",\n "content": "print(42)"\n }\n ]\n}' | docker run --rm -i --read-only --tmpfs /tmp:rw,noexec,nosuid,size=65536k --tmpfs /home/glot:rw,exec,nosuid,uid=1000,gid=1000,size=131072k -u glot -w /home/glot glot/javascript:latest", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "执行完成之后以 stdo(基本输出)的方式输出 json,stdout、stderr 流、以及错误信息在序列化后拆分成各个字段:" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "{\n "stdout": "42\\n",\n "stderr": "",\n "error": ""\n}", + "lang": "language-json" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "一般编程语言分为编译型、解释型和虚拟机型,其中解释型直接执行文本文件中的内容,编译型则需将其编译为可执行文件再执行,而虚拟机型在编译完之后,还需用 vm 执行字节码。glot-images 将各类编程语言生成的工作流统一归做 json 格式的文本流,这样标准化更利于开发和扩展,这种能力归功于 code-runner 这个组件。" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "code-runner 作为 glot 的一个特殊组件,并不运行在宿主机中,它是一个 cli 工具,运行在执行容器中,使用 Rust 语言开发。在 glot-images 的每个镜像中,均以相同方式工作在底层。它支持多种编程语言从编译到运行的生命周期管理,同时接管运行时的 stdio(基本输入输出)" + } + }, + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": { + "bold": true + }, + "words": "," + } + }, + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "例如 C 语言,首先会将输入的文本反序列化,写入到文件,接着调用 clang 编译这个文件,最后再运行编译器生成的可执行文件,执行过程中也会将预定义的 stdi 发送给程序,程序的 stdo/stderr 流被它记录下来随后序列化为 json 文本返回。实际上在使用docker run这类命令执行 glot-images 镜像时,就是调用了之中的 code-runner,而不是调用了clang这种编译器。" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "使用 stdi 传递 json 给它,就会调用相应的编译执行流程:" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "echo '{\n "language": "python",\n "files": [\n {\n "name": "main.py",\n "content": "print(42)"\n }\n ]\n}' | code-runner", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "与 glot-images 的镜像相同,执行后也会使用 stdo 以 json 格式返回:" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "{\n "stdout": "42\\n",\n "stderr": "",\n "error": ""\n}", + "lang": "language-json" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "要将这些跑在 Docker 上的执行器服务化、RPC(远程过程调用)化,必须有一个 daemon 在底层进行调度,一边开放 HTTP 服务,另一边通过 unix socket 操纵 DockerEngine,执行容器操作。提供这个能力的就是 docker-run 组件,它也使用 Rust 语言开发。" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "例如这样访问 docker-run,和上文中的例子相同:" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "curl 'http://localhost:8088/run' \\\n -H 'X-Access-Token: some-secret-token' \\\n -H 'Content-type: application/json' \\\n -d '{\n "image": "glot/python:latest",\n "payload": {\n "language": "python",\n "files": [\n {\n "name": "main.py",\n "content": "print(42)"\n }\n ]\n }\n}'", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "有了这些组件,就可以自行私有化搭建一个 glot 服务,因为各组件的标准化和解耦,可以随意进行裁剪和二次开发。" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "接下来将介绍 docker-run 和 glot-images 这两个基本组件的搭建(不搭建前端 WebUI 和共享服务)。" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 24, + "style": { + "bold": true + }, + "words": "Glot服务搭建" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "首先应该准备一台性能不错的服务器,要求 CPU 核心数和 RAM 不能太低。以下步骤使用 Debian 12 系统进行操作,整个过程需要有稳定的网络环境,并且已更新包管理器的索引。" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 24, + "style": { + "bold": true + }, + "words": "安装Docker和运行环境" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "首先需要安装前置依赖,其中 git 和 gcc 安装 Rust 时需要,runsc 是 gVisor 运行环境" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "sudo apt-get install ca-certificates curl git gcc runsc", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "安装 Docker,这里参考了官方文档的安装方式,先进行软件源的添加,再安装各组件" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "https://docs.docker.com/engine/install/debian/" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "sudo install -m 0755 -d /etc/apt/keyrings\nsudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc\nsudo chmod a+r /etc/apt/keyrings/docker.asc\necho \\\n "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \\\n $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \\\n sudo tee /etc/apt/sources.list.d/docker.list > /dev/null\nsudo apt update\n\nsudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "gVisor 作为谷歌开源的一款轻量容器运行时沙箱,可作为 Docker 的运行时中间件,隔离容器内的 syscall,提升容器安全性,具体可以参考官网 https://gvisor.dev" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "对于 Docker,需要配置 gVisor 为 DockerEngine 插件,创建配置文件后写入以下内容:" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "vi /etc/docker/daemon.json", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "\n" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "{\n "default-runtime": "runsc",\n "runtimes": {\n "runsc": {\n "path": "/usr/bin/runsc"\n }\n }\n}", + "lang": "language-json" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "在修改配置文件后,应重启 DockerEngine" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "systemctl restart docker", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "可以使用以下命令检查检查 Docker 和 gVisor 安装状态" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "docker system info\ndocker system info | grep 'runsc'", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "\n" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/f2a9046662ce5bdc93a5bbe7393dd2b4293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "\n" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/888de2ab19dede7ec6880f407269519c293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "接者我们创建名为glot的用户,作为 daemon 的运行角色" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "useradd -m glot\nusermod -aG docker glot", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "安装 Rust,这里参考官方文档,使用脚本进行安装" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "https://rustup.rs/" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "\n" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/2d7118b743cd2f10cd289e59969eeb01293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "安装完毕后,可以使用以下命令检查 Rust 的安装" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "cargo -V", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "\n" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/0e40ab6cc26aa95bcaf7458159316d7c293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "因官方的 crates 源速度很慢,如果国内使用可以换为镜像源,这里使用了 SJTU 镜像" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "vi ~/.cargo/config.toml", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "\n" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/4b8b4b8e7550009d6fd0c4439922564a293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 24, + "style": { + "bold": true + }, + "words": "编译docker-run" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "克隆 docker-run 项目,准备使用源码进行编译安装" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "git clone https://github.com/glotcode/docker-run glot-docker-run", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "进入仓库目录,使用 cargo 编译 Rust 工程" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "cd glot-docker-run\ncargo b -r", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "\n" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/7c39ed2031e7932c1bc24926ea1c3025293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "检查编译结果,在工程目录的target/release中将会生成名为docker-run的可执行文件" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "\n" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/51d7ad2ddf5dd75c531e267965c6ddb6293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "复制可执行文件和 systemd 服务模板" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "cp target/release/docker-run /home/glot/bin/\ncp systemd/docker-run.service /etc/systemd/system/", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "docker-run 服务使用 systemd 进行托管,作为 daemon 运行,它对外提供一个 http 服务,其他应用使用 RestAPI 与之对接\n编辑 systemd 服务配置文件" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "vi /etc/systemd/system/docker-run.service", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "docker-run 的配置文件全部为环境变量,一些重要的参数已经给出了注释" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "其中SERVER_LISTEN_ADDR和SERVER_LISTEN_PORT决定了 daemon 监听的 ip 和端口号,可以根据需求修改" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "SERVER_WORKER_THREADS为 worker 线程数,根据实际业务并发量修改,即越多可同时执行的任务越多" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "API_ACCESS_TOKEN是 RestAPI 的访问 Token,设定一个较复杂的值,可防止未授权访问,在调用中以 HTTP 请求 Header 的X-Access-Token字段进行传递" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "RUN_MAX_EXECUTION_TIME参数用来限制任务执行的超时时间,其单位为秒,如果一个任务大于这个时间没有执行完毕,docker-run 就会销毁这个容器,并会返回一个 400 错误" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "RUN_MAX_OUTPUT_SIZE参数是用来限制最大输出量的,它的单位是 Byte,如果输出的内容过大,同样会被丢弃并报错\n这些参数的详细配置也可以参考 docker-run 项目的 README: https://github.com/glotcode/docker-run?tab=readme-ov-file#environment-variables" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "[Unit]\nDescription=docker-run\n\n[Service]\nUser=glot\nGroup=glot\nRestart=always\nRestartSec=10\nExecStart=/home/glot/bin/docker-run\n# 服务绑定 ip\nEnvironment="SERVER_LISTEN_ADDR=0.0.0.0"\n# 服务监听端口\nEnvironment="SERVER_LISTEN_PORT=8088"\n# worker 线程数\nEnvironment="SERVER_WORKER_THREADS=10"\n# API Token\nEnvironment="API_ACCESS_TOKEN=some-secret-token"\n# Docker socket 路径\nEnvironment="DOCKER_UNIX_SOCKET_PATH=/var/run/docker.sock"\nEnvironment="DOCKER_UNIX_SOCKET_READ_TIMEOUT=3"\nEnvironment="DOCKER_UNIX_SOCKET_WRITE_TIMEOUT=3"\n# 容器主机名\nEnvironment="DOCKER_CONTAINER_HOSTNAME=glot"\n# 容器用户\nEnvironment="DOCKER_CONTAINER_USER=glot"\n# 容器最大内存限制\nEnvironment="DOCKER_CONTAINER_MEMORY=1000000000"\n# 容器内是否禁用网络支持\nEnvironment="DOCKER_CONTAINER_NETWORK_DISABLED=true"\nEnvironment="DOCKER_CONTAINER_ULIMIT_NOFILE_SOFT=90"\nEnvironment="DOCKER_CONTAINER_ULIMIT_NOFILE_HARD=100"\nEnvironment="DOCKER_CONTAINER_ULIMIT_NPROC_SOFT=90"\nEnvironment="DOCKER_CONTAINER_ULIMIT_NPROC_HARD=100"\nEnvironment="DOCKER_CONTAINER_CAP_DROP=MKNOD NET_RAW NET_BIND_SERVICE"\nEnvironment="DOCKER_CONTAINER_READONLY_ROOTFS=true"\nEnvironment="DOCKER_CONTAINER_TMP_DIR_PATH=/tmp"\nEnvironment="DOCKER_CONTAINER_TMP_DIR_OPTIONS=rw,noexec,nosuid,size=65536k"\n# 容器工作目录\nEnvironment="DOCKER_CONTAINER_WORK_DIR_PATH=/home/glot"\nEnvironment="DOCKER_CONTAINER_WORK_DIR_OPTIONS=rw,exec,nosuid,size=131072k"\n# 容器执行超时时间\nEnvironment="RUN_MAX_EXECUTION_TIME=15"\n# 最大允许输出\nEnvironment="RUN_MAX_OUTPUT_SIZE=100000"\n# 日志级别\nEnvironment="RUST_LOG=debug"\n\n[Install]\nWantedBy=multi-user.target", + "lang": "language-yaml" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "修改完配置文件就可启动服务了,并将它设为开机自启" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "systemctl daemon-reload\nsystemctl enable --now docker-run.service", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "GET 请求刚才配置的那个地址的根路径,测试服务运行状态正常,我这里是 http://localhost:8088/" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/7e0a6d73cdb1ba63bcfcbe94df9c7b39293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 24, + "style": { + "bold": true + }, + "words": "拉取Docker镜像" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "glot-images 构建了各编程语言的执行镜像,这些镜像使用 nix 构建,但因为 nix 的配置比较复杂,且占用存储空间巨大,这里直接使用上传在 DockerHub 的镜像了(弊端就是语言版本比较旧)" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "https://hub.docker.com/u/glot" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/e63013e3c15cd556ec7ce82048d43889293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "通过 docker pull命令拉取各个镜像,可以按照自己的需求拉取,比如你只需要执行某几个编程语言" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "docker pull glot/assembly\ndocker pull glot/ats\ndocker pull glot/bash\ndocker pull glot/clang\ndocker pull glot/clisp\ndocker pull glot/clojure\ndocker pull glot/cobol\ndocker pull glot/coffeescript\ndocker pull glot/crystal\ndocker pull glot/csharp\ndocker pull glot/dart\ndocker pull glot/elixir\ndocker pull glot/elm\ndocker pull glot/erlang\ndocker pull glot/fsharp\ndocker pull glot/golang\ndocker pull glot/groovy\ndocker pull glot/guile\ndocker pull glot/hare\ndocker pull glot/haskell\ndocker pull glot/idris\ndocker pull glot/java\ndocker pull glot/javascript\ndocker pull glot/julia\ndocker pull glot/kotlin\ndocker pull glot/lua\ndocker pull glot/mercury\ndocker pull glot/nim\ndocker pull glot/nix\ndocker pull glot/ocaml\ndocker pull glot/pascal\ndocker pull glot/perl\ndocker pull glot/php\ndocker pull glot/python\ndocker pull glot/raku\ndocker pull glot/ruby\ndocker pull glot/rust\ndocker pull glot/sac\ndocker pull glot/scala\ndocker pull glot/swift\ndocker pull glot/typescript\ndocker pull glot/zig", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "这些全部拉取下来大概需要38GB,可以使用docker images命令检查拉取情况" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/82a01995548eb266d59f7fd22f75e542293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "如果已经拉取了所有的镜像,可以执行单元测试脚本,来验证各编程语言执行容器的正确性,在 docker-run 的目录下的scripts目录内" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "cd glot-docker-run/scripts/\n./test_glot.sh 'http://localhost:8088' 'some-secret-token'", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "\n" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/004e79df950a4bc93ff42fae8017d0aa293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 24, + "style": { + "bold": true + }, + "words": "使用Glot服务" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "docker-run 这个组件对外提供 RestAPI 接口,其他进程或者其他主机可以直接调用,它共有三个功能对应其路径:" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/a28b283d2075bbd78c12e1d2859fd40d293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "查询服务状态" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "curl http://localhost:8088/", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "返回 daemon 的服务名、版本等" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "{\n "name": "docker-run",\n "version": "1.4.0",\n "description": "Api for running code in transient docker containers"\n}", + "lang": "language-json" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "查询宿主机 DockerEngine 信息,访问这个接口需要在请求 Header 的X-Access-Token字段中携带 Token" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "curl http://localhost:8088/version \\\n -H 'X-Access-Token: some-secret-token'", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "执行成功将会返回 DockerEngine 的版本信息" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "{\n "docker": {\n "version": "26.1.2",\n "apiVersion": "1.45",\n "gitCommit": "ef1912d",\n "goVersion": "go1.21.10",\n "os": "linux",\n "arch": "amd64",\n "kernelVersion": "6.2.16-3-pve",\n "buildTime": "2024-05-08T13:59:59.000000000+00:00",\n "platform": {\n "name": "Docker Engine - Community"\n },\n "components": [\n {\n "name": "Engine",\n "version": "26.1.2"\n },\n {\n "name": "containerd",\n "version": "1.6.31"\n },\n {\n "name": "runsc",\n "version": "0.0~20221219.0"\n },\n {\n "name": "docker-init",\n "version": "0.19.0"\n }\n ]\n }\n}", + "lang": "language-json" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "执行响应的代码前,需要构建一个 json 请求体,用来描述创建的执行任务的行为,下表是它的定义:" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/752ce6ef76a448158eb97222befa7c92293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "payload 结构:" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/752ce6ef76a448158eb97222befa7c92293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "文件对象的结构:" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/752ce6ef76a448158eb97222befa7c92293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "eg:" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "{\n "image": "glot/python:latest",\n "payload": {\n "language": "python",\n "files": [\n {\n "name": "main.py",\n "content": "print(42)"\n }\n ]\n }\n}", + "lang": "language-json" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "访问这个接口也需要在请求 Header 中携带 Token:" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "curl 'http://localhost:8088/run' \\\n -H 'X-Access-Token: some-secret-token' \\\n -H 'Content-type: application/json' \\\n -d '{\n "image": "glot/python:latest",\n "payload": {\n "language": "python",\n "files": [\n {\n "name": "main.py",\n "content": "print(42)"\n }\n ]\n }\n}'", + "lang": "language-bash" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "我们可以直接将它与自己熟悉的编程语言对接,实现给应用或者平台提供运行任意代码的能力。" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "这里使用 Python 通过 RestAPI 调用 glot(docker-run),实现运行一段 rust 代码并取回输出为字符串:" + } + } + ] + } + }, + { + "align": 0, + "code": { + "content": "import requests\n\ndef run_code(image, lang, file_name, code):\n resp = requests.post(\n url="http://localhost:8088/run",\n headers={\n "X-Access-Token": "some-secret-token",\n },\n json={\n "image": image,\n "payload": {\n "language": lang,\n "files": [\n {\n "name": file_name,\n "content": code,\n },\n ],\n },\n },\n )\n json_content = resp.json()\n return json_content\n\n\nimage = "glot/rust:latest"\nlang = "rust"\nfile_name = "main.rs"\ncode = """\nfn main() {\n for i in 1..=9 {\n for j in 1..=i {\n print!("{}x{}={:2} ", j, i, j * i);\n }\n println!();\n }\n}\n"""\n\nresult = run_code(image, lang, file_name, code)\nprint(result["stdout"])", + "lang": "language-python" + }, + "para_type": 7 + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "测试可以正确输出执行内容" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "\n" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": null, + "live_url": null, + "size": null, + "url": "https://i0.hdslb.com/bfs/new_dyn/21e396261fb607d4823f7ec4327908b1293793435.png", + "width": null + } + ], + "style": 2 + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "有了通用接口的能力,我们就有了将其集成进自己平台的可能,只要发挥创造力,就可以围绕在线执行代码提供相关的业务,或者作为微服务连接上游的业务,比如搭建 OJ(在线判题)平台等。以及 glot 项目以 MIT 协议开源,这意味着我们可以随意修改底层代码,比如增加网络和共享路径支持、增加第三方库等。总之,这是一个完成度很高、十分推荐的开源项目。" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "由 " + } + }, + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "color": "#ff968d", + "font_size": 17, + "style": {}, + "words": "来笙云 Laysense.cn" + } + }, + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": " 强力支持" + } + } + ] + } + }, + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "原文链接:https://shakaianee.top/archives/1002/" + } + } + ] + } + } + ] + }, + "module_type": "MODULE_TYPE_CONTENT" + }, + { + "module_extend": { + "items": [ + { + "icon": null, + "jump_url": "//search.bilibili.com/all?keyword=%E8%BF%90%E7%BB%B4", + "text": "运维" + }, + { + "icon": null, + "jump_url": "//search.bilibili.com/all?keyword=%E6%9C%8D%E5%8A%A1%E6%90%AD%E5%BB%BA", + "text": "服务搭建" + }, + { + "icon": null, + "jump_url": "//search.bilibili.com/all?keyword=glot.io", + "text": "glot.io" + } + ] + }, + "module_type": "MODULE_TYPE_EXTEND" + }, + { + "module_bottom": { + "share_info": { + "pic": "https://static.hdslb.com/mobile/img/app_logo.png", + "summary": "感谢 来笙云 Laysense.cn 提供算力 作为一个全栈工程师,开发、维护和测试一些软件系统时,必然会涉及到多种编程语言,有时还需要测试一些编程语言的安全特性,常常需要敏捷地了解它们并立即上手。在朋友的推荐和社区分享下,我了解到一个名叫 glot.io 的开源项目。 它支持40多种编程语言,无论是热门的 Python、Go、Rust、Kotlin,还是冷门的 COBOL、Erlang、Haskell 只需在网页上选择对应的语言,即可开始编写。为使用者提供了一个 Sandbox(沙箱)和 Playground(游乐场)环境,既不需要配置它们的 Runtime(运行环境)和 IDE(集成开发环境),也不需要担心误操作对系统产生破坏性,还不会占用任何用户端的系统资源,实现真正的零开销运行代码。 [图片] 在代码编写界面,可以创建多个源码文件,完成后点击Run就能执行它并得到输出,类似我们平时编程那样,将输出打在终端上。整个过程不会生成任何可执行文件,所以它的应用场景不是在线编译,而是在线运行代码片段。 [图片] glot.io 这个网站提供了公开的代码片段执行和分享功能,任何人在注册后都可以分享自", + "title": "【服务搭建】零开销在线运行代码!glot.io服务私有化部署" + } + }, + "module_type": "MODULE_TYPE_BOTTOM" + }, + { + "module_stat": { + "coin": { + "count": 1, + "forbidden": false, + "status": false + }, + "comment": { + "count": 3, + "forbidden": false + }, + "favorite": { + "count": 4, + "forbidden": false, + "status": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 17, + "forbidden": false, + "status": false + } + }, + "module_type": "MODULE_TYPE_STAT" + } + ], + "type": 1 + } + }, + "message": "0", + "ttl": 1 +} +``` +
+ + diff --git a/bb-api-collect/docs/opus/features.md b/bb-api-collect/docs/opus/features.md new file mode 100644 index 0000000000..b54e9616d3 --- /dev/null +++ b/bb-api-collect/docs/opus/features.md @@ -0,0 +1,1295 @@ +# 功能模块 + +部分动态相关接口请求存在 `features` 参数, 意为功能
+主要用于控制返回结果中的 `modules` 中的内容, 意为模块
+此两者在一定程度上为对应关系, 但也存在大量例外
+本页文档整理了大部分常见的已知功能与模块以供参考 + +## features + +请求 URL 参数, 用 `,` 分隔 + +| 名称 | 含义 | 备注 | 示例 | +| ---- | ---- | ---- | ---- | +| htmlNewStyle | 是否显示专栏正文 | 对于纯动态类型接口无效 | 1056353752004427792 | +| itemOpusStyle | 是否以图文风格显示动态 | 部分动态强制需要, 对于图文类型接口无效 | 1060771233257226247, 1065507757569867779 | +| listOnlyfans | | | | +| opusBigCover | 是否在返回结果中区分大封面与九宫格 | 对于图文接口似乎无效, 前置条件 `itemOpusStyle` | 1052711525276450824 | +| onlyfansVote | 是否在投票信息中增加参与按钮等 | | 1060771233257226247 | +| onlyfansAssetsV2 | | | | +| forwardListHidden | | | | +| ugcDelete | | | | +| onlyfansQaCard | 是否展示更详细的展示充电专属问答 | | 1087983622038749191 | +| commentsNewVersion | | | | +| decorationCard | 是否以卡片形式显示装扮 | | 566950981753221664 | +| editable | 是否在右上角三点菜单中显示 `编辑` | 必须是自己发送的动态才有效果 | 1065142062572109830 | +| opusPrivateVisible | | | | +| tribeeEdit | | | | +| avatarAutoTheme | 头像颜色使用 CSS 变量 | 对于纯动态类型接口无效 | 933099353259638816 | +| avatarTypeOpus | | | | + +## modules + +内容以 [获取图文详细信息](detail.md) 为基础 + +### MODULE_TYPE_TITLE + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| module_title | object | 标题模块 | | +| module_type | string | 模块类型 | `MODULE_TYPE_TITLE` | + +`module_title` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| text | string | 标题内容 | | + +
+查看示例: + +```json +{ + "module_title": { + "text": "欢迎加入粉丝交流群~" + }, + "module_type": "MODULE_TYPE_TITLE" +} +``` +
+ + + +### MODULE_TYPE_AUTHOR + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| module_author | object | 作者模块 | | +| module_type | string | 模块类型 | `MODULE_TYPE_AUTHOR` | + +`module_author` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| avater | object | 头像信息 | 主要用于网页渲染, 若感兴趣可参考 [图片格式化](../misc/picture.md) | +| decorate | object | 装扮 | 仅当动态接口且无 `decorationCard` 时存在 | +| decorate_card | object | 装扮 | 仅当图文接口时存在 | +| decoration_card | object | 装扮 | 仅当动态接口且有 `decorationCard` 时存在, 同 `decorate_card` | +| face | string | 头像 URL | | +| face_nft | boolean | 是否为 NFT 头像 | | +| following | boolean | 是否关注此 UP 主 | 自己的动态为 `null` | +| jump_url | string | 跳转链接 | | +| label | string | 名称前标签 | `合集`
`电视剧`
`番剧` | +| mid | number | UP 主 UID
剧集 SeasonId | | +| more | object | 三点按钮中的项目 | 参见 [module_more](#module_more), 仅图文接口 | +| name | string | UP 主名称
剧集名称
合集名称 | | +| official | object | UP 主认证信息 | 仅图文接口 | +| official_verify | object | UP主认证信息 | 仅动态接口 | +| pendant | object | UP 主头像框 | | +| pub_action | string | 更新动作描述 | 仅动态接口
`投稿了视频`
`直播了`
`投稿了文章`
`更新了合集`
`与他人联合创作`
`发布了动态视频`
`投稿了直播回放` | +| pub_location_text | string | 空 | | +| pub_time | string | 更新时间 | `x分钟前`
`x小时前`
`昨天`
等 | +| pub_ts | number | 更新时间戳 | UNIX 秒级时间戳 | +| views_text | string | | | +| vip | object | UP 主大会员信息 | | +| type | string | 作者类型 | 仅动态接口, [作者类型](../dynamic/dynamic_enum.md#作者类型) | +| nft_info | object | NFT 头像信息 | 可能不存在 | + +`module_author.avatar` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| container_size | object | | | +| fallback_layers | object | | | +| mid | string | | | + +`module_author.avatar.container_size` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| height | number | | | +| width | number | | | + +`module_author.avatar.fallback_layers` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| is_critical_group | boolean | | | +| layers | object[] | | | + +`module_author.avatar.fallback_layers.layers[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| general_spec | object | | | +| layer_config | object | | | +| resource | object | | | +| visible | boolean | | | + +`module_author.avatar.fallback_layers.layers[].general_spec` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| pos_spec | object | | | +| render_spec | object | | | +| size_spec | object | | | + +`module_author.avatar.fallback_layers.layers[].general_spec.pos_spec` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| axis_x | number | | | +| axis_y | number | | | +| coordinate_pos | number | | | + +`module_author.avatar.fallback_layers.layers[].general_spec.render_spec` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| opacity | number | | | + +`module_author.avatar.fallback_layers.layers[].general_spec.size_spec` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| height | number | | | +| width | number | | | + +`module_author.avatar.fallback_layers.layers[].layer_config` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| is_critical | boolean | | | +| tags | object | | | + +`module_author.avatar.fallback_layers.layers[].layer_config.tags` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| AVATAR_LAYER | object | | | +| GENERAL_CFG | object | | | + +`module_author.avatar.fallback_layers.layers[].layer_config.tags.AVATAR_LAYER` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | + +`module_author.avatar.fallback_layers.layers[].layer_config.tags.GENERAL_CFG` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| config_type | number | | | +| general_config | object | | | + +`module_author.avatar.fallback_layers.layers[].layer_config.tags.GENERAL_CFG.general_config` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| web_css_style | object | | | + +`module_author.avatar.fallback_layers.layers[].layer_config.tags.GENERAL_CFG.general_config.web_css_style` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| borderRadius | string | | | + +`module_author.avatar.fallback_layers.layers[].resource` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| res_image | object | | | +| res_type | number | | | + +`module_author.avatar.fallback_layers.layers[].resource.res_image` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| image_src | object | | | + +`module_author.avatar.fallback_layers.layers[].resource.res_image.image_src` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| placeholder | number | | | +| remote | object | | | +| src_type | number | | | + +`module_author.avatar.fallback_layers.layers[].resource.res_image.image_src.remote` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| bfs_style | string | | | +| url | string | | | + +`module_author.decorate` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| card_url | string | 动态卡片小图标图片URL | | +| fan | object | 粉丝装扮信息 | | +| id | number | 装扮 ID | | +| jump_url | string | 跳转 URL | | +| name | string | 装扮名称 | | +| type | number | `1` `2` `3` | | + +`module_author.decorate.fan` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| color | string | 编号颜色 | | +| color_format | object | 颜色格式 | | +| is_fan | boolean | 是否是粉丝装扮 | | +| num_str | string | 装扮编号前缀 | 如 `NO.` | +| number | number | 装扮编号 | | + + +`module_author.decorate.fan.color_format` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| colors | string[] | 颜色 | 带 `#` 前缀的 16 进制颜色代码 | +| end_point | string| 端点 | `0,100` | +| gradients | number[] | 渐变 | 内容 [0, 100] | +| start_point | string | 起点 | `0,0` | + +`module_author.decorate_card` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| big_card_url | string | 大装扮卡片 URL | | +| card_type | number | 装扮卡片类型 | | +| card_type_name | string | 装扮卡片类型名称 | | +| card_url | string | 装扮卡片 URL | | +| fan | object | 粉丝装扮信息 | 同 `module_author.decorate.fan` | +| id | number | 装扮 ID | | +| image_enhance | string | 同 `card_url`? | | +| item_id | number | 项目 ID? | | +| item_type | number? | 项目类型? | 图文接口当 `decorationCard` 时才有此项 | +| jump_url | string | 跳转 URL | | +| name | string | 装扮名称 | | + + + +`module_author.official` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| desc | string | 认证说明 | | +| role | number | | | +| title | string | | | +| type | number | 认证类型 | | + +`module_author.pendant` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| expire | number | 过期时间 | 此接口返回恒为`0` | +| image | string | 头像框图片 URL | | +| image_enhance | string | 头像框图片 URL | | +| image_enhance_frame | string | 头像框图片逐帧序列 URL | | +| n_pid | number | 同 `pid` | | +| name | string | 头像框名称 | | +| pid | number | 头像框id | | + +`module_author.vip` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| avatar_icon | object | | 仅图文接口 | +| avatar_subscript | number | 是否显示角标 | 0:不显示
1:显示 | +| avatar_subscript_url | string | 空 | | +| due_date | number | 大会员过期时间戳 | UNIX 毫秒时间戳 | +| label | object | 大会员标签 | | +| nickname_color | string | 名字显示颜色 | 大会员:`#FB7299` | +| role | number | | 仅图文接口 | +| status | number | 大会员状态 | 0:无
1:有
2:封禁? | +| theme_type | number | 主题类型? | 仅图文接口 | +| tv_due_date | number | TV 端过期时间? | 仅图文接口 | +| tv_vip_pay_type | number | TV 端付费状态? | 仅图文接口| +| tv_vip_status | number | TV 端会员状态? | | +| type | number | 大会员类型? | | +| vip_pay_type | number | 大会员付费类型? | + +`module_author.vip.avatar_icon` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| icon_resource | object | | | + +`module_author.vip.avatar_icon.icon_resource` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | + +`module_author.vip.label` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| bg_color | string | 会员标签背景颜色 | `#FB7299` | +| bg_style | number | `0` `1` | | +| border_color | string | 空 | | +| img_label_uri_hans | string | 大会员牌子图片 | 动态版 简体版 | +| img_label_uri_hans_static | string | 大会员牌子图片 | 静态版 简体版 | +| img_label_uri_hant | string | 大会员牌子图片 | 动态版 繁体版 | +| img_label_uri_hant_static | string | 大会员牌子图片 | 静态版 繁体版 | +| label_theme | string | 会员标签 | vip:大会员
annual_vip:年度大会员
ten_annual_vip:十年大会员
hundred_annual_vip:百年大会员
fools_day_hundred_annual_vip:最强绿鲤鱼 | +| path | string | 空 | | +| text | string | 会员类型文案 | `大会员` `年度大会员` `十年大会员` `百年大会员` `最强绿鲤鱼` | +| text_color | string | 用户名文字颜色 | | +| use_img_label | boolean | `true` | | + +`module_author.nft_info`: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| region_icon | string | NFT头像角标URL | 类型1:https://i0.hdslb.com/bfs/activity-plat/static/20220506/334553dd7c506a92b88eaf4d59ac8b4d/j8AeXAkEul.gif
类型2:https://i0.hdslb.com/bfs/activity-plat/static/20220506/334553dd7c506a92b88eaf4d59ac8b4d/IOHoVs1ebP.gif | +| region_type | number | NFT头像角标类型 | 1,2 | +| show_status | number | `1` | | + +
+查看示例: + +```json +{ + "module_author": { + "avatar": { + "container_size": { + "height": 1.35, + "width": 1.35 + }, + "fallback_layers": { + "is_critical_group": true, + "layers": [ + { + "general_spec": { + "pos_spec": { + "axis_x": 0.675, + "axis_y": 0.675, + "coordinate_pos": 2 + }, + "render_spec": { + "opacity": 1 + }, + "size_spec": { + "height": 1, + "width": 1 + } + }, + "layer_config": { + "is_critical": true, + "tags": { + "AVATAR_LAYER": {}, + "GENERAL_CFG": { + "config_type": 1, + "general_config": { + "web_css_style": { + "borderRadius": "50%" + } + } + } + } + }, + "resource": { + "res_image": { + "image_src": { + "placeholder": 6, + "remote": { + "bfs_style": "widget-layer-avatar", + "url": "https://i2.hdslb.com/bfs/face/77906db03b1eefac02613de184afad03f7bc58d7.jpg" + }, + "src_type": 1 + } + }, + "res_type": 3 + }, + "visible": true + } + ] + }, + "mid": "645769214" + }, + "decorate_card": { + "big_card_url": "https://i0.hdslb.com/bfs/vip/e2ffa1d1d491fe0464338ed3921327ef5e4b42c5.png", + "card_type": 2, + "card_type_name": "免费", + "card_url": "https://i0.hdslb.com/bfs/vip/a9e3d993c7a15e88ce0bf714a142f7d2b44121e2.png", + "fan": {}, + "id": 28, + "image_enhance": "https://i0.hdslb.com/bfs/vip/a9e3d993c7a15e88ce0bf714a142f7d2b44121e2.png", + "item_id": 28, + "item_type": 1, + "jump_url": "https://www.bilibili.com/h5/mall/equity-link/collect-home?item_id=28&isdiy=0&part=card&from=post&f_source=garb&vmid=645769214&native.theme=1&navhide=1", + "name": "2233娘" + }, + "face": "https://i2.hdslb.com/bfs/face/77906db03b1eefac02613de184afad03f7bc58d7.jpg", + "face_nft": false, + "following": true, + "jump_url": "//space.bilibili.com/645769214", + "label": "", + "mid": 645769214, + "more": { + "three_point_items": [ + { + "label": "举报", + "type": "THREE_POINT_REPORT" + } + ] + }, + "name": "Session小胡", + "official": { + "desc": "", + "role": 0, + "title": "", + "type": -1 + }, + "pendant": { + "expire": 0, + "image": "", + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0, + "name": "", + "pid": 0 + }, + "pub_location_text": "", + "pub_time": "2025年04月06日 20:18", + "pub_ts": 1743941902, + "views_text": "", + "vip": { + "avatar_icon": { + "icon_resource": {} + }, + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": 1665158400000, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + }, + "nickname_color": "", + "role": 0, + "status": 0, + "theme_type": 0, + "tv_due_date": 0, + "tv_vip_pay_type": 0, + "tv_vip_status": 0, + "type": 1, + "vip_pay_type": 0 + } + }, + "module_type": "MODULE_TYPE_AUTHOR" +} +``` +
+ + + +### module_more + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| module_more | object | 三点更多模块 | | + +`module_more` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| three_point_items | object[] | 右上角三点菜单 | 套了个娃 | + +`module_more.three_point_items[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| label | string | 显示文本 | | +| modal | object? | 弹出框文本 | | +| params | object? | 参数信息 | | +| type | string | 三点操作类型 | 参见 [右上角三点菜单](../dynamic/dynamic_enum.md#右上角三点菜单) | + +`module_more.three_point_items[].modal` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| cancel | string | 取消文本 | | +| confirm | string | 确认文本 | | +| content | string | 内容文本 | | +| title | string | 标题文本 | | + +`module_more.three_point_items[].params` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| dyn_id_str | string | 动态 id 字符串 | | +| dyn_type | number | 动态类型 | | +| rid_str | string | 动态 id 字符串 | | + + + +
+查看示例: + +```json +{ + "three_point_items": [ + { + "label": "编辑", + "type": "THREE_POINT_EDIT" + }, + { + "label": "可见范围", + "params": { + "dynamic_id": "1067779202512584729", + "status": 0, + "type": 1 + }, + "type": "THREE_POINT_PRIVATE" + }, + { + "label": "删除", + "modal": { + "cancel": "取消", + "confirm": "确认删除", + "content": "动态删除后将无法恢复,请谨慎操作", + "title": "要删除动态吗?" + }, + "params": { + "dyn_id_str": "1067779202512584729", + "dyn_type": 1, + "rid_str": "1067779202512584729" + }, + "type": "THREE_POINT_DELETE" + } + ] +} +``` + +
+ +### MODULE_TYPE_STAT + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| module_stat | object | 统计模块 | | +| module_type | string | 模块类型 | `MODULE_TYPE_STAT` | + +`module_stat` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| coin | object | 硬币数据 | 仅图文接口 | +| comment | object | 评论数据 | | +| favorite | object | 收藏数据 | 仅图文接口 | +| forward | object | 转发数据 | | +| like | object | 点赞数据 | | + +`module_stat` 中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| count | number | 数量 | | +| forbidden | boolean | 是否屏蔽 | | +| hidden | boolean | 是否隐藏 | | +| status | boolean | 当前状态 | 是否已进行该操作 | + +
+查看示例: + +```json +{ + "module_stat": { + "coin": { + "count": 0, + "forbidden": false, + "hidden": true + }, + "comment": { + "count": 42, + "forbidden": false + }, + "favorite": { + "count": 0, + "forbidden": false, + "status": false + }, + "forward": { + "count": 0, + "forbidden": false + }, + "like": { + "count": 56, + "forbidden": false, + "status": true + } + }, + "module_type": "MODULE_TYPE_STAT" +} +``` +
+ + + +### MODULE_TYPE_CONTENT + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| module_content | object | 内容模块 | | +| module_type | string | 模块类型 | `MODULE_TYPE_CONTENT` | + +`module_content` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| paragraphs | object[] | 段落 | | + +`module_content.paragraphs[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| align | number | 对齐方式 | 0: 左对齐 (默认)
1: 居中
2: 右对齐 | +| para_type | number | 段落类型 | 1: 文本
2: 图片
3: 分割线
4: 块引用
5: 列表
6: 链接卡片
7: 代码 | +| text | object | 文本 | `para_type=1` 或 `para_type=4` | +| pics | object | 图片 | `para_type=2` | +| line | object | 分割线 | `para_type=3` | +| list | object | 列表 | `para_type=5` | +| link_card | object | 链接卡片 | `para_type=6` | +| code | object | 代码 | `para_type=7` | + +`module_content.paragraphs[].text` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| nodes | object[] | 文本节点 | | + +`module_content.paragraphs[].text.nodes[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| type | string | 文本节点类型 | 纯文本: `TEXT_NODE_TYPE_WORD`
富文本: `TEXT_NODE_TYPE_RICH` | +| word | object | 纯文本 | 仅 `type='TEXT_NODE_TYPE_WORD'` | +| rich | object | 富文本 | 仅 `type='TEXT_NODE_TYPE_RICH'`, 详细参见 [富文本节点](rich_text_nodes.md) | +| formula | object | 公式 | 仅 `type='TEXT_NODE_TYPE_FORMULA' | + +`module_content.paragraphs[].text.nodes[].word` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| font_size | number | 字体大小 | 用于控制文本所用标签名 (如 `h1` `h2` `p`) 及行高 | +| style | object | 补充样式 | | +| words | string | 文本内容 | | + +`module_content.paragraphs[].text.nodes[].formula` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| latex_content | string | 公式内容 | LaTeX | + +`module_content.paragraphs[].line` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| pic | object | 图片 | | + +`module_content.paragraphs[].line.pic` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| height | number | 高度 | | +| url | string | 图片 URL | | + +`module_content.paragraphs[].list` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| style | number | 样式 | 1: 有序列表
2: 无序列表 | +| items | object[] | 列表项 | | + +`module_content.paragraphs[].list.items[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| level | number | 级别 | | +| nodes | object[] | 文本节点 | 同 `module_content.paragraphs[].text.nodes[]` 对象 | +| order | number | 序号 | | + +`module_content.paragraphs[].pic` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| pics | object[] | 图片 | 套了个娃 | +| style | number | 样式 | 1: isAlbum | + +`module_content.paragraphs[].pic.pics[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| height | number | 高度 | | +| live_url | unknown | 动图 URL? | | +| size | number \| null | 大小 | 单位: ki | +| url | string | 图片 URL | | +| width | number | 宽度 | | + +`module_content.paragraphs[].link_card` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| card | object | 卡片内容 | | + +`module_content.paragraphs[].link_card.card` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| oid | string | 关联 id | 可能为 `"undefined"` | +| type | string | 卡片类型 | | +| common | object | 一般信息 | 仅 `type='LINK_CARD_TYPE_COMMON', 参见 [获取全部动态列表](../dynamic/all.md#获取全部动态列表) 的 `data.items[].modules.module_dynamic.additional.common` | +| goods | object | 商品信息 | 仅 `type='LINK_CARD_TYPE_GOODS'`, 参见 [获取全部动态列表](../dynamic/all.md#获取全部动态列表) 的 `data.items[].modules.module_dynamic.additional.goods` | +| match | object | 比赛信息? | 仅 `type='LINK_CARD_TYPE_MATCH'` | +| vote | object | 投票信息 | 仅 `type='LINK_CARD_TYPE_VOTE'`, 参见 [获取全部动态列表](../dynamic/all.md#获取全部动态列表) 的 `data.items[].modules.module_dynamic.additional.vote` | +| ugc | object | 视频信息 | 仅 `type='LINK_CARD_TYPE_UGC'`, 参见 [获取全部动态列表](../dynamic/all.md#获取全部动态列表) 的 `data.items[].modules.module_dynamic.additional.ugc` | +| reserve | object | 预约信息 | 仅 `type='LINK_CARD_TYPE_RESERVE'`, 参见 [获取全部动态列表](../dynamic/all.md#获取全部动态列表) 的 `data.items[].modules.module_dynamic.additional.reserve` | +| upower_lottery | object | 充电专属抽奖信息 | 仅 `type='LINK_CARD_TYPE_UPOWER_LOTTERY'` | +| opus | object | 图文信息 | 仅 `type='LINK_CARD_TYPE_OPUS'` | +| music | object | 音乐信息 | 仅 `type='LINK_CARD_TYPE_MUSIC'`, 参见 [获取全部动态列表](../dynamic/all.md#获取全部动态列表) 的 `data.items[].modules.module_dynamic.major.music` | +| live | object | 直播信息 | 仅 `type='LINK_CARD_TYPE_LIVE'`, 参见 [获取全部动态列表](../dynamic/all.md#获取全部动态列表) 的 `data.items[].modules.module_dynamic.major.live` | +| item_null | object | 提示信息 | 仅 `type='LINK_CARD_TYPE_ITEM_NULL'` | + +`module_content.paragraphs[].link_card.card.match` 对象: + +*注: 该对象结构由 AI 根据前端代码推断得出未经验证仅供参考* + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| id_str | string | 动态 ID | | +| jump_url | string | 跳转 URL | | +| match_info | object | 比赛信息 | 套了个娃 | + +`module_content.paragraphs[].link_card.card.match.match_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| center_bottom | string | 中间区域底部的信息 | | +| center_top | string[] | 中间区域顶部的信息 | 会循环显示出来, 可能用来显示比分或者比赛时间 | +| left_team | object | 右边队伍的信息 | | +| right_team | object | 左边队伍的信息 | | +| status | number | 比赛状态 | 2: 进行中 (文字会高亮)
其他: 正常状态 | +| sub_title | string | 副标题 | | +| title | string | 标题 | | + +`module_content.paragraphs[].link_card.card.match.match_info.left_team` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| name | string | 队伍名字 | | +| pic | string | 图片 | | + +`module_content.paragraphs[].link_card.card.match.match_info.right_team` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| name | string | 队伍名字 | | +| pic | string | 图片 | | + + + +`module_content.paragraphs[].link_card.card.upower_lottery` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| button | object | 按钮 | | +| desc | object | 描述 | | +| hint | object | 提示 | | +| jump_url | string | 跳转 URL | | +| rid | number | 关联 id | | +| state | number | 状态 | | +| title | string | 标题 | | +| up_mid | number | UP 主 mid (UID) | | +| upower_action_state | number | 充电操作状态 | | +| upower_level | number | 充电级别 | | + +`module_content.paragraphs[].link_card.card.upower_lottery.button` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| check | object | 选中状态 | | +| status | number | 状态 | | +| type | number | 类型 | 0 1 2 | + +`module_content.paragraphs[].link_card.card.upower_lottery.button.check` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| disable | number | 是否禁用 | 1: 禁用 | +| icon_url | string | 图标 URL | | +| text | string | 文字 | | +| toast | string | 提示 | | + +`module_content.paragraphs[].link_card.card.upower_lottery.desc` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| jump_url | string | 跳转 URL | | +| style | number | 样式 | | +| text | string | 文字 | | + +`module_content.paragraphs[].link_card.card.upower_lottery.hint` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| style | number | 样式 | | +| text | string | 文字 | | + + + +`module_content.paragraphs[].link_card.card.opus` 对象: + +*注: 该对象结构根据前端代码推断得出未经验证仅供参考* + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| author | object | 作者信息 | | +| cover | string | 封面 URL | | +| jump_url | string | 跳转 URL | | +| stat | object | 状态信息 | | +| title | string | 标题 | | + +`module_content.paragraphs[].link_card.card.opus.author` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| name | string | 作者名 | | + +`module_content.paragraphs[].link_card.card.opus.stat` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| view | number | 阅读数 | | + +`module_content.paragraphs[].link_card.card.item_null` 对象: + +注: 该对象结构根据前端代码推断得出未经验证仅供参考 + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| text | string | 文字 | | + +`module_content.paragraphs[].code` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| content | string | 内容 | | +| lang | string | 语言 | 如 `language-html` `language-bash` | + +**示例:** + +
+查看示例: + +```json +{ + "module_content": { + "paragraphs": [ + { + "link_card": { + "card": { + "opus": { + "author": { + "name": "作者的名字" + }, + "cover": "https://example.com/path/to/cover.jpg", + "jump_url": "https://www.bilibili.com/read/cvxxxxxxxx", + "stat": { + "view": 12345 + }, + "title": "这里是作品的标题" + } + } + } + } + ] + } +} +``` +
+ + + +**示例:** + +
+查看示例: + +```json +{ + "module_content": { + "paragraphs": [ + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "洛天依2025「无限共鸣·流光协奏」全息巡回演唱会·成都站\n部分演出歌曲歌单抢先看~" + } + }, + { + "rich": { + "emoji": { + "gif_url": "https://i0.hdslb.com/bfs/garb/3ed01457a5a2c7c2ec304a1aa0565033f4b7fde4.gif", + "icon_url": "https://i0.hdslb.com/bfs/garb/d6a4aeb51134e1ddf0024a8c1fa48a91700207e2.png", + "size": 2, + "text": "[洛天依·天星问动态_萌]", + "type": 3, + "webp_url": "https://i0.hdslb.com/bfs/garb/1c017fee22994ff261b90c9790a2cfc553ef1845.webp" + }, + "orig_text": "[洛天依·天星问动态_萌]", + "text": "[洛天依·天星问动态_萌]", + "type": "RICH_TEXT_NODE_TYPE_EMOJI" + }, + "type": "TEXT_NODE_TYPE_RICH" + }, + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "\n《Dramatic》\n《蝴蝶》\n\n✨成都站城市限定演出歌曲\n《又见月光光》\n\n有没有你期待的歌曲呀?" + } + }, + { + "rich": { + "emoji": { + "gif_url": "https://i0.hdslb.com/bfs/emote/55bbe7e1c69fb5382764cd467a6ef43c97e8fb81.gif", + "icon_url": "https://i0.hdslb.com/bfs/emote/e55207be553ac505ac80892a3f325be383139aa2.png", + "size": 2, + "text": "[心律共鸣动态表情包_啾啾]", + "type": 3, + "webp_url": "https://i0.hdslb.com/bfs/emote/fc0c8ef4ba8271521d934b9b6ee1a7c60ab27e4c.webp" + }, + "orig_text": "[心律共鸣动态表情包_啾啾]", + "text": "[心律共鸣动态表情包_啾啾]", + "type": "RICH_TEXT_NODE_TYPE_EMOJI" + }, + "type": "TEXT_NODE_TYPE_RICH" + }, + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "\n天依已经迫不及待在演唱会的舞台上和大家相见啦!" + } + } + ] + } + }, + { + "align": 0, + "para_type": 2, + "pic": { + "pics": [ + { + "height": 5755, + "live_url": null, + "size": 4180.7216796875, + "url": "http://i0.hdslb.com/bfs/new_dyn/bda8c1b1e9c98e09994742a26c1f62c636081646.jpg", + "width": 1080 + } + ], + "style": 1 + } + }, + { + "link_card": { + "card": { + "goods": { + "head_icon": "", + "head_text": "UP主的推荐", + "items": [ + { + "brief": "", + "cover": "https://i0.hdslb.com/bfs/openplatform/202506/aNnr4PFN1749449633226.jpeg", + "id": 102803, + "jump_desc": "去看看", + "jump_url": "https://mall.bilibili.com/neul-next/ticket/detail.html?noTitleBar=1&id=102803&track_id=__BGMT__&contentId=&from=&msource=cps_Mdynamic_36081646_cont-2-1077137468098084900", + "name": "成都·2025洛天依「无限共鸣•流光协奏」全息演唱会-成都站", + "price": "¥480" + } + ], + "jump_url": "" + }, + "oid": "undefined", + "type": "LINK_CARD_TYPE_GOODS" + } + }, + "para_type": 6 + } + ] + }, + "module_type": "MODULE_TYPE_CONTENT" +} +``` + +```json +{ + "module_content": { + "paragraphs": [ + { + "align": 0, + "para_type": 1, + "text": { + "nodes": [ + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "欢迎使用咱开发的 TG 机器人, 自由开源, 目前支持很多功能, 如 天气查询, IP 查询, 甚至可以执行 Shell 命令\nSINO Is Not Object! " + } + }, + { + "type": "TEXT_NODE_TYPE_WORD", + "word": { + "font_size": 17, + "style": {}, + "words": "https://t.me/SessX6cfBot" + } + } + ] + } + } + ] + }, + "module_type": "MODULE_TYPE_CONTENT" +} +``` +
+ + + +### MODULE_TYPE_TOPIC + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| module_topic | object | 话题模块 | | +| module_type | string | 模块类型 | `MODULE_TYPE_TOPIC` | + +`module_topic` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| id | number | 话题 id | | +| jump_url | string | 跳转 URL | | +| name | string | 话题名称 | | + +**示例:** + +
+查看示例: + +```json +{ + "module_topic": { + "id": 1310025, + "jump_url": "https://m.bilibili.com/topic-detail?topic_id=1310025&topic_name=%E6%B4%9B%E5%A4%A9%E4%BE%9D%E5%96%8A%E4%BD%A0%E6%9D%A5%E7%9C%8B%E5%85%A8%E6%81%AF%E5%B7%A1%E6%BC%94", + "name": "洛天依喊你来看全息巡演" + }, + "module_type": "MODULE_TYPE_TOPIC" +} +``` +
+ + + +### MODULE_TYPE_COLLECTION + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| module_collection | object | 文集模块 | | +| module_type | string | 模块类型 | `MODULE_TYPE_COLLECTION` | + +`module_collection` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| count | string | 文章数 | | +| id | number | 文集 id | | +| name | string | 文集名 | | +| title | string | 标题 | `收录于文集` | + +**示例:** + +
+查看示例: + +```json +{ + "module_collection": { + "count": "4篇", + "id": 326286, + "name": "电脑", + "title": "收录于文集" + }, + "module_type": "MODULE_TYPE_COLLECTION" +} +``` +
+ + + + +### MODULE_TYPE_EXTEND + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| module_extend | object | 扩展模块 | | +| module_type | string | 模块类型 | `MODULE_TYPE_EXTEND` | + +`module_extend` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| items | object[] | 项 | 套了个娃 | + +`module_extend.items[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| icon | string \| null | 图标 | | +| icon_svg | unknown | SVG 图版 | | +| jump_url | string | 跳转 URL | | +| text | string | 文本 | | + +**示例:** + +
+查看示例: + +```json +{ + "module_extend": { + "items": [ + { + "icon": null, + "jump_url": "//search.bilibili.com/all?keyword=HTML", + "text": "HTML" + }, + { + "icon": null, + "jump_url": "//search.bilibili.com/all?keyword=API", + "text": "API" + }, + { + "icon": null, + "jump_url": "//search.bilibili.com/all?keyword=BAC", + "text": "BAC" + }, + { + "icon": null, + "jump_url": "//search.bilibili.com/all?keyword=JavaScript", + "text": "JavaScript" + }, + { + "icon": null, + "jump_url": "//search.bilibili.com/all?keyword=Bilibili", + "text": "Bilibili" + }, + { + "icon": null, + "jump_url": "//search.bilibili.com/all?keyword=GitHub", + "text": "GitHub" + }, + { + "icon": null, + "jump_url": "//search.bilibili.com/all?keyword=Web", + "text": "Web" + }, + { + "icon": null, + "jump_url": "//search.bilibili.com/all?keyword=Chromium", + "text": "Chromium" + }, + { + "icon": null, + "jump_url": "//search.bilibili.com/all?keyword=DevTools", + "text": "DevTools" + } + ] + }, + "module_type": "MODULE_TYPE_EXTEND" +} +``` +
+ + + +### MODULE_TYPE_BOTTOM + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| module_bottom | object | 底部模块 | | +| module_type | string | 模块类型 | | + +`module_bottom` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| share_info | object | 分享信息 | | + +`module_bottom.share_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| pic | string | 图片 URL | | +| summary | string | 总结 | | +| title | string | 标题 | | + +**示例:** + +
+查看示例: + +```json +{ + "module_bottom": { + "share_info": { + "pic": "https://static.hdslb.com/mobile/img/app_logo.png", + "summary": "背景", + "title": "通过 DevTools 绕过 SSR 抓包某站专栏正文接口" + } + }, + "module_type": "MODULE_TYPE_BOTTOM" +} +``` +
+ + diff --git a/bb-api-collect/docs/opus/rich_text_nodes.md b/bb-api-collect/docs/opus/rich_text_nodes.md new file mode 100644 index 0000000000..d3e36edfc5 --- /dev/null +++ b/bb-api-collect/docs/opus/rich_text_nodes.md @@ -0,0 +1,422 @@ +# 富文本节点 + +补充: 已知动态与图文接口获取结果的富文本节点与发送时的 `type` 等有关 + +## 富文本节点类型 + +| 类型 | 说明 | type | biz_id | 示例 | +| ---- | ---- | ---- | ------ | ---- | +| RICH_TEXT_NODE_TYPE_NONE | | | | | +| RICH_TEXT_NODE_TYPE_TEXT | 文字节点 | 1 | 空 | [106514206257210983](https://t.bilibili.com/106514206257210983) | +| RICH_TEXT_NODE_TYPE_AT | @用户 | 2 | 用户 mid (UID) | [721296515797090324](https://t.bilibili.com/721296515797090324) | +| RICH_TEXT_NODE_TYPE_LOTTERY | 互动抽奖 | 3 | 抽奖 id | [720907383182721040](https://t.bilibili.com/720907383182721040) | +| RICH_TEXT_NODE_TYPE_VOTE | 投票 | 4 | 投票 id | [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 | 表情 | 9 | 空 | [1069394178937454662](https://t.bilibili.com/1069394178937454662) | +| RICH_TEXT_NODE_TYPE_CV | 专栏 | | | | +| RICH_TEXT_NODE_TYPE_VIEW_PICTURE | 查看图片 | | | [1069394178937454662](https://t.bilibili.com/1069394178937454662) | +| RICH_TEXT_NODE_TYPE_WEB | 网页链接 | | | [716751027361022055](https://t.bilibili.com/716751027361022055) | +| RICH_TEXT_NODE_TYPE_TAOBAO | | | | | +| RICH_TEXT_NODE_TYPE_MAIL | 邮箱地址 | | | ~~721314095109767220~~ | +| RICH_TEXT_NODE_TYPE_OGV_SEASON | 剧集信息 | | | ~~721282046064853080~~ | +| RICH_TEXT_NODE_TYPE_OGV_EP | | | | | + +## 富文本节点对象 + +### RICH_TEXT_NODE_TYPE_TEXT + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| orig_text | string | 原始文本 | | +| text | string | 显示文本 | 一般与 `orig_text` 内容相同 | +| type | string | `RICH_TEXT_NODE_TYPE_TEXT` | | + +**示例:** + +
+查看示例: + +```json +{ + "orig_text": "【洛天依·共鸣宝石收藏家】设定也分享给大家~!", + "text": "【洛天依·共鸣宝石收藏家】设定也分享给大家~!", + "type": "RICH_TEXT_NODE_TYPE_TEXT" +} +``` +
+ + + +### RICH_TEXT_NODE_TYPE_AT + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| orig_text | string | 原始文本 | | +| rid | string | 用户 mid (UID) | | +| text | string | 显示文本 | 一般与 `orig_text` 内容相同 | +| type | string | `RICH_TEXT_NODE_TYPE_AT` | | + +**示例:** + +
+查看示例: + +```json +{ + "orig_text": "@wuziqian211 ", + "rid": "425503913", + "text": "@wuziqian211 ", + "type": "RICH_TEXT_NODE_TYPE_AT" +} +``` +
+ + + +### RICH_TEXT_NODE_TYPE_LOTTERY + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| orig_text | string | 原始文本 | 一般为 `互动抽奖` | +| rid | string | 抽奖 id | | +| text | string | 显示文本 | 一般为 `互动抽奖` | +| type | string | `RICH_TEXT_NODE_TYPE_LOTTERY` | | + +**示例:** + +
+查看示例: + +```json +{ + "orig_text": "互动抽奖", + "rid": "116067", + "text": "互动抽奖", + "type": "RICH_TEXT_NODE_TYPE_LOTTERY" +} +``` +
+ + + +### RICH_TEXT_NODE_TYPE_VOTE + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| orig_text | string | 原始文本 | | +| rid | string | 抽奖 id | | +| text | string | 显示文本 | 一般与 `orig_text` 一致 | +| type | string | `RICH_TEXT_NODE_TYPE_VOTE` | | + +**示例:** + +
+查看示例: + +```json +{ + "orig_text": "次の文の ★ に入る最もよいものを一つ選びなさい。", + "rid": "3925886", + "text": "次の文の ★ に入る最もよいものを一つ選びなさい。", + "type": "RICH_TEXT_NODE_TYPE_VOTE" +} +``` +
+ + + +### RICH_TEXT_NODE_TYPE_TOPIC + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| jump_url | string | 跳转 URL | 无协议头 | +| orig_text | string | 原始文本 | | +| text | string | 显示文本 | 一般与 `orig_text` 一致 | +| type | string | `RICH_TEXT_NODE_TYPE_TOPIC ` | | + +**示例:** + +
+查看示例: + +```json +{ + "jump_url": "//search.bilibili.com/all?keyword=ASOUL%E7%9A%84%E5%A5%87%E5%A6%99%E5%AE%87%E5%AE%99", + "orig_text": "#ASOUL的奇妙宇宙#", + "text": "#ASOUL的奇妙宇宙#", + "type": "RICH_TEXT_NODE_TYPE_TOPIC" +} +``` +
+ + + +### RICH_TEXT_NODE_TYPE_GOODS + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| goods | object | 商品信息 | | +| icon_name | string | 图标名称 | `shop` `taobao` | +| jump_url | string | 跳转 URL | | +| orig_text | string | 原始文本 | | +| rid | string | | | +| text | string | 显示文本 | 一般与 `orig_text` 一致 | +| type | string | `RICH_TEXT_NODE_TYPE_GOODS` | | + +`goods` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| jump_url | string | 跳转 URL | 一般与根对象下的 `jump_url` 相同 | +| type | number | `1` | | + +**示例:** + +
+查看示例: + +```json +{ + "goods": { + "jump_url": "https://s.click.taobao.com/t?e=m%3D2%26s%3DhRVW5Ol4GrZw4vFB6t2Z2ueEDrYVVa64XoO8tOebS%2BdRAdhuF14FMcvdLjw%2BYA8F1aH1Hk3GeOgLhuv3v%2BUO0FVeaszYyErWfp5XqHpg%2Bfwn9kK7XrZu6WxZ8BPtnRZfqGXK58Jc1%2BhtJfOipEYQaSY0lFm97JITUXK%2FCnFktAT05J9EjZ4Cg6Q6sZp7gNLmb4%2BNtrBbTSxr7mxbAs%2BuXGY7X5f4YTwUTi8eJkfcZdQxNgzykgJnxNGRxz%2FytfH1UnsQ1Sg4FG%2Fgk553RHFro7zDM6tzzB%2FwUFU78FEla0%2F6liDBUuxx%2BfRWY0eqeyPKGJZJ34Yh7cK34L0nA6HzjPrdYgTMW7Qubh8ReVU%2F9k2Huec2Q%2B1T%2BJwkZZwMWMdb2FGsw09L73Dq%2F8VFknkEdmd1Il7G%2BufOO%2FbGmELtDp4hhQs2DjqgEA%3D%3D&union_lens=lensId:TAPI@1674460806@212ccf35_0bed_185dda43d7a_a840@01", + "type": 1 + }, + "icon_name": "taobao", + "jump_url": "https://s.click.taobao.com/t?e=m%3D2%26s%3DhRVW5Ol4GrZw4vFB6t2Z2ueEDrYVVa64XoO8tOebS%2BdRAdhuF14FMcvdLjw%2BYA8F1aH1Hk3GeOgLhuv3v%2BUO0FVeaszYyErWfp5XqHpg%2Bfwn9kK7XrZu6WxZ8BPtnRZfqGXK58Jc1%2BhtJfOipEYQaSY0lFm97JITUXK%2FCnFktAT05J9EjZ4Cg6Q6sZp7gNLmb4%2BNtrBbTSxr7mxbAs%2BuXGY7X5f4YTwUTi8eJkfcZdQxNgzykgJnxNGRxz%2FytfH1UnsQ1Sg4FG%2Fgk553RHFro7zDM6tzzB%2FwUFU78FEla0%2F6liDBUuxx%2BfRWY0eqeyPKGJZJ34Yh7cK34L0nA6HzjPrdYgTMW7Qubh8ReVU%2F9k2Huec2Q%2B1T%2BJwkZZwMWMdb2FGsw09L73Dq%2F8VFknkEdmd1Il7G%2BufOO%2FbGmELtDp4hhQs2DjqgEA%3D%3D&union_lens=lensId:TAPI@1674460806@212ccf35_0bed_185dda43d7a_a840@01", + "orig_text": "​啊脑袋周边抱枕", + "rid": "688066082845462528", + "text": "​啊脑袋周边抱枕", + "type": "RICH_TEXT_NODE_TYPE_GOODS" +} +``` +
+ + + +### RICH_TEXT_NODE_TYPE_BV + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| jump_url | string | 跳转 URL | | +| orig_text | string | 原始文本 | | +| rid | string | 视频 bvid | | +| text | string | 显示文本 | 视频标题 | +| type | string | `RICH_TEXT_NODE_TYPE_BV` | | + +**示例:** + +
+查看示例: + +```json +{ + "jump_url": "https://www.bilibili.com/video/BV1xx411c7mD/", + "orig_text": "https://www.bilibili.com/video/BV1xx411c7mD/", + "rid": "BV1xx411c7mD", + "text": "字幕君交流场所", + "type": "RICH_TEXT_NODE_TYPE_BV" +} +``` +
+ + + +### RICH_TEXT_NODE_TYPE_EMOJI + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| emoji | object | 表情信息 | | +| orig_text | string | 原始文本 | | +| text | string | 显示文本 | 一般与 `orig_text` 一致 | +| type | string | `RICH_TEXT_NODE_TYPE_EMOJI` | | + +`emoji` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| icon_url | string | 表情图片 URL | | +| size | number | 表情尺寸 | 1: small
2: middle | +| text | string | 表情的文字代码 | 一般与根对象的 `text` 一致 | +| type | number | 表情类型 | `1` `2` `3` | + +**示例:** + +
+查看示例: + +```json +{ + "emoji": { + "icon_url": "https://i0.hdslb.com/bfs/emote/5ce649d5f716566db41dbf68c2e319517516d321.png", + "size": 2, + "text": "[热词系列_干杯]", + "type": 1 + }, + "orig_text": "[热词系列_干杯]", + "text": "[热词系列_干杯]", + "type": "RICH_TEXT_NODE_TYPE_EMOJI" +} +``` +
+ + + +### RICH_TEXT_NODE_TYPE_CV + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| jump_url | string | 跳转 URL | 无协议名 | +| orig_text | string | 原始文本 | | +| rid | string | 专栏 CV 号 | | +| text | string | 显示文本 | | +| type | string | `RICH_TEXT_NODE_TYPE_CV` | | + +**示例:** + +
+查看示例: + +```json +{ + "jump_url": "//www.bilibili.com/read/cv1/", + "orig_text": "1", + "rid": "1", + "text": "未知的光", + "type": "RICH_TEXT_NODE_TYPE_CV" +} +``` +
+ + + +### RICH_TEXT_NODE_TYPE_VIEW_PICTURE + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| jump_url | string | | | +| orig_text | string | 原始文本 | | +| pics | object[] | 图片信息 | | +| rid | string | 本条动态 id | | +| text | string | 显示文本 | 一般与 `orig_text` 一致 | +| type | string | `RICH_TEXT_NODE_TYPE_VIEW_PICTURE ` | | + +`pics[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| height | number | 高度 | | +| size | number | 大小? | 单位为 K | +| src | string | 图片 URL | | +| width | number | 宽度 | | + +**示例:** + +
+查看示例: + +```json +{ + "jump_url": "//www.bilibili.com/read/cv/", + "orig_text": "查看图片", + "pics": [ + { + "height": 4000, + "size": 4218.501, + "src": "http://i0.hdslb.com/bfs/new_dyn/d13a5793f7101824e9c9181ebc4df1a936081646.png", + "width": 6411 + } + ], + "rid": "1069394178937454662", + "text": "查看图片", + "type": "RICH_TEXT_NODE_TYPE_VIEW_PICTURE" +} +``` +
+ + + +### RICH_TEXT_NODE_TYPE_WEB + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| jump_url | string | 跳转 URL | | +| orig_text | string | 原始文本 | | +| style | object \| null | 样式信息 | | +| text | string | 显示文本 | | +| type | string | `RICH_TEXT_NODE_TYPE_WEB` | | + +`style` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| font_level | string | 字体等级 | `regular` | +| font_size | number | 字体大小 | `17` | + +**示例:** + +
+查看示例: + +```json +{ + "jump_url": "https://api.bilibili.com/x/web-interface/nav", + "orig_text": "https://api.bilibili.com/x/web-interface/nav", + "style": { + "font_level": "regular", + "font_size": 17 + }, + "text": "网页链接", + "type": "RICH_TEXT_NODE_TYPE_WEB" +} +``` + +```json +{ + "jump_url": "//www.bilibili.com/video/av1", + "orig_text": "//www.bilibili.com/video/av1", + "style": null, + "text": "av1", + "type": "RICH_TEXT_NODE_TYPE_WEB" +} +``` + +
+ + + +### RICH_TEXT_NODE_TYPE_OGV_SEASON + +参考 [RICH_TEXT_NODE_TYPE_BV](#rich-text-node-type-bv) + +### RICH_TEXT_NODE_TYPE_OGV_EP + +参考 [RICH_TEXT_NODE_TYPE_BV](#rich-text-node-type-bv) + +### RICH_TEXT_NODE_TYPE_AV + +参考 [RICH_TEXT_NODE_TYPE_BV](#rich-text-node-type-bv) diff --git a/bb-api-collect/docs/opus/space.md b/bb-api-collect/docs/opus/space.md new file mode 100644 index 0000000000..56efa158c9 --- /dev/null +++ b/bb-api-collect/docs/opus/space.md @@ -0,0 +1,356 @@ +## 空间图文 + +## 获取用户空间图文 + +> https://api.bilibili.com/x/polymer/web-dynamic/v1/opus/feed/space + +*请求方法: GET* + +注: 该接口**只能**获取图文信息, 无法获取如转发动态一类的内容, 如需获取参见 [获取用户空间动态](docs/dynamic/space.md) + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ------ | ---- | ------ | ---- | +| host_mid | number | 被获取用户的 mid (UID) | 必要 | | +| page | number | 假装自己是分页信息 | 不必要 | 以 `1` 开始 | +| offset | number | 偏移信息 | 不必要 | 上一次返回的 `offset` (同时也是最后一条的 opus id), 默认为空 | +| type | string | 类型 | 不必要 | all: 全部 (默认)
article: 专栏
dynamic: 动态 | +| web_location | string | `333.1387` | 不必要 | | +| w_rid | string | WBI 签名 | 不必要 | 参见 [WBI 签名](../misc/sign/wbi.md) | +| wts | number | UNIX 秒级时间戳 | 不必要 | 参见 [WBI 签名](../misc/sign/wbi.md) | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | number | 返回值 | 0: 成功 | +| data | object | 数据本体 | | +| message | string | 错误信息 | 成功时为 `0` | +| ttl | number | `1` | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| has_more | boolean | 是否还有更多 | | +| items | object[] | 信息本体 | | +| offset | string | 偏移信息 | 下次翻页请求时传入的 `offest` (同时也是最后一条的 opus id) | +| update_num | number | 更新数? | 0 | + +`data.items[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| content | string | 文本内容 | | +| cover | object? | 封面信息 | | +| jump_url | string | 跳转 URL | | +| opus_id | string | opus id | | +| stat | object | 统计信息 | | + +`data.items[].cover` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| height | number | 高度 | | +| url | string | 图片 URL | | +| width | number | 宽度 | | + +`data.items[].stat` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| like | string | 点赞数 | 是个字符串 | +| view | string | 浏览数 | 仅当获取登录状态下获取自己的时才存在, 也是个字符串 | + +**示例:** + +获取 `645769214` 空间的最近几条全部图文 + +```shell +curl 'https://api.bilibili.com/x/polymer/web-dynamic/v1/opus/feed/space' \ +--url-query 'host_mid=645769214' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "data": { + "has_more": true, + "items": [ + { + "content": "我在 Google I/O 2025 的 puzzle 取得了获胜的优异成绩, 你也来试试吧", + "cover": { + "height": 1640, + "url": "http://i0.hdslb.com/bfs/new_dyn/a48c47c07bf19f07c01b489eb6b42e63645769214.jpg", + "width": 720 + }, + "jump_url": "//www.bilibili.com/opus/1057955152016703512", + "opus_id": "1057955152016703512", + "stat": { + "like": "1" + } + }, + { + "content": "通过 DevTools 绕过 SSR 抓包某站专栏正文接口", + "cover": { + "height": 430, + "url": "http://i0.hdslb.com/bfs/article/9071997152b6fec0ae465fe2a86b580e645769214.jpg", + "width": 768 + }, + "jump_url": "//www.bilibili.com/opus/1056353752004427792", + "opus_id": "1056353752004427792", + "stat": { + "like": "3" + } + }, + { + "content": "今天也是看上 Minecraft 大电影 了, 看的人几乎没有, 虽然看的是中配, 总体上感觉剧情有趣甚至有点小感动, 音乐也感觉不错, 价格也实惠", + "cover": { + "height": 4080, + "url": "http://i0.hdslb.com/bfs/new_dyn/408d4e2b2ad8df6873c303cf26f571db645769214.jpg", + "width": 3060 + }, + "jump_url": "//www.bilibili.com/opus/1052711525276450824", + "opus_id": "1052711525276450824", + "stat": { + "like": "3" + } + }, + { + "content": "糟了没注意, 自己成小丑了", + "cover": { + "height": 1640, + "url": "http://i0.hdslb.com/bfs/new_dyn/6ebb3894cfab53966d6e440e4f5a905d645769214.jpg", + "width": 720 + }, + "jump_url": "//www.bilibili.com/opus/1051313732437671938", + "opus_id": "1051313732437671938", + "stat": { + "like": "3" + } + }, + { + "content": "好消息, 我免费了, 想玩的随时联系\nhttps://t.me/c/2148747379/77", + "cover": { + "height": 720, + "url": "http://i0.hdslb.com/bfs/new_dyn/fbc2b38406099df0bdaea47d08daa6f1645769214.jpg", + "width": 1640 + }, + "jump_url": "//www.bilibili.com/opus/1050579658107518984", + "opus_id": "1050579658107518984", + "stat": { + "like": "2" + } + }, + { + "content": "认真的, 我的 Linux 发行版是 Android", + "cover": { + "height": 1080, + "url": "http://i0.hdslb.com/bfs/new_dyn/3e512d84361323c319f79061d2f078d1645769214.jpg", + "width": 1440 + }, + "jump_url": "//www.bilibili.com/opus/1032607998809210903", + "opus_id": "1032607998809210903", + "stat": { + "like": "8" + } + }, + { + "content": "于学校机房启动 QEMU 珍贵影像", + "cover": { + "height": 1080, + "url": "http://i0.hdslb.com/bfs/new_dyn/2fdc7524449b029f8baf241d94663256645769214.jpg", + "width": 1440 + }, + "jump_url": "//www.bilibili.com/opus/993403941079220225", + "opus_id": "993403941079220225", + "stat": { + "like": "3" + } + }, + { + "content": "BAC 正处于历史以来最困难的时期 - 中秋考古有感", + "cover": { + "height": 188, + "url": "https://i0.hdslb.com/bfs/article/0c9b5e20356e07f89a8bb7769fef8eeb645769214.jpg", + "width": 640 + }, + "jump_url": "//www.bilibili.com/opus/985444108243828741", + "opus_id": "985444108243828741", + "stat": { + "like": "7" + } + }, + { + "content": "发送文件到手机的 N 种正确姿势", + "cover": { + "height": 420, + "url": "http://i0.hdslb.com/bfs/article/56a4024abebf7ed1166a1d247bb5cf64645769214.jpg", + "width": 750 + }, + "jump_url": "//www.bilibili.com/opus/971804623539011587", + "opus_id": "971804623539011587", + "stat": { + "like": "8" + } + }, + { + "content": "我在朝鲜?", + "cover": { + "height": 468, + "url": "http://i0.hdslb.com/bfs/new_dyn/ea12cca6abd75fe3fb5ad1abd1f347d3645769214.png", + "width": 474 + }, + "jump_url": "//www.bilibili.com/opus/971255284349534210", + "opus_id": "971255284349534210", + "stat": { + "like": "5" + } + }, + { + "content": "一周没上 B 站就 99+ 了?", + "cover": { + "height": 284, + "url": "http://i0.hdslb.com/bfs/new_dyn/9e3b889fd2dc75e9bae38a13e55fee26645769214.png", + "width": 165 + }, + "jump_url": "//www.bilibili.com/opus/970197833343827970", + "opus_id": "970197833343827970", + "stat": { + "like": "6" + } + }, + { + "content": "今天因为Linux被骂, 决定放弃支持 Windows. 而且明天要开始军训了, 将停更若干时间, 遂发此动态, 望不知.", + "cover": { + "height": 1080, + "url": "http://i0.hdslb.com/bfs/new_dyn/0f6f939334104ddc347566514fa4bfa7645769214.jpg", + "width": 1440 + }, + "jump_url": "//www.bilibili.com/opus/967717348014293017", + "opus_id": "967717348014293017", + "stat": { + "like": "73" + } + }, + { + "content": "我的萌ICP备案通过了!", + "cover": { + "height": 2712, + "url": "http://i0.hdslb.com/bfs/new_dyn/0a9bb3e82bbefe499b10b7fd02f2a4f4645769214.jpg", + "width": 1220 + }, + "jump_url": "//www.bilibili.com/opus/956241611959828547", + "opus_id": "956241611959828547", + "stat": { + "like": "1" + } + }, + { + "content": "新年第一个AP", + "cover": { + "height": 1220, + "url": "https://album.biliimg.com/bfs/new_dyn/ea5a39d37a4a1f20f32b25bfed466004645769214.jpg", + "width": 2712 + }, + "jump_url": "//www.bilibili.com/opus/896448108088524805", + "opus_id": "896448108088524805", + "stat": { + "like": "1" + } + }, + { + "content": "新年快乐?", + "cover": { + "height": 605, + "url": "https://album.biliimg.com/bfs/new_dyn/dab5d3e2ff03027215e5bfd4933abe45645769214.jpg", + "width": 1220 + }, + "jump_url": "//www.bilibili.com/opus/896342627995090966", + "opus_id": "896342627995090966", + "stat": { + "like": "1" + } + }, + { + "content": "我回苏州了", + "cover": { + "height": 1280, + "url": "https://album.biliimg.com/bfs/new_dyn/65c880f64997fab0c79527649d7fbe1b645769214.png", + "width": 720 + }, + "jump_url": "//www.bilibili.com/opus/831507996405137432", + "opus_id": "831507996405137432", + "stat": { + "like": "1" + } + }, + { + "content": "Phigros RKS 12 纪念", + "cover": { + "height": 720, + "url": "https://album.biliimg.com/bfs/new_dyn/dab03003aee2166987428857acbf4ffb645769214.png", + "width": 1280 + }, + "jump_url": "//www.bilibili.com/opus/830690195959447605", + "opus_id": "830690195959447605", + "stat": { + "like": "0" + } + }, + { + "content": "现在知道B站推荐机制有多烂了吧", + "cover": { + "height": 1280, + "url": "https://album.biliimg.com/bfs/new_dyn/05a5f769bed2705d2c8c3c69f60441df645769214.png", + "width": 720 + }, + "jump_url": "//www.bilibili.com/opus/829284474633060387", + "opus_id": "829284474633060387", + "stat": { + "like": "0" + } + }, + { + "content": "求证: B站创始人们的成分\n证: [图片]", + "cover": { + "height": 1600, + "url": "https://album.biliimg.com/bfs/new_dyn/830a9bbc3d5179a6d33af97e5baac7c8645769214.jpg", + "width": 720 + }, + "jump_url": "//www.bilibili.com/opus/828071498582327315", + "opus_id": "828071498582327315", + "stat": { + "like": "1" + } + }, + { + "content": "如果排除掉可能的误差, 14=12.", + "cover": { + "height": 720, + "url": "https://album.biliimg.com/bfs/new_dyn/79823dd0b617af6fc71126d6e042de3f645769214.png", + "width": 1280 + }, + "jump_url": "//www.bilibili.com/opus/827727935543705620", + "opus_id": "827727935543705620", + "stat": { + "like": "1" + } + } + ], + "offset": "827727935543705620", + "update_num": 0 + }, + "message": "0", + "ttl": 1 +} +``` +
+ + diff --git a/bb-api-collect/docs/search/hot.md b/bb-api-collect/docs/search/hot.md new file mode 100644 index 0000000000..6c7cdb9a64 --- /dev/null +++ b/bb-api-collect/docs/search/hot.md @@ -0,0 +1,693 @@ +# 默认搜索&热搜 + +## 获取默认搜索内容(web端) + +> 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回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | --------------- | -------------- | +| seid | str | 搜索seid | | +| id | num | 默认搜索id | | +| type | num | 0 | | +| show_name | str | 显示文字 | | +| name | str | 空 | | +| goto_type | num | 跳转类型 | 1:视频 | +| goto_value | str | 搜索目标id | 视频:稿件avid | +| url | str | 搜索目标跳转url | | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/web-interface/search/default' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "seid": "17607543598496143098", + "id": 3296036255232726331, + "type": 0, + "show_name": "歪果仁在中国做模特能赚多少钱?", + "name": "", + "goto_type": 1, + "goto_value": "243920322", + "url": "https://www.bilibili.com/video/BV1Tv411q7gx" + } +} +``` + +
+ +## 获取热搜列表 + +> https://api.bilibili.com/x/web-interface/wbi/search/square +> ~~https://api.bilibili.com/x/web-interface/search/square~~ + +*请求方式: GET* + +**URL参数:** + +|参数名|类型|内容|必要性|备注| +|-|-|-|-|-| +|limit|num|结果限制|必要|范围 [1, 50]| +|platform|str|平台标识|不必要|web: web 端| + +**JSON回复:** + +根对象: + +|字段|类型|内容|备注| +|-|-|-|-| +|code|num|返回值|0: 成功
-400: 请求错误| +|message|str|错误信息|默认为空| +|ttl|num|1|| +|data|obj|数据本体|| + +`data`对象: + +|字段|类型|内容|备注| +|-|-|-|-| +|trending|obj|热搜榜单|套了个娃| + +`data`中的`trending`对象: + +|字段|类型|内容|备注| +|-|-|-|-| +|title|str|标题|| +|trackid|str|跟踪 ID?|| +|list|array|热搜列表|| +|top_list|array|空|| + +`trending`中的`list`数组: + +|项|类型|内容|备注| +|-|-|-|-| +|0|obj|热搜 1|| +|1|obj|热搜 2|| +|……|obj|……|| +|n|obj|热搜 (n+1)|| + +`list`数组中的对象: + +|字段|类型|内容|备注| +|-|-|-|-| +|keyword|str|关键词|| +|show_name|str|显示文字|| +|icon|str|图标 URL|| +|uri|str|空|| +|goto|str|空|| + +**示例:** + +获取热搜列表, 数量限制 4 + +```shell +curl -G --url 'https://api.bilibili.com/x/web-interface/search/square' \ +--url-query 'limit=4' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "trending": { + "title": "bilibili热搜", + "trackid": "8079760748892487175", + "list": [ + { + "keyword": "马克龙祝贺中国世界前两名", + "show_name": "马克龙祝贺中国世界前两名", + "icon": "http://i0.hdslb.com/bfs/activity-plat/static/20221213/eaf2dd702d7cc14d8d9511190245d057/lrx9rnKo24.png", + "uri": "", + "goto": "" + }, + { + "keyword": "小孩电竞世界杯夺冠", + "show_name": "小孩电竞世界杯夺冠", + "icon": "http://i0.hdslb.com/bfs/activity-plat/static/20221213/eaf2dd702d7cc14d8d9511190245d057/lrx9rnKo24.png", + "uri": "", + "goto": "" + }, + { + "keyword": "孙颖莎说我全勤下班了", + "show_name": "孙颖莎说我全勤下班了", + "icon": "http://i0.hdslb.com/bfs/activity-plat/static/20221118/eaf2dd702d7cc14d8d9511190245d057/UF7B1wVKT2.png", + "uri": "", + "goto": "" + }, + { + "keyword": "7月广东新冠新增一万余例", + "show_name": "7月广东新冠新增一万余例", + "icon": "http://i0.hdslb.com/bfs/activity-plat/static/20221213/eaf2dd702d7cc14d8d9511190245d057/lrx9rnKo24.png", + "uri": "", + "goto": "" + } + ], + "top_list": [] + } + } +} +``` + +
+ +## 获取热搜列表(web端) + +> https://s.search.bilibili.com/main/hotword + +*请求方式:GET* + +榜单每隔固定时间统计一次,请求后返回搜索前10的关键词 + +带有转义 + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | ------------ | ------------- | +| exp_str | str | ??? | | +| code | num | 返回值 | 0:成功 | +| cost | obj | 详细搜索用时 | 大概是吧? | +| seid | str | 搜索seid | | +| timestamp | num | 榜单统计时间 | 时间戳 | +| message | str | 错误信息 | 默认为success | +| list | array | 热搜列表 | | + +`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ------------ | +| 0 | obj | 榜单第1名 | | +| n | obj | 榜单第(n+1)名 | 按照名次顺序 | +| 10 | obj | 榜单第10名 | 最后一项 | + +`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | -------- | ------- | +| status | str | 空 | | +| hot_id | num | 热词id | 大概是吧? | +| keyword | str | 关键词 | | +| resource_id| num | 资源id | | +| goto_type | num | 0 | | +| res | array| null | | +| show_name | str | 完整关键词| | +| pos | num | 名次 | 1-10 | +| word_type | num | 条目属性 | 4: 新
5: 热
6: [雾,咒,小丑(愚人节)] 具体看icon7: 直播中
8: 默认(无标签)
9: 梗
11: 话题
12: 独家 | +| id | num | 名次 | 1-10 | +| goto_value | str | 空 | | +| live_id | array| null | | +| name_type | str | 空 | | +| icon | str | 图标url | | + +**示例:** + +```shell +curl 'https://s.search.bilibili.com/main/hotword' +``` + +
+查看响应示例: + +```json +{ + "exp_str": "8104#8200#8300#8401#8500#5502#6699", + "code": 0, + "cost": { + "reas_request": "0.001895", + "params_check": "0.000127", + "reas_response_format": "0.000098", + "deserialize_response": "0.000080", + "reas_request_format": "0.000076", + "total": "0.002479", + "main_handler": "0.002252" + }, + "seid": "9318821020548476185", + "timestamp": 1596034742, + "message": "success", + "list": [{ + "status": "", + "hot_id": 11003, + "keyword": "流浪地球2刘德华", + "resource_id": 0, + "goto_type": 0, + "res": [ + + ], + "show_name": "流浪地球2刘德华造型", + "pos": 1, + "word_type": 8, + "id": 1, + "goto_value": "", + "live_id": [ + + ], + "name_type": "", + "icon": "http://i0.hdslb.com/bfs/feed-admin/e9e7a2d8497d4063421b685e72680bf1cfb99a0d.png" + }, + { + "status": "", + "hot_id": 11012, + "keyword": "QQ飞车手游飞跃黄河", + "resource_id": 0, + "goto_type": 0, + "res": [ + + ], + "show_name": "QQ飞车手游飞跃黄河", + "pos": 2, + "word_type": 8, + "id": 2, + "goto_value": "", + "live_id": [ + + ], + "name_type": "", + "icon": "http://i0.hdslb.com/bfs/feed-admin/4d579fb61f9655316582db193118bba3a721eec0.png" + }, + { + "status": "", + "hot_id": 10996, + "keyword": "西工大遭网络攻击最新调查", + "resource_id": 0, + "goto_type": 0, + "res": [ + + ], + "show_name": "西工大遭网络攻击最新调查", + "pos": 3, + "word_type": 8, + "id": 3, + "goto_value": "", + "live_id": [ + + ], + "name_type": "", + "icon": "http://i0.hdslb.com/bfs/feed-admin/e9e7a2d8497d4063421b685e72680bf1cfb99a0d.png" + }, + { + "status": "", + "hot_id": 11004, + "keyword": "EDG 起诉", + "resource_id": 0, + "goto_type": 0, + "res": [ + + ], + "show_name": "EDGJieJie已起诉多家企业", + "pos": 4, + "word_type": 8, + "id": 4, + "goto_value": "", + "live_id": [ + + ], + "name_type": "", + "icon": "http://i0.hdslb.com/bfs/feed-admin/4d579fb61f9655316582db193118bba3a721eec0.png" + }, + { + "status": "", + "hot_id": 10992, + "keyword": "隐入尘烟", + "resource_id": 0, + "goto_type": 0, + "res": [ + + ], + "show_name": "隐入尘烟全平台下架", + "pos": 5, + "word_type": 8, + "id": 5, + "goto_value": "", + "live_id": [ + + ], + "name_type": "", + "icon": "http://i0.hdslb.com/bfs/feed-admin/e9e7a2d8497d4063421b685e72680bf1cfb99a0d.png" + }, + { + "status": "", + "hot_id": 10987, + "keyword": "原神半年内最良心封神池", + "resource_id": 0, + "goto_type": 0, + "res": [ + + ], + "show_name": "原神半年内最良心封神池", + "pos": 6, + "word_type": 8, + "id": 6, + "goto_value": "", + "live_id": [ + + ], + "name_type": "", + "icon": "" + }, + { + "status": "", + "hot_id": 10988, + "keyword": "高校回应设国内首个元宇宙院系", + "resource_id": 0, + "goto_type": 0, + "res": [ + + ], + "show_name": "高校回应设国内首个元宇宙院系", + "pos": 7, + "word_type": 8, + "id": 7, + "goto_value": "", + "live_id": [ + + ], + "name_type": "", + "icon": "" + }, + { + "status": "", + "hot_id": 10994, + "keyword": "美宇宙飞船成功撞击小行星", + "resource_id": 0, + "goto_type": 0, + "res": [ + + ], + "show_name": "美宇宙飞船成功撞击小行星", + "pos": 8, + "word_type": 8, + "id": 8, + "goto_value": "", + "live_id": [ + + ], + "name_type": "", + "icon": "" + }, + { + "status": "", + "hot_id": 10991, + "keyword": "你薅的羊毛可能已违法", + "resource_id": 0, + "goto_type": 0, + "res": [ + + ], + "show_name": "你薅的羊毛可能已违法", + "pos": 9, + "word_type": 8, + "id": 9, + "goto_value": "", + "live_id": [ + + ], + "name_type": "", + "icon": "" + }, + { + "status": "", + "hot_id": 11013, + "keyword": "辛普森一家", + "resource_id": 0, + "goto_type": 0, + "res": [ + + ], + "show_name": "辛普森一家", + "pos": 10, + "word_type": 8, + "id": 10, + "goto_value": "", + "live_id": [ + + ], + "name_type": "", + "icon": "http://i0.hdslb.com/bfs/feed-admin/4d579fb61f9655316582db193118bba3a721eec0.png" + } + ] +} +``` + +
+ +## 获取热搜列表(手机端) + +> https://app.bilibili.com/x/v2/search/trending/ranking + +*请求方式:GET* + +榜单每隔固定时间统计一次 + +带有转义 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | ---------------- | ------ | ---- | +| limit | num | 热搜数量 | 非必要 | 留空为20, 最大为100 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | ------------ | ------------- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 返回值 | 默认为1 | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ------------ | +| trackid | num | | 不知用途 | +| list | array | 热搜列表 | | + +`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ------------ | +| 0 | obj | 榜单第1名 | | +| n | obj | 榜单第(n+1)名 | 按照名次顺序 | +| 20/limit | obj | 榜单第20名 | 最后一项 | + +`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | -------- | ------- | +| position | num | 名次 | 1-20/limit | +| keyword | str | 关键词 | | +| show_name | str | 完整关键词| | +| word_type | num | 条目属性 | 同 web 端 | +| icon | str | 图标url | | +| hot_id | num | 热词id | 大概是吧? | + +**示例:** + +```shell +curl 'https://app.bilibili.com/x/v2/search/trending/ranking' +``` + +
+查看响应示例: + +```json +{ + "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" + } +} +``` + +
diff --git a/bb-api-collect/docs/search/search_request.md b/bb-api-collect/docs/search/search_request.md new file mode 100644 index 0000000000..038c8f7d1c --- /dev/null +++ b/bb-api-collect/docs/search/search_request.md @@ -0,0 +1,1440 @@ +# 搜索 + +> **B站于2022年8月24日更新了搜索api,增加了一大堆Cookies的校验,如果Cookies不足会返回-412搜索被拦截。如果没有cookies的话,请在搜索之前先GET一遍 https://bilibili.com 以获取cookies** + +## 综合搜索(web端) + +> https://api.bilibili.com/x/web-interface/wbi/search/all/v2 + +> ~~https://api.bilibili.com/x/web-interface/search/all/v2~~ (旧链接) + +*方式:GET* + +鉴权方式:[Wbi 签名](../misc/sign/wbi.md), Cookie 中含有 [`buvid3`](../misc/buvid3_4.md) 字段 + +返回和关键字相关的20条信息 + +综合搜索为默认搜索方式,主要用于优先搜索用户、影视、番剧、游戏、话题等,并加载第一页的20项相关视频,还用于展示各个类型的结果数目,便于进一步分类搜索 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | ---------------- | ------ | ---- | +| keyword | str | 需要搜索的关键词 | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
-412:请求被拦截 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------------- | ----- | ---------------- | ---------------- | +| seid | str | 搜索id | | +| page | num | 页数 | 固定为1 | +| page_size | num | 每页条数 | 固定为20 | +| numResults | num | 总条数 | 最大值为1000 | +| numPages | num | 分页数 | 最大值为50 | +| suggest_keyword | str | 空 | **作用尚不明确** | +| rqt_type | str | search | **作用尚不明确** | +| cost_time | obj | 详细搜索用时 | 大概是吧? | +| exp_list | obj | ??? | **作用尚不明确** | +| egg_hit | num | 0 | **作用尚不明确** | +| pageinfo | obj | 分类页数信息 | | +| top_tlist | obj | 分类结果数目信息 | | +| show_column | num | 0 | **作用尚不明确** | +| show_module_list | array | 返回结果类型列表 | | +| result | array | 结果列表 | | + +`data`中的`cost_time`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------------- | ---- | ---- | ---- | +| params_check | str | | | +| illegal_handler | str | | | +| as_response_format | str | | | +| as_request | str | | | +| save_cache | str | | | +| deserialize_response | str | | | +| as_request_format | str | | | +| total | str | | | +| main_handler | str | | | + +`data`中的`pageinfo`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | -------- | ---- | +| pgc | obj | - | | +| live_room | obj | 直播数 | | +| photo | obj | 相簿数 | | +| topic | obj | 话题数 | | +| video | obj | 视频数 | | +| user | obj | - | | +| bili_user | obj | 用户数 | | +| media_ft | obj | 电影数 | | +| article | obj | 专栏数 | | +| media_bangumi | obj | 番剧数 | | +| special | obj | - | | +| operation_card | obj | - | | +| upuser | obj | - | | +| movie | obj | - | | +| live_all | obj | - | | +| tv | obj | - | | +| live | obj | 直播间数 | | +| bangumi | obj | - | | +| activity | obj | 活动数 | | +| live_master | obj | - | | +| live_user | obj | 主播数 | | + +`pageinfo`中的所有对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | -------- | ---- | +| numResults | num | 总计数量 | | +| total | num | 总计数量 | | +| pages | num | 分页数量 | | + +`data`中的`top_tlist`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | -------- | ---- | +| pgc | num | - | | +| live_room | num | 直播数 | | +| photo | num | 相簿数 | | +| topic | num | 话题数 | | +| video | num | 视频数 | | +| user | num | - | | +| bili_user | num | 用户数 | | +| media_ft | num | 电影数 | | +| article | num | 专栏数 | | +| media_bangumi | num | 番剧数 | | +| card | num | - | | +| operation_card | num | - | | +| upuser | num | - | | +| movie | num | - | | +| live_all | num | - | | +| tv | num | - | | +| live | num | 直播间数 | | +| special | num | - | | +| bangumi | num | - | | +| activity | num | 活动数 | | +| live_master | num | - | | +| live_user | num | 主播数 | | + +`data`中的`show_module_list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---- | +| 0 | str | activity | | +| 1 | str | web_game | 游戏 | +| 2 | str | card | | +| 3 | str | media_bangumi | 番剧 | +| 4 | str | media_ft | 电影 | +| 5 | str | bili_user | 用户 | +| 6 | str | user | | +| 7 | str | star | | +| 8 | str | video | 视频 | + +`data`中的`result`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| 0 | obj | - | | +| 1 | obj | 游戏结果 | | +| 2 | obj | - | | +| 3 | obj | 番剧结果 | | +| 4 | obj | 电影结果 | | +| 5 | obj | 用户结果 | | +| 6 | obj | - | | +| 7 | obj | - | | +| 8 | obj | 视频结果 | | + +`result`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----- | -------- | ------------------------------ | +| result_type | str | 结果类型 | 与`result`数组对应的项相同 | +| data | array | 搜索结果 | 结果为该项所对应的对象条目格式 | + +`result`数组中的对象中的`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---------------------------------------- | +| 0 | obj | 搜索结果1 | 对象详情见[搜索结果](search_response.md) | +| n | obj | 搜索结果(n+1) | 按照参数指定的顺序排列 | +| …… | obj | …… | …… | + +**示例:** + +使用综合搜索进行搜索关键字`洛天依` + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/search/all/v2' \ +--data-urlencode 'keyword=洛天依' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "seid": "8850295244740510044", + "page": 1, + "pagesize": 20, + "numResults": 1000, + "numPages": 50, + "suggest_keyword": "", + "rqt_type": "search", + "cost_time": { + "params_check": "0.000496", + "get upuser live status": "0.002325", + "illegal_handler": "0.000118", + "as_response_format": "0.007020", + "mysql_request": "0.000054", + "as_request": "0.099139", + "as_request_format": "0.002199", + "deserialize_response": "0.000342", + "total": "0.109753", + "main_handler": "0.109041" + }, + "exp_list": { + "5520": true + }, + "egg_hit": 0, + "pageinfo": { + "pgc": { + "numResults": 0, + "total": 0, + "pages": 0 + }, + "live_room": { + "numResults": 1, + "total": 1, + "pages": 1 + }, + "photo": { + "numResults": 1000, + "total": 1000, + "pages": 50 + }, + "bili_user": { + "numResults": 548, + "total": 548, + "pages": 28 + }, + "topic": { + "numResults": 0, + "total": 0, + "pages": 0 + }, + "video": { + "numResults": 1000, + "total": 1000, + "pages": 50 + }, + "user": { + "numResults": 0, + "total": 0, + "pages": 0 + }, + "article": { + "numResults": 1000, + "total": 1000, + "pages": 50 + }, + "media_ft": { + "numResults": 1, + "total": 1, + "pages": 1 + }, + "media_bangumi": { + "numResults": 0, + "total": 0, + "pages": 0 + }, + "special": { + "numResults": 14, + "total": 14, + "pages": 1 + }, + "operation_card": { + "numResults": 0, + "total": 0, + "pages": 0 + }, + "upuser": { + "numResults": 0, + "total": 0, + "pages": 0 + }, + "movie": { + "numResults": 0, + "total": 0, + "pages": 0 + }, + "live_all": { + "numResults": 2, + "total": 2, + "pages": 1 + }, + "tv": { + "numResults": 0, + "total": 0, + "pages": 0 + }, + "live": { + "numResults": 773, + "total": 773, + "pages": 39 + }, + "bangumi": { + "numResults": 0, + "total": 0, + "pages": 0 + }, + "activity": { + "numResults": 0, + "total": 0, + "pages": 0 + }, + "live_master": { + "numResults": 1, + "total": 1, + "pages": 1 + }, + "live_user": { + "numResults": 772, + "total": 772, + "pages": 39 + } + }, + "top_tlist": { + "pgc": 0, + "live_room": 1, + "photo": 1000, + "bili_user": 548, + "topic": 0, + "video": 1000, + "user": 0, + "article": 1000, + "media_ft": 1, + "media_bangumi": 0, + "card": 0, + "operation_card": 0, + "upuser": 0, + "movie": 0, + "tv": 0, + "live": 2, + "special": 14, + "bangumi": 0, + "activity": 0, + "live_master": 1, + "live_user": 772 + }, + "show_column": 0, + "show_module_list": [ + "bili_user", + "user", + "activity", + "web_game", + "card", + "media_bangumi", + "media_ft", + "star", + "video" + ], + "result": [ + { + "result_type": "bili_user", + "data": [ + { + "type": "bili_user", + "mid": 36081646, + "uname": "洛天依", + "usign": "上海禾念Vsinger旗下歌手,世界第一位VOCALOID中文虚拟歌姬。投食请戳:luotianyi@sh-henian.com", + "fans": 1982688, + "videos": 45, + "upic": "//i2.hdslb.com/bfs/face/cc96d1d6bf76f8198263f9083921997ab3a80d8b.jpg", + "verify_info": "", + "level": 6, + "gender": 2, + "is_upuser": 1, + "is_live": 0, + "room_id": 1546736, + "res": [ + { + "aid": 753839250, + "bvid": "BV1Hk4y1B7Cx", + "title": "【洛天依】2020.7.12洛天依生日会", + "pubdate": 1594559234, + "arcurl": "http://www.bilibili.com/video/av753839250", + "pic": "//i2.hdslb.com/bfs/archive/5347eafb5a65ad9a9ffc39063d686772ea1298c4.jpg", + "play": "269428", + "dm": 30648, + "coin": 33838, + "fav": 24066, + "desc": "从2012年一路走至2020年,8年间刻画下的无数回忆,都在生日会上娓娓道来。\n大家的每一次应援,每一条弹幕都无可替代,都凝结着无可比拟的珍贵回忆。\n希望天依的歌声能鼓起每个人心中的勇气,跨过悲伤、无力,去迎接希望。\n愿我们一同携手成长~相扶相伴。\n天依的首张官方数字专辑也已经上线,等你来听。\n试听: BV1Tp4y1S7cu\n购买:https://y.music.163.com/m/album?id=92206376", + "duration": "58:6", + "is_pay": 0, + "is_union_video": 0 + }, + { + "aid": 968772260, + "bvid": "BV1Tp4y1S7cu", + "title": "【洛天依原创曲】万分之一的光", + "pubdate": 1594557008, + "arcurl": "http://www.bilibili.com/video/av968772260", + "pic": "//i1.hdslb.com/bfs/archive/67c6118e4f94bee89b984525ca665fc88c969cac.jpg", + "play": "333322", + "dm": 9323, + "coin": 39961, + "fav": 29818, + "desc": "8年间我们一起经历了许多,有欢乐也有悲伤,有相遇自然也有别离,但曾相处的日子永远那么辉光闪耀。\n感谢你成为我的光芒,而我也会是你万分之一的光。\n\n音乐:ChiliChill\n贝斯:山口進也\n鼓手:口口口口口\n调校:动点P\n弦乐编配:胡静成 / ChiliChill\n小提琴:庞阔 / 张浩\n中提琴:毕芳\n大提琴:郎莹\n监制:人形兎\n出品:Vsinger", + "duration": "4:12", + "is_pay": 0, + "is_union_video": 1 + }, + { + "aid": 883803983, + "bvid": "BV1kK4y1s7Dd", + "title": "洛天依2020官方专辑《Moments》试听PV", + "pubdate": 1594526467, + "arcurl": "http://www.bilibili.com/video/av883803983", + "pic": "//i1.hdslb.com/bfs/archive/2ff004df9d98e2a78531c6400ee8e823fb30e6f4.jpg", + "play": "205340", + "dm": 7748, + "coin": 18792, + "fav": 14222, + "desc": "8是数字也是象征;\n∞是循环也是无限;\n \n音乐给予了我诞生和成长的力量,让我不断汲取养分,直至冲破险阻向阳生长;\n音乐让我更加幸运,在曾经未知的道路上遇见属于我们彼此的蓝色星光;\n那些一路上的美好,我都想和你们一起收集,瞬间即永恒。\n\n--------Staff--------\n作曲:Chilichill / COP / 人形兎 / 纯白P / 花之祭P / 希望索任合资 / 银临 / JUSF周存\n作词: Chilichill / COP / 人形兎 / 果汁凉菜 / 沈病娇 / 南岐 / 冥凰 / ", + "duration": "3:44", + "is_pay": 0, + "is_union_video": 0 + } + ], + "official_verify": { + "type": 0, + "desc": "洛天依官方账号" + }, + "hit_columns": [ + "uname" + ] + } + ] + }, + { + "result_type": "user", + "data": [] + }, + { + "result_type": "activity", + "data": [] + }, + { + "result_type": "web_game", + "data": [] + }, + { + "result_type": "card", + "data": [] + }, + { + "result_type": "media_bangumi", + "data": [] + }, + { + "result_type": "media_ft", + "data": [] + }, + { + "result_type": "star", + "data": [] + }, + { + "result_type": "video", + "data": [ + { + "type": "video", + "id": 753839250, + "author": "洛天依", + "mid": 36081646, + "typeid": "30", + "typename": "VOCALOID·UTAU", + "arcurl": "http://www.bilibili.com/video/av753839250", + "aid": 753839250, + "bvid": "BV1Hk4y1B7Cx", + "title": "【洛天依】2020.7.12洛天依生日会", + "description": "从2012年一路走至2020年,8年间刻画下的无数回忆,都在生日会上娓娓道来。\n大家的每一次应援,每一条弹幕都无可替代,都凝结着无可比拟的珍贵回忆。\n希望天依的歌声能鼓起每个人心中的勇气,跨过悲伤、无力,去迎接希望。\n愿我们一同携手成长~相扶相伴。\n天依的首张官方数字专辑也已经上线,等你来听。\n试听: BV1Tp4y1S7cu\n购买:https://y.music.163.com/m/album?id=92206376", + "arcrank": "0", + "pic": "//i2.hdslb.com/bfs/archive/5347eafb5a65ad9a9ffc39063d686772ea1298c4.jpg", + "play": 269428, + "video_review": 30648, + "favorites": 24066, + "tag": "VSINGER,洛天依生日快乐,2020洛天依生日会,洛天依生日会,VOCALOID,洛天依", + "review": 4391, + "pubdate": 1594559234, + "senddate": 1594559234, + "duration": "58:6", + "badgepay": false, + "hit_columns": [ + "title", + "author", + "tag" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 102616359 + }, + { + "type": "video", + "id": 753460703, + "author": "低调的黑叔", + "mid": 22065421, + "typeid": "25", + "typename": "MMD·3D", + "arcurl": "http://www.bilibili.com/video/av753460703", + "aid": 753460703, + "bvid": "BV1Zk4y1B7bn", + "title": "【4K/布料/水手服】洛天依 - GimmexGimme", + "description": "喜欢本期4K请点个关注并长按视频下方大拇指一键三连拜托啦这对我真的很重要\n\nModel:\niRon0129/夏夜/Tda様/やまもと/Samsink(机动战士牛肉)\n\nMotion:\nシガー\n\nSailor Suit:\n星音\n\nStage:\nG_Wuuuuu\n\nRenderer:\nToolbag 3\n\nMusic:\n【初音ミク×鏡音リン】Gimme×Gimme【八王子P×Giga】", + "arcrank": "0", + "pic": "//i1.hdslb.com/bfs/archive/d1bd3d4d12b1e115ce82463853ff791a45472f1f.jpg", + "play": 809854, + "video_review": 1189, + "favorites": 47632, + "tag": "自制,3D,TDA,动画,百万剪辑师挑战,洛天依,美腿,舞蹈MMD,4K", + "review": 798, + "pubdate": 1591367468, + "senddate": 1591404973, + "duration": "1:11", + "badgepay": false, + "hit_columns": [ + "title", + "tag" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 102465557 + }, + { + "type": "video", + "id": 10131337, + "author": "赛亚♂sya", + "mid": 157056, + "typeid": "30", + "typename": "VOCALOID·UTAU", + "arcurl": "http://www.bilibili.com/video/av10131337", + "aid": 10131337, + "bvid": "BV1fx411U7Kg", + "title": "【洛天依原创】自言自语", + "description": "词曲编调绘:Sya;混音:JUSF周存;简介你随便拿个之前的复制粘贴就行", + "arcrank": "0", + "pic": "//i0.hdslb.com/bfs/archive/e5aab7ddab3e060854e420edae6c5282cbe09324.jpg", + "play": 746480, + "video_review": 4665, + "favorites": 49097, + "tag": "黑洛,诚信代投,自言自语,洛天依,VOCALOID中文曲,原创,高级一图流,自x自x,自A自B系列,赛亚♂sya,JUSF周存", + "review": 7310, + "pubdate": 1493282828, + "senddate": 1542308981, + "duration": "4:14", + "badgepay": false, + "hit_columns": [ + "title", + "tag" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 102432728 + }, + ………… + ] + } + ] + } +} +``` + +
+ +## 分类搜索(web端) + +> https://api.bilibili.com/x/web-interface/wbi/search/type + +> ~~https://api.bilibili.com/x/web-interface/search/type~~ (旧链接) + +*请求方式:GET* + +鉴权方式:[Wbi 签名](../misc/sign/wbi.md), Cookie 中含有 [`buvid3`](../misc/buvid3_4.md) 字段, Referer 在 `.bilibili.com` 下, User-Agent 不含敏感子串 + +根据关键词进行搜索,返回结果每页20项 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----------- | ---- | ------------------------ | ------ | ------------------------------------------------------------ | +| search_type | str | 搜索目标类型 | 必要 | 视频:video
番剧:media_bangumi
影视:media_ft
直播间及主播:live
直播间:live_room
主播:live_user
专栏:article
话题:topic
用户:bili_user
相簿:photo | +| keyword | str | 需要搜索的关键词 | 必要 | | +| order | str | 结果排序方式 | 非必要 | 搜索类型为视频、专栏及相簿时:
默认为totalrank
综合排序:totalrank
最多点击:click
最新发布:pubdate
最多弹幕:dm
最多收藏:stow
最多评论:scores
最多喜欢:attention(仅用于专栏)
----------------------------
搜索结果为直播间时:
默认为online
人气直播:online
最新开播:live_time
----------------------------
搜索结果为用户时:
默认为0
默认排序:0
粉丝数:fans
用户等级:level | +| order_sort | num | 用户粉丝数及等级排序顺序 | 非必要 | 仅用于搜索用户
默认为0
由高到低:0
由低到高:1 | +| user_type | num | 用户分类筛选 | 非必要 | 仅用于搜索用户
默认为0
全部用户:0
up主:1
普通用户:2
认证用户:3 | +| duration | num | 视频时长筛选 | 非必要 | 仅用于搜索视频
默认为0
全部时长:0
10分钟以下:1
10-30分钟:2
30-60分钟:3
60分钟以上:4 | +| tids | num | 视频分区筛选 | 非必要 | 仅用于搜索视频
默认为0
全部分区:0
筛选分区:目标分区tid | +| category_id | num | 专栏及相簿分区筛选 | 非必要 | 搜索结果为专栏时:
默认为0
全部分区:0
动画:2
游戏:1
影视:28
生活:3
兴趣:29
轻小说:16
科技:17
--------
搜索结果为相簿时:
默认为0
全部分区:0
画友:1
摄影:2 | +| page | num | 页码 | 非必要 | 默认为1 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0: 成功
-400: 请求错误
-412: 请求被拦截
-1200: 被降级过滤的请求(搜索目标类型不存在) | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---------------------------------------------------------- | ------------ | ------------------------------ | +| seid | num | 搜索seid | | +| page | num | 当前页码 | | +| pagesize | num | 每页条数 | 固定20 | +| numResults | num | 总条数 | 最大值为1000 | +| numPages | num | 总计分页数 | 最大值为50 | +| suggest_keyword | str | 空 | **作用尚不明确** | +| rqt_type | str | search | **作用尚不明确** | +| cost_time | obj | 详细搜索用时 | 大概 | +| exp_list | obj | ??? | **作用尚不明确** | +| egg_hit | num | 0 | **作用尚不明确** | +| pageinfo | obj | 副分页信息 | 只在搜索类型为直播间及主播有效 | +| result | 搜索类型为直播间及主播时:obj
搜索类型为其他时:array | 结果列表 | | +| show_column | num | 0 | **作用尚不明确** | + +`data`中的`cost_time`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------------- | ---- | ---- | ---- | +| params_check | str | | | +| illegal_handler | str | | | +| as_response_format | str | | | +| as_request | str | | | +| save_cache | str | | | +| deserialize_response | str | | | +| as_request_format | str | | | +| total | str | | | +| main_handler | str | | | + +`data`中的`pageinfo`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ---------- | ---- | +| live_room | obj | 直播间信息 | | +| live_user | obj | 主播信息 | | + +`pageinfo`中的`live_room`及`live_user`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | -------- | ---- | +| numPages | num | 总计页数 | | +| numResults | num | 总计项数 | | +| total | num | 总计项数 | | +| pages | num | 总计页数 | | + +**搜索类型为直播间及主播时:** + +`data`中的`result`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | ---------- | ---- | +| live_room | array | 直播间信息 | | +| live_user | array | 主播信息 | | + +`result`中的`live_room`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------------- | ---------------------------------------- | +| 0 | obj | 直播间搜索结果1 | 对象详情见[搜索结果](search_response.md) | +| n | obj | 直播间搜索结果(n+1) | 按照参数指定的顺序排列 | +| …… | obj | …… | …… | + +`result`中的`live_user`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------------- | ---------------------------------------- | +| 0 | obj | 主播搜索结果1 | 对象详情见[搜索结果](search_response.md) | +| n | obj | 主播搜索结果(n+1) | 按照参数指定的顺序排列 | +| …… | obj | …… | …… | + +**搜索类型为其他时:** + +`data`中的`result`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---------------------------------------- | +| 0 | obj | 搜索结果1 | 对象详情见[搜索结果](search_response.md) | +| n | obj | 搜索结果(n+1) | 按照参数指定的顺序排列 | +| …… | obj | …… | …… | + +**示例:** + +按照关键词` 少年 `搜索视频,默认排序,全部时长,全部分区,第1页 + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/search/type' \ +--data-urlencode 'search_type=video' \ +--data-urlencode 'keyword=少年' \ +--data-urlencode 'order=totalrank' \ +--data-urlencode 'duration=0' \ +--data-urlencode 'tids=0' \ +--data-urlencode 'page=1' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "seid": "9339963973663795027", + "page": 1, + "pagesize": 20, + "numResults": 1000, + "numPages": 50, + "suggest_keyword": "", + "rqt_type": "search", + "cost_time": { + "params_check": "0.000300", + "illegal_handler": "0.000077", + "as_response_format": "0.003071", + "as_request": "0.072525", + "save_cache": "0.001115", + "deserialize_response": "0.000310", + "as_request_format": "0.000319", + "total": "0.077996", + "main_handler": "0.076419" + }, + "exp_list": { + "5520": true + }, + "egg_hit": 0, + "result": [ + { + "type": "video", + "id": 243082173, + "author": "大橘爱吃猫", + "mid": 178932626, + "typeid": "193", + "typename": "MV", + "arcurl": "http://www.bilibili.com/video/av243082173", + "aid": 243082173, + "bvid": "BV1De411p77r", + "title": "梦然-《少年》官方版", + "description": "https://www.ixigua.com/i6822128361129640462/?logTag=EBTB5DTpBmxcfK1GYOOea\n梦然老师《少年》MV官方版,原版:西瓜视频搜索“抖音梦然-《少年》” 抖音搜索 “《少年》MV梦然。", + "arcrank": "0", + "pic": "//i0.hdslb.com/bfs/archive/e25120857a6298d1d4b9e64a805c023b5143c8ff.jpg", + "play": 1037655, + "video_review": 2616, + "favorites": 27341, + "tag": "华语MV,国语MV,梦然,少年,梦想,成长,循环,热歌", + "review": 1265, + "pubdate": 1588407050, + "senddate": 1588407051, + "duration": "4:18", + "badgepay": false, + "hit_columns": [ + "title", + "description", + "tag" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 105415949 + }, + { + "type": "video", + "id": 97387124, + "author": "小石头和孩子们", + "mid": 324914635, + "typeid": "31", + "typename": "翻唱", + "arcurl": "http://www.bilibili.com/video/av97387124", + "aid": 97387124, + "bvid": "BV1B7411R7a8", + "title": "你还是从前的那个少年吗?来自元气少女超甜的《少年》", + "description": "", + "arcrank": "0", + "pic": "//i1.hdslb.com/bfs/archive/8502088a888aeb37df7c4bd1b77d57aabae4f4d3.jpg", + "play": 1953494, + "video_review": 5934, + "favorites": 50883, + "tag": "全民音乐UP主,小石头和孩子们,少年,MV,翻唱,音乐推荐", + "review": 2963, + "pubdate": 1584581433, + "senddate": 1584581434, + "duration": "4:1", + "badgepay": false, + "hit_columns": [ + "title", + "tag" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 101083208 + }, + { + "type": "video", + "id": 200115746, + "author": "似乎一脸懵逼", + "mid": 110939266, + "typeid": "22", + "typename": "鬼畜调教", + "arcurl": "http://www.bilibili.com/video/av200115746", + "aid": 200115746, + "bvid": "BV1Yz411b7A3", + "title": "【马化腾】我还是充钱那个少年,没有一丝丝改变~", + "description": "临时做的小作品\n音源:-提问-", + "arcrank": "0", + "pic": "//i1.hdslb.com/bfs/archive/078a9b50b4df8d25c2f586668741b30348604173.jpg", + "play": 1069066, + "video_review": 3198, + "favorites": 16321, + "tag": "黄绿合战5th-绿队应援,马化腾,鬼畜调教,腾讯,腾讯游戏,QQ,氪金,少年,我还是从前那个少年", + "review": 1438, + "pubdate": 1585650825, + "senddate": 1586310556, + "duration": "1:26", + "badgepay": false, + "hit_columns": [ + "title", + "tag" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 100482941 + }, + { + "type": "video", + "id": 96440301, + "author": "Da圣音乐", + "mid": 353230307, + "typeid": "130", + "typename": "音乐综合", + "arcurl": "http://www.bilibili.com/video/av96440301", + "aid": 96440301, + "bvid": "BV1LE411G7F4", + "title": "最近突然火的《少年》太好听了,单曲循环了很多遍!", + "description": "Hello,大家好,我是阿光\n本期节目为大家盘点三首最近特别火的中文歌曲\n我保证每一首歌都能撩动你的心弦\n来喽,正如:恰同学少年,风华正茂!\n第一首就是歌手梦然发行于2019年的《少年》\n第二首《后会无期》\n第三首《平凡天使》", + "arcrank": "0", + "pic": "//i2.hdslb.com/bfs/archive/bcde6fb455902b367138b7a4026419de0a50a42d.jpg", + "play": 2440158, + "video_review": 2314, + "favorites": 7163, + "tag": "乐评盘点,音乐,少年,后会无期,平凡天使,邓紫棋,热门歌曲,感动,高考,疫情", + "review": 1072, + "pubdate": 1584334818, + "senddate": 1584339026, + "duration": "3:2", + "badgepay": false, + "hit_columns": [ + "title", + "description", + "tag" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 100455675 + }, + { + "type": "video", + "id": 370000842, + "author": "猫耳半圆", + "mid": 485450109, + "typeid": "24", + "typename": "MAD·AMV", + "arcurl": "http://www.bilibili.com/video/av370000842", + "aid": 370000842, + "bvid": "BV1AZ4y1j7t6", + "title": "最近火爆全网的《少年》,你喜欢吗?", + "description": "BGM:少年——梦然\n花了好多心思的作品,求个三连呀φ(>ω<*)", + "arcrank": "0", + "pic": "//i0.hdslb.com/bfs/archive/7437b6f66856b0d87437afd8827939954716cb2f.jpg", + "play": 2257050, + "video_review": 16225, + "favorites": 95864, + "tag": "bilibili新星计划,AMV,MAD,新人向,论BGM的重要性,青春,少年,治愈向,催泪向,多素材", + "review": 3548, + "pubdate": 1585459066, + "senddate": 1585459067, + "duration": "1:37", + "badgepay": false, + "hit_columns": [ + "title", + "description", + "tag" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 100409086 + }, + { + "type": "video", + "id": 837972700, + "author": "Da圣音乐", + "mid": 353230307, + "typeid": "130", + "typename": "音乐综合", + "arcurl": "http://www.bilibili.com/video/av837972700", + "aid": 837972700, + "bvid": "BV1Ug4y1z7oN", + "title": "终于找到日语版《少年》了!开口就是恋爱的味道,岛国也要被洗脑", + "description": "终于找到日语版《少年》了!开口就是恋爱的味道,岛国也要被洗脑", + "arcrank": "0", + "pic": "//i2.hdslb.com/bfs/archive/413b5417418c0e1107b3f79a284d20040b8bb4e9.jpg", + "play": 1390981, + "video_review": 2344, + "favorites": 11330, + "tag": "乐评盘点,梦然,少年,下山,日语,斋藤飞鸟,告白气球,花泽香菜,火影忍者,海贼王", + "review": 988, + "pubdate": 1588239130, + "senddate": 1588241127, + "duration": "3:12", + "badgepay": false, + "hit_columns": [ + "title", + "description", + "tag" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 100407822 + }, + { + "type": "video", + "id": 285145715, + "author": "潮汕好男人", + "mid": 19071708, + "typeid": "22", + "typename": "鬼畜调教", + "arcurl": "http://www.bilibili.com/video/av285145715", + "aid": 285145715, + "bvid": "BV1ac411h7BC", + "title": "【全明星】少年", + "description": "我还是充钱那个少年,又大又圆的少年\nBGM:少年\n制作:MC传奇(潮汕好男人/永远的MG)\n\n黄绿合战Day.3 对阵作品:BV1qQ4y1K7Gs, 投票传送门:https://www.bilibili.com/blackboard/activity-yellowVSgreen5th.html", + "arcrank": "0", + "pic": "//i1.hdslb.com/bfs/archive/911faee003fc828c46497cbd58fab0e22c7554f8.jpg", + "play": 3689254, + "video_review": 38262, + "favorites": 115408, + "tag": "鬼畜调教,鬼畜,黄绿合战,少年,黄绿合战5th,全明星", + "review": 4560, + "pubdate": 1586404524, + "senddate": 1592816392, + "duration": "3:1", + "badgepay": false, + "hit_columns": [ + "title", + "description", + "tag" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 100254286 + }, + { + "type": "video", + "id": 51475845, + "author": "吃你的馒头", + "mid": 25770774, + "typeid": "137", + "typename": "明星", + "arcurl": "http://www.bilibili.com/video/av51475845", + "aid": 51475845, + "bvid": "BV1K4411i7mw", + "title": "【日本少年混剪】氧气/心动瞬间/薄荷味的夏天要来了", + "description": "个人喜欢的霓虹国少年们混剪\n\n喜欢的少年会让我想起夏天,淡淡的薄荷味在校服衬衫晕开,笑容在空气里变成汽水,砰的一声打开砸向心脏。\n\nBGM:米津玄师/菅田将晖《灰色与青》\n\n道枝骏佑/新田真剑佑/菅田将晖\n坂口健太郎/古川雄辉/山崎贤人\n山田凉介/片寄凉太/贺来贤人\n龙星凉/佐藤健/吉沢亮\n柏原崇/锦户亮\n\n不按出场顺序(剪得昏天黑地完全记不住)\n\n禁二改转载出站,微博非本人发布皆为盗取视频,请随手举报或@吃你的馒头。\n\n原创作品不易,谢谢喜欢和理解。", + "arcrank": "0", + "pic": "//i2.hdslb.com/bfs/archive/93ae9d66eaf62161f1f12d0102b6c2d66ebe05a9.jpg", + "play": 1842547, + "video_review": 10738, + "favorites": 136384, + "tag": "明星,龙星凉,新田真剑佑,菅田将晖,古川雄辉,片寄凉太,柏原崇,山崎贤人,道枝骏佑,贺来贤人,山田凉介,锦户亮", + "review": 2385, + "pubdate": 1556992133, + "senddate": 1559716273, + "duration": "3:5", + "badgepay": false, + "hit_columns": [ + "title", + "description" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 100239604 + }, + { + "type": "video", + "id": 967814999, + "author": "沙拉酱merry", + "mid": 492472, + "typeid": "31", + "typename": "翻唱", + "arcurl": "http://www.bilibili.com/video/av967814999", + "aid": 967814999, + "bvid": "BV1Hp4y1y7iQ", + "title": "真的不是原唱?!《少年》超A御姐音翻唱", + "description": "少年\n词/曲/原唱/Rap:梦然\n和声编写:海青/梦然\n和声演唱:海青/梦然\n翻唱:沙拉酱merry\n后期:小敏\n这首歌真好听!\nPs:由于这首歌的难度和换气问题,音频和视频是分开录的所以会有口型差异,敬请谅解!!!大家听歌愉快~", + "arcrank": "0", + "pic": "//i0.hdslb.com/bfs/archive/565e8cdc98dab13dfa547cb13744410964f2fc00.jpg", + "play": 959598, + "video_review": 2447, + "favorites": 15166, + "tag": "被才华封印的颜值,少年,翻唱,女声,沙拉酱merry,御姐音", + "review": 1371, + "pubdate": 1587114006, + "senddate": 1587114030, + "duration": "7:58", + "badgepay": false, + "hit_columns": [ + "title", + "description", + "tag" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 100235329 + }, + { + "type": "video", + "id": 455021866, + "author": "鲨然鲨然", + "mid": 435476320, + "typeid": "126", + "typename": "人力VOCALOID", + "arcurl": "http://www.bilibili.com/video/av455021866", + "aid": 455021866, + "bvid": "BV195411673y", + "title": "【川普】我还是曾经那个少年", + "description": "鬼畜娱乐,请勿当真哦\n希望大家能开怀一笑\n笑了的话别忘了点赞哦", + "arcrank": "0", + "pic": "//i0.hdslb.com/bfs/archive/7cee31977deb39f297d2d2598e736d26ed337568.jpg", + "play": 3845319, + "video_review": 34660, + "favorites": 74705, + "tag": "黄绿合战5th-黄队应援,鬼畜调教,人力VOCALOID,自制,UTAU,川普,搞笑,少年,恶搞,青春", + "review": 4469, + "pubdate": 1585651085, + "senddate": 1586266006, + "duration": "2:56", + "badgepay": false, + "hit_columns": [ + "title", + "tag" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 100163091 + }, + { + "type": "video", + "id": 753055295, + "author": "大门E", + "mid": 735734, + "typeid": "31", + "typename": "翻唱", + "arcurl": "http://www.bilibili.com/video/av753055295", + "aid": 753055295, + "bvid": "BV1xk4y1k7aw", + "title": "【完整版日语版《少年》本尊来了】竟是国人元老唱见~", + "description": "词:lolo2513&梦然\n曲:梦然\n编曲:张亮\n混音:顾潇予\nPV:大门E\n之前唱了一个片段不料被许多人误以为《少年》原版是日本歌曲改编。因为没有版权一直没full,如今终于得到梦然老师(版权方)的认可及改编授权,终于出来了,再次感谢~!以我的key重新编曲,好哥们儿@lolo2513 老师的完整版日文填词,满满的少年jump既视感,唱的时候满脑子鸣人路飞,作为一个十五年的国人老唱见能被大家认可一首ACG歌曲简直泪流满面,希望大家能够喜欢~", + "arcrank": "0", + "pic": "//i1.hdslb.com/bfs/archive/363ece7b0fd61d1eb48a4bc3c2e804446b46ca1d.jpg", + "play": 676181, + "video_review": 1209, + "favorites": 31147, + "tag": "bilibili新星计划,少年,日语歌,翻唱", + "review": 1964, + "pubdate": 1588932007, + "senddate": 1588957659, + "duration": "4:1", + "badgepay": false, + "hit_columns": [ + "title", + "description", + "tag" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 100152701 + }, + { + "type": "video", + "id": 328601322, + "author": "萌宠教主", + "mid": 23976014, + "typeid": "24", + "typename": "MAD·AMV", + "arcurl": "http://www.bilibili.com/video/av328601322", + "aid": 328601322, + "bvid": "BV1EA411i7MD", + "title": "用三十部动漫唱一首《少年》——你长大了,你还在追番吗?", + "description": "BGM:少年\n【剪辑,填词】萌宠教主\n【演唱】浅若_natsu", + "arcrank": "0", + "pic": "//i0.hdslb.com/bfs/archive/eb7c1be356fd3bc6a947bb6398b6f02fc961bec2.jpg", + "play": 381018, + "video_review": 2881, + "favorites": 28530, + "tag": "少年,AMV,多素材,MAD,综漫,混剪,梦然,催泪", + "review": 922, + "pubdate": 1592020805, + "senddate": 1592020836, + "duration": "4:5", + "badgepay": false, + "hit_columns": [ + "title", + "description", + "tag" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 100129139 + }, + { + "type": "video", + "id": 838737756, + "author": "bili_148834382", + "mid": 148834382, + "typeid": "138", + "typename": "搞笑", + "arcurl": "http://www.bilibili.com/video/av838737756", + "aid": 838737756, + "bvid": "BV1Ug4y1v7mU", + "title": "大爷:我还是从前那个少年,没有一丝丝改变!", + "description": "大爷:我还是从前那个少年,没有一丝丝改变!", + "arcrank": "0", + "pic": "//i2.hdslb.com/bfs/archive/912cb238879558119d2f129438d7c71bb4372f9e.jpg", + "play": 7052, + "video_review": 18, + "favorites": 17, + "tag": "逗比,挑战,卧槽,沙雕,搞笑,大爷,厉害了,不一样呀,秀", + "review": 8, + "pubdate": 1593489906, + "senddate": 1593489906, + "duration": "1:34", + "badgepay": false, + "hit_columns": [ + "title", + "description" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 100123108 + }, + { + "type": "video", + "id": 541162396, + "author": "鬼兄奇谈", + "mid": 94641579, + "typeid": "124", + "typename": "社科人文", + "arcurl": "http://www.bilibili.com/video/av541162396", + "aid": 541162396, + "bvid": "BV1Bi4y1G7mo", + "title": "少年黑帮“新龙会”覆灭记!史上最“中二”的黑社会,作案后竟留下错别字?", + "description": "少年黑帮“新龙会”覆灭记!史上最“中二”的黑社会,作案后竟留下错别字?\n视频内容及素材均来源于网络", + "arcrank": "0", + "pic": "//i2.hdslb.com/bfs/archive/4c0c8d8f720119e3087b6b02025c3d957d642781.jpg", + "play": 150747, + "video_review": 627, + "favorites": 487, + "tag": "犯罪,案件,奇闻,全能打卡挑战,学生,法制,黑社会,中二,违法", + "review": 438, + "pubdate": 1593596709, + "senddate": 1593596710, + "duration": "8:42", + "badgepay": false, + "hit_columns": [ + "title", + "description" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 100120066 + }, + { + "type": "video", + "id": 413715309, + "author": "wkkm13", + "mid": 4056950, + "typeid": "76", + "typename": "美食圈", + "arcurl": "http://www.bilibili.com/video/av413715309", + "aid": 413715309, + "bvid": "BV1gV41167WS", + "title": "梦开始的地方,一年前那个不会剪辑的少年阿强。", + "description": "转自强哥第一个视频,那时候他还叫“浮华d假象”。\n梦开始的地方,那个不会剪辑的少年。", + "arcrank": "0", + "pic": "//i0.hdslb.com/bfs/archive/73772867e6a4ebaf66a12c73f1bc0d7a1f0fa085.jpg", + "play": 149332, + "video_review": 332, + "favorites": 86, + "tag": "cram阿强,泪目,美食,吃播,梦想,剪辑", + "review": 437, + "pubdate": 1593604848, + "senddate": 1593604848, + "duration": "5:31", + "badgepay": false, + "hit_columns": [ + "title", + "description" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 100102196 + }, + { + "type": "video", + "id": 838507935, + "author": "木子山上起酥酥", + "mid": 185924591, + "typeid": "75", + "typename": "动物圈", + "arcurl": "http://www.bilibili.com/video/av838507935", + "aid": 838507935, + "bvid": "BV1Jg4y1q77h", + "title": "少年人,这是修行。", + "description": "微博", + "arcrank": "0", + "pic": "//i1.hdslb.com/bfs/archive/8eae881830a5fc2be1434781e086f7191082cec8.jpg", + "play": 120068, + "video_review": 43, + "favorites": 312, + "tag": "逗比,正能量,水豚,动物", + "review": 155, + "pubdate": 1592366769, + "senddate": 1592366769, + "duration": "0:15", + "badgepay": false, + "hit_columns": [ + "title" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 100101593 + }, + { + "type": "video", + "id": 47749359, + "author": "Da圣音乐", + "mid": 353230307, + "typeid": "130", + "typename": "音乐综合", + "arcurl": "http://www.bilibili.com/video/av47749359", + "aid": 47749359, + "bvid": "BV12b411W7nF", + "title": "16岁中国少年韩国综艺上怒怼:老子来自中国!现场一片哗然", + "description": "16岁中国少年韩国综艺上怒怼:老子来自中国!现场一片哗然", + "arcrank": "0", + "pic": "//i1.hdslb.com/bfs/archive/171d9b27a0b9823b71894008117501014dd561ba.jpg", + "play": 5042589, + "video_review": 3949, + "favorites": 26065, + "tag": "说唱,韩国,中国,音乐选集,Rap,瞧不起,DISS,迪亚克,D.ark,综艺节目", + "review": 2793, + "pubdate": 1553926233, + "senddate": 1553926233, + "duration": "2:38", + "badgepay": false, + "hit_columns": [ + "title", + "description" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 100101064 + }, + { + "type": "video", + "id": 82363754, + "author": "在下甘柒辣", + "mid": 374835894, + "typeid": "24", + "typename": "MAD·AMV", + "arcurl": "http://www.bilibili.com/video/av82363754", + "aid": 82363754, + "bvid": "BV1qJ411V7QH", + "title": "我已不再是少年,但你们终究活在我心里", + "description": "国动会越来越好的,它由我们一同注目它的成长。\nBGM: start\n可否给个币,给这个肝疼的up点鼓励( ̄y▽ ̄)~*", + "arcrank": "0", + "pic": "//i2.hdslb.com/bfs/archive/2c7afbc835dbce9f554eb1b21b583ef6bed34cce.jpg", + "play": 1588667, + "video_review": 6782, + "favorites": 37909, + "tag": "国产动画,国漫良心,国漫,国漫王者归来,星游记,镇魂街,灵笼,刺客伍六七,大圣归来,哪吒", + "review": 1190, + "pubdate": 1578320753, + "senddate": 1582999612, + "duration": "3:44", + "badgepay": false, + "hit_columns": [ + "title" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 100099970 + }, + { + "type": "video", + "id": 413742409, + "author": "音乐Fans小琼", + "mid": 342943435, + "typeid": "130", + "typename": "音乐综合", + "arcurl": "http://www.bilibili.com/video/av413742409", + "aid": 413742409, + "bvid": "BV1bV41167Un", + "title": "《少年》霸占7周热歌第一,如今终于被新的神曲打破!网友:听吐了!", + "description": "bgm 纸砚zyan《画皮》\n《惊雷》MC六道\n《素颜》许嵩\n《麻雀》李荣浩\n《点歌的人》海来阿木\n《桥边姑娘》海伦 \n《旧梦一场》阿悠悠\n《世界这么大还是遇见你》程响(翻唱)\n《后来遇见他》胡66\n《处处吻》杨千嬅\n《少年》梦然", + "arcrank": "0", + "pic": "//i2.hdslb.com/bfs/archive/f004565df82a9ac3a8a168b4c12e244861f1d812.jpg", + "play": 12363, + "video_review": 137, + "favorites": 100, + "tag": "乐评盘点,全能打卡挑战,翻唱,许嵩,杨千嬅,李荣浩,喊麦,民谣,热歌,神曲", + "review": 71, + "pubdate": 1593523679, + "senddate": 1593576757, + "duration": "3:37", + "badgepay": false, + "hit_columns": [ + "title", + "description" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 100097483 + }, + { + "type": "video", + "id": 625380628, + "author": "涩廊", + "mid": 178366933, + "typeid": "137", + "typename": "明星", + "arcurl": "http://www.bilibili.com/video/av625380628", + "aid": 625380628, + "bvid": "BV1Xt4y127bX", + "title": "这TM才叫日系美少年!", + "description": "道枝骏佑,02年霓虹国弟弟!杰尼斯美少年!没长残的童星代表!身高现在180+了!绰号米七(谐音)\n出演过电视剧《成为母亲》《我的裙子去哪了》\n\n米七是一个超级帅气可爱的男孩子!一直都在努力提升自己,请敬请期待他未来的作品!\n米七米七!未来可期!\n跪求三连三连三连三连三连三连三连三连三连三连三连三连三连三连三连三连三连三连三连三连三连三连三连三连三连", + "arcrank": "0", + "pic": "//i2.hdslb.com/bfs/archive/9d727949eed2d82eb0561d08cbb3e28ac6603532.jpg", + "play": 768179, + "video_review": 1595, + "favorites": 29494, + "tag": "全能打卡挑战,杰尼斯,美少年,道枝骏佑,日系,米七", + "review": 1545, + "pubdate": 1588381204, + "senddate": 1590253109, + "duration": "1:22", + "badgepay": false, + "hit_columns": [ + "title", + "description", + "tag" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 100094816 + } + ], + "show_column": 0 + } +} +``` + +
diff --git a/bb-api-collect/docs/search/search_response.md b/bb-api-collect/docs/search/search_response.md new file mode 100644 index 0000000000..fb977473cf --- /dev/null +++ b/bb-api-collect/docs/search/search_response.md @@ -0,0 +1,765 @@ +# 搜索响应条目 + +本页为搜索结果数组`result`中的对象的说明 + +## 对象类型1-结果为视频 + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ----- | -------------- | ----------------------------------------- | +| type | str | 结果类型 | 固定为video | +| id | num | 结果 | 为稿件avid | +| author | str | UP主昵称 | | +| mid | num | UP主mid | | +| typeid | str | 视频分区tid | | +| typename | str | 视频子分区名 | | +| arcurl | str | 视频重定向url | | +| aid | num | 稿件avid | | +| bvid | str | 稿件bvid | | +| title | str | 视频标题 | 关键字用xml标签``标注 | +| description | str | 视频简介 | | +| arcrank | str | 0 | **作用尚不明确** | +| pic | str | 视频封面url | | +| play | num | 视频播放量 | | +| video_review | num | 视频弹幕量 | | +| favorites | num | 视频收藏数 | | +| tag | str | 视频TAG | 每项TAG用`,`分隔 | +| review | num | 视频评论数 | | +| pubdate | num | 视频投稿时间 | 时间戳 | +| senddate | num | 视频发布时间 | 时间戳 | +| duration | str | 视频时长 | HH:MM | +| badgepay | bool | false | **作用尚不明确** | +| hit_columns | array | 关键字匹配类型 | | +| view_type | str | 空 | **作用尚不明确** | +| is_pay | num | 0 | **作用尚不明确** | +| is_union_video | num | 是否为合作视频 | 0:否
1:是 | +| rec_tags | null | - | **作用尚不明确** | +| new_rec_tags | array | 空 | **作用尚不明确** | +| rank_score | num | 结果排序量化值 | | + +`视频条目`中的`hit_columns`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ------------------------------------------------------------ | +| 0 | str | 匹配类型1 | title:标题匹配
description:简介匹配
author:UP主昵称匹配
tag:视频TAG匹配 | +| n | str | 匹配类型(n+1) | 项数为同时匹配到的类型数 | +| …… | str | …… | …… | + +**示例:** + +
+查看响应示例: + +```json +{ + "type": "video", + "id": 78977417, + "author": "MitchieM", + "mid": 5669526, + "typeid": "30", + "typename": "VOCALOID·UTAU", + "arcurl": "http://www.bilibili.com/video/av78977417", + "aid": 78977417, + "bvid": "BV1KJ411C7Un", + "title": "【Mitchie M】初音未来《买买买》【2020拜年祭单品】", + "description": "bilibili拜年祭のために、ダンスミュージックと中国の伝統楽器を組み合わせた曲を作りました。歌詞に「买买买」を使ったユニークな曲が出来上がったので、最高のクオリティーのMVと共に楽しんでもらえたら嬉しいです!\n为哔哩哔哩拜年祭制作了一首电子舞曲与中国传统乐器相结合的音乐,歌词是描写【买买买】的独特作品,和最棒的PV一起享受吧!\n\n▶︎ 舞蹈视频 [BV1pA411i7J6]", + "arcrank": "0", + "pic": "//i1.hdslb.com/bfs/archive/f0403bbd1ff3bad1df79aaa159d9e1cfb52c92de.jpg", + "play": 2915520, + "video_review": 14572, + "favorites": 114102, + "tag": "2020拜年祭单品,买买买,初音未来", + "review": 6124, + "pubdate": 1579877678, + "senddate": 1593099008, + "duration": "4:2", + "badgepay": false, + "hit_columns": [ + "title", + "description", + "tag" + ], + "view_type": "", + "is_pay": 0, + "is_union_video": 0, + "rec_tags": null, + "new_rec_tags": [], + "rank_score": 109020056 +} +``` + +
+ +## 对象类型2-结果为番剧&影视 + +| 字段 | 类型 | 内容 | 备注 | +| ---------------- | ------------------------------- | ---------------------------- | ------------------------------------------------------------ | +| type | str | 结果类型 | media_bangumi:番剧
media_ft:影视 | +| media_id | num | 剧集mdid | | +| season_id | num | 剧集ssid | | +| title | str | 剧集标题 | 关键字用xml标签``标注 | +| org_title | str | 剧集原名 | 关键字用xml标签``标注
可为空 | +| cover | str | 剧集封面url | | +| media_type | num | 剧集类型 | 1:番剧
2:电影
3:纪录片
4:国创
5:电视剧
7:综艺 | +| areas | str | 地区 | | +| styles | str | 风格 | | +| cv | str | 声优 | | +| staff | str | 制作组 | | +| play_state | num | 0 | **作用尚不明确** | +| goto_url | str | 剧集重定向url | | +| desc | str | 简介 | | +| corner | num | 角标有无 | 2:无
13:有 | +| pubtime | num | 开播时间 | 时间戳 | +| media_mode | num | 2 | **作用尚不明确** | +| is_avid | bool | false | **作用尚不明确** | +| fix_pubtime_str | str | 开播时间重写信息 | 优先级高于`pubtime`
可为空 | +| media_score | 有效时:obj
无效时:null | 评分信息 | | +| hit_columns | 有效时:array
无效时:null | 关键字匹配类型 | | +| all_net_name | str | 空 | **作用尚不明确** | +| all_net_icon | str | 空 | **作用尚不明确** | +| all_net_url | str | 空 | **作用尚不明确** | +| angle_title | str | 角标内容 | | +| angle_color | num | 角标颜色 | 0:红色
2:橙色 | +| display_info | array | 剧集标志信息 | | +| hit_epids | str | 关键字匹配分集标题的分集epid | 多个用`,`分隔 | +| pgc_season_id | num | 剧集ssid | | +| season_type | num | 剧集类型 | 1:番剧
2:电影
3:纪录片
4:国创
5:电视剧
7:综艺 | +| season_type_name | str | 剧集类型文字 | | +| selection_style | str | 分集选择按钮风格 | horizontal:横排式
grid:按钮式 | +| ep_size | num | 结果匹配的分集数 | | +| url | str | 剧集重定向url | | +| button_text | str | 观看按钮文字 | | +| is_follow | num | 是否追番 | 需要登录(SESSDATA)
未登录则恒为0
0:否
1:是 | +| is_selection | num | 1 | **作用尚不明确** | +| eps | array | 结果匹配的分集信息 | | +| badges | array | 剧集标志信息 | | + +`番剧条目`中的`media_score`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------ | ---- | +| user_count | num | 总计评分人数 | | +| score | num | 评分 | | + +`番剧条目`中的`hit_columns`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | -------------------------------------- | +| 0 | str | 匹配类型1 | title:标题匹配
org_title:原标题 | +| n | str | 匹配类型(n+1) | 项数为同时匹配到的类型数 | +| …… | str | …… | …… | + +`番剧条目`中的`display_info`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------ | ---- | +| 0 | obj | 剧集标志信息 | | + +`display_info`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------ | ---- | ------------ | ------ | +| bg_color_night | str | 夜间背景颜色 | 颜色码 | +| text | str | 剧集标志 | 颜色码 | +| border_color | str | 背景颜色 | 颜色码 | +| bg_style | num | 1 | | +| text_color | str | 文字颜色 | 颜色码 | +| bg_color | str | 背景颜色 | 颜色码 | +| text_color_night | str | 夜间文字颜色 | 颜色码 | +| border_color_night | str | 夜间背景颜色 | 颜色码 | + +`番剧条目`中的`eps`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ------------------------ | +| 0 | obj | 分集信息1 | | +| n | obj | 分集信息(n+1) | 项数为同时匹配到的分集数 | +| …… | obj | …… | …… | + +`eps`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ----- | ------------- | ---- | +| id | num | 分集epid | | +| cover | str | 分集封面url | | +| title | str | 完整标题 | | +| url | str | 分集重定向url | | +| release_date | str | 空 | | +| badges | array | 分集标志 | | +| index_title | str | 短标题 | | +| long_title | str | 单集标题 | | + +`番剧条目`中的`badges`数组(同`eps`数组中的对象中的`badges`数组): + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------ | ---- | +| 0 | obj | 剧集标志信息 | | + +`badges`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------ | ---- | ------------ | ------ | +| text | str | 剧集标志 | 颜色码 | +| text_color | str | 文字颜色 | 颜色码 | +| text_color_night | str | 夜间文字颜色 | 颜色码 | +| bg_color | str | 背景颜色 | 颜色码 | +| bg_color_night | str | 夜间背景颜色 | 颜色码 | +| border_color | str | 空 | | +| border_color_night | str | 空 | | +| bg_style | num | 1 | | + +**示例:** + +
+查看响应示例: + +```json +{ + "media_id": 28224080, + "season_id": 29310, + "type": "media_bangumi", + "title": "异度侵入 ID:INVADED", + "org_title": "イド:インヴェイデッド", + "cover": "//i0.hdslb.com/bfs/bangumi/image/9bf9e66968f85b33ec3769a16c86b36dc984abbc.png", + "media_type": 1, + "areas": "日本", + "styles": "原创/科幻/推理", + "cv": "酒井户:津田健次郎\n百贵:细谷佳正\n富久田:竹内良太\n本堂町:M・A・O\n东乡:布里德卡特·塞拉·惠美\n早濑浦:村治学\n白岳:近藤隆\n羽二重:岩濑周平\n若鹿:榎木淳弥\n国府:加藤涉\n西村:落合福嗣\n松冈:西凛太朗 ", + "staff": "监督:青木英\n脚本:舞城王太郎\n角色原案:小玉有起\n角色设计:碇谷敦\n美术:曽野由大\n作画监督:又贺大介\n副监督:久保田雄大\n色彩设计:千叶絵美\n动画制作:NAZ", + "play_state": 0, + "goto_url": "https://www.bilibili.com/bangumi/play/ss29310/", + "desc": "本片讲述利用能检测出人们杀意的装置以及利用思想粒子做出的“井”,来探知事件真相的科幻故事。", + "corner": 13, + "pubtime": 1578240000, + "media_mode": 2, + "is_avid": false, + "fix_pubtime_str": "", + "media_score": { + "user_count": 275391, + "score": 9.8 + }, + "hit_columns": [ + "title" + ], + "all_net_name": "", + "all_net_icon": "", + "all_net_url": "", + "angle_title": "会员专享", + "angle_color": 0, + "display_info": [ + { + "bg_color_night": "#BB5B76", + "text": "会员专享", + "border_color": "#FB7299", + "bg_style": 1, + "text_color": "#FFFFFF", + "bg_color": "#FB7299", + "text_color_night": "#E5E5E5", + "border_color_night": "#BB5B76" + } + ], + "hit_epids": "", + "pgc_season_id": 29310, + "season_type": 1, + "season_type_name": "番剧", + "selection_style": "grid", + "ep_size": 13, + "url": "https://www.bilibili.com/bangumi/play/ss29310", + "button_text": "立即观看", + "is_follow": 1, + "is_selection": 1, + "eps": [ + { + "id": 307446, + "cover": "http://i0.hdslb.com/bfs/archive/4a1895e5b675209b6948dc321c3cc4991a6262bc.jpg", + "title": "1", + "url": "https://www.bilibili.com/bangumi/play/ep307446", + "release_date": "", + "badges": [], + "index_title": "1", + "long_title": "JIGSAWED 碎片世界" + }, + { + "id": 307447, + "cover": "http://i0.hdslb.com/bfs/archive/c66175203fdb6f54a9fb3accd793da0341b3140a.jpg", + "title": "2", + "url": "https://www.bilibili.com/bangumi/play/ep307447", + "release_date": "", + "badges": [ + { + "text": "会员", + "text_color": "#FFFFFF", + "text_color_night": "#E5E5E5", + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "border_color": "", + "border_color_night": "", + "bg_style": 1 + } + ], + "index_title": "2", + "long_title": "JIGSAWED Ⅱ 碎片世界" + }, + ………… + ], + "badges": [ + { + "text": "会员专享", + "text_color": "#FFFFFF", + "text_color_night": "#E5E5E5", + "bg_color": "#FB7299", + "bg_color_night": "#BB5B76", + "border_color": "", + "border_color_night": "", + "bg_style": 1 + } + ] +}, +``` + +
+ +## 对象类型3-结果为直播间 + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----- | -------------- | ----------------------------------------- | +| type | str | 结果类型 | 固定为live_room | +| rank_offset | num | 搜索结果排名值 | | +| uid | num | 主播mid | | +| tas | str | 直播间TAG | 多个用`,`分隔 | +| hit_columns | array | 关键字匹配类型 | | +| live_time | str | 开播时间 | YYYY-MM-DD HH:MM:SS | +| cate_name | str | 子分区名 | | +| live_status | num | 1 | | +| uname | str | 主播昵称 | | +| uface | str | 主播头像url | | +| user_cover | str | 直播间封面url | | +| short_id | num | 0 | **作用尚不明确** | +| area | num | 1 | **作用尚不明确** | +| title | str | 直播间标题 | 关键字用xml标签``标注 | +| cover | str | 关键帧截图url | | +| online | num | 在线人数 | | +| rank_index | num | 0 | **作用尚不明确** | +| rank_score | num | 结果排序量化值 | | +| roomid | num | 直播间id | | +| attentions | num | 主播粉丝数 | | + +`直播间条目`中的`hit_columns`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ------------------------------------------------------------ | +| 0 | str | 匹配类型1 | title:直播间标题匹配
cate_name:子分区名匹配
uname:主播昵称匹配 | +| n | str | 匹配类型(n+1) | 项数为同时匹配到的类型数 | +| …… | str | …… | …… | + +**示例:** + +
+查看响应示例: + +```json +{ + "rank_offset": 1, + "uid": 682508, + "tags": "minecraft,声控,我的世界,虚拟主播,助眠", + "hit_columns": [ + "title", + "cate_name" + ], + "live_time": "2020-07-03 19:08:46", + "cate_name": "我的世界", + "live_status": 1, + "uname": "超心塞的十六", + "uface": "//i0.hdslb.com/bfs/face/dc33ad47b5e299c08bea9cfe565373213012599c.jpg", + "user_cover": "//i0.hdslb.com/bfs/live/new_room_cover/cbc7b1d0ba181df2c714c2e45ab00937129d3c5c.jpg", + "short_id": 148, + "area": 1, + "type": "live_room", + "title": "MC 1.16 极限服", + "cover": "//i0.hdslb.com/bfs/live/keyframe07031915000000010313u3z18a.jpg", + "online": 34702, + "rank_index": 0, + "rank_score": 34702, + "roomid": 10313, + "attentions": 317864 +} +``` + +
+ +## 对象类型4-结果为主播 + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----- | -------------- | ------------------------------------------------------ | +| type | str | 结果类型 | 固定为live_user | +| rank_offset | num | 搜索结果排名值 | | +| uid | num | 主播mid | | +| tas | str | 直播间TAG | 多个用`,`分隔 | +| live_time | str | 开播时间 | YYYY-MM-DD HH:MM:SS
如未开播为0000-00-00 00:00:00 | +| hit_columns | array | 关键字匹配类型 | | +| live_status | num | 是否开播 | 0:未开播
1:已开播 | +| area | num | 1 | **作用尚不明确** | +| is_live | bool | 是否开播 | false:未开播
true:已开播 | +| uname | str | 主播昵称 | 关键字用xml标签``标注 | +| uface | str | 主播头像url | | +| rank_index | num | 0 | **作用尚不明确** | +| rank_score | num | 结果排序量化值 | | +| attentions | num | 主播粉丝数 | | + +`主播条目`中的`hit_columns`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ------------------------ | +| 0 | str | 匹配类型1 | uname:主播昵称匹配 | +| n | str | 匹配类型(n+1) | 项数为同时匹配到的类型数 | +| …… | str | …… | …… | + +**示例:** + +
+查看响应示例: + +```json +{ + "rank_offset": 1, + "uid": 322892, + "tags": "鬼畜,游戏,瞎扯淡,轰炸挂", + "type": "live_user", + "live_time": "2020-07-03 17:57:30", + "hit_columns": [ + "uname" + ], + "live_status": 1, + "area": 1, + "is_live": true, + "uname": "痒局长", + "uface": "//i2.hdslb.com/bfs/face/bcdf640faa16ebaacea1d4c930baabaec9087a80.jpg", + "rank_index": 0, + "rank_score": 2620790, + "roomid": 5441, + "attentions": 2570790 +} +``` + +
+ +## 对象类型5-结果为专栏 + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ----- | -------------- | ---------------- | +| type | str | 结果类型 | 固定为article | +| rank_offset | num | 搜索结果排名值 | | +| pub_time | num | 投稿时间 | 时间戳 | +| like | num | 获赞数 | | +| title | str | 标题 | | +| mid | num | UP主mid | | +| image_urls | array | 封面图组 | | +| template_id | num | ??? | **作用尚不明确** | +| category_id | num | 专栏分区 | | +| view | num | 阅读数 | | +| reply | num | 评论数 | | +| rank_index | num | 0 | **作用尚不明确** | +| desc | str | 文章预览 | | +| rank_score | num | 结果排序量化值 | | +| id | num | 专栏cvid | | +| category_name | str | 子分区名 | | + +`专栏条目`中的`covers`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | str | 封面图片1 | | +| n | str | 封面图片(n+1) | | +| …… | str | …… | | + +**示例:** + +
+查看响应示例: + +```json +{ + "pub_time": 1582123245, + "like": 113, + "title": "【洛水闲谈】《普通DISCO》神话达成后的个人感想", + "rank_offset": 1, + "mid": 295535204, + "image_urls": [ + "//i0.hdslb.com/bfs/article/0c2e7e3cc14f7e097482688600be713a9e9a7029.png" + ], + "template_id": 4, + "category_id": 4, + "view": 843, + "reply": 58, + "rank_index": 0, + "desc": "今天,2020年2月19日,随着bilibili弹幕网上《普通DISCO》的播放量突破1000W,中文VOCALOID的第一首神话级歌曲诞生了。笔者昨夜盯着《普通DISCO》的播放量的增长速率熬到很晚,今早又起了个大早盯着那最后一万的播放量差距,直到播放量突破1000W才放松紧绷的神经,敲打键盘时肢体困倦神疲乏力,故长话短说,若有表达不妥之处还望各位海涵。ilem教主,其拥有近二十首百万传说曲,占bilibili弹幕网中文VOCALOID百万传说曲的三分之一,中文VOCALOID第一首传说曲与第", + "rank_score": 19, + "type": "article", + "id": 4743576, + "category_name": "动漫杂谈" +} +``` + +
+ +## 对象类型6-结果为话题 + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----- | ----------------- | ---------------- | +| type | str | 结果类型 | 固定为topic | +| description | str | 简介 | | +| pubdate | nm | 发布时间 | 时间戳 | +| title | str | 标题 | | +| favourite | num | 0 | **作用尚不明确** | +| hit_columns | array | 关键字匹配类型 | | +| review | num | 0 | **作用尚不明确** | +| rank_offset | num | 搜索结果排名值 | | +| cover | str | 话题封面url | | +| update | num | 上传时间 | 时间戳 | +| mid | nm | 0 | **作用尚不明确** | +| click | num | ??? | **作用尚不明确** | +| tp_type | num | ??? | **作用尚不明确** | +| keyword | str | 空 | **作用尚不明确** | +| tp_id | num | 话题tp | | +| rank_index | num | 0 | **作用尚不明确** | +| author | str | UP主昵称 | | +| arcurl | str | 话题页面重定向url | | +| rank_score | num | 结果排序量化值 | | + +`话题条目`中的`hit_columns`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ------------------------ | +| 0 | str | 匹配类型1 | title:话题标题匹配 | +| n | str | 匹配类型(n+1) | 项数为同时匹配到的类型数 | +| …… | str | …… | …… | + +**示例:** + +
+查看响应示例: + +```json +{ + "description": "「Bad Apple」的各式各样的PV有很多很多,小编在这里给大家推荐一些比较特别且高人气的特别PV......", + "pubdate": 1479380676, + "title": "「Bad Apple」 的N种特别PV", + "favourite": 0, + "hit_columns": [ + "title" + ], + "review": 0, + "rank_offset": 1, + "cover": "//i0.hdslb.com/bfs/active/3005a94d446db3873d97b483323156b491d850ac.jpg", + "update": 31507200, + "mid": 0, + "click": 211843, + "tp_type": 0, + "keyword": "", + "tp_id": 2215, + "rank_index": 0, + "author": "Nuuu", + "type": "topic", + "arcurl": "http://www.bilibili.com/topic/50.html", + "rank_score": 1851888 +} +``` + +
+ +## 对象类型7-结果为用户 + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ----- | -------------- | ----------------------------- | +| type | str | 结果类型 | 固定为bili_user | +| mid | num | 用户mid | | +| uname | str | 用户昵称 | | +| usign | str | 用户签名 | | +| fans | num | 用户粉丝数 | | +| videos | num | 用户稿件数 | | +| upic | str | 用户头像url | | +| verify_info | str | 空 | **作用尚不明确** | +| level | num | 用户等级 | | +| gender | num | 用户性别 | 1:男
2:女
3:私密 | +| is_upuser | num | 是否为UP主 | 0:否
1:是 | +| is_live | num | 是否正在直播 | 0:否
1:是 | +| room_id | num | 用户直播间id | | +| res | array | 用户投稿内容 | | +| official_verify | obj | 用户认证信息 | | +| hit_columns | array | 关键字匹配类型 | | + +`用户条目`中的`res`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------------- | ------------------------- | +| 0 | obj | 用户投稿视频1 | | +| n | obj | 用户投稿视频(n+1) | 项数为用户投稿的3个视频数 | +| …… | obj | …… | …… | + +`res`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | ----------------- | ---------------- | +| aid | num | 稿件avid | | +| bvid | str | 稿件bvid | | +| title | str | 视频标题 | | +| pubdate | num | 视频投稿时间 | 时间戳 | +| arcurl | str | 视频页面重定向url | | +| pic | str | 视频封面图片url | | +| play | str | 播放量 | | +| dm | str | 弹幕量 | | +| coin | num | 投币数 | | +| fav | num | 收藏数 | | +| desc | str | 视频简介 | | +| duration | str | 视频时长 | MM:SS | +| is_pay | num | 0 | **作用尚不明确** | +| is_union_video | num | 是否为合作视频 | 0:否
1:是 | + +`用户条目`中的`official_verify`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ----------------------------------------- | +| type | num | 是否认证 | 127:无
0:个人认证
1:组织认证 | +| desc | str | 认证名称 | | + +`用户条目`中的`hit_columns`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ------------------------ | +| 0 | str | 匹配类型1 | uname:用户昵称匹配 | +| n | str | 匹配类型(n+1) | 项数为同时匹配到的类型数 | +| …… | str | …… | …… | + +**示例:** + +
+查看响应示例: + +```json +{ + "type": "bili_user", + "mid": 208259, + "uname": "陈睿", + "usign": "喜欢的话就坚持吧", + "fans": 1561640, + "videos": 5, + "upic": "//i1.hdslb.com/bfs/app/8920e6741fc2808cce5b81bc27abdbda291655d3.png", + "verify_info": "", + "level": 6, + "gender": 1, + "is_upuser": 1, + "is_live": 0, + "room_id": 3394945, + "res": [ + { + "aid": 883660923, + "bvid": "BV1SK4y1477d", + "title": "BILIBILI 11周年演讲", + "pubdate": 1593176427, + "arcurl": "http://www.bilibili.com/video/av883660923", + "pic": "//i0.hdslb.com/bfs/archive/b28021df9c67ee2821cb9c1142b9d5e594e3b951.jpg", + "play": "6144081", + "dm": 185789, + "coin": 167803, + "fav": 147421, + "desc": "BILIBILI 11周年演讲,邀请数位嘉宾分享他们与B站的故事。\n陈睿《bilibili 11周年主题演讲》\n机智的党妹 《在B站,表达自我》\n腾格尔《在B站,做全新的腾格尔》\n周深《在B站,做一个歌手》《起风了》\n罗翔《在B站,授业与解惑》\nCarly李旎《在B站,一起成长》\nBILIBILI 11周年特映片《喜相逢》", + "duration": "217:7", + "is_pay": 0, + "is_union_video": 1 + }, + { + "aid": 838688095, + "bvid": "BV1Wg4y1v77h", + "title": "我们的五年——B站五年员工纪念视频 2020版", + "pubdate": 1593004830, + "arcurl": "http://www.bilibili.com/video/av838688095", + "pic": "//i1.hdslb.com/bfs/archive/701da662dfe00fb180eb4a47f1c38403838570a7.jpg", + "play": "957960", + "dm": 10830, + "coin": 44030, + "fav": 23108, + "desc": "每年626前夕,我们都会给本年度满五年工龄的员工颁发金LOGO(金质的小电视胸章),感谢他们对公司的陪伴和付出。“五年守护,感恩有你”", + "duration": "4:51", + "is_pay": 0, + "is_union_video": 0 + }, + { + "aid": 327892668, + "bvid": "BV1fA411b7zo", + "title": "【推荐一本喜欢的书】上帝掷骰子吗?", + "pubdate": 1587632267, + "arcurl": "http://www.bilibili.com/video/av327892668", + "pic": "//i0.hdslb.com/bfs/archive/c3ec25e2e4425303d7f4915692e3a9f0ec027669.jpg", + "play": "2131624", + "dm": 13570, + "coin": 37432, + "fav": 35498, + "desc": "#推荐一本喜欢的书# 423世界读书日,推荐我看过的最好看的量子物理科普书籍《上帝掷骰子吗》#读书等身#\n欢迎参与B站读书日活动:https://www.bilibili.com/blackboard/activity-gNeFPygv0.html 你每投一个读书视频,B站都会为你捐出一本书。", + "duration": "4:46", + "is_pay": 0, + "is_union_video": 0 + } + ], + "official_verify": { + "type": 0, + "desc": "bilibili董事长兼CEO" + }, + "hit_columns": [ + "uname" + ] +} +``` + +
+ +## 对象类型8-结果为相簿 + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----- | -------------- | ---------------- | +| type | str | 结果类型 | 固定为photo | +| count | num | 图片数 | | +| like | num | 收藏数 | | +| title | str | 相簿标题 | | +| hit_columns | array | 关键字匹配类型 | | +| rank_offset | num | 搜索结果排名值 | | +| cover | str | 相簿封面url | | +| mid | num | UP主mid | | +| uname | str | UP主昵称 | | +| rank_index | num | 0 | **作用尚不明确** | +| view | num | 观看次数 | | +| id | num | 相簿id | | +| rank_score | num | 结果排序量化值 | | + +`相簿条目`中的`hit_columns`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ------------------------------------------------------------ | +| 0 | str | 匹配类型1 | title:相簿标贴匹配
description:相簿简介匹配
source_tag:相簿TAG匹配 | +| n | str | 匹配类型(n+1) | 项数为同时匹配到的类型数 | +| …… | str | …… | …… | + +**示例:** + +
+查看响应示例: + +```json +{ + "count": 4, + "like": 42, + "title": "EVA Q 绫波丽", + "hit_columns": [ + "title" + ], + "rank_offset": 1, + "cover": "http://i0.hdslb.com/bfs/album/1043ee70b677c9aab406142c6aa00d097be07c1e.jpg", + "mid": 3306217, + "uname": "迷失人形LLS", + "rank_index": 0, + "view": 100924, + "type": "photo", + "id": 8952802, + "rank_score": 25315 +} +``` + +
\ No newline at end of file diff --git a/bb-api-collect/docs/search/suggest.md b/bb-api-collect/docs/search/suggest.md new file mode 100644 index 0000000000..276b0d0969 --- /dev/null +++ b/bb-api-collect/docs/search/suggest.md @@ -0,0 +1,175 @@ +# 搜索建议 + +## 获取搜索建议关键词(web端) + +> https://s.search.bilibili.com/main/suggest + +*请求方式:GET* + +搜索建议最多提供10个候选关键词 + +搜索建议内容可为任意语言(中 英 日等....),中文拼音支持全拼联想词 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------------- | ---- | ---------------------- | ------ | ------------------------ | +| term | str | 需要获得建议的输入内容 | 必要 | | +| main_ver | str | v1 | 非必要 | 默认为 `v1` | +| highlight | str | 任意, 无明显作用 | 非必要 | 默认为空 | +| func | str | 函数? | 非必要 | 默认为 `suggest` | +| suggest_type | str | 建议类型? | 非必要 | 默认为 `accurate` | +| sub_type | str | 子类型? | 非必要 | 默认为 `tag` | +| userid | num | 本用户 mid | 非必要 | 可能用于个性化推荐 | +| bangumi_acc_num | num | 番剧累积数? | 非必要 | 默认为 `1` | +| special_acc_num | num | 特殊累积数? | 非必要 | 默认为 `1` | +| topic_acc_num | num | 话题累积数? | 非必要 | 默认为 `1` | +| upuser_acc_num | num | UP主累积数? | 非必要 | 默认为 `1` | +| tag_num | num | Tag 数? | 非必要 | 默认为 `10` | +| special_num | num | 特殊推荐数? | 非必要 | 默认为 `10` | +| bangumi_num | num | 番剧推荐数? | 非必要 | 默认为 `10` | +| upuser_num | num | UP主推荐数? | 非必要 | 默认为 `3` | +| rnd | num | 一个随机浮点数 | 非必要 | 由 `Math.random()` 生成? | +| buvid | str | 同 Cookie 中 buvid3 | 非必要 | | +| spmid | str | 333.1007 | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ------------ | ------------ | +| exp_str | str | 实验字符串? | 作用尚不明确 | +| code | num | 返回值 | 0:成功 | +| result | obj | 搜索建议结果 | | +| stoken | str | ??? | 作用尚不明确 | + +`result`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ----- | -------- | ---- | +| tag | array | 套了个娃 | | + +`result`中的`tag`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------------- | ---------------------- | +| 0 | obj | 第1建议关键词 | | +| n | obj | 第(n+1)建议关键词 | 按照相关程度与热度顺序 | +| 9 | obj | 第10建议关键词 | 最后一项 | + +`tag`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ---------- | -------------------------------------------------- | +| value | str | 关键词内容 | | +| ref | num | 0 | 作用尚不明确 | +| name | str | 显示内容 | 带有 `` 的 XML 标签 | +| spid | num | 5 | 作用尚不明确 | +| type | str | 空 | | + +**示例:** + +获取关于 `洛天依` 的搜索建议 + +```shell +curl -G 'https://s.search.bilibili.com/main/suggest' \ +--data-urlencode 'term=洛天依' +``` + +
+查看响应示例: + +```json +{ + "exp_str": "106301_106700", + "code": 0, + "result": { + "tag": [ + { + "value": "洛天依", + "term": "洛天依", + "ref": 0, + "name": "洛天依", + "spid": 5, + "type": "" + }, + { + "value": "洛天依十二周年", + "term": "洛天依十二周年", + "ref": 0, + "name": "洛天依十二周年", + "spid": 5, + "type": "" + }, + { + "value": "洛天依演唱会", + "term": "洛天依演唱会", + "ref": 0, + "name": "洛天依演唱会", + "spid": 5, + "type": "" + }, + { + "value": "洛天依手办", + "term": "洛天依手办", + "ref": 0, + "name": "洛天依手办", + "spid": 5, + "type": "" + }, + { + "value": "洛天依歌曲", + "term": "洛天依歌曲", + "ref": 0, + "name": "洛天依歌曲", + "spid": 5, + "type": "" + }, + { + "value": "洛天依童话镇", + "term": "洛天依童话镇", + "ref": 0, + "name": "洛天依童话镇", + "spid": 5, + "type": "" + }, + { + "value": "洛天依东京不太热", + "term": "洛天依东京不太热", + "ref": 0, + "name": "洛天依东京不太热", + "spid": 5, + "type": "" + }, + { + "value": "洛天依霜雪千年", + "term": "洛天依霜雪千年", + "ref": 0, + "name": "洛天依霜雪千年", + "spid": 5, + "type": "" + }, + { + "value": "洛天依生日会", + "term": "洛天依生日会", + "ref": 0, + "name": "洛天依生日会", + "spid": 5, + "type": "" + }, + { + "value": "洛天依生日", + "term": "洛天依生日", + "ref": 0, + "name": "洛天依生日", + "spid": 5, + "type": "" + } + ] + }, + "stoken": "4020133863501304726" +} +``` + +
diff --git a/bb-api-collect/docs/teenager/teenager_mode.md b/bb-api-collect/docs/teenager/teenager_mode.md new file mode 100644 index 0000000000..e7f5a1b3e6 --- /dev/null +++ b/bb-api-collect/docs/teenager/teenager_mode.md @@ -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:成功
-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' \ +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` +pwd有数值时 +```json +{ + "code": -400, + "message": "关闭时密码必须为空", + "ttl": 1 +} +``` + +
diff --git a/bb-api-collect/docs/user/batch.md b/bb-api-collect/docs/user/batch.md new file mode 100644 index 0000000000..98953e9feb --- /dev/null +++ b/bb-api-collect/docs/user/batch.md @@ -0,0 +1,85 @@ +# 批量查询 + +## 用户名查 mid + +### 动态 + +> https://api.bilibili.com/x/polymer/web-dynamic/v1/name-to-uid + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + + + +**URL 参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ------ | ------ | ------ | ---- | +| names | string | 用户名 | 必要 | 多个用户名以 `,` 分隔 | + +**JSON 回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| code | number | 返回值 | 0: 成功
-101: 账号未登录
-400: 请求错误 | +| data | object | 数据本体 | | +| message | string | 错误信息 | 成功时为 `0` | +| ttl | number | `1` | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| uid_list | object[] | UID 列表 | 套了个娃 | + +`data.uid_list[]` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| name | string | 用户名 | | +| uid | string | mid (UID) | | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/polymer/web-dynamic/v1/name-to-uid' \ +--url-query 'names=社会易姐qwq,session小胡,陈睿,洛天依' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "data": { + "uid_list": [ + { + "name": "社会易姐QwQ", + "uid": "293793435" + }, + { + "name": "陈睿", + "uid": "208259" + }, + { + "name": "Session小胡", + "uid": "645769214" + }, + { + "name": "洛天依", + "uid": "36081646" + } + ] + }, + "message": "0", + "ttl": 1 +} +``` +
+ + diff --git a/bb-api-collect/docs/user/check_nickname.md b/bb-api-collect/docs/user/check_nickname.md new file mode 100644 index 0000000000..b006dbca17 --- /dev/null +++ b/bb-api-collect/docs/user/check_nickname.md @@ -0,0 +1,145 @@ +# 检查昵称是否可注册 + +## ~~检查昵称(已失效)~~ + +
+查看折叠内容 + +> https://passport.bilibili.com/web/generic/check/nickname + +*请求方式:GET* + +也可用于判断指定昵称的用户是否存在 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ----------- | ------ | ---- | +| nickName | str | 目标昵称 | 必要 | 最长为16字符 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 状态码 | -400:请求错误
-500:服务器端异常
**详细说明见下一表格** | +| message | str | 错误详情 | 若昵称可用,则不返回message | + +`code`状态码: + +| 值 | 含义 | +| ----- | --------------------------------- | +| 0 | 昵称未被注册 | +| 2001 | 该昵称已被他人使用 | +| 40002 | 昵称包含敏感信息 | +| 40004 | 昵称不可包含除\-和_以外的特殊字符 | +| 40005 | 昵称过长(超过16字符) | +| 40006 | 昵称过短(少于2字符) | +| 40014 | 昵称已存在 | + +**示例:** + +查询昵称 `xijinping` 是否被使用: + +```shell +curl -G 'https://passport.bilibili.com/web/generic/check/nickname' \ +--data-urlencode 'nickName=xijinping' +``` + +
+查看响应示例: + +```json +{ + "code":40002, + "message":"昵称包含敏感信息" +} +``` + +
+ +查询昵称 `//` 是否被使用: + +```shell +curl -G 'https://passport.bilibili.com/web/generic/check/nickname' \ +--data-urlencode 'nickName=//' +``` + +
+查看响应示例: + +```json +{ + "code": 40004, + "message": "昵称不可包含除-和_以外的特殊字符" +} +``` + +
+ +查询昵称 `test0000000000000 ` 是否被使用: + +```shell +curl -G 'https://passport.bilibili.com/web/generic/check/nickname' \ +--data-urlencode 'nickName=test0000000000000 ' +``` + +
+查看响应示例: + +```json +{ + "code": 40005, + "message": "昵称过长" +} +``` + +
+ +查询昵称 `0` 是否被使用: + +```shell +curl -G 'https://passport.bilibili.com/web/generic/check/nickname' \ +--data-urlencode 'nickName=0' +``` + +
+查看响应示例: + +```json +{ + "code": 40006, + "message": "昵称过短" +} +``` + +
+ +查询昵称 `test` 是否被使用: + +```shell +curl -G 'https://passport.bilibili.com/web/generic/check/nickname' \ +--data-urlencode 'nickName=test' +``` + +
+查看响应示例: + +```json +{ + "code":40014, + "message":"昵称已存在" +} +``` + +
+ +
+ +目前该接口无论参数,稳定返回: +```json +{ + "code": 0 +} +``` diff --git a/bb-api-collect/docs/user/contract.md b/bb-api-collect/docs/user/contract.md new file mode 100644 index 0000000000..ec4d110785 --- /dev/null +++ b/bb-api-collect/docs/user/contract.md @@ -0,0 +1,131 @@ +# 加入老粉计划 + +> https://api.bilibili.com/x/v1/contract/add_contract + +*请求方式:POST* + +是否需要登录:`是` + +认证方式:Cookie(SESSDATA) + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|----------|-----|--------|-----|-----| +| aid | str | `空串` | | | +| up_mid | str | UP主UID | 必要 | | +| source | str | `4` | | | +| scene | str | `105` | | | +| platform | str | `web` | | | +| mobi_app | str | `pc` | | | +| csrf | str | 用户csrf | 必要 | | + +**json回复:** + +根对象: + +| 字段名 | 类型 | 内容 | 备注 | +|---------|-----|------|-------------------------| +| code | num | 响应码 | 0:成功
158001:`不满足条件` | +| message | str | 0 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|---------------|------|-----------------------------------|-----| +| allow_message | bool | `true` | | +| input_text | str | `UP主加油!看好你噢~` | | +| input_title | str | `感谢你对UP主的特别支持,“老粉”可期!私信留言鼓励下TA吧~ ` | | + +**示例:** + +```shell +curl --location --request POST 'https://api.bilibili.com/x/v1/contract/add_contract' \ +--header 'Cookie: SESSDATA=xxx' \ +--header 'Content-Type: application/x-www-form-urlencoded' \ +--data-urlencode 'up_mid=2' \ +--data-urlencode 'csrf=xxx' +``` + +
+点击查看 + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "allow_message": true, + "input_text": "UP主加油!看好你噢~", + "input_title": "感谢你对UP主的特别支持,“老粉”可期!私信留言鼓励下TA吧~" + } +} +``` + +
+ +# 老粉计划发送留言 + +> https://api.bilibili.com/x/v1/contract/add_message + +*请求方式:POST* + +认证方式:Cookie (SESSDATA) + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|---------|-----|--------|-----|-----| +| aid | str | `空串` | | | +| up_mid | str | UP主UID | 必要 | | +| source | str | `4` | | | +| scene | str | `105` | | | +| content | str | 留言内容 | 必要 | | +| csrf | str | 用户csrf | 必要 | | + +**json回复:** + +根对象: + +| 字段名 | 类型 | 内容 | 备注 | +|---------|-----|------|------------------------------| +| code | num | 响应码 | 0:成功
158005:您跟up主还不是契约关系 | +| message | str | 0 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|---------------|-----|------------------|-----| +| success_toast | str | `提交成功,UP主已收到留言~` | | + +**示例:** + +```shell +curl --location --request POST 'https://api.bilibili.com/x/v1/contract/add_message' \ +--header 'Cookie: SESSDATA=xxx' \ +--header 'Content-Type: application/x-www-form-urlencoded' \ +--data-urlencode 'up_mid=2' \ +--data-urlencode 'content=..' \ +--data-urlencode 'csrf=xxx' +``` + +
+点击查看 + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "success_toast": "提交成功,UP主已收到留言~" + } +} +``` + +
diff --git a/bb-api-collect/docs/user/info.md b/bb-api-collect/docs/user/info.md new file mode 100644 index 0000000000..ead40b3530 --- /dev/null +++ b/bb-api-collect/docs/user/info.md @@ -0,0 +1,1777 @@ +# 用户基本信息 + + + +## 用户空间详细信息 + +> https://api.bilibili.com/x/space/wbi/acc/info + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +鉴权方式:[Wbi 签名](../misc/sign/wbi.md), Cookie (包含 SESSDATA 与空值的总项数大于等于 3) + +~~该接口的旧版 API :~~(已废弃,不建议使用) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ------------------------------------ | +| mid | num | 目标用户mid | 必要 | | +| w_rid | str | Wbi 签名 | 必要 | 详见 [Wbi 签名](../misc/sign/wbi.md) | +| wts | num | 当前时间戳 | 必要 | 详见 [Wbi 签名](../misc/sign/wbi.md) | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
-403:访问权限不足
-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 头像
1:是 NFT 头像 | +| face_nft_type | num | NFT 头像类型? | | +| sign | str | 签名 | | +| rank | num | 用户权限等级 | 目前应该无任何作用
5000:0级未答题
10000:普通会员
20000:字幕君
25000:VIP
30000:真·职人
32000:管理员 | +| level | num | 当前等级 | 0-6 级 | +| jointime | num | 注册时间 | 此接口返回恒为`0` | +| moral | num | 节操值 | 此接口返回恒为`0` | +| silence | num | 封禁状态 | 0:正常
1:被封 | +| coins | num | 硬币数 | 需要登录(Cookie)
只能查看自己的
默认为`0` | +| fans_badge | bool | 是否具有粉丝勋章 | false:无
true:有 | +| fans_medal | obj | 粉丝勋章信息 | | +| official | obj | 认证信息 | | +| vip | obj | 会员信息 | | +| pendant | obj | 头像框信息 | | +| nameplate | obj | 勋章信息 | | +| user_honour_info | obj | (?) | | +| is_followed | bool | 是否关注此用户 | true:已关注
false:未关注
需要登录(Cookie)
未登录恒为`false` | +| top_photo | str | 主页头图链接 | | +| theme | obj | (?) | | +| sys_notice | obj | 系统通知 | 无内容则为空对象
主要用于展示如用户争议、纪念账号等等的小黄条 | +| live_room | obj | 直播间信息 | | +| birthday | str | 生日 | MM-DD
如设置隐私为空 | +| school | obj | 学校 | | +| profession | obj | 专业资质信息 | | +| tags | 有效时:array
无效时:null | 个人标签 | | +| series | obj | (?) | | +| is_senior_member | num | 是否为硬核会员 | 0:否
1:是 | +| mcn_info | null | (?) | | +| gaia_res_type | num | (?) | | +| gaia_data | null | (?) | | +| is_risk | bool | (?) | | +| elec | obj | 充电信息 | | +| contract | obj | 是否显示老粉计划 | | +| certificate_show | bool | (?) | | +| name_render | 有效时:obj
无效时:null | 昵称渲染信息 | | + +`rank`示例 + +| UID | rank | +| --------- | ----- | +| 2 | 20000 | +| 16765 | 20000 | +| 15773384 | 20000 | +| 124416 | 20000 | +| 429736362 | 25000 | +| 424261768 | 25000 | +| 41273726 | 25000 | +| 15080107 | 25000 | +| 9847497 | 25000 | +| 4856007 | 25000 | +| 928123 | 25000 | +| 132704 | 25000 | +| 70093 | 25000 | +| 47291 | 25000 | +| 27380 | 25000 | +| 22445 | 25000 | +| 3351 | 25000 | +| 1101 | 25000 | +| 93066 | 30000 | +| 2443068 | 30000 | +| 46368 | 30000 | +| 11167 | 30000 | + +`profession`示例 + +| UID | +| ------- | +| 654391 | +| 1440295 | +| 1785155 | +| 2990100 | +| 3875803 | + +`data`中的`official`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | -------- | ---------------------------------------- | +| role | num | 认证类型 | 见 [用户认证类型一览](official_role.md) | +| title | str | 认证信息 | 无为空 | +| desc | str | 认证备注 | 无为空 | +| type | num | 是否认证 | -1:无
0:个人认证
1:机构认证 | + +`data`中的`vip`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------------- | ---- | ------------------ | -------------------------------------------------------------------- | +| type | num | 会员类型 | 0:无
1:月大会员
2:年度及以上大会员 | +| status | num | 会员状态 | 0:无
1:有 | +| due_date | num | 会员过期时间 | 毫秒时间戳 | +| vip_pay_type | num | 支付类型 | 0:未开启自动续费
1:已开启自动续费 | +| theme_type | num | 0 | 作用尚不明确 | +| label | obj | 会员标签 | | +| avatar_subscript | num | 是否显示会员图标 | 0:不显示
1:显示 | +| nickname_color | str | 会员昵称颜色 | 颜色码,一般为`#FB7299`,曾用于愚人节改变大会员配色 | +| role | num | 大角色类型 | 1:月度大会员
3:年度大会员
7:十年大会员
15:百年大会员 | +| avatar_subscript_url | str | 大会员角标地址 | | +| tv_vip_status | num | 电视大会员状态 | 0:未开通 | +| tv_vip_pay_type | num | 电视大会员支付类型 | | +| tv_due_date | num | 电视大会员过期时间 | 秒级时间戳 | +| avatar_icon | obj | 大会员角标信息 | | + +`vip`中的`label`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------------- | ---- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| path | str | 空 | 作用尚不明确 | +| text | str | 会员类型文案 | `大会员` `年度大会员` `十年大会员` `百年大会员` `最强绿鲤鱼` | +| label_theme | str | 会员标签 | vip:大会员
annual_vip:年度大会员
ten_annual_vip:十年大会员
hundred_annual_vip:百年大会员
fools_day_hundred_annual_vip:最强绿鲤鱼 | +| text_color | str | 会员标签 | | +| bg_style | num | 1 | | +| bg_color | str | 会员标签背景颜色 | 颜色码,一般为`#FB7299`,曾用于愚人节改变大会员配色 | +| border_color | str | 会员标签边框颜色 | 未使用 | +| use_img_label | bool | `true` | | +| img_label_uri_hans | str | `空串` | | +| img_label_uri_hant | str | `空串` | | +| img_label_uri_hans_static | str | 大会员牌子图片 | 简体版 | +| img_label_uri_hant_static | str | 大会员牌子图片 | 繁体版 | + +`vip`中的`avatar_icon`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ------ | ------------ | +| icon_type | num | (?) | 作用尚不明确 | +| icon_resource | obj | (?) | 作用尚不明确 | + +`data`中的`pendant`对象: + +**普通头像框的`image`与`image_enhance`内容相同** + +**动态头像框的`image`为png静态图片,`image_enhance`为webp动态图片,`image_enhance_frame`为png逐帧序列** + +| 字段 | 类型 | 内容 | 备注 | +| ------------------- | ---- | --------------------- | ----------------- | +| pid | num | 头像框id | | +| name | str | 头像框名称 | | +| image | str | 头像框图片url | | +| expire | num | 过期时间 | 此接口返回恒为`0` | +| image_enhance | str | 头像框图片url | | +| image_enhance_frame | str | 头像框图片逐帧序列url | | +| n_pid | num | 新版头像框id | | + +`data`中的`nameplate`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | -------------- | ---- | +| nid | num | 勋章id | | +| name | str | 勋章名称 | | +| image | str | 勋章图标 | | +| image_small | str | 勋章图标(小) | | +| level | str | 勋章等级 | | +| condition | str | 获取条件 | | + +`data`中的`fans_medal`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ------------------ | ---- | +| show | bool | | | +| wear | bool | 是否佩戴了粉丝勋章 | | +| medal | obj | 粉丝勋章信息 | | + +`fans_medal`中的`medal`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------ | ---- | ------------------- | -------------------------------- | +| uid | num | 此用户mid | | +| target_id | num | 粉丝勋章所属UP的mid | | +| medal_id | num | 粉丝勋章id | | +| level | num | 粉丝勋章等级 | | +| medal_name | str | 粉丝勋章名称 | | +| medal_color | num | 颜色 | | +| intimacy | num | 当前亲密度 | | +| next_intimacy | num | 下一等级所需亲密度 | | +| day_limit | num | 每日亲密度获取上限 | | +| today_feed | num | 今日已获得亲密度 | | +| medal_color_start | num | 粉丝勋章颜色 | 十进制数,可转为十六进制颜色代码 | +| medal_color_end | num | 粉丝勋章颜色 | 十进制数,可转为十六进制颜色代码 | +| medal_color_border | num | 粉丝勋章边框颜色 | 十进制数,可转为十六进制颜色代码 | +| is_lighted | num | | | +| light_status | num | | | +| wearing_status | num | 当前是否佩戴 | 0:未佩戴
1:已佩戴 | +| score | num | | | + +`data`中的`sys_notice`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | -------- | ---- | +| id | num | id | | +| content | str | 显示文案 | | +| url | str | 跳转地址 | | +| notice_type | num | 提示类型 | 1,2 | +| icon | str | 前缀图标 | | +| text_color | str | 文字颜色 | | +| bg_color | str | 背景颜色 | | + +`sys_notice`示例 + +| id | content | notice_type | 示例用户 | +| --- | ---------------------------------------------------------------------------------------------- | ----------- | --------------------------------------------------- | +| 5 | 该用户存在争议行为,已冻结其帐号功能的使用 | 1 | | +| 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 | | + +`data`中的`live_room`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | -------------- | ------------------------ | +| roomStatus | num | 直播间状态 | 0:无房间
1:有房间 | +| liveStatus | num | 直播状态 | 0:未开播
1:直播中 | +| url | str | 直播间网页 url | | +| title | str | 直播间标题 | | +| cover | str | 直播间封面 url | | +| watched_show | obj | | | +| roomid | num | 直播间 id | | +| roundStatus | num | 轮播状态 | 0:未轮播
1:轮播 | +| broadcast_type | num | 0 | | + +`live_room`中的`watched_show`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ------------------- | ---- | +| switch | bool | ? | | +| num | num | total watched users | | +| text_small | str | | | +| text_large | str | | | +| icon | str | watched icon url | | +| icon_location | str | ? | | +| icon_web | str | watched icon url | | + +`data`中的`school`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------ | ---------- | +| name | str | 就读大学名称 | 没有则为空 | + +`data`中的`profession`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | -------- | --------------------- | +| name | str | 资质名称 | | +| department | str | 职位 | | +| title | str | 所属机构 | | +| is_show | num | 是否显示 | 0:不显示
1:显示 | + +`data`中的`user_honour_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ----- | ---- | ---- | +| mid | num | 0 | | +| colour | str | null | | +| tags | array | null | | + +`data`中的`series`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------- | ---- | ---- | ---- | +| user_upgrade_status | num | (?) | | +| show_upgrade_window | bool | (?) | | + +`data`中的`elec`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | -------------- | ---- | +| show_info | obj | 显示的充电信息 | | + +`elec`中的`show_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ---------------- | ------------------------------------------------------------------------------------------------------------- | +| show | bool | 是否显示充电按钮 | | +| state | num | 充电功能开启状态 | -1:未开通充电功能
1:已开通自定义充电
2:已开通包月、自定义充电
3:已开通包月高档、自定义充电 | +| title | str | 充电按钮显示文字 | 空字符串或 `充电` 或 `充电中` | +| icon | str | 充电图标 | | +| jump_url | str | 跳转url | | + +`data`中的`contract`对象: + +| 字段名 | 类型 | 内容 | 备注 | +| ----------------- | ---- | ------------------ | ----------------------------------- | +| is_display | bool | | true/false
在页面中未使用此字段 | +| is_follow_display | bool | 是否在显示老粉计划 | true:显示
false:不显示 | + +**示例:** + +查询用户`mid=2`的详细信息,Wbi 签名的 `wts`、`w_rid`生成方式详见 [Wbi 签名](../misc/sign/wbi.md) 文档 + +```shell +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 ;a= ; b=' \ + -A 'Mozilla/9.0 (X11; qwq)' +``` + +
+查看响应示例: + +```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": 548076, + "medal_id": 32525, + "level": 28, + "medal_name": "桜樱怪", + "medal_color": 398668, + "intimacy": 25364, + "next_intimacy": 160000, + "day_limit": 250000, + "today_feed": 2382, + "medal_color_start": 398668, + "medal_color_end": 6850801, + "medal_color_border": 6809855, + "is_lighted": 1, + "guard_level": 3, + "light_status": 1, + "wearing_status": 1, + "score": 50185364 + } + }, + "official": { + "role": 2, + "title": "bilibili创始人(站长)", + "desc": "", + "type": 0 + }, + "vip": { + "type": 2, + "status": 1, + "due_date": 3979555200000, + "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": 1, + "tv_due_date": 2003500800, + "avatar_icon": { + "icon_type": 1, + "icon_resource": {} + } + }, + "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", + "n_pid": 32257 + }, + "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_latest_100honour": 0 + }, + "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": 3, + "text_small": "3", + "text_large": "3人看过", + "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 + }, + "certificate_show": false, + "name_render": null + } +} +``` + +
+ +## 用户名片信息 + +> https://api.bilibili.com/x/web-interface/card + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------------------- | ------ | ----------------------- | +| mid | num | 目标用户mid | 必要 | | +| photo | bool | 是否请求用户主页头图 | 非必要 | true:是
false:否 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | -------------- | ------------------------------------------------------------------------ | +| card | obj | 卡片信息 | | +| following | bool | 是否关注此用户 | true:已关注
false:未关注
需要登录(Cookie)
未登录为false | +| archive_count | num | 用户稿件数 | | +| article_count | num | 0 | **作用尚不明确** | +| follower | num | 粉丝数 | | +| like_num | num | 点赞数 | | + +`data`中的`card`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ----- | ------------ | ----------------------- | +| mid | str | 用户mid | | +| approve | bool | false | **作用尚不明确** | +| name | str | 用户昵称 | | +| sex | str | 用户性别 | 男 女 保密 | +| face | str | 用户头像链接 | | +| DisplayRank | str | 0 | **作用尚不明确** | +| regtime | num | 0 | **作用尚不明确** | +| spacesta | num | 用户状态 | 0:正常
-2:被封禁 | +| birthday | str | 空 | **作用尚不明确** | +| place | str | 空 | **作用尚不明确** | +| description | str | 空 | **作用尚不明确** | +| article | num | 0 | **作用尚不明确** | +| attentions | array | 空 | **作用尚不明确** | +| fans | num | 粉丝数 | | +| friend | num | 关注数 | | +| attention | num | 关注数 | | +| sign | str | 签名 | | +| level_info | obj | 等级 | | +| pendant | obj | 挂件 | | +| nameplate | obj | 勋章 | | +| Official | obj | 认证信息 | | +| official_verify | obj | 认证信息2 | | +| vip | obj | 大会员状态 | | +| space | obj | 主页头图 | | + +`card`中的`level_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | -------- | ---------------- | +| current_level | num | 当前等级 | 0-6级 | +| current_min | num | 0 | **作用尚不明确** | +| current_exp | num | 0 | **作用尚不明确** | +| next_exp | num | 0 | **作用尚不明确** | + +`card`中的`pendant`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ----------- | ---------------- | +| pid | num | 挂件id | | +| name | str | 挂件名称 | | +| image | str | 挂件图片url | | +| expire | num | 0 | **作用尚不明确** | + +`card`中的`nameplate`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ---------------- | -------------------- | +| nid | num | 勋章id | **详细说明有待补充** | +| name | str | 勋章名称 | | +| image | str | 挂件图片url 正常 | | +| image_small | str | 勋章图片url 小 | | +| level | str | 勋章等级 | | +| condition | str | 勋章条件 | | + +`card`中的`Official`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | -------- | ---------------------------------------- | +| role | num | 认证类型 | 见[用户认证类型一览](official_role.md) | +| title | str | 认证信息 | 无为空 | +| desc | str | 认证备注 | 无为空 | +| type | num | 是否认证 | -1:无
0:UP主认证
1:机构认证 | + +`card`中的`official_verify`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---------------------------------------- | +| type | num | 是否认证 | -1:无
0:UP主认证
1:机构认证 | +| desc | str | 认证信息 | 无为空 | + +`card`中的`vip`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ---------- | ------------------------------------------------- | +| vipType | num | 大会员类型 | 0:无
1:月度大会员
2:年度及以上大会员 | +| dueRemark | str | 空 | **作用尚不明确** | +| accessStatus | num | 0 | **作用尚不明确** | +| vipStatus | num | 大会员状态 | 0:无
1:有 | +| vipStatusWarn | str | 空 | **作用尚不明确** | +| theme_type | num | 0 | **作用尚不明确** | + +`card`中的`space`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ---------------- | ---- | +| s_img | str | 主页头图url 小图 | | +| l_img | str | 主页头图url 正常 | | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/card' \ +--data-urlencode 'mid=2' \ +--data-urlencode 'photo=true' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "card": { + "mid": "2", + "name": "碧诗", + "approve": false, + "sex": "男", + "rank": "20000", + "face": "http://i2.hdslb.com/bfs/face/ef0457addb24141e15dfac6fbf45293ccf1e32ab.jpg", + "DisplayRank": "0", + "regtime": 0, + "spacesta": 0, + "birthday": "", + "place": "", + "description": "", + "article": 0, + "attentions": [], + "fans": 969999, + "friend": 234, + "attention": 234, + "sign": "kami.im 直男过气网红 # av362830 “We Are Star Dust”", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "" + }, + "nameplate": { + "nid": 10, + "name": "见习偶像", + "image": "http://i2.hdslb.com/bfs/face/e93dd9edfa7b9e18bf46fd8d71862327a2350923.png", + "image_small": "http://i2.hdslb.com/bfs/face/275b468b043ec246737ab8580a2075bee0b1263b.png", + "level": "普通勋章", + "condition": "所有自制视频总播放数\u003e=10万" + }, + "Official": { + "role": 2, + "title": "bilibili创始人(站长)", + "desc": "", + "type": 0 + }, + "official_verify": { + "type": 0, + "desc": "bilibili创始人(站长)" + }, + "vip": { + "type": 2, + "status": 1, + "due_date": 3896524800000, + "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": "" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299", + "role": 7, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png", + "vipType": 2, + "vipStatus": 1 + } + }, + "space": { + "s_img": "http://i1.hdslb.com/bfs/space/768cc4fd97618cf589d23c2711a1d1a729f42235.png", + "l_img": "http://i1.hdslb.com/bfs/space/cb1c3ef50e22b6096fde67febe863494caefebad.png" + }, + "following": true, + "archive_count": 37, + "article_count": 0, + "follower": 969999, + "like_num": 3547978 + } +} +``` + +
+ +## 登录用户空间详细信息 + +> https://api.bilibili.com/x/space/myinfo + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------- | +| code | num | 返回值 | 0:成功
-101:未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | ------------ | ------------------------ | +| mid | num | mid | | +| name | str | 昵称 | | +| sex | str | 性别 | 男 女 保密 | +| face | str | 头像图片url | | +| sign | str | 签名 | | +| rank | num | 10000 | **作用尚不明确** | +| level | num | 当前等级 | 0-6级 | +| jointime | num | 0 | **作用尚不明确** | +| moral | num | 节操 | 默认70 | +| silence | num | 封禁状态 | 0:正常
1:被封 | +| email_status | num | 已验证邮箱 | 0:未验证
1:已验证 | +| tel_status | num | 已验证手机号 | 0:未验证
1:已验证 | +| identification | num | 1 | **作用尚不明确** | +| vip | obj | 大会员状态 | | +| birthday | num | 生日 | 时间戳 | +| is_tourist | num | 0 | **作用尚不明确** | +| is_fake_account | num | 0 | **作用尚不明确** | +| pin_prompting | num | 0 | **作用尚不明确** | +| is_deleted | num | 0 | **作用尚不明确** | +| coins | num | 硬币数 | | +| following | num | 粉丝数 | | +| follower | num | 粉丝数 | | + +`data`中的`vip`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------------- | ---- | ---------------- | ----------------------------------------------- | +| type | num | 会员类型 | 0:无
1:月大会员
2:年度及以上大会员 | +| status | num | 会员状态 | 0:无
1:有 | +| due_date | num | 会员过期时间 | Unix时间戳(毫秒) | +| theme_type | num | 0 | 作用尚不明确 | +| label | obj | 会员标签 | | +| avatar_subscript | num | 是否显示会员图标 | 0:不显示
1:显示 | +| nickname_color | str | 会员昵称颜色 | 颜色码 | + +`vip`中的`label`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | -------- | ----------------------------------------------------------------------------------------------------------- | +| path | str | 空 | 作用尚不明确 | +| text | str | 会员名称 | | +| label_theme | str | 会员标签 | vip:大会员
annual_vip:年度大会员
ten_annual_vip:十年大会员
hundred_annual_vip:百年大会员 | + +`data`中的`pendant`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ----------- | -------------------- | +| pid | num | 挂件id | **详细说明有待补充** | +| name | str | 挂件名称 | | +| image | str | 挂件图片url | | +| expire | num | 0 | **作用尚不明确** | + +`data`中的`nameplate`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ---------------- | -------------------- | +| nid | num | 勋章id | **详细说明有待补充** | +| name | str | 勋章名称 | | +| image | str | 挂件图片url 正常 | | +| image_small | str | 勋章图片url 小 | | +| level | str | 勋章等级 | | +| condition | str | 勋章条件 | | + +`data`中的`Official`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | -------- | -------------------------------------- | +| role | num | 认证类型 | 见[用户认证类型一览](official_role.md) | +| title | str | 认证信息 | 无为空 | +| desc | str | 认证备注 | 无为空 | +| type | num | 是否认证 | -1:无
0:认证 | + +`data`中的`level_exp`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | -------- | ------------------------------------------ | +| current_level | num | 当前等级 | 0-6级 | +| current_min | num | 0 | 指当前等级从多少经验值开始 | +| current_exp | num | 0 | 当前账户的经验值 | +| next_exp | num | 0 | 下一个等级所需的经验值**(不是还需要多少)** | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/space/myinfo' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "mid": 293793435, + "name": "社会易姐QwQ", + "sex": "男", + "face": "http://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg", + "sign": "高考刚结束的普通技术宅一枚,喜欢MC和编程以及电子,是车车人也是术术人,粉丝群:1136462265", + "rank": 10000, + "level": 5, + "jointime": 0, + "moral": 70, + "silence": 0, + "email_status": 1, + "tel_status": 1, + "identification": 1, + "vip": { + "type": 2, + "status": 1, + "due_date": 1644163200000, + "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": "" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299", + "role": 3, + "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png" + }, + "pendant": { + "pid": 2511, + "name": "初音未来13周年", + "image": "http://i0.hdslb.com/bfs/garb/item/4f8f3f1f2d47f0dad84f66aa57acd4409ea46361.png", + "expire": 0, + "image_enhance": "http://i0.hdslb.com/bfs/garb/item/fe0b83b53e2342b16646f6e7a9370d8a867decdb.webp", + "image_enhance_frame": "http://i0.hdslb.com/bfs/garb/item/127c507ec8448be30cf5f79500ecc6ef2fd32f2c.png" + }, + "nameplate": { + "nid": 4, + "name": "青铜殿堂", + "image": "http://i0.hdslb.com/bfs/face/2879cd5fb8518f7c6da75887994c1b2a7fe670bd.png", + "image_small": "http://i0.hdslb.com/bfs/face/6707c120e00a3445933308fd9b7bd9fad99e9ec4.png", + "level": "普通勋章", + "condition": "单个自制视频总播放数\u003e=1万" + }, + "official": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "birthday": 1015257600, + "is_tourist": 0, + "is_fake_account": 0, + "pin_prompting": 0, + "is_deleted": 0, + "in_reg_audit": 0, + "is_rip_user": false, + "profession": { + "id": 0, + "name": "", + "show_name": "" + }, + "level_exp": { + "current_level": 5, + "current_min": 10800, + "current_exp": 27125, + "next_exp": 28800 + }, + "coins": 9, + "following": 1122, + "follower": 1122 + } +} +``` + +
+ +## 多用户详细信息 + +> https://api.bilibili.com/x/polymer/pc-electron/v1/user/cards + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------------- | ------ | --------------------------------- | +| uids | nums | 目标用户的mid列表 | 必要 | 每个成员间用`,`分隔,最多50个成员 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误
40143:批量大小超过限制 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | 用户信息随机排序 | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------------- | ---- | +| {用户mid} | obj | 该mid对应的用户信息 | | +| …… | obj | …… | …… | + +`data`中的`{用户mid}`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----------------------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------- | +| mid | str | mid | | +| face | str | 头像链接 | | +| name | str | 昵称 | | +| official | obj | 认证信息 | 基本同「[用户空间详细信息](#用户空间详细信息)」中的 `data.official` 对象 | +| vip | obj | 会员信息 | 基本同「[用户空间详细信息](#用户空间详细信息)」中的 `data.vip` 对象,其中有些类型为 `num` 的字段在本接口中类型为 `str` | +| name_render | 有效时:obj
无效时:null | 昵称渲染信息 | | + +`{用户mid}`中的`name_render`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | --------------------------- | ---------------- | +| colors_info | obj | 昵称颜色信息(?) | **作用尚不明确** | +| render_scheme | str | `"Default"` 或 `"Colorful"` | **作用尚不明确** | + +`name_render`中的`colors_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | -------------- | ---------------- | +| color | array | 昵称颜色(?) | **作用尚不明确** | +| color_ids | array | `["6"]` | **作用尚不明确** | + +`color`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | --------- | ---- | +| 0 | obj | 颜色1 | | +| n | obj | 颜色(n+1) | | +| …… | obj | …… | …… | + +`color`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ---------------- | ----------- | +| color_day | str | 浅色模式昵称颜色 | HEX颜色代码 | +| color_night | str | 深色模式昵称颜色 | HEX颜色代码 | + +**示例:** + +查询用户`uids=1,2,3`的详细信息 + +```shell +curl -G 'https://api.bilibili.com/x/polymer/pc-electron/v1/user/cards' \ +--data-urlencode 'uids=1,2,3' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "1": { + "mid": "1", + "face": "http://i1.hdslb.com/bfs/face/34c5b30a990c7ce4a809626d8153fa7895ec7b63.gif", + "name": "bishi", + "official": { + "desc": "", + "role": 0, + "title": "", + "type": -1 + }, + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": "1912521600000", + "nickname_color": "#FB7299", + "role": "7", + "status": 1, + "theme_type": 0, + "type": 2, + "label": { + "bg_color": "#FB7299", + "bg_style": 1, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/adb599797dd171e2d3d6d012f448b49679258344.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/sGu57N6pgK.png", + "label_theme": "ten_annual_vip", + "path": "", + "text": "十年大会员", + "text_color": "#FFFFFF", + "use_img_label": true + } + }, + "name_render": null + }, + "2": { + "mid": "2", + "face": "https://i2.hdslb.com/bfs/face/ef0457addb24141e15dfac6fbf45293ccf1e32ab.jpg", + "name": "碧诗", + "official": { + "desc": "", + "role": 2, + "title": "bilibili创始人(站长)", + "type": 0 + }, + "vip": { + "avatar_subscript": 1, + "avatar_subscript_url": "", + "due_date": "3995625600000", + "nickname_color": "#FB7299", + "role": "7", + "status": 1, + "theme_type": 0, + "type": 2, + "label": { + "bg_color": "#FB7299", + "bg_style": 1, + "border_color": "", + "img_label_uri_hans": "https://i0.hdslb.com/bfs/activity-plat/static/20220608/e369244d0b14644f5e1a06431e22a4d5/wltavwHAkL.gif", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/802418ff03911645648b63aa193ba67997b5a0bc.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/8u7iRTPE7N.png", + "label_theme": "ten_annual_vip", + "path": "", + "text": "十年大会员", + "text_color": "#FFFFFF", + "use_img_label": true + } + }, + "name_render": null + }, + "3": { + "mid": "3", + "face": "http://i0.hdslb.com/bfs/face/d4de6a84557eea8f18510a3f61115d96832aa071.jpg", + "name": "囧囧倉", + "official": { + "desc": "", + "role": 0, + "title": "", + "type": -1 + }, + "vip": { + "avatar_subscript": 0, + "avatar_subscript_url": "", + "due_date": "0", + "nickname_color": "", + "role": "0", + "status": 0, + "theme_type": 0, + "type": 0, + "label": { + "bg_color": "", + "bg_style": 0, + "border_color": "", + "img_label_uri_hans": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant": "", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", + "label_theme": "", + "path": "", + "text": "", + "text_color": "", + "use_img_label": true + } + }, + "name_render": null + } + } +} +``` + +
+ +## 多用户详细信息2 + +> https://api.vc.bilibili.com/account/v1/user/cards + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +本接口较其他接口相比,只会返回非常有限的信息 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------------- | ------ | --------------------------------------------------------------------- | +| uids | nums | 目标用户的mid列表 | 必要 | 每个成员间用`,`分隔,最多50个成员,若超过此限制则返回的`data`数组为空 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | array | 信息本体 | 用户信息随机排序 | + + +**示例:** + +查询用户`uids=1,2,3`的详细信息 + +```shell +curl -G 'https://api.vc.bilibili.com/account/v1/user/cards' \ +--data-urlencode 'uids=1,2,3' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "mid": 3, + "name": "囧囧倉", + "face": "http://i0.hdslb.com/bfs/face/d4de6a84557eea8f18510a3f61115d96832aa071.jpg", + "sign": "富强、民主、文明、和谐、自由、平等、公正、法治、爱国、敬业、诚信、友善。", + "rank": 10000, + "level": 6, + "silence": 0 + }, + { + "mid": 2, + "name": "碧诗", + "face": "https://i2.hdslb.com/bfs/face/ef0457addb24141e15dfac6fbf45293ccf1e32ab.jpg", + "sign": "https://kami.im 直男过气网红 # We Are Star Dust", + "rank": 20000, + "level": 6, + "silence": 0 + }, + { + "mid": 1, + "name": "bishi", + "face": "http://i1.hdslb.com/bfs/face/34c5b30a990c7ce4a809626d8153fa7895ec7b63.gif", + "sign": "", + "rank": 10000, + "level": 6, + "silence": 0 + } + ] +} +``` + +
+ +## 多用户详细信息3 + +> https://api.vc.bilibili.com/x/im/user_infos + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------------- | ------ | ------------------- | +| uids | nums | 目标用户的mid列表 | 必要 | 每个成员间用`,`分隔 | + + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | --------- | ---- | +| 0 | obj | 用户1 | | +| n | obj | 用户(n+1) | | +| …… | obj | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | ------------ | -------------------- | +| mid | num | mid | | +| name | str | 昵称 | | +| face | str | 头像链接 | | +| sign | str | 签名 | | +| rank | num | 用户权限等级 | | +| level | num | 当前等级 | 0-6 级 | +| silence | num | 封禁状态 | 0:正常
1:被封 | +| vip | obj | 大会员信息 | | +| offical | obj | 认证信息 | | +| is_fake_account | bool | | | +| expert_info | obj | 专业信息? | | + +**示例:** + +查询用户`uids=1,2,3`的详细信息 + +```shell +curl -G 'https://api.vc.bilibili.com/x/im/user_infos' \ +--data-urlencode 'uids=2,114514' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "0", + "message": "0", + "ttl": 1, + "data": [ + { + "mid": 2, + "name": "碧诗", + "sex": "男", + "face": "https://i2.hdslb.com/bfs/face/ef0457addb24141e15dfac6fbf45293ccf1e32ab.jpg", + "sign": "https://kami.im 直男过气网红 # We Are Star Dust", + "rank": 20000, + "level": 6, + "silence": 0, + "vip": { + "type": 2, + "status": 1, + "due_date": 4000982400000, + "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": 1, + "tv_due_date": 2003500800, + "avatar_icon": { + "icon_type": 1, + "icon_resource": { + + } + } + }, + "pendant": { + "pid": -338454175, + "name": "箱庭少女之梦头像", + "image": "https://i2.hdslb.com/bfs/garb/open/efe5e579cbb95a404c2ba289f37c5965dee7a3a2.png", + "expire": 0, + "image_enhance": "https://i2.hdslb.com/bfs/garb/open/efe5e579cbb95a404c2ba289f37c5965dee7a3a2.png", + "image_enhance_frame": "", + "n_pid": 1743418268001 + }, + "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": "所有自制视频总播放数\u003E=10万" + }, + "official": { + "role": 2, + "title": "bilibili创始人(站长)", + "desc": "", + "type": 0 + }, + "birthday": 622137600, + "is_fake_account": 0, + "is_deleted": 0, + "in_reg_audit": 0, + "face_nft": 0, + "face_nft_new": 0, + "is_senior_member": 0, + "digital_id": "", + "digital_type": -2, + "attestation": { + "type": 2, + "common_info": { + "title": "bilibili创始人(站长)", + "prefix": "bilibili UP主认证", + "prefix_title": "bilibili UP主认证:bilibili创始人(站长)" + }, + "splice_info": { + "title": "bilibili创始人(站长)" + }, + "icon": "https://i0.hdslb.com/bfs/activity-plat/static/20230828/e3b8ebec8e86f060b930a2c0536bb88b/72wejSxl9Z.png", + "desc": "" + }, + "expert_info": { + "title": "", + "state": 0, + "type": 0, + "desc": "" + }, + "honours": { + "mid": 2, + "colour": { + "dark": "#CE8620", + "normal": "#F0900B" + }, + "tags": null, + "is_latest_100honour": 0 + }, + "name_render": null, + "json_ava": { + "container_size": { + "width": 1.375, + "height": 1.375 + }, + "fallback_layers": { + "layers": [ + { + "visible": true, + "general_spec": { + "pos_spec": { + "coordinate_pos": 2, + "axis_x": 0.6875, + "axis_y": 0.6875 + }, + "size_spec": { + "width": 0.787, + "height": 0.787 + }, + "render_spec": { + "opacity": 1 + } + }, + "layer_config": { + "tags": { + "AVATAR_LAYER": { + + } + }, + "is_critical": true, + "layer_mask": { + "general_spec": { + "pos_spec": { + "coordinate_pos": 2, + "axis_x": 0.6875, + "axis_y": 0.6875 + }, + "size_spec": { + "width": 0.787, + "height": 0.787 + }, + "render_spec": { + "opacity": 1 + } + }, + "mask_src": { + "src_type": 3, + "draw": { + "draw_type": 1, + "fill_mode": 1, + "color_config": { + "day": { + "argb": "#FF000000" + } + } + } + } + } + }, + "resource": { + "res_type": 3, + "res_image": { + "image_src": { + "src_type": 1, + "placeholder": 6, + "remote": { + "url": "https://i2.hdslb.com/bfs/face/ef0457addb24141e15dfac6fbf45293ccf1e32ab.jpg", + "bfs_style": "widget-layer-avatar" + } + } + } + } + }, + { + "visible": true, + "general_spec": { + "pos_spec": { + "coordinate_pos": 2, + "axis_x": 0.6875, + "axis_y": 0.6875 + }, + "size_spec": { + "width": 1.375, + "height": 1.375 + }, + "render_spec": { + "opacity": 1 + } + }, + "layer_config": { + "tags": { + "PENDENT_LAYER": { + + } + } + }, + "resource": { + "res_type": 3, + "res_image": { + "image_src": { + "src_type": 1, + "remote": { + "url": "https://i2.hdslb.com/bfs/garb/open/efe5e579cbb95a404c2ba289f37c5965dee7a3a2.png", + "bfs_style": "widget-layer-avatar" + } + } + } + } + }, + { + "visible": true, + "general_spec": { + "pos_spec": { + "coordinate_pos": 1, + "axis_x": 0.806, + "axis_y": 0.822666666666667 + }, + "size_spec": { + "width": 0.35, + "height": 0.35 + }, + "render_spec": { + "opacity": 1 + } + }, + "layer_config": { + "tags": { + "ICON_LAYER": { + + } + } + }, + "resource": { + "res_type": 5, + "res_native_draw": { + "draw_src": { + "src_type": 3, + "draw": { + "draw_type": 1, + "fill_mode": 1, + "color_config": { + "is_dark_mode_aware": true, + "day": { + "argb": "#FFFFFFFF" + }, + "night": { + "argb": "#FF17181A" + } + } + } + } + } + } + }, + { + "visible": true, + "general_spec": { + "pos_spec": { + "coordinate_pos": 1, + "axis_x": 0.831, + "axis_y": 0.847666666666667 + }, + "size_spec": { + "width": 0.3, + "height": 0.3 + }, + "render_spec": { + "opacity": 1 + } + }, + "layer_config": { + "tags": { + "ICON_LAYER": { + + } + } + }, + "resource": { + "res_type": 3, + "res_image": { + "image_src": { + "src_type": 2, + "local": 3 + } + } + } + } + ], + "is_critical_group": true + }, + "mid": "2" + } + }, + { + "mid": 114514, + "name": "田所こうじ", + "sex": "保密", + "face": "http://i1.hdslb.com/bfs/face/875eb66bb952f16afa9634081a820dea8e3fac96.jpg", + "sign": "?!", + "rank": 10000, + "level": 6, + "silence": 0, + "vip": { + "type": 1, + "status": 0, + "due_date": 1683043200000, + "vip_pay_type": 0, + "theme_type": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "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/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "", + "tv_vip_status": 0, + "tv_vip_pay_type": 0, + "tv_due_date": 0, + "avatar_icon": { + "icon_resource": { + + } + } + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0 + }, + "nameplate": { + "nid": 0, + "name": "", + "image": "", + "image_small": "", + "level": "", + "condition": "" + }, + "official": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "birthday": -1590393600, + "is_fake_account": 0, + "is_deleted": 0, + "in_reg_audit": 0, + "face_nft": 0, + "face_nft_new": 0, + "is_senior_member": 0, + "digital_id": "", + "digital_type": -2, + "attestation": { + "type": 0, + "common_info": { + "title": "", + "prefix": "", + "prefix_title": "" + }, + "splice_info": { + "title": "" + }, + "icon": "", + "desc": "" + }, + "expert_info": { + "title": "", + "state": 0, + "type": 0, + "desc": "" + }, + "honours": { + "mid": 114514, + "colour": { + "dark": "#CE8620", + "normal": "#F0900B" + }, + "tags": null, + "is_latest_100honour": 0 + }, + "name_render": null, + "json_ava": { + "container_size": { + "width": 1.35, + "height": 1.35 + }, + "fallback_layers": { + "layers": [ + { + "visible": true, + "general_spec": { + "pos_spec": { + "coordinate_pos": 2, + "axis_x": 0.675, + "axis_y": 0.675 + }, + "size_spec": { + "width": 1, + "height": 1 + }, + "render_spec": { + "opacity": 1 + } + }, + "layer_config": { + "tags": { + "AVATAR_LAYER": { + + } + }, + "is_critical": true, + "layer_mask": { + "general_spec": { + "pos_spec": { + "coordinate_pos": 2, + "axis_x": 0.675, + "axis_y": 0.675 + }, + "size_spec": { + "width": 1, + "height": 1 + }, + "render_spec": { + "opacity": 1 + } + }, + "mask_src": { + "src_type": 3, + "draw": { + "draw_type": 1, + "fill_mode": 1, + "color_config": { + "day": { + "argb": "#FF000000" + } + } + } + } + } + }, + "resource": { + "res_type": 3, + "res_image": { + "image_src": { + "src_type": 1, + "placeholder": 6, + "remote": { + "url": "http://i1.hdslb.com/bfs/face/875eb66bb952f16afa9634081a820dea8e3fac96.jpg", + "bfs_style": "widget-layer-avatar" + } + } + } + } + } + ], + "is_critical_group": true + }, + "mid": "114514" + } + } + ] +} +``` +
diff --git a/bb-api-collect/docs/user/medals.md b/bb-api-collect/docs/user/medals.md new file mode 100644 index 0000000000..d2374bc0a6 --- /dev/null +++ b/bb-api-collect/docs/user/medals.md @@ -0,0 +1,822 @@ +# 所有粉丝勋章 + +## 指定用户的所有粉丝勋章信息 + +> https://api.live.bilibili.com/xlive/web-ucenter/user/MedalWall + +*请求方法: GET* + +认证方式: Cookie (SESSDATA) + + + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | -------- | ------ | ---- | +| target_id | num | 目标 mid | 必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0: 成功
-101: 账号未登录 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | 失败时不存在 | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ----- | --------------------- | ----- | +| list | array | 勋章列表 | | +| count | num | 勋章数 | | +| close_space_medal | num | 关闭空间粉丝勋章显示? | 0: 否 | +| only_show_wearing | num | 只显示当前佩戴的? | 0: 否 | +| name | str | 目标用户名 | | +| icon | str | 目标用户头像 URL | | +| uid | num | 目标用户 mid | | +| level | num | 目标用户等级 | | + +`data` 对象中 `list` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ------------ | ---- | +| medal_info | obj | 勋章信息 | | +| target_name | str | 主播名称 | | +| target_icon | str | 主播头像 URL | | +| link | str | 主播主页 URL | | +| live_status | num | 直播状态 | 0: 未直播
1: 正在直播
2: 轮播中 | +| offical | num | 主播认证类型 | 参见 [用户认证类型一览](official_role.md) | +| uinfo_medal | str | 用户勋章信息 | | + +`list` 数组中的对象中的 `medal_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ---- | -------- | ---- | +| target_id | num | 主播 mid | | +| level | num | 勋章等级 | | +| medal_name | str | 勋章名称 | | +| medal_color_start | num | 勋章开始颜色 | 十进制(自行转换为16进制) | +| medal_color_end | num | 勋章结束颜色 | 同上 | +| medal_color_border | num | 勋章边框颜色 | 同上 | +| guard_level | num | 守护等级? | 1: 总督
2: 提督
3: 舰长 | +| wearing_status | num | 佩戴状态 | 0: 未佩戴
1: 佩戴中 | +| medal_id | num | 勋章 ID | | +| intimacy | num | 当前亲密度 | | +| next_intimacy | num | 下一等级所需亲密度 | | +| today_feed | num | 今日已获得亲密度 | | +| day_limit | num | 亲密度每日上限? | | +| guard_icon | str | 守护徽章图标 URL? | | +| honor_icon | str | 荣誉徽章图标 URL? | | + +`list` 数组中的对象中的 `uinfo_medal` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ---- | ---- | +| name | str | 勋章名称 | | +| level | num | 勋章等级 | | +| color_start | num | 勋章渐变开始颜色 | 十进制(自行转换为16进制) | +| color_end | num | 勋章渐变结束颜色 | 同上 | +| color_border | num | 勋章边框颜色 | 同上 | +| color | num | 勋章颜色 | 同上 | +| id | num | 勋章 ID | | +| typ | num | 勋章类型? | | +| is_light | num | 是否点亮? | | +| ruid | num | 主播 mid | | +| guard_level | num | 大航海等级 | 1: 总督
2: 提督
3: 舰长 | +| score | num | 勋章分数? | | +| guard_icon | str | 大航海图标 URL? | 粉丝牌左边的图标 | +| honor_icon | str | 荣誉徽章图标 URL? | | +| v2_medal_color_start | str | 勋章开始颜色 | 16进制 | +| v2_medal_color_end | str | 勋章结束颜色 | 同上 | +| v2_medal_color_border | str | 勋章边框颜色 | 同上 | +| v2_medal_color_text | str | 勋章文本色 | 同上 | +| v2_medal_color_level | str | 勋章等级颜色 | 同上 | +| user_receive_count | num | 勋章已获得数量? | | + +**示例:** + +```shell +curl -G 'https://api.live.bilibili.com/xlive/web-ucenter/user/MedalWall' \ +--url-query 'target_id=293793435' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "medal_info": { + "target_id": 178429408, + "level": 3, + "medal_name": "滑稽果", + "medal_color_start": 6067854, + "medal_color_end": 6067854, + "medal_color_border": 6067854, + "guard_level": 0, + "wearing_status": 1, + "medal_id": 113190, + "intimacy": 248, + "next_intimacy": 500, + "today_feed": 0, + "day_limit": 2000, + "guard_icon": "", + "honor_icon": "" + }, + "target_name": "老弟一号", + "target_icon": "https://i1.hdslb.com/bfs/face/21426275f3d3149b96b88783275205ba574c09e3.jpg", + "link": "https://space.bilibili.com/178429408", + "live_status": 2, + "official": 1, + "uinfo_medal": { + "name": "滑稽果", + "level": 3, + "color_start": 6067854, + "color_end": 6067854, + "color_border": 6067854, + "color": 0, + "id": 113190, + "typ": 0, + "is_light": 1, + "ruid": 178429408, + "guard_level": 0, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#5762A799", + "v2_medal_color_end": "#5762A799", + "v2_medal_color_border": "#5762A799", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + } + }, + { + "medal_info": { + "target_id": 15858903, + "level": 9, + "medal_name": "二技猿", + "medal_color_start": 9272486, + "medal_color_end": 9272486, + "medal_color_border": 9272486, + "guard_level": 0, + "wearing_status": 0, + "medal_id": 159670, + "intimacy": 168, + "next_intimacy": 1900, + "today_feed": 0, + "day_limit": 3000, + "guard_icon": "", + "honor_icon": "" + }, + "target_name": "暮光小猿wzt", + "target_icon": "https://i0.hdslb.com/bfs/face/4113913241f83b03301c316fec6e4c3923bef64e.jpg", + "link": "https://space.bilibili.com/15858903", + "live_status": 0, + "official": 0, + "uinfo_medal": { + "name": "二技猿", + "level": 9, + "color_start": 9272486, + "color_end": 9272486, + "color_border": 9272486, + "color": 0, + "id": 159670, + "typ": 0, + "is_light": 1, + "ruid": 15858903, + "guard_level": 0, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#596FE099", + "v2_medal_color_end": "#596FE099", + "v2_medal_color_border": "#596FE099", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + } + }, + { + "medal_info": { + "target_id": 24022863, + "level": 7, + "medal_name": "粉丝团", + "medal_color_start": 6126494, + "medal_color_end": 6126494, + "medal_color_border": 6126494, + "guard_level": 0, + "wearing_status": 0, + "medal_id": 233401, + "intimacy": 1499, + "next_intimacy": 1600, + "today_feed": 0, + "day_limit": 2000, + "guard_icon": "", + "honor_icon": "" + }, + "target_name": "黄禄轩电脑专用账号", + "target_icon": "https://i0.hdslb.com/bfs/face/a70ec7d2a3822980a915ef4b30371af0cbc79132.jpg", + "link": "https://space.bilibili.com/24022863", + "live_status": 2, + "official": 0, + "uinfo_medal": { + "name": "粉丝团", + "level": 7, + "color_start": 6126494, + "color_end": 6126494, + "color_border": 6126494, + "color": 0, + "id": 233401, + "typ": 0, + "is_light": 1, + "ruid": 24022863, + "guard_level": 0, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#5866C799", + "v2_medal_color_end": "#5866C799", + "v2_medal_color_border": "#5866C799", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + } + }, + { + "medal_info": { + "target_id": 1347373376, + "level": 6, + "medal_name": "Geek范", + "medal_color_start": 6126494, + "medal_color_end": 6126494, + "medal_color_border": 6126494, + "guard_level": 0, + "wearing_status": 0, + "medal_id": 658512, + "intimacy": 999, + "next_intimacy": 1500, + "today_feed": 0, + "day_limit": 2000, + "guard_icon": "", + "honor_icon": "" + }, + "target_name": "GeekLogic", + "target_icon": "https://i2.hdslb.com/bfs/face/fc4ba4087efa80dce11dfdd1c2bc07d84fb603b9.jpg", + "link": "https://space.bilibili.com/1347373376", + "live_status": 0, + "official": 1, + "uinfo_medal": { + "name": "Geek范", + "level": 6, + "color_start": 6126494, + "color_end": 6126494, + "color_border": 6126494, + "color": 0, + "id": 658512, + "typ": 0, + "is_light": 1, + "ruid": 1347373376, + "guard_level": 0, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#5866C799", + "v2_medal_color_end": "#5866C799", + "v2_medal_color_border": "#5866C799", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + } + }, + { + "medal_info": { + "target_id": 451664, + "level": 5, + "medal_name": "粉丝团", + "medal_color_start": 6126494, + "medal_color_end": 6126494, + "medal_color_border": 6126494, + "guard_level": 0, + "wearing_status": 0, + "medal_id": 408689, + "intimacy": 799, + "next_intimacy": 1000, + "today_feed": 0, + "day_limit": 2000, + "guard_icon": "", + "honor_icon": "" + }, + "target_name": "刘师兄_liujun", + "target_icon": "https://i2.hdslb.com/bfs/face/90665d1613cc5501a3f7bbc79b5dc83bcc30667d.jpg", + "link": "https://space.bilibili.com/451664", + "live_status": 0, + "official": 0, + "uinfo_medal": { + "name": "粉丝团", + "level": 5, + "color_start": 6126494, + "color_end": 6126494, + "color_border": 6126494, + "color": 0, + "id": 408689, + "typ": 0, + "is_light": 1, + "ruid": 451664, + "guard_level": 0, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#5866C799", + "v2_medal_color_end": "#5866C799", + "v2_medal_color_border": "#5866C799", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + } + }, + { + "medal_info": { + "target_id": 89240844, + "level": 5, + "medal_name": "六零", + "medal_color_start": 6126494, + "medal_color_end": 6126494, + "medal_color_border": 6126494, + "guard_level": 0, + "wearing_status": 0, + "medal_id": 306526, + "intimacy": 799, + "next_intimacy": 1000, + "today_feed": 0, + "day_limit": 2000, + "guard_icon": "", + "honor_icon": "" + }, + "target_name": "A60_OnE", + "target_icon": "https://i0.hdslb.com/bfs/face/483513f7b0533d666fdf7eff96a70b69992056fd.jpg", + "link": "https://space.bilibili.com/89240844", + "live_status": 0, + "official": 0, + "uinfo_medal": { + "name": "六零", + "level": 5, + "color_start": 6126494, + "color_end": 6126494, + "color_border": 6126494, + "color": 0, + "id": 306526, + "typ": 0, + "is_light": 1, + "ruid": 89240844, + "guard_level": 0, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#5866C799", + "v2_medal_color_end": "#5866C799", + "v2_medal_color_border": "#5866C799", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + } + }, + { + "medal_info": { + "target_id": 1850091, + "level": 5, + "medal_name": "観測者", + "medal_color_start": 6126494, + "medal_color_end": 6126494, + "medal_color_border": 6126494, + "guard_level": 0, + "wearing_status": 0, + "medal_id": 118910, + "intimacy": 98, + "next_intimacy": 1000, + "today_feed": 0, + "day_limit": 2000, + "guard_icon": "", + "honor_icon": "" + }, + "target_name": "Jannchie见齐", + "target_icon": "https://i0.hdslb.com/bfs/face/983034448f81f45f05956d0455a86fe0639d6a36.jpg", + "link": "https://space.bilibili.com/1850091", + "live_status": 2, + "official": 1, + "uinfo_medal": { + "name": "観測者", + "level": 5, + "color_start": 6126494, + "color_end": 6126494, + "color_border": 6126494, + "color": 0, + "id": 118910, + "typ": 0, + "is_light": 1, + "ruid": 1850091, + "guard_level": 0, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#5866C799", + "v2_medal_color_end": "#5866C799", + "v2_medal_color_border": "#5866C799", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + } + }, + { + "medal_info": { + "target_id": 4911405, + "level": 4, + "medal_name": "毛狐狸", + "medal_color_start": 6067854, + "medal_color_end": 6067854, + "medal_color_border": 6067854, + "guard_level": 0, + "wearing_status": 0, + "medal_id": 18887, + "intimacy": 658, + "next_intimacy": 700, + "today_feed": 0, + "day_limit": 2000, + "guard_icon": "", + "honor_icon": "" + }, + "target_name": "粉毛变态老狐狸", + "target_icon": "https://i0.hdslb.com/bfs/face/5924e9201ac87066e76534472303b636a9961647.jpg", + "link": "https://space.bilibili.com/4911405", + "live_status": 0, + "official": 0, + "uinfo_medal": { + "name": "毛狐狸", + "level": 4, + "color_start": 6067854, + "color_end": 6067854, + "color_border": 6067854, + "color": 0, + "id": 18887, + "typ": 0, + "is_light": 1, + "ruid": 4911405, + "guard_level": 0, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#5762A799", + "v2_medal_color_end": "#5762A799", + "v2_medal_color_border": "#5762A799", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + } + }, + { + "medal_info": { + "target_id": 130914376, + "level": 3, + "medal_name": "江草", + "medal_color_start": 6067854, + "medal_color_end": 6067854, + "medal_color_border": 6067854, + "guard_level": 0, + "wearing_status": 0, + "medal_id": 166326, + "intimacy": 463, + "next_intimacy": 500, + "today_feed": 0, + "day_limit": 2000, + "guard_icon": "", + "honor_icon": "" + }, + "target_name": "江灵夏草", + "target_icon": "https://i1.hdslb.com/bfs/face/63eb615514fddbc6024a34ddcacfb0bc6103d019.jpg", + "link": "https://space.bilibili.com/130914376", + "live_status": 0, + "official": 1, + "uinfo_medal": { + "name": "江草", + "level": 3, + "color_start": 6067854, + "color_end": 6067854, + "color_border": 6067854, + "color": 0, + "id": 166326, + "typ": 0, + "is_light": 1, + "ruid": 130914376, + "guard_level": 0, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#5762A799", + "v2_medal_color_end": "#5762A799", + "v2_medal_color_border": "#5762A799", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + } + }, + { + "medal_info": { + "target_id": 316568752, + "level": 3, + "medal_name": "SEAL", + "medal_color_start": 6067854, + "medal_color_end": 6067854, + "medal_color_border": 6067854, + "guard_level": 0, + "wearing_status": 0, + "medal_id": 312420, + "intimacy": 428, + "next_intimacy": 500, + "today_feed": 0, + "day_limit": 2000, + "guard_icon": "", + "honor_icon": "" + }, + "target_name": "马督工", + "target_icon": "https://i1.hdslb.com/bfs/face/1c56737dfc0deffffc31c78e0cefb0c3ecf7e000.jpg", + "link": "https://space.bilibili.com/316568752", + "live_status": 0, + "official": 1, + "uinfo_medal": { + "name": "SEAL", + "level": 3, + "color_start": 6067854, + "color_end": 6067854, + "color_border": 6067854, + "color": 0, + "id": 312420, + "typ": 0, + "is_light": 1, + "ruid": 316568752, + "guard_level": 0, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#5762A799", + "v2_medal_color_end": "#5762A799", + "v2_medal_color_border": "#5762A799", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + } + }, + { + "medal_info": { + "target_id": 633003, + "level": 3, + "medal_name": "器材党", + "medal_color_start": 6067854, + "medal_color_end": 6067854, + "medal_color_border": 6067854, + "guard_level": 0, + "wearing_status": 0, + "medal_id": 57027, + "intimacy": 198, + "next_intimacy": 500, + "today_feed": 0, + "day_limit": 2000, + "guard_icon": "", + "honor_icon": "" + }, + "target_name": "和光Channel", + "target_icon": "https://i0.hdslb.com/bfs/face/c34413202f3f4ab6c7955a2c9ca5a9ac8e86d8c2.jpg", + "link": "https://space.bilibili.com/633003", + "live_status": 0, + "official": 0, + "uinfo_medal": { + "name": "器材党", + "level": 3, + "color_start": 6067854, + "color_end": 6067854, + "color_border": 6067854, + "color": 0, + "id": 57027, + "typ": 0, + "is_light": 1, + "ruid": 633003, + "guard_level": 0, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#5762A799", + "v2_medal_color_end": "#5762A799", + "v2_medal_color_border": "#5762A799", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + } + }, + { + "medal_info": { + "target_id": 5760446, + "level": 2, + "medal_name": "花泪", + "medal_color_start": 6067854, + "medal_color_end": 6067854, + "medal_color_border": 6067854, + "guard_level": 0, + "wearing_status": 0, + "medal_id": 32283, + "intimacy": 298, + "next_intimacy": 300, + "today_feed": 0, + "day_limit": 2000, + "guard_icon": "", + "honor_icon": "" + }, + "target_name": "花儿不哭", + "target_icon": "https://i2.hdslb.com/bfs/face/4f220d57ca877167f3efdc60e40d0cb53ca58b72.jpg", + "link": "https://space.bilibili.com/5760446", + "live_status": 0, + "official": 1, + "uinfo_medal": { + "name": "花泪", + "level": 2, + "color_start": 6067854, + "color_end": 6067854, + "color_border": 6067854, + "color": 0, + "id": 32283, + "typ": 0, + "is_light": 1, + "ruid": 5760446, + "guard_level": 0, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#5762A799", + "v2_medal_color_end": "#5762A799", + "v2_medal_color_border": "#5762A799", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + } + }, + { + "medal_info": { + "target_id": 3644545, + "level": 2, + "medal_name": "东方狗", + "medal_color_start": 6067854, + "medal_color_end": 6067854, + "medal_color_border": 6067854, + "guard_level": 0, + "wearing_status": 0, + "medal_id": 249059, + "intimacy": 98, + "next_intimacy": 300, + "today_feed": 0, + "day_limit": 2000, + "guard_icon": "", + "honor_icon": "" + }, + "target_name": "白倉カナ", + "target_icon": "https://i1.hdslb.com/bfs/face/ae839f221a5812683fe0a3967f4a612dd65a05d2.jpg", + "link": "https://space.bilibili.com/3644545", + "live_status": 0, + "official": 0, + "uinfo_medal": { + "name": "东方狗", + "level": 2, + "color_start": 6067854, + "color_end": 6067854, + "color_border": 6067854, + "color": 0, + "id": 249059, + "typ": 0, + "is_light": 1, + "ruid": 3644545, + "guard_level": 0, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#5762A799", + "v2_medal_color_end": "#5762A799", + "v2_medal_color_border": "#5762A799", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + } + }, + { + "medal_info": { + "target_id": 614801, + "level": 1, + "medal_name": "神油", + "medal_color_start": 6067854, + "medal_color_end": 6067854, + "medal_color_border": 6067854, + "guard_level": 0, + "wearing_status": 0, + "medal_id": 627, + "intimacy": 119, + "next_intimacy": 201, + "today_feed": 0, + "day_limit": 2000, + "guard_icon": "", + "honor_icon": "" + }, + "target_name": "神游八方", + "target_icon": "https://i2.hdslb.com/bfs/face/98f8e0f609ff2403cc086f7254f388336b6f5366.jpg", + "link": "https://space.bilibili.com/614801", + "live_status": 0, + "official": 1, + "uinfo_medal": { + "name": "神油", + "level": 1, + "color_start": 6067854, + "color_end": 6067854, + "color_border": 6067854, + "color": 0, + "id": 627, + "typ": 0, + "is_light": 1, + "ruid": 614801, + "guard_level": 0, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#5762A799", + "v2_medal_color_end": "#5762A799", + "v2_medal_color_border": "#5762A799", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + } + }, + { + "medal_info": { + "target_id": 12246, + "level": 1, + "medal_name": "纯色派", + "medal_color_start": 6067854, + "medal_color_end": 6067854, + "medal_color_border": 6067854, + "guard_level": 0, + "wearing_status": 0, + "medal_id": 5171, + "intimacy": 99, + "next_intimacy": 201, + "today_feed": 0, + "day_limit": 2000, + "guard_icon": "", + "honor_icon": "" + }, + "target_name": "囧仙", + "target_icon": "https://i0.hdslb.com/bfs/face/b7ee967282a33a59908218df5b240b45f51afda8.jpg", + "link": "https://space.bilibili.com/12246", + "live_status": 0, + "official": 1, + "uinfo_medal": { + "name": "纯色派", + "level": 1, + "color_start": 6067854, + "color_end": 6067854, + "color_border": 6067854, + "color": 0, + "id": 5171, + "typ": 0, + "is_light": 1, + "ruid": 12246, + "guard_level": 0, + "score": 0, + "guard_icon": "", + "honor_icon": "", + "v2_medal_color_start": "#5762A799", + "v2_medal_color_end": "#5762A799", + "v2_medal_color_border": "#5762A799", + "v2_medal_color_text": "#FFFFFFFF", + "v2_medal_color_level": "#000B7099", + "user_receive_count": 0 + } + } + ], + "count": 15, + "close_space_medal": 0, + "only_show_wearing": 0, + "name": "社会易姐QwQ", + "icon": "https://i0.hdslb.com/bfs/face/aebb2639a0d47f2ce1fec0631f412eaf53d4a0be.jpg", + "uid": 645769214, + "level": 6 + } +} +``` + +
diff --git a/bb-api-collect/docs/user/official_role.md b/bb-api-collect/docs/user/official_role.md new file mode 100644 index 0000000000..fb70aacc20 --- /dev/null +++ b/bb-api-collect/docs/user/official_role.md @@ -0,0 +1,12 @@ +# 用户认证类型一览 +| ID | 认证类型 | 详细类型 | +| -- | ------- | ------- | +| 0 | 无 | | +| 1 | 个人认证 | 知名UP主 | +| 2 | 个人认证 | 大V达人 | +| 3 | 机构认证 | 企业 | +| 4 | 机构认证 | 组织 | +| 5 | 机构认证 | 媒体 | +| 6 | 机构认证 | 政府 | +| 7 | 个人认证 | 高能主播 | +| 9 | 个人认证 | 社会知名人士 | \ No newline at end of file diff --git a/bb-api-collect/docs/user/register.md b/bb-api-collect/docs/user/register.md new file mode 100644 index 0000000000..21be1d6af2 --- /dev/null +++ b/bb-api-collect/docs/user/register.md @@ -0,0 +1,100 @@ +# 用户注册 + +## 人机验证 + +[完成人机验证(参考验证登录)](../login/login_action/readme.md#验证登录) + +完成后得到`key`, `challenge`, `validate`, `seccode`四个参数 + +## 发送短信验证码 + +[发送短信验证码(参考短信登录)](../login/login_action/SMS.md#发送短信验证码(web端)) + +**注意不同的是这里type=1而非21**,推测此参数决定短信内容 + +```bash +curl 'https://passport.bilibili.com/web/sms/general/v2/send' \ + --data-urlencode 'key=6eeb28e7bbd64b389da2be3a2778c7e3' \ + --data-urlencode 'captchaType=6' \ + --data-urlencode 'type=1' \ + --data-urlencode 'cid=1' \ + --data-urlencode 'tel=13888888888' \ + --data-urlencode 'challenge=c52148f88a28b6011db52bb213483ee8' \ + --data-urlencode 'validate=a98841cd6ea58e1b1f5783fca73cddb6' \ + --data-urlencode 'seccode=a98841cd6ea58e1b1f5783fca73cddb6|jordan' +``` + +
+查看示例 + +```json +{ + "code": 0, + "message": "验证码短信已下发" +} +``` + +
+ +## 提交注册请求 + +> https://passport.bilibili.com/web/reg/tel + +*请求方式:POST* + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------- | ---- | ---------------- | ------ | ------------------------------------------------------------ | +| cid | num | 国际冠字码 | 必要 | 可以从 [获取国际冠字码](../login/login_action/SMS.md#获取国际冠字码_web端) 接口中获取 | +| tel | num | 手机号码 | 必要 | | +| code | num | 短信验证码 | 必要 | | +| nickName | str | 昵称 | 必要 | | +| pwd | str | 密码 | 必要 | 密码为明文 | +| plat | num | 0 | 必要 | 平台? | +| gourl | str | 注册成功跳转地址 | 非必要 | 默认为主页`https://www.bilibili.com/` | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------------------------- | +| code | num | 返回值 | 0:成功
1005:验证码错误
1007:验证码过期 | +| message | str | 错误信息 | 成功时无此字段 | +| data | obj | 信息本体 | 只在成功时存在 | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ---------- | ----------------------------- | +| redirectUrl | str | 跳转链接 | | +| hint | str | "注册成功" | 成功后不提示成功还能提示什么? | +| in_reg_audit | num | (?) | | + +```bash +curl 'https://passport.bilibili.com/web/reg/tel' \ + --data-urlencode 'plat=0' \ + --data-urlencode 'cid=1' \ + --data-urlencode 'tel=13888888888' \ + --data-urlencode 'code=121314' \ + --data-urlencode 'nickName=萌系小妹纸わ' + --data-urlencode 'pwd=Password1234' \ + --data-urlencode 'gourl=https://www.bilibili.com' +``` + +
+查看示例 + +```json +{ + "code": 0, + "data": { + "redirectUrl": "https://www.bilibili.com", + "hint": "注册成功", + "in_reg_audit": 0 + } +} +``` + +
\ No newline at end of file diff --git a/bb-api-collect/docs/user/relation.md b/bb-api-collect/docs/user/relation.md new file mode 100644 index 0000000000..b8d4fa05d1 --- /dev/null +++ b/bb-api-collect/docs/user/relation.md @@ -0,0 +1,2724 @@ +# 用户关系相关 + +## 查询关系列表 + + + +### 关系列表对象 + +以下说明中的 “目标用户” 指被查询的用户,“对方” 指返回的关系列表中的用户。 + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ------------------------------------------- | -------------------------- | ----------------------------------------------------------------------------------------- | +| mid | num | 用户 mid | | +| attribute | num | 对方对于**自己**的关系属性 | 0:未关注
~~1:悄悄关注(现已下线)~~
2:已关注
6:已互粉
128:已拉黑 | +| mtime | num | 对方关注目标用户时间 | 秒级时间戳
互关后刷新 | +| tag | 默认分组:null
存在至少一个分组:array | 目标用户将对方分组到的 id | | +| special | num | 目标用户特别关注对方标识 | 0:否
1:是 | +| contract_info | obj | 契约计划相关信息 | | +| uname | str | 用户昵称 | | +| face | str | 用户头像url | | +| sign | str | 用户签名 | | +| face_nft | num | 是否为 NFT 头像 | 0:非 NFT 头像
1:NFT 头像 | +| official_verify | obj | 认证信息 | | +| vip | obj | 会员信息 | | +| name_render | 有效时:obj
无效时:null | 昵称渲染信息 | | +| nft_icon | str | (?) | | +| rec_reason | str | 推荐该用户的原因 | 大多数情况下为空;如:`xxx关注了TA`、`xx粉丝 xx视频` | +| track_id | str | 内部记录id | 大多数情况下为空;如:`up_rec_0.router-main-2021485-5f84c987cf-dv8fg.1746380060327.607` | +| follow_time | str | (?) | | + +`list`中的对象中的`tag`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | ------------------------ | ---- | +| 0 | num | 位于分组 1 的分组 id | | +| n | num | 位于分组(n+1)的分组 id | | +| …… | num | …… | …… | + +`list`中的对象中的`contract_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ------------------------------ | ----------------------------------------------------------- | +| is_contract | bool | 目标用户是否为对方的契约者 | 仅当为 `true` 时才有此项 | +| is_contractor | bool | 对方是否为目标用户的契约者 | 仅当为 `true` 时才有此项 | +| ts | num | 对方成为目标用户的契约者的时间 | 秒级时间戳,仅当 `is_contractor` 项的值为 `true` 时才有此项 | +| user_attr | num | 对方作为目标用户的契约者的属性 | 1:老粉
否则为原始粉丝
仅当有特殊属性时才有此项 | + +`list`中的对象中的`official_verify`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------ | ----------------------------------------- | +| type | num | 用户认证类型 | -1:无
0:UP 主认证
1:机构认证 | +| desc | str | 用户认证信息 | 无为空 | + +`list`中的对象中的`vip`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ------------ | ----------------------------------------------- | +| vipType | num | 会员类型 | 0:无
1:月度大会员
2:年度以上大会员 | +| vipDueDate | num | 会员到期时间 | 时间戳 毫秒 | +| dueRemark | str | (?) | | +| accessStatus | num | (?) | | +| vipStatus | num | 大会员状态 | 0:无
1:有 | +| vipStatusWarn | str | (?) | | +| themeType | num | (?) | | +| label | obj | (?) | | + +`vip`中的`label`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | ---- | +| path | str | (?) | | + +### 查询用户粉丝明细(新) + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +本接口只有登录、标头 `referer` 为 `bilibili.com` 下的子域名、UA 不含 `python` 时才会返回列表 + +- 当请求参数 `from=main` 且目标用户为自己时,返回列表按照**智能推荐算法**排序,**仅返回前 1000 名粉丝**,且返回的列表中不含 `mtime` 字段 +- 否则,返回列表按关注时间排序,此时**当前用户仅返回前 1000 名粉丝,其他用户仅返回前 100 名粉丝**,若继续往后查询则返回空列表 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| -------------- | ---- | ---------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | +| vmid | num | 目标用户 mid | 必要 | | +| ps | num | 每页项数 | 非必要 | 默认为 50 | +| pn | num | 页码 | 非必要 | 默认为 1 | +| offset | str | 偏移量 | 非必要 | 从上次请求的响应数据中的 `data.offset` 获取
此项有效且不为 `rcmd` 时会从此偏移量开始返回粉丝列表,忽略参数 `pn` | +| last_access_ts | num | 上次访问粉丝列表的时间 | 非必要 | 秒级时间戳,从[获取自己粉丝列表的未读状态](#获取自己粉丝列表的未读状态)接口获取
当按照**智能推荐算法**排序时,会优先展示此时间后关注的粉丝 | +| from | str | 请求来源 | 非必要 | 当为 `main` 且目标用户为自己时,粉丝列表按照**智能推荐算法**排序,此时响应数据中的 `data.list` 的成员中的 `rec_reason` 与 `track_id` 为非空 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------------------------------------------------------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-352:请求被拦截
-400:请求错误
22118:由于该用户隐私设置,粉丝列表不可见 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | -------- | ----------------------------------------------------------------------------------------------------- | +| list | array | 明细列表 | | +| offset | str | 偏移量 | 供下次请求使用
普通:`{列表最后的粉丝的 mtime}:{列表最后的粉丝的 mid}`
智能推荐算法:`rcmd` | +| re_version | num | (?) | | +| total | num | 粉丝总数 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | ------------ | ---------------------------------- | +| 0 | obj | 粉丝 1 | 详见 [关系列表对象](#关系列表对象) | +| n | obj | 粉丝 (n+1) | | +| …… | obj | …… | …… | + +**示例:** + +获取用户`mid=293793435`的粉丝明细 + +```shell +curl -G 'https://api.bilibili.com/x/relation/fans' \ + --data-urlencode 'vmid=293793435' \ + --data-urlencode 'ps=2' \ + --data-urlencode 'pn=1' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "mid": 289796932, + "attribute": 0, + "mtime": 1746199088, + "tag": null, + "special": 0, + "contract_info": {}, + "uname": "Astlinga_星灵", + "face": "https://i1.hdslb.com/bfs/face/005264524d05c0b8c132acc3ee88bb839351025b.jpg", + "sign": "", + "face_nft": 0, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1734278400000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "avatar_subscript_url": "" + }, + "name_render": {}, + "nft_icon": "", + "rec_reason": "", + "track_id": "", + "follow_time": "" + }, + { + "mid": 3494375621396821, + "attribute": 0, + "mtime": 1746098997, + "tag": null, + "special": 0, + "contract_info": {}, + "uname": "JSRCode", + "face": "https://i1.hdslb.com/bfs/face/f6c74700c72d27ae224c5311634b4a3770e3cdcf.jpg", + "sign": "一个喜欢码代码的高中牲", + "face_nft": 0, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 0, + "vipDueDate": 0, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "avatar_subscript_url": "" + }, + "name_render": {}, + "nft_icon": "", + "rec_reason": "", + "track_id": "", + "follow_time": "" + } + ], + "offset": "1746098997:3494375621396821", + "re_version": 0, + "total": 3776 + } +} +``` + +
+ +### 查询用户粉丝明细(旧) + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +本接口只有登录、标头 `referer` 为 `bilibili.com` 下的子域名、UA 不含 `python` 时才会返回列表 + +**本接口仅可返回前 1000 名粉丝**,若继续往后查询则返回空列表 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | ------------------------------------ | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| vmid | num | 目标用户 mid | 必要 | | +| ps | num | 每页项数 | 非必要 | 默认为 50 | +| pn | num | 页码 | 非必要 | 默认为 1
仅可查看前 1000 名粉丝 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------------------------------------------------------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-352:请求被拦截
-400:请求错误
22118:由于该用户隐私设置,粉丝列表不可见 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | -------- | ---- | +| list | array | 明细列表 | | +| re_version | num | (?) | | +| total | num | 粉丝总数 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | ------------ | ---------------------------------- | +| 0 | obj | 粉丝 1 | 详见 [关系列表对象](#关系列表对象) | +| n | obj | 粉丝 (n+1) | 按照添加顺序排列 | +| …… | obj | …… | …… | + +**示例:** + +获取用户`mid=293793435`的粉丝明细 + +```shell +curl -G 'https://api.bilibili.com/x/relation/followers' \ + --data-urlencode 'vmid=293793435' \ + --data-urlencode 'ps=2' \ + --data-urlencode 'pn=1' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "mid": 289796932, + "attribute": 0, + "mtime": 1746199088, + "tag": null, + "special": 0, + "contract_info": {}, + "uname": "Astlinga_星灵", + "face": "https://i1.hdslb.com/bfs/face/005264524d05c0b8c132acc3ee88bb839351025b.jpg", + "sign": "", + "face_nft": 0, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1734278400000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "avatar_subscript_url": "" + }, + "name_render": {}, + "nft_icon": "", + "rec_reason": "", + "track_id": "", + "follow_time": "" + }, + { + "mid": 3494375621396821, + "attribute": 0, + "mtime": 1746098997, + "tag": null, + "special": 0, + "contract_info": {}, + "uname": "JSRCode", + "face": "https://i1.hdslb.com/bfs/face/f6c74700c72d27ae224c5311634b4a3770e3cdcf.jpg", + "sign": "一个喜欢码代码的高中牲", + "face_nft": 0, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 0, + "vipDueDate": 0, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "avatar_subscript_url": "" + }, + "name_render": {}, + "nft_icon": "", + "rec_reason": "", + "track_id": "", + "follow_time": "" + } + ], + "re_version": 0, + "total": 3776 + } +} +``` + +
+ +### 查询用户粉丝明细 + +> + +*请求方式:GET* + +认证方式:无 + +返回目标用户前100个粉丝 + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------ | ------ | --------- | +| vmid | num | 目标用户 mid | 必要 | | +| ps | num | 每页项数 | 非必要 | 默认为 20 | +| pn | num | 页码 | 非必要 | 默认为 1 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | -------- | +| code | num | 返回值 | | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | +| ts | num | 时间戳 | | + +`data.list`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------- | ---- | +| mid | num | 用户mid | | +| uname | str | 用户名 | | +| face | str | 头像 | | +| attribute | num | | | + + +**示例:** + +```shell +curl 'https://line3-h5-mobile-api.biligame.com/game/center/h5/user/relationship/follower_list?vmid=504140200&pn=5&ps=21' +``` +
+查看响应示例: + +```json +{ + "code": 0, + "data": { + "list": [ + { + "mid": "3493078644034173", + "attribute": 0, + "uname": "雨天下小雪啦", + "face": "//i0.hdslb.com/bfs/face/28ad110baa58db9265eca657fcba501589981555.jpg", + "attestation_display": { + "type": 0, + "desc": "" + } + }, + { + "mid": "1356049904", + "attribute": 0, + "uname": "一埋子", + "face": "//i2.hdslb.com/bfs/face/84356fd3b183284bc11b011b676432badb4096bf.jpg", + "attestation_display": { + "type": 0, + "desc": "" + } + }, + ] + }, + "ts": 1748829553371, + "request_id": "0684785391344bdc85e4e701bed41b1c" +} +``` +
+ +### 获取自己粉丝列表的未读状态 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +调用此接口后会重置未读状态 + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | -------------------------- | ---------------------------------- | +| count | num | 自上次访问后新增的粉丝个数 | | +| time | num | 上次访问粉丝列表时间 | 秒级时间戳;当没有新增粉丝时为 `0` | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/relation/followers/unread/count' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "count": 55, + "time": 1743677191 + } +} +``` + +
+ +### 查询用户关注明细 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +本接口只有登录、标头 `referer` 为 `bilibili.com` 下的子域名、UA 不含 `python` 时才会返回列表 + +登录可看当前用户全部,其他用户仅可查看前 100 个,访问超过 100 个时返回空列表(但 `code` 值为 `0`) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | ----------------------------------------------------------------------------------- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| vmid | num | 目标用户 mid | 必要 | | +| order_type | str | 排序方式 | 非必要 | 当目标用户为自己时有效
按照关注顺序排列:留空
按照最常访问排列:attention | +| ps | num | 每页项数 | 非必要 | 默认为 50 | +| pn | num | 页码 | 非必要 | 默认为 1
其他用户仅可查看前 100 个 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-352:请求被拦截
-400:请求错误
22115:用户已设置隐私,无法查看 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | -------- | ---- | +| list | array | 明细列表 | | +| re_version | num | (?) | | +| total | num | 关注总数 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | ----------- | -------------------------------- | +| 0 | obj | 关注1 | 见 [关系列表对象](#关系列表对象) | +| n | obj | 关注(n+1) | 按照添加顺序排列 | +| …… | obj | …… | …… | + +**示例:** + +获取用户`mid=293793435`的关注明细,按照关注顺序 + +```shell +curl -G 'https://api.bilibili.com/x/relation/followings' \ + --data-urlencode 'vmid=293793435' \ + --data-urlencode 'order_type=' \ + --data-urlencode 'ps=2' \ + --data-urlencode 'pn=1' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [{ + "mid": 14082, + "attribute": 2, + "mtime": 1584271945, + "tag": null, + "special": 0, + "contract_info": {}, + "uname": "山新", + "face": "https://i0.hdslb.com/bfs/face/74c82caee6d9eb623e56161ea8ed6d68afabfeae.jpg", + "sign": "都说了是天依爹地,不是妈咪。\r私信有点多回复不过来~商业合作啥的请移步Weibo私信@山新 哦哦哦~", + "official_verify": { + "type": 0, + "desc": "配音演员、声优。洛天依声源提供者。" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1601654400000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299", + "avatar_subscript_url": "" + }, + "name_render": {}, + "nft_icon": "", + "rec_reason": "", + "track_id": "", + "follow_time": "" + }, { + "mid": 420831218, + "attribute": 2, + "mtime": 1584208169, + "tag": [207542], + "special": 0, + "contract_info": {}, + "uname": "支付宝Alipay", + "face": "https://i2.hdslb.com/bfs/face/aaf18aeb2d9822e28a590bd8d878572ca8c59e04.jpg", + "sign": "阿支来了,关注点赞转发投币四连走起!", + "official_verify": { + "type": 1, + "desc": "支付宝官方账号" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1585065600000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299", + "avatar_subscript_url": "" + }, + "name_render": {}, + "nft_icon": "", + "rec_reason": "", + "track_id": "", + "follow_time": "" + }], + "re_version": 0, + "total": 1028 + } +} +``` + +
+ +### 查询用户关注明细2 + +> + +*请求方式:GET* + +仅可查看前 5 页,对于已设置可见性隐私关注列表的用户,响应数据中的 `data.list` 为 null,且 `data.total` 为0 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------ | ------ | ----------------------------------------------------------- | +| vmid | num | 目标用户 mid | 必要 | | +| order | str | 排序方式 | 非必要 | 按照降序排列:desc
按照升序排列:asc
默认降序排列 | +| ps | num | 每页项数 | 非必要 | 默认为 50 | +| pn | num | 页码 | 非必要 | 默认为 1
仅可查看前 5 页 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
22007:访问超过 5 页 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | -------- | ---- | +| list | array | 明细列表 | | +| re_version | num | (?) | | +| total | num | 关注总数 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | ----------- | ------------------------------------------------- | +| 0 | obj | 关注 1 | 与 [关系列表对象](#关系列表对象) 数据结构**不同** | +| n | obj | 关注(n+1) | 按照添加顺序排列 | +| …… | obj | …… | …… | + +数组`list`中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ------------------------------------------- | ------------ | --------------------------------------- | +| mid | num | 用户 mid | | +| attribute | num | 关注属性 | 0:未关注
2:已关注
6:已互粉 | +| mtime | num | 关注对方时间 | 时间戳
互关后刷新 | +| tag | 默认分组:null
存在至少一个分组:array | 分组 id | | +| special | num | 特别关注标志 | 0:否
1:是 | +| uname | str | 用户昵称 | | +| face | str | 用户头像 url | | +| sign | str | 用户签名 | | +| official_verify | obj | 认证信息 | | +| vip | obj | 会员信息 | | +| live | num | 是否直播 | 0:未直播
1:直播中 | + +数组`list`中的对象中的`tag`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | ------------------------ | ---- | +| 0 | num | 位于分组 1 的分组 id | | +| n | num | 位于分组(n+1)的分组 id | | +| …… | num | …… | …… | + +`list`中的对象中的`official_verify`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------ | ---------------------------------------- | +| type | num | 用户认证类型 | -1:无
0:UP主认证
1:机构认证 | +| desc | str | 用户认证信息 | 无为空 | + +`list`中的对象中的`vip`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ------------ | ----------------------------------------------- | +| vipType | num | 会员类型 | 0:无
1:月度大会员
2:年度以上大会员 | +| vipDueDate | num | 会员到期时间 | 时间戳 毫秒 | +| dueRemark | str | (?) | | +| accessStatus | num | (?) | | +| vipStatus | num | 大会员状态 | 0:无
1:有 | +| vipStatusWarn | str | (?) | | +| themeType | num | (?) | | +| label | obj | (?) | | + +`vip`中的`label`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------ | ---- | +| path | str | (?) | | + +**示例:** + +获取用户`mid=293793435`的关注明细,按照关注顺序 + +```shell +curl -G 'https://app.biliapi.net/x/v2/relation/followings' \ + --data-urlencode 'vmid=293793435' \ + --data-urlencode 'ps=2' \ + --data-urlencode 'pn=1' \ +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [{ + "mid": 14082, + "attribute": 2, + "mtime": 1584271945, + "tag": null, + "special": 0, + "uname": "山新", + "face": "https://i0.hdslb.com/bfs/face/74c82caee6d9eb623e56161ea8ed6d68afabfeae.jpg", + "sign": "都说了是天依爹地,不是妈咪。\r私信有点多回复不过来~商业合作啥的请移步Weibo私信@山新 哦哦哦~", + "official_verify": { + "type": 0, + "desc": "配音演员、声优。洛天依声源提供者。" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1601654400000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "live": 0 + }, { + "mid": 420831218, + "attribute": 2, + "mtime": 1584208169, + "tag": [207542], + "special": 0, + "uname": "支付宝Alipay", + "face": "https://i2.hdslb.com/bfs/face/aaf18aeb2d9822e28a590bd8d878572ca8c59e04.jpg", + "sign": "阿支来了,关注点赞转发投币四连走起!", + "official_verify": { + "type": 1, + "desc": "支付宝官方账号" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1585065600000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + }, + "live": 0 + }], + "re_version": 3228575555, + "total": 699 + } +} +``` + +
+ +### 查询用户关注明细3 + +> + +*请求方式:GET* + +对于设置了可见性隐私关注列表的用户会返回空列表 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | -------- | +| vmid | num | 目标用户mid | 必要 | | +| ps | num | 每页项数 | 非必要 | 默认为20 | +| pn | num | 页码 | 非必要 | 默认为1 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ---------- | --------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 成功时无此项 | +| data | obj | 信息本体 | 失败时无此项 | +| ts | num | 当前时间戳 | 单位为毫秒 | +| request_id | str | 请求id | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ----- | -------- | ---- | +| list | array | 明细列表 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | --------- | ---------------- | +| 0 | obj | 关注1 | | +| n | obj | 关注(n+1) | 按照关注顺序排列 | +| …… | obj | …… | …… | + +数组`list`中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ---- | ------------------------------ | --------------------------------------- | +| mid | str | 用户mid | | +| attribute | num | 对方对于**目标用户**的关注属性 | 0:未关注
2:已关注
6:已互粉 | +| uname | str | 用户昵称 | | +| face | str | 用户头像url | | +| attention_display | obj | 用户认证信息 | | + +`attention_display`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ------------------------------------------------------------ | +| type | num | 是否认证 | 0:无
1:UP主专业认证
2:UP主认证
3:机构认证 | +| desc | str | 认证信息 | | + +**示例:** + +获取用户`mid=293793435`的关注明细 + +```shell +curl -G 'https://line3-h5-mobile-api.biligame.com/game/center/h5/user/relationship/following_list' \ + --data-urlencode 'vmid=293793435' \ + --data-urlencode 'ps=2' \ + --data-urlencode 'pn=1' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "data": { + "list": [{ + "mid": "14082", + "attribute": 2, + "uname": "山新", + "face": "https://i0.hdslb.com/bfs/face/74c82caee6d9eb623e56161ea8ed6d68afabfeae.jpg", + "attestation_display": { "type": 0, "desc": "" } + }, { + "mid": "420831218", + "attribute": 2, + "uname": "支付宝Alipay", + "face": "https://i2.hdslb.com/bfs/face/aaf18aeb2d9822e28a590bd8d878572ca8c59e04.jpg", + "attestation_display": { "type": 3, "desc": "bilibili机构认证:支付宝官方账号" } + }] + }, + "ts": 1677410818395, + "request_id": "d9d541b9f2d24e21821e2d6d2d16c17d" +} +``` + +
+ +### 搜索关注明细 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | --------- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| vmid | str | 目标用户 mid | 必要 | | +| name | str | 搜索关键词 | 非必要 | | +| ps | num | 每页项数 | 非必要 | 默认为 50 | +| pn | num | 页码 | 非必要 | 默认为 1 | + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
22007:访问超过 5 页 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | -------- | ---- | +| list | array | 明细列表 | | +| re_version | num | (?) | | +| total | num | 关注总数 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | --------------- | -------------------------------- | +| 0 | obj | 匹配项目 1 | 见 [关系列表对象](#关系列表对象) | +| n | obj | 匹配项目(n+1) | 按照添加顺序排列 | +| …… | obj | …… | …… | + +**示例:** + +搜索我的关注列表中关键词`warma` + +```shell +curl -G 'https://api.bilibili.com/x/relation/followings/search' \ + --data-urlencode 'vmid=293793435' \ + --data-urlencode 'name=warma' \ + --data-urlencode 'ps=2' \ + --data-urlencode 'pn=1' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "mid": 53456, + "attribute": 2, + "mtime": 1586415053, + "tag": [-10], + "special": 1, + "uname": "Warma", + "face": "https://i2.hdslb.com/bfs/face/c1bbee6d255f1e7fc434e9930f0f288c8b24293a.jpg", + "sign": "我是沃玛,做点傻开心的视频。日常发在微博:@_warma_ ", + "official_verify": { + "type": 0, + "desc": "bilibili 知名UP主" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1637424000000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + } + } + ], + "total": 1 + } +} +``` + +
+ +### 查询共同关注明细 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | --------- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| vmid | num | 目标用户 mid | 必要 | | +| ps | num | 每页项数 | 非必要 | 默认为 50 | +| pn | num | 页码 | 非必要 | 默认为 1 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | -------- | ---- | +| list | array | 明细列表 | | +| re_version | num | (?) | | +| total | num | 关注总数 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | --------------- | -------------------------------- | +| 0 | obj | 共同关注 1 | 见 [关系列表对象](#关系列表对象) | +| n | obj | 共同关注(n+1) | 按照添加顺序排列 | +| …… | obj | …… | …… | + +**示例:** + +获取自己与用户`mid=2`的共同关注明细 + +```shell +curl -G 'https://api.bilibili.com/x/relation/same/followings' \ + --data-urlencode 'vmid=2' \ + --data-urlencode 'ps=2' \ + --data-urlencode 'pn=1' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "mid": 116683, + "attribute": 2, + "mtime": 1564627532, + "tag": null, + "special": 0, + "uname": "=咬人猫=", + "face": "https://i0.hdslb.com/bfs/face/8fad84a4470f3d894d8f0dc95555ab8f2cb10a83.jpg", + "sign": "面瘫女仆酱~小粗腿~事业线什么的!!吐槽你就输了!喵~", + "official_verify": { + "type": 0, + "desc": "bilibili 2019百大UP主、高能联盟成员" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1618934400000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + } + }, + { + "mid": 517717593, + "attribute": 2, + "mtime": 1592126052, + "tag": [207542], + "special": 0, + "uname": "上海爱丽丝幻乐团", + "face": "https://i0.hdslb.com/bfs/face/851a9191cbe93e66304d7577c0f6f83834e52109.jpg", + "sign": "日本同人社团 上海爱丽丝幻乐团", + "official_verify": { + "type": 0, + "desc": "上海爱丽丝幻乐团官方账号" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1593792000000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + } + } + ], + "re_version": 2498273968, + "total": 38 + } +} +``` + +
+ +### 查询悄悄关注明细 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | ---- | +| access_key | str | APP 登录 Token | APP 方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | -------- | ---- | +| list | array | 明细列表 | | +| re_version | num | (?) | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | --------------- | -------------------------------- | +| 0 | obj | 悄悄关注 1 | 见 [关系列表对象](#关系列表对象) | +| n | obj | 悄悄关注(n+1) | 按照操作顺序排列 | +| …… | obj | …… | …… | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/relation/whispers' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "mid": 178429408, + "attribute": 1, + "mtime": 1605972105, + "tag": null, + "special": 0, + "uname": "老弟一号", + "face": "https://i2.hdslb.com/bfs/face/21426275f3d3149b96b88783275205ba574c09e3.jpg", + "sign": "萌新硬件玩家,前垃圾佬~(◦˙▽˙◦某宝店 老弟一号 粉丝群679540094商务合作V13869651328", + "official_verify": { + "type": 0, + "desc": "知识领域优质UP主" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1632499200000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + } + } + ], + "re_version": 2137574562 + } +} +``` + +
+ +### 查询互相关注明细 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +查询与自己互关的用户明细,可看全部 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | ---- | +| access_key | str | APP 登录 Token | APP 方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | -------- | ---- | +| list | array | 明细列表 | | +| re_version | num | (?) | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | ----------- | -------------------------------- | +| 0 | obj | 互关 1 | 见 [关系列表对象](#关系列表对象) | +| n | obj | 互关(n+1) | 按照添加顺序排列 | +| …… | obj | …… | …… | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/relation/friends' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```jsonc +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "mid": 596000, + "attribute": 6, + "mtime": 1685110154, + "tag": null, + "special": 0, + "uname": "椛椛在睡觉", + "face": "https://i2.hdslb.com/bfs/face/365c1ef3b2a3afe21d6832796338fad5119b2592.jpg", + "sign": "欢迎来找椛椛玩~ https://blogs.momiji-jin.com/", + "face_nft": 0, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1702742400000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299", + "avatar_subscript_url": "" + }, + "nft_icon": "", + "rec_reason": "", + "track_id": "" + }, + { + "mid": 24022863, + "attribute": 6, + "mtime": 1685026230, + "tag": [-10], + "special": 1, + "uname": "黄禄轩电脑专用账号", + "face": "https://i0.hdslb.com/bfs/face/a70ec7d2a3822980a915ef4b30371af0cbc79132.jpg", + "sign": "若要私信,请私信「黄禄轩手机专用账号」http://space.bilibili.com/17640193/,群:410311648", + "face_nft": 0, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1686412800000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299", + "avatar_subscript_url": "" + }, + "nft_icon": "", + "rec_reason": "", + "track_id": "" + }, + { + "mid": 85438718, + "attribute": 6, + "mtime": 1684759843, + "tag": [194110], + "special": 0, + "uname": "忘忧北萱草Official", + "face": "https://i2.hdslb.com/bfs/face/68d8cba01aab907dbb2cf2e17074f20947156237.jpg", + "sign": "现已加入 OrangeFire 豪华套餐!", + "face_nft": 0, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 2, + "vipDueDate": 1691683200000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "年度大会员", + "label_theme": "annual_vip", + "text_color": "#FFFFFF", + "bg_style": 1, + "bg_color": "#FB7299", + "border_color": "" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299", + "avatar_subscript_url": "" + }, + "nft_icon": "", + "rec_reason": "", + "track_id": "" + }, + { + "mid": 41620134, + "attribute": 6, + "mtime": 1684759649, + "tag": null, + "special": 0, + "uname": "Tiggy_Chan", + "face": "https://i0.hdslb.com/bfs/face/8c8d9f43eda207f8cb8503bfdf6cc3802a1cd6c1.jpg", + "sign": "此号只发科技类视频,娱乐类转至:虎子酱233", + "face_nft": 0, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1669219200000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "avatar_subscript_url": "" + }, + "nft_icon": "", + "rec_reason": "", + "track_id": "" + }, + // …… + ], + "re_version": 0 + } +} +``` + +
+ +### 查询黑名单明细 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | --------------------------------------- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| ps | num | 每页项数 | 非必要 | 默认为 50,且最多为50,大于50则按50输出 | +| pn | num | 页码 | 非必要 | 默认为 1 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | ------------ | ---- | +| list | array | 明细列表 | | +| re_version | num | (?) | | +| total | num | 黑名单总计数 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | -------------- | -------------------------------- | +| 0 | obj | 黑名单 1 | 见 [关系列表对象](#关系列表对象) | +| n | obj | 黑名单 (n+1) | 按照添加顺序排列 | +| …… | obj | …… | …… | + +**示例:** + +获取黑名单明细 + +```shell +curl -G 'https://api.bilibili.com/x/relation/blacks' \ + --data-urlencode 'ps=2' \ + --data-urlencode 'pn=1' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "mid": 22179720, + "attribute": 128, + "mtime": 1603032789, + "tag": null, + "special": 0, + "uname": "咩2016", + "face": "https://i0.hdslb.com/bfs/face/41fe435a7e62eae605a5908652f32f3afff2ae74.jpg", + "sign": "", + "official_verify": { + "type": 0, + "desc": "" + }, + "vip": { + "vipType": 0, + "vipDueDate": 0, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + } + }, + { + "mid": 16174624, + "attribute": 128, + "mtime": 1603026420, + "tag": null, + "special": 0, + "uname": "其实死亡没有那么痛", + "face": "https://i2.hdslb.com/bfs/face/79257f5a2e7194a71337ccca5927afba7706d316.jpg", + "sign": "等我,我马上就来", + "official_verify": { + "type": 0, + "desc": "" + }, + "vip": { + "vipType": 0, + "vipDueDate": 0, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + } + } + ], + "re_version": 897205356, + "total": 2 + } +} +``` + +
+ +## 操作关系 + + + +### 操作用户关系 + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或 APP + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| fid | num | 目标用户mid | 必要 | | +| act | num | 操作代码 | 必要 | **操作代码见下表** | +| re_src | num | 关注来源代码 | 非必要 | 包月充电:1
个人空间:11
视频:14
评论区:15
视频播放器结束页面:17
H5推荐关注:58
H5关注列表:106
H5粉丝列表:107
专栏:115
私信:118
搜索:120
视频播放器左上角关注按钮:164
H5共同关注:167
创作激励计划:192
活动页面:222
联合投稿视频:229
消息中心点赞详情:235
视频播放器关注弹幕:245 | +| csrf | str | CSRF Token(位于 Cookie) | Cookie 方式必要 | | + +操作代码`act`: + +| 代码 | 含义 | 备注 | +| ---- | ------------ | ---------------------------------------------------- | +| 1 | 关注 | 无法对已注销或不存在的用户进行此操作 | +| 2 | 取关 | | +| 3 | 悄悄关注 | **现已下线**,使用本操作代码请求接口会提示“请求错误” | +| 4 | 取消悄悄关注 | | +| 5 | 拉黑 | 无法对已注销或不存在的用户进行此操作 | +| 6 | 取消拉黑 | | +| 7 | 踢出粉丝 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-102:账号被封停
-111:csrf校验失败
-400:请求错误
22001:不能对自己进行此操作
22002:因对方隐私设置,你还不能关注
22003:关注失败,请将该用户移除黑名单之后再试
22008:黑名单达到上限
22009:关注失败,已达关注上限
22013:账号已注销,无法完成操作
22014:已经关注用户,无法重复关注
22120:重复加入黑名单
40061:用户不存在 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +关注`mid=14082`的用户 + +```shell +curl 'https://api.bilibili.com/x/relation/modify' \ + --data-urlencode 'fid=14082' \ + --data-urlencode 'act=1' \ + --data-urlencode 're_src=11' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
+ +### 批量操作用户关系 + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或 APP + +此接口只支持关注和拉黑操作 + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------- | --------------- | ----------------------------------------------------------- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| fids | nums | 目标用户 mid 列表 | 必要 | 每个成员之间用 `,` 间隔,最多 50 个成员,不能包含自己的 mid | +| act | num | 操作代码 | 必要 | 同上
仅可为 1 或 5,故只能进行批量关注和拉黑 | +| re_src | num | 关注来源代码 | 非必要 | 同上 | +| csrf | str | CSRF Token(位于 Cookie) | Cookie 方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | -------------------------------------------------------------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-102:账号被封停
-111:csrf校验失败
-400:请求错误
22003:用户位于黑名单 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----- | ------------------- | ---- | +| failed_fids | array | 操作失败的 mid 列表 | | + +`data`中的`failed_fids`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | --------------------- | ---- | +| 0 | num | 操作失败的 mid 1 | | +| n | num | 操作失败的 mid(n+1) | | +| …… | num | …… | …… | + +**示例:** + +批量关注`mid=1,2,3,4,5`的用户 + +```shell +curl 'https://api.bilibili.com/x/relation/batch/modify' \ + --data-urlencode 'fid=1,2,3,4,5' \ + --data-urlencode 'act=1' \ + --data-urlencode 're_src=11' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "failed_fids": [] + } +} +``` + +
+ +## 查询关系属性 + +### 关系属性对象 + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ------------------------------------------- | ------------ | --------------------------------------------------------------------------------------- | +| mid | num | 目标用户 mid | | +| attribute | num | 关系属性 | 0:未关注
~~1:悄悄关注(已弃用)~~
2:已关注
6:已互粉
128:已拉黑 | +| mtime | num | 关注对方时间 | 时间戳
未关注为 0 | +| tag | 默认分组:null
存在至少一个分组:array | 分组 id | | +| special | num | 特别关注标志 | 0:否
1:是 | + +`tag`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | --------------------- | ---- | +| 0 | num | 位于分组 1 的分组 | | +| n | num | 位于分组(n+1)的分组 | | +| …… | num | …… | …… | + +### 查询用户与自己关系(仅关注) + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | ---- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| fid | num | 目标用户 mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | 详见 [关系属性对象](#关系属性对象) | + +**示例:** + +可得对于`mid=258150656`的用户,在`2018/10/28 0:51:41`时关注,且设为特别关注,并位于为`-10`分组中 + +```shell +curl -G 'https://api.bilibili.com/x/relation' \ + --data-urlencode 'fid=258150656' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "mid": 258150656, + "attribute": 2, + "mtime": 1540659101, + "tag": [-10], + "special": 1 + } +} +``` + +
+ +### 查询用户与自己关系(互相关系) + +> 接口1: + +> 接口2: + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +鉴权方式(仅接口1):[Wbi 签名](../misc/sign/wbi.md) + +~~该接口的旧版 API :~~(已废弃,不建议使用) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | ------------------------------------ | +| access_key | str | APP登录Token | APP方式必要 | | +| mid | num | 目标用户mid | 必要 | | +| w_rid | str | Wbi 签名 | 仅接口1必要 | 详见 [Wbi 签名](../misc/sign/wbi.md) | +| wts | num | 当前时间戳 | 仅接口1必要 | 详见 [Wbi 签名](../misc/sign/wbi.md) | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | -------------------------- | ---------------------------------- | +| relation | obj | 目标用户对于当前用户的关系 | 详见 [关系属性对象](#关系属性对象) | +| be_relation | obj | 当前用户对于目标用户的关系 | 详见 [关系属性对象](#关系属性对象) | + +**示例:** + +可得对于`mid=15858903`的用户,在`2019/1/24 14:24:19`时关注了对方,且互相关注,自己将对方特别关注,并同时位于为`-10`和`194110`的分组中,对方也将自己设为特别关注,并同时位于为`-10`和`56502`的分组中(虽然我看不到) + +Wbi 签名的 `wts`、`w_rid`生成方式详见 [Wbi 签名](../misc/sign/wbi.md) 文档 + +```shell +curl -G 'https://api.bilibili.com/x/space/acc/relation' \ + --data-urlencode 'mid=15858903' \ + --data-urlencode 'wts=1686015899' \ + --data-urlencode 'w_rid=e10a3c566c9be80a7cebe7bcdf262588' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "relation": { + "mid": 15858903, + "attribute": 6, + "mtime": 1548311059, + "tag": [-10, 194110, 248468], + "special": 1 + }, + "be_relation": { + "mid": 293793435, + "attribute": 6, + "mtime": 1548311059, + "tag": [56502, -10], + "special": 1 + } + } +} +``` + +
+ +### 批量查询用户与自己关系 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | ----------------------------- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| fids | nums | 目标用户 mid | 必要 | 每个之间用`,`间隔,无成员限制 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ---------- | ---------------------------------- | +| {用户mid} | obj | 关注的用户 | 详见 [关系属性对象](#关系属性对象) | +| …… | obj | …… | 下同 | + +**示例:** + +批量查询`mid=1,2,3,4,5`的关系 + +```shell +curl -G 'https://api.bilibili.com/x/relation/relations' \ + --data-urlencode 'fid=258150656' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "1": { + "mid": 1, + "attribute": 2, + "mtime": 1601654227, + "tag": null, + "special": 0 + }, + "2": { + "mid": 2, + "attribute": 2, + "mtime": 1601654225, + "tag": null, + "special": 0 + } + } +} +``` + +
+ +## 关注分组相关 + +分组 id 特殊值: + +| id | 含义 | +| --- | -------- | +| 0 | 默认分组 | +| -10 | 特别关心 | + +### 查询关注分组列表 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | ---- | +| access_key | str | APP 登录 Token | APP 方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | array | 分组列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | ----------- | ---- | +| 0 | obj | 分组 1 | | +| n | obj | 分组(n+1) | | +| …… | num | …… | …… | + +数组`data`中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ---------- | ------------------------------ | +| tagid | num | 分组 id | -10:特别关注
0:默认分组 | +| name | str | 分组名称 | | +| count | num | 分组成员数 | | +| tip | str | 提示信息 | | + +**示例:** + +查询所有的分组的名字以及id + +```shell +curl 'https://api.bilibili.com/x/relation/tags' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```jsonc +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "tagid": -10, + "name": "特别关注", + "count": 19, + "tip": "第一时间收到该分组下用户更新稿件的通知" + }, + { + "tagid": 0, + "name": "默认分组", + "count": 340, + "tip": "" + }, + { + "tagid": 194110, + "name": "基友们", + "count": 127, + "tip": "" + }, + { + "tagid": 194111, + "name": "我的同学", + "count": 22, + "tip": "" + }, + // …… + ] +} +``` + +
+ +### 查询关注分组明细 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +只可查询属于自己的分组 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | ------------------------------------------------------- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| tagid | num | 分组 id | 必要 | 0:默认分组
-10:特别关注
-20:所有 | +| order_type | str | 排序方式 | 非必要 | 按照关注顺序排列:留空
按照最常访问排列:attention | +| ps | num | 每页项数 | 非必要 | 默认为 20 | +| pn | num | 页数 | 非必要 | 默认为1 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | -------------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误
22104:该分组不存在 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | array | 成员列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | --------------- | --------------------------------------- | +| 0 | obj | 成员信息 1 | 与[关系列表对象](#关系列表对象)**不同** | +| n | obj | 成员信息(n+1) | 按照添加顺序排序 | +| …… | obj | …… | …… | + +`data` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | --------------- | ----------- | +| mid | num | 用户mid | | +| attribute | num | 关系属性 | 恒为 `0` | +| tag | null | 关注分组id | 恒为 `null` | +| special | num | 是否特别关注 | 恒为 `0` | +| contract_info | obj | 契约计划信息 | | +| uname | str | 用户昵称 | | +| face | str | 用户头像url | | +| sign | str | 用户签名 | | +| face_nft | num | 是否为 NFT 头像 | | +| official_verify | obj | 认证信息 | 具体见下 | +| vip | obj | 会员信息 | | +| live | obj | 直播状态 | 具体见下 | +| nft_icon | str | (?) | | +| rec_reason | str | (?) | | +| track_id | str | (?) | | +| follow_time | str | (?) | | + +`data`中的对象中的`official_verify`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------ | ----------------------------------------- | +| type | num | 用户认证类型 | -1:无
0:UP 主认证
1:机构认证 | +| desc | str | 用户认证信息 | 无为空 | + +`data`中的对象中的`vip`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ------------ | ----------------------------------------------- | +| vipType | num | 会员类型 | 0:无
1:月度大会员
2:年度以上大会员 | +| vipDueDate | num | 会员到期时间 | 时间戳 毫秒 | +| dueRemark | str | (?) | | +| accessStatus | num | (?) | | +| vipStatus | num | 大会员状态 | 0:无
1:有 | +| vipStatusWarn | str | (?) | | +| themeType | num | (?) | | +| label | obj | (?) | | + +`data`数组中的对象中的`live`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | -------- | ------------------------ | +| live_status | num | 直播状态 | 0:未开播
1:已直播 | +| jump_url | str | 直播链接 | | + +`data`数组中的对象中的`contract_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ------------------------------ | ----------------------------------------------------------- | +| is_contract | bool | 目标用户是否为对方的契约者 | 仅当为 `true` 时才有此项 | +| is_contractor | bool | 对方是否为目标用户的契约者 | 仅当为 `true` 时才有此项 | +| ts | num | 对方成为目标用户的契约者的时间 | 秒级时间戳,仅当 `is_contractor` 项的值为 `true` 时才有此项 | +| user_attr | num | 对方作为目标用户的契约者的属性 | 1:老粉
否则为原始粉丝
仅当有特殊属性时才有此项 | + +**示例:** + +以每页2项的方式获取了id为`207542`分组的第1页的粉丝明细,按照关注顺序 + +```shell +curl -G 'https://api.bilibili.com/x/relation/tag' \ + --data-urlencode 'tagid=207542' \ + --data-urlencode 'order_type=' \ + --data-urlencode 'ps=2' \ + --data-urlencode 'pn=1' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [{ + "mid": 420831218, + "uname": "支付宝Alipay", + "face": "https://i2.hdslb.com/bfs/face/aaf18aeb2d9822e28a590bd8d878572ca8c59e04.jpg", + "sign": "阿支来了,关注点赞转发投币四连走起!", + "official_verify": { + "type": 1, + "desc": "支付宝官方账号" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1585065600000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 1, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + } + }, { + "mid": 125086406, + "uname": "MSI微星科技", + "face": "https://i1.hdslb.com/bfs/face/a844760e4e491677615b39399bc761e74c579bb4.jpg", + "sign": "你好,这里是微星显卡官方!专注显卡三十年,欢迎私信咨询或提问MSI", + "official_verify": { + "type": 1, + "desc": "微星科技官方账号" + }, + "vip": { + "vipType": 1, + "vipDueDate": 1540656000000, + "dueRemark": "", + "accessStatus": 0, + "vipStatus": 0, + "vipStatusWarn": "", + "themeType": 0, + "label": { + "path": "" + } + } + }] +} +``` + +
+ +### 查询目标用户所在的分组 + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | ---- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| fid | num | 目标用户 mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | -------- | ---------------------------------- | +| {加入的分组 id} | str | 分组名称 | 若目标用户存在默认分组中,则不显示 | +| …… | str | …… | 下同 | + +**示例:** + +查询用户`mid=319214221`存在的所有分组和名称 + +```shell +curl -G 'https://api.bilibili.com/x/relation/tag/user' \ + --data-urlencode 'fid=319214221' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "-10": "特别关注", + "194111": "我的同学" + } +} +``` + +
+ +### 查询所有特别关注 mid + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或 APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | ---- | +| access_key | str | APP 登录 Token | APP 方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | ----------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | array | 成员列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | -------------- | ---- | +| 0 | num | 成员 1 mid | | +| n | num | 成员(n+1)mid | | +| …… | num | …… | …… | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/relation/tag/special' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + 500716647, + 32832243, + 53456, + 25944552, + 301839556, + 427494870, + 319214221, + 31949159, + 382666849, + 258318451, + 15858903, + 54992199, + 3379951, + 392279807, + 23215368, + 258150656, + 20165629, + 22179720 + ] +} +``` + +
+ +### 创建分组 + + + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或 APP + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------- | --------------- | ------------- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| tag | str | 分组名 | 必要 | 最长 16 字符 | +| csrf | str | CSRF Token(位于 Cookie) | Cookie 方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-111:csrf校验失败
-101:账号未登录
-400:请求错误
22101:分组名称存在不允许的字符
22102:分组数量超过限制
22103:分组名过长
22106:该分组已经存在 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | --------------- | ---- | +| tagid | num | 创建的分组的 id | | + +**示例:** + +创建了名为`测试`的分组,得到id为`216677` + +```shell +curl 'https://api.bilibili.com/x/relation/tag/create' \ + --data-urlencode 'tag=测试' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "tagid": 216677 + } +} +``` + +
+ +### 重命名分组 + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或 APP + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------- | --------------- | ------------ | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| tagid | num | 分组 id | 必要 | | +| name | str | 新名称 | 必要 | 最长 16 字符 | +| csrf | str | CSRF Token(位于 Cookie) | Cookie 方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-111:csrf校验失败
-101:账号未登录
-400:请求错误
22101:分组名称存在不允许的字符
22103:分组名过长
22104:该分组不存在 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | + +**示例:** + +把id为`194112`的分组更名为`膜法师` + +```shell +curl 'https://api.bilibili.com/x/relation/tag/update' \ + --data-urlencode 'tagid=194112' \ + --data-urlencode 'name=膜法师' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
+ +### 删除分组 + + + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或 APP + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------- | --------------- | ---- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| tagid | num | 分组 id | 必要 | | +| csrf | str | CSRF Token(位于 Cookie) | Cookie 方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-111:csrf校验失败
-101:账号未登录
-400:请求错误 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | + +示例: + +删除分组id为`216699`的分组 + +```shell +curl 'https://api.bilibili.com/x/relation/tag/del' \ + --data-urlencode 'tagid=216699' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
+ +### 修改分组成员 + + + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或 APP + +如需删除分组中的成员,请将`tagids`设为 0,即移动至默认分组,而不是取关 + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------- | --------------- | ----------------- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| fids | nums | 目标用户 mid 列表 | 必要 | 每个之间用`,`间隔 | +| tagids | nums | 分组 id 列表 | 必要 | 每个之间用`,`间隔 | +| csrf | str | CSRF Token(位于 Cookie) | Cookie 方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-111:csrf校验失败
-101:账号未登录
-400:请求错误
22104:分组不存在
22105:未关注 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | + +**示例:** + +把关注用户`mid=205631797`同时添加分组关系到id为`-10`和`207542`的分组中 + +```shell +curl 'https://api.bilibili.com/x/relation/tags/addUsers' \ + --data-urlencode 'fids=205631797' \ + --data-urlencode 'tagids=-10,207542' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
+ +### 复制关注到分组 + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或 APP + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------- | --------------- | ----------------- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| fids | nums | 待复制的用户 mid 列表 | 必要 | 每个之间用`,`间隔 | +| tagids | nums | 目标分组 id 列表 | 必要 | 每个之间用`,`间隔 | +| csrf | str | CSRF Token(位于 Cookie) | Cookie 方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-111:csrf校验失败
-101:账号未登录
-400:请求错误
22104:分组不存在
22105:未关注 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | + +**示例:** + +把关注用户`mid=4856007`和`mid=326499679`同时复制到为`231305`的分组id中 + +```shell +curl 'https://api.bilibili.com/x/relation/tags/copyUsers' \ + --data-urlencode 'fids=4856007,326499679' \ + --data-urlencode 'tagids=231305' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
+ +### 移动关注到分组 + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA)或 APP + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------ | ---- | ------------------------- | --------------- | ----------------- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| beforeTagids | nums | 原分组 id 列表 | 必要 | 每个之间用`,`间隔 | +| afterTagids | nums | 新分组 id 列表 | 必要 | 每个之间用`,`间隔 | +| fids | nums | 待移动的用户 mid 列表 | 必要 | 每个之间用`,`间隔 | +| csrf | str | CSRF Token(位于 Cookie) | Cookie 方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-111:csrf校验失败
-101:账号未登录
-400:请求错误
22104:分组不存在
22105:未关注 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | + +**示例:** + +把关注用户`mid=321173469`和`mid=327086920`同时从id为`207542`的分组移动到为`231305`的分组中 + +```shell +curl 'https://api.bilibili.com/x/relation/tags/moveUsers' \ + --data-urlencode 'beforeTagids=207542' \ + --data-urlencode 'afterTagids=23130' \ + --data-urlencode 'fids=321173469,327086920' \ + --data-urlencode 'csrf=xxx' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
diff --git a/bb-api-collect/docs/user/space.md b/bb-api-collect/docs/user/space.md new file mode 100644 index 0000000000..24dd9cb0ce --- /dev/null +++ b/bb-api-collect/docs/user/space.md @@ -0,0 +1,4981 @@ +# 用户空间相关 + +## 主页 + + + +### 置顶视频 + +#### 查询用户置顶视频 + +>https://api.bilibili.com/x/space/top/arc + +*请求方式:GET* + +粉丝在其主页上可见 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| vmid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
53016:没有置顶视频 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ------------------------------ | ------------------------------------------------------------ | +| aid | num | 稿件avid | | +| videos | num | 视频分P总数 | 默认为1 | +| tid | num | 分区tid | | +| tname | str | 子分区名称 | | +| copyright | num | 是否转载 | 1:原创
2:转载
3:未填写 | +| pic | str | 视频封面图片url | | +| title | str | 稿件标题 | | +| pubdate | num | 稿件发布时间 | 时间戳 | +| ctime | num | 用户提交稿件的时间 | 时间戳 | +| desc | str | 视频简介 | | +| 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`对象 | +| dynamic | str | 视频同步发布的的动态的文字内容 | 无为空 | +| cid | num | 视频1P cid | | +| dimension | obj | 视频1P分辨率 | 略,见[获取视频详细信息(web端)](../video/info.md#获取视频详细信息web端)中的`dimension`对象 | +| bvid | str | 稿件bvid | | +| reason | str | 置顶视频备注 | | +| inter_video | bool | 是否为合作视频 | false:否
true:是 | + +**示例:** + +查询用户`mid=23215368`的置顶视频 + +```shell +curl -G 'https://api.bilibili.com/x/space/top/arc' \ +--data-urlencode 'vmid=23215368' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "aid": 37896701, + "videos": 1, + "tid": 28, + "tname": "原创音乐", + "copyright": 1, + "pic": "http://i2.hdslb.com/bfs/archive/cc9e72822d68fffdd0406144f1b5348a13c89652.jpg", + "title": "燃烧吧!铃声!把主流手机铃声编成一首曲子", + "pubdate": 1544469671, + "ctime": 1544469671, + "desc": "各品牌的手机铃声大合奏,毫无违和感~", + "state": 0, + "attribute": 16768, + "duration": 208, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0 + }, + "owner": { + "mid": 23215368, + "name": "Wayjon冰冰酱", + "face": "http://i2.hdslb.com/bfs/face/7c9715f1768191137eb7ebf91918ca0f99532012.jpg" + }, + "stat": { + "aid": 37896701, + "view": 1058237, + "danmaku": 16821, + "reply": 3725, + "favorite": 76888, + "coin": 100694, + "share": 17091, + "now_rank": 0, + "his_rank": 0, + "like": 90521, + "dislike": 0 + }, + "dynamic": "#编曲##FL##纯音乐#", + "cid": 66621209, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "bvid": "BV18t411q7zz", + "reason": "", + "inter_video": false + } +} +``` + +
+ +#### 设置置顶视频 + +> https://api.bilibili.com/x/space/top/arc/set + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------ | ------------ | -------------------------------- | +| aid | num | 置顶目标稿件avid | 必要(可选) | avid与bvid任选一个 | +| bvid | str | 置顶目标稿件bvid | 必要(可选) | avid与bvid任选一个 | +| reason | str | 置顶视频备注 | 非必要 | 置顶备注最大40字符
默认为空 | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-111:csrf校验失败
-304:未修改
-400:请求错误
53014:稿件已失效
53015:备注过长
53017:置顶非自己的稿件 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +置顶视频`av98948772`/`BV1n741127LD` + +avid方式: + +```shell +curl 'https://api.bilibili.com/x/space/top/arc/set' \ +--data-urlencode 'aid=98948772' \ +-b 'SESSDATA=xxx' +``` + +bvid方式: + +```shell +curl 'https://api.bilibili.com/x/space/top/arc/set' \ +--data-urlencode 'bvid=BV1n741127LD' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
+ +#### 取消置顶视频 + +> https://api.bilibili.com/x/space/top/arc/cancel + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------ | ------ | ---- | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-111:csrf校验失败
-400:请求错误(重复取消) | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/space/top/arc/cancel' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
+ +### 代表作视频 + +#### 查询用户代表作视频列表 + +> https://api.bilibili.com/x/space/masterpiece + +*请求方式:GET* + +新访客在其主页上可见 + +最多可以设置3个 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| vmid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | ---------- | --------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | array | 代表作列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------- | ------------------------- | +| 0 | obj | 代表作1 | 无则为空 | +| 1 | obj | 代表作2 | 无则为空 | +| 2 | obj | 代表作3 | 无则为空
最多设置3个 | + +`data`数组中的对象: + +同[查询用户置顶视频](#查询用户置顶视频)中的`data`对象 + +**示例:** + +查询用户`mid=23215368`的代表作视频列表 + +```shell +curl -G 'https://api.bilibili.com/x/space/masterpiece' \ +--data-urlencode 'vmid=23215368' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [{ + "aid": 37896701, + "videos": 1, + "tid": 28, + "tname": "原创音乐", + "copyright": 1, + "pic": "http://i2.hdslb.com/bfs/archive/cc9e72822d68fffdd0406144f1b5348a13c89652.jpg", + "title": "燃烧吧!铃声!把主流手机铃声编成一首曲子", + "pubdate": 1544469671, + "ctime": 1544469671, + "desc": "各品牌的手机铃声大合奏,毫无违和感~", + "state": 0, + "attribute": 16768, + "duration": 208, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0 + }, + "owner": { + "mid": 23215368, + "name": "Wayjon冰冰酱", + "face": "http://i2.hdslb.com/bfs/face/7c9715f1768191137eb7ebf91918ca0f99532012.jpg" + }, + "stat": { + "aid": 37896701, + "view": 1058241, + "danmaku": 16821, + "reply": 3725, + "favorite": 76888, + "coin": 100694, + "share": 17091, + "now_rank": 0, + "his_rank": 0, + "like": 90521, + "dislike": 0 + }, + "dynamic": "#编曲##FL##纯音乐#", + "cid": 66621209, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "bvid": "BV18t411q7zz", + "reason": "", + "inter_video": false + }, { + "aid": 39596658, + "videos": 1, + "tid": 21, + "tname": "日常", + "copyright": 1, + "pic": "http://i2.hdslb.com/bfs/archive/431e51d0e40e3461e1c1b0f59c755ae8843b1adb.jpg", + "title": "MY2018 - 纪念我的2018年", + "pubdate": 1546328392, + "ctime": 1546328392, + "desc": "", + "state": 0, + "attribute": 16768, + "duration": 239, + "mission_id": 10996, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0 + }, + "owner": { + "mid": 23215368, + "name": "Wayjon冰冰酱", + "face": "http://i2.hdslb.com/bfs/face/7c9715f1768191137eb7ebf91918ca0f99532012.jpg" + }, + "stat": { + "aid": 39596658, + "view": 1518, + "danmaku": 16, + "reply": 40, + "favorite": 22, + "coin": 60, + "share": 9, + "now_rank": 0, + "his_rank": 0, + "like": 112, + "dislike": 0 + }, + "dynamic": "#vlog##记录##生活记录#", + "cid": 69561078, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "bvid": "BV1Jt411B7La", + "reason": "", + "inter_video": false + }, { + "aid": 44721369, + "videos": 1, + "tid": 28, + "tname": "原创音乐", + "copyright": 1, + "pic": "http://i0.hdslb.com/bfs/archive/9887797402599c42f74a7624f3db4a92a0ebf465.jpg", + "title": "【铃声串烧系列】华米两开花;中华有为,国之荣耀!把主流手机铃声编成一首曲子", + "pubdate": 1551128445, + "ctime": 1551128445, + "desc": "把主流手机铃声编成一首曲子,这一版用华为的铃声作为主旋律,毫无违和感~伴随着2019mwc的开幕,希望国产厂商能获得全世界的目光,并且将属于中国人的科技自信传递到全世界!", + "state": 0, + "attribute": 16768, + "duration": 174, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0 + }, + "owner": { + "mid": 23215368, + "name": "Wayjon冰冰酱", + "face": "http://i2.hdslb.com/bfs/face/7c9715f1768191137eb7ebf91918ca0f99532012.jpg" + }, + "stat": { + "aid": 44721369, + "view": 306757, + "danmaku": 7713, + "reply": 1520, + "favorite": 17216, + "coin": 16489, + "share": 2917, + "now_rank": 0, + "his_rank": 0, + "like": 21439, + "dislike": 0 + }, + "dynamic": "#铃声##纯音乐##音乐#【铃声串烧】Mix Ringtones!船新的版本来啦!这一版用华为的铃声作为主旋律,毫无违和感~伴随着2019mwc的开幕,希望国产厂商能获得全世界的目光,并且将属于中国人的科技自信传递到全世界!", + "cid": 78290138, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "bvid": "BV1vb411879C", + "reason": "", + "inter_video": false + }] +} +``` + +
+ +#### 添加代表作视频 + +> https://api.bilibili.com/x/space/masterpiece/add + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +代表作上限为3个稿件 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------ | ------------ | -------------------------------- | +| aid | num | 置顶目标稿件avid | 必要(可选) | avid与bvid任选一个 | +| bvid | str | 置顶目标稿件bvid | 必要(可选) | avid与bvid任选一个 | +| reason | str | 代表作备注 | 非必要 | 置顶备注最大40字符
默认为空 | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-111:csrf校验失败
-400:请求错误
53014:稿件已失效
53015:备注过长
53017:置顶非自己的稿件
53019:达到上限
53020:已经存在该稿件 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +添加视频`av94916552`/`BV1ZE411K7ux`到代表作列表 + +avid方式: + +```shell +curl 'https://api.bilibili.com/x/space/masterpiece/add' \ +--data-urlencode 'aid=94916552' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +bvid方式: + +```shell +curl 'https://api.bilibili.com/x/space/masterpiece/add' \ +--data-urlencode 'bvid=BV1ZE411K7ux' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
+ +#### 删除代表作视频 + +> https://api.bilibili.com/x/space/masterpiece/cancel + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------ | ------------ | ------------------ | +| aid | num | 要删除的目标稿件avid | 必要(可选) | avid与bvid任选一个 | +| bvid | str | 要删除的目标稿件bvid | 必要(可选) | avid与bvid任选一个 | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-111:csrf校验失败
-400:请求错误
53021:置顶列表中没有该视频 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | 作用尚不明确 | + +**示例:** + +删除置顶视频`av59765630`/`BV1Yt41137T6` + +avid方式: + +```shell +curl 'https://api.bilibili.com/x/space/masterpiece/cancel' \ +--data-urlencode 'aid=59765630' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +bvid方式: + +```shell +curl 'https://api.bilibili.com/x/space/masterpiece/cancel' \ +--data-urlencode 'bvid=BV1Yt41137T6' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +### 个人TAG + +#### 查看用户个人TAG + +> https://api.bilibili.com/x/space/acc/tags + +*请求方式:GET* + +上限5条,且内容由用户自定义 + +带有转义 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| mid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | array | 信息本体 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ------------- | +| 0 | obj | 套了个娃 | 只有1项??? | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ----- | ----------- | ---- | +| mid | num | 目标用户mid | | +| tags | array | TAG名称 | | + +`data`数组中的对象中的`tags`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ------- | +| 0 | str | TAG1 | | +| n | str | TAG(n+1) | | +| …… | str | …… | | +| 4 | str | TAG5 | 上限5条 | + +**示例:** + +查看用户`mid=53456`的个人TAG + +```shell +curl -G 'https://api.bilibili.com/x/space/acc/tags' \ +--data-urlencode 'mid=53456' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "mid": 53456, + "tags": [ + "游戏", + "音乐", + "warma", + "搞笑", + "动画" + ] + } + ] +} +``` + +
+ +#### 修改个人TAG + +> https://api.bilibili.com/x/space/acc/tags/set + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +鉴权方式:Cookie中`DedeUserID`存在且不为0 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------ | ------ | ------------------------------------------------------------ | +| tags | strs | 要设置的TAG内容 | 非必要 | 删除公告留空或省去即可
各TAG长度小于10字符
最多5个TAG
各TAG之间用","(%2C)分隔
重复TAG无效 | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-111:csrf校验失败
-400:请求错误(超出长度限制) | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +修改个人TAG为`minecraft,技术宅,大佬,小哥哥,可爱` + +```shell +curl 'https://api.bilibili.com/x/space/acc/tags/set' \ +--data-urlencode 'tags=minecraft,技术宅,大佬,小哥哥,可爱' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx;DedeUserID=1' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
+ +### 空间公告 + +#### 查看用户空间公告 + +> https://api.bilibili.com/x/space/notice + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| mid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | str | 公告信息 | 无则为空 | + +**示例:** + +查看用户`mid=53456`的空间公告 + +```shell +curl -G 'https://api.bilibili.com/x/space/notice' \ +--data-urlencode 'mid=53456' +``` + +
+查看响应示例: + +```json +{ + "code":0, + "message":"0", + "ttl":1, + "data":"我的微博 @_warma_\n直播录像上传到:warma养鸽场\n头像画师是:微博@Dr-H_喵_\n横幅画师:@薬屋" +} +``` + +
+ +#### 修改空间公告 + +> https://api.bilibili.com/x/space/notice/set + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------ | ------ | --------------------------------------- | +| notice | str | 要设置的公告内容 | 非必要 | 删除公告留空或省去即可
少于150字符 | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-111:csrf校验失败
-304:未修改
-400:请求错误(超出长度限制) | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | 作用尚不明确 | + +**示例:** + +修改个人空间公告为`鸽子` + +```shell +curl 'https://api.bilibili.com/x/space/notice/set' \ +--data-urlencode 'notice=鸽子' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
+ +### 主页板块布局与权限 + +#### 查询空间设置 + +> http://space.bilibili.com/ajax/settings/getSettings + +*请求方式:GET* + +注:带有转义 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| mid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ------------------- | -------- | ---- | +| status | bool | 用户是否存在 | true:存在
false:不存在 | +| data | 用户存在时:obj
用户不存在时:str| 用户存在时:信息本体
用户不存在时:错误信息 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------------------- | ----- | ---------------- | ------------ | +| privacy | obj | 空间隐私权限 | | +| index_order | array | 空间板块布局 | | +| theme | str | default主题? | 作用尚不明确 | +| theme_preview_img_path | str | 主题预览图路径? | 作用尚不明确 | +| toutu | obj | 空间头图 | | + +`privacy`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | -------------- | ------------------------------ | +| bangumi | num | 追番及追剧 | 0:隐藏
1:公开
**下同** | +| bbq | num | 轻视频 | | +| channel | num | 频道 | | +| coins_video | num | 最近投币的视频 | | +| comic | num | 追漫 | | +| dress_up | num | 装扮 | | +| fav_video | num | 收藏夹 | | +| groups | num | 圈子? | 作用尚不明确 | +| likes_video | num | 最近点赞的视频 | | +| played_game | num | 最近玩过的游戏 | | +| tags | num | 订阅标签 | | +| user_info | num | 个人资料 | | + +`index_order`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | -------------------------------------------- | +| 0 | obj | 板块1 | 根据板块布局顺序排序
先左侧布局后右侧布局 | +| n | obj | 板块(n+1) | | +| …… | obj | …… | …… | + +`index_order`数组内对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| id | num | 板块编号 | | +| name | str | 板块名称 | | + +`toutu`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | -------------------- | -------------------------------------------------- | +| sid | num | 空间头图ID | | +| expire | num | 到期时间? | 时间戳?
作用尚不明确 | +| s_img | str | 空间头图小图相对路径 | 完整url为`http://i0.hdslb.com/`+相对路径 | +| l_img | str | 空间头图相对路径 | **同上** | +| android_img | str | 空 | 注:**手机端头图与web端不同,需要用另一个api获取** | +| iphone_img | str | 空 | | +| ipad_img | str | 空 | | +| thumbnail_img | str | 缩略图 | | +| platform | num | 0 | 作用尚不明确 | + +**示例:** + +查看`mid=2`的空间设置 + +```shell +curl -G 'http://space.bilibili.com/ajax/settings/getSettings' \ +--data-urlencode 'mid=2' +``` + +
+查看响应示例: + +```json +{ + "status":true, + "data":{ + "privacy":{ + "bangumi":1, + "bbq":1, + "channel":1, + "coins_video":0, + "comic":1, + "dress_up":1, + "fav_video":0, + "groups":0, + "likes_video":0, + "played_game":1, + "tags":1, + "user_info":1 + }, + "index_order":[ + { + "id":1, + "name":"我的稿件" + }, + { + "id":8, + "name":"我的专栏" + }, + { + "id":7, + "name":"我的频道" + }, + { + "id":2, + "name":"我的收藏夹" + }, + { + "id":3, + "name":"订阅番剧" + }, + { + "id":4, + "name":"订阅标签" + }, + { + "id":5, + "name":"最近投币的视频" + }, + { + "id":6, + "name":"我的圈子" + }, + { + "id":9, + "name":"我的相簿" + }, + { + "id":21, + "name":"公告" + }, + { + "id":22, + "name":"直播间" + }, + { + "id":23, + "name":"个人资料" + }, + { + "id":24, + "name":"官方活动" + }, + { + "id":25, + "name":"最近玩过的游戏" + } + ], + "theme":"default", + "theme_preview_img_path":"", + "toutu":{ + "sid":1, + "expire":2861874560, + "s_img":"bfs/space/768cc4fd97618cf589d23c2711a1d1a729f42235.png", + "l_img":"bfs/space/cb1c3ef50e22b6096fde67febe863494caefebad.png", + "android_img":"", + "iphone_img":"", + "ipad_img":"", + "thumbnail_img":"", + "platform":0 + } + } +} +``` + +
+ +#### 查询可用头图列表 (Web端) + +> https://space.bilibili.com/ajax/topphoto/getlist + +*请求方式: GET* + +注: 带有转义 + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | -------------------------- | +| mid | num | 目标用户mid | 必要 | 非负数, 即使该用户并不存在 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ------------------------- | -------------------------------------- | ---- | +| status | bool | 成功: true
失败: false | | +| data | 成功: array
失败: str | 成功: 信息本体
失败: "用户id错误" | | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ----------- | ------------------------------------ | +| id | num | 空间头图 ID | | +| product_name | str | 显示名称 | | +| price | num | 价格 | | +| coin_type | num | 支付类型? | | +| vip_free | num | 大会员免费 | | +| s_img | str | 小图 URI | 需要自行与 `i0.hdslb.com` 拼接成 URL | +| l_img | str | 大图 URI | 同 s_img | +| thumbnail_img | str | 空 | 并不存在的缩略图? | +| sort_num | num | 排序编号 | | +| is_disable | num | 已禁用 | 0: 未禁用 | +| expire | num | 过期时间? | UNIX 时间戳, 或 0 为永不过期 | +| had | num | 是否拥有? | 当 expire 不为 0 时 为 1, 否则为 0 | + +**示例:** + +查询`mid=1145141919810000000`的可用空间头图 + +```shell +curl -G "https://space.bilibili.com/ajax/topphoto/getlist" \ +--data-urlencode "mid=1145141919810000000" +``` + +
+查看响应示例: + +```json +{ + "status": true, + "data": [ + { + "id": 1, + "product_name": "bilibili春", + "price": 0, + "coin_type": 0, + "vip_free": 0, + "s_img": "bfs/space/768cc4fd97618cf589d23c2711a1d1a729f42235.png", + "l_img": "bfs/space/cb1c3ef50e22b6096fde67febe863494caefebad.png", + "thumbnail_img": "", + "sort_num": 19, + "is_disable": 0, + "expire": 0, + "had": 0 + }, + { + "id": 2, + "product_name": "两人单车", + "price": 0, + "coin_type": 0, + "vip_free": 0, + "s_img": "bfs/space/d60a4be11f1bca6168a60a53c64bca18eddd6443.jpg", + "l_img": "bfs/space/44873d3568bdcb3d850d234e02a19602972450f1.png", + "thumbnail_img": "", + "sort_num": 16, + "is_disable": 0, + "expire": 0, + "had": 0 + }, + { + "id": 5, + "product_name": "成为偶像", + "price": 0, + "coin_type": 0, + "vip_free": 0, + "s_img": "bfs/space/5fe2632486a5a91a234f0e7cb368ab6397477da4.jpg", + "l_img": "bfs/space/87277d30cd19edcec9db466a9a3e556aeb0bc0ed.png", + "thumbnail_img": "", + "sort_num": 15, + "is_disable": 0, + "expire": 0, + "had": 0 + }, + { + "id": 11, + "product_name": "星际勘探", + "price": 0, + "coin_type": 0, + "vip_free": 0, + "s_img": "bfs/space/6849abc6e67000ad807b35a970aba31dd1e400dd.jpg", + "l_img": "bfs/space/c919a9818172a8297f8b0597722f96504a1e1d88.png", + "thumbnail_img": "", + "sort_num": 14, + "is_disable": 0, + "expire": 0, + "had": 0 + }, + { + "id": 10, + "product_name": "星O大战", + "price": 0, + "coin_type": 0, + "vip_free": 0, + "s_img": "bfs/space/ff3b0882e55c1099738e59616e5956ad357d9948.jpg", + "l_img": "bfs/space/e22f5b8e06ea3ee4de9e4da702ce8ef9a2958f5a.png", + "thumbnail_img": "", + "sort_num": 13, + "is_disable": 0, + "expire": 0, + "had": 0 + }, + { + "id": 12, + "product_name": "王牌特工", + "price": 0, + "coin_type": 0, + "vip_free": 0, + "s_img": "bfs/space/f5d38e2af44fd12fa65423aff55933fcf9071419.jpg", + "l_img": "bfs/space/8cd85a382756ab938df23a856017abccd187188e.png", + "thumbnail_img": "", + "sort_num": 12, + "is_disable": 0, + "expire": 0, + "had": 0 + }, + { + "id": 3, + "product_name": "仰望星空", + "price": 0, + "coin_type": 0, + "vip_free": 0, + "s_img": "bfs/space/c9dae917e24b4fc17c4d544caf6b6c0b17f8692b.jpg", + "l_img": "bfs/space/9ccc0447aebf0656809b339b41aa5b3705f27c47.png", + "thumbnail_img": "", + "sort_num": 11, + "is_disable": 0, + "expire": 0, + "had": 0 + }, + { + "id": 14, + "product_name": "雨过天晴", + "price": 0, + "coin_type": 0, + "vip_free": 0, + "s_img": "bfs/space/1115b2fdabd128337f892feada4ce32e51f3a5ad.jpg", + "l_img": "bfs/space/6a1198e25f8764bd30d53411dac9fdf840bc3265.png", + "thumbnail_img": "", + "sort_num": 10, + "is_disable": 0, + "expire": 0, + "had": 0 + }, + { + "id": 6, + "product_name": "绿荫秘境", + "price": 0, + "coin_type": 0, + "vip_free": 0, + "s_img": "bfs/space/dc02d22a718c1c436f1a355b3cd726b04098ef7d.jpg", + "l_img": "bfs/space/265ecddc52d74e624dc38cf0cff13317085aedf7.png", + "thumbnail_img": "", + "sort_num": 9, + "is_disable": 0, + "expire": 0, + "had": 0 + }, + { + "id": 13, + "product_name": "漫游仙境", + "price": 0, + "coin_type": 0, + "vip_free": 0, + "s_img": "bfs/space/184abe52a5ea9390b506c064cfba4f8f20ae9cca.jpg", + "l_img": "bfs/space/24d0815514951bb108fbb360b04a969441079315.png", + "thumbnail_img": "", + "sort_num": 7, + "is_disable": 0, + "expire": 0, + "had": 0 + }, + { + "id": 15, + "product_name": "放课后time", + "price": 0, + "coin_type": 0, + "vip_free": 0, + "s_img": "bfs/space/aea2dd7b8894ce31d578d4fad6a7188c7b49cb2f.jpg", + "l_img": "bfs/space/6e799ff2de2de55d27796707a283068d66cdf3f4.png", + "thumbnail_img": "", + "sort_num": 6, + "is_disable": 0, + "expire": 0, + "had": 0 + }, + { + "id": 4, + "product_name": "昴宿星团", + "price": 0, + "coin_type": 0, + "vip_free": 0, + "s_img": "bfs/space/1f4eaf70d1bb981f6057b3e440249d7a1f65774f.jpg", + "l_img": "bfs/space/3ab888c1d149e864ab44802dea8c1443e940fa0d.png", + "thumbnail_img": "", + "sort_num": 5, + "is_disable": 0, + "expire": 0, + "had": 0 + }, + { + "id": 7, + "product_name": "蔷薇洛丽塔", + "price": 0, + "coin_type": 0, + "vip_free": 0, + "s_img": "bfs/space/718eac8c71e29b8a80431c46110805c3a40e30a6.jpg", + "l_img": "bfs/space/70ce28bcbcb4b7d0b4f644b6f082d63a702653c1.png", + "thumbnail_img": "", + "sort_num": 4, + "is_disable": 0, + "expire": 0, + "had": 0 + }, + { + "id": 9, + "product_name": "黑暗之门", + "price": 0, + "coin_type": 0, + "vip_free": 0, + "s_img": "bfs/space/ef1b08e62fdc35b06e39795bc6de8e510935bf97.jpg", + "l_img": "bfs/space/cd52d4ac1d336c940cc4958120170f7928d9e606.png", + "thumbnail_img": "", + "sort_num": 3, + "is_disable": 0, + "expire": 0, + "had": 0 + }, + { + "id": 19, + "product_name": "你的名字", + "price": 0, + "coin_type": 0, + "vip_free": 0, + "s_img": "bfs/space/373e127e8784d3e4c1b5e6db0c27702ba077643f.jpg", + "l_img": "bfs/space/f49642b3683a08e3190f29d5a095386451f8952c.jpg", + "thumbnail_img": "", + "sort_num": 2, + "is_disable": 0, + "expire": 0, + "had": 0 + } + ] +} +``` + +
+ +### 设置空间头图 (Web端) + +> https://space.bilibili.com/ajax/settings/setToutu + +*请求方式: POST* + +认证方式: Cookie (SESSDATA) + +鉴权方式: referer为 `.bilibili.com` 域名下 + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---------------------------------- | ------ | ---- | +| id | num | 头图 ID | 必要 | | +| csrf | str | CSRF Token (即 Cookie bili_jct 值) | 不必要 | | + +**JSON回复:** + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | -------- | --------------------------- | +| status | bool | 状态 | true: 成功
false: 失败 | +| data | str | 错误信息 | 正确时无此项 (带有转义) | + +**示例:** + +设置空间头图为为`王牌特工(id=12)` + +```shell +curl -X POST "https://space.bilibili.com/ajax/settings/setToutu" \ +--referer "https://space.bilibili.com/" \ +--data-urlencode "id=12" \ +--data-urlencode "csrf=xxx" \ +-b "SESSDATA=xxx; bili_jct=xxx" +``` + +
+查看响应示例: + +```json +{ + "status": true +} +``` + +
+ +#### 调整空间板块布局 + +> http://space.bilibili.com/ajax/settings/setIndexOrder + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +鉴权方式:Cookie中`DedeUserID`及`DedeUserID__ckMd5`存在且不为0,referer为 `.bilibili.com`域名下 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----------- | ---- | ------------------------ | ------ | ------------------------------------------------------------ | +| index_order | nums | 布局列表 | 必要 | 每个值之间用","(%2C)分隔
先左侧布局再右侧布局
值的意义见下表 | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +布局参数`index_order`: + +| 值 | 含义 | +| ---- | ------------------------------------ | +| 1 | (左侧)我的稿件 | +| 2 | (左侧)我的收藏夹 | +| 3 | (左侧)订阅番剧 | +| 4 | (左侧)订阅标签 | +| 5 | (左侧)最近投币的视频 | +| 6 | (左侧)我的圈子 **(此板块被隐藏)** | +| 7 | (左侧)我的频道 | +| 8 | (左侧)我的专栏 | +| 9 | (左侧)我的相簿 | +| 21 | (右侧)公告 | +| 22 | (右侧)直播间 | +| 23 | (右侧)个人资料 | +| 24 | (右侧)官方活动 | +| 25 | (右侧)最近玩的游戏 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | -------- | ----------------------------------- | +| status | bool | 操作结果 | true:操作成功
false:操作失败 | +| data | str | 错误信息 | 正确时无此项 | + +**示例:** + +调整空间布局为: + +```text +我的稿件 直播间 +我的专栏 个人资料 +订阅番剧 公告 +我的收藏夹 官方活动 +我的相簿 最近玩的游戏 +最近投币的视频 +订阅标签 +我的频道 +``` + +```shell +curl 'https://space.bilibili.com/ajax/settings/setIndexOrder' \ +--data-urlencode 'index_order=1,8,3,2,9,5,4,7,22,23,21,24,25,6' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx;DedeUserID=1;DedeUserID__ckMd5=1;' \ +-e 'https://www.bilibili.com' +``` + +
+查看响应示例: + +```json +{ + "status": true +} +``` + +
+ +#### 修改空间隐私权限 + +> http://space.bilibili.com/ajax/settings/setPrivacy + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +鉴权方式:Cookie中`DedeUserID`及`DedeUserID__ckMd5`存在且不为0,referer为 `.bilibili.com`域名下 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----------- | ---- | ------------------------ | ------ | ---------------------------------- | +| fav_video | num | 收藏视频 | 非必要 | 0:隐藏
1:公开
**下同** | +| bangumi | num | 追番及追剧 | 非必要 | | +| tags | num | 关注的TAG | 非必要 | | +| coins_video | num | 投币的视频 | 非必要 | | +| user_info | num | 个人信息 | 非必要 | | +| played_game | num | 玩过的游戏 | 非必要 | | +| csrf | nstr | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | -------- | ----------------------------------- | +| status | bool | 操作结果 | true:操作成功
false:操作失败 | +| data | str | 错误信息 | 正确时无此项 | + +**示例:** + +设置`关注的TAG`为隐藏 + +```shell +curl 'https://space.bilibili.com/ajax/settings/setPrivacy' \ +--data-urlencode 'tags=0' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx;DedeUserID=1;DedeUserID__ckMd5=1;' \ +-e 'https://www.bilibili.com' +``` + +
+查看响应示例: + +```json +{ + "status": true +} +``` + +
+ +### 查询用户最近访问内容 + +#### 查询用户最近玩过的游戏 + +> https://api.bilibili.com/x/space/lastplaygame + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +如设置隐私查看自己的需要认证 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| mid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------------------------------- | -------- | ---------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
53013:用户隐私设置未公开 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 隐藏时:null
公开时:array | 信息本体 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---------------- | +| 0 | obj | 游戏1 | | +| n | obj | 游戏(n+1) | 项数为总计游戏数 | +| …… | obj | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ---------- | ---- | +| website | str | 游戏主页 url | | +| image | str | 游戏图标 url | | +| name | str | 游戏名 | | + +**示例:** + +查询`mid=2`的最近玩过的游戏 + +```shell +curl -G 'https://api.bilibili.com/x/space/lastplaygame' \ + --data-urlencode 'mid=2' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "website": "https://game.bilibili.com/fgo/event_meihosou", + "image": "http://i0.hdslb.com/bfs/game/f7d4ee0877089e4079b8f0b4f5c95dd4ceba512a.png", + "name": "命运-冠位指定(Fate/GO)" + }, + { + "website": "https://game.bilibili.com/pcr/xxtix", + "image": "http://i0.hdslb.com/bfs/game/7922ecea5cc76fe3c8c177e1d4a6c8cf1c36a700.jpg", + "name": "公主连结Re:Dive" + }, + { + "website": "https://game.bilibili.com/dwbgx/", + "image": "http://i0.hdslb.com/bfs/game/6d5b2df70dfa987408d8d09110cdc327949885e3.png", + "name": "大王不高兴" + }, + { + "website": "https://game.bilibili.com/bangdream/1stanniversary-yxzx/", + "image": "http://i0.hdslb.com/bfs/game/4a7d0b7272dffe5a489ee935b6bd2d4f7d5f1257.png", + "name": "BanG Dream!" + }, + { + "website": "http://www.biligame.com/detail/?id=101772", + "image": "http://i0.hdslb.com/bfs/game/8e8b04e7bd2170c2ba2c9f563a62c72bac2eba2c.jpg", + "name": "明日方舟" + } + ] +} +``` + +
+ +#### 查询用户最近玩过的游戏V2 + +> https://api.bilibili.com/x/space/lastplaygame/v2 + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +如设置隐私查看自己的需要认证 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| mid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------------------------------- | -------- | ---------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
53013:用户隐私设置未公开 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 隐藏时:null
公开时:obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----- | ------ | --- | +| page_num | num | 当前页码 | | +| page_size | num | 每页项数 | | +| total_count | num | 游戏总数 | | +| list | array | 游戏列表 | | + +`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | ---------------- | +| 0 | obj | 游戏1 | | +| n | obj | 游戏(n+1) | 项数为总计游戏数 | +| …… | obj | …… | …… | + +`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ----- | ----------- | ----------------- | +| game_base_id | num | 游戏 id | biligame 的游戏 id | +| game_name | str | 游戏名 | | +| game_icon | str | 游戏图标 url | | +| grade | num | 游戏评分 | 如`8.2`、`6.8` | +| detail_url | str | 游戏主页 url | | +| game_tags | array | 游戏标签 | | +| notice | str | 游戏简介文案 | | +| gift_title | str | 游戏礼物文案 | | +| game_status_v2 | num | (?) | | + +`game_tags`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------ | --------------------------- | +| 0 | obj | 游戏标签1 | 如`角色扮演`、`音乐节奏`、`休闲` | +| n | obj | 游戏标签(n+1) | | +| …… | obj | …… | …… | + +**示例:** + +查询`mid=2`的最近玩过的游戏 + +```shell +curl -G 'https://api.bilibili.com/x/space/lastplaygame/v2' \ + --data-urlencode 'mid=2' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "page_num": 0, + "page_size": 15, + "total_count": 8, + "list": [ + { + "game_base_id": 102567, + "game_name": "坎特伯雷公主与骑士唤醒冠军之剑的奇幻冒险", + "game_icon": "https://i0.hdslb.com/bfs/game/fc2f4fd3a347eeb9b8b6ab59d961269bdd05d4e0.png", + "grade": 8.2, + "detail_url": "https://www.biligame.com/detail/?id=102567", + "game_tags": [ + "角色扮演", + "像素风" + ], + "notice": "像素风欢脱冒险RPG", + "gift_title": "", + "game_status_v2": 0 + }, + { + "game_base_id": 101661, + "game_name": "光·遇", + "game_icon": "https://i0.hdslb.com/bfs/game/9a1be39915f057597f9328afe503a2bbd0de7754.png", + "grade": 6.8, + "detail_url": "https://www.biligame.com/detail/?id=101661", + "game_tags": [ + "休闲", + "治愈", + "唯美" + ], + "notice": "九色鹿季开启,探索本真之旅", + "gift_title": "光·遇九色鹿季回归礼包", + "game_status_v2": 0 + }, + { + "game_base_id": 103496, + "game_name": "原神", + "game_icon": "https://i0.hdslb.com/bfs/game/2b29383536b3d1a2517bfcb73767f78c242f0458.png", + "grade": 6.5, + "detail_url": "https://www.biligame.com/detail/?id=103496", + "game_tags": [ + "角色扮演", + "二次元", + "冒险" + ], + "notice": "跨越尘世的探索之旅", + "gift_title": "bilibili-原神4.4版本独家礼包", + "game_status_v2": 0 + }, + { + "game_base_id": 49, + "game_name": "命运-冠位指定(Fate/GO)", + "game_icon": "https://i0.hdslb.com/bfs/game/ca5d8d4b3a042beddf7cabca20ae0c946527d1bf.png", + "grade": 6, + "detail_url": "https://www.biligame.com/detail/?id=49", + "game_tags": [ + "卡牌", + "fate", + "厨向" + ], + "notice": "第2部现已开启!", + "gift_title": "", + "game_status_v2": 0 + }, + { + "game_base_id": 102216, + "game_name": "公主连结Re:Dive", + "game_icon": "https://i0.hdslb.com/bfs/game/3bb819e010fe6d594d8f4d417ee380f40e8b5b06.png", + "grade": 8.4, + "detail_url": "https://www.biligame.com/detail/?id=102216", + "game_tags": [ + "角色扮演" + ], + "notice": "新角色「璃乃(圣诞节)」登场!", + "gift_title": "", + "game_status_v2": 0 + }, + { + "game_base_id": 168, + "game_name": "BanG Dream!", + "game_icon": "https://i0.hdslb.com/bfs/game/d196365d9f112a5adede7eedea1e4154e98c5e53.png", + "grade": 9.2, + "detail_url": "https://www.biligame.com/detail/?id=168", + "game_tags": [ + "音乐节奏", + "BanG Dream" + ], + "notice": "「迎风展翅的我们」活动开启!", + "gift_title": "", + "game_status_v2": 0 + }, + { + "game_base_id": 101772, + "game_name": "明日方舟", + "game_icon": "https://i0.hdslb.com/bfs/game/faa556b00d29fffc88281c1ee038b1b7f23aa5c2.jpg", + "grade": 7.4, + "detail_url": "https://www.biligame.com/detail/?id=101772", + "game_tags": [ + "策略", + "架空文明", + "末世" + ], + "notice": "2023感谢庆典正式开启", + "gift_title": "", + "game_status_v2": 0 + }, + { + "game_base_id": 97, + "game_name": "碧蓝航线", + "game_icon": "https://i0.hdslb.com/bfs/game/b141a7690c226a0eae66518c713d3af62613b21d.png", + "grade": 8.7, + "detail_url": "https://www.biligame.com/detail/?id=97", + "game_tags": [ + "养成" + ], + "notice": "指挥官,欢迎回港", + "gift_title": "", + "game_status_v2": 0 + } + ] + } +} +``` + +
+ +#### 查询用户最近投币视频(Web) + +> https://api.bilibili.com/x/space/coin/video + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +如设置隐私查看自己的需要认证 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | --------- | ------ | ---- | +| vmid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------------------------------- | -------- | ---------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
53013:用户隐私设置未公开 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 隐藏时:null
公开时:array | 信息本体 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | obj | 投币视频1 | | +| n | obj | 投币视频(n+1) | | +| …… | obj | …… | | + +`data`数组中的对象: + +基本与[获取视频详细信息(web端)](../video/info.md#获取视频详细信息web端)中`data`对象字段一致 + +**示例:** + +查看用户`mid=15858903`的最近投币视频 + +```shell +curl -G 'http://space.bilibili.com/x/space/coin/video' \ + --data-urlencode 'vmid=15858903' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "aid": 669644066, + "videos": 1, + "tid": 75, + "tname": "动物圈", + "copyright": 2, + "pic": "http://i1.hdslb.com/bfs/archive/0f73a68b8f449cc72e9ef109685bd295dc0c0c9d.jpg", + "title": "在人类幼崽身上用尽了温柔", + "pubdate": 1600608261, + "ctime": 1600608261, + "desc": "https://weibo.com/tv/show/1034:4551253766897703?from=old_pc_videoshow", + "state": 0, + "attribute": 16384, + "duration": 29, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0 + }, + "owner": { + "mid": 258457966, + "name": "卧龙寺", + "face": "http://i2.hdslb.com/bfs/face/f868d1f522733fdcf72a6267e0237157dd0e9948.jpg" + }, + "stat": { + "aid": 669644066, + "view": 3412898, + "danmaku": 719, + "reply": 1481, + "favorite": 21909, + "coin": 2864, + "share": 13702, + "now_rank": 0, + "his_rank": 0, + "like": 86970, + "dislike": 0 + }, + "dynamic": "", + "cid": 237319289, + "dimension": { + "width": 576, + "height": 1024, + "rotate": 0 + }, + "bvid": "BV1sa4y1j7jk", + "coins": 1, + "time": 1601802763, + "ip": "", + "inter_video": false + }, + { + "aid": 202267998, + "videos": 1, + "tid": 138, + "tname": "搞笑", + "copyright": 1, + "pic": "http://i0.hdslb.com/bfs/archive/ca7746f2207114513f1a421d7f744523275ee679.jpg", + "title": "充 电 器 の 痛", + "pubdate": 1601750952, + "ctime": 1601750952, + "desc": "这个简介吓到我了!", + "state": 0, + "attribute": 16512, + "duration": 50, + "mission_id": 14725, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0 + }, + "owner": { + "mid": 129922746, + "name": "-白糖洒一地-", + "face": "http://i0.hdslb.com/bfs/face/1f581f3b20a380c2fd13ecb8bbe409f8b49c6418.jpg" + }, + "stat": { + "aid": 202267998, + "view": 109, + "danmaku": 2, + "reply": 11, + "favorite": 5, + "coin": 9, + "share": 0, + "now_rank": 0, + "his_rank": 0, + "like": 20, + "dislike": 0 + }, + "dynamic": "", + "cid": 241861687, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "bvid": "BV1oh411X7iA", + "coins": 2, + "time": 1601773750, + "ip": "", + "inter_video": false + }, + { + "aid": 839722373, + "videos": 1, + "tid": 208, + "tname": "校园学习", + "copyright": 1, + "pic": "http://i2.hdslb.com/bfs/archive/11ed53241ceab314c919adba9f85582d24d9313c.jpg", + "title": "“白piáo”用日语到底怎么说?油管人气日语老师来教你!", + "pubdate": 1601026026, + "ctime": 1601026026, + "desc": "志方老师的B站用语日语课又来了~\n欢迎大家来看哦,\n如果喜欢我们的作品的话,欢迎大家用2~3连+转发来支持我们~\n如果拒绝的话,也可以用日语在评论和弹幕里刷上一波~即可以锻炼日语又可以拒绝我们,岂不美哉~~", + "state": 0, + "attribute": 16768, + "duration": 310, + "mission_id": 14655, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0 + }, + "owner": { + "mid": 677926489, + "name": "日语志方老师", + "face": "http://i2.hdslb.com/bfs/face/d465e5cd42e3523a52b3bef38dce7b23627b7723.jpg" + }, + "stat": { + "aid": 839722373, + "view": 130688, + "danmaku": 1320, + "reply": 799, + "favorite": 3722, + "coin": 5883, + "share": 339, + "now_rank": 0, + "his_rank": 0, + "like": 17585, + "dislike": 0 + }, + "dynamic": "志方老师的B站用语日语课又来了~\n欢迎大家来看哦,\n如果喜欢我们的作品的话,欢迎大家用2~3连+转发来支持我们~\n如果拒绝的话,也可以用日语在评论和弹幕里刷上一波~即可以锻炼日语又可以拒绝我们,岂不美哉~~", + "cid": 238876133, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "bvid": "BV1n54y117kq", + "coins": 2, + "time": 1601036198, + "ip": "", + "inter_video": false + } + ] +} +``` + +
+ +#### 查询用户最近投币视频(APP) + +> https://app.bilibili.com/x/v2/space/coinarc + +*请求方式:GET* + +认证方式:APP + +如设置隐私查看自己的需要认证 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ----------- | ------ | -------- | +| access_key | str | APP登录Token | APP方式必要 | | +| appkey | str | APP密钥 | APP方式必要 | | +| vmid | num | 目标用户mid | 必要 | | +| pn | num | 页码 | 非必要 | 默认为1 | +| ps | num | 每页项数 | 非必要 | 默认为20 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------ | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ----- | ---------- | ---- | +| count | num | 投币的视频数 | | +| item | array | 投币视频列表 | | + +`item`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------------ | ---- | +| 0 | obj | 投币的视频信息1 | | +| n | obj | 投币的视频信息(n+1) | | +| …… | obj | …… | | + +`item`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ---- | ------------ | ---------------------- | +| title | str | 稿件标题 | | +| subtitle | str | 空 | | +| tname | str | 空 | | +| cover | str | 封面图片 url | | +| cover_icon | str | 空 | | +| uri | str | APP 跳转 uri | 如`bilibili://video/2` | +| param | str | 稿件 avid | | +| goto | str | av | | +| length | num | 空 | | +| duration | num | 稿件视频长度 | 单位为秒 | +| is_popular | bool | (?) | | +| is_steins | bool | (?) | | +| is_ugcpay | bool | (?) | | +| is_cooperation | str | (?) | | +| is_pgc | str | (?) | | +| is_live_playback | str | (?) | | +| is_pugv | str | (?) | | +| is_fold | num | (?) | | +| play | num | 播放量 | | +| danmaku | num | 弹幕量 | | +| ctime | num | 发布时间 | 时间戳 | +| ugc_pay | num | 0 | | +| author | str | UP主昵称 | | +| state | bool | true | | +| videos | num | 0 | | +| view_content | str | 稿件播放量文案 | | +| icon_type | num | 0 | | +| publish_time_text | str | 空 | | + +**示例:** + +用户`mid=2`的投币列表 + +```shell +curl -G 'https://app.bilibili.com/x/v2/space/coinarc' \ + --data-urlencode 'appkey=1d8b6e7d45233436' \ + --data-urlencode 'access_key=xxx' \ + --data-urlencode 'vmid=2' \ + --data-urlencode 'ps=2' \ + --data-urlencode 'pn=1' \ +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "count": 2, + "item": [ + { + "title": "请打开麦克风交流", + "subtitle": "", + "tname": "", + "cover": "http://i1.hdslb.com/bfs/archive/cf9aea43b72354ee8c9486e4bf8e07cb38920a65.jpg", + "cover_icon": "", + "uri": "bilibili://video/496832459?player_width=1080\u0026player_height=1920\u0026player_rotate=0", + "param": "496832459", + "goto": "av", + "length": "", + "duration": 134, + "is_popular": false, + "is_steins": false, + "is_ugcpay": false, + "is_cooperation": false, + "is_pgc": false, + "is_live_playback": false, + "is_pugv": false, + "is_fold": false, + "play": 706480, + "danmaku": 167, + "ctime": 1706431476, + "ugc_pay": 0, + "author": "三个猪鼓励", + "state": true, + "videos": 0, + "view_content": "70.6万", + "icon_type": 0, + "publish_time_text": "" + }, + { + "title": "【裏命】地球的内部【いよわ】【中文CC字幕】", + "subtitle": "", + "tname": "", + "cover": "http://i0.hdslb.com/bfs/archive/e087224ae4a5ff9ef3f2f6b7644d635276b8f5c6.jpg", + "cover_icon": "", + "uri": "bilibili://video/860645391?player_width=1920\u0026player_height=1080\u0026player_rotate=0", + "param": "860645391", + "goto": "av", + "length": "", + "duration": 264, + "is_popular": false, + "is_steins": false, + "is_ugcpay": false, + "is_cooperation": false, + "is_pgc": false, + "is_live_playback": false, + "is_pugv": false, + "is_fold": false, + "play": 194375, + "danmaku": 173, + "ctime": 1669713070, + "ugc_pay": 0, + "author": "精神安定剤", + "state": true, + "videos": 0, + "view_content": "19.4万", + "icon_type": 0, + "publish_time_text": "" + } + ] + } +} +``` + +
+ +#### 查询用户最近点赞视频(Web) + +> https://api.bilibili.com/x/space/like/video + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +如设置隐私查看自己的需要认证 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | --------- | ------ | ---- | +| vmid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------------------------------- | -------- | ---------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
53013:用户隐私设置未公开 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 隐藏时:null
公开时:array | 信息本体 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | obj | 点赞视频1 | | +| n | obj | 点赞视频(n+1) | | +| …… | obj | …… | | + +`data`数组中的对象: + +基本与[获取视频详细信息(web端)](../video/info.md#获取视频详细信息web端)中`data`对象字段一致 + +**示例:** + +查看用户`mid=15858903`的最近点赞视频 + +```shell +curl -G 'http://space.bilibili.com/x/space/like/video' \ + --data-urlencode 'vmid=15858903' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [ + { + "aid": 1700085880, + "videos": 1, + "tid": 21, + "tname": "日常", + "copyright": 1, + "pic": "http://i0.hdslb.com/bfs/archive/7fad4ca408c66eb7ea72188f56bcf952306d5807.jpg", + "title": "你是从什么时候,意识到自己缺爱的呢?", + "pubdate": 1706706000, + "ctime": 1706602115, + "desc": "关于个人情感问题,私信发“2024”我来帮你~", + "state": 0, + "duration": 91, + "mission_id": 4009559, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 2104592226, + "name": "鲸落艳红尘", + "face": "https://i0.hdslb.com/bfs/face/80160fbcf71958e6f5ad3a4fdfa39a55cc0699a5.jpg" + }, + "stat": { + "aid": 1700085880, + "view": 930, + "danmaku": 1, + "reply": 5, + "favorite": 18, + "coin": 0, + "share": 4, + "now_rank": 0, + "his_rank": 0, + "like": 27, + "dislike": 0, + "vt": 0, + "vv": 930 + }, + "dynamic": "", + "cid": 1424231007, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1XK421y7ZL", + "first_frame": "http://i2.hdslb.com/bfs/storyff/n240130sa1k9birz4lwlsm21ya1w3p2c_firsti.jpg", + "pub_location": "湖北", + "bvid": "BV1XK421y7ZL", + "inter_video": false, + "resource_type": "ugc", + "subtitle": "", + "enable_vt": 0 + }, + { + "aid": 836926413, + "videos": 1, + "tid": 21, + "tname": "日常", + "copyright": 1, + "pic": "http://i2.hdslb.com/bfs/archive/dceaf79d1cc4f74ab8cd862f454a8ec4b4a44343.jpg", + "title": "内心的创伤,是建立深度亲密关系的桥梁!", + "pubdate": 1706594400, + "ctime": 1706515438, + "desc": "关于个人情感问题,私信发“2024”我来帮你~", + "state": 0, + "duration": 297, + "mission_id": 4009559, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 2104592226, + "name": "鲸落艳红尘", + "face": "https://i0.hdslb.com/bfs/face/80160fbcf71958e6f5ad3a4fdfa39a55cc0699a5.jpg" + }, + "stat": { + "aid": 836926413, + "view": 1903, + "danmaku": 0, + "reply": 7, + "favorite": 142, + "coin": 34, + "share": 30, + "now_rank": 0, + "his_rank": 0, + "like": 118, + "dislike": 0, + "vt": 0, + "vv": 1903 + }, + "dynamic": "", + "cid": 1423127570, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1xg4y1e7kY", + "first_frame": "http://i0.hdslb.com/bfs/storyff/n240129qn55at7dr1775k12hp34tw284_firsti.jpg", + "pub_location": "湖北", + "bvid": "BV1xg4y1e7kY", + "inter_video": false, + "resource_type": "ugc", + "subtitle": "", + "enable_vt": 0 + }, + …… + ] + } +} +``` + +
+ +#### 查询用户最近点赞视频(APP) + +> https://app.bilibili.com/x/v2/space/likearc + +*请求方式:GET* + +认证方式:APP + +如设置隐私查看自己的需要认证 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ----------- | ------ | -------- | +| access_key | str | APP登录Token | APP方式必要 | | +| appkey | str | APP密钥 | APP方式必要 | | +| vmid | num | 目标用户mid | 必要 | | +| pn | num | 页码 | 非必要 | 默认为1 | +| ps | num | 每页项数 | 非必要 | 默认为20 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ----- | ---------- | ---- | +| count | num | 点赞的视频数 | | +| item | array | 点赞视频列表 | | + +`item`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------------ | ---- | +| 0 | obj | 点赞的视频信息1 | | +| n | obj | 点赞的视频信息(n+1) | | +| …… | obj | …… | | + +`item`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ---- | ------------ | ---------------------- | +| title | str | 稿件标题 | | +| subtitle | str | 空 | | +| tname | str | 空 | | +| cover | str | 封面图片 url | | +| cover_icon | str | 空 | | +| uri | str | APP 跳转 uri | 如`bilibili://video/2` | +| param | str | 稿件 avid | | +| goto | str | av | | +| length | num | 空 | | +| duration | num | 稿件视频长度 | 单位为秒 | +| is_popular | bool | (?) | | +| is_steins | bool | (?) | | +| is_ugcpay | bool | (?) | | +| is_cooperation | str | (?) | | +| is_pgc | str | (?) | | +| is_live_playback | str | (?) | | +| is_pugv | str | (?) | | +| is_fold | num | (?) | | +| play | num | 播放量 | | +| danmaku | num | 弹幕量 | | +| ctime | num | 发布时间 | 时间戳 | +| ugc_pay | num | 0 | | +| author | str | UP主昵称 | | +| state | bool | true | | +| videos | num | 0 | | +| view_content | str | 稿件播放量文案 | | +| icon_type | num | 0 | | +| publish_time_text | str | 空 | | + +**示例:** + +用户`mid=2`的点赞列表 + +```shell +curl -G 'https://app.bilibili.com/x/v2/space/likearc' \ + --data-urlencode 'appkey=1d8b6e7d45233436' \ + --data-urlencode 'access_key=xxx' \ + --data-urlencode 'vmid=2' \ + --data-urlencode 'ps=2' \ + --data-urlencode 'pn=1' \ +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "count": 2, + "item": [ + { + "title": "兄弟难舍也难分", + "subtitle": "", + "tname": "", + "cover": "http://i1.hdslb.com/bfs/archive/58f031a52eab6d5faec5a39dfaab5728f65672d5.jpg", + "cover_icon": "", + "uri": "bilibili://video/624351941?player_width=1080\u0026player_height=1920\u0026player_rotate=0", + "param": "624351941", + "goto": "av", + "length": "", + "duration": 216, + "is_popular": false, + "is_steins": false, + "is_ugcpay": false, + "is_cooperation": false, + "is_pgc": false, + "is_live_playback": false, + "is_pugv": false, + "is_fold": false, + "play": 423652, + "danmaku": 362, + "ctime": 1706320200, + "ugc_pay": 0, + "author": "甜蜜老张", + "state": true, + "videos": 0, + "view_content": "42.4万", + "icon_type": 0, + "publish_time_text": "" + }, + { + "title": "技能搭配不累,共赴热血团战!", + "subtitle": "", + "tname": "", + "cover": "http://i2.hdslb.com/bfs/archive/2094b8e0be819222d320e2841ee1c39f5f2e4357.jpg", + "cover_icon": "", + "uri": "bilibili://video/793597196?player_width=1280\u0026player_height=720\u0026player_rotate=0", + "param": "793597196", + "goto": "av", + "length": "", + "duration": 41, + "is_popular": false, + "is_steins": false, + "is_ugcpay": false, + "is_cooperation": false, + "is_pgc": false, + "is_live_playback": false, + "is_pugv": false, + "is_fold": false, + "play": 1237, + "danmaku": 2, + "ctime": 1704855559, + "ugc_pay": 0, + "author": "38047aa1-cb8a-4", + "state": true, + "videos": 0, + "view_content": "1237", + "icon_type": 0, + "publish_time_text": "" + } + ] + } +} +``` + +
+ +## 投稿 + + + +### 查询用户投稿视频明细 + +> https://api.bilibili.com/x/space/wbi/arc/search + +> ~~https://api.bilibili.com/x/space/arc/search~~ (已废弃,保留是方便遇到问题的人搜索到此处) + +*请求方式:GET* + +鉴权方式:[Wbi 签名](../misc/sign/wbi.md) + +另见 [根据关键词查找视频](../video/collection.md#根据关键词查找视频), 功能基本相同, 暂未发现风控校验 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------- | ---- | ------------ | ------ | ----------------------------------------------------------------------------- | +| mid | num | 目标用户mid | 必要 | | +| order | str | 排序方式 | 非必要 | 默认为pubdate
最新发布:pubdate
最多播放:click
最多收藏:stow | +| tid | num | 筛选目标分区 | 非必要 | 默认为0
0:不进行分区筛选
分区tid为所筛选的分区 | +| keyword | str | 关键词筛选 | 非必要 | 用于使用关键词搜索该UP主视频稿件 | +| pn | num | 页码 | 非必要 | 默认为 `1` | +| ps | num | 每页项数 | 非必要 | 默认为 `30` | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
-412:请求被拦截 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | -------------- | ---- | +| list | obj | 列表信息 | | +| page | obj | 页面信息 | | +| episodic_button | obj | “播放全部“按钮 | | +| is_risk | bool | | | +| gaia_res_type | num | | | +| gaia_data | obj | | | + +`data`中的`list`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ------ | ---------------- | ---- | +| slist | array | 空数组 | | +| tlist | obj | 投稿视频分区索引 | | +| vlist | array | 投稿视频列表 | | + +`list`中的`tlist`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ------------ | --------------------- | +| {tid} | obj | 该分区的详情 | 字段名为存在的分区tid | +| …… | obj | …… | 向下扩展 | + +`tlist`中的`{tid}`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | -------------------- | ---- | +| count | num | 投稿至该分区的视频数 | | +| name | str | 该分区名称 | | +| tid | num | 该分区tid | | + +`list`中的`vlist`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | obj | 投稿视频1 | | +| n | obj | 投稿视频(n+1) | | +| …… | obj | …… | …… | + +`list`中的`vlist`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------ | ---- | -------------- | ---------------------------- | +| aid | num | 稿件avid | | +| attribute | num | | | +| author | str | 视频UP主 | 不一定为目标用户(合作视频) | +| bvid | str | 稿件bvid | | +| comment | num | 视频评论数 | | +| copyright | str | 视频版权类型 | | +| created | num | 投稿时间 | 时间戳 | +| description | str | 视频简介 | | +| elec_arc_type | num | 充电为1,否则0 | 可能还有其他情况 | +| enable_vt | num | 0 | 作用尚不明确 | +| hide_click | bool | false | 作用尚不明确 | +| is_avoided | num | 0 | 作用尚不明确 | +| is_charging_arc | bool | 是否为充电视频 | | +| is_lesson_video | num | 是否为课堂视频 | 0:否
1:是 | +| is_lesson_finished | num | 课堂是否已完结 | 0:否
1:是 | +| is_live_playback | num | 是否为直播回放 | 0:否
1:是 | +| is_pay | num | 0 | 作用尚不明确 | +| is_self_view | bool | 是否仅自己可见 | | +| is_steins_gate | num | 是否为互动视频 | 0:否
1:是 | +| is_union_video | num | 是否为合作视频 | 0:否
1:是 | +| jump_url | str | 跳转链接 | 跳转到课堂的链接,否则为"" | +| length | str | 视频长度 | MM:SS | +| mid | num | 视频UP主mid | 不一定为目标用户(合作视频) | +| meta | obj | 所属合集或课堂 | 无数据时为 null | +| pic | str | 视频封面 | | +| play | num | 视频播放次数 | | +| playback_position | num | 百分比播放进度 | 封面下方显示的粉色条 | +| review | num | 0 | 作用尚不明确 | +| season_id | num | 合集或课堂编号 | 都不属于时为0 | +| subtitle | str | 空 | 作用尚不明确 | +| title | str | 视频标题 | | +| typeid | num | 视频分区tid | | +| video_review | num | 视频弹幕数 | | +| vt | num | 0 | 作用尚不明确 | +| vt_display | str | 空 | 作用尚不明确 | + +`list`中的`vlist`数组中的对象中的`meta`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------ | ---------------- | +| attribute | num | 0 | 作用尚不明确 | +| cover | str | 合集封面URL | | +| ep_count | num | 合集视频数量 | | +| ep_num | num | 合集视频数量 | | +| first_aid | num | 首个视频av号 | | +| id | num | 合集id | | +| intro | str | 合集介绍 | | +| mid | num | UP主uid | 若为课堂,则为0 | +| ptime | num | unix时间(s) | 最后更新时间 | +| sign_state | num | 0 | 作用尚不明确 | +| stat | obj | 合集统计数据 | | +| title | str | 合集名称 | | + +`list`中的`vlist`数组中的对象中的`meta`对象中的`stat`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------ | -------------------- | +| coin | num | 合集总投币数 | | +| danmaku | num | 合集总弹幕数 | | +| favorite | num | 合集总收藏数 | | +| like | num | 合集总点赞数 | | +| mtime | num | unix时间(s) | 其他统计数据更新时间 | +| reply | num | 合集总评论数 | | +| season_id | num | 合集id | | +| share | num | 合集总分享数 | | +| view | num | 合集总播放量 | | +| vt | num | 0 | 作用尚不明确 | +| vv | num | 0 | 作用尚不明确 | + +`data`中的`page`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ---------- | ---- | +| count | num | 总计稿件数 | | +| pn | num | 当前页码 | | +| ps | num | 每页项数 | | + +`data`中的`episodic_button`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---- | +| text | str | 按钮文字 | | +| uri | str | 全部播放页url | | + +**示例:** + +`pn`(页码)和`ps`(每页项数)只改变`vlist`中成员的多少与内容 + +以每页2项查询用户`mid=53456`的第1页投稿视频明细 + +```shell +curl -G 'https://api.bilibili.com/x/space/arc/search' \ +--data-urlencode 'mid=53456' \ +--data-urlencode 'ps=2' \ +--data-urlencode 'pn=1' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": { + "slist": [], + "tlist": { + "1": { + "tid": 1, + "count": 3, + "name": "动画" + }, + "129": { + "tid": 129, + "count": 1, + "name": "舞蹈" + }, + "160": { + "tid": 160, + "count": 96, + "name": "生活" + }, + "177": { + "tid": 177, + "count": 4, + "name": "纪录片" + }, + "181": { + "tid": 181, + "count": 50, + "name": "影视" + }, + "188": { + "tid": 188, + "count": 444, + "name": "科技" + }, + "196": { + "tid": 196, + "count": 2, + "name": "课堂" + } + }, + "vlist": [{ + "comment": 985, + "typeid": 250, + "play": 224185, + "pic": "http://i0.hdslb.com/bfs/archive/5e56c10a9bd67f2fcac46fdd0fc2caa8769700c8.jpg", + "subtitle": "", + "description": "这一次,我们的样片日记首次来到了西藏,在桃花季开启了藏东样片之旅!这趟“开荒”之旅我们跋山涉水,一路硬刚,多亏有路虎卫士这样的神队友撑全场!这次的素材我们也上传到了官网(ysjf.com/material),欢迎大家去看看~如果你喜欢这期视频,请多多支持我们,并把视频分享给你的朋友们一起看看!", + "copyright": "1", + "title": "和朋友去西藏拍样片日记……", + "review": 0, + "author": "影视飓风", + "mid": 946974, + "created": 1745290800, + "length": "22:11", + "video_review": 2365, + "aid": 114375683741573, + "bvid": "BV1ac5yzhE94", + "hide_click": false, + "is_pay": 0, + "is_union_video": 1, + "is_steins_gate": 0, + "is_live_playback": 0, + "is_lesson_video": 0, + "is_lesson_finished": 0, + "lesson_update_info": "", + "jump_url": "", + "meta": { + "id": 2046621, + "title": "样片日记", + "cover": "https://archive.biliimg.com/bfs/archive/e2ca3e5a6672cf35c9e61ac02e8d739cc0aafa8b.jpg", + "mid": 946974, + "intro": "", + "sign_state": 0, + "attribute": 140, + "stat": { + "season_id": 2046621, + "view": 31755096, + "danmaku": 171253, + "reply": 33685, + "favorite": 409505, + "coin": 935105, + "share": 199467, + "like": 1791607, + "mtime": 1745309513, + "vt": 0, + "vv": 0 + }, + "ep_count": 13, + "first_aid": 238588630, + "ptime": 1745290800, + "ep_num": 13 + }, + "is_avoided": 0, + "season_id": 2046621, + "attribute": 16793984, + "is_charging_arc": false, + "elec_arc_type": 0, + "vt": 0, + "enable_vt": 0, + "vt_display": "", + "playback_position": 0, + "is_self_view": false + }, { + "comment": 0, + "typeid": 197, + "play": 8506, + "pic": "https://archive.biliimg.com/bfs/archive/489f3df26a190a152ad479bfe50a73f1cd4c43c5.jpg", + "subtitle": "", + "description": "8节课,Tim和青青带你用iPhone拍出电影感", + "copyright": "1", + "title": "【影视飓风】只看8节课,用iPhone拍出电影感", + "review": 0, + "author": "影视飓风", + "mid": 946974, + "created": 1744865737, + "length": "00:00", + "video_review": 9, + "aid": 114351440726681, + "bvid": "BV1WB5ezxEnz", + "hide_click": false, + "is_pay": 0, + "is_union_video": 0, + "is_steins_gate": 0, + "is_live_playback": 0, + "is_lesson_video": 1, + "is_lesson_finished": 1, + "lesson_update_info": "8", + "jump_url": "https://www.bilibili.com/cheese/play/ss190402215", + "meta": { + "id": 190402215, + "title": "【影视飓风】只看8节课,用iPhone拍出电影感", + "cover": "https://archive.biliimg.com/bfs/archive/489f3df26a190a152ad479bfe50a73f1cd4c43c5.jpg", + "mid": 0, + "intro": "", + "sign_state": 0, + "attribute": 0, + "stat": { + "season_id": 190402215, + "view": 1111222, + "danmaku": 1853, + "reply": 0, + "favorite": 0, + "coin": 0, + "share": 0, + "like": 0, + "mtime": 0, + "vt": 0, + "vv": 0 + }, + "ep_count": 0, + "ptime": 1744865737, + "ep_num": 0 + }, + "is_avoided": 0, + "season_id": 190402215, + "attribute": 1073758592, + "is_charging_arc": false, + "elec_arc_type": 0, + "vt": 0, + "enable_vt": 0, + "vt_display": "", + "playback_position": 0, + "is_self_view": false + }] + }, + "page": { + "pn": 1, + "ps": 42, + "count": 786 + }, + "episodic_button": { + "text": "播放全部", + "uri": "//www.bilibili.com/medialist/play/946974?from=space" + }, + "is_risk": false, + "gaia_res_type": 0, + "gaia_data": null + } +} +``` + +
+ + +### 查询用户投稿明细(APP、无需wbi鉴权) + +> https://app.biliapi.com/x/v2/space/archive/cursor + +*请求方式:GET* + +可以获取APP端可获得的用户空间投稿所有信息 + +APP端请求对web端包容度最高,无需Cookie以外的任何认证,只需填写vmid即可查询 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------- | ---- | ----------------------- | -------------- | ------------- | +| vmid | num | 目标用户mid | 必要 | | +| aid | num | 请求返回起始视频 | 首次请求不需要 | 填写上次请求返回最后视频的aid | +| order | str | 排序方式 | 非必要 | `click`代表最多播放,`pubdate`代表最新发布 | +| sort | str | 确有影响,但这是什么呢? | 非必要 | 创建时间: asc
修改时间: desc | +| access_key | str | APP登录Token | APP方式必要 | | +| appkey | str | APP密钥 | APP方式必要 | | +| build | num | 版本 | APP方式必要 | 可为`8130300` | +| c_locale | str | 语言 | 非必要 | zh_CN | +| channel | num | 频道 | 非必要 | | +| fnval | num | 视频流类型 | 非必要 | | +| fnver | num | 请求时提供的fnver | 非必要 | 可为 0 | +| force_host | num | 源url类型 | 非必要 | 0:无限制 1:使用http 2:使用https | +| fourk | num | 是否允许 4K 视频 | 非必要 | 画质最高 1080P:0(默认)
画质最高 4K:1 | +| include_cursor| bool | 未知 | 非必要 | 可为false | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web`、`android` 等 | +| platform | str | 平台 | 非必要 | 可为`web` | +| ps | int | 每页条数 | 非必要 | 默认为 `20` | +| pn | int | 似乎不是页码 | 非必要 | 默认为 `32` | +| pn_policy | int | 未知 | 非必要 | 可为 `1` | +| s_locale | str | 语言 | 非必要 | zh_CN | +| statistics | str | 位置 | 非必要 | 可为{"appId":1,"platform":3,"version":"8.13.0","abtest":""} | +| ts | num | 秒级时间戳 | 非必要 | | +| voice_balance | num | 未知 | 非必要 | 默认为 `1` | +| sign | str | APP签名 | APP方式必要 | | + +**json回复:** + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 视频信息 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------------- | ------ | ------------- | ----------------------------- | +| count | num | 总数 | 0:成功
-400:请求错误 | +| episodic_button | obj | 播放按钮 | 播放按钮的显示文字与跳转链接 | +| has_next | bool | 有无后续 | true:有;false:没有 | +| has_prev | bool | 有无前置 | true:有;false:没有 | +| item | array | 视频列表 | 注意是item没有复数 | +| last_watched_locator | obj | 上次播放定位 | 上次播放定位的一些信息 | +| order | array | 排列方式 | 排列方式的显示与值 | + +`episodic_button`对象 + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ------ | ----------------- | ------ | +| text | str | 四个大字“播放全部” | | +| uri | str | 跳转链接 | | + +`item`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------ | ---- | +| 0 | obj | 视频信息1 | | +| n | obj | 视频信息(n+1) | | +| …… | obj | …… | …… | + +`item`数组元素: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ----- | ----------------------- | ------------------------ | +| author | str | 作者昵称 | | +| bvid | str | 视频bv号 | | +| cover | str | 封面url | | +| cover_icon | str | 封面icon?未知 | | +| ctime | num | 应该是发布时间秒级时间戳 | | +| cursor_attr | obj | 上次观看标记 | | +| danmaku | num | 弹幕数 | | +| duration | num | 视频时长 | | +| first_cid | num | 首个频道cid | | +| goto | str | 应该是跳转去向类型 | 已知av为视频 | +| icon_type | num | icon类型?未知 | | +| is_cooperation | bool | 是否为合作视频 | 如果true会有粉色合作视频标签 | +| is_fold | bool | 是否折叠?未知 | | +| is_live_playback | bool | 是否为直播回放 | 如果true会有粉色直播回放标签 | +| is_onself | bool | 是否自己?未知 | | +| is_pgc | bool | 是否开pgc | | +| is_popular | bool | 是否上热门 | 如果true会有热门标签 | +| is_pugv | bool | 未知 | | +| is_steins | bool | 未知 | | +| is_ugcpay | bool | 未知 | | +| length | num | 长度?未知 | | +| param | str | 参数,实际为视频aid | | +| play | num | 播放量 | | +| publish_time_text | str | 发布时间汉字字符串版 | | +| state | bool | 状态?未知 | | +| subtitle | str | 子标题 | | +| three_points | array | 三点按钮内容 | 关于稍后再看和分享的显示内容 | +| title | str | 标题 | | +| tname | str | tag的name | | +| ugc_pay | num | ugc支付?未知 | | +| uri | str | APP 跳转 uri | | +| video | num | 未知 | | +| view_content | str | 播放量字符串版 | | + +`item`元素中的`cursor_attr`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------- | ---- | ----------------------- | -------------------------------------- | +| is_last_watched_arc | bool | 是否为上次播放 | 如果ture则封面笼罩一层写有“上次播放”的灰幕 | +| rank | num | 视频所处该列表排名 | | + +`last_watched_locator`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------ | ----- | ----------------- | ------ | +| display_threshold | num | 显示阈值 | | +| insert_ranking | num | 嵌入排名 | | +| text | str | 定位上次观看字样 | | + +`order`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------ | ----------------- | +| 0 | obj | 最新发布的内容 | 内包括文字和值 | +| 1 | obj | 最多播放的内容 | 内包括文字和值 | + +**示例:** + +查询用户mid=1240283469的稿件 +以播放量排序,显示3个稿件,但假设aid=1301087872及以前稿件已经加载过 + +> https://app.biliapi.com/x/v2/space/archive/cursor?vmid=1240283469&order=click&ps=3&aid=1301087872 + +输入浏览器 + +
+查看响应示例: + +```json + +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "episodic_button": { + "text": "播放全部", + "uri": "bilibili://music/playlist/spacepage/1240283469?desc=1\u0026offset=0\u0026oid=0\u0026order=time\u0026page_type=1\u0026playlist_intro=UP%E4%B8%BB%E7%9A%84%E5%85%A8%E9%83%A8%E8%A7%86%E9%A2%91\u0026ps=20\u0026sort_field=2\u0026sort_hidden=1\u0026total_count=33\u0026user_name=%E7%A5%9E%E5%9D%A1%E5%86%9C%E8%8E%AB" + }, + "order": [ + { + "title": "最新发布", + "value": "pubdate" + }, + { + "title": "最多播放", + "value": "click" + } + ], + "count": 33, + "item": [ + { + "title": "【神坡农二】后半段更是天籁!汉堡仙人神坡农二吃完快餐深情演唱《樱花树下的约定》", + "subtitle": "", + "tname": "搞笑", + "cover": "http://i2.hdslb.com/bfs/archive/3e5d02f50b2e0a756cc5e3dd7f705abc58c3a439.jpg", + "cover_icon": "", + "uri": "bilibili://video/1351875564?history_progress=0\u0026player_height=1920\u0026player_rotate=0\u0026player_width=1080", + "param": "1351875564", + "goto": "av", + "length": "", + "duration": 45, + "is_popular": false, + "is_steins": false, + "is_ugcpay": false, + "is_cooperation": false, + "is_pgc": false, + "is_live_playback": false, + "is_pugv": false, + "is_fold": false, + "is_oneself": false, + "play": 1248, + "danmaku": 1, + "ctime": 1710518403, + "ugc_pay": 0, + "author": "神坡农莫", + "state": false, + "bvid": "BV1H6421w7Gy", + "videos": 1, + "three_point": [ + { + "type": "addtoview", + "icon": "https://i0.hdslb.com/bfs/app/25cc01346574a601dafd45c94226d92a67eed79a.png", + "text": "添加至稍后再看" + }, + { + "type": "share", + "icon": "https://i0.hdslb.com/bfs/app/a5787f586c72f2d6f6ade4b33c64908938c4a01f.png", + "text": "分享", + "share_succ_toast": "分享成功", + "share_fail_toast": "分享失败", + "share_path": "pages/video/video?avid=1351875564", + "short_link": "https://b23.tv/BV1H6421w7Gy" + } + ], + "first_cid": 1471110689, + "cursor_attr": { + "is_last_watched_arc": false, + "rank": 1 + }, + "view_content": "1248", + "icon_type": 0, + "publish_time_text": "3月16日" + }, + { + "title": "【迪迦奥特曼】亲自配音?迪迦超战神联合网络新星神坡农二!共同打造奥特曼大电影!", + "subtitle": "", + "tname": "搞笑", + "cover": "http://i0.hdslb.com/bfs/archive/c6c94d16aeeefca148c1694e45fd352b22cac3fb.jpg", + "cover_icon": "", + "uri": "bilibili://video/1950389780?history_progress=0\u0026player_height=1080\u0026player_rotate=0\u0026player_width=1920", + "param": "1950389780", + "goto": "av", + "length": "", + "duration": 101, + "is_popular": false, + "is_steins": false, + "is_ugcpay": false, + "is_cooperation": false, + "is_pgc": false, + "is_live_playback": false, + "is_pugv": false, + "is_fold": false, + "is_oneself": false, + "play": 1184, + "danmaku": 0, + "ctime": 1707431804, + "ugc_pay": 0, + "author": "神坡农莫", + "state": false, + "bvid": "BV1fC411x7uf", + "videos": 1, + "three_point": [ + { + "type": "addtoview", + "icon": "https://i0.hdslb.com/bfs/app/25cc01346574a601dafd45c94226d92a67eed79a.png", + "text": "添加至稍后再看" + }, + { + "type": "share", + "icon": "https://i0.hdslb.com/bfs/app/a5787f586c72f2d6f6ade4b33c64908938c4a01f.png", + "text": "分享", + "share_succ_toast": "分享成功", + "share_fail_toast": "分享失败", + "share_path": "pages/video/video?avid=1950389780", + "short_link": "https://b23.tv/BV1fC411x7uf" + } + ], + "first_cid": 1434820367, + "cursor_attr": { + "is_last_watched_arc": false, + "rank": 2 + }, + "view_content": "1184", + "icon_type": 0, + "publish_time_text": "2月9日" + } + ], + "last_watched_locator": { + "display_threshold": 10, + "insert_ranking": 6, + "text": "定位至上次观看" + }, + "has_next": true, + "has_prev": true + } +} + +``` + +
+ + +### 查询用户投稿相簿预览 + +
+相簿功能已下线, 以下接口失效, 参见 +#801 + + +> https://api.bilibili.com/x/space/album/index + +*请求方式:GET* + +所有类型的相簿 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------ | ------ | ------- | +| mid | num | 目标用户mid | 必要 | | +| ps | num | 获取的相簿量 | 非必要 | 默认为8 定义域 1-大于1700 (注意滥用风险) | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | -------- | --------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | array | 相簿列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | obj | 相簿内容1 | | +| n | obj | 相簿内容(n+1) | | +| …… | obj | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ------ | ----------- | -------------- | +| count | num | 总计图片数 | | +| ctime | num | 发布时间 | 时间戳 | +| description | str | 简介 | | +| doc_id | num | 相簿id | 非动态!!! | +| like | num | 点赞数 | | +| pictures | array | 图片内容 | | +| poster_uid | num | 上传用户mid | | +| title | str | 标题 | 动态内容无 | +| view | num | 浏览数 | | + +`data`数组中的对象中的`pictures`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | --------------------- | +| 0 | obj | 内容图片1 | | +| n | obj | 内容图片(n+1) | 项数取决于`count`的值 | +| …… | obj | …… | …… | + +`pictures`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | -------- | ----------- | +| img_height | num | 图片高度 | | +| img_size | num | 图片大小 | 单位为KByte | +| img_src | str | 图片url | | +| img_width | num | 图片宽度 | | + +**示例:** + +查询用户`mid=53456`的投稿相簿预览 + +```shell +curl -G 'https://api.bilibili.com/x/space/album/index' \ +--data-urlencode 'mid=53456' \ +--data-urlencode 'ps=2' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [{ + "doc_id": 60470424, + "poster_uid": 53456, + "title": "", + "description": "你醒啦![tv_大佬]\n之前说到过的百万粉纪念的视频已经定时在了今天下午七点,欢迎来看呀!", + "pictures": [{ + "img_src": "https://i0.hdslb.com/bfs/album/2840366e30bf7c0aba9da5adde1a771255a57bc7.jpg", + "img_width": 625, + "img_height": 134, + "img_size": 14 + }], + "count": 1, + "ctime": 1583444859, + "view": 1677521, + "like": 29974 + }, { + "doc_id": 58962388, + "poster_uid": 53456, + "title": "", + "description": "上次的那些写实儿童画发出来啦!可以打印下来辟邪[tv_大佬]", + "pictures": [{ + "img_src": "https://i0.hdslb.com/bfs/album/8acaf7c7897cb858cccab36c33a5e875adfef177.jpg", + "img_width": 2172, + "img_height": 3258, + "img_size": 2831 + }, { + "img_src": "https://i0.hdslb.com/bfs/album/1611b6b56d3d4328889a62b9f9bdc92e9d065532.jpg", + "img_width": 3456, + "img_height": 5184, + "img_size": 3024 + }, { + "img_src": "https://i0.hdslb.com/bfs/album/f3a30a2ef5b39711af8b945d54d85ffd1e932b8a.jpg", + "img_width": 1200, + "img_height": 757, + "img_size": 313 + }], + "count": 3, + "ctime": 1582881332, + "view": 1176646, + "like": 25734 + }] +} +``` + +
+ +
+ +### 查询用户投稿相簿明细 + +
+ +相簿功能已下线, 以下接口失效 + + +> https://api.vc.bilibili.com/link_draw/v1/doc/doc_list +> https://api.bilibili.com/x/dynamic/feed/draw/doc_list + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | ----------- | ------ | ------------------------------------------------------------ | +| uid | num | 目标用户mid | 必要 | | +| page_num | num | 页码 | 必要 | 默认为0 | +| page_size | num | 每页项数 | 必要 | 默认为30 | +| biz | str | 查询类型 | 非必要 | 全部:all
绘画:draw
摄影:photo
日常:daily
默认为all | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------- | +| code | num | 返回值 | 0:成功 | +| msg | str | 错误信息 | 默认为success | +| message | str | 错误信息 | 默认为success | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ------ | -------- | ---- | +| items | array | 相簿列表 | | + +`items`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | obj | 相簿内容1 | | +| n | obj | 相簿内容(n+1) | | +| …… | obj | …… | …… | + +`items`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ------ | ----------- | -------------- | +| count | num | 总计图片数 | | +| ctime | num | 发布时间 | 时间戳 | +| description | str | 简介 | | +| doc_id | num | 相簿id | 非动态!!! | +| like | num | 点赞数 | | +| pictures | array | 图片内容 | | +| poster_uid | num | 上传用户mid | | +| title | str | 标题 | 动态内容无 | +| view | num | 浏览数 | | + +`items`数组中的对象中的`pictures`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | --------------------- | +| 0 | obj | 内容图片1 | | +| n | obj | 内容图片(n+1) | 项数取决于`count`的值 | +| …… | obj | …… | …… | + +`pictures`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | -------- | ----------- | +| img_height | num | 图片高度 | | +| img_size | num | 图片大小 | 单位为KByte | +| img_src | str | 图片url | | +| img_width | num | 图片宽度 | | + +**示例:** + +查询用户`mid=53456`的投稿明细中的全部类型 + +```shell +curl -G 'https://api.vc.bilibili.com/link_draw/v1/doc/doc_list' \ +--data-urlencode 'uid=2' \ +--data-urlencode 'page_num=1' \ +--data-urlencode 'page_size=2' \ +--data-urlencode 'biz=all' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "success", + "message": "success", + "data": { + "items": [{ + "doc_id": 59015720, + "poster_uid": 2, + "title": "", + "description": "6影是真的无脑,2个宝石都护不住(设计师:这真是太酷了)", + "pictures": [{ + "img_src": "http://i0.hdslb.com/bfs/album/8456f050ec8639c6e0cef36aba27bfdedc550590.jpg", + "img_width": 1824, + "img_height": 840, + "img_size": 1024 + }], + "count": 1, + "ctime": 1582894607, + "view": 707073, + "like": 7055 + }, { + "doc_id": 46853140, + "poster_uid": 2, + "title": "", + "description": "#年度报告# #新年Flag# https://www.bilibili.com/blackboard/timemachine2019.html\n决定了,这就是我的新年Flag!今年我一定要…", + "pictures": [{ + "img_src": "http://i0.hdslb.com/bfs/album/5b3ae76f79d7cf2501afc3ca7c7da509dcf0e38a.jpg", + "img_width": 1125, + "img_height": 2184, + "img_size": 465 + }, { + "img_src": "http://i0.hdslb.com/bfs/album/87789fe9644337a1f7e6a0655a32584705af8bda.jpg", + "img_width": 1125, + "img_height": 2184, + "img_size": 421 + }, { + "img_src": "http://i0.hdslb.com/bfs/album/f752d7f3bb7952f6c0013b3f48ddcb07060b4721.jpg", + "img_width": 1125, + "img_height": 2184, + "img_size": 524 + }, { + "img_src": "http://i0.hdslb.com/bfs/active/7a52a411bccb716c8e67fe70e6c330d5209346de.jpg", + "img_width": 1125, + "img_height": 2184, + "img_size": 534 + }], + "count": 4, + "ctime": 1577966163, + "view": 833193, + "like": 5667 + }] + } +} +``` + +
+ +
+ +### 查询用户投稿专栏明细 + +> https://api.bilibili.com/x/space/wbi/article + +> ~~https://api.bilibili.com/x/space/article~~(旧链接) + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +鉴权方式:[Wbi 签名](../misc/sign/wbi.md) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|------|-----|-------|--------------------------------------------------------------------------|-----| +| mid | num | 用户uid | | √ | +| pn | num | | 默认:1 | | +| ps | num | | 默认:30
范围:\[1,30\] | | +| sort | str | | `publish_time`:最新发布
`view`:最多阅读
`fav`:最多收藏
默认:`publish_time` | | + +**json回复:** + +根对象 + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|--------------------| +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|----------|-------|----------|-----| +| articles | array | 专栏文章信息列表 | | +| pn | num | 本次请求分页页数 | | +| ps | num | 本次请求分页大小 | | +| count | num | 专栏文章总数 | | + +`data`对象 -> `articles`数组中的对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-------------------|-------|----------|------| +| id | num | 专栏文章id | | +| category | obj | 分类 | | +| categories | array | 分类 | | +| title | str | 标题 | | +| summary | str | 摘要 | | +| banner_url | str | 封面图 | | +| template_id | num | | | +| state | num | | | +| author | obj | UP主信息 | | +| reprint | num | | | +| image_urls | array | | | +| publish_time | num | 发布时间戳 | 单位:秒 | +| ctime | num | 提交时间戳 | 单位:秒 | +| stats | obj | 专栏文章数据统计 | | +| tags | array | 标签 | | +| words | num | | | +| dynamic | str | 粉丝动态文案 | | +| origin_image_urls | array | | | +| list | | `null` | | +| is_like | bool | | | +| media | obj | | | +| apply_time | str | `空串` | | +| check_time | str | `空串` | | +| original | num | | | +| act_id | num | | | +| dispute | | `null` | | +| authenMark | | `null` | | +| cover_avid | num | | | +| top_video_info | | `null` | | +| type | num | | | + +`data`对象 -> `articles`数组中的对象 -> `category`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-----------|-----|--------|-----| +| id | num | 分类id | | +| parent_id | num | 父级分类id | | +| name | str | 分类名称 | | + +`data`对象 -> `articles`数组中的对象 -> `categories`数组中的对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-----------|-----|--------|-----| +| id | num | 分类id | | +| parent_id | num | 父级分类id | | +| name | str | 分类名称 | | + +`data`对象 -> `articles`数组中的对象 -> `author`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-----------------|-----|--------|-----| +| mid | num | 用户uid | | +| name | str | 用户名 | | +| face | str | 头像 | | +| pendant | obj | 头像框信息 | | +| official_verify | obj | 账号认证信息 | | +| nameplate | obj | 成就勋章信息 | | +| vip | obj | 大会员信息 | | + +`data`对象 -> `articles`数组中的对象 -> `author`对象 -> `pendant`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|--------|-----|----------|-----| +| pid | num | 头像框id | | +| name | str | 头像框名称 | | +| image | str | 头像框图片url | | +| expire | num | 过期时间 | | + +`data`对象 -> `articles`数组中的对象 -> `author`对象 -> `official_verify`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|------|-----|------|------------------------------| +| type | num | 是否认证 | -1:无
0:个人认证
1:机构认证 | +| desc | str | 认证备注 | | + +`data`对象 -> `articles`数组中的对象 -> `author`对象 -> `nameplate`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-------------|-----|---------|-----| +| nid | num | 勋章id | | +| name | str | 勋章名称 | | +| image | str | 勋章图标 | | +| image_small | str | 勋章图标(小) | | +| level | str | 勋章等级 | | +| condition | str | 获取条件 | | + +`data`对象 -> `articles`数组中的对象 -> `author`对象 -> `vip`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|------------------|-----|------------|---------------------------------| +| type | num | 大会员类型 | 0:无
1:月大会员
2:年度及以上大会员 | +| status | num | 大会员状态 | 0:无
1:有 | +| due_date | num | 大会员过期时间时间戳 | 单位:毫秒 | +| vip_pay_type | num | 支付类型 | | +| theme_type | num | `0` | | +| label | obj | 大会员标签 | | +| avatar_subscript | num | 是否显示大会员图标 | 0:不显示
1:显示 | +| nickname_color | str | 大会员昵称颜色 | | + +`data`对象 -> `articles`数组中的对象 -> `author`对象 -> `vip`对象 -> `label`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-------------|-----|--------|------------------------------------------------------------------------------------------------------------------------------| +| path | str | `空串` | | +| text | str | 会员类型文案 | `大会员` `年度大会员` `十年大会员` `百年大会员` `最强绿鲤鱼` | +| label_theme | str | 会员标签 | vip:大会员
annual_vip:年度大会员
ten_annual_vip:十年大会员
hundred_annual_vip:百年大会员
fools_day_hundred_annual_vip:最强绿鲤鱼 | + +`data`对象 -> `articles`数组中的对象 -> `stats`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|----------|-----|-----|-------| +| view | num | 浏览数 | | +| favorite | num | 收藏数 | | +| like | num | 点赞数 | | +| dislike | num | 点踩数 | 恒为`0` | +| reply | num | 回复数 | | +| share | num | 转发数 | | +| coin | num | 投币数 | | +| dynamic | num | | | + +`data`对象 -> `articles`数组中的对象 -> `tags`数组中的对象 + +| 字段名 | 类型 | 内容 | 备注 | +|------|-----|------|-----| +| tid | num | 标签id | | +| name | str | 标签名称 | | + +`data`对象 -> `articles`数组中的对象 -> `media`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-----------|-----|------|-----| +| score | num | `0` | | +| media_id | num | `0` | | +| title | str | `空串` | | +| cover | str | `空串` | | +| area | str | `空串` | | +| type_id | num | `0` | | +| type_name | str | `空串` | | +| spoiler | num | `0` | | + +**示例:** + +```shell +curl -L -X GET 'https://api.bilibili.com/x/space/article?mid=300021061&pn=1&ps=2&sort=publish_time' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "articles": [ + { + "id": 18989884, + "category": { + "id": 15, + "parent_id": 3, + "name": "日常" + }, + "categories": [ + { + "id": 3, + "parent_id": 0, + "name": "生活" + }, + { + "id": 15, + "parent_id": 3, + "name": "日常" + } + ], + "title": "B站UP主日报2022年10月08日23点(v1.1)", + "summary": "冠:罗翔说刑法(2485.45万粉,+7204) 涨:肯德基(+18.37万粉) 掉:Overidea_China(-186850粉) 播:开心锤锤(+927.56万) 赞:荒草音乐(+31.02万) 赞:飞翔的丘丘人(+22.08万) 充:冰糖IO(+210)", + "banner_url": "https://i0.hdslb.com/bfs/article/5e53260f58f77fff0b8ba6b20179db85b8741b76.jpg", + "template_id": 4, + "state": 0, + "author": { + "mid": 300021061, + "name": "狸工智能", + "face": "https://i1.hdslb.com/bfs/face/4cba9bc9d6cf6935a37ec156dedb8f8d26c1df95.jpg", + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0 + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "nameplate": { + "nid": 3, + "name": "白银殿堂", + "image": "https://i2.hdslb.com/bfs/face/f6a31275029365ae5dc710006585ddcf1139bde1.png", + "image_small": "https://i2.hdslb.com/bfs/face/b09cdb4c119c467cf2d15db5263b4f539fa6e30b.png", + "level": "高级勋章", + "condition": "单个自制视频总播放数>=10万" + }, + "vip": { + "type": 0, + "status": 0, + "due_date": 0, + "vip_pay_type": 0, + "theme_type": 0, + "label": { + "path": "", + "text": "", + "label_theme": "" + }, + "avatar_subscript": 0, + "nickname_color": "" + } + }, + "reprint": 0, + "image_urls": [ + "https://i0.hdslb.com/bfs/article/8e5497f7854e7df3468fbc29b0dd10fcf17d1223.png" + ], + "publish_time": 1665278884, + "ctime": 1665278884, + "stats": { + "view": 689, + "favorite": 2, + "like": 61, + "dislike": 0, + "reply": 18, + "share": 0, + "coin": 1, + "dynamic": 0 + }, + "words": 0, + "dynamic": "狸子的UP主日报📰v1.1,每天稳定更新~(如果咕咕咕了,请艾特狸子LePtC检查狐务器 [tv_微笑] #排行榜##大数据##狸工智能#", + "origin_image_urls": [ + "https://i0.hdslb.com/bfs/article/5e53260f58f77fff0b8ba6b20179db85b8741b76.jpg" + ], + "list": null, + "is_like": false, + "media": { + "score": 0, + "media_id": 0, + "title": "", + "cover": "", + "area": "", + "type_id": 0, + "type_name": "", + "spoiler": 0 + }, + "apply_time": "", + "check_time": "", + "original": 1, + "act_id": 0, + "dispute": null, + "authenMark": null, + "cover_avid": 0, + "top_video_info": null, + "type": 0 + }, + { + "id": 18972446, + "category": { + "id": 15, + "parent_id": 3, + "name": "日常" + }, + "categories": [ + { + "id": 3, + "parent_id": 0, + "name": "生活" + }, + { + "id": 15, + "parent_id": 3, + "name": "日常" + } + ], + "title": "B站UP主日报2022年10月07日23点(v1.1)", + "summary": "冠:罗翔说刑法(2484.73万粉,+8020) 涨:靖菌命(+3.61万粉) 掉:Overidea_China(-8593粉) 播:开心锤锤(+971.44万) 赞:荒草音乐(+53.14万) 赞:南方都市报(+18.05万) 充:内德维德(+190)", + "banner_url": "https://i0.hdslb.com/bfs/article/5e53260f58f77fff0b8ba6b20179db85b8741b76.jpg", + "template_id": 4, + "state": 0, + "author": { + "mid": 300021061, + "name": "狸工智能", + "face": "https://i1.hdslb.com/bfs/face/4cba9bc9d6cf6935a37ec156dedb8f8d26c1df95.jpg", + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0 + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "nameplate": { + "nid": 3, + "name": "白银殿堂", + "image": "https://i2.hdslb.com/bfs/face/f6a31275029365ae5dc710006585ddcf1139bde1.png", + "image_small": "https://i2.hdslb.com/bfs/face/b09cdb4c119c467cf2d15db5263b4f539fa6e30b.png", + "level": "高级勋章", + "condition": "单个自制视频总播放数>=10万" + }, + "vip": { + "type": 0, + "status": 0, + "due_date": 0, + "vip_pay_type": 0, + "theme_type": 0, + "label": { + "path": "", + "text": "", + "label_theme": "" + }, + "avatar_subscript": 0, + "nickname_color": "" + } + }, + "reprint": 0, + "image_urls": [ + "https://i0.hdslb.com/bfs/article/8e5497f7854e7df3468fbc29b0dd10fcf17d1223.png" + ], + "publish_time": 1665189149, + "ctime": 1665189149, + "stats": { + "view": 1021, + "favorite": 1, + "like": 66, + "dislike": 0, + "reply": 21, + "share": 2, + "coin": 2, + "dynamic": 0 + }, + "tags": [ + { + "tid": 1598, + "name": "粉丝" + }, + { + "tid": 422982, + "name": "狸子" + }, + { + "tid": 526616, + "name": "大数据" + }, + { + "tid": 14082112, + "name": "狸工智能" + }, + { + "tid": 438, + "name": "排行榜" + } + ], + "words": 0, + "dynamic": "狸子的UP主日报📰v1.1,每天稳定更新~(如果咕咕咕了,请艾特狸子LePtC检查狐务器 [tv_微笑] #排行榜##大数据##狸工智能#", + "origin_image_urls": [ + "https://i0.hdslb.com/bfs/article/5e53260f58f77fff0b8ba6b20179db85b8741b76.jpg" + ], + "list": null, + "is_like": false, + "media": { + "score": 0, + "media_id": 0, + "title": "", + "cover": "", + "area": "", + "type_id": 0, + "type_name": "", + "spoiler": 0 + }, + "apply_time": "", + "check_time": "", + "original": 1, + "act_id": 0, + "dispute": null, + "authenMark": null, + "cover_avid": 0, + "top_video_info": null, + "type": 0 + } + ], + "pn": 1, + "ps": 2, + "count": 1563 + } +} +``` + +
+ +### 查询用户专栏文集明细 + +> https://api.bilibili.com/x/article/up/lists + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|----------|-----|-------|-----|-------------------| +| mid | num | 用户uid | √ | | +| sort | num | 排序方式 | | 0:最近更新
1:最多阅读 | +| jsonp | str | | | | +| callback | str | | | | + +**json回复:** + +根对象 + +| 字段名 | 类型 | 内容 | 备注 | +|---------|-----|------|--------------------| +| code | num | 响应码 | 0:成功
-400:请求错误 | +| message | str | 0 | | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象 + +| 字段名 | 类型 | 内容 | 备注 | +|-------|-------|--------|-----| +| lists | array | 文集信息列表 | | +| total | num | 文集总数 | | + +`data`对象 -> `lists`数组中的对象 + +| 字段名 | 类型 | 内容 | 备注 | +|----------------|-----|---------|------| +| id | num | 文集id | | +| mid | num | 作者uid | | +| name | str | 文集名称 | | +| image_url | str | 封面 | | +| update_time | num | 最后更新时间戳 | 单位:秒 | +| ctime | num | 创建时间戳 | 单位:秒 | +| publish_time | num | | 单位:秒 | +| summary | str | `空串` | | +| words | num | 总字数 | | +| read | num | 阅读量 | | +| articles_count | num | 包含文章数 | | +| state | num | `1` | | +| reason | str | `空串` | | +| apply_time | str | `空串` | | +| check_time | str | `空串` | | + +**示例:** + +```shell +curl -X GET 'https://api.bilibili.com/x/article/up/lists' \ + --data-urlencode 'mid=2859372' \ + --data-urlencode 'sort=0' +``` + +
+点击查看 + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "lists": [ + { + "id": 77163, + "mid": 2859372, + "name": "碟报", + "image_url": "https://i0.hdslb.com/bfs/article/96d2b3d2a72e6497a011c885ab9245c51507ce18.png", + "update_time": 1664854854, + "ctime": 1554785697, + "publish_time": 1664863200, + "summary": "", + "words": 71532, + "read": 478726, + "articles_count": 113, + "state": 1, + "reason": "", + "apply_time": "", + "check_time": "" + }, + { + "id": 26407, + "mid": 2859372, + "name": "周榜", + "image_url": "https://i0.hdslb.com/bfs/article/96d2b3d2a72e6497a011c885ab9245c51507ce18.png", + "update_time": 1664721205, + "ctime": 1537942450, + "publish_time": 1664721307, + "summary": "", + "words": 102099, + "read": 1366280, + "articles_count": 206, + "state": 1, + "reason": "", + "apply_time": "", + "check_time": "" + }, + { + "id": 107952, + "mid": 2859372, + "name": "制作委员会", + "image_url": "https://i0.hdslb.com/bfs/article/96d2b3d2a72e6497a011c885ab9245c51507ce18.png", + "update_time": 1646663919, + "ctime": 1563107348, + "publish_time": 1646910000, + "summary": "", + "words": 47564, + "read": 72911, + "articles_count": 10, + "state": 1, + "reason": "", + "apply_time": "", + "check_time": "" + }, + { + "id": 26457, + "mid": 2859372, + "name": "实时榜", + "image_url": "https://i0.hdslb.com/bfs/article/96d2b3d2a72e6497a011c885ab9245c51507ce18.png", + "update_time": 1603115712, + "ctime": 1537955117, + "publish_time": 1603115719, + "summary": "", + "words": 206741, + "read": 1136352, + "articles_count": 76, + "state": 1, + "reason": "", + "apply_time": "", + "check_time": "" + }, + { + "id": 49769, + "mid": 2859372, + "name": "预测", + "image_url": "https://i0.hdslb.com/bfs/article/96d2b3d2a72e6497a011c885ab9245c51507ce18.png", + "update_time": 1593933314, + "ctime": 1546153226, + "publish_time": 1593933314, + "summary": "", + "words": 2518, + "read": 55123, + "articles_count": 6, + "state": 1, + "reason": "", + "apply_time": "", + "check_time": "" + }, + { + "id": 96916, + "mid": 2859372, + "name": "书籍周榜", + "image_url": "https://i0.hdslb.com/bfs/article/96d2b3d2a72e6497a011c885ab9245c51507ce18.png", + "update_time": 1559815260, + "ctime": 1559815159, + "publish_time": 1559815577, + "summary": "", + "words": 272, + "read": 2955, + "articles_count": 1, + "state": 1, + "reason": "", + "apply_time": "", + "check_time": "" + }, + { + "id": 96610, + "mid": 2859372, + "name": "原始周榜存档", + "image_url": "https://i0.hdslb.com/bfs/article/96d2b3d2a72e6497a011c885ab9245c51507ce18.png", + "update_time": 1559721231, + "ctime": 1559720762, + "publish_time": 1559721271, + "summary": "", + "words": 290, + "read": 1498, + "articles_count": 1, + "state": 1, + "reason": "", + "apply_time": "", + "check_time": "" + }, + { + "id": 26453, + "mid": 2859372, + "name": "杂谈", + "image_url": "https://i0.hdslb.com/bfs/article/96d2b3d2a72e6497a011c885ab9245c51507ce18.png", + "update_time": 1557303117, + "ctime": 1537954625, + "publish_time": 1557303168, + "summary": "", + "words": 10673, + "read": 38363, + "articles_count": 4, + "state": 1, + "reason": "", + "apply_time": "", + "check_time": "" + }, + { + "id": 59028, + "mid": 2859372, + "name": "新春访谈", + "image_url": "https://i0.hdslb.com/bfs/article/96d2b3d2a72e6497a011c885ab9245c51507ce18.png", + "update_time": 1549878596, + "ctime": 1549343048, + "publish_time": 1549884125, + "summary": "", + "words": 33472, + "read": 34597, + "articles_count": 13, + "state": 1, + "reason": "", + "apply_time": "", + "check_time": "" + } + ], + "total": 9 + } +} +``` + +
+ +### 查询用户投稿音频明细 + +> https://api.bilibili.com/audio/music-service/web/song/upper + +*请求方法: GET* + + + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --- | --- | --- | --- | --- | +| mid | num | 用户 mid | 必要 | | +| pn | num | 页码 | 必要 | 默认为 1 | +| ps | num | 每页项数 | 必要 | 默认为 30 | +| order | str | 排序方式 | 必要 | 1: 最新发布
2: 最多播放
3: 最多收藏 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| code | num | 返回值 | 0: 成功
72000000: 缺少参数 | +| msg | str | 返回信息 | 成功为 `success` | +| data | str | 数据本体 | 失败时不存在 | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| curPage | num | 当前页码 | | +| pageCount | num | 总页数 | | +| totalSize | num | 总计数 | | +| pageSize | num | 每页项数 | | +| data | array | 音频列表 | | + +`data` 对象中的 `data` 数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| id | num | 音频 AU 号 | | +| uid | num | 用户 mid | | +| uname | str | 用户名 | | +| author | null | | | +| title | str | 音频标题 | | +| cover | str | 音频封面图片 URL | | +| intro | null | | | +| lyric | str | 音频歌词 URL | | +| crtype | num | 1 | | +| duration | num | 音频时长 | 单位为 秒 | +| passtime | num | 发布时间 | UNIX 秒级时间戳 | +| curtime | num | 0 | | +| aid | null | | | +| cid | null | | | +| msid | null | | | +| attr | null | | | +| limit | null | | | +| activityId | null | | | +| limitdesc | null | | | +| ctime | num | 发布时间 | UNIX 毫秒时间戳 | +| statistic | obj | 统计数 | | +| coin_num | num | 硬币数量 | | +| is_cooper | null | | | + +`data` 数组中的对象中的 `statistic` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| sid | num | 音频 AU 号 | | +| play | num | 播放数 | | +| collect | num | 收藏数 | | +| comment | num | 评论数 | | +| share | num | 分享数 | | + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/audio/music-service/web/song/upper' \ +--url-query 'uid=8047632' \ +--url-query 'pn=1' \ +--url-query 'ps=30' \ +--url-query 'order=2' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "msg": "success", + "data": { + "curPage": 1, + "pageCount": 1, + "totalSize": 2, + "pageSize": 30, + "data": [ + { + "id": 257709, + "uid": 8047632, + "uname": "哔哩哔哩弹幕网", + "author": null, + "title": "【2018拜年祭单品】与你同行~B With U~", + "cover": "http://i0.hdslb.com/bfs/music/0f890889c8e1101f37317def0c4c555068054c88.jpg", + "intro": null, + "lyric": "http://i0.hdslb.com/bfs/music/1519959250257709.lrc", + "crtype": 1, + "duration": 301, + "passtime": 1519878405, + "curtime": 0, + "aid": null, + "cid": null, + "msid": null, + "attr": null, + "limit": null, + "activityId": null, + "limitdesc": null, + "ctime": 1519875632000, + "statistic": { + "sid": 257709, + "play": 845264, + "collect": 21978, + "comment": 1983, + "share": 1685 + }, + "coin_num": 13368, + "is_cooper": null + }, + { + "id": 378521, + "uid": 8047632, + "uname": "哔哩哔哩弹幕网", + "author": null, + "title": "《B TOGETHER》-bilibili九周年主题曲", + "cover": "http://i0.hdslb.com/bfs/music/109136c63e16d83fbad5ec9282a6fb96498d8144.jpg", + "intro": null, + "lyric": "http://i0.hdslb.com/bfs/music/1529979007378521.lrc", + "crtype": 1, + "duration": 261, + "passtime": 1529928347, + "curtime": 0, + "aid": null, + "cid": null, + "msid": null, + "attr": null, + "limit": null, + "activityId": null, + "limitdesc": null, + "ctime": 1529928235000, + "statistic": { + "sid": 378521, + "play": 123264, + "collect": 5501, + "comment": 1591, + "share": 535 + }, + "coin_num": 3640, + "is_cooper": null + } + ] + } +} +``` + +
+ +## 频道 + + + +[所有旧接口](https://github.com/SocialSisterYi/bilibili-API-collect/blob/7d89ece2ac46425810647c4ac92acf5f3721cb68/docs/user/space.md#%E9%A2%91%E9%81%93) 已弃用, 现可用接口参见 [合集和视频列表信息](../video/collection.md) + +## 课程 + + + +### 查询用户发布的课程列表 + +> https://api.bilibili.com/pugv/app/web/season/page + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | -------- | +| mid | num | 目标用户mid | 必要 | | +| pn | num | 页码 | 非必要 | 默认为1 | +| ps | num | 每页项数 | 非必要 | 默认为20 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
53013:用户隐私设置未公开 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ----- | -------- | ---- | +| list | array | 课程列表 | | +| page | obj | 页面信息 | | + +`data`中的`page`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | -------------- | ------------------------------------- | +| next | bool | 是否存在下一页 | false:最后一页
true:存在下一页 | +| num | num | 当前页码 | | +| size | num | 每页项数 | | +| total | num | 总计项数 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | -------------------------- | +| 0 | obj | 课程1 | | +| n | obj | 课程(n+1) | 按照目标用户的发布顺序排列 | +| …… | obj | …… | | + +`data`中的`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | ------------- | +| cover | str | 课程封面url | | +| ep_count | num | 课程集数 | | +| link | str | 课程页面url | 手机版页面url | +| page | num | 1 | 作用尚不明确 | +| play | num | 课程播放数 | | +| season_id | num | 课程ssid | | +| status | str | 更新状态说明 | | +| subtitle | str | 课程副标题 | | +| title | str | 课程标题 | | + +**示例:** + +查询用户`mid=33683045`的课程发布列表 + +```shell +curl -G 'https://api.bilibili.com/pugv/app/web/season/page' \ +--data-urlencode 'mid=33683045' \ +--data-urlencode 'ps=5' \ +--data-urlencode 'pn=1' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "data": { + "items": [ + { + "cover": "http://i0.hdslb.com/bfs/archive/596575057885fff7f0ceff047437186cba459358.jpg", + "ep_count": 10, + "link": "https://m.bilibili.com/cheese/play/ss80", + "page": 1, + "play": 174467, + "season_id": 80, + "status": "共10期", + "subtitle": "百科全书式军事科普短视频系列", + "title": "《战忽知道》第一季" + }, + { + "cover": "http://i0.hdslb.com/bfs/archive/322aa94d27cece62d2a859caf71ac2426f29eee2.jpg", + "ep_count": 1, + "link": "https://m.bilibili.com/cheese/play/ss145", + "page": 1, + "play": 22155, + "season_id": 145, + "status": "更新至第1期", + "subtitle": "此课程为《局座:第四次工业革命来了》部分集数,请谨慎购买", + "title": "【体验课】局座讲5G:5G如何改变我们的生活?" + }, + { + "cover": "http://i0.hdslb.com/bfs/archive/b9794ac4507f8764e219df413b661b5faf499a19.jpg", + "ep_count": 10, + "link": "https://m.bilibili.com/cheese/play/ss113", + "page": 1, + "play": 49833, + "season_id": 113, + "status": "更新至第10期", + "subtitle": "百科全书式军事科普短视频系列", + "title": "《战忽知道》第二季" + }, + { + "cover": "http://i0.hdslb.com/bfs/archive/7351fcb33592a4bc7aac9f71d421b4b5ce0177d3.jpg", + "ep_count": 10, + "link": "https://m.bilibili.com/cheese/play/ss51", + "page": 1, + "play": 4981037, + "season_id": 51, + "status": "共10期", + "subtitle": "洞悉国际局势,学习战略思维", + "title": "局座的国际战略课" + }, + { + "cover": "http://i0.hdslb.com/bfs/archive/31e2a170b5a815e34f0537a2727b28f1b87dca18.jpg", + "ep_count": 10, + "link": "https://m.bilibili.com/cheese/play/ss121", + "page": 1, + "play": 30754, + "season_id": 121, + "status": "更新至第10期", + "subtitle": "百科全书式军事科普短视频系列", + "title": "《战忽知道》第三季" + } + ], + "page": { + "next": true, + "num": 1, + "size": 5, + "total": 8 + } + }, + "message": "success" +} +``` + +
+ +## 订阅 + + + +### 查询用户追番预览列表 + +> http://space.bilibili.com/ajax/Bangumi/getList + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +如设置隐私查看自己的需要认证 + +带有转义,且只能获取最多15条 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| mid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ------------------------ | ---------------------------------- | --------------------------- | +| status | bool | 状态 | false:失败
true:成功 | +| data | 失败:str
成功:obj | 失败:错误信息
成功:信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ----- | ------------ | ------------ | +| count | num | 总计追番数 | | +| pages | num | 0 | 作用尚不明确 | +| result | array | 追番预览列表 | | + +`data`中的`result`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | -------------------------- | +| 0 | obj | 追番1 | | +| n | obj | 追番(n+1) | 按照目标用户的关注顺序排列 | +| …… | obj | …… | | +| 14 | obj | 追番15 | 最后一项 | + +`data`中的`result`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | --------------- | --------------------------------- | +| brief | str | 简介 | | +| cover | str | 封面图片url | | +| evaluate | str | 空 | | +| favorites | num | 追番数 | | +| is_finish | num | 是否已完结 | 0:未完结
1:已完结 | +| last_ep_index | num | 0 | 作用尚不明确 | +| newest_ep_index | num | 最新一话 | 可能为0 | +| season_id | str | 番剧ssid | | +| share_url | str | 播放页面链接url | | +| title | str | 标题 | | +| total_count | num | 总计集数 | 未完结:-1
已完结:非0正整数 | + +**示例:** + +查看用户`mid=14082`的追番预览列表 + +```shell +curl -G 'http://space.bilibili.com/ajax/Bangumi/getList' \ +--data-urlencode 'mid=14082' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "status": true, + "data": { + "count": 25, + "pages": 0, + "result": [{ + "season_id": "29310", + "share_url": "http:\/\/bangumi.bilibili.com\/anime\/29310\/", + "title": "异度侵入 ID:INVADED", + "is_finish": 1, + "favorites": 3479220, + "newest_ep_index": 13, + "last_ep_index": 0, + "total_count": 13, + "cover": "http:\/\/i0.hdslb.com\/bfs\/bangumi\/image\/9bf9e66968f85b33ec3769a16c86b36dc984abbc.png", + "evaluate": "", + "brief": "本片讲述利用能检测出人们杀意的装置以及利用思想粒子做出的“井”,来探知事件真相的科幻故事。" + }, { + "season_id": "25739", + "share_url": "http:\/\/bangumi.bilibili.com\/anime\/25739\/", + "title": "关于我转生变成史莱姆这档事", + "is_finish": 1, + "favorites": 5518829, + "newest_ep_index": 0, + "last_ep_index": 0, + "total_count": 27, + "cover": "http:\/\/i0.hdslb.com\/bfs\/bangumi\/a4c0e0ccc44fe3949a734f546cf5bb07da925bad.png", + "evaluate": "", + "brief": "史莱姆生活,开始了。\n上班族的三上悟在道路上被歹徒给刺杀身亡后,回过神来发现自己转生到了异世界。\n不..." + }, + ………… + ] + } +} +``` + +
+ +### 查询用户追番(追剧)明细 + +> https://api.bilibili.com/x/space/bangumi/follow/list + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +如设置隐私查看自己的需要认证 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | -------------------- | +| vmid | num | 目标用户mid | 必要 | | +| pn | num | 页码 | 非必要 | 默认为1 | +| ps | num | 每页项数 | 非必要 | 默认为15 定义域1-30 | +| type | num | 查询类型 | 必要 | 1:追番
2:追剧 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
53013:用户隐私设置未公开 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ----- | ---------- | ---- | +| list | array | 追番列表 | | +| pn | num | 当前页码 | | +| ps | num | 每页项数 | | +| total | num | 总计追番数 | | + +`data`中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | -------------------------- | +| 0 | obj | 追番1 | | +| n | obj | 追番(n+1) | 按照目标用户的关注顺序排列 | +| …… | obj | …… | | + +`data`中的`list`数组中的对象: + +基本同「番剧详细信息」中的result对象(未完工) + +**示例:** + +查看用户`mid=14082`的追番明细 + +```shell +curl -G 'https://api.bilibili.com/x/space/bangumi/follow/list' \ +--data-urlencode 'vmid=14082' \ +--data-urlencode 'type=1' \ +--data-urlencode 'ps=2' \ +--data-urlencode 'pn=1' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "list": [{ + "season_id": 29310, + "media_id": 28224080, + "season_type": 1, + "season_type_name": "番剧", + "title": "异度侵入 ID:INVADED", + "cover": "http://i0.hdslb.com/bfs/bangumi/image/9bf9e66968f85b33ec3769a16c86b36dc984abbc.png", + "total_count": 13, + "is_finish": 1, + "is_started": 1, + "is_play": 1, + "badge": "会员专享", + "badge_type": 0, + "rights": { + "allow_review": 1, + "is_selection": 1, + "selection_style": 1 + }, + "stat": { + "follow": 3475768, + "view": 87500861, + "danmaku": 1334654, + "reply": 316632, + "coin": 835150, + "series_follow": 3475242, + "series_view": 87500861 + }, + "new_ep": { + "id": 307774, + "index_show": "全13话", + "cover": "http://i0.hdslb.com/bfs/archive/3dce2b856a7b0ea667aa288b51b7c0478fa56c4d.jpg", + "title": "13", + "long_title": "CHANNELEDⅡ", + "pub_time": "2020-03-23 00:30:00", + "duration": 1481000 + }, + "rating": { + "score": 9.8, + "count": 262589 + }, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/image/664dbf039ec2da8dd982b697a108e28e87b9897e.jpg", + "season_status": 13, + "season_title": "TV", + "badge_ep": "会员", + "media_attr": 196608, + "season_attr": 0, + "evaluate": "本片讲述利用能检测出人们杀意的装置以及利用思想粒子做出的“井”,来探知事件真相的科幻故事。...", + "areas": [{ + "id": 2, + "name": "日本" + }], + "subtitle": "", + "first_ep": 307446, + "can_watch": 1, + "series": { + "series_id": 4760, + "title": "ID:INVADED", + "season_count": 1, + "new_season_id": 29310 + }, + "publish": { + "pub_time": "2020-01-06 00:30:00", + "pub_time_show": "敬请期待", + "release_date": "2020-01-06", + "release_date_show": "2020年1月6日" + }, + "mode": 2, + "section": [{ + "section_id": 39327, + "season_id": 29310, + "limit_group": 328, + "watch_platform": 15, + "copyright": "dujia", + "ban_area_show": 1 + }, { + "section_id": 39633, + "season_id": 29310, + "limit_group": 328, + "watch_platform": 15, + "type": 1, + "copyright": "dujia", + "title": "其他", + "ban_area_show": 1 + }, { + "section_id": 44101, + "season_id": 29310, + "limit_group": 316, + "watch_platform": 15, + "type": 4, + "copyright": "ugc", + "ban_area_show": 1 + }], + "url": "https://www.bilibili.com/bangumi/play/ss29310", + "follow_status": 2, + "is_new": 0, + "progress": "", + "both_follow": true + }, { + "season_id": 25739, + "media_id": 139252, + "season_type": 1, + "season_type_name": "番剧", + "title": "关于我转生变成史莱姆这档事", + "cover": "http://i0.hdslb.com/bfs/bangumi/a4c0e0ccc44fe3949a734f546cf5bb07da925bad.png", + "total_count": 27, + "is_finish": 1, + "is_started": 1, + "is_play": 1, + "badge": "会员专享", + "badge_type": 0, + "rights": { + "allow_review": 1, + "is_selection": 1, + "selection_style": 1 + }, + "stat": { + "follow": 5516519, + "view": 246739631, + "danmaku": 3802465, + "reply": 460225, + "coin": 1338958, + "series_follow": 5516535, + "series_view": 246739631 + }, + "new_ep": { + "id": 316957, + "index_show": "全27话", + "cover": "http://i0.hdslb.com/bfs/archive/81d07d1a478ce3a6209b557e14df9b9c78c42abb.jpg", + "title": "OAD03", + "long_title": "外传:利姆鲁的华丽教师生活 其一", + "pub_time": "2020-03-27 00:00:03", + "duration": 1493000 + }, + "rating": { + "score": 9.4, + "count": 83354 + }, + "square_cover": "http://i0.hdslb.com/bfs/bangumi/8d9f5b4a566d0547bc2e3f6f733b732a09c0d3d4.jpg", + "season_status": 13, + "season_title": "TV", + "badge_ep": "会员", + "media_attr": 0, + "season_attr": 0, + "evaluate": "史莱姆生活,开始了。\n上班族的三上悟在道路上被歹徒给刺杀身亡后,回过神来发现自己转生到了异世界。\n不过,自己居然是“史莱姆”!\n他在得到利姆鲁这个名字后开始了自己的史莱姆人生,随着与各个种族相处交流的...", + "areas": [{ + "id": 2, + "name": "日本" + }], + "subtitle": "", + "first_ep": 250460, + "can_watch": 1, + "series": { + "series_id": 4188, + "title": "关于我转生变成史莱姆这档事", + "season_count": 1, + "new_season_id": 25739 + }, + "publish": { + "pub_time": "2018-10-02 00:30:00", + "pub_time_show": "2018年10月02日00:30", + "release_date": "2018-10-02", + "release_date_show": "2018年10月2日" + }, + "mode": 2, + "section": [{ + "section_id": 34988, + "season_id": 25739, + "limit_group": 328, + "watch_platform": 15, + "copyright": "bilibili", + "ban_area_show": 1 + }], + "url": "https://www.bilibili.com/bangumi/play/ss25739", + "follow_status": 2, + "is_new": 0, + "progress": "", + "both_follow": true + }], + "pn": 1, + "ps": 2, + "total": 25 + } +} +``` + +
+ +### 查询用户关注的TAG(话题) + +> http://space.bilibili.com/ajax/tags/getSubList + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +如设置隐私查看自己的需要认证 + +带有转义 + +只显示前100个 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| mid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---------------------------- | -------------------------------------- | --------------------------- | +| status | bool | 返回值 | false:错误
true:正确 | +| data | 错误时:str
正确时:obj | 错误时:错误信息
正确时:数据本体 | 正确时不返回错误信息 | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ----- | ----------- | ---- | +| tags | array | 关注TAG列表 | | +| count | num | 关注TAG的数 | | + +`data`中的`tags`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | -------- | +| 0 | obj | 关注TAG1 | | +| n | obj | 关注TAG(n+1) | | +| …… | obj | …… | …… | +| 99 | obj | 关注TAG100 | 最后一项 | + +`data`中的`tags`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | ------------------- | ------------ | +| archive_count | num | 0 | 作用尚不明确 | +| cover | str | TAG图片url | 无则为空 | +| name | str | TAG名 | | +| notify | num | 1 | 作用尚不明确 | +| tag_id | num | tag_id | | +| updated_ts | str | 1970-01-01 08:00:00 | 作用尚不明确 | + +**示例:** + +查询用户`mid=2`的关注TAG + +```shell +curl -G 'http://space.bilibili.com/ajax/tags/getSubList' \ +--data-urlencode 'mid=2' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "status": true, + "data": { + "tags": [{ + "name": "豪宅", + "cover": "", + "tag_id": 47637, + "notify": 1, + "archive_count": 0, + "updated_ts": "1970-01-01 08:00:00" + }, { + "name": "死亡搁浅", + "cover": "", + "tag_id": 1737239, + "notify": 1, + "archive_count": 0, + "updated_ts": "1970-01-01 08:00:00" + }, + ………… + ], + "count": 58 + } +} +``` + +
diff --git a/bb-api-collect/docs/user/status_number.md b/bb-api-collect/docs/user/status_number.md new file mode 100644 index 0000000000..e33ac45b11 --- /dev/null +++ b/bb-api-collect/docs/user/status_number.md @@ -0,0 +1,305 @@ +# 用户状态数 + +## 关系状态数 +> https://api.bilibili.com/x/relation/stat + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | ---- | +| access_key | str | APP登录Token | APP方式必要 | | +| vmid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ----------- | ----------------------------------------------- | +| mid | num | 目标用户mid | | +| following | num | 关注数 | | +| whisper | num | 悄悄关注数 | 需要登录(Cookie或APP)
未登录或非自己恒为0 | +| black | num | 黑名单数 | 需要登录(Cookie或APP)
未登录或非自己恒为0 | +| follower | num | 粉丝数 | | + +**示例:** + +查询用户`mid=332704117`的关系状态数 + +```shell +curl -G 'https://api.bilibili.com/x/relation/stat' \ +--data-urlencode 'vmid=332704117' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "mid": 332704117, + "following": 32, + "whisper": 0, + "black": 0, + "follower": 919515 + } +} +``` + +
+ +## UP主状态数 + +> https://api.bilibili.com/x/space/upstat + +*请求方式:GET* + +认证方式:Cookie(SESSDATA)或APP + +注:该接口需要**任意用户**登录,否则**不会返回任何数据** + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------ | ----------- | ---- | +| access_key | str | APP登录Token | APP方式必要 | | +| mid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | ---------- | ----- | +| archive | obj | 视频播放量 | | +| article | obj | 专栏阅读量 | | +| likes | num | 获赞次数 | | + +`data`中的`archive`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ----- | ---------- | ----- | +| view | num | 视频播放量 | | + +`data`中的`article`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ----- | ---------- | ----- | +| view | num | 专栏阅读量 | | + +**示例:** + +查询用户`mid=456664753`的UP主状态数 + +```shell +curl -G 'https://api.bilibili.com/x/space/upstat' \ +--data-urlencode 'mid=456664753' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "archive": { + "view": 213567370 + }, + "article": { + "view": 3230808 + }, + "likes": 20295095 + } +} +``` + +
+ +## 用户导航栏状态数 + +> https://api.bilibili.com/x/space/navnum + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| mid | num | 目标用户mid | 必要 | | +| web_location | str | 333.999 | 不必要 || + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | ---------- | ------------ | +| video | num | 投稿视频数 | | +| bangumi | num | 追番数 | 无视隐私设置 | +| cinema | num | 追剧数 | 无视隐私设置 | +| channel | obj | 视频列表数 | | +| favourite | obj | 收藏夹数 | | +| tag | num | 关注TAG数 | 无视隐私设置 | +| article | num | 投稿专栏数 | | +| playlist | num | 0 | 作用尚不明确 | +| album | num | 投稿图文数 | | +| audio | num | 投稿音频数 | | +| pugv | num | 投稿课程数 | | +| upos | num | 动态数 | | +| season_num | num | 视频合集数 | | + +`data`中的`channel`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | ---------- | ------------ | +| master | num | 视频列表数 | | +| guest | num | 视频列表数 | | + +`data`中的`favourite`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ------------ | --------------------------------------- | +| master | num | 全部收藏夹数 | 需要登录(SESSDATA)
只能查看自己的 | +| guest | num | 公开收藏夹数 | | + +**示例:** + +查询用户`mid=645769214`的订阅&投稿状态数 + +```shell +curl -G 'https://api.bilibili.com/x/space/navnum' \ +--data-urlencode 'mid=645769214' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "video": 34, + "bangumi": 1, + "cinema": 0, + "channel": { + "master": 5, + "guest": 5 + }, + "favourite": { + "master": 0, + "guest": 0 + }, + "tag": 0, + "article": 1, + "playlist": 0, + "album": 59, + "audio": 0, + "pugv": 0, + "season_num": 1, + "opus": 59 + } +} +``` + +
+ +## 相簿投稿数 + +> https://api.vc.bilibili.com/link_draw/v1/doc/upload_count + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ----------- | ------ | ---- | +| uid | num | 目标用户mid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------- | +| code | num | 返回值 | 0:成功 | +| msg | str | 错误信息 | 默认为success | +| message | str | 错误信息 | 默认为success | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ---------------------- | ------------------ | +| all_count | num | 相簿总数 | 总数为以下三者之和 | +| draw_count | num | 发布绘画数 | | +| photo_count | num | 发布摄影数 | | +| daily_count | num | 发布日常(图片动态)数 | | + +**示例:** + + 查询用户`mid=53456`的投稿相簿数 + +```shell +curl -G 'https://api.vc.bilibili.com/link_draw/v1/doc/upload_count' \ +--data-urlencode 'uid=53456' +``` + +
+查看响应示例: + +```json +{ + "code":0, + "msg":"success", + "message":"success", + "data":{ + "all_count":92, + "draw_count":5, + "photo_count":0, + "daily_count":87 + } +} +``` + +
diff --git a/bb-api-collect/docs/video/action.md b/bb-api-collect/docs/video/action.md new file mode 100644 index 0000000000..c6ecb1a863 --- /dev/null +++ b/bb-api-collect/docs/video/action.md @@ -0,0 +1,893 @@ +# 稿件观众操作 + +## 点赞 + + + +### 点赞视频(web端) + +> https://api.bilibili.com/x/web-interface/archive/like + +*请求方式:POST* + +认证方式:仅可Cookie(SESSDATA) + +需验证 Cookie 中`buvid3`字段存在且正常, 否则将导致触发风控 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------- | ------------ | ---------------------- | +| aid | num | 稿件 avid | 必要(可选) | avid 与 bvid 任选一个 | +| bvid | str | 稿件 bvid | 必要(可选) | avid 与 bvid 任选一个 | +| like | num | 操作方式 | 必要 | 1:点赞
2:取消赞 | +| csrf | str | CSRF Token(位于 Cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-111:csrf校验失败
-400:请求错误
-403: 账号异常
10003:不存在该稿件
65004:取消点赞失败
65006:重复点赞 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +点赞视频`av79677524`/`BV1uJ411r7hL` + +avid方式: + +```shell +curl 'https://api.bilibili.com/x/web-interface/archive/like' \ +--data-urlencode 'aid=79677524' \ +--data-urlencode 'like=1' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +bvid方式: + +```shell +curl 'https://api.bilibili.com/x/web-interface/archive/like' \ +--data-urlencode 'bvid=BV1uJ411r7hL' \ +--data-urlencode 'like=1' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
+ +### 点赞视频(APP端) + +> https://app.bilibili.com/x/v2/view/like + +*请求方式:POST* + +认证方式:仅可APP + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | ---------------------- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| aid | num | 稿件 avid | 必要 | | +| like | num | 操作方式 | 必要 | 0:点赞
1:取消赞 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误
-403: 账号异常
10003:不存在该稿件 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ------------ | ---- | +| toast | str | 提示信息内容 | | + +**示例:** + +点赞视频`av79677524` + +```shell +curl 'https://app.bilibili.com/x/v2/view/like' \ +--data-urlencode 'access_key=xxx' \ +--data-urlencode 'aid=79677524' \ +--data-urlencode 'like=0' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "toast": "点赞收到!视频可能推荐哦" + } +} +``` + +
+ +### 判断视频近期是否被点赞(双端) + +> https://api.bilibili.com/x/web-interface/archive/has/like + +*请求方式:GET* + +认证方式:APP或Cookie(SESSDATA) + +注: 这一 API 实际上只能判断出视频**在近期内**是否被点赞, 并不能判断出视频是否被点赞. +「近期」的定义不明, 但至少半年前点赞过的视频, 用这一接口获取到的结果就已经是 `0` 了. 参见 [#380](https://github.com/SocialSisterYi/bilibili-API-collect/issues/380). + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | --------------------- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| aid | num | 稿件 avid | 必要(可选) | avid 与 bvid 任选一个 | +| bvid | str | 稿件 bvid | 必要(可选) | avid 与 bvid 任选一个 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ---------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | num | 被点赞标志 | 0:未点赞
1:已点赞 | + +**示例:** + +视频`av39330059`/`BV1Bt411z799`的状态为已点赞 + +avid方式: + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/archive/has/like' \ +--data-urlencode 'aid=39330059' \ +-b 'SESSDATA=xxx' +``` + +bvid方式: + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/archive/has/like' \ +--data-urlencode 'bvid=BV1Bt411z799' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": 1 +} +``` + +
+ +## 点踩 + +### 点踩视频(App端) + +> https://app.biliapi.net/x/v2/view/dislike + +*请求方式:POST* + +认证方式:仅可App + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------ | ----------------------- | +| access_key | str | APP 登录 Token | 必要 | | +| aid | num | 视频 aid | 必要 | | +| dislike | num | 操作类型 | 必要 | 0:点踩
1:取消点踩 | + +**json回复:** + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|-----------------------------------------------------------------------------------------| +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误
-404:啥都木有
65005:取消踩失败 未点踩过
65007:已踩过 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +点踩视频 + +```shell +curl -L -X POST 'https://app.biliapi.net/x/v2/view/dislike' \ +-H 'Content-Type: application/x-www-form-urlencoded' \ +--data-urlencode 'access_key=xxx' \ +--data-urlencode 'aid=xxx' \ +--data-urlencode 'dislike=0' +``` + +取消点踩 + +```shell +curl -L -X POST 'https://app.biliapi.net/x/v2/view/dislike' \ +-H 'Content-Type: application/x-www-form-urlencoded' \ +--data-urlencode 'access_key=xxx' \ +--data-urlencode 'aid=xxx' \ +--data-urlencode 'dislike=1' +``` + +## 投币 + + + + +### 投币视频(web端) + +> https://api.bilibili.com/x/web-interface/coin/add + +*请求方式:POST* + +认证方式:仅可Cookie(SESSDATA) + +需验证 Cookie 中`buvid3`字段存在且正常, 否则将导致触发风控 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----------- | ---- | ------------------------- | ------------ | --------------------------------------- | +| aid | num | 稿件 avid | 必要(可选) | avid 与 bvid 任选一个 | +| bvid | str | 稿件 bvid | 必要(可选) | avid 与 bvid 任选一个 | +| multiply | num | 投币数量 | 必要 | 上限为2 | +| select_like | num | 是否附加点赞 | 非必要 | 0:不点赞
1:同时点赞
默认为0 | +| csrf | str | CSRF Token(位于 Cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-102:账号被封停
-104:硬币不足
-111:csrf校验失败
-400:请求错误
-403: 账号异常
10003:不存在该稿件
34002:不能给自己投币
34003:非法的投币数量
34004:投币间隔太短
34005:超过投币上限 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +data 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------ | ----------------------------------------------------- | +| like | bool | 是否点赞成功 | true:成功
false:失败
已赞过则附加点赞失败 | + +**示例:** + +为视频`av90671873`/`BV1N7411A7wC`投币2枚 + +avid方式: + +```shell +curl 'https://api.bilibili.com/x/web-interface/coin/add' \ +--data-urlencode 'aid=90671873' \ +--data-urlencode 'select_like=1' \ +--data-urlencode 'multiply=2' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +bvid方式: + +```shell +curl 'https://api.bilibili.com/x/web-interface/coin/add' \ +--data-urlencode 'bvid=BV1N7411A7wC' \ +--data-urlencode 'select_like=1' \ +--data-urlencode 'multiply=2' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "like": true + } +} +``` + +
+ +### 投币视频(APP端) + +> https://app.bilibili.com/x/v2/view/coin/add + +*请求方式:POST* + +认证方式:仅可APP + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----------- | ---- | -------------- | ------------ | --------------------------------------- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| aid | num | 稿件 avid | 必要 | | +| multiply | num | 投币数量 | 必要 | 上限为2 | +| select_like | num | 附加点赞 | 非必要 | 0:不点赞
1:同时点赞
默认为0 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-102:账号被封停
-104:硬币不足
-400:请求错误
10003:不存在该稿件
34002:不能给自己投币
34003:非法的投币数量
34004:投币间隔太短
34005:超过投币上限 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +data 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------ | ----------------------------------------------------- | +| like | bool | 是否点赞成功 | true:成功
false:失败
已赞过则附加点赞失败 | + +为视频`av90671873`投币2枚 + +```shell +curl 'https://app.bilibili.com/x/v2/view/coin/add' \ +--data-urlencode 'access_key=xxx' \ +--data-urlencode 'aid=90671873' \ +--data-urlencode 'select_like=1' \ +--data-urlencode 'multiply=2' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "like": true + } +} +``` + +
+ +### 判断视频是否被投币(双端) + +> https://api.bilibili.com/x/web-interface/archive/coins + +*请求方式:GET* + +认证方式:APP或Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | --------------------- | +| access_key | str | APP 登录 Token | APP方式必要 | | +| aid | num | 稿件 avid | 必要(可选) | avid 与 bvid 任选一个 | +| bvid | str | 稿件 bvid | 必要(可选) | avid 与 bvid 任选一个 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------- | --------- | +| multiply | num | 投币枚数 | 未投币为0 | + +**示例:** + +视频`av37896701`/`BV18t411q7zz`的投币数为2枚 + +avid方式: + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/archive/coins' \ +--data-urlencode 'aid=37896701' \ +-b 'SESSDATA=xxx' +``` + +bvid方式: + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/archive/coins' \ +--data-urlencode 'bvid=BV18t411q7zz' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "multiply": 2 + } +} +``` + +
+ +## 收藏 + + + +### 收藏视频(双端) + +> https://api.bilibili.com/medialist/gateway/coll/resource/deal + +*请求方式:POST* + +认证方式:APP或Cookie(SESSDATA) + +鉴权方式:Cookie方式时需要验证referer为 `.bilibili.com`域名下 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------- | ---- | ------------------------ | -------------- | ------------------------------ | +| 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 方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-111:csrf校验失败
-400:请求错误
-403:访问权限不足
10003:不存在该稿件
11010: 您访问的内容不存在
11201:已经收藏过了
11202:已经取消收藏了
11203:达到收藏上限
72010017:参数错误 | +| message | str | 错误信息 | 正确为success | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | -------------------- | ----------------------- | +| prompt | bool | 是否为未关注用户收藏 | false:否
true:是 | + +**示例:** + +将视频`av49166435`添加到收藏夹`49166435`中 + +Cookie方式: + +```shell +curl 'https://api.bilibili.com/medialist/gateway/coll/resource/deal' \ +--data-urlencode 'rid=90671873' \ +--data-urlencode 'type=2' \ +--data-urlencode 'add_media_ids=49166435' \ +--data-urlencode 'del_media_ids=' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' \ +-e 'https://www.bilibili.com' +``` + +APP方式: + +```shell +curl 'https://api.bilibili.com/medialist/gateway/coll/resource/deal' \ +--data-urlencode 'access_key=xxx' \ +--data-urlencode 'rid=90671873' \ +--data-urlencode 'type=2' \ +--data-urlencode 'add_media_ids=49166435' \ +--data-urlencode 'del_media_ids=' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "data": { + "prompt": false + }, + "message": "success" +} +``` + +
+ +### 收藏视频(Web端) + +> https://api.bilibili.com/x/v3/fav/resource/deal + +*请求方式: POST* + +认证方式: Cookie(SESSDATA) + +**正文参数(application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------- | ---- | ---------------------------------- | ------------ | ------------------------------ | +| rid | num | 稿件 avid | 必要 | | +| type | num | 必须为2 | 必要 | | +| add_media_ids | nums | 需要加入的收藏夹 mlid | 必要(可选) | 同时添加多个,用`,`(%2C)分隔 | +| del_media_ids | nums | 需要取消的收藏夹 mlid | 必要(可选) | 同时取消多个,用`,`(%2C)分隔 | +| csrf | str | CSRF Token (即 Cookie 中 bili_jct) | 必要 | | +| platform | str | 平台标识? | 非必要 | web端: web | +| eab_x | num | 1 | 非必要 | 作用尚不明确 | +| ramval | num | 正整数 | 非必要 | 可能与在该页面的停留时间相关? | +| ga | num | 1 | 非必要 | 作用尚不明确 | +| gaia_source | str | ??? | 非必要 | web端: web_normal | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0: 成功
-101: 账号未登录
-111: csrf 校验失败
2001000: 参数错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | 错误时为 null 或不存在 | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | --------------------- | ----------------------- | +| prompt | bool | 是否为未关注用户收藏? | false:否
true:是 | +| ga_data | null | | 作用尚不明确 | +| toast_msg | str | 空 | 作用尚不明确 | +| success_num | num | 0 | 作用尚不明确 | + +**示例:** + +将视频 `av2` 添加到收藏夹 `645769214` 中 + +```shell +curl -X POST "https://api.bilibili.com/x/v3/fav/resource/deal" \ +--data-urlencode "rid=2" \ +--data-urlencode "type=2" \ +--data-urlencode "csrf=xxx" \ +--data-urlencode "add_media_ids=1428261914" \ +-b "SESSDATA=xxx" +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "prompt": false, + "ga_data": null, + "toast_msg": "", + "success_num": 0 + } +} +``` + +
+ +### 判断视频是否被收藏(双端) + +> https://api.bilibili.com/x/v2/fav/video/favoured + +*请求方式:GET* + +认证方式:APP或Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---------- | --------------------- | ------------ | ---- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| aid | num 或 str | 稿件 avid 或稿件 bvid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
-101:账号未登录 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +data 对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | -------- | ------------------------------- | +| count | num | 1 | 作用尚不明确 | +| favoured | bool | 是否收藏 | true:已收藏
false:未收藏 | + +**示例:** + +视频`av46281123`/`BV1Bb411H7Dv`的状态为已收藏 + +avid方式: + +```shell +curl -G 'https://api.bilibili.com/x/v2/fav/video/favoured' \ +--data-urlencode 'aid=46281123' \ +-b 'SESSDATA=xxx' +``` + +bvid方式: + +```shell +curl -G 'https://api.bilibili.com/x/v2/fav/video/favoured' \ +--data-urlencode 'aid=BV1Bb411H7Dv' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "count": 1, + "favoured": true + } +} +``` + +
+ +## 一键三连 + + + +### 一键三连视频(web端) + +> https://api.bilibili.com/x/web-interface/archive/like/triple + +*请求方式:POST* + +认证方式:仅可Cookie(SESSDATA) + +同时点赞投币收藏视频,收藏于默认收藏夹中 + +需验证 Cookie 中`buvid3`字段存在且正常, 否则将导致触发风控 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------- | ------------ | --------------------- | +| aid | num | 稿件 avid | 必要(可选) | avid 与 bvid 任选一个 | +| bvid | str | 稿件 bvid | 必要(可选) | avid 与 bvid 任选一个 | +| csrf | str | CSRF Token(位于 Cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- |------------------------------------------------------------------------------------------| +| code | num | 返回值 | 0:成功
-101:账号未登录
-111:csrf校验失败
-400:请求错误
10003:不存在该稿件
-403: 账号异常 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------------ | --------------------------- | +| like | bool | 是否点赞成功 | true:成功
false:失败 | +| coin | bool | 是否投币成功 | true:成功
false:失败 | +| fav | bool | 是否收藏成功 | true:成功
false:失败 | +| multiply | num | 投币枚数 | 默认为2 | + +**示例:** + +将视频`av91003840`/`BV1Wj411f79U`一键三连 + +avid方式: + +```shell +curl 'https://api.bilibili.com/x/web-interface/archive/like/triple' \ +--data-urlencode 'aid=91003840' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +bvid方式: + +```shell +curl 'https://api.bilibili.com/x/web-interface/archive/like/triple' \ +--data-urlencode 'bvid=BV1Wj411f79U' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "like": true, + "coin": true, + "fav": true, + "multiply": 2 + } +} +``` + +
+ +### 一键三连视频(APP端) + +> https://app.bilibili.com/x/v2/view/like/triple + +*请求方式:POST* + +认证方式:仅可APP + +同时点赞投币收藏视频,收藏于默认收藏夹中 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | -------------- | ------------ | ---- | +| access_key | str | APP 登录 Token | APP 方式必要 | | +| aid | num | 稿件 avid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | -------------------------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-101:账号未登录
-400:请求错误
10003:不存在该稿件 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------------ | --------------------------- | +| like | bool | 是否点赞成功 | true:成功
false:失败 | +| coin | bool | 是否投币成功 | true:成功
false:失败 | +| fav | bool | 是否收藏成功 | true:成功
false:失败 | +| multiply | num | 投币枚数 | 默认为2 | + +**示例:** + +将视频`av91003840`一键三连 + +```shell +curl 'https://app.bilibili.com/x/v2/view/like/triple' \ +--data-urlencode 'access_key=xxx' \ +--data-urlencode 'aid=91003840' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "like": true, + "coin": true, + "fav": true, + "multiply": 2 + } +} +``` + +
+ +## 分享 + +### 分享视频 (Web端) + +> https://api.bilibili.com/x/web-interface/share/add + +*请求方式:POST* + +鉴权方式: Cookie (buvid3) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------- | ------------ | --------------------- | +| aid | num | 稿件 aid | 必要 (可选) | aid 与 bvid 任选一个 | +| bvid | str | 稿件 bvid | 必要 (可选) | aid 与 bvid 任选一个 | +| csrf | str | CSRF Token (即 Cookie 中 bili_jct) | 不必要 | | +| eab_x | num | 2 | 不必要 | 作用尚不明确 | +| ramval | num | 0 | 不必要 | 作用尚不明确 | +| source | str | web_normal | 不必要 | | +| ga | num | 1 | 不必要 | 可能与风控有关? | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | ---------- | ------------------------------------------------------------------------- | +| code | num | 返回值 | 0: 成功
-101: 账号未登录
-111: csrf校验失败
-400: 请求错误
403: 账号异常,操作失败
71000: 重复分享 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | num | 当前分享数 | | + +**示例:** + +分享视频`BV1oA411776z` + +```shell +curl 'https://api.bilibili.com/x/web-interface/share/add' \ +--data-urlencode 'csrf=xxx' \ +--data-urlencode 'bvid=BV1oA411776z' +``` + +
+查看响应示例: + +```json +{ + "code":0, + "message":"0", + "ttl":1, + "data":19 +} +``` + +
diff --git a/bb-api-collect/docs/video/appeal.md b/bb-api-collect/docs/video/appeal.md new file mode 100644 index 0000000000..2324e45881 --- /dev/null +++ b/bb-api-collect/docs/video/appeal.md @@ -0,0 +1,425 @@ +# 稿件投诉 + +## 附件上传 + +> 附件上传与视频封面上传共用一个api。 + +## 获取投诉类型 + +> https://api.bilibili.com/x/web-interface/archive/appeal/tags + +*请求类型:GET* + +**json回复:** + +| 参数名 | 类型 | 内容 | 备注 | +| ------- | ------------- | ---- | ------- | +| code | num | | 成功为0 | +| message | str | | 成功为0 | +| ttl | num | 1 | | +| data | array | | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | ------------------ | +| 0 | obj | 类型条目 1 | | +| n | obj | 类型条目 (n+1) | 按照指定的顺序排列 | +| …… | obj | …… | …… | + +`data`数组中的对象 + +| 项 | 类型 | 内容 | 备注 | +| -------- | ------------------------------ | ---------------- | -------- | +| tid | num | 类型tid | | +| business | num | | 意义不明 | +| weight | num | 权重 | | +| round | num | | 意义不明 | +| state | num | | 意义不明 | +| name | str | 类型名称 | | +| remark | str | 类型备注 | | +| ctime | str | | 意义不明 | +| mtime | str | | 意义不明 | +| controls | 拥有时:array
没有时:null | 详细信息填写提示 | | + +`controls`数组中的对象: + +| 项 | 类型 | 内容 | 备注 | +| ----------- | ---- | -------------- | -------- | +| tid | num | 同上 | | +| bid | num | | 意义不明 | +| name | str | 提示名称 | | +| title | str | 提示标题 | | +| component | str | 需要填入的类型 | | +| placeholder | str | 文本框占位符 | | +| required | num | 是否为必填 | | + +**示例:** + +```bash +curl --location --request GET 'https://api.bilibili.com/x/web-interface/archive/appeal/tags' +``` + +
+查看响应示例 + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "tid": 1, + "business": 1, + "weight": 1, + "round": 2, + "state": 1, + "name": "其他", + "remark": "为帮助审核人员更快处理,请补充问题类型和出现位置等详细信息", + "ctime": "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, + "weight": 30, + "round": 2, + "state": 1, + "name": "引战", + "remark": "为帮助审核人员更快处理, 请补充引战的话题和出现位置", + "ctime": "2018-08-13T15:41:20+08:00", + "mtime": "2018-08-13T15:41:20+08:00", + "controls": null + }, + { + "tid": 10, + "business": 1, + "weight": 20, + "round": 2, + "state": 1, + "name": "不能参加充电", + "remark": "为帮助审核人员更快处理, 请补充问题类型和出现位置等详细信息", + "ctime": "2018-08-13T15:41:20+08:00", + "mtime": "2018-08-23T11:35:28+08:00", + "controls": null + }, + { + "tid": 52, + "business": 1, + "weight": 35, + "round": 2, + "state": 1, + "name": "转载/自制错误", + "remark": "为帮助审核人员更快处理, 请补充原创作品出处", + "ctime": "2018-08-13T15:41:20+08:00", + "mtime": "2023-09-20T16:23:39+08:00", + "controls": [ + { + "tid": 52, + "bid": 1, + "name": "出处", + "title": "原创视频出处", + "component": "link", + "placeholder": "请填写链接", + "required": 1 + } + ] + }, + { + "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, + "weight": 100, + "round": 1, + "state": 1, + "name": "违法违禁", + "remark": "为帮助审核人员更快处理,补充违规内容出现位置", + "ctime": "2018-08-13T15:41:20+08:00", + "mtime": "2018-08-13T15:41:20+08:00", + "controls": null + }, + { + "tid": 3, + "business": 1, + "weight": 90, + "round": 1, + "state": 1, + "name": "色情低俗", + "remark": "为帮助审核人员更快处理,补充违规内容出现位置", + "ctime": "2018-08-13T15:41:20+08:00", + "mtime": "2023-09-21T19:07:10+08:00", + "controls": null + }, + { + "tid": 4, + "business": 1, + "weight": 80, + "round": 1, + "state": 1, + "name": "低俗", + "remark": "为帮助审核人员更快处理,补充违规内容出现位置", + "ctime": "2018-08-13T15:41:20+08:00", + "mtime": "2018-08-13T15:41:20+08:00", + "controls": null + }, + { + "tid": 5, + "business": 1, + "weight": 70, + "round": 1, + "state": 1, + "name": "赌博诈骗", + "remark": "为帮助审核人员更快处理,补充违规内容出现位置", + "ctime": "2018-08-13T15:41:20+08:00", + "mtime": "2018-08-13T15:41:20+08:00", + "controls": null + }, + { + "tid": 6, + "business": 1, + "weight": 60, + "round": 1, + "state": 1, + "name": "血腥暴力", + "remark": "为帮助审核人员更快处理,补充违规内容出现位置", + "ctime": "2018-08-13T15:41:20+08:00", + "mtime": "2018-08-13T15:41:20+08:00", + "controls": null + }, + { + "tid": 7, + "business": 1, + "weight": 50, + "round": 1, + "state": 1, + "name": "人身攻击", + "remark": "为帮助审核人员更快处理,补充违规内容出现位置", + "ctime": "2018-08-13T15:41:20+08:00", + "mtime": "2018-08-13T15:41:20+08:00", + "controls": null + }, + { + "tid": 10000, + "business": 1, + "weight": 10, + "round": 1, + "state": 1, + "name": "青少年不良信息", + "remark": "为帮助审核人员更快处理, 请补充违规内容出现位置", + "ctime": "2018-08-13T15:41:20+08:00", + "mtime": "2018-08-13T15:41:20+08:00", + "controls": null + }, + { + "tid": 10013, + "business": 1, + "weight": 37, + "round": 1, + "state": 1, + "name": "不良封面/标题", + "remark": "为帮助审核人员更快处理, 请描述详细信息", + "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 + } + ] +} +``` + +
+ +## 投诉稿件 + +> https://api.bilibili.com/x/web-interface/appeal/v2/submit +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +**正文参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------ | ------ | ------------------------ | +| 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回复:** + +| 参数名 | 类型 | 内容 | 备注 | +| ------- | ---- | ------ | ------- | +| code | num | 返回码 | 成功为0 | +| message | str | | 成功为0 | +| ttl | | 1 | | + +**示例:举报av号为61080066的视频,理由为人身攻击,描述为“xxxxx”,并附带了一个图片附件 + +```bash +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"' \ +--form 'attach="https://archive.biliimg.com/bfs/archive/xxxxx.png"' +``` + +
+ 查看响应示例 + +```json +{ + "code":0, + "message":"0", + "ttl":1 +} +``` + +
diff --git a/bb-api-collect/docs/video/attribute_data.md b/bb-api-collect/docs/video/attribute_data.md new file mode 100644 index 0000000000..a3d1e70aea --- /dev/null +++ b/bb-api-collect/docs/video/attribute_data.md @@ -0,0 +1,71 @@ +# 视频属性数据说明 + +**PS**:以下部分内容来源不明,且部分值前端不可见,有待验证 + +## attribute字段值(稿件属性位) + +该字段前端已弃用, 相关接口返回恒为 `0`, 参见 [验证视频属性字段,实锤B站视频限流](https://shakaianee.top/archives/9/) + +该字段为二进制标志位,多个标志请用`OR`运算叠加 + +| 位 | 内容 | 备注 | +| ---- | ---------------------- | ------------------------------------------------------------ | +| 0 | 禁止排行 | | +| 1 | 动态禁止 | 禁止APP推送动态 | +| 2 | 禁止网页输出 | | +| 3 | 禁止客户端列表 | | +| 4 | 搜索禁止 | 打全标题或av/bv号都搜索不到的那种 | +| 5 | 海外禁止 | | +| 6 | 禁止推荐 | 禁止被APP端天马列表推荐 | +| 7 | 是否显示“禁止转载“标志 | **注:未经作者授权 禁止转载** | +| 8 | 是否高清 | 视频清晰度>=1080P | +| 9 | 是否PGC稿件 | 番剧&影视 | +| 10 | 允许承包 | | +| 11 | 是否番剧 | | +| 12 | 是否私单 | 存在商业推广恰饭内容 | +| 13 | 是否限制地区 | 大多数番剧&影视 | +| 14 | 禁止其他人添加TAG | | +| 15 | ? | 大多数旧视频会有这个标志 | +| 16 | 跳转 | 番剧及影视av/bv->ep跳转 | +| 17 | 是否影视 | | +| 18 | 是否付费 | | +| 19 | 推送动态 | | +| 20 | 家长模式 | | +| 21 | 是否限制游客和外链 | 分为两种情况,默认全部网页限制referer跳转,但第二种未登录无法访问,可以通过未登陆b站访问https://api.bilibili.com/x/web-interface/view 返回的code为-403来判断 | +| 22 | ? | | +| 23 | ? | | +| 24 | 是否为联合投稿 | | +| 25 | ? | | +| 26 | ? | | +| 27 | ? | | +| 28 | ? | | +| 29 | 是否为互动视频 | | + +## state字段值(稿件状态) + +| 值 | 内容 | 备注 | +| ---- | ------------ | ---------- | +| 1 | 橙色通过 | | +| 0 | 开放浏览 | | +| -1 | 待审 | | +| -2 | 被打回 | | +| -3 | 网警锁定 | | +| -4 | 被锁定 | 视频撞车了 | +| -5 | 管理员锁定 | | +| -6 | 修复待审 | | +| -7 | 暂缓审核 | | +| -8 | 补档待审 | | +| -9 | 等待转码 | | +| -10 | 延迟审核 | | +| -11 | 视频源待修 | | +| -12 | 转储失败 | | +| -13 | 允许评论待审 | | +| -14 | 临时回收站 | | +| -15 | 分发中 | | +| -16 | 转码失败 | | +| -20 | 创建未提交 | | +| -30 | 创建已提交 | | +| -40 | 定时发布 | | +| -50 | 仅UP主可见 | | +| -100 | 用户删除 | | + diff --git a/bb-api-collect/docs/video/collection.md b/bb-api-collect/docs/video/collection.md new file mode 100644 index 0000000000..40efe80536 --- /dev/null +++ b/bb-api-collect/docs/video/collection.md @@ -0,0 +1,1986 @@ +# 合集和视频列表信息 + +请注意区分 **合集(seasons_archives)** 和 **视频列表(seasons_series)** + +合集是后加入的功能, 图标为立体叠放的正方形(.icon-heji), 可以在创作中心管理, 参见 [合集管理](../creativecenter/season.md) + +列表即系列(series)或频道(channel), 图标为平面叠放的矩形且中央有播放按钮标识(.icon-ic_channel1), 在个人空间直接操作 + +此处保留原 Issue 的表述, 参见 [#945](https://github.com/SocialSisterYi/bilibili-API-collect/issues/945) + +## 获取视频合集信息 + +> https://api.bilibili.com/x/polymer/web-space/seasons_archives_list (需验证referer) +> +> https://api.bilibili.com/x/polymer/space/seasons_archives_list (旧接口, 不推荐使用, 无鉴权验证) + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|--------|-----|------|--------|-----| +| mid | num | 用户 mid | 必要 | 创建者的 mid,但也可以是任意的非负整数 | +| season_id | num | 视频合集 ID | 必要 | | +| sort_reverse | bool | 排序方式 | 可选 | true: 升序排序
false: 默认排序 | +| page_num | num | 页码索引 | 可选 | 默认为 1 | +| page_size | num | 单页内容数量 | 可选 | 默认为 30 | +| gaia_vtoken | str | 风控验证? | 可选 | 若被风控则必要(如User-Agent不正常) | +| web_location | str | 页面位置? | 可选 | 333.999 | +| w_rid | str | WBI 签名 | 可选 | 参见 [WBI 签名](../misc/sign/wbi.md) | +| wts | num | UNIX 秒级时间戳 | 可选 | 参见 [WBI 签名](../misc/sign/wbi.md) | + +**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 | 是否是互动视频 | | +| pic | str | 封面 URL || +| playback_position | num || 会随着播放时间增长,播放完成后为 -1 。单位为 % | +| pubdate | num | 发布日期 | Unix 时间戳 | +| stat | obj | 稿件信息 || +| state | num | 0 || +| title | str | 稿件标题|| +| ugc_pay | num | UGC 付费? | 0: 否 | +| vt_display | str | 空 | 旧接口无 | + +`archives`中的`stat`对象: + +| 字段 | 类型 | 内容 | 备注 | +|----------|-----|------|-----| +| view | num | 稿件播放量 || +| vt | num | 0 || + +`data`中的`meta`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-----------------|-----|--------------|--------| +| category | num | 0 | | +| cover | str | 合集封面 URL | | +| description | str | 合集描述 | | +| mid | num | UP 主 ID | | +| name | str | 合集标题 | | +| ptime | num | 发布时间 | Unix 时间戳 | +| season_id | num | 合集 ID | | +| total | num | 合集内视频数量 | | + +`data`中的`page`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-----------------|-----|--------------|--------| +| page_num | num | 分页页码 | | +| page_size | num | 单页个数 | | +| total | num | 合集内视频数量 | | + +**示例:** + +获取 `mid=37737161` 的 `season_id=1227671` 视频合集信息,默认排序,第 1 页,每页 30 个视频 + +```shell +curl -G "https://api.bilibili.com/x/polymer/space/seasons_archives_list" \ +--data-urlencode "mid=37737161" \ +--data-urlencode "sort_reverse=false" \ +--data-urlencode "season_id=1227671" \ +--data-urlencode "page_num=1" \ +--data-urlencode "page_size=30" +``` + +
+查看响应示例: + + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "aids": [ + 311606079, + 400546145 + ], + "archives": [ + { + "aid": 311606079, + "bvid": "BV1XN411K7g9", + "ctime": 1679651747, + "duration": 261, + "interactive_video": false, + "pic": "http://i2.hdslb.com/bfs/archive/234e6bd061176dba9e148f4373c52fa7cd2d801f.jpg", + "pubdate": 1679651747, + "stat": { + "view": 12145 + }, + "state": 0, + "title": "某些IT社区平台乱象,文章千篇一律,毫不注重版权,文章互相抄袭成潮流,希望能够好好管管!", + "ugc_pay": 0 + }, + { + "aid": 400546145, + "bvid": "BV1qo4y1L73P", + "ctime": 1682777426, + "duration": 335, + "interactive_video": false, + "pic": "http://i2.hdslb.com/bfs/archive/a6b6fb0330bbf6c500720a024e5a9ade24d888c3.jpg", + "pubdate": 1682777425, + "stat": { + "view": 52743 + }, + "state": 0, + "title": "某些搜索引擎得到的结果,官方网站反而排在一些诈骗广告后面,诱导用户下载大量捆绑垃圾软件", + "ugc_pay": 0 + } + ], + "meta": { + "category": 0, + "cover": "https://archive.biliimg.com/bfs/archive/5e1c1f77c3065ec31eec43d7e35f7a061602e4d6.jpg", + "description": "白马首席讲师吐槽系列视频", + "mid": 37737161, + "name": "水浅王八多,真假白马说", + "ptime": 1682777425, + "season_id": 1227671, + "total": 2 + }, + "page": { + "page_num": 1, + "page_size": 30, + "total": 2 + } + } +} +``` + +
+ +## 只获取系列视频 + +> https://api.bilibili.com/x/polymer/web-space/home/seasons_series + +*请求方式: GET* + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | ------------ | ------ | ---- | +| mid | num | 用户 mid | 必要 | | +| page_num | num | 页码索引 | 必要 | | +| page_size | num | 单页内容数量 | 必要 | | +| gaia_vtoken | str | 风控验证? | 可选 | 若被风控则必要(如User-Agent不正常) | +| w_rid | str | WBI 签名 | 不必要 | 参见 [WBI 签名](../misc/sign/wbi.md) | +| wts | num | UNIX 秒级时间戳 | 不必要 | 参见 [WBI 签名](../misc/sign/wbi.md) | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功
-352: 请求被风控
-400: 请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | -------- | -------- | +| items_lists | obj | 内容列表 | 套了个娃 | + +`data`中的`items_lists`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ----- | -------- | ---- | +| page | obj | 分页信息 | | +| seasons_list | array | 空 | | +| series_list | array | 系列列表 | | + +`items_lists`中的`page`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | -------- | ---- | +| page_num | num | 分页页码 | | +| page_size | num | 单页个数 | | +| total | num | 总页数 | | + +`items_lists`中的`series_list`数组: + +| 项 | 类型 | 内容 | 备注 | +| -- | ---- | ----------------- | ---- | +| 0 | obj | 第1个系列内容 | | +| 1 | obj | 第2个系列内容 | | +| …… | obj | …… | …… | +| n | obj | 第(n+1)个系列内容 | | + +`series_list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ----- | ----------------- | ------------- | +| archives | array | 系列视频列表 | | +| meta | obj | 系列元数据 | | +| recent_aids | array | 系列视频 aid 列表 | 内容类型为num | + +`series_list`中的`archives`数组: + +同[获取视频合集信息](#获取视频合集信息)中的`archives`数组 + +`series_list`中的`meta`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ----- | -------------- | ------------- | +| category | num | 1 | | +| cover | str | 系列封面 URL | | +| creator | str | auto | | +| ctime | num | 创建时间 | Unix 时间戳 | +| description | str | 系列描述 | | +| keywords | array | 系列关键词列表 | 内容类型为str | +| last_update_ts | num | 最近更新时间 | Unix 时间戳 | +| mid | num | UP 主 ID | | +| mtime | num | 修改时间 | Unix 时间戳 | +| name | str | 系列标题 | | +| raw_keywords | str | 原始系列关键词 | | +| series_id | num | 系列 ID | | +| state | num | 2 | | +| total | num | 系列视频数量 | | + +**示例:** + +```shell +curl -G "https://api.bilibili.com/x/polymer/web-space/home/seasons_series" \ +--data-urlencode "mid=37737161" \ +--data-urlencode "page_num=1" \ +--data-urlencode "page_size=10" +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "items_lists": { + "page": { + "page_num": 1, + "page_size": 10, + "total": 1 + }, + "seasons_list": [], + "series_list": [ + { + "archives": [ + { + "aid": 284063097, + "bvid": "BV1Fc411x7xF", + "ctime": 1705925782, + "duration": 8885, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i0.hdslb.com/bfs/archive/5aa1bb0a121d89969e9bd2634bc7ae23272bf850.jpg", + "playback_position": 0, + "pubdate": 1705925781, + "stat": { + "view": 14683, + "vt": 0 + }, + "state": 0, + "title": "Gradle 教程 已完结 (基于Kotlin DSL讲解) 4K蓝光画质 超强的脚本式项目依赖和构建工具", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 367948632, + "bvid": "BV1P94y1c7tV", + "ctime": 1703844221, + "duration": 52036, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i2.hdslb.com/bfs/archive/499aeb41a0428e05523b766e367540b04f7c3ae2.jpg", + "playback_position": 0, + "pubdate": 1703844220, + "stat": { + "view": 82997, + "vt": 0 + }, + "state": 0, + "title": "Kotlin 教程 已完结 (IDEA 2024 最新版) 4K蓝光画质+杜比音效 零基础入门一套搞定 入门到入土经典版", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 836303388, + "bvid": "BV1Hg4y1m7Ca", + "ctime": 1705401362, + "duration": 5873, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i1.hdslb.com/bfs/archive/a20b09d1cc1a81f6a9c5ed8ea322656e406be725.jpg", + "playback_position": 0, + "pubdate": 1705401362, + "stat": { + "view": 8417, + "vt": 0 + }, + "state": 0, + "title": "Kotlin 扩展篇 已完结 (IDEA 2024 最新版) 4K蓝光画质 与Java语言混合编程", + "ugc_pay": 0, + "vt_display": "" + } + ], + "meta": { + "category": 1, + "cover": "http://i0.hdslb.com/bfs/archive/5aa1bb0a121d89969e9bd2634bc7ae23272bf850.jpg", + "creator": "auto", + "ctime": 1705401630, + "description": "包含Kotlin语言学习的完整流程,正在不断完善中哦~", + "keywords": [ + "Kotlin" + ], + "last_update_ts": 1705925782, + "mid": 37737161, + "mtime": 1705925782, + "name": "Kotlin开心路线", + "raw_keywords": "Kotlin", + "series_id": 3908327, + "state": 2, + "total": 3 + }, + "recent_aids": [ + 284063097, + 367948632, + 836303388 + ] + }, + { + "archives": [ + { + "aid": 848832470, + "bvid": "BV1CL4y1i7qR", + "ctime": 1635258883, + "duration": 106474, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i0.hdslb.com/bfs/archive/45dddea811257f78ddd6f1e70197d95d7d6b5187.jpg", + "playback_position": 0, + "pubdate": 1635258883, + "stat": { + "view": 438645, + "vt": 0 + }, + "state": 0, + "title": "JavaWeb 教程 已完结(IDEA 2021版本)4K蓝光画质 入土到起立", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 566880413, + "bvid": "BV1Kv4y1x7is", + "ctime": 1676544280, + "duration": 25149, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i1.hdslb.com/bfs/archive/cc59de5afebc66447ba93ad9ea0ba73a9b09c117.jpg", + "playback_position": 0, + "pubdate": 1676544280, + "stat": { + "view": 87171, + "vt": 0 + }, + "state": 0, + "title": "Spring 核心教程 已完结(IDEA 2023最新版)4K蓝光画质 基于Spring6的全新重制版本 起立到起飞", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 615286308, + "bvid": "BV1Lh4y1M7kx", + "ctime": 1688117457, + "duration": 10373, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i0.hdslb.com/bfs/archive/5f860de4bc0fab30651ae93396f9c572be8380b2.jpg", + "playback_position": 0, + "pubdate": 1688117457, + "stat": { + "view": 41428, + "vt": 0 + }, + "state": 0, + "title": "Spring MVC 教程 已完结(IDEA 2023最新版)4K蓝光画质 基于Spring6的全新重制版本 起立到起飞", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 403104913, + "bvid": "BV1fV411M7aS", + "ctime": 1688560394, + "duration": 17611, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i1.hdslb.com/bfs/archive/c4557a16aa3519183d6ae0114e1c64107bb23703.jpg", + "playback_position": 0, + "pubdate": 1688560394, + "stat": { + "view": 59298, + "vt": 0 + }, + "state": 0, + "title": "Spring Security 教程 已完结(IDEA 2023最新版)4K蓝光画质 基于Spring6的全新重制版本 起立到起飞", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 828666773, + "bvid": "BV1xu4y1m7UP", + "ctime": 1689767299, + "duration": 29696, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i1.hdslb.com/bfs/archive/06cf686d4d3f7ce6731975ef59938d759283318e.jpg", + "playback_position": 0, + "pubdate": 1689767299, + "stat": { + "view": 108078, + "vt": 0 + }, + "state": 0, + "title": "Spring Boot 教程 已完结(IDEA 2023最新版)4K蓝光画质 基于SpringBoot 3 的全新重制版本 起飞到删库跑路", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 852857221, + "bvid": "BV1AL4y1j7RY", + "ctime": 1648811079, + "duration": 55544, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i2.hdslb.com/bfs/archive/629755f79c13c96c9b6d91da80257a352b29dd86.jpg", + "playback_position": 0, + "pubdate": 1648811079, + "stat": { + "view": 168251, + "vt": 0 + }, + "state": 0, + "title": "SpringCloud 教程 已完结(IDEA 2022.1最新版)4K蓝光画质 微服务开发", + "ugc_pay": 0, + "vt_display": "" + } + ], + "meta": { + "category": 1, + "cover": "http://i0.hdslb.com/bfs/archive/45dddea811257f78ddd6f1e70197d95d7d6b5187.jpg", + "creator": "auto", + "ctime": 1669273103, + "description": "已排序完成,共4个系列,请至少完成Java SE篇视频之后再开始JavaEE路线哦~ 整个路线大致为:JavaWeb基础篇、SSM成长篇、SpringBoot成熟篇、SpringCloud进阶篇", + "keywords": [ + "" + ], + "last_update_ts": 1696249622, + "mid": 37737161, + "mtime": 1696249622, + "name": "JavaEE通关路线", + "raw_keywords": "", + "series_id": 2800548, + "state": 2, + "total": 9 + }, + "recent_aids": [ + 848832470, + 566880413, + 615286308, + 403104913, + 828666773, + 852857221 + ] + }, + { + "archives": [ + { + "aid": 445283537, + "bvid": "BV14j411S76G", + "ctime": 1687946670, + "duration": 7008, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i1.hdslb.com/bfs/archive/208bb09ecf97fbbd73e45b3839715276ffbbe8f4.jpg", + "playback_position": 0, + "pubdate": 1687946670, + "stat": { + "view": 9483, + "vt": 0 + }, + "state": 0, + "title": "Apache Maven 依赖管理 极速上手 已完结(2021 版本)4K蓝光画质+杜比音效 从导入到冲突", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 813084463, + "bvid": "BV1r34y1p7j9", + "ctime": 1656909478, + "duration": 17457, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i2.hdslb.com/bfs/archive/798135f31dc9e03121458f32825dc81d8e403887.jpg", + "playback_position": 0, + "pubdate": 1656909478, + "stat": { + "view": 46179, + "vt": 0 + }, + "state": 0, + "title": "Docker 容器技术 已完结(2022 最新版)4K蓝光画质+杜比音效 从内卷到开摆", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 432905025, + "bvid": "BV1a3411f7nh", + "ctime": 1669296029, + "duration": 10393, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i2.hdslb.com/bfs/archive/d14c0fad064a224de7afb7edd147f8b335324c53.jpg", + "playback_position": 0, + "pubdate": 1669296029, + "stat": { + "view": 37040, + "vt": 0 + }, + "state": 0, + "title": "Linux 操作系统 光速入门 已完结(2021 版本)4K蓝光画质+杜比音效 从讨厌到喜欢", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 390385576, + "bvid": "BV19d4y147Df", + "ctime": 1669272992, + "duration": 23389, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i0.hdslb.com/bfs/archive/8ba763e1a1e14c47c1c178ecf21240896d3fbb5e.jpg", + "playback_position": 0, + "pubdate": 1669272992, + "stat": { + "view": 32189, + "vt": 0 + }, + "state": 0, + "title": "MySQL 数据库技术 已完结(2021版本)4K蓝光画质+杜比音效 从内卷到开摆", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 647924810, + "bvid": "BV1ce4y1W7YB", + "ctime": 1669275447, + "duration": 8492, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i0.hdslb.com/bfs/archive/f5bcc92a4e181cb12a8b80499cea255f43f2d97b.jpg", + "playback_position": 0, + "pubdate": 1669275447, + "stat": { + "view": 20004, + "vt": 0 + }, + "state": 0, + "title": "Git 版本控制 快速上手 已完结(2021版本)4K蓝光画质+杜比音效 从开摆到放弃", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 347934006, + "bvid": "BV1vR4y1o7Z2", + "ctime": 1669295228, + "duration": 10631, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i0.hdslb.com/bfs/archive/f95d39b0bc1a2bdad07461a8f4b1ea48c174902c.jpg", + "playback_position": 0, + "pubdate": 1669295228, + "stat": { + "view": 25860, + "vt": 0 + }, + "state": 0, + "title": "Redis 缓存技术 已完结(2021版本)4K蓝光画质+杜比音效 从内卷到开摆", + "ugc_pay": 0, + "vt_display": "" + } + ], + "meta": { + "category": 1, + "cover": "http://i1.hdslb.com/bfs/archive/208bb09ecf97fbbd73e45b3839715276ffbbe8f4.jpg", + "creator": "auto", + "ctime": 1669273164, + "description": "包含主线中讲解的中间件归档视频与当下必学的火热技术。", + "keywords": [ + "" + ], + "last_update_ts": 1688123428, + "mid": 37737161, + "mtime": 1688123428, + "name": "必学技术与中间件", + "raw_keywords": "", + "series_id": 2800550, + "state": 2, + "total": 7 + }, + "recent_aids": [ + 445283537, + 813084463, + 432905025, + 390385576, + 647924810, + 347934006 + ] + }, + { + "archives": [ + { + "aid": 900707014, + "bvid": "BV1YP4y1o75f", + "ctime": 1663494406, + "duration": 103542, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i0.hdslb.com/bfs/archive/291dd3b60b67a8f74567a81999612bd50b4e8017.jpg", + "playback_position": 0, + "pubdate": 1663494406, + "stat": { + "view": 312144, + "vt": 0 + }, + "state": 0, + "title": "JavaSE 教程 已完结 (IDEA 2022 最新版) 4K蓝光画质+杜比音效 零基础入门一套搞定 入门到入土", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 604837097, + "bvid": "BV1G84y1v7Vj", + "ctime": 1667815711, + "duration": 19395, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i0.hdslb.com/bfs/archive/4a4522194a1d0c8ae684976b26fb2fe43ce28f39.jpg", + "playback_position": 0, + "pubdate": 1667815711, + "stat": { + "view": 74496, + "vt": 0 + }, + "state": 0, + "title": "JavaSE AWT/Swing 图形化编程 (IDEA 2022 最新版) 4K蓝光画质+杜比音效 快速上手桌面程序 用IDEA写IDEA", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 766688029, + "bvid": "BV1Er4y1r7as", + "ctime": 1645157763, + "duration": 21585, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i2.hdslb.com/bfs/archive/ced6a8c8548f0f921f306ea3589f9d470adc0446.jpg", + "playback_position": 0, + "pubdate": 1645157763, + "stat": { + "view": 133409, + "vt": 0 + }, + "state": 0, + "title": "Java JVM 虚拟机 已完结(IDEA 2021版本)4K蓝光画质 全程劝退", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 936955310, + "bvid": "BV1JT4y1S7K8", + "ctime": 1646391131, + "duration": 31736, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i1.hdslb.com/bfs/archive/9347ef3cdb6cf0e5bca29ce32e211b488e90ab7b.jpg", + "playback_position": 0, + "pubdate": 1646391131, + "stat": { + "view": 74731, + "vt": 0 + }, + "state": 0, + "title": "Java JUC 并发编程 已完结(IDEA 2021版本)4K蓝光画质 玩转多线程", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 768437265, + "bvid": "BV1ar4y1J7mC", + "ctime": 1650881312, + "duration": 26314, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i0.hdslb.com/bfs/archive/7f97549147c09a386d9402b121cc6206c36e4079.jpg", + "playback_position": 0, + "pubdate": 1650881312, + "stat": { + "view": 67900, + "vt": 0 + }, + "state": 0, + "title": "Java NIO Netty网络编程 已完结(IDEA 2022.1最新版)4K蓝光画质 网络I/O进阶编程", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 684547077, + "bvid": "BV1tU4y1y7Fg", + "ctime": 1653900327, + "duration": 10243, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i2.hdslb.com/bfs/archive/dc0cc9464c6fc274c1f23f682a01dab5a358217b.jpg", + "playback_position": 0, + "pubdate": 1653900327, + "stat": { + "view": 47693, + "vt": 0 + }, + "state": 0, + "title": "JavaSE 9-17 新特性 已完结(IDEA 2022.1最新版)4K蓝光画质 Java9/10/11/12/13/14/15/16/17讲解", + "ugc_pay": 0, + "vt_display": "" + } + ], + "meta": { + "category": 1, + "cover": "http://i0.hdslb.com/bfs/archive/291dd3b60b67a8f74567a81999612bd50b4e8017.jpg", + "creator": "auto", + "ctime": 1648810702, + "description": "已排序完成,共3个系列,完成JavaSE篇之后,就可以开启JavaEE路线了", + "keywords": [ + "" + ], + "last_update_ts": 1667816253, + "mid": 37737161, + "mtime": 1667816253, + "name": "JavaSE基础路线", + "raw_keywords": "", + "series_id": 2158988, + "state": 2, + "total": 6 + }, + "recent_aids": [ + 900707014, + 604837097, + 766688029, + 936955310, + 768437265, + 684547077 + ] + }, + { + "archives": [ + { + "aid": 770027221, + "bvid": "BV1Cr4y137os", + "ctime": 1655371329, + "duration": 48185, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i0.hdslb.com/bfs/archive/5d9bd135f068e623e50c7341244635f6cc96c3ea.jpg", + "playback_position": 0, + "pubdate": 1655371329, + "stat": { + "view": 275378, + "vt": 0 + }, + "state": 0, + "title": "C语言程序设计 已完结(CLion 2022 最新版)4K蓝光画质+杜比音效 梦开始的地方", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 941207928, + "bvid": "BV13W4y127Ey", + "ctime": 1658474799, + "duration": 69081, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i2.hdslb.com/bfs/archive/0bf055a0961c0f9bbb7f869b47c3e3d7df21f55c.jpg", + "playback_position": 0, + "pubdate": 1658474798, + "stat": { + "view": 220072, + "vt": 0 + }, + "state": 0, + "title": "数据结构与算法 已完结(CLion 2022 最新版)4K蓝光画质+杜比音效 全程高能", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 426681358, + "bvid": "BV1u3411P7Na", + "ctime": 1653033628, + "duration": 12346, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i0.hdslb.com/bfs/archive/4174e2976f750d5410d6cef374c3035190717cac.jpg", + "playback_position": 0, + "pubdate": 1653033628, + "stat": { + "view": 71911, + "vt": 0 + }, + "state": 0, + "title": "Java 设计模式 已完结(IDEA 2022.1最新版)4K蓝光画质+杜比音效", + "ugc_pay": 0, + "vt_display": "" + } + ], + "meta": { + "category": 1, + "cover": "http://i0.hdslb.com/bfs/archive/5d9bd135f068e623e50c7341244635f6cc96c3ea.jpg", + "creator": "auto", + "ctime": 1653296733, + "description": "Java设计模式系列视频,提升你的代码编写规范。", + "keywords": [ + "" + ], + "last_update_ts": 1658735292, + "mid": 37737161, + "mtime": 1658735292, + "name": "高等院校计算机必修课", + "raw_keywords": "", + "series_id": 2318088, + "state": 2, + "total": 3 + }, + "recent_aids": [ + 770027221, + 941207928, + 426681358 + ] + } + ] + } + } +} +``` + +
+ +## 获取系列和合集视频 + +> https://api.bilibili.com/x/polymer/web-space/seasons_series_list + +*请求方式: GET* + +鉴权方式: 请求头 User-Agent 为正常浏览器, 若仍被风控则请求头再带上 Referer 为 `.bilibili.com` 下任意页 + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| mid | num | 用户 mid | 必要 | | +| page_num | num | 页码 | 必要 | 默认为 1 | +| page_size | num | 每页数量 | 必要 | 默认为 20 | +| w_rid | str | WBI 签名 | 可选 | 参见 [WBI 签名](../misc/sign/wbi.md) | +| wts | num | UNIX 秒级时间戳 | 可选 | 参见 [WBI 签名](../misc/sign/wbi.md) | +| web_location | str | 页面位置? | 可选 | 333.999 | + +**JSON回复:** + +与 [只获取系列视频](#只获取系列视频) 基本一致, 但 `.data.items_lists.seasons_list` 数组不为空, +且该数组中的元素结构与 `.data.items_lists.series_list` 相同, 略 + +**示例:** + +获取 `mid=37737161` 的系列视频列表,每页 5 条,页码为 1 + +```shell +curl -G "https://api.bilibili.com/x/polymer/web-space/seasons_series_list" \ +--data-urlencode "mid=37737161" \ +--data-urlencode "page_num=1" \ +--data-urlencode "page_size=5" \ +--data-urlencode "w_rid=xxx" \ +--data-urlencode "wts=xxx" +``` + +
+查看响应示例: + +```jsonc +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "items_lists": { + "page": { + "page_num": 1, + "page_size": 5, + "total": 9 + }, + "seasons_list": [ + { + "archives": [ + { + "aid": 343807541, + "bvid": "BV1t94y1D79E", + "ctime": 1658907465, + "duration": 2164, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i1.hdslb.com/bfs/archive/0af0faa77a1921db4cf86c115db70aa2594983f0.jpg", + "playback_position": 0, + "pubdate": 1658907465, + "stat": { + "view": 43096, + "vt": 0 + }, + "state": 0, + "title": "Java学习路线两条龙版,让你不再迷茫!包含各个知识点梳理,常用技术栈介绍等。", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 429032764, + "bvid": "BV11G411h7NB", + "ctime": 1659499261, + "duration": 197, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i2.hdslb.com/bfs/archive/5235a0ab2738e288b08654aa8e0cd3a509a7ef96.jpg", + "playback_position": 0, + "pubdate": 1659499200, + "stat": { + "view": 22700, + "vt": 0 + }, + "state": 0, + "title": "好书推荐《On Java》都什么年代了,还在看传统Java书籍?", + "ugc_pay": 0, + "vt_display": "" + }, + // ... + ], + "meta": { + "category": 0, + "cover": "https://archive.biliimg.com/bfs/archive/27733cf13514d990c880154b937cd8633f583aa4.jpg", + "description": "除教程视频外其他的视频,均在此。", + "mid": 37737161, + "name": "合集·拾枝杂谈", + "ptime": 1694682652, + "season_id": 587216, + "total": 10 + }, + "recent_aids": [ + 343807541, + 429032764, + 857089796, + 560181990, + 774119786, + 859397126 + ] + }, + { + "archives": [ + { + "aid": 311606079, + "bvid": "BV1XN411K7g9", + "ctime": 1679651747, + "duration": 261, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i2.hdslb.com/bfs/archive/234e6bd061176dba9e148f4373c52fa7cd2d801f.jpg", + "playback_position": 0, + "pubdate": 1679651747, + "stat": { + "view": 12150, + "vt": 0 + }, + "state": 0, + "title": "某些IT社区平台乱象,文章千篇一律,毫不注重版权,文章互相抄袭成潮流,希望能够好好管管!", + "ugc_pay": 0, + "vt_display": "" + }, + { + "aid": 400546145, + "bvid": "BV1qo4y1L73P", + "ctime": 1682777426, + "duration": 335, + "enable_vt": false, + "interactive_video": false, + "pic": "http://i2.hdslb.com/bfs/archive/a6b6fb0330bbf6c500720a024e5a9ade24d888c3.jpg", + "playback_position": 0, + "pubdate": 1682777425, + "stat": { + "view": 52744, + "vt": 0 + }, + "state": 0, + "title": "某些搜索引擎得到的结果,官方网站反而排在一些诈骗广告后面,诱导用户下载大量捆绑垃圾软件", + "ugc_pay": 0, + "vt_display": "" + } + ], + "meta": { + "category": 0, + "cover": "https://archive.biliimg.com/bfs/archive/5e1c1f77c3065ec31eec43d7e35f7a061602e4d6.jpg", + "description": "白马首席讲师吐槽系列视频", + "mid": 37737161, + "name": "合集·水浅王八多,真假白马说", + "ptime": 1682777425, + "season_id": 1227671, + "total": 2 + }, + "recent_aids": [ + 311606079, + 400546145 + ] + }, + // ... + ], + "series_list": [ + // 与前接口基本相同 + ] + } + } +} +``` + +
+ +## 查询指定系列 + +> https://api.bilibili.com/x/series/series + +*请求方式: GET* + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| series_id | num | 系列ID | 必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ------------ | ---- | +| meta | obj | 系列信息 | | +| recent_aids | array | 系列 aid 列表 | 内容类型为 num | + +`data`中的`meta`对象: + +同[只获取系列视频](#只获取系列视频)中的`meta`对象 + +**示例:** + +```shell +curl -G 'https://api.bilibili.com/x/series/series' \ +--data-urlencode 'series_id=2158988' +``` + +
+查看响应示例 + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "meta": { + "series_id": 2158988, + "mid": 37737161, + "name": "JavaSE基础路线", + "description": "已排序完成,共3个系列,完成JavaSE篇之后,就可以开启JavaEE路线了", + "keywords": [ + "" + ], + "creator": "auto", + "state": 2, + "last_update_ts": 1667816253, + "total": 6, + "ctime": 1648810702, + "mtime": 1667816253, + "raw_keywords": "", + "category": 1 + }, + "recent_aids": [ + 900707014, + 604837097, + 766688029, + 936955310, + 768437265, + 684547077 + ] + } +} +``` + +
+ +## 获取指定系列视频 + +> https://api.bilibili.com/x/series/archives + +*请求方式: GET* + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| mid | num | 用户 mid | 必要 | | +| series_id | num | 系列ID | 必要 | | +| only_normal | bool | 作用尚不明确 | 可选 | 默认为 true | +| sort | str | 排序方式 | 可选 | desc: 默认排序
asc: 升序排序 | +| pn | num | 页码 | 可选 | 默认为 1 | +| ps | num | 每页数量 | 可选 | 默认为 20 | +| current_mid | num | 当前用户 mid | 可选 | 用于 `playback_position` 播放进度 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------- | +| code | num | 返回值 | 0:成功 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------ | ---- | ------------ | ---- | +| aids | array | 视频 aid 列表 | 内容类型为 num | +| page | obj | 页码信息 | | +| archives | array | 视频信息列表 | | + +`data`中的`page`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| num | num | 当前页码 | | +| size | num | 每页数量 | | +| total | num | 视频总数 | | + +`data`中的`archives`数组: + +基本同[获取视频合集信息](#获取视频合集信息)中的`archives`数组 + +**示例:** + +获取 `mid=39665558` 的 `series_id=534501` 系列视频列表,每页 16 条,页码为 1,默认排序, 当前用户 mid 为 `1070915568` + +```shell +curl -G "https://api.bilibili.com/x/series/archives" \ +--data-urlencode "mid=39665558" \ +--data-urlencode "series_id=534501" \ +--data-urlencode "only_normal=true" \ +--data-urlencode "sort=desc" \ +--data-urlencode "pn=1" \ +--data-urlencode "ps=16" \ +--data-urlencode "current_mid=1070915568" +``` + +
+查看响应示例: + +```jsonc +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "aids": [ + 695029098, + 724599872, + 594794875, + 41565264, + 541053051, + 499696652, + 673071936, + 462891077, + 973903762, + 61692380, + 336713491, + 372661682, + 550840795, + 51839931, + 718592873, + 87838863 + ], + "page": { + "num": 1, + "size": 16, + "total": 25 + }, + "archives": [ + { + "aid": 695029098, + "title": "Python控制Minecraft教程(下):自动建造", + "pubdate": 1677321251, + "ctime": 1677321251, + "state": 0, + "pic": "http://i1.hdslb.com/bfs/archive/187c0ba21b9ceba908a8760e83d49f466316824b.jpg", + "duration": 275, + "stat": { + "view": 26555 + }, + "bvid": "BV1k24y1J78X", + "ugc_pay": 0, + "interactive_video": false, + "enable_vt": 0, + "vt_display": "", + "playback_position": 0 + }, + { + "aid": 724599872, + "title": "『教程』一看就懂!Github基础教程", + "pubdate": 1646740815, + "ctime": 1646740824, + "state": 0, + "pic": "http://i0.hdslb.com/bfs/archive/1401ebe64e88deddf2b44ad6a740ff8872c2fda6.jpg", + "duration": 296, + "stat": { + "view": 2412054 + }, + "bvid": "BV1hS4y1S7wL", + "ugc_pay": 0, + "interactive_video": false, + "enable_vt": 0, + "vt_display": "", + "playback_position": 0 + }, + { + "aid": 594794875, + "title": "『教程』手把手教你流畅访问Github", + "pubdate": 1647345613, + "ctime": 1647336725, + "state": 0, + "pic": "http://i0.hdslb.com/bfs/archive/71cc640a84087cc99399449c00b93212fe78ee6f.jpg", + "duration": 236, + "stat": { + "view": 910491 + }, + "bvid": "BV1Aq4y1q7hr", + "ugc_pay": 0, + "interactive_video": false, + "enable_vt": 0, + "vt_display": "", + "playback_position": 0 + }, + { + "aid": 41565264, + "title": "《Python负基础到入门教程》专为\"非计算机专业和编程困难户\"制作(全13集 配音字幕重制版)", + "pubdate": 1548316071, + "ctime": 1548316072, + "state": 0, + "pic": "http://i0.hdslb.com/bfs/archive/5f4f6acfc00723c84f726d35add94b1d4b4ee482.jpg", + "duration": 6395, + "stat": { + "view": 261286 + }, + "bvid": "BV1et411b76c", + "ugc_pay": 0, + "interactive_video": false, + "enable_vt": 0, + "vt_display": "", + "playback_position": 0 + }, + { + "aid": 541053051, + "title": "『教程』文字频频乱码 这背后是显卡的扭曲还是规则的沦丧?", + "pubdate": 1592996906, + "ctime": 1592996907, + "state": 0, + "pic": "http://i0.hdslb.com/bfs/archive/8a3c3e3d01a91776763d34bba79add698869c82d.jpg", + "duration": 381, + "stat": { + "view": 1184937 + }, + "bvid": "BV1ai4y1x7Uz", + "ugc_pay": 0, + "interactive_video": false, + "enable_vt": 0, + "vt_display": "", + "playback_position": 0 + }, + { + "aid": 499696652, + "title": "『教程』VsCode五分钟上手教程 无一句废话", + "pubdate": 1601207369, + "ctime": 1601207369, + "state": 0, + "pic": "http://i1.hdslb.com/bfs/archive/cb78c07a090ed456bdcc217b0417670867772a29.jpg", + "duration": 329, + "stat": { + "view": 417610 + }, + "bvid": "BV1bK411P767", + "ugc_pay": 0, + "interactive_video": false, + "enable_vt": 0, + "vt_display": "", + "playback_position": 0 + }, + { + "aid": 673071936, + "title": "『教程』补码怎么来的?", + "pubdate": 1620994814, + "ctime": 1620986531, + "state": 0, + "pic": "http://i1.hdslb.com/bfs/archive/12c02599321a0b1386b29ddc4653ff7df9bd54b4.jpg", + "duration": 445, + "stat": { + "view": 247578 + }, + "bvid": "BV16U4y1t7LD", + "ugc_pay": 0, + "interactive_video": false, + "enable_vt": 0, + "vt_display": "", + "playback_position": 0 + }, + { + "aid": 462891077, + "title": "『教程』回调函数是个啥?", + "pubdate": 1631274885, + "ctime": 1631274885, + "state": 0, + "pic": "http://i0.hdslb.com/bfs/archive/df294350462558601f65b743ca25e2fdc01de628.jpg", + "duration": 452, + "stat": { + "view": 213895 + }, + "bvid": "BV1vL411t78b", + "ugc_pay": 0, + "interactive_video": false, + "enable_vt": 0, + "vt_display": "", + "playback_position": 98 + }, + { + "aid": 973903762, + "title": "『教程』堆栈是个啥?", + "pubdate": 1625227205, + "ctime": 1625227209, + "state": 0, + "pic": "http://i0.hdslb.com/bfs/archive/bf7956b6311ec0787fd52d1293bb4287d16b7e65.jpg", + "duration": 370, + "stat": { + "view": 535174 + }, + "bvid": "BV1P44y1q7uL", + "ugc_pay": 0, + "interactive_video": false, + "enable_vt": 0, + "vt_display": "", + "playback_position": 99 + }, + { + "aid": 61692380, + "title": "『教程』什么是递归?", + "pubdate": 1564660818, + "ctime": 1564637347, + "state": 0, + "pic": "http://i1.hdslb.com/bfs/archive/4af853671204b9bc631fada1934a3e86145a7d19.jpg", + "duration": 658, + "stat": { + "view": 487397 + }, + "bvid": "BV194411f71o", + "ugc_pay": 0, + "interactive_video": false, + "enable_vt": 0, + "vt_display": "", + "playback_position": 79 + }, + { + "aid": 336713491, + "title": "『教程』几分钟听懂迭代器", + "pubdate": 1636713476, + "ctime": 1636713476, + "state": 0, + "pic": "http://i0.hdslb.com/bfs/archive/6e255cce7c0303ab0211acd0f9d1ec5980ff03f7.jpg", + "duration": 453, + "stat": { + "view": 110688 + }, + "bvid": "BV18R4y1t7Hg", + "ugc_pay": 0, + "interactive_video": false, + "enable_vt": 0, + "vt_display": "", + "playback_position": 97 + }, + { + "aid": 372661682, + "title": "『教程』桌面精灵是怎样实现的?", + "pubdate": 1604916264, + "ctime": 1604916264, + "state": 0, + "pic": "http://i0.hdslb.com/bfs/archive/aaa8bb7b6fced63dd4792e28c1f78ba903fcc4cc.jpg", + "duration": 326, + "stat": { + "view": 168775 + }, + "bvid": "BV1aZ4y1V7aa", + "ugc_pay": 0, + "interactive_video": false, + "enable_vt": 0, + "vt_display": "", + "playback_position": 0 + }, + { + "aid": 550840795, + "title": "『教程』什么是钩子技术?", + "pubdate": 1642744335, + "ctime": 1642744335, + "state": 0, + "pic": "http://i0.hdslb.com/bfs/archive/380b1ff9726c673411cf916b03268c7fb16aff68.jpg", + "duration": 240, + "stat": { + "view": 237568 + }, + "bvid": "BV1Cq4y1c7kK", + "ugc_pay": 0, + "interactive_video": false, + "enable_vt": 0, + "vt_display": "", + "playback_position": 0 + }, + { + "aid": 51839931, + "title": "『教程』学编程前必知的8个电脑操作", + "pubdate": 1557313623, + "ctime": 1557313623, + "state": 0, + "pic": "http://i2.hdslb.com/bfs/archive/b54535ee3ff27006912d8013f2ea1667b2a50f80.jpg", + "duration": 641, + "stat": { + "view": 139385 + }, + "bvid": "BV1t4411v78E", + "ugc_pay": 0, + "interactive_video": false, + "enable_vt": 0, + "vt_display": "", + "playback_position": 0 + }, + { + "aid": 718592873, + "title": "『教程』这些常见编程单词到底该怎么读?看你能否读对?对✔❌✅☑", + "pubdate": 1634300675, + "ctime": 1634265090, + "state": 0, + "pic": "http://i1.hdslb.com/bfs/archive/de43275f44aea9f6d79c13ee68c6dcdfc9e5fc5e.jpg", + "duration": 783, + "stat": { + "view": 81193 + }, + "bvid": "BV1JQ4y1D79p", + "ugc_pay": 0, + "interactive_video": true, + "enable_vt": 0, + "vt_display": "", + "playback_position": 100 + }, + { + "aid": 87838863, + "title": "『教程』什么是环境变量", + "pubdate": 1581258353, + "ctime": 1581258353, + "state": 0, + "pic": "http://i0.hdslb.com/bfs/archive/331b2304d8262c4252f338599846761d6a5a8e0c.jpg", + "duration": 353, + "stat": { + "view": 99797 + }, + "bvid": "BV1w741147G9", + "ugc_pay": 0, + "interactive_video": false, + "enable_vt": 0, + "vt_display": "", + "playback_position": 0 + } + ] + } +} +``` + +
+ +## 根据关键词查找视频 + +> https://api.bilibili.com/x/series/recArchivesByKeywords + +*请求方式:GET* + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| mid | num | 用户 mid | 必要 | | +| keywords | str | 关键词 | 必要 | 可为空, 即获取所有视频 | +| ps | num | 每页视频数 | 非必要 | 默认为 0, 留空为 20,最大值 100 | +| pn | num | 页码 | 非必要 | 留空为 1,为 0 则直接忽略 ps 参数获取所有 | +| orderby | str | 排序方式 | 非必要 | 最新发布: pubdate(默认)
最多播放: views
senddate: 最新发布 | +| series_id | num | 系列 ID | 非必要 | 用于过滤结果, 即若某一视频包含在系列内则不返回该视频 | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------- | +| code | num | 返回值 | 0: 成功 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | ---- | +| archives | arr | 视频列表 | | +| page | obj | 页码信息 | | + +`archives` 数组: + +同[获取视频合集信息](#获取视频合集信息)中的`archives`数组 + +`page` 对象: + +同[获取视频合集信息](#获取视频合集信息)中的`page`对象 + +**示例:** + +查询用户 `mid=2` 关键词为 `幕` 的视频, 不限制每页视频数 + +```shell +curl -G "https://api.bilibili.com/x/series/recArchivesByKeywords" \ +--data-urlencode "mid=2" \ +--data-urlencode "keywords=幕" \ +--data-urlencode "ps=0" +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "archives": [ + { + "aid": 120040, + "title": "高级语言弹幕测试", + "pubdate": 1311616515, + "ctime": 1497344798, + "state": 0, + "pic": "http://i1.hdslb.com/bfs/archive/55a553659799d8a6fcb645d8f1f9df418ad6fe4e.jpg", + "duration": 911, + "stat": { + "view": 3584767 + }, + "bvid": "BV1Xx411c7cH", + "ugc_pay": 0, + "interactive_video": false, + "enable_vt": 0, + "vt_display": "", + "playback_position": 0 + }, + { + "aid": 2, + "title": "字幕君交流场所", + "pubdate": 1252458549, + "ctime": 1497344798, + "state": 0, + "pic": "http://static.hdslb.com/images/transparent.gif", + "duration": 2055, + "stat": { + "view": 4609291 + }, + "bvid": "BV1xx411c7mD", + "ugc_pay": 0, + "interactive_video": false, + "enable_vt": 0, + "vt_display": "", + "playback_position": 0 + }, + { + "aid": 271, + "title": "弹幕测试专用", + "pubdate": 1249886475, + "ctime": 1497344798, + "state": 0, + "pic": "http://i1.hdslb.com/bfs/archive/a5980672f3d03e8292148748a63de99cd45679d3.jpg", + "duration": 1213, + "stat": { + "view": 4857422 + }, + "bvid": "BV1xx411c7Xg", + "ugc_pay": 0, + "interactive_video": false, + "enable_vt": 0, + "vt_display": "", + "playback_position": 0 + } + ], + "page": { + "num": 1, + "size": 0, + "total": 3 + } + } +} +``` + +
+ +## 创建视频列表 + +> https://api.bilibili.com/x/series/series/createAndAddArchives + +*请求方式: POST* + +认证方式: Cookie (SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ----| ---- | ------ | ---- | +| csrf | str | CSRF Token (即 Cookies 中 bili_jct ) | 必要 | | + +**正文参数 (multipart/form-data):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| mid | num | 用户 mid | 必要 | | +| name | str | 标题 | 必要 | | +| keywords | str | 关键词 | 不必要 | | +| description | str | 简介 | 不必要 | | +| aids | str | 视频 aid 列表 | 不必要 | 以 `,` 分隔, 如 `2,112861,112861976201494,976201494` | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------- | +| code | num | 返回值 | 0: 成功 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ---- | ------------ | ---- | +| series_id | num | 视频列表 ID | | + +**示例:** + +为 `mid=616368979` 创建视频列表, 标题为 `NAME`, 视频为 `112861976201494` + +```shell +curl -X POST --url "https://api.bilibili.com/x/series/series/createAndAddArchives" \ +--url-query "csrf=xxxxxxxxxx" \ +--data-urlencode "mid=616368979" \ +--data-urlencode "name=NAME" \ +--data-urlencode "aids=112861976201494" \ +-b "SESSDATA=xxx" +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "series_id": 4269765 + } +} +``` + +
+ +## 删除视频列表 + +> https://api.bilibili.com/x/series/series/delete + +*请求方式: POST* + +认证方式: Cookie (SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ----| ---- | ------ | ---- | +| csrf | str | CSRF Token (即 Cookies 中 bili_jct ) | 必要 | | +| mid | num | 用户 mid | 必要 | | +| series_id | num | 视频列表 ID | 必要 | | +| aids | str | 空 | 不必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------- | +| code | num | 返回值 | 0: 成功 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 空 | | + +**示例:** + +为 `mid=616368979` 删除视频列表 `series_id=4269765` + +```shell +curl -X POST --url "https://api.bilibili.com/x/series/series/delete" \ +--url-query "csrf=xxxxxxxxxx" \ +--url-query "series_id=4269765" \ +--url-query "mid=616368979" \ +-b "SESSDATA=xxx" +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": {} +} +``` + +
+ +## 删除视频列表中的稿件 + +> https://api.bilibili.com/x/series/series/delArchives + +*请求方式: POST* + +认证方式: Cookie (SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ----| ---- | ------ | ---- | +| csrf | str | CSRF Token (即 Cookies 中 bili_jct ) | 必要 | | + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| mid | num | 用户 mid | 必要 | | +| series_id | num | 视频列表 ID | 必要 | | +| aids | str | 视频 aid 列表 | 必要 | 以 `,` 分隔, 如 `2,112861,112861976201494,976201494` | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------- | +| code | num | 返回值 | 0: 成功 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 空 | | + +**示例:** + +为 `mid=616368979` 删除视频列表 `series_id=4269782` 中的 `112861976201494` + +```shell +curl -X POST --url "https://api.bilibili.com/x/series/series/delArchives" \ +--url-query "csrf=xxxxxxxxxx" \ +--data-urlencode "mid=616368979" \ +--data-urlencode "series_id=4269782" \ +--data-urlencode "aids=112861976201494" \ +-b "SESSDATA=xxx" +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": {} +} +``` + +
+ +## 添加稿件至视频列表 + +> https://api.bilibili.com/x/series/series/addArchives + +*请求方式: POST* + +认证方式: Cookie (SESSDATA) + +**URL参数:** + +同[删除视频列表中的稿件](#删除视频列表中的稿件) + +**正文参数 (application/x-www-form-urlencoded):** + +同[删除视频列表中的稿件](#删除视频列表中的稿件) + +**JSON回复:** + +同[删除视频列表中的稿件](#删除视频列表中的稿件) + +**示例:** + +为 `mid=616368979` 添加视频 `112861976201494` 至视频列表 `series_id=4269782` + +```shell +curl -X POST --url "https://api.bilibili.com/x/series/series/addArchives" \ +--url-query "csrf=xxxxxxxxxx" \ +--data-urlencode "mid=616368979" \ +--data-urlencode "series_id=4269782" \ +--data-urlencode "aids=112861976201494" \ +-b "SESSDATA=xxx" +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": {} +} +``` + +
+ +## 编辑视频列表信息 + +> https://api.bilibili.com/x/series/series/update + +*请求方式: POST* + +认证方式: Cookie (SESSDATA) + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ----| ---- | ------ | ---- | +| csrf | str | CSRF Token (即 Cookies 中 bili_jct ) | 必要 | | + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| mid | num | 用户 mid | 必要 | | +| series_id | num | 视频列表 ID | 必要 | | +| name | str | 标题 | 必要 | | +| keywords | str | 关键词 | 不必要 | | +| description | str | 简介 | 不必要 | | +| add_aids | str | 视频 aid 列表 | 不必要 | 以 `,` 分隔 | +| del_aids | str | 视频 aid 列表 | 不必要 | | +| aids | str | 空 | 不必要 | | + +**JSON回复:** + +同[删除视频列表中的稿件](#删除视频列表中的稿件) + +**示例:** + +为 `mid=616368979` 编辑视频列表 `series_id=4269782`, 设置标题为 `NAME`, 设置简介为空, 设置关键词 `Telnet`, 添加视频 `112861976201494` + +```shell +curl -X POST --url "https://api.bilibili.com/x/series/series/update" \ +--url-query "csrf=xxxxxxxxxx" \ +--data-urlencode "name=NAME" \ +--data-urlencode "mid=616368979" \ +--data-urlencode "series_id=4269782" \ +--data-urlencode "keywords=Telnet" \ +--data-urlencode "add_aids=112861976201494" \ +-b "SESSDATA=xxx" +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": {} +} +``` + +
diff --git a/bb-api-collect/docs/video/info.md b/bb-api-collect/docs/video/info.md new file mode 100644 index 0000000000..75c14d8971 --- /dev/null +++ b/bb-api-collect/docs/video/info.md @@ -0,0 +1,4779 @@ +# 视频基本信息 + + + +## 获取视频详细信息(web端) + +> https://api.bilibili.com/x/web-interface/wbi/view +> https://api.bilibili.com/x/web-interface/view + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +限制游客访问的视频需要登录 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|------|-----|--------|--------|---------------| +| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 | +| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|------------------------------------------------------------------------------------| +| code | num | 返回值 | 0:成功
-400:请求错误
-403:权限不足
-404:无视频
62002:稿件不可见
62004:稿件审核中
62012:仅UP主自己可见 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------------- | ------- | ------------------------------ | ------------------------------------------------------------ | +| bvid | str | 稿件bvid | | +| aid | num | 稿件avid | | +| videos | num | 稿件分P总数 | 默认为1 | +| tid | num | 分区tid | 详情见[视频分区一览](video_zone.md) | +| tid_v2 | num | 分区tid (v2) | 详情见[视频分区一览 (v2)](video_zone_v2.md) | +| tname | str | 子分区名称 | | +| tname_v2 | str | 子分区名称 (v2) | | +| copyright | num | 视频类型 | 1:原创
2:转载
3:未填写 | +| pic | str | 稿件封面图片url | | +| title | str | 稿件标题 | | +| pubdate | num | 稿件发布时间 | 秒级时间戳 | +| ctime | num | 用户投稿时间 | 秒级时间戳 | +| desc | str | 视频简介 | | +| desc_v2 | array | 新版视频简介 | | +| state | num | 视频状态 | 详情见[属性数据文档](attribute_data.md#state字段值稿件状态) | +| ~~attribute~~(已经弃用) | ~~num~~ | ~~稿件属性位配置~~ | 详情见[属性数据文档](attribute_data.md#attribute字段值稿件属性位) | +| duration | num | 稿件总时长(所有分P) | 单位为秒 | +| forward | num | 撞车视频跳转avid | 仅撞车视频存在此字段 | +| mission_id | num | 稿件参与的活动id | | +| redirect_url | str | 重定向url | 仅番剧或影视视频存在此字段
用于番剧&影视的av/bv->ep | +| rights | obj | 视频属性标志 | | +| owner | obj | 视频UP主信息 | | +| stat | obj | 视频状态数 | | +| argue_info | obj | 争议/警告信息 | | +| dynamic | str | 视频同步发布的的动态的文字内容 | | +| cid | num | 视频1P cid | | +| dimension | obj | 视频1P分辨率 | | +| premiere | | null | | +| teenage_mode | num | | 用于青少年模式 | +| is_chargeable_season | bool | | | +| is_story | bool | 是否为动态视频 | | +| is_upower_exclusive | bool | 是否为充电专属视频 | | +| is_upower_play | bool | | | +| is_upower_preview | bool | 充电专属视频是否支持试看 | | +| no_cache | bool | 是否不允许缓存? | | +| pages | array | 视频分P列表 | | +| subtitle | obj | 视频CC字幕信息 | | +| ugc_season | obj | 视频合集信息 | 不在合集中的视频无此项 | +| staff | array | 合作成员列表 | 非合作视频无此项 | +| is_season_display | bool | | | +| user_garb | obj | 用户装扮信息 | | +| honor_reply | obj | | | +| like_icon | str | 空串 | | +| need_jump_bv | bool | 需要跳转到BV号? | | +| disable_show_up_info | bool | 禁止展示UP主信息? | | +| is_story_play | bool | | 作用未知,可能与动态视频有关 | +| is_view_self | bool | 是否尽自己可见 | | + +`data`中的`desc_v2`数组: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|--------|-----| +| 0 | obj | 新版简介内容 | | + +`desc_v2`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|----------|-----|------|-----| +| raw_text | str | 简介内容 |type=1时显示原文
type=2时显示'@'+raw_text+' '并链接至biz_id的主页| +| type | num | 类型 |1:普通,2:@他人| +| biz_id | num |被@用户的mid|=0,当type=1| + +`data`中的`rights`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-----------------|-----|--------------|--------| +| bp | num | 是否允许承包 | | +| elec | num | 是否支持充电 | | +| download | num | 是否允许下载 | | +| movie | num | 是否电影 | | +| pay | num | 是否PGC付费 | | +| hd5 | num | 是否有高码率 | | +| no_reprint | num | 是否显示“禁止转载”标志 | | +| autoplay | num | 是否自动播放 | | +| ugc_pay | num | 是否UGC付费 | | +| is_cooperation | num | 是否为联合投稿 | | +| ugc_pay_preview | num | 0 | 作用尚不明确 | +| no_background | num | 0 | 作用尚不明确 | +| clean_mode | num | 0 | 作用尚不明确 | +| is_stein_gate | num | 是否为互动视频 | | +| is_360 | num | 是否为全景视频 | | +| no_share | num | 0 | 作用尚不明确 | +| arc_pay | num | 0 | 作用尚不明确 | +| free_watch | num | 0 | 作用尚不明确 | + +`data`中的`owner`对象: + +| 字段 | 类型 | 内容 | 备注 | +|------|-----|--------|-----| +| mid | num | UP主mid | | +| name | str | UP主昵称 | | +| face | str | UP主头像 | | + +`data`中的`stat`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ------------ | ------- | +| aid | num | 稿件avid | | +| view | num | 播放数 | | +| danmaku | num | 弹幕数 | | +| reply | num | 评论数 | | +| favorite | num | 收藏数 | | +| coin | num | 投币数 | | +| share | num | 分享数 | | +| now_rank | num | 当前排名 | | +| his_rank | num | 历史最高排行 | | +| like | num | 获赞数 | | +| dislike | num | 点踩数 | 恒为`0` | +| evaluation | str | 视频评分 | | +| vt | int | 作用尚不明确 | 恒为`0` | + +`data`中的`argue_info`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ---- | ----------------- | ------------ | +| argue_link | str | | 作用尚不明确 | +| argue_msg | str | 警告/争议提示信息 | | +| argue_type | int | | 作用尚不明确 | + +`data`中的`pages`数组: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|----------|---------| +| 0 | obj | 1P内容 | 无分P仅有此项 | +| n | obj | (n+1)P内容 | | +| …… | obj | …… | …… | + +`pages`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|-----------|-----|-----------|---------------------------------------------| +| cid | num | 分P cid | | +| page | num | 分P序号 | 从1开始 | +| from | str | 视频来源 | vupload:普通上传(B站)
hunan:芒果TV
qq:腾讯 | +| part | str | 分P标题 | | +| duration | num | 分P持续时间 | 单位为秒 | +| vid | str | 站外视频vid | 仅站外视频有效 | +| weblink | str | 站外视频跳转url | 仅站外视频有效 | +| dimension | obj | 当前分P分辨率 | 部分较老视频无分辨率值 | + +`pages`数组中的对象中的`dimension`对象(同`data`中的`dimension`对象): + +| 字段 | 类型 | 内容 | 备注 | +|--------|-----|---------|----------------| +| width | num | 当前分P 宽度 | | +| height | num | 当前分P 高度 | | +| rotate | num | 是否将宽高对换 | 0:正常
1:对换 | + +`subtitle`对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------------|-------|----------|-----| +| allow_submit | bool | 是否允许提交字幕 | | +| list | array | 字幕列表 | 未登录为空 | + +`subtitle`对象中的`list`数组: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|---------|-----| +| 0 | obj | 字幕1 | | +| n | obj | 字幕(n+1) | | +| …… | obj | …… | …… | + +`list`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------------|------|---------------|-----| +| id | num | 字幕id | | +| lan | str | 字幕语言 | | +| lan_doc | str | 字幕语言名称 | | +| is_lock | bool | 是否锁定 | | +| author_mid | num | 字幕上传者mid | | +| subtitle_url | str | json格式字幕文件url | | +| author | obj | 字幕上传者信息 | | + +`list`数组中的对象中的`author`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-----------------|-----|------------|--------| +| mid | num | 字幕上传者mid | | +| name | str | 字幕上传者昵称 | | +| sex | str | 字幕上传者性别 | 男 女 保密 | +| face | str | 字幕上传者头像url | | +| sign | str | 字幕上传者签名 | | +| rank | num | 10000 | 作用尚不明确 | +| birthday | num | 0 | 作用尚不明确 | +| is_fake_account | num | 0 | 作用尚不明确 | +| is_deleted | num | 0 | 作用尚不明确 | + +`ugc_season`对象: + +| 字段 | 类型 | 内容 | 备注 | +|------------|-------|---------|--------| +| id | num | 视频合集id | | +| title | str | 视频合集标题 | | +| mid | str | 视频合集作者id | | +| intro | str | 视频合集介绍 | | +| sign_state | num | ? | 作用尚不明确 | +| attribute | num | 稿件属性位 | 详情见[属性数据文档](attribute_data.md#attribute字段值(稿件属性位)) | +| sections | array | 视频合集中分部列表,名称可由up主自定义,默认为正片 | | +| stat | obj | 视频合集状态数 | | +| ep_count | num | 视频合集中视频数量 | | +| season_type | num | 作用尚不明确 | | +| is_pay_season | bool | 是否为付费合集 | | +| enable_vt | num | 作用尚不明确 | | + +`ugc_season`中的`sections`数组: + +| 字段 | 类型 | 内容 | 备注 | +|------------|-------|---------|--------| +| season_id | num | 视频合集中分部所属视频合集id | | +| section_id | num | 视频合集中分部id | | +| title | str | 视频合集中分部标题 | | +| type | num | ? | 作用尚不明确 | +| episodes | array | 视频合集中分部的视频列表 | | + +`sections`中的`episodes`数组: + +| 字段 | 类型 | 内容 | 备注 | +|------------|-------|---------|--------| +| season_id | num | 视频合集中分部中视频所属视频合集id | | +| section_id | num | 视频合集中视频合集中分部中视频所属视频合集分部id | | +| id | num | 视频合集分部中视频id(以下简称视频) | | +| aid | num | 视频aid | | +| cid | num | 视频cid | | +| title | str | 视频标题 | 合集列表中展示的标题。默认视频真实标题,在[创作中心-合集管理-单集标题](https://member.bilibili.com/platform/upload-manager/ep)修改后则以修改后为准 | +| ~~attribute~~(已经弃用) | ~~num~~ | ~~稿件属性位配置~~ | 详情见[属性数据文档](attribute_data.md#attribute字段值(稿件属性位)) | +| arc | obj | 视频详细信息 | 基本同「[获取视频详细信息(web端)](#获取视频详细信息(web端))」中的data对象 | + +`ugc_season`中的`stat`对象: + +|字段 | 类型 | 内容 | 备注 | +|------------|-------|---------|--------| +| season_id | num | 视频合集id | | +| view | num | 视频合集总浏览量 | | +| danmaku | num | 视频合集总弹幕量 | | +| reply | num | 视频合集总评论量 | | +| fav | num | 视频合集总收藏数 | | +| coin | num | 视频合集总投币数 | | +| share | num | 视频合集总分享数 | | +| now_rank | num | 视频合集当前排名 | | +| his_rank | num | 视频合集历史排名 | | +| like | num | 视频合集总获赞数 | | +| vt | num | 作用尚不明确 | | +| vv | num | 作用尚不明确 | | + +`ugc_season`示例 + +```jsonc + "ugc_season": { + "id": 2974525, + "title": "楚汉传奇", + "cover": "https://archive.biliimg.com/bfs/archive/5a853e8bd10a041360b45a462785d90a58ec469e.png", + "mid": 1557073149, + "intro": "", + "sign_state": 0, + "attribute": 140, + "sections": [ + { + "season_id": 2974525, + "id": 3341804, + "title": "正片", + "type": 1, + "episodes": [ + { + "season_id": 2974525, + "section_id": 3341804, + "id": 64976947, + "aid": 1804383120, + "cid": 1541093346, + "title": "项燕的10万大军惨败秦国,临死前,立下狠誓“楚虽三户,亡秦必楚”", + "attribute": 0, + "arc": { + "aid": 1804383120, + "videos": 0, + "type_id": 0, + "type_name": "", + "copyright": 0, + "pic": "http://i1.hdslb.com/bfs/archive/9d0ebd0a8abd7b005466cb57632ddaa550d24dab.jpg", + "title": "项燕的10万大军惨败秦国,临死前,立下狠誓“楚虽三户,亡秦必楚”", + "pubdate": 1715427472, + "ctime": 1715427472, + "desc": "", + "state": 0, + "duration": 612, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 0, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "arc_pay": 0, + "free_watch": 0 + }, + "author": { + "mid": 0, + "name": "", + "face": "" + }, + "stat": { + "aid": 1804383120, + "view": 787330, + "danmaku": 1298, + "reply": 774, + "fav": 2589, + "coin": 1947, + "share": 271, + "now_rank": 0, + "his_rank": 0, + "like": 12320, + "dislike": 0, + "evaluation": "", + "argue_msg": "", + "vt": 2630119, + "vv": 787330 + }, + "dynamic": "", + "dimension": { + "width": 0, + "height": 0, + "rotate": 0 + }, + "desc_v2": null, + "is_chargeable_season": false, + "is_blooper": false, + "enable_vt": 0, + "vt_display": "" + }, + "page": { + "cid": 1541093346, + "page": 1, + "from": "vupload", + "part": "项燕的10万大军惨败秦国,临死前,立下狠誓“楚虽三户,亡秦必楚”", + "duration": 612, + "vid": "", + "weblink": "", + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + } + }, + "bvid": "BV1Tb421b7mi", + "pages": [ + { + "cid": 1541093346, + "page": 1, + "from": "vupload", + "part": "项燕的10万大军惨败秦国,临死前,立下狠誓“楚虽三户,亡秦必楚”", + "duration": 612, + "vid": "", + "weblink": "", + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + } + } + ] + }, + { + "season_id": 2974525, + "section_id": 3341804, + "id": 65121012, + "aid": 1004394994, + "cid": 1542426326, + "title": "卢绾斗鸡输了,眼看十个手指头保不住,刘邦倾家荡产帮了他", + "attribute": 0, + "arc": { + /// + } + } + ] + } + ], + "stat": { + "season_id": 3617611, + "view": 1826438, + "danmaku": 5193, + "reply": 3036, + "fav": 5970, + "coin": 2303, + "share": 663, + "now_rank": 0, + "his_rank": 0, + "like": 40848, + "vt": 0, + "vv": 0 + }, + "ep_count": 21, + "season_type": 1, + "is_pay_season": false, + "enable_vt": 0 + + } +``` + +`staff`数组: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|-----------|-----| +| 0 | obj | 合作成员1 | | +| n | obj | 合作成员(n+1) | | +| …… | obj | …… | …… | + +`staff`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|----------|-----|---------|-----| +| mid | num | 成员mid | | +| title | str | 成员名称 | | +| name | str | 成员昵称 | | +| face | str | 成员头像url | | +| vip | obj | 成员大会员状态 | | +| official | obj | 成员认证信息 | | +| follower | num | 成员粉丝数 | | +| label_style | num | | | + +`staff`数组中的对象中的`vip`对象: + +| 字段 | 类型 | 内容 | 备注 | +|------------|-----|--------|---------------------------| +| type | num | 成员会员类型 | 0:无
1:月会员
2:年会员 | +| status | num | 会员状态 | 0:无
1:有 | +| due_date | num | 到期时间 | UNIX 毫秒时间戳 | +| vip_pay_type | num | | | +| theme_type | num | 0 | | +| label | obj | | | + +`staff`数组中的对象中的`official`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------|-----|--------|---------------------------------------| +| role | num | 成员认证级别 | 见[用户认证类型一览](../user/official_role.md) | +| title | str | 成员认证名 | 无为空 | +| desc | str | 成员认证备注 | 无为空 | +| type | num | 成员认证类型 | -1:无
0:有 | + +`data`中的`user_garb`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------------|-----|-------|-----| +| url_image_ani_cut | str | 某url? | | + +`data`中的`honor_reply`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------|-------|-----|-----| +| honor | array | | | + +`honor`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|----------------------|-----|-------------------------------------|-----| +| aid | num | 当前稿件aid | | +| type | num | 1:入站必刷收录
2:第?期每周必看
3:全站排行榜最高第?名
4:热门 | | +| desc | num | 描述 | | +| weekly_recommend_num | num | | | + +**示例:** + +获取视频`av85440373`/`BV117411r7R1`的基本信息 + +avid方式: + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/view' \ +--data-urlencode 'aid=85440373' +``` + +bvid方式: + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/view' \ +--data-urlencode 'bvid=BV117411r7R1' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "bvid": "BV117411r7R1", + "aid": 85440373, + "videos": 1, + "tid": 28, + "tid_v2": 2061, + "tname": "原创音乐", + "tname_v2": "人力VOCALOID", + "copyright": 1, + "pic": "http://i1.hdslb.com/bfs/archive/ea0dd34bf41e23a68175680a00e3358cd249105f.jpg", + "title": "当我给拜年祭的快板加了电音配乐…", + "pubdate": 1580377255, + "ctime": 1580212263, + "desc": "【CB想说的】看完拜年祭之后最爱的一个节目!给有快板的部分简单加了一些不同风格的配乐hhh,感谢沃玛画的我!太可爱了哈哈哈哈哈哈哈!!!\n【Warma想说的】我画了打碟的CB,画风为了还原原版视频所以参考了四迹老师的画风,四迹老师的画真的太可爱啦!不过其实在画的过程中我遇到了一个问题,CB的耳机……到底是戴在哪个耳朵上呢?\n\n原版:av78977080\n编曲(配乐):Crazy Bucket\n人声(配音):Warma/谢拉\n曲绘:四迹/Warma\n动画:四迹/Crazy Bucket\n剧本:Mokurei-木灵君\n音频后期:DMYoung/纳兰寻风/Crazy Bucket\n包装:破晓天", + "desc_v2": [ + { + "raw_text": "【CB想说的】看完拜年祭之后最爱的一个节目!给有快板的部分简单加了一些不同风格的配乐hhh,感谢沃玛画的我!太可爱了哈哈哈哈哈哈哈!!!\n【Warma想说的】我画了打碟的CB,画风为了还原原版视频所以参考了四迹老师的画风,四迹老师的画真的太可爱啦!不过其实在画的过程中我遇到了一个问题,CB的耳机……到底是戴在哪个耳朵上呢?\n\n原版:av78977080\n编曲(配乐):Crazy Bucket\n人声(配音):Warma/谢拉\n曲绘:四迹/Warma\n动画:四迹/Crazy Bucket\n剧本:Mokurei-木灵君\n音频后期:DMYoung/纳兰寻风/Crazy Bucket\n包装:破晓天", + "type": 1, + "biz_id": 0 + } + ], + "state": 0, + "duration": 486, + "mission_id": 11838, + "rights": { + "bp": 0, + "elec": 0, + "download": 1, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 1, + "ugc_pay_preview": 0, + "no_background": 0, + "clean_mode": 0, + "is_stein_gate": 0, + "is_360": 0, + "no_share": 0, + "arc_pay": 0, + "free_watch": 0 + }, + "owner": { + "mid": 66606350, + "name": "陈楒潼桶桶桶", + "face": "https://i2.hdslb.com/bfs/face/c9af3b32cf74baec5a4b65af8ca18ae5ff571f77.jpg" + }, + "stat": { + "aid": 85440373, + "view": 2404179, + "danmaku": 12348, + "reply": 2676, + "favorite": 58329, + "coin": 72793, + "share": 9620, + "now_rank": 0, + "his_rank": 55, + "like": 161270, + "dislike": 0, + "evaluation": "", + "vt": 0 + }, + "argue_info": { + "argue_msg": "", + "argue_type": 0, + "argue_link": "" + }, + "dynamic": "进来就出不去了!!!\n#全民音乐UP主##CB##warma##电音##快板##拜年祭##诸神的奥运##编曲##Remix#", + "cid": 146044693, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "premiere": null, + "teenage_mode": 0, + "is_chargeable_season": false, + "is_story": false, + "is_upower_exclusive": false, + "is_upower_play": false, + "is_upower_preview": false, + "enable_vt": 0, + "vt_display": "", + "is_upower_exclusive_with_qa": false, + "no_cache": false, + "pages": [ + { + "cid": 146044693, + "page": 1, + "from": "vupload", + "part": "建议改成:建议改成:诸 神 的 电 音 节(不是)", + "duration": 486, + "vid": "", + "weblink": "", + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "ctime": 1580212263 + } + ], + "subtitle": { + "allow_submit": false, + "list": [ + { + "id": 1061981378473779968, + "lan": "ai-zh", + "lan_doc": "中文(自动生成)", + "is_lock": false, + "subtitle_url": "", + "type": 1, + "id_str": "1061981378473779968", + "ai_type": 0, + "ai_status": 2, + "author": { + "mid": 0, + "name": "", + "sex": "", + "face": "", + "sign": "", + "rank": 0, + "birthday": 0, + "is_fake_account": 0, + "is_deleted": 0, + "in_reg_audit": 0, + "is_senior_member": 0, + "name_render": null + } + } + ] + }, + "staff": [ + { + "mid": 66606350, + "title": "UP主", + "name": "陈楒潼桶桶桶", + "face": "https://i2.hdslb.com/bfs/face/c9af3b32cf74baec5a4b65af8ca18ae5ff571f77.jpg", + "vip": { + "type": 2, + "status": 1, + "due_date": 1769443200000, + "vip_pay_type": 1, + "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": 0, + "avatar_icon": { + "icon_type": 1, + "icon_resource": {} + } + }, + "official": { + "role": 1, + "title": "bilibili 知名音乐UP主", + "desc": "", + "type": 0 + }, + "follower": 616428, + "label_style": 0 + }, + { + "mid": 53456, + "title": "曲绘", + "name": "Warma", + "face": "https://i2.hdslb.com/bfs/face/87c0b7e4d3eedf04c458a82b9271013beaa4bc59.jpg", + "vip": { + "type": 2, + "status": 1, + "due_date": 1770480000000, + "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": "https://i0.hdslb.com/bfs/activity-plat/static/20220608/e369244d0b14644f5e1a06431e22a4d5/0DFy9BHgwE.gif", + "img_label_uri_hant": "", + "img_label_uri_hans_static": "https://i0.hdslb.com/bfs/vip/8d7e624d13d3e134251e4174a7318c19a8edbd71.png", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/uckjAv3Npy.png" + }, + "avatar_subscript": 1, + "nickname_color": "#FB7299", + "role": 3, + "avatar_subscript_url": "", + "tv_vip_status": 1, + "tv_vip_pay_type": 1, + "tv_due_date": 1753286400, + "avatar_icon": { + "icon_type": 1, + "icon_resource": {} + } + }, + "official": { + "role": 1, + "title": "bilibili 知名UP主", + "desc": "", + "type": 0 + }, + "follower": 4818052, + "label_style": 0 + } + ], + "is_season_display": false, + "user_garb": { + "url_image_ani_cut": "https://i0.hdslb.com/bfs/garb/item/e4c1c34e8b87fc05a893ed4a04ad322f75edbed9.bin" + }, + "honor_reply": { + "honor": [ + { + "aid": 85440373, + "type": 2, + "desc": "第45期每周必看", + "weekly_recommend_num": 45 + }, + { + "aid": 85440373, + "type": 3, + "desc": "全站排行榜最高第55名", + "weekly_recommend_num": 0 + }, + { + "aid": 85440373, + "type": 4, + "desc": "热门", + "weekly_recommend_num": 0 + }, + { + "aid": 85440373, + "type": 7, + "desc": "热门收录", + "weekly_recommend_num": 0 + } + ] + }, + "like_icon": "", + "need_jump_bv": false, + "disable_show_up_info": false, + "is_story_play": 1, + "is_view_self": false + } +} +``` + +
+ +视频标题为:`当我给拜年祭的快板加了电音配乐…` + +视频分区为:`tid=28(音乐->原创音乐)` + +视频时长:`486s` + +视频发布时间:`2020/1/30 17:40:55` + +视频投稿时间:`2020/1/28 19:51:3` + +视频分P为:`1` + +视频类型为:`1(原创)` + +视频UP主为:`66606350(Crazy_Bucket_陈楒潼)` + +视频简介为: + +`【CB想说的】看完拜年祭之后最爱的一个节目!给有快板的部分简单加了一些不同风格的配乐hhh,感谢沃玛画的我!太可爱了哈哈哈哈哈哈哈!!!\n【Warma想说的】我画了打碟的CB,画风为了还原原版视频所以参考了四迹老师的画风,四迹老师的画真的太可爱啦!不过其实在画的过程中我遇到了一个问题,CB的耳机……到底是戴在哪个耳朵上呢?\n\n原版:av78977080\n编曲(配乐):Crazy Bucket\n人声(配音):Warma/谢拉\n曲绘:四迹/Warma\n动画:四迹/Crazy Bucket\n剧本:Mokurei-木灵君\n音频后期:DMYoung/纳兰寻风/Crazy Bucket\n包装:破晓天` + +视频状态为:`0(开放浏览)` + +视频属性为: `显示“禁止转载“标志`、`高清`、`禁止其他人添加TAG`、`联合投稿视频` + +视频封面为: + +https://i1.hdslb.com/bfs/archive/ea0dd34bf41e23a68175680a00e3358cd249105f.jpg + + + +## 获取视频超详细信息(web端) + +> https://api.bilibili.com/x/web-interface/view/detail + +> https://api.bilibili.com/x/web-interface/wbi/view/detail + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +鉴权方式:[Wbi 签名](../misc/sign/wbi.md) + +限制游客访问的视频需要登录 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| --------- | ---- | -------------------- | ---------- | ------------------ | +| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 | +| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 | +| need_elec | num | 是否获取UP主充电信息 | 非必要 | 0:否
1:是 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-400:请求错误
-403:权限不足
-404:无视频
62002:稿件不可见
62004:稿件审核中
62012:仅UP主自己可见 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------------- | ----- | ---------------- | ------------ | +| View | obj | 视频基本信息 | | +| Card | obj | 视频UP主信息 | | +| Tags | array | 视频TAG信息 | | +| Reply | obj | 视频热评信息 | | +| Related | array | 推荐视频信息 | | +| Spec | null | ? | 作用尚不明确 | +| hot_share | obj | ? | 作用尚不明确 | +| elec | 有效时:obj
无效时:null | 充电信息 | 当请求参数 `need_elec=1` 且有充电信息时有效 | +| recommend | null | ? | 作用尚不明确 | +| emergency | obj | 视频操作按钮信息 | | +| view_addit | obj | ? | 作用尚不明确 | +| guide | null | ? | 作用尚不明确 | +| query_tags | null | ? | 作用尚不明确 | +| participle | array | 分词信息 | 用于推荐 | +| module_ctrl | null | ? | 作用尚不明确 | +| replace_recommend | bool | ? | 作用尚不明确 | + +`data`中的`View`对象: + +基本同「[获取视频详细信息(web端)](#获取视频详细信息web端)」中的data对象 + +`data`中的`Card`对象: + +基本同「[用户名片信息](../user/info.md#用户名片信息)」中的data对象 + +`data`中的`Tags`数组: + +基本同「[获取视频TAG信息(新)](tags.md#获取视频TAG信息新)」中的data数组 + +`data`中的`Reply`对象: + +基本同「[获取评论区热评](../comment/list.md#获取评论区热评)」中的data对象 + +`data`中的`Related`数组: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|-----------|-----| +| 0 | obj | 推荐视频1 | | +| n | obj | 推荐视频(n+1) | | +| …… | obj | …… | …… | + +`Related`数组中的对象: + +基本同「[获取视频详细信息(web端)](#获取视频详细信息web端)」中的data对象,已知部分字段有差异,如没有分P信息 + +`data`中的`hot_share`对象: + +| 字段 | 类型 | 内容 | 备注 | +|------|-------|-------|--------| +| show | bool | false | 作用尚不明确 | +| list | array | 空 | 作用尚不明确 | + +`data`中的`elec`对象: + +基本同「[获取视频充电鸣谢名单](../electric/charge_list.md#获取视频充电鸣谢名单)」中的data对象 + +`data`中的`emergency`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------------------ | -------- | +| no_like | bool | 是否不显示点赞按钮 | | +| no_coin | bool | 是否不显示投币按钮 | | +| no_fav | bool | 是否不显示收藏按钮 | | +| no_share | bool | 是否不显示分享按钮 | | + +`data`中的`view_addit`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------------- | ------------ | +| 63 | bool | 是否不显示直播推荐 | | +| 64 | bool | 是否不显示活动推荐 | | +| 69 | bool | ? | 作用尚不明确 | +| 71 | bool | 是否不显示标签与笔记 | | +| 72 | bool | ? | 作用尚不明确 | + +**示例:** + +获取视频`av170001`/`BV17x411w7KC`的详细信息 + +avid方式: + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/view/detail' \ +--data-urlencode 'aid=170001' \ +--data-urlencode 'need_elec=1' +``` + +bvid方式: + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/view/detail' \ +--data-urlencode 'bvid=BV17x411w7KC' \ +--data-urlencode 'need_elec=1' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "View": { + "bvid": "BV17x411w7KC", + "aid": 170001, + "videos": 10, + "tid": 193, + "tid_v2": 2017, + "tname": "MV", + "tname_v2": "MV", + "copyright": 2, + "pic": "http://i2.hdslb.com/bfs/archive/1ada8c32a9d168e4b2ee3e010f24789ba3353785.jpg", + "title": "【MV】保加利亚妖王AZIS视频合辑", + "pubdate": 1320850533, + "ctime": 1497380562, + "desc": "sina 保加利亚超级天王 Azis1999年出道。他的音乐融合保加利亚名族曲风chalga和pop、rap等元素,不过他惊艳的易装秀与浮夸的角色诠释才是他最为出名的地方 Azis与众多保加利亚天王天后级歌手都有过合作.06年,他作为Mariana Popova的伴唱,在欧洲半决赛上演唱了他们的参赛曲Let Me Cry 06年他被Velikite Balgari评为保加利亚有史以来最伟大的名人之一", + "desc_v2": [ + { + "raw_text": "sina 保加利亚超级天王 Azis1999年出道。他的音乐融合保加利亚名族曲风chalga和pop、rap等元素,不过他惊艳的易装秀与浮夸的角色诠释才是他最为出名的地方 Azis与众多保加利亚天王天后级歌手都有过合作.06年,他作为Mariana Popova的伴唱,在欧洲半决赛上演唱了他们的参赛曲Let Me Cry 06年他被Velikite Balgari评为保加利亚有史以来最伟大的名人之一", + "type": 1, + "biz_id": 0 + } + ], + "state": 0, + "duration": 2412, + "rights": { + "bp": 0, + "elec": 0, + "download": 1, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "clean_mode": 0, + "is_stein_gate": 0, + "is_360": 0, + "no_share": 0, + "arc_pay": 0, + "free_watch": 0 + }, + "owner": { + "mid": 122541, + "name": "冰封.虾子", + "face": "http://i0.hdslb.com/bfs/face/40c46ee74dd6ea33d46c38cd6083e6a1286aa482.gif" + }, + "stat": { + "aid": 170001, + "view": 45252521, + "danmaku": 914336, + "reply": 184686, + "favorite": 883733, + "coin": 291585, + "share": 12779204, + "now_rank": 0, + "his_rank": 13, + "like": 928358, + "dislike": 0, + "evaluation": "", + "vt": 0 + }, + "argue_info": { + "argue_msg": "", + "argue_type": 0, + "argue_link": "" + }, + "dynamic": "", + "cid": 279786, + "dimension": { + "width": 512, + "height": 288, + "rotate": 0 + }, + "premiere": null, + "teenage_mode": 0, + "is_chargeable_season": false, + "is_story": false, + "is_upower_exclusive": false, + "is_upower_play": false, + "is_upower_preview": false, + "enable_vt": 0, + "vt_display": "", + "is_upower_exclusive_with_qa": false, + "no_cache": false, + "pages": [ + { + "cid": 279786, + "page": 1, + "from": "vupload", + "part": "Хоп", + "duration": 199, + "vid": "", + "weblink": "", + "dimension": { + "width": 512, + "height": 288, + "rotate": 0 + }, + "ctime": 1497380562 + }, + { + "cid": 275431, + "page": 2, + "from": "vupload", + "part": "Imash li surce", + "duration": 205, + "vid": "", + "weblink": "", + "dimension": { + "width": 640, + "height": 360, + "rotate": 0 + }, + "ctime": 1497380562 + }, + { + "cid": 279787, + "page": 3, + "from": "vupload", + "part": "No Kazvam Ti Stiga", + "duration": 308, + "vid": "", + "weblink": "", + "dimension": { + "width": 432, + "height": 324, + "rotate": 0 + }, + "ctime": 1497380562 + }, + { + "cid": 280467, + "page": 4, + "from": "vupload", + "part": "Samo za teb", + "duration": 273, + "vid": "", + "weblink": "", + "dimension": { + "width": 360, + "height": 288, + "rotate": 0 + }, + "ctime": 1497380562 + }, + { + "cid": 280468, + "page": 5, + "from": "vupload", + "part": "Tochno sega", + "duration": 241, + "vid": "", + "weblink": "", + "dimension": { + "width": 584, + "height": 360, + "rotate": 0 + }, + "ctime": 1497380562 + }, + { + "cid": 280469, + "page": 6, + "from": "vupload", + "part": "Kak boli", + "duration": 336, + "vid": "", + "weblink": "", + "dimension": { + "width": 384, + "height": 288, + "rotate": 0 + }, + "ctime": 1497380562 + }, + { + "cid": 274491, + "page": 7, + "from": "vupload", + "part": "Obicham Te", + "duration": 250, + "vid": "", + "weblink": "", + "dimension": { + "width": 402, + "height": 208, + "rotate": 0 + }, + "ctime": 1497380562 + }, + { + "cid": 267410, + "page": 8, + "from": "vupload", + "part": "Mrazish", + "duration": 201, + "vid": "", + "weblink": "", + "dimension": { + "width": 540, + "height": 360, + "rotate": 0 + }, + "ctime": 1497380562 + }, + { + "cid": 267714, + "page": 9, + "from": "vupload", + "part": "Няма накъде", + "duration": 201, + "vid": "", + "weblink": "", + "dimension": { + "width": 450, + "height": 360, + "rotate": 0 + }, + "ctime": 1497380562 + }, + { + "cid": 270380, + "page": 10, + "from": "vupload", + "part": "Gadna poroda", + "duration": 198, + "vid": "", + "weblink": "", + "dimension": { + "width": 432, + "height": 324, + "rotate": 0 + }, + "ctime": 1497380562 + } + ], + "subtitle": { + "allow_submit": false, + "list": [] + }, + "is_season_display": false, + "user_garb": { + "url_image_ani_cut": "https://i0.hdslb.com/bfs/garb/item/e4c1c34e8b87fc05a893ed4a04ad322f75edbed9.bin" + }, + "honor_reply": { + "honor": [ + { + "aid": 170001, + "type": 3, + "desc": "全站排行榜最高第13名", + "weekly_recommend_num": 0 + } + ] + }, + "like_icon": "", + "need_jump_bv": false, + "disable_show_up_info": false, + "is_story_play": 0, + "is_view_self": false + }, + "Card": { + "card": { + "mid": "122541", + "name": "冰封.虾子", + "approve": false, + "sex": "保密", + "rank": "10000", + "face": "http://i0.hdslb.com/bfs/face/40c46ee74dd6ea33d46c38cd6083e6a1286aa482.gif", + "face_nft": 0, + "face_nft_type": 0, + "DisplayRank": "0", + "regtime": 0, + "spacesta": 0, + "birthday": "", + "place": "", + "description": "", + "article": 0, + "attentions": [], + "fans": 64052, + "friend": 45, + "attention": 45, + "sign": "路亚钓鱼爱好者交流群411267154", + "level_info": { + "current_level": 6, + "current_min": 0, + "current_exp": 0, + "next_exp": 0 + }, + "pendant": { + "pid": 0, + "name": "", + "image": "", + "expire": 0, + "image_enhance": "", + "image_enhance_frame": "", + "n_pid": 0 + }, + "nameplate": { + "nid": 9, + "name": "出道偶像", + "image": "https://i0.hdslb.com/bfs/face/3f2d64f048b39fb6c26f3db39df47e6080ec0f9c.png", + "image_small": "https://i0.hdslb.com/bfs/face/90c35d41d8a19b19474d6bac672394c17b444ce8.png", + "level": "高级勋章", + "condition": "所有自制视频总播放数>=50万" + }, + "Official": { + "role": 0, + "title": "", + "desc": "", + "type": -1 + }, + "official_verify": { + "type": -1, + "desc": "" + }, + "vip": { + "type": 1, + "status": 0, + "due_date": 1493827200000, + "vip_pay_type": 0, + "theme_type": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "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/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "", + "tv_vip_status": 0, + "tv_vip_pay_type": 0, + "tv_due_date": 0, + "avatar_icon": { + "icon_resource": {} + }, + "vipType": 1, + "vipStatus": 0 + }, + "is_senior_member": 0, + "name_render": null + }, + "space": { + "s_img": "http://i1.hdslb.com/bfs/activity-plat/static/LRjqHhi0wL.png", + "l_img": "http://i1.hdslb.com/bfs/space/cb1c3ef50e22b6096fde67febe863494caefebad.png" + }, + "following": false, + "archive_count": 382, + "article_count": 0, + "follower": 64052, + "like_num": 1048712 + }, + "Tags": [ + { + "tag_id": 0, + "tag_name": "发现《Hop》", + "music_id": "MA407124762800730394", + "tag_type": "bgm", + "jump_url": "https://music.bilibili.com/h5/music-detail?music_id=MA407124762800730394&cid=279786&aid=170001&na_close_hide=1" + }, + { + "tag_id": 117552, + "tag_name": "保加利亚妖王", + "music_id": "", + "tag_type": "old_channel", + "jump_url": "" + }, + { + "tag_id": 112503, + "tag_name": "保加利亚", + "music_id": "", + "tag_type": "old_channel", + "jump_url": "" + }, + { + "tag_id": 2958988, + "tag_name": "Азис", + "music_id": "", + "tag_type": "old_channel", + "jump_url": "" + }, + { + "tag_id": 2622213, + "tag_name": "azis", + "music_id": "", + "tag_type": "old_channel", + "jump_url": "" + }, + { + "tag_id": 2512079, + "tag_name": "mv", + "music_id": "", + "tag_type": "old_channel", + "jump_url": "" + } + ], + "Reply": { + "page": null, + "replies": [ + { + "rpid": 1, + "oid": 0, + "type": 0, + "mid": 0, + "root": 0, + "parent": 0, + "dialog": 0, + "count": 0, + "rcount": 0, + "state": 0, + "fansgrade": 0, + "attr": 0, + "ctime": 0, + "like": 0, + "action": 0, + "content": null, + "replies": null, + "assist": 0, + "show_follow": false + } + ] + }, + "Related": [ + { + "aid": 1252180876, + "videos": 1, + "tid": 130, + "tname": "音乐综合", + "copyright": 2, + "pic": "http://i2.hdslb.com/bfs/archive/5a4eef19e38a3fa27f9db53cc45e7233e714ae03.jpg", + "title": "Ricardo Milos - Dancin song [1080p]", + "pubdate": 1711002767, + "ctime": 1711002768, + "desc": "https://www.youtube.com/watch?v=e9ASqhs9770", + "state": 0, + "duration": 259, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 477132, + "name": "TAKERA", + "face": "https://i0.hdslb.com/bfs/face/5af8b319889ba7a7d20ac59edb8464d65f43c1e1.gif" + }, + "stat": { + "aid": 1252180876, + "view": 1590321, + "danmaku": 2766, + "reply": 2405, + "favorite": 58654, + "coin": 13468, + "share": 15966, + "now_rank": 0, + "his_rank": 0, + "like": 144640, + "dislike": 0, + "vt": 0, + "vv": 1590321, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 1483741030, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1hJ4m177RN", + "first_frame": "http://i0.hdslb.com/bfs/storyff/n240327ad1t4c11o1bbzfc2bkvg5fkuc_firsti.jpg", + "pub_location": "中国香港", + "cover43": "", + "tidv2": 2036, + "tnamev2": "舞蹈综合", + "pid_v2": 1004, + "pid_name_v2": "舞蹈", + "bvid": "BV1hJ4m177RN", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 1252180876, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 80433022, + "videos": 1, + "tid": 193, + "tname": "MV", + "copyright": 1, + "pic": "http://i1.hdslb.com/bfs/archive/5242750857121e05146d5d5b13a47a2a6dd36e98.jpg", + "title": "【官方 MV】Never Gonna Give You Up - Rick Astley", + "pubdate": 1577835803, + "ctime": 1577835803, + "desc": "-", + "state": 0, + "duration": 213, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 0, + "autoplay": 0, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 1, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 486906719, + "name": "索尼音乐中国", + "face": "https://i2.hdslb.com/bfs/face/6bc95d0670863d36bf9167a37b825c39ce258506.jpg" + }, + "stat": { + "aid": 80433022, + "view": 91790223, + "danmaku": 128050, + "reply": 170137, + "favorite": 1286326, + "coin": 1061915, + "share": 396054, + "now_rank": 0, + "his_rank": 0, + "like": 2464595, + "dislike": 0, + "vt": 0, + "vv": 91790223, + "fav_g": 10, + "like_g": 0 + }, + "dynamic": "", + "cid": 137649199, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1GJ411x7h7", + "up_from_v2": 15, + "pub_location": "未知", + "cover43": "", + "tidv2": 2017, + "tnamev2": "MV", + "pid_v2": 1003, + "pid_name_v2": "音乐", + "bvid": "BV1GJ411x7h7", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 80433022, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 718913090, + "videos": 1, + "tid": 27, + "tname": "综合", + "copyright": 1, + "pic": "http://i2.hdslb.com/bfs/archive/6567760d676268e2bf2e2c57486085a31427ed79.jpg", + "title": "【咩栗】镇 站 之 宝", + "pubdate": 1636448401, + "ctime": 1636448403, + "desc": "可以关注一下可爱的小羊和小狼呀~\n小羊主页:https://space.bilibili.com/745493\n小狼主页:https://space.bilibili.com/617459493\n⚡️☀️\n微博@电击咩阿栗\n微博@呜米嗷呜\n⚡️☀️\n网易云@咩栗\n网易云@呜米", + "state": 0, + "duration": 188, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 674421433, + "name": "呜米咩栗的草原日常", + "face": "https://i1.hdslb.com/bfs/face/5566e3a4786959527a72545f908b5664693a2945.jpg" + }, + "stat": { + "aid": 718913090, + "view": 315224, + "danmaku": 195, + "reply": 462, + "favorite": 2897, + "coin": 702, + "share": 202, + "now_rank": 0, + "his_rank": 0, + "like": 15615, + "dislike": 0, + "vt": 0, + "vv": 315224, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "咩栗,不可以。", + "cid": 436835160, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV14Q4y1S7HU", + "first_frame": "http://i0.hdslb.com/bfs/storyff/n211105a23d8ue6bh0m1ed1cu6yztac5_firsti.jpg", + "cover43": "", + "tidv2": 2047, + "tnamev2": "虚拟UP主", + "pid_v2": 1005, + "pid_name_v2": "二次元", + "bvid": "BV14Q4y1S7HU", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 718913090, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 895258574, + "videos": 2, + "tid": 130, + "tname": "音乐综合", + "copyright": 2, + "pic": "http://i2.hdslb.com/bfs/archive/b94b8be43cd0a9a12bf1a334541b017a3bd24cb6.jpg", + "title": "【全弹幕】av10388 武器A", + "pubdate": 1648906567, + "ctime": 1648906567, + "desc": "sm9307581\n武器A\n[日常]UP主:博丽·灵梦(UID:13308)\n播放:1605344 | 收藏:20926 | 弹幕:42522\n投稿时间:2010/06/20 10:13\n啊哈哈哈,啊哈哈,啊哈,啊……总之就是武器……", + "state": 0, + "duration": 144, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 104657830, + "name": "尚宜鼎MEMZ", + "face": "https://i1.hdslb.com/bfs/face/6761798442c6e9607c62803ac4fa5fe4a3e7b25b.jpg" + }, + "stat": { + "aid": 895258574, + "view": 3769820, + "danmaku": 22377, + "reply": 2776, + "favorite": 12271, + "coin": 484, + "share": 3748, + "now_rank": 0, + "his_rank": 0, + "like": 47622, + "dislike": 0, + "vt": 0, + "vv": 3769820, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 1491314436, + "dimension": { + "width": 2848, + "height": 1600, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1NP4y1K7Ze", + "first_frame": "http://i0.hdslb.com/bfs/storyff/n240402sa2muwqb7q7sbvedoskth1279_firsti.jpg", + "pub_location": "广东", + "cover43": "", + "tidv2": 2041, + "tnamev2": "动漫剪辑", + "pid_v2": 1005, + "pid_name_v2": "二次元", + "bvid": "BV1NP4y1K7Ze", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 895258574, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 56927206, + "videos": 1, + "tid": 138, + "tname": "搞笑", + "copyright": 2, + "pic": "http://i2.hdslb.com/bfs/archive/fd8324a72f0c6629f6d9b6af0daa11d950863993.jpg", + "title": "【每天一遍,网抑再见】万恶之源,抖就完事了", + "pubdate": 1561555314, + "ctime": 1561555314, + "desc": "【带字幕版】本人亲自翻译\nBGM:coincidance \n有些人看着看着就抖起来了,别说了,护士姐姐真漂亮\nhttps://www.youtube.com/watch?v=nBHkIWAJitg&feature=share\n肩膀好了,就来摇头吧\nav65659850", + "state": 0, + "duration": 139, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 34232005, + "name": "200斤的五条艾", + "face": "https://i1.hdslb.com/bfs/face/5135289ba858105ae466429ba9610e7980cf73f0.jpg" + }, + "stat": { + "aid": 56927206, + "view": 43534329, + "danmaku": 77687, + "reply": 19894, + "favorite": 1584517, + "coin": 721148, + "share": 563420, + "now_rank": 0, + "his_rank": 15, + "like": 2118557, + "dislike": 0, + "vt": 0, + "vv": 43534329, + "fav_g": 3, + "like_g": 0 + }, + "dynamic": "#沙雕##搞笑视频##魔性#", + "cid": 99428737, + "dimension": { + "width": 960, + "height": 720, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1Ax411d7jD", + "up_from_v2": 11, + "cover43": "", + "tidv2": 2059, + "tnamev2": "鬼畜调教", + "pid_v2": 1007, + "pid_name_v2": "鬼畜", + "bvid": "BV1Ax411d7jD", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 56927206, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 3643130, + "videos": 1, + "tid": 138, + "tname": "搞笑", + "copyright": 2, + "pic": "http://i1.hdslb.com/bfs/archive/bc23ac6f17c82700d5c1941e0991bc8a6fcbd46c.png", + "title": "金坷垃原版", + "pubdate": 1453518942, + "ctime": 1497431869, + "desc": "http://v.youku.com/v_show/id_XNTkzMDUxNzI0.html?from=y1.2-1-102.3.1-1.1-1-1-0-0#paction 给知道金坷垃的孩子们补补课", + "state": 0, + "duration": 101, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 11374676, + "name": "LX秦先生", + "face": "https://i2.hdslb.com/bfs/face/90a808cdd9414d5f53e04d85b8929333eb61f474.jpg" + }, + "stat": { + "aid": 3643130, + "view": 11110768, + "danmaku": 29385, + "reply": 7168, + "favorite": 287656, + "coin": 61435, + "share": 190334, + "now_rank": 0, + "his_rank": 0, + "like": 379164, + "dislike": 0, + "vt": 0, + "vv": 11110768, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 5827830, + "dimension": { + "width": 640, + "height": 354, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1Rs411R7Hi", + "cover43": "", + "tidv2": 2059, + "tnamev2": "鬼畜调教", + "pid_v2": 1007, + "pid_name_v2": "鬼畜", + "bvid": "BV1Rs411R7Hi", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 3643130, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 1601123876, + "videos": 1, + "tid": 130, + "tname": "音乐综合", + "copyright": 1, + "pic": "http://i0.hdslb.com/bfs/archive/bc7442c6c54ef573ebe0455104ad87703703fad5.jpg", + "title": "「保加利亚妖王」Hop - Azis 阿吉斯 百万级装备试听【Hi-Res】", + "pubdate": 1709023713, + "ctime": 1709023713, + "desc": "作词 : Azis\n作曲 : Azis\n\n\n\n音响:天朗皇家西敏寺\n功放:麦景图 \n录音MIC:纽曼149 \n录音设备:SSL+ Protools", + "state": 0, + "duration": 189, + "mission_id": 4009709, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 440121192, + "name": "JLRS日落fm", + "face": "https://i0.hdslb.com/bfs/face/008f2cf802f48e1d7f837887a3cefd95b918a0e5.jpg" + }, + "stat": { + "aid": 1601123876, + "view": 549485, + "danmaku": 1576, + "reply": 1569, + "favorite": 7872, + "coin": 5056, + "share": 4117, + "now_rank": 0, + "his_rank": 0, + "like": 22458, + "dislike": 0, + "vt": 0, + "vv": 549485, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "还记得这位妖王吗?", + "cid": 1452568619, + "dimension": { + "width": 3840, + "height": 2160, + "rotate": 0 + }, + "season_id": 4499678, + "short_link_v2": "https://b23.tv/BV1e1421f7rA", + "first_frame": "http://i2.hdslb.com/bfs/storyff/n240227sauzmn6l1y49t5cjnklc5tyvk_firsti.jpg", + "pub_location": "吉林", + "cover43": "", + "tidv2": 2024, + "tnamev2": "电台·歌单", + "pid_v2": 1003, + "pid_name_v2": "音乐", + "bvid": "BV1e1421f7rA", + "season_type": 1, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 1601123876, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 1581914, + "videos": 1, + "tid": 130, + "tname": "音乐综合", + "copyright": 2, + "pic": "http://i2.hdslb.com/bfs/archive/7437f19df1061f4a9cd2972b81dbd3a6723bf74c.jpg", + "title": "妖王都开始男人了,怎么办!", + "pubdate": 1412259320, + "ctime": 1497428704, + "desc": "音悦台 保加利亚妖男Azis /Азис携手流行男歌手Giorgos Tsalikis/Тсаликис 最新单曲 Estar Loco /Полудяваме\n纯爷们,男人就该干男人,该干的事。", + "state": 0, + "duration": 227, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 4685783, + "name": "FoolishJoker", + "face": "https://i2.hdslb.com/bfs/face/a81786a76af0cbd6d7e35adc488ccc22b0030d72.jpg" + }, + "stat": { + "aid": 1581914, + "view": 2303678, + "danmaku": 5815, + "reply": 6856, + "favorite": 28958, + "coin": 5696, + "share": 14014, + "now_rank": 0, + "his_rank": 0, + "like": 24255, + "dislike": 0, + "vt": 0, + "vv": 2303678, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 2403522, + "dimension": { + "width": 640, + "height": 360, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1gx411P77L", + "up_from_v2": 8, + "cover43": "", + "tidv2": 2027, + "tnamev2": "音乐综合", + "pid_v2": 1003, + "pid_name_v2": "音乐", + "bvid": "BV1gx411P77L", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 1581914, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 31130726, + "videos": 1, + "tid": 130, + "tname": "音乐综合", + "copyright": 2, + "pic": "http://i0.hdslb.com/bfs/archive/e9755c62c5a38ec352e424aa0d7d20417c1a3fde.jpg", + "title": "PPAP原版完整视频", + "pubdate": 1536122369, + "ctime": 1536122367, + "desc": "视频时长令强迫症不爽(我故意的)", + "state": 0, + "duration": 121, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 180305935, + "name": "不懂事的记忆", + "face": "https://i1.hdslb.com/bfs/face/7c1510f2fc8911cf885c9b14a94a99db738813c2.jpg" + }, + "stat": { + "aid": 31130726, + "view": 3810989, + "danmaku": 5269, + "reply": 2587, + "favorite": 76845, + "coin": 7721, + "share": 21117, + "now_rank": 0, + "his_rank": 0, + "like": 122042, + "dislike": 0, + "vt": 0, + "vv": 3810989, + "fav_g": 8, + "like_g": 0 + }, + "dynamic": "", + "cid": 54379754, + "dimension": { + "width": 640, + "height": 360, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1BW411Z7J3", + "up_from_v2": 8, + "cover43": "", + "tidv2": 2027, + "tnamev2": "音乐综合", + "pid_v2": 1003, + "pid_name_v2": "音乐", + "bvid": "BV1BW411Z7J3", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 31130726, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 675490509, + "videos": 1, + "tid": 138, + "tname": "搞笑", + "copyright": 2, + "pic": "http://i1.hdslb.com/bfs/archive/58f8f3c8dfcf3b1ac6cf7a7b0eda660aa2e1e1fc.jpg", + "title": "奥地利美术生就业经历", + "pubdate": 1631273645, + "ctime": 1631272999, + "desc": "https://m.youtube.com/watch?v=h7s410TPnWg", + "state": 0, + "duration": 128, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 489656132, + "name": "古米廖夫", + "face": "https://i2.hdslb.com/bfs/face/633ed3ba1ec5bcde5db105849c2498b03f6b7eee.jpg" + }, + "stat": { + "aid": 675490509, + "view": 40823108, + "danmaku": 48676, + "reply": 12360, + "favorite": 952804, + "coin": 557605, + "share": 256173, + "now_rank": 0, + "his_rank": 0, + "like": 1531015, + "dislike": 0, + "vt": 0, + "vv": 40823108, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 405970117, + "dimension": { + "width": 1280, + "height": 720, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1jU4y1N7vg", + "up_from_v2": 35, + "first_frame": "http://i1.hdslb.com/bfs/storyff/n210910a2u7yjx97xzec435kyzziyn8s_firsti.jpg", + "pub_location": "黑龙江", + "cover43": "", + "tidv2": 2060, + "tnamev2": "鬼畜剧场", + "pid_v2": 1007, + "pid_name_v2": "鬼畜", + "bvid": "BV1jU4y1N7vg", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 675490509, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 44501, + "videos": 1, + "tid": 26, + "tname": "音MAD", + "copyright": 2, + "pic": "http://i0.hdslb.com/bfs/archive/1dff881735a73cdc4757237e45eff03d42c81137.jpg", + "title": "久本雅美の頭がカービィのBGMに合わせて爆発したようです", + "pubdate": 1293118092, + "ctime": 1497366357, + "desc": "sm6999999 恭请四代御本尊様,45秒后大量召唤三色弹幕,顺带头像同步测试┗(^o^ )┓", + "state": 0, + "duration": 72, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 59948, + "name": "高興帝", + "face": "http://i2.hdslb.com/bfs/face/68a4fb8cf9442f0db277d58a9dbccbf02eacdad4.jpg" + }, + "stat": { + "aid": 44501, + "view": 2450853, + "danmaku": 16774, + "reply": 5627, + "favorite": 25342, + "coin": 3316, + "share": 3531, + "now_rank": 0, + "his_rank": 0, + "like": 47552, + "dislike": 0, + "vt": 0, + "vv": 2450853, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 74884, + "dimension": { + "width": 480, + "height": 360, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1Bx411c7NF", + "cover43": "", + "tidv2": 2062, + "tnamev2": "音MAD", + "pid_v2": 1007, + "pid_name_v2": "鬼畜", + "bvid": "BV1Bx411c7NF", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 44501, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 1706416465, + "videos": 1, + "tid": 193, + "tname": "MV", + "copyright": 2, + "pic": "http://i2.hdslb.com/bfs/archive/2365889cfca6e33566104487604138906a610c59.jpg", + "title": "【4K珍藏】诈骗神曲《Never Gonna Give You Up》!愿者上钩!", + "pubdate": 1723457882, + "ctime": 1723042776, + "desc": "《‌Never Gonna Give You Up》‌这首歌曲发行于1987年11月16日。‌这首歌曲由Rick Astley演唱,‌并收录于他的专辑《‌Whenever You Need Somebody》‌中。", + "state": 0, + "duration": 213, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 2043250564, + "name": "4K音乐馆", + "face": "https://i1.hdslb.com/bfs/face/4be964615e70e18ab469e4403cb0fa320f8d2fdc.jpg" + }, + "stat": { + "aid": 1706416465, + "view": 1001774, + "danmaku": 1150, + "reply": 1204, + "favorite": 20440, + "coin": 2354, + "share": 12072, + "now_rank": 0, + "his_rank": 0, + "like": 28749, + "dislike": 0, + "vt": 0, + "vv": 1001774, + "fav_g": 38, + "like_g": 0 + }, + "dynamic": "", + "cid": 1641702404, + "dimension": { + "width": 3840, + "height": 2160, + "rotate": 0 + }, + "season_id": 257515, + "short_link_v2": "https://b23.tv/BV1UT42167xb", + "first_frame": "http://i1.hdslb.com/bfs/storyff/n240807sa3h3ta5x4y8t48d3i1ld43yn_firsti.jpg", + "pub_location": "山东", + "cover43": "", + "tidv2": 2017, + "tnamev2": "MV", + "pid_v2": 1003, + "pid_name_v2": "音乐", + "bvid": "BV1UT42167xb", + "season_type": 1, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 1706416465, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 70025529, + "videos": 1, + "tid": 130, + "tname": "音乐综合", + "copyright": 2, + "pic": "http://i0.hdslb.com/bfs/archive/49948624e5b18fda60ec255eeffe9fb86e2a73a0.jpg", + "title": "大悲咒(高品质珍藏版)", + "pubdate": 1570435422, + "ctime": 1570183927, + "desc": "净化心情,佛祖保佑,大吉大利!!!", + "state": 0, + "duration": 1792, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 362819520, + "name": "抹茶牛油果", + "face": "http://i0.hdslb.com/bfs/face/3b2571027baef2a954c2fc1b5473ed609ef00fb3.jpg" + }, + "stat": { + "aid": 70025529, + "view": 15194194, + "danmaku": 126652, + "reply": 36609, + "favorite": 447623, + "coin": 115299, + "share": 201225, + "now_rank": 0, + "his_rank": 0, + "like": 432430, + "dislike": 0, + "vt": 0, + "vv": 15194194, + "fav_g": 49, + "like_g": 0 + }, + "dynamic": "#大悲咒##高音质##循环#", + "cid": 121325699, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1XE411S7Ew", + "cover43": "", + "tidv2": 2192, + "tnamev2": "疗愈成长", + "pid_v2": 1028, + "pid_name_v2": "神秘学", + "bvid": "BV1XE411S7Ew", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 70025529, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 827984205, + "videos": 1, + "tid": 193, + "tname": "MV", + "copyright": 2, + "pic": "http://i1.hdslb.com/bfs/archive/ffacd250c10ca7cea1a665e89b691b3b7b837587.jpg", + "title": "燃!保加利亚妖王2023新歌MV!", + "pubdate": 1688208848, + "ctime": 1688208848, + "desc": "youtube\n保加利亚妖王azis新歌mv", + "state": 0, + "duration": 225, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 1295732260, + "name": "蒂尼黄DiniHuang", + "face": "https://i1.hdslb.com/bfs/face/71cc994f3b717fb64dec53cab8b825b471f3886a.jpg" + }, + "stat": { + "aid": 827984205, + "view": 168546, + "danmaku": 188, + "reply": 343, + "favorite": 851, + "coin": 79, + "share": 2315, + "now_rank": 0, + "his_rank": 0, + "like": 4373, + "dislike": 0, + "vt": 0, + "vv": 168546, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 1181623685, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV19g4y1A7xq", + "up_from_v2": 8, + "first_frame": "http://i0.hdslb.com/bfs/storyff/n230701qn3tfuifpjvvh0e2pctwqbkep_firsti.jpg", + "pub_location": "上海", + "cover43": "", + "tidv2": 2017, + "tnamev2": "MV", + "pid_v2": 1003, + "pid_name_v2": "音乐", + "bvid": "BV19g4y1A7xq", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 827984205, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 80573606, + "videos": 1, + "tid": 29, + "tname": "音乐现场", + "copyright": 2, + "pic": "http://i0.hdslb.com/bfs/archive/b0433e71df7f856cf1a45a926361661eca28b8fb.jpg", + "title": "满级大佬屠杀新手村", + "pubdate": 1577243562, + "ctime": 1577243562, + "desc": "YouTube\n\n*《She Taught Me How to Yodel》\n\n约德尔唱法(Yodeling)是瑞士阿尔卑斯山区的一种特殊唱法,采用真假声迅速切换的方式演唱。“约德尔”,在当地方言中是“树林歌唱”的意思,因此有时也将其翻译为“woods sing”。\n\n小女孩叫Sofia Shkidchenko,演唱于乌克兰达人秀,她有自己的油管频道可以去订阅哦~\n\n自己也没想到随手上传的个视频突然播放量这么多,不是专业的搬运博主,此视频留作纪念,但更新随缘啦。祝大家万事如意。", + "state": 0, + "duration": 126, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 247412150, + "name": "Ueroey", + "face": "https://i2.hdslb.com/bfs/face/f8cef132ebaeac9da8c73ad52f6c53b7d1f74637.jpg" + }, + "stat": { + "aid": 80573606, + "view": 62129265, + "danmaku": 106580, + "reply": 27081, + "favorite": 1259191, + "coin": 453054, + "share": 189609, + "now_rank": 0, + "his_rank": 7, + "like": 2766708, + "dislike": 0, + "vt": 0, + "vv": 62129265, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "#音乐#", + "cid": 137890032, + "dimension": { + "width": 638, + "height": 312, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1LJ411W7Bo", + "up_from_v2": 9, + "pub_location": "浙江", + "cover43": "", + "tidv2": 2018, + "tnamev2": "音乐现场", + "pid_v2": 1003, + "pid_name_v2": "音乐", + "bvid": "BV1LJ411W7Bo", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 80573606, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 370010949, + "videos": 2, + "tid": 138, + "tname": "搞笑", + "copyright": 2, + "pic": "http://i1.hdslb.com/bfs/archive/8339e4a40c1a10cfb0e0abe0bc4ef6ecbd61a45f.jpg", + "title": "黑人抬棺原版视频", + "pubdate": 1585735296, + "ctime": 1585735296, + "desc": "up主关于本条视频收入的说明戳:BV1YK41157dT\n转载自https://www.youtube.com/watch?v=b3Y_9bTRGVg\n其他:抖棺(肩)舞:BV1kt4y127Ee\n苏卡棺裂:BV1GZ4y1x7mZ\n我是比划,感谢您的观看感谢点赞感谢一切!改天一定陪老铁好好比划比划!(咕)\n(建议大家戳一下宝藏2p)", + "state": 0, + "duration": 200, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 479724334, + "name": "比划大魔王", + "face": "http://i1.hdslb.com/bfs/face/910e60494f7deff1b3bdcf1eaaead6779d77bac5.jpg" + }, + "stat": { + "aid": 370010949, + "view": 65490009, + "danmaku": 454078, + "reply": 47875, + "favorite": 1008732, + "coin": 445010, + "share": 783444, + "now_rank": 0, + "his_rank": 2, + "like": 1912992, + "dislike": 0, + "vt": 0, + "vv": 65490009, + "fav_g": 24, + "like_g": 0 + }, + "dynamic": "", + "cid": 172423516, + "dimension": { + "width": 1280, + "height": 720, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1NZ4y1j7nw", + "cover43": "", + "tidv2": 2059, + "tnamev2": "鬼畜调教", + "pid_v2": 1007, + "pid_name_v2": "鬼畜", + "bvid": "BV1NZ4y1j7nw", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 370010949, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 161596, + "videos": 1, + "tid": 21, + "tname": "日常", + "copyright": 2, + "pic": "http://i2.hdslb.com/bfs/archive/90bc3229e862994ac021a5f0894f232bc49b36bf.jpg", + "title": "据说80%的男生都听过这段音乐,有木有?", + "pubdate": 1319379031, + "ctime": 1497399731, + "desc": "据说男生都听过,为啥我没有呢? ", + "state": 0, + "duration": 0, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 211322, + "name": "卍解←死神", + "face": "https://i2.hdslb.com/bfs/face/2cb86d5f33a409732e4a0dcc7cda70bc8c199a7f.jpg" + }, + "stat": { + "aid": 161596, + "view": 576962, + "danmaku": 1042, + "reply": 1638, + "favorite": 6576, + "coin": 227, + "share": 931, + "now_rank": 0, + "his_rank": 612, + "like": 9845, + "dislike": 0, + "vt": 0, + "vv": 576962, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 266868, + "dimension": { + "width": 448, + "height": 336, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1Nx411w7tR", + "cover43": "", + "tidv2": 2027, + "tnamev2": "音乐综合", + "pid_v2": 1003, + "pid_name_v2": "音乐", + "bvid": "BV1Nx411w7tR", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 161596, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 112699505707398, + "videos": 1, + "tid": 22, + "tname": "鬼畜调教", + "copyright": 1, + "pic": "http://i0.hdslb.com/bfs/archive/54c8218801e90a957e67541ea7d76e6d310614fe.jpg", + "title": "【范小勤】HOP", + "pubdate": 1719658405, + "ctime": 1719658405, + "desc": "", + "state": 0, + "duration": 200, + "mission_id": 1729431, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 40488241, + "name": "帅气的五岁少年", + "face": "https://i1.hdslb.com/bfs/face/0438443dd2bbb2fe1b46aa1d2134745f8d9f26c8.jpg" + }, + "stat": { + "aid": 112699505707398, + "view": 47395, + "danmaku": 176, + "reply": 125, + "favorite": 566, + "coin": 242, + "share": 1366, + "now_rank": 0, + "his_rank": 0, + "like": 1598, + "dislike": 0, + "vt": 0, + "vv": 47395, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 500001599795260, + "dimension": { + "width": 1440, + "height": 1080, + "rotate": 0 + }, + "season_id": 3617308, + "short_link_v2": "https://b23.tv/BV1J63veXEvH", + "first_frame": "http://i1.hdslb.com/bfs/storyff/n240629sabnqqnvswrfyh2h8capwsas5_firsti.jpg", + "pub_location": "上海", + "cover43": "", + "tidv2": 2059, + "tnamev2": "鬼畜调教", + "pid_v2": 1007, + "pid_name_v2": "鬼畜", + "bvid": "BV1J63veXEvH", + "season_type": 1, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 112699505707398, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 345957866, + "videos": 1, + "tid": 193, + "tname": "MV", + "copyright": 2, + "pic": "http://i2.hdslb.com/bfs/archive/2327de6051626e9f263e265805cbb1be3a05ad8d.jpg", + "title": "【越南神曲】-《Kẻ Cắp Gặp Bà Già 》!终于找到原版了!", + "pubdate": 1664102700, + "ctime": 1664027264, + "desc": "提到「越南电音」,大家可能会感到比较陌生,甚至摸不着头脑。 事实上,越南电音已经席卷国内短视频平台,没有人可以逃过它的轰炸。 音乐一开,无人不嗨~", + "state": 0, + "duration": 234, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 0, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 2043250564, + "name": "4K音乐馆", + "face": "https://i1.hdslb.com/bfs/face/4be964615e70e18ab469e4403cb0fa320f8d2fdc.jpg" + }, + "stat": { + "aid": 345957866, + "view": 8519264, + "danmaku": 3892, + "reply": 3755, + "favorite": 143914, + "coin": 9867, + "share": 8152, + "now_rank": 0, + "his_rank": 0, + "like": 136218, + "dislike": 0, + "vt": 0, + "vv": 8519264, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 842321779, + "dimension": { + "width": 3840, + "height": 2160, + "rotate": 0 + }, + "season_id": 725909, + "short_link_v2": "https://b23.tv/BV1Ud4y1M7C7", + "first_frame": "http://i1.hdslb.com/bfs/storyff/n220924qn371jsgk4te6781w32102ovo_firsti.jpg", + "pub_location": "山东", + "cover43": "", + "tidv2": 2017, + "tnamev2": "MV", + "pid_v2": 1003, + "pid_name_v2": "音乐", + "bvid": "BV1Ud4y1M7C7", + "season_type": 1, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 345957866, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 456093155, + "videos": 1, + "tid": 59, + "tname": "演奏", + "copyright": 1, + "pic": "http://i2.hdslb.com/bfs/archive/9c160af2907ba2c161d565a99e61032ba72868ff.png", + "title": "太羞耻了!敢于琴行挑战演奏《Hop》!", + "pubdate": 1592883074, + "ctime": 1592883074, + "desc": "太羞耻了!敢于琴行挑战演奏《Hop》! Hop改编版", + "state": 0, + "duration": 168, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 13677047, + "name": "Piano莱特", + "face": "https://i2.hdslb.com/bfs/face/edf6a0ae7dfe9adb5e8d5e813a69455554931c73.jpg" + }, + "stat": { + "aid": 456093155, + "view": 1432473, + "danmaku": 3867, + "reply": 1839, + "favorite": 14907, + "coin": 7949, + "share": 5164, + "now_rank": 0, + "his_rank": 0, + "like": 75832, + "dislike": 0, + "vt": 0, + "vv": 1432473, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 204234033, + "dimension": { + "width": 3840, + "height": 2160, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1r5411W71r", + "cover43": "", + "tidv2": 2021, + "tnamev2": "演奏", + "pid_v2": 1003, + "pid_name_v2": "音乐", + "bvid": "BV1r5411W71r", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 456093155, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 88379669, + "videos": 1, + "tid": 138, + "tname": "搞笑", + "copyright": 1, + "pic": "http://i0.hdslb.com/bfs/archive/44deb7e35de1c0d19fc79e6f838ad334585755f6.jpg", + "title": "当你怂恿网课老师放HOP", + "pubdate": 1581481509, + "ctime": 1581481509, + "desc": "我受不了了我要笑死了\n网课欢乐多", + "state": 0, + "duration": 131, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 8307655, + "name": "-Holog-", + "face": "https://i1.hdslb.com/bfs/face/797edf7cf269bdf89d1deb46b2b5068e65920b88.jpg" + }, + "stat": { + "aid": 88379669, + "view": 1553672, + "danmaku": 5349, + "reply": 1662, + "favorite": 7998, + "coin": 2519, + "share": 6023, + "now_rank": 0, + "his_rank": 0, + "like": 57979, + "dislike": 0, + "vt": 0, + "vv": 1553672, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "#保加利亚妖王##搞笑视频##HOP#\n把害怕打在公屏上_(:з」∠)_", + "cid": 150977310, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1D7411G76q", + "up_from_v2": 8, + "cover43": "", + "tidv2": 2207, + "tnamev2": "随拍·综合", + "pid_v2": 1032, + "pid_name_v2": "其他", + "bvid": "BV1D7411G76q", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 88379669, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 752882938, + "videos": 1, + "tid": 21, + "tname": "日常", + "copyright": 1, + "pic": "http://i0.hdslb.com/bfs/archive/f5a60b4edaef1b44faab4ffc47384843a7d47c56.jpg", + "title": "【av100000000】b站视频破亿了!第一亿个视频十小时循环(补档)", + "pubdate": 1588142976, + "ctime": 1588142976, + "desc": "【av100000000】b站视频破亿了!第一亿个视频十小时循环(补档)\nBV1y7411Q743/av100000000", + "state": 0, + "duration": 36000, + "mission_id": 13243, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 382043832, + "name": "輝夜姬想讓人告白", + "face": "https://i0.hdslb.com/bfs/face/647d2a40ac51b8e1379d6c46c64f5a8e28b269ab.jpg" + }, + "stat": { + "aid": 752882938, + "view": 161614, + "danmaku": 357, + "reply": 497, + "favorite": 1217, + "coin": 165, + "share": 166, + "now_rank": 0, + "his_rank": 0, + "like": 4623, + "dislike": 0, + "vt": 0, + "vv": 161614, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "#B站##BILIBILI##哔哩哔哩#", + "cid": 184673331, + "dimension": { + "width": 960, + "height": 600, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1Yk4y1r7g2", + "cover43": "", + "tidv2": 2207, + "tnamev2": "随拍·综合", + "pid_v2": 1032, + "pid_name_v2": "其他", + "bvid": "BV1Yk4y1r7g2", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 752882938, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 676186170, + "videos": 1, + "tid": 193, + "tname": "MV", + "copyright": 2, + "pic": "http://i1.hdslb.com/bfs/archive/24e8bd7eb31bbc142cd2676d28efa4c45c06bc33.jpg", + "title": "【4K60FPS】查理·普斯《See You Again》爆火神曲!珍惜身边的人!", + "pubdate": 1634983053, + "ctime": 1634983053, + "desc": "官方MV\n原盘提取制作,进行了部分调整\n中英文双语字幕制作,自己双语翻译\n《See You Again》是由美国说唱歌手维兹·卡利法与歌手查理·普斯合作演唱的一首歌曲\n这首歌,我想不用多说了,因为太多人点这首歌了\n希望大家珍惜身边的人", + "state": 0, + "duration": 229, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 0, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 229733301, + "name": "音乐私藏馆", + "face": "https://i0.hdslb.com/bfs/face/91a6526445f61e2d491523242b532d5e76f0435a.jpg" + }, + "stat": { + "aid": 676186170, + "view": 19331747, + "danmaku": 55418, + "reply": 19047, + "favorite": 459123, + "coin": 125647, + "share": 58270, + "now_rank": 0, + "his_rank": 30, + "like": 560583, + "dislike": 0, + "vt": 0, + "vv": 19331747, + "fav_g": 208, + "like_g": 0 + }, + "dynamic": "", + "cid": 429657756, + "dimension": { + "width": 3840, + "height": 2160, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1qU4y1F73A", + "first_frame": "http://i1.hdslb.com/bfs/storyff/n211023qn35uju26iwo4pw2enpricqvy_firsti.jpg", + "pub_location": "陕西", + "cover43": "", + "tidv2": 2017, + "tnamev2": "MV", + "pid_v2": 1003, + "pid_name_v2": "音乐", + "bvid": "BV1qU4y1F73A", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 676186170, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 11841799, + "videos": 1, + "tid": 236, + "tname": "竞技体育", + "copyright": 2, + "pic": "http://i2.hdslb.com/bfs/archive/20b223c72345a544272f70014f3a9ce2e30b39c8.jpg", + "title": "【万恶之源】游泳教练原视频", + "pubdate": 1499056716, + "ctime": 1499056716, + "desc": "在网盘里翻出来的不知道有没有人上传过。不断地摸索和练习,你就学会了游泳\n其中重点不能上传,我试过一次了。", + "state": 0, + "duration": 231, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 25844288, + "name": "希爾薇", + "face": "https://i2.hdslb.com/bfs/face/67b49b90952cd64320432ae561e78e54ea3ecb53.jpg" + }, + "stat": { + "aid": 11841799, + "view": 693786, + "danmaku": 4253, + "reply": 1097, + "favorite": 20296, + "coin": 2820, + "share": 14821, + "now_rank": 0, + "his_rank": 0, + "like": 13990, + "dislike": 0, + "vt": 0, + "vv": 693786, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 19555184, + "dimension": { + "width": 352, + "height": 288, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1ox411B7jr", + "cover43": "", + "tidv2": 2063, + "tnamev2": "鬼畜综合", + "pid_v2": 1007, + "pid_name_v2": "鬼畜", + "bvid": "BV1ox411B7jr", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 11841799, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 96842562, + "videos": 1, + "tid": 193, + "tname": "MV", + "copyright": 2, + "pic": "http://i0.hdslb.com/bfs/archive/5c33d3957fee3dac7376ab12b3e9a2b595600d84.jpg", + "title": "真正的冰雪女王", + "pubdate": 1584448702, + "ctime": 1584448702, + "desc": "转载https://weibo.com/tv/v/FlXRiE62K?fid=1034:217aa2b6ddb0f47e65468914c7d2c9af\n妖王的歌简直可以洗涤灵魂", + "state": 0, + "duration": 219, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 388982725, + "name": "萌萌四海为家", + "face": "https://i1.hdslb.com/bfs/face/f4ce35193db8743094a4efb4e00e97442244f2aa.jpg" + }, + "stat": { + "aid": 96842562, + "view": 39902, + "danmaku": 47, + "reply": 32, + "favorite": 372, + "coin": 39, + "share": 627, + "now_rank": 0, + "his_rank": 0, + "like": 507, + "dislike": 0, + "vt": 0, + "vv": 39902, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "#欧美MV##BGM##歌曲#", + "cid": 165335972, + "dimension": { + "width": 480, + "height": 360, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1V7411Z7HX", + "cover43": "", + "tidv2": 2017, + "tnamev2": "MV", + "pid_v2": 1003, + "pid_name_v2": "音乐", + "bvid": "BV1V7411Z7HX", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 96842562, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 84204989, + "videos": 1, + "tid": 267, + "tname": "电台", + "copyright": 1, + "pic": "http://i0.hdslb.com/bfs/archive/c6533d1b6c9fcd3cd574a0117acaa4e5ddbe7fa4.jpg", + "title": "【B站入站曲】(全站最清晰音质)", + "pubdate": 1579462179, + "ctime": 1579462179, + "desc": "【B站音乐同名】本曲是本人使用Chrome+多种技术手段历时4个小时扒出的原曲,扒曲不易(如有异议请自行尝试即可知之),请多支持!", + "state": 0, + "duration": 131, + "mission_id": 12642, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 189708807, + "name": "Yc云灿", + "face": "https://i0.hdslb.com/bfs/face/c815a0c66ab6adbd208558a0fe25c59c6ee916fa.jpg" + }, + "stat": { + "aid": 84204989, + "view": 113298, + "danmaku": 2640, + "reply": 426, + "favorite": 6659, + "coin": 1578, + "share": 238, + "now_rank": 0, + "his_rank": 0, + "like": 8192, + "dislike": 0, + "vt": 0, + "vv": 113298, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "#2019##2019年度报告##年度报告#", + "cid": 144036516, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV157411v76Z", + "pub_location": "山西", + "cover43": "", + "tidv2": 2024, + "tnamev2": "电台·歌单", + "pid_v2": 1003, + "pid_name_v2": "音乐", + "bvid": "BV157411v76Z", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 84204989, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 45213203, + "videos": 1, + "tid": 138, + "tname": "搞笑", + "copyright": 1, + "pic": "http://i0.hdslb.com/bfs/archive/1c73c8c16fe733568c3b6a5332c85be3ddc41acd.jpg", + "title": "如果把极乐净土的背景音乐换成hop会怎么样", + "pubdate": 1551585358, + "ctime": 1551585358, + "desc": "-", + "state": 0, + "duration": 222, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 300015102, + "name": "砂糖血块", + "face": "https://i0.hdslb.com/bfs/face/77d73e4aa3fa669255be492596e02f1570f4fb5d.jpg" + }, + "stat": { + "aid": 45213203, + "view": 521576, + "danmaku": 4054, + "reply": 867, + "favorite": 12646, + "coin": 12832, + "share": 8799, + "now_rank": 0, + "his_rank": 0, + "like": 31530, + "dislike": 0, + "vt": 0, + "vv": 521576, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 79166580, + "dimension": { + "width": 1144, + "height": 640, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1bb411B7dn", + "cover43": "", + "tidv2": 2036, + "tnamev2": "舞蹈综合", + "pid_v2": 1004, + "pid_name_v2": "舞蹈", + "bvid": "BV1bb411B7dn", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 45213203, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 66372123, + "videos": 1, + "tid": 21, + "tname": "日常", + "copyright": 1, + "pic": "http://i2.hdslb.com/bfs/archive/a12315d2efc49f1862be996093c8076284719e43.jpg", + "title": "学校食堂公然放HOP,这到底是人性的泯灭,还是道德的伦桑?", + "pubdate": 1567398824, + "ctime": 1567398825, + "desc": "吃饭时的我惊呆了。。。", + "state": 0, + "duration": 61, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 298061175, + "name": "Dusk-氵夕", + "face": "https://i0.hdslb.com/bfs/face/803bf620ead9c25168935e31797b25d51f2cb614.jpg" + }, + "stat": { + "aid": 66372123, + "view": 270243, + "danmaku": 238, + "reply": 211, + "favorite": 1443, + "coin": 116, + "share": 427, + "now_rank": 0, + "his_rank": 0, + "like": 7846, + "dislike": 0, + "vt": 0, + "vv": 270243, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "#自制##奇葩##HOP#", + "cid": 115113475, + "dimension": { + "width": 1280, + "height": 720, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV174411177w", + "up_from_v2": 8, + "pub_location": "宁夏", + "cover43": "", + "tidv2": 2088, + "tnamev2": "社会观察", + "pid_v2": 1010, + "pid_name_v2": "知识", + "bvid": "BV174411177w", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 66372123, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 669351541, + "videos": 1, + "tid": 138, + "tname": "搞笑", + "copyright": 1, + "pic": "http://i2.hdslb.com/bfs/archive/fa08f65dc87fa6a26a99d0dc6fbc141adcef917b.jpg", + "title": "这TM才是东京热!!!", + "pubdate": 1597827562, + "ctime": 1597827562, + "desc": "祝大家长高3cm!", + "state": 0, + "duration": 73, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 641529005, + "name": "海胆君の日本留学日记", + "face": "https://i2.hdslb.com/bfs/face/75b3ddf5767533667d08c4475823fdf6ed7111d0.jpg" + }, + "stat": { + "aid": 669351541, + "view": 183005, + "danmaku": 78, + "reply": 54, + "favorite": 685, + "coin": 101, + "share": 225, + "now_rank": 0, + "his_rank": 0, + "like": 1310, + "dislike": 0, + "vt": 0, + "vv": 183005, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "#bilibili新星计划##搞笑##全程高能#", + "cid": 226269297, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1ea4y177Rj", + "pub_location": "辽宁", + "cover43": "", + "tidv2": 2002, + "tnamev2": "影视剪辑", + "pid_v2": 1001, + "pid_name_v2": "影视", + "bvid": "BV1ea4y177Rj", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 669351541, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 239236582, + "videos": 1, + "tid": 22, + "tname": "鬼畜调教", + "copyright": 1, + "pic": "http://i2.hdslb.com/bfs/archive/60e0c8b0bdb8781ae5213d06e35a80e416b624fd.jpg", + "title": "av10388闪版", + "pubdate": 1706161150, + "ctime": 1706160987, + "desc": "-", + "state": 0, + "duration": 72, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 352435610, + "name": "尼911a", + "face": "https://i2.hdslb.com/bfs/face/dca0c49ddabaae204209764e73a1eeddd4e94fa3.jpg" + }, + "stat": { + "aid": 239236582, + "view": 98736, + "danmaku": 149, + "reply": 201, + "favorite": 700, + "coin": 45, + "share": 379, + "now_rank": 0, + "his_rank": 0, + "like": 875, + "dislike": 0, + "vt": 0, + "vv": 98736, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 1418632218, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1he411Y7MB", + "up_from_v2": 11, + "first_frame": "http://i2.hdslb.com/bfs/storyff/n240125saqkgdlb6aio291t2cc5qola0_firsti.jpg", + "pub_location": "江苏", + "cover43": "", + "tidv2": 2207, + "tnamev2": "随拍·综合", + "pid_v2": 1032, + "pid_name_v2": "其他", + "bvid": "BV1he411Y7MB", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 239236582, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 294464399, + "videos": 1, + "tid": 21, + "tname": "日常", + "copyright": 1, + "pic": "http://i2.hdslb.com/bfs/archive/8327a7955381a3a7fc0606b08ad87dd74a948a4b.png", + "title": "B站的两个极限AV号被我找到了!", + "pubdate": 1638019819, + "ctime": 1638019819, + "desc": "-", + "state": 0, + "duration": 71, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 495847991, + "name": "Tedsan", + "face": "https://i2.hdslb.com/bfs/face/d3689b9a5f93d82deb1f8b6a081767a16b16e5ca.jpg" + }, + "stat": { + "aid": 294464399, + "view": 86852, + "danmaku": 25, + "reply": 280, + "favorite": 338, + "coin": 54, + "share": 61, + "now_rank": 0, + "his_rank": 0, + "like": 450, + "dislike": 0, + "vt": 0, + "vv": 86852, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 450235439, + "dimension": { + "width": 1440, + "height": 720, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1fF411b7Hm", + "up_from_v2": 19, + "first_frame": "http://i1.hdslb.com/bfs/storyff/n211127a23442em8g5nug2775mg3789m_firsti.jpg", + "pub_location": "四川", + "cover43": "", + "tidv2": 2207, + "tnamev2": "随拍·综合", + "pid_v2": 1032, + "pid_name_v2": "其他", + "bvid": "BV1fF411b7Hm", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 294464399, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 592220402, + "videos": 1, + "tid": 193, + "tname": "MV", + "copyright": 2, + "pic": "http://i2.hdslb.com/bfs/archive/234b7c4a99412224007bf21a0e3902946dc45cd6.jpg", + "title": "【4K50帧】“我在东北玩泥巴”原曲 Daler Mehndi - Tunak Tunak Tun", + "pubdate": 1638883948, + "ctime": 1638883948, + "desc": "-", + "state": 0, + "duration": 257, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 0, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 472562429, + "name": "智英武54", + "face": "https://i2.hdslb.com/bfs/face/e7bb5b2f16863992562f10ce2a686035bf33a1b4.jpg" + }, + "stat": { + "aid": 592220402, + "view": 2711581, + "danmaku": 7298, + "reply": 1980, + "favorite": 58898, + "coin": 5115, + "share": 17577, + "now_rank": 0, + "his_rank": 0, + "like": 72931, + "dislike": 0, + "vt": 0, + "vv": 2711581, + "fav_g": 11, + "like_g": 0 + }, + "dynamic": "", + "cid": 456563995, + "dimension": { + "width": 2880, + "height": 2160, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1bq4y1q7Ho", + "up_from_v2": 8, + "first_frame": "http://i2.hdslb.com/bfs/storyff/n211207a24niqqktio4no1wmwd5tsget_firsti.jpg", + "pub_location": "江苏", + "cover43": "", + "tidv2": 2017, + "tnamev2": "MV", + "pid_v2": 1003, + "pid_name_v2": "音乐", + "bvid": "BV1bq4y1q7Ho", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 592220402, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 441264199, + "videos": 1, + "tid": 26, + "tname": "音MAD", + "copyright": 1, + "pic": "http://i0.hdslb.com/bfs/archive/4e36449edad0021385e5477bbe427ca9243d549a.jpg", + "title": "五大哲学", + "pubdate": 1679426636, + "ctime": 1679426636, + "desc": "-", + "state": 0, + "duration": 13, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 613658683, + "name": "长瀞重度依赖", + "face": "https://i1.hdslb.com/bfs/face/c53f852b5ca574eed9be9877d7ce3f28a2e89385.jpg" + }, + "stat": { + "aid": 441264199, + "view": 671881, + "danmaku": 92, + "reply": 230, + "favorite": 2720, + "coin": 228, + "share": 1060, + "now_rank": 0, + "his_rank": 0, + "like": 9049, + "dislike": 0, + "vt": 0, + "vv": 671881, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 1064182352, + "dimension": { + "width": 720, + "height": 720, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1nL411r7mS", + "up_from_v2": 8, + "first_frame": "http://i2.hdslb.com/bfs/storyff/n230322qntglnzeqo4m1c23cnoyehccs_firsti.jpg", + "pub_location": "广西", + "cover43": "", + "tidv2": 2015, + "tnamev2": "娱乐综合", + "pid_v2": 1002, + "pid_name_v2": "娱乐", + "bvid": "BV1nL411r7mS", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 441264199, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 49016435, + "videos": 1, + "tid": 31, + "tname": "翻唱", + "copyright": 1, + "pic": "http://i2.hdslb.com/bfs/archive/9b7da84975469b7ddcd78717d06c092c4433ccf4.jpg", + "title": "【喵会长】妹子竟被逼着翻唱保加利亚妖王!⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄!", + "pubdate": 1555135227, + "ctime": 1554999201, + "desc": "这次视频改了N遍,剪的好累~希望大家能多多支持一下\n网易云音频链接:https://music.163.com/#/song?id=1358976277\n关注微博有惊喜!@隔壁班的喵会长", + "state": 0, + "duration": 200, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 21330948, + "name": "隔壁班的喵会长", + "face": "https://i0.hdslb.com/bfs/face/75a4a80496daacb478496f6a0aaf4d3ab357393d.jpg" + }, + "stat": { + "aid": 49016435, + "view": 1988312, + "danmaku": 8866, + "reply": 5413, + "favorite": 53008, + "coin": 136074, + "share": 13019, + "now_rank": 0, + "his_rank": 4, + "like": 268302, + "dislike": 0, + "vt": 0, + "vv": 1988312, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "那个曾经制霸b站的男银又肥来了!!!!", + "cid": 86290623, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1vb411M79s", + "pub_location": "山西", + "cover43": "", + "tidv2": 2061, + "tnamev2": "人力VOCALOID", + "pid_v2": 1007, + "pid_name_v2": "鬼畜", + "bvid": "BV1vb411M79s", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 49016435, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 730704908, + "videos": 1, + "tid": 193, + "tname": "MV", + "copyright": 2, + "pic": "http://i1.hdslb.com/bfs/archive/2fd2b442a3f42ed0ba20c5204afdd92dbdfb9a68.jpg", + "title": "【越南神曲】-《Cứ Chill Thôi》!终于找到原版了!", + "pubdate": 1663586400, + "ctime": 1663574508, + "desc": "听完以后瞬间心情舒畅,太绝了!", + "state": 0, + "duration": 281, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 0, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 2043250564, + "name": "4K音乐馆", + "face": "https://i1.hdslb.com/bfs/face/4be964615e70e18ab469e4403cb0fa320f8d2fdc.jpg" + }, + "stat": { + "aid": 730704908, + "view": 4715077, + "danmaku": 3141, + "reply": 4132, + "favorite": 75716, + "coin": 9002, + "share": 7597, + "now_rank": 0, + "his_rank": 0, + "like": 79627, + "dislike": 0, + "vt": 0, + "vv": 4715077, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 837595821, + "dimension": { + "width": 3840, + "height": 2160, + "rotate": 0 + }, + "season_id": 725909, + "short_link_v2": "https://b23.tv/BV1GD4y1i7dA", + "first_frame": "http://i2.hdslb.com/bfs/storyff/n220919qn29hpyl52if2k1dthb32a0ji_firsti.jpg", + "pub_location": "山东", + "cover43": "", + "tidv2": 2017, + "tnamev2": "MV", + "pid_v2": 1003, + "pid_name_v2": "音乐", + "bvid": "BV1GD4y1i7dA", + "season_type": 1, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 730704908, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 413754644, + "videos": 1, + "tid": 59, + "tname": "演奏", + "copyright": 1, + "pic": "http://i0.hdslb.com/bfs/archive/4769bc9c91af6fc8598d1b22d16033b540af33a8.jpg", + "title": "【东京热】TOKY HOT THEME SONG ( FULL VERSION)", + "pubdate": 1594208253, + "ctime": 1594208253, + "desc": "-", + "state": 0, + "duration": 157, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 476156735, + "name": "星际的小喵", + "face": "http://i2.hdslb.com/bfs/face/b6fcd4d4d23047432012576dda4239b5d0b5fa6e.jpg" + }, + "stat": { + "aid": 413754644, + "view": 476215, + "danmaku": 166, + "reply": 906, + "favorite": 6630, + "coin": 627, + "share": 3116, + "now_rank": 0, + "his_rank": 0, + "like": 6086, + "dislike": 0, + "vt": 0, + "vv": 476215, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "#日本##音乐##东京#", + "cid": 210245452, + "dimension": { + "width": 426, + "height": 240, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1pV41167y7", + "cover43": "", + "tidv2": 2027, + "tnamev2": "音乐综合", + "pid_v2": 1003, + "pid_name_v2": "音乐", + "bvid": "BV1pV41167y7", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 413754644, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 468509831, + "videos": 1, + "tid": 193, + "tname": "MV", + "copyright": 2, + "pic": "http://i0.hdslb.com/bfs/archive/03971484b4c3931e89cbcf5862f8c10645e6aaec.jpg", + "title": "补裆 av3440 -", + "pubdate": 1651067890, + "ctime": 1651067890, + "desc": "新浪\nbiliplus,里面只有残缺的信息,发布时间应该是2010-2-27", + "state": 0, + "duration": 215, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 675115853, + "name": "゚゙゙゙゚゚゙゚゚", + "face": "https://i2.hdslb.com/bfs/face/8706d12c0df1f27aff5ae3c045b7da0133bd8c4a.png" + }, + "stat": { + "aid": 468509831, + "view": 280276, + "danmaku": 89, + "reply": 324, + "favorite": 4518, + "coin": 151, + "share": 209, + "now_rank": 0, + "his_rank": 0, + "like": 6403, + "dislike": 0, + "vt": 0, + "vv": 280276, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 586522933, + "dimension": { + "width": 320, + "height": 240, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1H541117sZ", + "up_from_v2": 8, + "first_frame": "http://i2.hdslb.com/bfs/storyff/n220427qn2g6emv26rnqxq247csj5kgn_firsti.jpg", + "cover43": "", + "tidv2": 2027, + "tnamev2": "音乐综合", + "pid_v2": 1003, + "pid_name_v2": "音乐", + "bvid": "BV1H541117sZ", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 468509831, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 19390801, + "videos": 1, + "tid": 22, + "tname": "鬼畜调教", + "copyright": 1, + "pic": "http://i0.hdslb.com/bfs/archive/d52994a1876d07a975dc6683b78a898d9b581208.png", + "title": "【春晚鬼畜】赵本山:我就是念诗之王!【改革春风吹满地】", + "pubdate": 1518339644, + "ctime": 1518230987, + "desc": "小时候每次吃完年夜饭,都会急急忙忙跑回自己房间跟朋友玩彩虹岛,街头篮球,泡泡堂,极品飞车,CS。一旦听到外面大人们喊“哦!赵本山来咯!”,就马上暂停手上的游戏赶紧跑出去看。对我来说没有赵本山的春晚根本不是春晚。\n鬼畜本家:av18521530\n【举起手来】花姑娘又要吸旺仔牛奶!\nby @疯猴pme", + "state": 0, + "duration": 152, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 353246678, + "name": "UP-Sings", + "face": "http://i2.hdslb.com/bfs/face/224815f69567dfbdacffc64185b89568bf8da0f3.jpg" + }, + "stat": { + "aid": 19390801, + "view": 123739584, + "danmaku": 667864, + "reply": 325458, + "favorite": 3047850, + "coin": 4800461, + "share": 1494973, + "now_rank": 0, + "his_rank": 3, + "like": 5445710, + "dislike": 0, + "vt": 0, + "vv": 123739584, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "不管今年春晚有没有本山叔,鬼畜区总归是有的!", + "cid": 31621681, + "dimension": { + "width": 640, + "height": 360, + "rotate": 0 + }, + "season_id": 879555, + "short_link_v2": "https://b23.tv/BV1bW411n7fY", + "cover43": "", + "tidv2": 2059, + "tnamev2": "鬼畜调教", + "pid_v2": 1007, + "pid_name_v2": "鬼畜", + "bvid": "BV1bW411n7fY", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 19390801, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 305593327, + "videos": 1, + "tid": 255, + "tname": "颜值·网红舞", + "copyright": 1, + "pic": "http://i2.hdslb.com/bfs/archive/b4917bb0a9147f205e6af9d87d6d50b864a7a97f.jpg", + "title": "蝴蝶步2.0(◦˙▽˙◦)", + "pubdate": 1669474753, + "ctime": 1669474753, + "desc": "-", + "state": 0, + "duration": 15, + "mission_id": 1039224, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 43724742, + "name": "怎么这样的呐", + "face": "https://i0.hdslb.com/bfs/face/f9e9ae6025a9e02b134eec3dd84b87c3689216a3.jpg" + }, + "stat": { + "aid": 305593327, + "view": 13909975, + "danmaku": 1401, + "reply": 7111, + "favorite": 235000, + "coin": 83120, + "share": 24633, + "now_rank": 0, + "his_rank": 0, + "like": 383239, + "dislike": 0, + "vt": 0, + "vv": 13909975, + "fav_g": 14, + "like_g": 0 + }, + "dynamic": "双更一下~", + "cid": 904012490, + "dimension": { + "width": 1456, + "height": 2592, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1kP411u7jr", + "up_from_v2": 19, + "first_frame": "http://i2.hdslb.com/bfs/storyff/n221126qn2i92o9zf8m22h34kykxw0dl_firsti.jpg", + "pub_location": "浙江", + "cover43": "", + "tidv2": 2030, + "tnamev2": "颜值·网红舞", + "pid_v2": 1004, + "pid_name_v2": "舞蹈", + "bvid": "BV1kP411u7jr", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 305593327, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + }, + { + "aid": 114075187020133, + "videos": 1, + "tid": 256, + "tname": "短片", + "copyright": 1, + "pic": "http://i1.hdslb.com/bfs/archive/3d3aaf0ab2da5e41f4de7ed3e7995babbfd1168a.jpg", + "title": "中国人自己的保加利亚妖王", + "pubdate": 1740649401, + "ctime": 1740649401, + "desc": "-", + "state": 0, + "duration": 53, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0, + "arc_pay": 0, + "pay_free_watch": 0 + }, + "owner": { + "mid": 1247190580, + "name": "麦克瑟瑟大型纪录片", + "face": "https://i1.hdslb.com/bfs/face/98df710e5e76e7fe37c0d5fd8047b899b21943d5.jpg" + }, + "stat": { + "aid": 114075187020133, + "view": 9167, + "danmaku": 1, + "reply": 12, + "favorite": 24, + "coin": 2, + "share": 9, + "now_rank": 0, + "his_rank": 0, + "like": 166, + "dislike": 0, + "vt": 0, + "vv": 9167, + "fav_g": 0, + "like_g": 0 + }, + "dynamic": "", + "cid": 28602729880, + "dimension": { + "width": 1440, + "height": 1080, + "rotate": 0 + }, + "short_link_v2": "https://b23.tv/BV1Xg9cYYEDZ", + "up_from_v2": 19, + "first_frame": "http://i0.hdslb.com/bfs/storyff/n250227sao3m0apa1gc9g2yxt3vx2l53_firsti.jpg", + "pub_location": "河南", + "cover43": "", + "tidv2": 2026, + "tnamev2": "乐评盘点", + "pid_v2": 1003, + "pid_name_v2": "音乐", + "bvid": "BV1Xg9cYYEDZ", + "season_type": 0, + "is_ogv": false, + "ogv_info": null, + "rcmd_reason": "", + "enable_vt": 0, + "ai_rcmd": { + "id": 114075187020133, + "goto": "av", + "trackid": "web_related_0.router-related-2004712-fdb74c5f6-v6rmv.1744730526909.62", + "uniq_id": "" + } + } + ], + "Spec": null, + "hot_share": { + "show": false, + "list": [] + }, + "elec": null, + "emergency": { + "no_like": false, + "no_coin": false, + "no_fav": false, + "no_share": false + }, + "view_addit": { + "63": false, + "64": false, + "69": false, + "71": false, + "72": false + }, + "guide": null, + "query_tags": null, + "participle": [ + "保加利亚", + "azis", + "mv" + ], + "module_ctrl": null, + "replace_recommend": false + } +} +``` + +
+ +## 获取视频简介 + +> https://api.bilibili.com/x/web-interface/archive/desc + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|------|-----|--------|--------|---------------| +| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 | +| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|--------------------------------------| +| code | num | 返回值 | 0:成功
-400:请求错误
62002:稿件不可见 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | str | 简介内容 | | + +**示例:** + +查看视频(教主的咕鸽)`av39330059`/`BV1Bt411z799`的简介 + +avid方式: + +```shell +curl -G 'https://api.bilibili.com/x/archive/desc' \ +--data-urlencode 'aid=39330059' +``` + +bvid方式: + +```shell +curl -G 'https://api.bilibili.com/x/archive/desc' \ +--data-urlencode 'bvid=BV1Bt411z799' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": "1.小朋友们大家好,我是你们爷爷最喜欢的超威一列姆!\r\n2.在过去的一年里,我创作了无数脍炙人口的歌曲,常常被人夸赞高产似雌豚。\r\n3.接下来的日子里我会一如既往地勤勉创作,争取继续保持现在的产量,文体两开花。\r\n4.我感觉照这个势头和速度下去别说日常更新不在话下,连出张新专辑都指日可待了啊。\r\n5.也感谢你们一如既往的支持和鼓励,我会注意身体,不把自己累垮掉的。\r\n6.我个人不建议你们在评论区里艾特任何UP主,我真的不建议,当然你们非要这么做我也没办法的。" +} +``` + +
+ +## 查询视频分P列表 (avid/bvid转cid) + +> https://api.bilibili.com/x/player/pagelist + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|------|-----|--------|--------|---------------| +| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 | +| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-------|------|-----------------------------------| +| code | num | 返回值 | 0:成功
-400:请求错误
-404:无视频 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | array | 分P列表 | | + +数组`data`: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|----------|---------| +| 0 | obj | 1P内容 | 无分P仅有此项 | +| n | obj | (n+1)P内容 | | +| …… | obj | …… | …… | + +数组`data`中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------|-----|-----------|---------------------------------------------| +| cid | num | 当前分P cid | | +| page | num | 当前分P | | +| from | str | 视频来源 | vupload:普通上传(B站)
hunan:芒果TV
qq:腾讯 | +| part | str | 当前分P标题 | | +| duration | num | 当前分P持续时间 | 单位为秒 | +| vid | str | 站外视频vid | | +| weblink | str | 站外视频跳转url | | +| dimension | obj | 当前分P分辨率 | 有部分视频无法获取分辨率 | +| first_frame | str | 分P封面 | | + +数组`data`中的对象中的`dimension`对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------|-----|---------|----------------| +| width | num | 当前分P 宽度 | | +| height | num | 当前分P 高度 | | +| rotate | num | 是否将宽高对换 | 0:正常
1:对换 | + +**示例:** + +查询视频`av13502509`/`BV1ex411J7GE`的分P列表 + +avid方式: + +```shell +curl -G 'https://api.bilibili.com/x/player/pagelist' \ +--data-urlencode 'aid=13502509' +``` + +bvid方式: + +```shell +curl -G 'https://api.bilibili.com/x/player/pagelist' \ +--data-urlencode 'bvid=BV1ex411J7GE' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [{ + "cid": 66445301, + "page": 1, + "from": "vupload", + "part": "00. 宣传短片", + "duration": 33, + "vid": "", + "weblink": "", + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + } + }, { + "cid": 35039663, + "page": 2, + "from": "vupload", + "part": "01. 火柴人与动画师", + "duration": 133, + "vid": "", + "weblink": "", + "dimension": { + "width": 1484, + "height": 1080, + "rotate": 0 + } + }, { + "cid": 35039678, + "page": 3, + "from": "vupload", + "part": "02. 火柴人与动画师 II", + "duration": 210, + "vid": "", + "weblink": "", + "dimension": { + "width": 1484, + "height": 1080, + "rotate": 0 + } + }, { + "cid": 35039693, + "page": 4, + "from": "vupload", + "part": "03. 火柴人与动画师 III", + "duration": 503, + "vid": "", + "weblink": "", + "dimension": { + "width": 992, + "height": 720, + "rotate": 0 + } + }] +} +``` + +
diff --git a/bb-api-collect/docs/video/interact_video.md b/bb-api-collect/docs/video/interact_video.md new file mode 100644 index 0000000000..c87892d44f --- /dev/null +++ b/bb-api-collect/docs/video/interact_video.md @@ -0,0 +1,369 @@ +# 互动视频信息 + +注:互动视频分P与普通视频分P不互通 + +## 获取互动视频模块详细信息 + +> https://api.bilibili.com/x/stein/edgeinfo_v2 + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------- | ---- | -------- | ------------ | ------------------ | +| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 | +| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 | +| graph_version | num | 剧情图id | 必要 | 可于[播放器](/docs/video/player.md)接口的 `interaction` 對象取得 | +| edge_id | num | 模块编号 | 非必要 | 0或留空为起始模块 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-400:请求错误
-404:无视频
99003:剧情图被修改已失效
99077:请输入aid/bvid | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ----- | ------------------- | ------------------------------------------------ | +| title | str | 视频模块(分P)标题 | | +| edge_id | num | 当前模块id | | +| story_list | array | 进度回溯信息 | 未登录仅有起始模块 | +| edges | obj | 当前模块信息 | | +| preload | obj | 预加载的分P | | +| hidden_vars | array | 变量列表 | 无变量时不存在此项 | +| is_leaf | num | 是否为结束模块 | 0:当前模块为普通模块
1:当前模块为结束模块 | +| no_tutorial | num | 禁止记录选择 | 1:禁止
非禁止时无此项 | +| no_backtracking | num | 禁止进度回溯 | 1:禁止
非禁止时无此项 | +| no_evaluation | num | 禁止结尾评分 | 1:禁止
非禁止时无此项 | + +`data`中的`story_list`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------------- | ---- | +| 0 | obj | 回溯第一项模块 | | +| n | obj | 回溯第(n+1)项模块 | | +| …… | obj | …… | …… | + +`story_list`数组中的对象: + +| 项 | 类型 | 内容 | 备注 | +| ---------- | ---- | ---------------- | ----------------------------- | +| node_id | num | 模块编号 | | +| edge_id | num | **同上** | | +| title | str | 模块(分P)标题 | | +| cid | num | 模块(分P)cid | | +| start_pos | num | 记录播放开始位置 | 单位为毫秒 | +| cover | str | 分P封面url | | +| is_current | num | 是否为当前模块 | 1:是
仅为当前模块时存在 | +| cursor | num | 进度序号 | 从0开始向上增长 | + +`data`中的`edges`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | ------------- | ------------------------ | +| dimension | obj | 当前分P分辨率 | 有部分视频无法获取分辨率 | +| questions | array | 问题 | 结束模块无此项 | +| skin | obj | 问题外观 | | + +`edges`中的`dimension`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | -------------- | -------------------- | +| width | num | 当前分P 宽度 | | +| height | num | 当前分P 高度 | | +| rotate | num | 是否将宽高对换 | 0:正常
1:对换 | +| sar | str | ??? | 作用尚不明确 | + +`edges`中的`questions`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| 0 | obj | 套了个娃 | | + +`edges`中的`questions`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ----- | ---------------- | ------------------------------------------------------------ | +| id | num | ??? | 作用尚不明确 | +| type | num | 选项显示模式 | 0:不显示选项
1:底部选项模式
2:坐标定点模式
3:???
127:??? | +| start_time_r | num | 300 或 duration | 作用尚不明确 | +| duration | num | 回答限时 | 单位为毫秒
不限时为`-1` | +| pause_video | num | 是否暂停播放视频 | 0:不暂停
1:暂停播放 | +| title | str | 空 | 作用尚不明确 | +| choices | array | 选项列表 | | +| fade_in_time | num | 选项淡入时间 | 毫秒 | +| fade_out_time | num | 选项淡出时间 | 毫秒 | + +`questions`数组中的对象中的`choices`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------- | ---- | +| 0 | obj | 第一选项 | | +| n | obj | 第(n+1)选项 | | +| …… | obj | …… | …… | + +`questions`数组中的对象中的`choices`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ---- | -------------------- | ------------------------------------- | +| id | num | 选项所跳转的模块id | | +| platform_action | str | 跳转信息文字 | JUMP+{所跳转的模块编号}+{所跳转的cid} | +| native_action | str | 点击后对变量运算语句 | 每项间用分号隔开
无为空 | +| condition | str | 选项出现条件判断语句 | 无为空 | +| cid | num | 选项所跳转分P的cid | | +| x | num | 选项出现的x坐标 | 仅坐标模式有此项 | +| y | num | 选项出现的y坐标 | 仅坐标模式有此项 | +| text_align | num | 选项文本对齐方式 | | +| option | str | 选项文字 | | +| selected | obj | 选择动画信息 | | +| submited | obj | 提交动画信息 | | +| is_default | num | 是否为默认选项 | 1:是
非默认选项无此项 | +| is_hidden | num | 是否为隐藏选项 | 1:是
非隐藏选项无此项 | + +`edges`中的`skin`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------------ | ---- | ------------------- | ---------------- | +| choice_image | str | 选项组件外观图片url | | +| title_text_color | str | 文字颜色 | 以下均为RGBA格式 | +| title_shadow_color | str | 文字阴影颜色 | | +| title_shadow_offset_x | num | 文字阴影x偏移 | | +| title_shadow_offset_y | num | 文字阴影y偏移 | | +| title_shadow_radius | num | 文字阴影半径 | | +| progressbar_color | str | 倒计时条颜色 | | +| progressbar_shadow_color | str | 倒计时条阴影颜色 | | + +`data`中的`preload`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ----- | ----------- | ---- | +| video | array | 预加载的分P | | + +`preload`中的`video`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ------------------------------------ | +| 0 | obj | 预加载第一项 | 预加载的内容为当前所有选项的跳转视频 | +| n | obj | 预加载第(n+1)项 | | +| …… | obj | …… | …… | + +`preload`中的`video`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | -------- | ---- | +| aid | num | 稿件avid | | +| cid | num | 分P cid | | + +`data`中的`hidden_vars`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---- | +| 0 | obj | 第一个变量 | | +| n | obj | 第(n+1)个变量 | | +| …… | obj | …… | …… | + +`data`中的`hidden_vars`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | ------------ | -------------------------- | +| value | num | 变量值 | 随机值为随机整数 | +| id | str | 变量编号 | | +| id_v2 | str | 变量编号 | 语句中一般使用这种 | +| type | num | 变量类型 | 1:普通变量
2:随机值 | +| is_show | num | 是否展示变量 | 0:否
1:是 | +| name | str | 变量名 | | +| skip_overwrite | num | 0 | 作用尚不明确 | + +**示例:** + +查询互动视频`av73267982`下剧情图`155446`模块`5556092`的信息 + +avid方式: + +```shell +curl -G 'https://api.bilibili.com/x/stein/edgeinfo_v2' \ +--data-urlencode 'aid=73267982' \ +--data-urlencode 'graph_version=155446' \ +--data-urlencode 'edge_id=5556092' \ +-b 'SESSDATA=xxx' +``` + +bvid方式: + +```shell +curl -G 'https://api.bilibili.com/x/stein/edgeinfo_v2' \ +--data-urlencode 'bvid=BV1UE411y7Wy' \ +--data-urlencode 'graph_version=155446' \ +--data-urlencode 'edge_id=5556092' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "title": "4", + "edge_id": 5556092, + "story_list": [ + { + "node_id": 1, + "edge_id": 1, + "title": "0 片头", + "cid": 127486603, + "start_pos": 27000, + "cover": "http://i0.hdslb.com/bfs/steins-gate/127486603_screenshot.jpg", + "cursor": 0 + }, + { + "node_id": 5556092, + "edge_id": 5556092, + "title": "4", + "cid": 125499378, + "start_pos": 82000, + "cover": "http://i0.hdslb.com/bfs/steins-gate/125499378_screenshot.jpg", + "is_current": 1, + "cursor": 15 + } + ], + "edges": { + "dimension": { + "width": 1920, + "height": 1000, + "rotate": 0, + "sar": "" + }, + "questions": [ + { + "id": 0, + "type": 2, + "start_time_r": 300, + "duration": -1, + "pause_video": 1, + "title": "", + "choices": [ + { + "id": 5556133, + "platform_action": "JUMP 5556133 125499249", + "native_action": "", + "condition": "$H7g_64_PG2EVS>=1.00 && $H7g_64_PG2EVS<=80.00", + "cid": 125499249, + "x": 947, + "y": 499, + "text_align": 2, + "option": "A <你已成为杀手> 试图砍死萌新 (成功率20%)", + "is_default": 1 + }, + { + "id": 5556134, + "platform_action": "JUMP 5556134 125502707", + "native_action": "", + "condition": "$H7g_64_PG2EVS>=81.00 && $H7g_64_PG2EVS<=100.00", + "cid": 125502707, + "x": 949, + "y": 502, + "text_align": 2, + "option": "B <你已成为杀手> 试图砍死萌新 (成功率20%)" + }, + { + "id": 5556135, + "platform_action": "JUMP 5556135 125499249", + "native_action": "", + "condition": "", + "cid": 125499249, + "x": 120, + "y": 145, + "text_align": 2, + "option": "C 直接【砍杀失败】" + } + ] + } + ], + "skin": { + "choice_image": "https://i0.hdslb.com/bfs/app/db0ae7700d4fb1416c8b305bcfb6f0948f818cc9.png", + "title_text_color": "d8fbffff", + "title_shadow_color": "00000033", + "title_shadow_offset_y": 1, + "title_shadow_radius": 1, + "progressbar_color": "ffffffff", + "progressbar_shadow_color": "000000cc" + } + }, + "preload": { + "video": [ + { + "aid": 73267982, + "cid": 125499249 + }, + { + "aid": 73267982, + "cid": 125502707 + } + ] + }, + "hidden_vars": [ + { + "value": 97, + "id": "v-H7g@PG2EVS", + "id_v2": "$H7g_64_PG2EVS", + "type": 2, + "is_show": 0, + "name": "随机值", + "skip_overwrite": 0 + }, + { + "value": 0, + "id": "v-YWB6dk1oCP", + "id_v2": "$YWB6dk1oCP", + "type": 1, + "is_show": 1, + "name": "达成假结局次数", + "skip_overwrite": 0 + }, + { + "value": 0, + "id": "v-Zh4JACIiId", + "id_v2": "$Zh4JACIiId", + "type": 1, + "is_show": 1, + "name": "死亡次数", + "skip_overwrite": 0 + }, + { + "value": 0, + "id": "v-a2vplaQlsP", + "id_v2": "$a2vplaQlsP", + "type": 1, + "is_show": 1, + "name": "达成真结局次数", + "skip_overwrite": 0 + }, + { + "value": 1, + "id": "v-lMQqQ994Sk", + "id_v2": "$lMQqQ994Sk", + "type": 1, + "is_show": 1, + "name": "循环编号", + "skip_overwrite": 0 + } + ], + "is_leaf": 0 + } +} +``` + +
diff --git a/bb-api-collect/docs/video/online.md b/bb-api-collect/docs/video/online.md new file mode 100644 index 0000000000..4b80f0e6c5 --- /dev/null +++ b/bb-api-collect/docs/video/online.md @@ -0,0 +1,143 @@ +# 视频在线人数 + +## 获取视频在线人数_web端 + +> https://api.bilibili.com/x/player/online/total + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ---------- | ------------------ | +| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 | +| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 | +| cid | num | 视频cid | 必要 | 用于选择目标分P | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
-404:无视频 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----------- | ---- | ----------------- | ----------- | +| total | str | 所有终端总计人数 | 例如`10万+` | +| count | str | web端实时在线人数 | | +| show_switch | obj | 数据显示控制 | | + +`data`中的`show_switch`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | --------------------- | ---- | +| total | bool | 展示所有终端总计人数 | | +| count | bool | 展示web端实时在线人数 | | + +**示例:** + +查询视频`av759949922`/`BV1y64y1q757`中1P(`392402545`)的在线人数 + +```shell +curl -G 'https://api.bilibili.com/x/player/online/total' \ +--data-urlencode 'aid=759949922' \ +--data-urlencode 'cid=392402545' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "total": "9.4万+", + "count": "50953", + "show_switch": { + "total": true, + "count": true + } + } +} +``` + +
+ +## 获取视频在线人数_APP端 + +> https://app.bilibili.com/x/v2/view/video/online + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---------- | ----------- | --------------- | +| aid | num | 稿件avid | 必要 | | +| appkey | str | APP密钥 | APP方式必要 | | +| cid | num | 视频cid | 必要 | 用于选择目标分P | +| ts | num | 当前时间戳 | APP方式必要 | | +| sign | str | APP签名 | APP方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
-404:无视频 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ---------------- | ---- | +| online | obj | 所有终端总计人数 | | + +`data`中的`show_switch`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------ | ---- | ---------------- | ----------------- | +| online | str | 所有终端总计人数 | 例如`10万+人在看` | + +**示例:** + +查询视频`av759949922`/`BV1y64y1q757`中1P(`392402545`)的在线人数 + +```shell +curl -G 'https://app.bilibili.com/x/v2/view/video/online' \ +--data-urlencode 'aid=759949922' \ +--data-urlencode 'appkey=1d8b6e7d45233436' \ +--data-urlencode 'cid=392402545' \ +--data-urlencode 'ts=0' \ +--data-urlencode 'sign=172dfd9941a01275eb93ce6246cd8556' +``` + +
+查看响应示例: + + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "online": { + "total_text": "8.8万+人在看" + } + } +} +``` + +
\ No newline at end of file diff --git a/bb-api-collect/docs/video/pbp.md b/bb-api-collect/docs/video/pbp.md new file mode 100644 index 0000000000..9ce5824474 --- /dev/null +++ b/bb-api-collect/docs/video/pbp.md @@ -0,0 +1,69 @@ +# 高能进度条 + +高能进度条反应了在时域上,单位时间内弹幕发送量的变化趋势 + +并用曲线顶点表示在进度条上,实现可视化 + +## 获取弹幕趋势顶点列表 + +> https://bvc.bilivideo.com/pbp/data + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| cid | num | 视频cid | 必要 | | +| aid | num | 稿件avid | 非必要 | | +| bvid | num | 稿件bvid | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ------------ | ---------------------------- | +| step_sec | num | 采样间隔时间 | 单位为秒
由视频时长决定 | +| tagstr | str | ??? | 作用尚不明确 | +| events | obj | 数据本体 | | +| debug | str | 调试信息 | json字串 | + +`events`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ------ | ---------- | ---- | +| default | array | 顶点值列表 | | + +`events`对象中的数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------- | -------------------------------- | +| 0 | num | 顶点1 | | +| n | num | 顶点(n+1) | 顶点个数由视频时长和采样时间决定 | +| …… | num | …… | …… | + +**示例:** + +获取视频`cid=3724723`的获取弹幕趋势顶点列表 + +```shell +curl -G 'https://api.bilibili.com/pbp/data' \ +--data-urlencode 'cid=3724723' +``` + +
+查看响应示例: + +```json +{ + "step_sec": 3, + "tagstr": "pbphide_0&client_&innersign_0&group_eg&nocheck_0&version_&pbphide_0", + "events": { + "default": [0, 8853, 8011, 8043.5, 8602.5, 9377, 18838, 9645, 10396, 10672.5, 10316.5, 9987, 9524, 9040, 9081, 8747, 8517, 8559.5, 8220.5, 8133, 7164, 5626, 4992, 4628.5, 4570.5, 4473.5, 4681.5, 4365.5, 3811.5, 3813, 3883, 4059.5, 4103.5, 4227.5, 4330.5, 4096.5, 4228.5, 4337, 5017, 5897, 6220, 5711.5, 4871.5, 4533, 4364, 3976, 4012, 3985, 3658, 3540, 3789, 3646, 3045, 2769, 2587, 2488.5, 2402.5, 2521.5, 2508.5, 2763.5, 2941.5, 3685.5, 3337.5, 2457, 2313, 2322.5, 2480.5, 2595, 2520, 2173.5, 2058.5, 2268.5, 2312.5, 2847, 1083, 1.5, 2.5, 0, 0, 2] + }, + "debug": "{\"max_time\":237,\"zero_points_ratio\":0.025,\"total_dm\":1000,\"event_count\":400147}" +} +``` + +
diff --git a/bb-api-collect/docs/video/player.md b/bb-api-collect/docs/video/player.md new file mode 100644 index 0000000000..66bce57ab9 --- /dev/null +++ b/bb-api-collect/docs/video/player.md @@ -0,0 +1,520 @@ +# 播放器 + +## web 播放器信息 + +web 播放器的信息接口,提供正常播放需要的元数据,包括:智能防挡弹幕、字幕、章节看点等。 + +> https://api.bilibili.com/x/player/wbi/v2 +> https://api.bilibili.com/x/player/v2 + +*请求方式:GET* + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | --------- | ----------- | ----------------- | +| aid | num | 稿件 avid | 必要 (可选) | aid 与 bvid 任选 | +| bvid | str | 稿件 bvid | 必要 (可选) | aid 与 bvid 任选 | +| cid | num | 稿件 cid | 必要 | | +| season_id | num | 番剧 season_id | 不必要 | | +| ep_id | num | 剧集 ep_id | 不必要 | | +| w_rid | str | WBI 签名 | 不必要 | | +| wts | num | 当前 unix 时间戳 | 不必要 | | + +**JSON回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0: 成功
-400: 请求错误 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | -------- | ---- | +| aid | num | 视频 aid | | +| bvid | str | 视频 bvid | | +| allow_bp | bool | | | +| no_share | bool | 禁止分享? | | +| cid | num | 视频 cid | | +| dm_mask | obj | webmask 防挡字幕信息 | 若无则没有防挡功能 | +| subtitle | obj | 字幕信息 | 若无则没有字幕, 若不登陆则为空 | +| view_points | array | 分段章节信息 | | +| ip_info | obj | 请求 IP 信息 | | +| login_mid | num | 登录用户 mid | | +| login_mid_hash | str | | | +| is_owner | bool | 是否为该视频 UP 主 | | +| name | str | | | +| permission | num | | | +| level_info | obj | 登录用户等级信息 | | +| vip | obj | 登录用户 VIP 信息 | | +| answer_status | num | 答题状态 | | +| block_time | num | 封禁时间? | | +| role | str | | | +| last_play_time | num | 上次观看时间? | | +| last_play_cid | num | 上次观看 cid? | | +| now_time | num | 当前 UNIX 秒级时间戳 | | +| online_count | num | 在线人数 | | +| need_login_subtitle | bool | 是否必须登陆才能查看字幕 | 是的 | +| preview_toast | str | `为创作付费,购买观看完整视频\|购买观看` | | +| interaction | obj | 互动视频资讯 | 若非互动视频,则无该栏位(直接没有该键,而非栏位值为空)| +| options | obj | | | +| guide_attention | any | | | +| jump_card | any | | | +| operation_card | any | | | +| online_switch | obj | | | +| fawkes | obj | 播放器相关信息? | | +| show_switch | obj | | | +| bgm_info | obj | 背景音乐信息 | | +| toast_block | bool | | | +| is_upower_exclusive | bool | 是否为充电专属视频 | | +| is_upower_play | bool | | | +| is_ugc_pay_preview | bool | | | +| elec_high_level | obj | 充电专属视频信息 | | +| disable_show_up_info | bool | | | + +`data` 对象中的 `options` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---- | ---- | --- | --- | +| is_360 | bool | 是否 360 全景视频 | | +| without_vip | bool | | | + +`data` 对象中的 `bgm_info` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --- | --- | --- | --- | +| music_id | str | 音乐 id | | +| music_title | str | 音乐标题 | | +| jump_url | str | 跳转 URL | | + +`data` 对象中的 `dm_mask` 对象 (如果有): + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | -------- | ---- | +|cid | num | 视频 cid | | +|plat | num | 未知 | | +|fps | num | webmask 取样 fps | | +|time | num | 未知 | | +|mask_url | str | webmask 资源 url | | + +解析 webmask 请看 [智能防挡弹幕](../danmaku/webmask.md) + +`data` 对象中的 `subtitle` 对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | -------- | ---- | +|allow_submit|bool | true | | +| lan | str | "" | | +|lan_doc | str | "" | | +|subtitles| array | | 不登录为 `[]` | + +`subtitle` 对象中的 `subtitles` 数组内的元素: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | -------- | ---- | +| ai_status | num | | | +| ai_type | num | | | +| id | num | | | +|id_str | str| | 和 id 不一样 | +| is_lock | bool | | | +| lan | str | 语言类型英文字母缩写 || +| lan_doc | str| 语言类型中文名称 | | +|subtitle_url|str| 资源 url 地址 | | +|type| num | 0 | | + +`data`对象中的`view_point` 数组内的元素: + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | -------- | ---- | +| content | str | 分段章节名 | | +| from | num | 分段章节起始秒数 | | +| to | num | 分段章节结束秒数 | | +| type | num | | | +| imgUrl | str | 图片资源地址 | | +| logoUrl | str | "" | | +| team_type | str | | | +| team_name | str | | | + +`data` 对象中的 `interaction` 对象 (如果有): + +| 字段 | 类型 | 内容 | 备注 | +| --------- | ----- | -------- | ---- | +| graph_version | num | 剧情图id | | +| msg | str | | 未登入有机会返回 `登录后才能体验全部结局哦~` | +| error_toast | str | 错误信息? | 所有互动视频皆返回 `剧情图被修改已失效`,不确定有没有例外 | +| mark | num | 0? | | +| need_reload | num | 0? | | + +`data`对象中的`elec_high_level`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | ------------------------------ | ---------------- | +| privilege_type | num | 解锁视频所需最低定价档位的代码 | 见[充电档位代码与定价](../electric/monthly.md#充电档位代码privilege_type与定价) | +| title | str | 提示标题 | `该视频为「{充电档位名称}」专属视频` | +| sub_title | str | 提示子标题 | `开通「{充电档位定价}元档包月充电」即可观看` | +| show_button | bool | 是否显示按钮 | | +| button_text | str | 按钮文本 | `去开通` | +| jump_url | obj | 跳转url信息 | 详细信息有待补充 | +| intro | str | 充电介绍语 | | +| open | bool | (?) | | +| new | bool | (?) | | +| question_text | str | (?) | | +| qa_detail_link | str | (?) | | + +**示例:** + +未登录, `aid=1906473802` + +```shell +curl -G 'https://api.bilibili.com/x/player/wbi/v2' \ +--url-query 'bvid=BV1MU411S7iJ' \ +--url-query 'aid=1906473802' \ +--url-query 'cid=1625992822' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "aid": 1906473802, + "bvid": "BV1MU411S7iJ", + "allow_bp": false, + "no_share": false, + "cid": 1625992822, + "max_limit": 1000, + "page_no": 1, + "has_next": false, + "ip_info": { + "ip": "104.28.152.138", + "zone_ip": " 10.163.150.25", + "zone_id": 29409280, + "country": "美国", + "province": "加利福尼亚州", + "city": "东洛杉矶" + }, + "login_mid": 0, + "login_mid_hash": "", + "is_owner": false, + "name": "", + "permission": "0", + "level_info": { + "current_level": 0, + "current_min": 0, + "current_exp": 0, + "next_exp": 0, + "level_up": 0 + }, + "vip": { + "type": 0, + "status": 0, + "due_date": 0, + "vip_pay_type": 0, + "theme_type": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "border_color": "", + "use_img_label": false, + "img_label_uri_hans": "", + "img_label_uri_hant": "", + "img_label_uri_hans_static": "", + "img_label_uri_hant_static": "" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "", + "tv_vip_status": 0, + "tv_vip_pay_type": 0, + "tv_due_date": 0, + "avatar_icon": { + "icon_resource": {} + } + }, + "answer_status": 0, + "block_time": 0, + "role": "", + "last_play_time": 0, + "last_play_cid": 0, + "now_time": 1725002188, + "online_count": 1, + "need_login_subtitle": false, + "view_points": [], + "preview_toast": "为创作付费,购买观看完整视频|购买观看", + "options": { + "is_360": false, + "without_vip": false + }, + "guide_attention": [], + "jump_card": [], + "operation_card": [], + "online_switch": { + "enable_gray_dash_playback": "500", + "new_broadcast": "1", + "realtime_dm": "1", + "subtitle_submit_switch": "1" + }, + "fawkes": { + "config_version": 30787, + "ff_version": 21289 + }, + "show_switch": { + "long_progress": false + }, + "bgm_info": { + "music_id": "MA436038343856245020", + "music_title": "Unwelcome school", + "jump_url": "https://music.bilibili.com/h5/music-detail?music_id=MA436038343856245020&cid=1625992822&aid=1906473802" + }, + "toast_block": false, + "is_upower_exclusive": false, + "is_upower_play": false, + "is_ugc_pay_preview": false, + "elec_high_level": { + "privilege_type": 0, + "title": "", + "sub_title": "", + "show_button": false, + "button_text": "", + "jump_url": "", + "intro": "", + "new": false + }, + "disable_show_up_info": false + } +} +``` + +
+ +已登陆, `aid=60977932` + +```shell +curl -G 'https://api.bilibili.com/x/player/v2' \ +--url-query 'aid=60977932' \ +--url-query 'cid=106101299' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "aid": 60977932, + "bvid": "BV1Jt411P77c", + "allow_bp": false, + "no_share": false, + "cid": 106101299, + "max_limit": 1000, + "page_no": 1, + "has_next": true, + "ip_info": { + "ip": "108.181.22.55", + "zone_ip": " 172.27.132.5", + "zone_id": 29409296, + "country": "美国", + "province": "加利福尼亚州", + "city": "洛杉矶" + }, + "login_mid": 616368979, + "login_mid_hash": "445e7035", + "is_owner": false, + "name": "淡紫玲儿", + "permission": "10000,1001", + "level_info": { + "current_level": 3, + "current_min": 1500, + "current_exp": 2962, + "next_exp": 4500, + "level_up": -62135596800 + }, + "vip": { + "type": 1, + "status": 0, + "due_date": 1665417600000, + "vip_pay_type": 0, + "theme_type": 0, + "label": { + "path": "", + "text": "", + "label_theme": "", + "text_color": "", + "bg_style": 0, + "bg_color": "", + "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/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", + "img_label_uri_hant_static": "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png" + }, + "avatar_subscript": 0, + "nickname_color": "", + "role": 0, + "avatar_subscript_url": "", + "tv_vip_status": 0, + "tv_vip_pay_type": 0, + "tv_due_date": 0, + "avatar_icon": { + "icon_resource": {} + } + }, + "answer_status": 0, + "block_time": 0, + "role": "0", + "last_play_time": 0, + "last_play_cid": 0, + "now_time": 1725003260, + "online_count": 1, + "need_login_subtitle": false, + "subtitle": { + "allow_submit": true, + "lan": "zh-CN", + "lan_doc": "中文(中国)", + "subtitles": [ + { + "id": 13643112644608002, + "lan": "zh-Hans", + "lan_doc": "中文(简体)", + "is_lock": true, + "subtitle_url": "//aisubtitle.hdslb.com/bfs/subtitle/c49b18a284739d99df1e3723cdf72c0c82db98e0.json?auth_key=1725003260-5d0391a07f4f47f6960f60cf5045dff3-0-fc16c1f67a6b41edcb2a89d5e0c9bfdd", + "type": 0, + "id_str": "13643112644608002", + "ai_type": 0, + "ai_status": 0 + }, + { + "id": 13643200114196484, + "lan": "en-US", + "lan_doc": "英语(美国)", + "is_lock": true, + "subtitle_url": "//aisubtitle.hdslb.com/bfs/subtitle/2b38bc0f5d7671176964d4c3de441ed37568500c.json?auth_key=1725003260-5f709a74aa884751b77f86b6f6a48078-0-9b2fc3c18b99b1bf0cc7c7e63d18f686", + "type": 0, + "id_str": "13643200114196484", + "ai_type": 0, + "ai_status": 0 + } + ] + }, + "view_points": [], + "preview_toast": "为创作付费,购买观看完整视频|购买观看", + "options": { + "is_360": false, + "without_vip": false + }, + "guide_attention": [], + "jump_card": [], + "operation_card": [], + "online_switch": { + "enable_gray_dash_playback": "500", + "new_broadcast": "1", + "realtime_dm": "1", + "subtitle_submit_switch": "1" + }, + "fawkes": { + "config_version": 30787, + "ff_version": 21289 + }, + "show_switch": { + "long_progress": false + }, + "bgm_info": null, + "toast_block": false, + "is_upower_exclusive": false, + "is_upower_play": false, + "is_ugc_pay_preview": false, + "elec_high_level": { + "privilege_type": 0, + "title": "", + "sub_title": "", + "show_button": false, + "button_text": "", + "jump_url": "", + "intro": "", + "new": false + }, + "disable_show_up_info": false + } +} +``` + +
+ +## 播放反馈 + +> https://app.bilibili.com/x/resource/laser2 + +*请求方式: POST* + +注: 该接口不传 Cookie + +**URL参数:** + +|参数名|类型|内容|必要性|备注| +|-|-|-|-|-| +|mid|num|当前用户 mid|不必要|未登录为空| +|buvid|str|BUVID (APP) 或 buvid3 (Web)|必要|可为任意非空字符串| +|app_key|str|APP 密钥|必要|Web: web_player
可为任意非空字符串| +|url|str|日志 URL|非必要|从 [上传接口](../creativecenter/upload.md#上传接口) 得到的 upos 协议 URL| +|task_type|num|任务类型|非必要|300: 播放卡顿
301: 进度条君无法调戏
354: 校园网无法访问
303: 弹幕无法显示
553: 跳过首尾时间有误
304: 出现浮窗广告
305: 无限小电视
302: 音画不同步
306: 黑屏
307: 其他| + +**JSON回复:** + +|字段|类型|内容|备注| +|-|-|-|-| +|code|num|返回值|0: 成功
-400: 请求错误| +|message|str|错误信息|默认为 0| +|ttl|num|1|| +|data|obj|数据本体| | + +`data` 对象: + +|字段|类型|内容|备注| +|-|-|-|-| +|task_id|num|任务 ID?|| + +**示例:** + +播放反馈无限小电视, 不登录, 不传文件, buvid 为 `chenrui-in-icu` + +```shell +curl -X POST "https://app.bilibili.com/x/resource/laser2" \ +--data-urlencode "buvid=chenrui-in-icu" \ +--data-urlencode "app_key=web_player" \ +--data-urlencode "task_type=305" +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "task_id": 850448532 + } +} +``` + +
diff --git a/bb-api-collect/docs/video/recommend.md b/bb-api-collect/docs/video/recommend.md new file mode 100644 index 0000000000..42704c4f0a --- /dev/null +++ b/bb-api-collect/docs/video/recommend.md @@ -0,0 +1,2680 @@ +# 视频推荐 + +## 获取单视频推荐列表(web端) + +> https://api.bilibili.com/x/web-interface/archive/related + +*请求方式:GET* + +最多获取40条推荐视频 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|------|-----|--------|--------|---------------| +| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 | +| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-------|------|----------------------| +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | array | 推荐列表 | | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +|----|-----|-----------|----| +| 0 | obj | 推荐视频1 | | +| n | obj | 推荐视频(n+1) | | +| …… | obj | …… | …… | +| 39 | obj | 推荐视频40 | | + +`data`数组中的对象: + +基本同「[获取视频详细信息(web端)](info.md#获取视频详细信息(web端))」中的data对象,已知没有分P信息 + +**示例:** + +查询视频`av7`/`BV1xx411c7m9`的推荐视频列表 + +avid方式: + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/archive/related' \ +--data-urlencode 'aid=7' +``` + +bvid方式: + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/archive/related' \ +--data-urlencode 'bvid=BV1xx411c7m9' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "aid": 21322566, + "videos": 1, + "tid": 124, + "tname": "趣味科普人文", + "copyright": 1, + "pic": "http://i2.hdslb.com/bfs/archive/37f383ac35d386af1fc578108ad643e5952ff66a.jpg", + "title": "bilibili上市宣传视频", + "pubdate": 1522205992, + "ctime": 1522205994, + "desc": "今天晚上9点30分(北京时间),bilibili将在美国纳斯达克(NASDAQ)证券交易所挂牌上市。", + "state": 0, + "attribute": 16768, + "duration": 155, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 1, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0 + }, + "owner": { + "mid": 208259, + "name": "陈睿", + "face": "http://i2.hdslb.com/bfs/face/8920e6741fc2808cce5b81bc27abdbda291655d3.png" + }, + "stat": { + "aid": 21322566, + "view": 2129084, + "danmaku": 51108, + "reply": 18119, + "favorite": 46524, + "coin": 85223, + "share": 16669, + "now_rank": 0, + "his_rank": 1, + "like": 95621, + "dislike": 0 + }, + "dynamic": "今天晚上9点30分(北京时间),bilibili将在美国纳斯达克(NASDAQ)证券交易所挂牌上市。", + "cid": 35063529, + "dimension": { + "width": 1920, + "height": 1080, + "rotate": 0 + }, + "bvid": "" + }, + { + "aid": 271, + "videos": 1, + "tid": 53, + "tname": "", + "copyright": 1, + "pic": "http://i1.hdslb.com/bfs/archive/a5980672f3d03e8292148748a63de99cd45679d3.jpg", + "title": "弹幕测试专用", + "pubdate": 1249886475, + "ctime": 1497344798, + "desc": "给职人发射弹幕定位用.", + "state": 0, + "attribute": 32768, + "duration": 4558, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0 + }, + "owner": { + "mid": 2, + "name": "碧诗", + "face": "http://i1.hdslb.com/bfs/face/3e60b20604b6fdc7d081eb6a1ec72aa47c5a3964.jpg" + }, + "stat": { + "aid": 271, + "view": 2532266, + "danmaku": 699214, + "reply": 10224, + "favorite": 34927, + "coin": 9712, + "share": 3586, + "now_rank": 0, + "his_rank": 182, + "like": 27257, + "dislike": 0 + }, + "dynamic": "", + "cid": 3659795, + "dimension": { + "width": 0, + "height": 0, + "rotate": 0 + }, + "bvid": "" + }, + { + "aid": 106, + "videos": 1, + "tid": 26, + "tname": "音MAD", + "copyright": 2, + "pic": "http://i2.hdslb.com/bfs/archive/34d8fdf08d1fe28c229dec2fd122815a1d012908.jpg", + "title": "最终鬼畜蓝蓝路", + "pubdate": 1350316631, + "ctime": 1497348932, + "desc": "sm2057168 把这个音mad的图腾和支柱从UP的怒火中搬出来重新立好,这是我所能做的最后的事情了。", + "state": 0, + "attribute": 32768, + "duration": 318, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 0, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0 + }, + "owner": { + "mid": 8839, + "name": "TSA", + "face": "http://i0.hdslb.com/bfs/face/0ef5daf622bf4789034b3c15147a45e11c48c9b3.jpg" + }, + "stat": { + "aid": 106, + "view": 7607070, + "danmaku": 212896, + "reply": 41521, + "favorite": 200705, + "coin": 51673, + "share": 38049, + "now_rank": 0, + "his_rank": 22, + "like": 148550, + "dislike": 0 + }, + "dynamic": "", + "cid": 3635863, + "dimension": { + "width": 0, + "height": 0, + "rotate": 0 + }, + "bvid": "" + }, + { + "aid": 50025934, + "videos": 1, + "tid": 122, + "tname": "野生技术协会", + "copyright": 1, + "pic": "http://i0.hdslb.com/bfs/archive/af534399612085dbd916381b3377b18c765fab2d.png", + "title": "B站又一位Lv9的up诞生了", + "pubdate": 1555829289, + "ctime": 1555829289, + "desc": "要不关注一下?", + "state": 0, + "attribute": 16512, + "duration": 45, + "rights": { + "bp": 0, + "elec": 0, + "download": 0, + "movie": 0, + "pay": 0, + "hd5": 0, + "no_reprint": 1, + "autoplay": 1, + "ugc_pay": 0, + "is_cooperation": 0, + "ugc_pay_preview": 0, + "no_background": 0 + }, + "owner": { + "mid": 174161216, + "name": "血色红茶Xenomprph", + "face": "http://i1.hdslb.com/bfs/face/5a5ececb9b7a688751024c60063ba5853bed7e1e.jpg" + }, + "stat": { + "aid": 50025934, + "view": 159595, + "danmaku": 62, + "reply": 153, + "favorite": 301, + "coin": 1059, + "share": 55, + "now_rank": 0, + "his_rank": 0, + "like": 1219, + "dislike": 0 + }, + "dynamic": "", + "cid": 87577929, + "dimension": { + "width": 2560, + "height": 1440, + "rotate": 0 + }, + "bvid": "" + } + … + … + … + … + ] +} +``` + +
+ +## 获取首页视频推荐列表(web端) + +> https://api.bilibili.com/x/web-interface/wbi/index/top/feed/rcmd + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +最多获取30条推荐视频,直播及推荐边栏 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|---------------|-----|--------------|-----|--------------------------------| +| fresh_type | num | 相关性 | 非必要 | 默认为 4
值越大推荐内容越相关 | +| ps | num | 单页返回的记录条数 | 非必要 | 默认为 12, 留空即最大值为 30 | +| fresh_idx | num | 当前翻页号 | 非必要 | 以 1 开始 | +| fresh_idx_1h | num | 当前翻页号(一小时前?) | 非必要 | 以 1 开始, 默认与 fresh_idx 内容相同 | +| brush | num | 刷子? | 非必要 | 以 1 开始, 默认与 fresh_idx 内容相同 | +| fetch_row | num | 本次抓取的最后一行行号 | 非必要 | 1 递归加上本次抓取总行数 | +| web_location | num | 网页位置 | 非必要 | 主页为 1430650 | +| y_num | num | 普通列数 | 非必要 | 一行中视频,直播及广告数 | +| last_y_num | num | 总列数 | 非必要 | 普通列数 + 边栏列数 | +| feed_version | str | V8 | 非必要 | 作用尚不明确 | +| homepage_ver | num | 1 | 非必要 | 首页版本 | +| screen | str | 浏览器视口大小 | 非必要 | 水平在前垂直在后以减号分割 | +| seo_info | str | 空 | 非必要 | 作用尚不明确 | +| last_showlist | str | 上次抓取的视频av号列表 | 非必要 | av与数字间用下划线分隔, 若视频UP主已关注则中间再插入n | +| uniq_id | str | ??? | 非必要 | 作用尚不明确 | +| w_rid | str | WBI 签名 | 非必要 | 见[WBI 签名](../misc/sign/wbi.md) | +| wts | num | UNIX 时间戳 | 非必要 | 见[WBI 签名](../misc/sign/wbi.md) | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|----------------------| +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------------------------|-------|-------|--------------------| +| business_card | null | | | +| floor_info | null | | | +| item | array | 推荐列表 | | +| mid | num | 用户mid | 未登录为0 | +| preload_expose_pct | num | 0.5 | 用于预加载? | +| preload_floor_expose_pct | num | 0.5 | 用于预加载? | +| side_bar_column | array | 边栏列表? | 可参考字段 item 及对应功能文档 | +| user_feature | null | | | + +`data`对象中`item`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------------|------|---------------|----------------------------------------------| +| av_feature | null | | | +| business_info | obj | 商业推广信息 | 无为null
对于推广内容,视频信息会在这个dict的"archive"属性下 | +| bvid | str | 视频bvid | | +| cid | num | 稿件cid | | +| dislike_switch | num | 1 | 显示不感兴趣开关? | +| dislike_switch_pc | num | 0 | 显示不感兴趣开关(PC)? | +| duraion | num | 视频时长 | | +| enable_vt | num | 0 | 作用尚不明确 | +| goto | num | 目标类型 | av: 视频
ogv: 边栏
live: 直播 | +| duraion | num | 视频时长 | | +| id | num | 视频aid / 直播间id | | +| is_followed | num | 已关注 | 0: 未关注
1: 已关注 | +| is_stock | num | 0 | 作用尚不明确 | +| ogv_info | null | | | +| owner | obj | UP主 | | +| pic | str | 封面 | | +| pic_4_3 | str | 封面(4:3) | | +| pos | num | 0 | 位置? | +| pubdate | num | 发布时间 | | +| rcmd_reason | obj | 推荐理由 | 直播等为null | +| room_info | obj | 直播间信息 | 普通视频等为null, 参见[直播](../live) | +| show_info | num | 展示信息 | 1: 普通视频
0: 直播 | +| stat | obj | 视频状态信息 | 直播等为null, 参见[视频基本信息](info.md) | +| title | str | 标题 | | +| track_id | str | 跟踪标识? | | +| uri | str | 目标页 URI | | +| vt_display | str | 空 | 作用尚不明确 | + +`item`数组中的对象中的`owner`对象: + +| 字段 | 类型 | 内容 | 备注 | +|------|-----|--------|----| +| face | str | 头像URL | | +| mid | num | UP主mid | | +| name | str | UP昵称 | | + +`item`数组中的对象中的`rcmd_reason`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------|-----|------|-------------------------------| +| reason_type | num | 原因类型 | 0: 无
1: 已关注
3: 高点赞量 | +| content | str | 原因描述 | 当 reason_type 为 3 时存在 | + +**示例:** + +获取新版web端首页推荐视频列表 + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/wbi/index/top/feed/rcmd' \ +--data-urlencode 'fresh_type=4' \ +--data-urlencode 'ps=12' \ +--data-urlencode 'fresh_idx=5' \ +--data-urlencode 'fresh_idx_1h=5' \ +--data-urlencode 'fetch_row=16' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "item": [ + { + "id": 1354614895, + "bvid": "BV1Dz42117GZ", + "cid": 1548835687, + "goto": "av", + "uri": "https://www.bilibili.com/video/BV1Dz42117GZ", + "pic": "http://i1.hdslb.com/bfs/archive/b47154987b4c0f40a39779c09a9d485176d1238f.jpg", + "pic_4_3": "http://i0.hdslb.com/bfs/archive/b47154987b4c0f40a39779c09a9d485176d1238f.jpg", + "title": "做数学题总是抄错 | 看错 | 算错 怎么破?决定高考分数的这个非智力因素不容忽视", + "duration": 882, + "pubdate": 1715946937, + "owner": { + "mid": 374484802, + "name": "数学阮禾老师", + "face": "https://i1.hdslb.com/bfs/face/4df57e4b48b04206bce7572831688741580ca0e1.jpg" + }, + "stat": { + "view": 48250, + "like": 2959, + "danmaku": 433, + "vt": 0 + }, + "av_feature": null, + "is_followed": 0, + "rcmd_reason": { + "reason_type": 0 + }, + "show_info": 1, + "track_id": "web_pegasus_4.router-web-pegasus-1554782-5c89895477-smhn8.1721098961744.133", + "pos": 0, + "room_info": null, + "ogv_info": null, + "business_info": null, + "is_stock": 0, + "enable_vt": 0, + "vt_display": "", + "dislike_switch": 1, + "dislike_switch_pc": 0 + }, + { + "id": 1255924089, + "bvid": "BV1DJ4m1u7Mp", + "cid": 1600833978, + "goto": "av", + "uri": "https://www.bilibili.com/video/BV1DJ4m1u7Mp", + "pic": "http://i0.hdslb.com/bfs/archive/5068d860e8bbc37679ece933aa8e6d8428cfb5c1.jpg", + "pic_4_3": "http://i0.hdslb.com/bfs/aistory/2024-07-01-1145021255924089_1612_gener.jpg", + "title": "人类这种生物,看到按钮就会按下去。", + "duration": 326, + "pubdate": 1719805500, + "owner": { + "mid": 5616993, + "name": "马夫鱼33", + "face": "https://i0.hdslb.com/bfs/face/4c2af23046147e91ce5a4af3375464fdcf1956e6.jpg" + }, + "stat": { + "view": 667067, + "like": 28529, + "danmaku": 483, + "vt": 0 + }, + "av_feature": null, + "is_followed": 0, + "rcmd_reason": { + "content": "2万点赞", + "reason_type": 3 + }, + "show_info": 1, + "track_id": "web_pegasus_4.router-web-pegasus-1554782-5c89895477-smhn8.1721098961744.133", + "pos": 0, + "room_info": null, + "ogv_info": null, + "business_info": null, + "is_stock": 0, + "enable_vt": 0, + "vt_display": "", + "dislike_switch": 1, + "dislike_switch_pc": 0 + }, + { + "id": 1306020278, + "bvid": "BV1rM4m117Ry", + "cid": 1608959606, + "goto": "av", + "uri": "https://www.bilibili.com/video/BV1rM4m117Ry", + "pic": "http://i0.hdslb.com/bfs/archive/49f62c70f17d0afe00e5e620dd366c68149c780e.jpg", + "pic_4_3": "http://i0.hdslb.com/bfs/archive/49f62c70f17d0afe00e5e620dd366c68149c780e.jpg", + "title": "Axios 前后端对接教程|HTTP", + "duration": 352, + "pubdate": 1720440325, + "owner": { + "mid": 260736087, + "name": "三分钟实验室", + "face": "https://i0.hdslb.com/bfs/face/6172aa089ed0b26ffffb72018422eb4280d4da41.jpg" + }, + "stat": { + "view": 7527, + "like": 365, + "danmaku": 1, + "vt": 0 + }, + "av_feature": null, + "is_followed": 0, + "rcmd_reason": { + "reason_type": 0 + }, + "show_info": 1, + "track_id": "web_pegasus_4.router-web-pegasus-1554782-5c89895477-smhn8.1721098961744.133", + "pos": 0, + "room_info": null, + "ogv_info": null, + "business_info": null, + "is_stock": 0, + "enable_vt": 0, + "vt_display": "", + "dislike_switch": 1, + "dislike_switch_pc": 0 + }, + { + "id": 1755972439, + "bvid": "BV1g4421D7qn", + "cid": 1597039275, + "goto": "av", + "uri": "https://www.bilibili.com/video/BV1g4421D7qn", + "pic": "http://i2.hdslb.com/bfs/archive/35ee2ffaab4206d17893a3f48cdf512b4f028fdc.jpg", + "pic_4_3": "http://i0.hdslb.com/bfs/aistory/2024-06-26-21354756381755972439_16_12_5326_crop.jpg", + "title": "《我爱发明》里那些抽象发明 歹徒兴奋床!", + "duration": 659, + "pubdate": 1719408945, + "owner": { + "mid": 348989367, + "name": "沫子瞪片", + "face": "https://i0.hdslb.com/bfs/face/a2131d38a2ea73f16ff25e61dbeb40377233f552.jpg" + }, + "stat": { + "view": 1540767, + "like": 65409, + "danmaku": 5383, + "vt": 0 + }, + "av_feature": null, + "is_followed": 0, + "rcmd_reason": { + "reason_type": 0 + }, + "show_info": 1, + "track_id": "web_pegasus_4.router-web-pegasus-1554782-5c89895477-smhn8.1721098961744.133", + "pos": 0, + "room_info": null, + "ogv_info": null, + "business_info": null, + "is_stock": 0, + "enable_vt": 0, + "vt_display": "", + "dislike_switch": 1, + "dislike_switch_pc": 0 + }, + { + "id": 1055953358, + "bvid": "BV1jH4y1w7A6", + "cid": 1598484848, + "goto": "av", + "uri": "https://www.bilibili.com/video/BV1jH4y1w7A6", + "pic": "http://i1.hdslb.com/bfs/archive/accdb655b4f2bef665e6fdedb4de28de2feda078.jpg", + "pic_4_3": "http://i0.hdslb.com/bfs/aistory/2024-06-28-12560692491055953358_16_12_2438_crop.jpg", + "title": "为什么一个数的5次方个位数是自己!", + "duration": 327, + "pubdate": 1719550565, + "owner": { + "mid": 483522694, + "name": "火星课堂", + "face": "https://i1.hdslb.com/bfs/face/fe751f0d7062c8e8adcef501390d48330fac0514.jpg" + }, + "stat": { + "view": 244673, + "like": 5406, + "danmaku": 210, + "vt": 0 + }, + "av_feature": null, + "is_followed": 0, + "rcmd_reason": { + "reason_type": 0 + }, + "show_info": 1, + "track_id": "web_pegasus_4.router-web-pegasus-1554782-5c89895477-smhn8.1721098961744.133", + "pos": 0, + "room_info": null, + "ogv_info": null, + "business_info": { + "id": 0, + "contract_id": "", + "res_id": 1055953358, + "asg_id": 0, + "pos_num": 0, + "name": "", + "pic": "", + "litpic": "", + "url": "", + "style": 0, + "agency": "", + "label": "", + "intro": "", + "creative_type": 0, + "request_id": "1721098961752q172a25a216a162q1363", + "src_id": 5637, + "area": 0, + "is_ad_loc": true, + "ad_cb": "", + "title": "", + "server_type": 0, + "cm_mark": 0, + "stime": 0, + "mid": "", + "activity_type": 0, + "epid": 0, + "sub_title": "", + "ad_desc": "", + "adver_name": "", + "null_frame": false, + "pic_main_color": "", + "card_type": 0, + "business_mark": null, + "inline": { + "inline_use_same": 0, + "inline_type": 0, + "inline_url": "", + "inline_barrage_switch": 0 + }, + "operater": "", + "jump_target": 0, + "show_urls": null, + "click_urls": null + }, + "is_stock": 1, + "enable_vt": 0, + "vt_display": "", + "dislike_switch": 1, + "dislike_switch_pc": 0 + }, + { + "id": 1763571437, + "bvid": "", + "cid": 0, + "goto": "live", + "uri": "https://live.bilibili.com/1763571437", + "pic": "http://i0.hdslb.com/bfs/live/new_room_cover/f1787ef2ce4a2a031fb4a6a63b62d15493268d71.jpg", + "pic_4_3": "", + "title": "【新V】今天不要再把自己笨哭了", + "duration": 0, + "pubdate": 0, + "owner": { + "mid": 3546712666802274, + "name": "伊柒璇儿_鹤熙冠", + "face": "https://i0.hdslb.com/bfs/face/3e0ff3d7d53b9ac1a2d90ea563e22d3f70ad28cc.jpg" + }, + "stat": null, + "av_feature": null, + "is_followed": 0, + "rcmd_reason": null, + "show_info": 0, + "track_id": "web_pegasus_4.router-web-pegasus-1554782-5c89895477-smhn8.1721098961744.133", + "pos": 0, + "room_info": { + "room_id": 1763571437, + "uid": 3546712666802274, + "live_status": 1, + "show": { + "short_id": 0, + "title": "【新V】今天不要再把自己笨哭了", + "cover": "http://i0.hdslb.com/bfs/live/new_room_cover/f1787ef2ce4a2a031fb4a6a63b62d15493268d71.jpg", + "keyframe": "http://i0.hdslb.com/bfs/live-key-frame/keyframe07161101001763571437k9l40v.jpg", + "popularity_count": 8539, + "tag_list": null, + "live_start_time": 0, + "live_id": 0, + "hidden_online": false + }, + "area": { + "area_id": 0, + "area_name": "虚拟日常", + "parent_area_id": 9, + "parent_area_name": "虚拟主播", + "old_area_id": 0, + "old_area_name": "", + "old_area_tag": "", + "area_pk_status": 0, + "is_video_room": false + }, + "watched_show": { + "switch": true, + "num": 168, + "text_small": "168", + "text_large": "168人看过", + "icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png", + "icon_location": "", + "icon_web": "https://i0.hdslb.com/bfs/live/8d9d0f33ef8bf6f308742752d13dd0df731df19c.png" + } + }, + "ogv_info": null, + "business_info": null, + "is_stock": 0, + "enable_vt": 0, + "vt_display": "", + "dislike_switch": 1, + "dislike_switch_pc": 0 + }, + { + "id": 1855792572, + "bvid": "BV16s421T7CU", + "cid": 1587596195, + "goto": "av", + "uri": "https://www.bilibili.com/video/BV16s421T7CU", + "pic": "http://i2.hdslb.com/bfs/archive/1b9d9799260a075b094212bf79e3d7ccb9e04087.jpg", + "pic_4_3": "http://i0.hdslb.com/bfs/aistory/2024-06-19-14044883851855792572_16_12_7260_crop.jpg", + "title": "压缩蚊件.zip", + "duration": 66, + "pubdate": 1718777086, + "owner": { + "mid": 173947574, + "name": "好奇五先生", + "face": "https://i2.hdslb.com/bfs/face/1c69fff12a2d0d50e71931cef0486ab919a818a2.jpg" + }, + "stat": { + "view": 951633, + "like": 22930, + "danmaku": 932, + "vt": 0 + }, + "av_feature": null, + "is_followed": 0, + "rcmd_reason": { + "reason_type": 0 + }, + "show_info": 1, + "track_id": "web_pegasus_4.router-web-pegasus-1554782-5c89895477-smhn8.1721098961744.133", + "pos": 0, + "room_info": null, + "ogv_info": null, + "business_info": null, + "is_stock": 0, + "enable_vt": 0, + "vt_display": "", + "dislike_switch": 1, + "dislike_switch_pc": 0 + }, + { + "id": 1405866842, + "bvid": "BV11r421F7E8", + "cid": 1589772517, + "goto": "av", + "uri": "https://www.bilibili.com/video/BV11r421F7E8", + "pic": "http://i2.hdslb.com/bfs/archive/50b1bb8d227d17a3b6195e80128ab295d152d3be.jpg", + "pic_4_3": "http://i0.hdslb.com/bfs/aistory/2024-06-20-2148551405866842_1612_gener.jpg", + "title": "【音游推荐】暑期音游推荐,不同基础都可入坑", + "duration": 311, + "pubdate": 1718891332, + "owner": { + "mid": 592146708, + "name": "Qc天水", + "face": "https://i0.hdslb.com/bfs/face/2998a9e762aa07559b2acf54234f07979c959ffe.jpg" + }, + "stat": { + "view": 278997, + "like": 6698, + "danmaku": 303, + "vt": 0 + }, + "av_feature": null, + "is_followed": 0, + "rcmd_reason": { + "reason_type": 0 + }, + "show_info": 1, + "track_id": "web_pegasus_4.router-web-pegasus-1554782-5c89895477-smhn8.1721098961744.133", + "pos": 0, + "room_info": null, + "ogv_info": null, + "business_info": null, + "is_stock": 0, + "enable_vt": 0, + "vt_display": "", + "dislike_switch": 1, + "dislike_switch_pc": 0 + }, + { + "id": 1055540151, + "bvid": "BV1in4y197U4", + "cid": 1582190043, + "goto": "av", + "uri": "https://www.bilibili.com/video/BV1in4y197U4", + "pic": "http://i2.hdslb.com/bfs/archive/9a366971fadd6e4dfd1813c42b180c8779038627.jpg", + "pic_4_3": "http://i0.hdslb.com/bfs/aistory/2024-06-15-18004087071055540151_16_12_7856_crop.jpg", + "title": "我把裁判罚下场了", + "duration": 217, + "pubdate": 1718445600, + "owner": { + "mid": 475304452, + "name": "生姜蛋包饭", + "face": "https://i1.hdslb.com/bfs/face/40feee36c71f7f53931854fc54c88d530360b1a7.jpg" + }, + "stat": { + "view": 678085, + "like": 62171, + "danmaku": 832, + "vt": 0 + }, + "av_feature": null, + "is_followed": 0, + "rcmd_reason": { + "content": "6万点赞", + "reason_type": 3 + }, + "show_info": 1, + "track_id": "web_pegasus_4.router-web-pegasus-1554782-5c89895477-smhn8.1721098961744.133", + "pos": 0, + "room_info": null, + "ogv_info": null, + "business_info": null, + "is_stock": 0, + "enable_vt": 0, + "vt_display": "", + "dislike_switch": 1, + "dislike_switch_pc": 0 + }, + { + "id": 1505823466, + "bvid": "BV1vS421d7No", + "cid": 1596567774, + "goto": "av", + "uri": "https://www.bilibili.com/video/BV1vS421d7No", + "pic": "http://i2.hdslb.com/bfs/archive/b2b19b067cdbf7dd93be5fc01009e72c20572184.jpg", + "pic_4_3": "http://i0.hdslb.com/bfs/aistory/2024-06-26-1241021505823466_1612_gener.jpg", + "title": "AI 视频:两小儿辩日", + "duration": 138, + "pubdate": 1719376858, + "owner": { + "mid": 589397373, + "name": "宝玉xp", + "face": "https://i0.hdslb.com/bfs/face/c2c29f6e1bb9b0860241f0df4d2cdea8242ab5d2.jpg" + }, + "stat": { + "view": 1216188, + "like": 54839, + "danmaku": 194, + "vt": 0 + }, + "av_feature": null, + "is_followed": 0, + "rcmd_reason": { + "reason_type": 0 + }, + "show_info": 1, + "track_id": "web_pegasus_4.router-web-pegasus-1554782-5c89895477-smhn8.1721098961744.133", + "pos": 0, + "room_info": null, + "ogv_info": null, + "business_info": null, + "is_stock": 0, + "enable_vt": 0, + "vt_display": "", + "dislike_switch": 1, + "dislike_switch_pc": 0 + }, + { + "id": 1055744039, + "bvid": "BV1Zn4y1Q7zj", + "cid": 1575814128, + "goto": "av", + "uri": "https://www.bilibili.com/video/BV1Zn4y1Q7zj", + "pic": "http://i0.hdslb.com/bfs/archive/5288cf0830e49de414084c4168b11033b08f8507.jpg", + "pic_4_3": "http://i0.hdslb.com/bfs/aistory/2024-06-09-17404720501055744039_16_12_294_crop.jpg", + "title": "【诺子】重新“看见”世界是一种什么样的感觉?", + "duration": 579, + "pubdate": 1717926045, + "owner": { + "mid": 10276136, + "name": "诺子喵呜", + "face": "https://i2.hdslb.com/bfs/face/7e6846ed5619b945c888b8f8db5000469f6353ff.jpg" + }, + "stat": { + "view": 1016467, + "like": 97886, + "danmaku": 979, + "vt": 0 + }, + "av_feature": null, + "is_followed": 0, + "rcmd_reason": { + "reason_type": 0 + }, + "show_info": 1, + "track_id": "web_pegasus_4.router-web-pegasus-1554782-5c89895477-smhn8.1721098961744.133", + "pos": 0, + "room_info": null, + "ogv_info": null, + "business_info": null, + "is_stock": 0, + "enable_vt": 0, + "vt_display": "", + "dislike_switch": 1, + "dislike_switch_pc": 0 + }, + { + "id": 1706215690, + "bvid": "BV1tT421k7By", + "cid": 1611364587, + "goto": "av", + "uri": "https://www.bilibili.com/video/BV1tT421k7By", + "pic": "http://i1.hdslb.com/bfs/archive/cd3308109e8726fe4147dd25ed7ca0dbeeda1dc1.jpg", + "pic_4_3": "http://i0.hdslb.com/bfs/aistory/2024-07-11-00194836761706215690_16_12_3934_crop.jpg", + "title": "谷歌翻译20遍《河中石兽》泌尿系统", + "duration": 145, + "pubdate": 1720628387, + "owner": { + "mid": 1030835113, + "name": "象哥嘎", + "face": "https://i1.hdslb.com/bfs/face/aa0ae89fa72dab7b8bc082433769b1768f51c3dc.jpg" + }, + "stat": { + "view": 78600, + "like": 3437, + "danmaku": 328, + "vt": 0 + }, + "av_feature": null, + "is_followed": 0, + "rcmd_reason": { + "reason_type": 0 + }, + "show_info": 1, + "track_id": "web_pegasus_4.router-web-pegasus-1554782-5c89895477-smhn8.1721098961744.133", + "pos": 0, + "room_info": null, + "ogv_info": null, + "business_info": null, + "is_stock": 0, + "enable_vt": 0, + "vt_display": "", + "dislike_switch": 1, + "dislike_switch_pc": 0 + } + ], + "side_bar_column": [ + { + "id": 25502, + "goto": "comic", + "track_id": "", + "pos": 1, + "card_type": "漫画", + "card_type_en": "comic", + "cover": "http://i0.hdslb.com/bfs/manga-static/5e410bf6f73ff87f87b543e4b918de5f024652e8.jpg", + "url": "https://manga.bilibili.com/detail/mc25502", + "title": "头文字D", + "sub_title": "", + "duration": 0, + "stats": null, + "room_info": null, + "styles": [ + "游戏竞技" + ], + "comic": { + "comic_id": 25502, + "title": "头文字D", + "horizontal_cover": "http://i0.hdslb.com/bfs/manga-static/5e410bf6f73ff87f87b543e4b918de5f024652e8.jpg", + "square_cover": "http://i0.hdslb.com/bfs/manga-static/da660f6274730af82d557f21a6247d4f6b1e300b.jpg", + "vertical_cover": "http://i0.hdslb.com/bfs/manga-static/64df8b860d2bf6bf2edd0426b4aefbff25b51386.jpg", + "is_finish": 1, + "status": 0, + "last_ord": 724, + "total": 724, + "release_time": "", + "last_short_title": "番外05", + "discount_type": 0, + "recommendation": "秋名山下坡最快的AE86神话!", + "last_read_ep_id": 0, + "latest_ep_short_title": "", + "style": [ + "游戏竞技" + ], + "author_name": [ + "重野秀一 ", + "讲谈社" + ], + "allow_wait_free": false, + "type": 0, + "rank": null, + "operate_cover": "", + "rookie_type": 0 + }, + "producer": null, + "source": "", + "av_feature": null, + "is_rec": 0, + "is_finish": 0, + "is_started": 0, + "is_play": 0, + "enable_vt": 0, + "vt_display": "" + }, + { + "id": 47800, + "goto": "ogv", + "track_id": "", + "pos": 2, + "card_type": "番剧", + "card_type_en": "bangumi", + "cover": "https://i0.hdslb.com/bfs/bangumi/image/1c61f75b571fffb8c5a2bd0396b49ce3529776f4.png", + "url": "https://www.bilibili.com/bangumi/play/ss47800", + "title": "铁甲小宝 重制版 中文配音", + "sub_title": "童年经典回归!", + "duration": 1382000, + "stats": { + "follow": 116644, + "view": 10864687, + "danmaku": 42428, + "reply": 11448, + "coin": 18904, + "series_follow": 209046, + "series_view": 17474247, + "likes": 61376, + "favorite": 116644 + }, + "room_info": null, + "new_ep": { + "id": 824212, + "index_show": "更新至第30话", + "cover": "http://i0.hdslb.com/bfs/archive/e185c054588945a1de6648ff7fb5001852df39f4.png", + "title": "30", + "long_title": "巨大机器来袭!!", + "pub_time": "2024-07-15 18:00:01", + "duration": 1382000, + "day_of_week": 1 + }, + "styles": [ + "日常", + "热血", + "搞笑", + "原创", + "特摄" + ], + "comic": null, + "producer": [ + { + "mid": 928123, + "name": "哔哩哔哩番剧", + "type": 3, + "is_contribute": 1 + } + ], + "source": "", + "av_feature": null, + "is_rec": 0, + "is_finish": 0, + "is_started": 1, + "is_play": 1, + "horizontal_cover_16_9": "https://i0.hdslb.com/bfs/bangumi/image/ec5065dc0e88417abd4792d5caa96dacc99d1d51.png", + "horizontal_cover_16_10": "https://i0.hdslb.com/bfs/bangumi/image/5cc132e336cc72e6521bba928d8a0e50bd5a6d34.png", + "enable_vt": 0, + "vt_display": "" + }, + { + "id": 48020, + "goto": "ogv", + "track_id": "", + "pos": 3, + "card_type": "国创", + "card_type_en": "guochuang", + "cover": "https://i0.hdslb.com/bfs/bangumi/image/fcb176fcbf5a66fd122fa99f9fdf2cabf22468bb.png", + "url": "https://www.bilibili.com/bangumi/play/ss48020", + "title": "不白吃古诗词漫游记 第二季", + "sub_title": "古诗词这动人的浪漫", + "duration": 179000, + "stats": { + "follow": 2173495, + "view": 325366, + "danmaku": 110, + "reply": 208, + "coin": 443, + "series_follow": 2208624, + "series_view": 3322752487, + "likes": 8794, + "favorite": 2173495 + }, + "room_info": null, + "new_ep": { + "id": 830238, + "index_show": "更新至第7话", + "cover": "http://i0.hdslb.com/bfs/archive/6db74bc8ab2670181562314a24abe525cebb7c76.jpg", + "title": "7", + "long_title": "王维当个官怎么还郁闷了?", + "pub_time": "2024-07-15 19:00:00", + "duration": 179000, + "day_of_week": 1 + }, + "styles": [ + "少儿", + "历史", + "原创", + "古风" + ], + "comic": null, + "producer": [], + "source": "", + "av_feature": null, + "is_rec": 0, + "is_finish": 0, + "is_started": 1, + "is_play": 1, + "horizontal_cover_16_9": "https://i0.hdslb.com/bfs/bangumi/image/f19013ddd7f87b0e03df10feccc4a61a3a43774a.png", + "horizontal_cover_16_10": "https://i0.hdslb.com/bfs/bangumi/image/966553b199829aae7e47882edbe053463ee85276.png", + "enable_vt": 0, + "vt_display": "" + } + ], + "business_card": null, + "floor_info": null, + "user_feature": null, + "preload_expose_pct": 0.5, + "preload_floor_expose_pct": 0.5, + "mid": 645769214 + } +} +``` + +
+ +## 根据点击视频获取的短视频播放列表 + +> https://app.bilibili.com/x/v2/feed/index/story + +*请求方式:GET* + +在APP端点击主页视频后发出的请求 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|---------------|------|-------------------------|----------------|------------------------------------------| +| aid | num | 点击视频的aid | 非必要 | 所点击视频的aid,会影响到后续视频内容 | +| display_id | num | 视频列表页数 | 非必要 | 从1开始,第1页会得到比其他页多aid处所填视频 | +| access_key | str | APP登录Token | APP方式必要 | | +| ad_extra | str | 额外广告? | 非必要 | | +| appkey | str | APP密钥 | APP方式必要 | | +| auto_play | num | 自动播放 | 非必要 | 可为0 | +| build | num | 版本 | APP方式必要 | 可为`8130300` | +| bvid | str | 视频的bv号 | 非必要 | 可为空,如果没有会导致返回不正常 | +| c_locale | str | 语言 | 非必要 | zh_CN | +| channel | num | 频道 | 非必要 | | +| cid | num | 目标频道id | 非必要 | | +| contain | bool | 未知 | 非必要 | 可为false | +| creative_id | num | 未知 | 非必要 | 默认为 `0` | +| device_name | str | 设备名称 | 非必要 | 随意字符串都行 | +| disable_rcmd | num | 未知 | 非必要 | 默认为 `1` | +| epid | num | 未知 | 非必要 | 默认为 `0` | +| feed_status | num | 未知 | 非必要 | 默认为 `0` | +| fnval | num | 视频流类型 | 非必要 | | +| fnver | num | 请求时提供的fnver | 非必要 | 可为 0 | +| force_host | num | 源url类型 | 非必要 | 0:无限制 1:使用http 2:使用https | +| fourk | num | 是否允许 4K 视频 | 非必要 | 画质最高 1080P:0(默认)
画质最高 4K:1 | +| from | num | 未知 | 非必要 | 可为 `7` | +| from_spmid | str | 未知 | 非必要 | tm.recommend.0.0 | +| goto | str | 未知 | 非必要 | | +| mobi_app | str | 平台标识 | 非必要 | 可为 `web`、`android` 等 | +| network | str | 网络 | 非必要 | 可为 `wifi` | +| ogv_style | num | 未知 | 非必要 | 默认为 `0` | +| platform | str | 平台 | 非必要 | 可为`web`或`android` | +| player_net | num | 未知 | 非必要 | 默认为 `1` | +| pull | num | 未知 | 非必要 | 默认为 `1` | +| pn | num | 似乎不是页码 | 非必要 | 默认为 `32` | +| request_from | num | 未知 | 非必要 | 默认为 `0` | +| s_locale | str | 语言 | 非必要 | zh_CN | +| spmid | str | 未知 | 非必要 | main.ugc-video-detail-vertical.0.0 | +| statistics | str | 位置 | 非必要 | 可为{"appId":1,"platform":3,"version":"8.13.0","abtest":""} | +| story_param | str | 未知 | 非必要 | | +| trackid | str | 路径id?未知 | 非必要 | | +| ts | num | 秒级时间戳 | 非必要 | | +| video_mode | num | 视频模式?未知 | 非必要 | 可为 `2`,应该是可以逆向出来的 | +| voice_balance | num | 未知 | 非必要 | 默认为 `1` | +| sign | str | APP签名 | APP方式必要 | | + +**json回复:** + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 默认为 0 | +| ttl | num | 1 | | +| data | obj | 视频信息 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | ---------------------------- | +| config | obj | 配置 | | +| items | array | 视频信息 | | + +`items`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------ | ---- | +| 0 | obj | 视频信息1 | | +| n | obj | 视频信息(n+1) | | +| …… | obj | …… | …… | + +`items`数组元素: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------- | ----- | ----------------------- | ------------------------ | +| bvid | str | 视频bv号 | | +| card_goto | str | 卡片跳转 | | +| copyright | num | 版权 | | +| cover | str | 封面url | | +| desc | str | 视频描述 | | +| dimension | num | 包括视频尺寸、旋转角度 | | +| dislike_reasons_v2 | obj | 不喜欢原因v2的各种显示 | | +| dislike_reasons_v3 | obj | 不喜欢原因v3的各种显示 | | +| duration | num | 视频时长 | | +| ff_cover | str | 短视频封面原图 | | +| goto | str | 应该是跳转去向类型 | 此处为vertical_av | +| owner | obj | 拥有者,也就是up信息 | | +| param | str | 参数,实际为视频aid | | +| player_args | obj | 播放器参数 | | +| pubdate | num | 发布时间秒级时间戳 | | +| report_flow_data | str | 报告流数据 | 是个伪装成obj的str | +| req_user | ? | 未知 | 空的 | +| rights | obj | 未知 | | +| share_bottom_button | obj | 分享下方按钮 | | +| share_guide | obj | 未知 | | +| short_link | str | 视频短链接 | | +| show_report | obj | 显示举报 | | +| stat | obj | 视频信息 | | +| sub_title | str | 子标题 | 但显示的是描述播放量的文字 | +| submission_entrance | obj | 提交入口 | icon的uri | +| three_point_button | obj | 三点按钮要显示的内容 | 里面有两个array | +| thumb_up_animation | str | 未知 | | +| title | str | 视频标题 | | +| top_search_bar | obj | 搜索栏 | 内含一个跳转的uri | +| track_id | str | 路由track | | +| uri | str | uri | | +| view_content | str | 用于显示的文本形式播放量 | | +| vip | obj | vip相关的信息 | | + +`owner`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------- | ----- | ----------------------- | ------------------------ | +| attention | num | 未知 | 包含一个mid的int字段 | +| avatar | obj | 一些显示设置 | | +| face | str | 头像url | | +| fans | num | 粉丝量 | | +| like_num | num | 获赞数 | | +| mid | num | up主的mid | | +| name | str | up主的昵称 | | +| official_verify | obj | 官方认证 | type=-1为无认证,没有其他字段;type=0为黄闪电同时role=1,type=1为蓝闪电同时role大于1,且type不为-1时有字段title为称号 | +| relation | num | 关系?未知 | | +| sub_avatar | obj | 子形象 | 包含一个mid的int字段 | +| upower | obj | 充电相关 | 包含一个button_uri字段类型为str,是充电跳转链接 | + +`player_args`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------- | ----- | ----------------------- | ------------------------ | +| aid | num | 视频作者的aid | | +| cid | num | 所属频道的cid | | +| type | str | 内容类型 | 视频一般都是av | + +`player_args`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------- | ----- | ------------------------ | ------------------------ | +| aid | num | 视频作者的aid | | +| coin | num | 视频硬币数 | | +| danmaku | num | 视频弹幕数 | | +| favorite | num | 视频收藏数 | | +| follow | num | 未知 | 很多都是0 | +| like | num | 视频点赞数 | | +| reply | num | 视频评论与回复总数 | | +| share | num | 视频分享数 | | +| view | num | 视频播放 | | + +**示例:** + +(1)模拟点击aid=113350747029965的视频并获取短视频推荐列表 + +```python +import json +import requests + +mobile_headers = { + "User-Agent": "xxx", + "env": "prod", + "session_id": "xxx", # 在实际使用中,session_id需要及时更新,否则将导致响应列表有问题 + "APP-KEY": "android64", + 'Buvid': "xxx" +} + +story_url = "https://app.bilibili.com/x/v2/feed/index/story" + +story_params = { + "aid": 113350747029965, + "display_id": 1, + "appkey": "1d8b6e7d45233436", + "build": "8130300", + "bvid": "", + "mobi_app": "android", + "statistics": "{\"appId\":1,\"platform\":3,\"version\":\"8.13.0\",\"abtest\":\"\"}" +} + +response = requests.get(story_url, params=story_params, headers=mobile_headers) + +print(json.dumps(response.json(), indent=4)) +``` + +返回值内容过长,暂不予展示 + +(2)随机的短视频推荐 + +> https://app.bilibili.com/x/v2/feed/index/story + +浏览器直接输入 + +返回值内容过长,暂不予展示 + +## 获取短视频模式视频列表 + +> https://app.bilibili.com/x/v2/feed/index + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +有大量不明意义的参数 备注仅供参考 + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +|---------------|------|------------|-----|--------------------------------------| +| fnval | num | 视频流格式标识 | 非必要 | 默认为272 | +| fnver | num | 视频流版本标识 | 非必要 | 恒为1 | +| force_host | num | 源url类型 | 非必要 | 0:无限制 1:使用http 2:使用https | +| fourk | num | 是否允许 4K 视频 | 非必要 | 画质最高 1080P:0(默认)
画质最高 4K:1 | +| 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 | 非必要 | | +| accessKey | str | | 非必要 | 登录成功后返回的accessToken,添加此参数会返回个性化内容和横幅 | +| 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 | 横幅时为banner | +| card_type | str | 卡片类型 | 视频为small_cover_v2,横幅为banner_v8 | +| 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 | 跳转链接 | | +| goto_icon | obj | 视频卡片左下角图标 | 视频为普通视频时出现 | +| rcmd_reason_style | obj | 左下角的'竖屏'or'2千点赞' | 视频为热门时出现 | +| banner_item | list | 横幅列表 | 登录后使用accessKey出现 包含横幅信息列表 | + +`desc_button`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------|-----|------|----| +| event | str | | | +| text | str | up名称 | | +| type | num | 1 | | +| uri | str | 跳转链接 | | + +`player_args`对象: + +| 字段 | 类型 | 内容 | 备注 | +|----------|-----|-------|----| +| aid | num | 视频aid | | +| cid | num | 视频cid | | +| duration | num | 视频长度 | 秒数 | +| type | str | | | + +`goto_icon`对象 : + +| 字段 | 类型 | 内容 | 备注 | +|----------------|-----|-----------|----| +| icon_url | str | 图标链接 | | +| icon_night_url | str | 应该跟上面那个一样 | | +| icon_width | num | 16 | 宽度 | +| icon_height | num | 16 | 高度 | + +`rcmd_reason_style`对象 : + +| 字段 | 类型 | 内容 | 备注 | +|--------------------|-----|------------|---------| +| text | str | 1万点赞 \| 竖屏 | 文字信息 | +| text_color | str | #FF6633 | 字体颜色 | +| bg_color | str | #FFF1ED | 文本的背景颜色 | +| border_color | str | #FFF1ED | | +| text_color_night | str | #BF5330 | | +| bg_color_night | str | #3D2D29 | | +| border_color_night | str | #3D2D29 | | + +`banner_item`横幅列表内对象(内容尚未完全解读): + +为动态时 (列表索引通常为1) + +```json + { + "type": "static", + "resource_id": 4336, + "id": 1674508, + "index": 1, + "static_banner": { + "id": 1674508, + "title": "火凤燎原第二季完结!新的战神,来了!", + "image": "http://i0.hdslb.com/bfs/banner/b1fc0b68f727c2d4ea57bee154f531c3b7f13fca.png", + "hash": "a6cee3b5b1c05227159f734f68289ba5", + "uri": "https://www.bilibili.com/bangumi/play/ep1365959?goto=static_banner", + "request_id": "1745482994326q172a27a87a21q3087", + "src_id": 4337, + "is_ad_loc": true, + "client_ip": "182.89.224.34", + "server_type": 0, + "resource_id": 4336, + "index": 1, + "cm_mark": 0 + } +} +``` + +为广告时 index(列表索引通常为2) + +```json +{ + "type": "ad", + "resource_id": 4336, + "id": 0, + "index": 2, + "ad_banner": { + "id": 0, + "title": "今日全球首发,千件外观福利免费领", + "image": "https://i0.hdslb.com/bfs/sycp/creative_img/202504/bbd7cc4e6a74508e9ccee467541cc06a.jpg", + "hash": "46cbecfe04e047692acfd4a149e81ebd", + "uri": "https://qrsj.biligame.com/gcxz/h5/?sourceFrom=777&sourceType=adPut", + "request_id": "1745482994326q172a27a87a21q3087", + "creative_id": 1017846649959747584, + "src_id": 4338, + "is_ad": true, + "is_ad_loc": true, + "ad_cb": "CAAQABiAoLC1qsSHkA4gACgAMKm4TDjyIUIfMTc0NTQ4Mjk5NDMyNnExNzJhMjdhODdhMjFxMzA4N0iWpZO35jJSBuafs+W3nloG5bm/6KW/YgbkuK3lm71oAXAAeICAgICAGoABAIgBpYgEkgENMTgyLjg5LjIyNC4zNJoBj0BjcGNfcXVvdGE6Y29uc3RhbnQsZWNvbV9mb3JjZV9yZWNhbGw6YmFzZV8wNjI4XzIwLGJyYW5kX3NwbGFzaF9saXN0X2J5X3RpbWU6YnJhbmRfc3BsYXNoX2xpc3RfYnlfdGltZV80MF90dW5uZWwsdWVzX2VycWk6MTcsamtfY2FydDpqazEsZmVlZHNQcmltYXJ5TW9kZWxDb25mOmJzbDIsY29tbWVudENvbXBvbmVudEFudG91UmF0aW86YmFzZSxTbWFsbEJ1ZGdldFJhdGlvOmRlZmF1bHQsc2VhcmNoX2Fkc19jcmVhdGl2ZTpsbG1fZXhwMSxkYWlodW9fYm9vc3RfZXhwOmJvb3N0X2V4cCxzZWFyY2hfYWRzX3JlbGV2YW5jZTp0b3BfYmxhY2tsaXN0X2NhbGksc3BsYXNoX2lubmVyX291dGVyX2V4cDpiYXNlLGNjZF9leHBfZGVtbzpjY2RfYmFzZSxmcmVxUm91dGluZzpiYXNlLHZpZGVvX3RlbXBsYXRlX3N1cHBvcnQ6ZXhwMyxpYWFfb25seV9lY3BtOjAwLHRlc3RfbW9kZWxfbmFtZTpiYXNlXzExLGZseV9qdW1wX2NvbW1lbnQ6ZXhwMyxsb2dnaW5nX2FkaW5mb19saXN0OmJhc2UsdXNlTmV3WWVsbG93Q2FydFBhbm5lbDpleHAyLGhpZ2hfcXVhbGl0eV9hdmlkX3R1cm5fYmFjazpiYXNlLG5ld19kaXJlY3RfYWRtaXNzaW9uX3YyOm9wZW5fc2hvdXRhb193dWR1YW4sdHJhZGVfcmVjYWxsOmRlZmF1bHQsb3R0X2VjcG1fdGhyZDpiYXNlLGVuYWJsZV9hbHRfZGF2aW5jaTpkZWZhdWx0LGlubmVyX291dGVyX2JpZF9leHA6bmV3X3JhbmtmcmFtZV8wNDAyLG9mZmxpbmVfbWlkX2ZlYV92MjpleHAzLGRjdnJfd29ybGRfMjAyNVEyOmJhc2UxLHVuZGVyZnJhbWVfcHVsbF91cDpleHAxLGVuYWJsZV9pbmR1c3RyeV92Ml9maWx0ZXI6YmFzZSxuRmVkQmFjazE6bG9vc2UsRHBhMlJ0YVBpY2tQcm9kdWN0OnNoYXJlZF8zMCxmaWx0ZXJfY2xlYW46YmFzZSxhY2NvdW50RnJlcUNvbmY6YmFzZSxtaW5pZ2FtZV9iaWRfZXhwOmV4cF8wMzA3LHN0b3J5X2RhaWh1b19zdHlsZTpleHAsbm9fYWdlX2dlbmRlcl9leHA6YWdlMCxvdHRjb25maWc6ZXhwXzE1LE1peGVyRUNvbW1lcmNlOmVuYWJsZSxzc3BEaXJlY3REaXNwYXRjaEFkVm9FeHA6ZXhwXzIscmlza3lfYWRfb3B0OmhpZGRlbl9jb3N0XzAsc0ZCcnU6MyxCaXpNaXhlclJvdXRlcjpiaXpfbWl4ZXJfcGcsMjUzOTkxOmJhc2UsdHNtdjJfdHJhZGU6YmFzZSxmbHlfZGVxOm9yZGVyX2xpdmUsdHNtXzE6ZWR1dGFnX3JlY2FsbF8wMjA2LHJldHJpZXZlX2xvZzpvcGVuLGdkX21vZGVsOmV4cDEsY3BhX3NlYXJjaDpjcGFfdjIsdHNtdjJfc3dpbmdmbHlfb3RoZXJzY2VuZTpiYXNlLGFkeF9yZXF1ZXN0X29wdGltaXphdGlvbl90ZXN0OmRlZmF1bHQsc3RfdnZfbW9kZWw6YmFzZSxicnVzaF9kdXA6ZGVmYXVsdCxzdG9yeV9saXZlX3Z2OmRlZixpbmxpbmVfemVyb19jYXJkX2luZGV4OmV4cCxyZXFfbG9nX3JhdGlvOmJhc2UsZHBhVW5kZXJmcmFtZU5ld1N0eWxlOmV4cDIsZHluYW1pY1RpbWVvdXRNaW5zOjI0MCxtb2RlbF9jYWxpOmV4cDEsZmx5X2NwY19jYWxpX25ldzpvcmRlcl9hY2NfZXhwLGVuYWJsZVNtYXJ0Q292ZXJVcmw6YmFzZV9hYV8wMTE1LG1pbmlfZ2FtZV9sb25nX3RpbWVfZmxpcF9leHA6ZXhwX2dyb3VwLHV2X2FhOmRlZmF1bHQsYWNjb3VudF9ibGFjazpiYXNlLGFzQ29tbWVudENoZWNrRGlmZlJhdGlvRXhwOmV4cDIsY3RyX21vZGVsOmV4cF8wMSxic0R1cEFkOm9wZW4sb3JkZXJfbGF4aW46bGF4aW5fYmFzZV92Ml8xLHByb2dDcmVhRmVlZEN0cjpkaXN0X2x0cix1bmlvbl9mbHlfY3BjOmV4cDAxMjQsQ3VzdG9tQ3JlYXRpdmVTZWxlY3RFeHA6a3Vhbmd4aWFfMDQwMixuZXdCc0ZpbHRlckxvZzpvcGVuLHNlYXJjaF9xdWlja19wbGFjZW1lbnQ6ZXhwMSxib29zdF9leHA6ZXhwMyx0c212Ml9tb2RlbF9yZWNhbGw6YmFzZSxjY2RfdWVzY29yZTpjY2RfYmFzZSxkQWR4MTpvcGVuLGRhbGFvX2NhcmRfb25seV90b3A6ZXhwLGNhc3NpbmlFeHA6c21hbGxfYnVkZ2V0X2Nsb3NlLHNwbGFzaF90d2lzdF9hbmdsZV9leHA6YmFzZSx0c212Ml9vdGhlcnM6YmFzZSxzcGxhc2hNaW5JbnRlcnZhbEV4cDpiYXNlXzFoLGR5bmFtaWNfaW5kZXg6YmFzZSxyZWNhbGxfbGltaXRfcmF0aW86YmFzZSxmbHlfY3BhOmZseV92MyxnYW9uZW5nX2FidGVzdDpiYXNlLHBFTjpQUixzZWFyY2hfY3RyX21vZGVsOmV4cF95LGxpdmVfY2FyZF90YWdfbW92ZTpleHAxXzAzMTgsYmVzdENyZWF0aXZlOmVjcG0yLHN0b3J5X3N0eWxlX3NlbGVjdF9jb25mOmJhc2UyMDI1MDIyNyxjbG9zZV9zcmNfZWZmOmV4cF8wNzI1X25vX3J1bGUsMTA3MjpiYXNlLHNvZnRfYWRfZXhwOjA2LGZseV9saWtlX3RoOmNsb3NlLG1peGVyX3N0b3J5X2FkX3dlaWdodDo2LGFpZ2NfYW50b3U6TFJfYmFzZV8yMDI1MDMxNCxqZzpleHAyLHBkY3ZyX3RocmVzaG9sZDpleHAxLGRjdnJfcmV0ZW50aW9uX25ldzpjb21ib19iYXNlLHBlZ2FzdXNfbWl4ZXI6MDEsZHBhMjpiYXNlLHVuZGVyX2ZyYW1lX2VjcG1fZXhwOmJhc2UsSW5kdXN0cnlFeGNsdWRlSW5mb0NvbmZfdjI6YmFzZSxlbmFibGVfdXNlcl9mZWF0dXJlX2J1Y2tldDpiYXNlbGluZSxlY29tX3JlY2FsbDpMSFVDX0IsZW5hYmxlVGFnTW92ZVVwOmV4cDRfbW92ZV90YWdfZGlzbGlrZWFkaixhZF9icmFuZF9nZF9lbmFibGVfZGlmZjpiYXNlLGZkX3BjdHI6YmFzZV8xLDI1NzM4OmJhc2UscHJvZ0NyZWFEaWN0VmVyOmRlZmF1bHQsc2VhcmNoX3BhcmFsbGVsX3JlcV9yZWRpczpleHAxLHByb2dyYW1DcmVhdGl2ZTpkZWZhdWx0LGRwczpkZWZhdWx0LHBhZF9pbm5lcl9hZGxvYWQ6YmFzZV8yMF8wLHVuZGVyZnJhbWVfcHVsbF91cF9uZXc6YmFzZV9hYWEsY29hcnNlRXhwbG9yZUZhY3RvckNvbmY6ZGVmYXVsdCxmbHlfc3RvcnlfeWVsbG93Y2FyX3N0eWxlOnlvdXh1YW5fYmFzZV9rZmMsZmx5X2NwYV9wYzpleHAxMCxEcGFTdnJQcmVzc3VyZTpiYXNlLGNwYTpiYXNlLGJvb3N0X2JzOmJhc2UsZmx5Q2FyZFF1YWxpdHk6ZXhwNCxhbGw6Y3BjX2Nyb3dkX3RhcmdldCxmbHlfY3BhX2JvdHRvbTpjbG9zZSxSVEFfRElWSURFX0VYUF9UQUdfODkyOnJ0YV9kaXZpZGVfZXhwXzg5Ml81LEluZHVzdHJ5THRyQ29hcnNlQ29uZjpnYW1lbGl2ZSxlZGdlX3JlcmFuazpiYXNlLFJUQV9ESVZJREVfRVhQX1RBR182NTc6cnRhX2RpdmlkZV9leHBfNjU3XzQsaGVhcnRfYm94OmV4cCwyMzUzMTpub3JtYWwscHVwX25hdGl2ZV9hZDpkZWZhdWx0LG90dF9lZHVjYXRpb25fYW50b3U6ZXhwLGg1X3Y6Y29tcGFyZSx1c2VMdWFTY3JpcHQ6YmFzZSxjb2Fyc2VfZGFpaHVvOmJhc2UsZmxvd1J1bGU6b3BlbkZsb3dSdWxlQ2hlY2tTd2l0Y2gsc3Rvcnlfc3R5bGVfc2VsZWN0aW9uX2NvbmY6YmFzZTIwMjQxMTI5LG5ld192aWRlb191cF9taWRfZmlsdGVyOmJhc2UsZmx5X2NvYXJzZTpjb25zdGFudCxkZWxldGVGcmVxQ29kZTpiYXNlMyxob25nZ3VvX25vdF9zaG93X2luX2NoYXJnaW5nX3BhZ2U6YmFzZSxEcGFDcmVhdGl2ZVN0cmF0ZWd5RXhwZXJpbWVudDpzZWFyY2hfbWVyZ2VfaW1hZ2VfZXhwLHNzcF9yZXBsYXlfYXM6YmFzZSxiZnNfc2RwYV9kaXZlcnNpZnk6cmVtYWluLHNlYXJjaF9zdWJjYXJkX3N0eWxlOmZvcm1fYnV0dG9uLGJzLXg6YnMsd2hpdGVfYm94OmNsb3NlLGR1YW5qdV9hcnB1OmFkZF9ub3ZlbF8wMzI3LE1vZGVsRmVhdHVyZXNIaXZlTG9nOmNsb3NlLGZseV9zdXBfZmFjdG9yczpleHAsY2x0cmNvbmY6YnNsMyxkYXZpbmNpX3JlcV9sb2c6ZGVmYXVsdCxmbHdfbGlrZV9lbmdhZ2U6YmFzZSxzdG9yeV9jdXN0b21pemVfZGFubXU6YmFzZSxhZHhQbGF5UGFnZVJhc2lvOmV4cDAsZHBhMlByb21vdGVQcm9kdWN0TWF0ZXJpYWw6YmFzZSxsaXZlX21vZGVsOmxpdmVfYmFzZV8wNDA4LHVzZUFpR2NUaXRsZTpiYXNlLHBlZ2FzdXNfYWRsb2FkXzM6MTQsbGFuY2VyX25hdHVyZTpleHAsc3RvcnlfZGFubXVfY29uZjpkYW5tdV9udW1fMzgsdHNtdjJfdG9rZW5fc2RwYTpiYXNlLDI0aF9yb2lfYXJwdV9uZXc6c3RhbGxfYmFzZV92MyxzcGxhc2hfaGFyZF9maWx0ZXJzOmV4cCxnYW1lX2VjcG1fcm9pX2ZhY3Rvcl9zd2l0Y2g6ZXhwX291dGVyLGJ1cGNwY19nc3A6ZGVmYXVsdCxuRmVkQmFjazpsb29zZSxVbml0RGV0YWlsSW5mbzpjbG9zZSzogIHkuInov57lub/lkYrlsY/olL06YmFzZSxnZF9mb3JjZV9zZWxlY3Q6ZXhwMixjb2xkX2Jvb3RfY2xlYXJfZnJlcTpiYXNlLGdhbWVfb3Blbl9pbnRlcmVzdF9vcmllbnRhdGlvbjpleHBfb3Blbl9ib3RoLGNsb3NlX3BlcnNvbmFsX3JlY29tbWVuZF8yMDI1OmV4cF9vcGVuX2FsbF8wMjI4LFJUQV9ESVZJREVfRVhQX1RBR183MzE6cnRhX2RpdmlkZV9leHBfNzMxXzMsbm9fYWRfc2V0OmJhc2UsUlRBX0RJVklERV9FWFBfVEFHXzg1NTpydGFfZGl2aWRlX2V4cF84NTVfNyxhY2NvdW50X2V4cGxvcmVfc2hvd19saW1pdDpkZWZhdWx0LGZseV9nb29kc19jb21tZW50X3VybDpibHVlbGlua19yZXBsYWNlXzA1LG9yZGVyX2xhcmdlOmRlbGF5MSxlY3BtX3RocmVzaG9sZF9sYXllcjowOCxyZWNhbGxfdW5pdF9saW1pdDpiYXNlLFJUQV9ESVZJREVfRVhQX1RBR182NDA6cnRhX2RpdmlkZV9leHBfNjQwXzE2LGRhaWh1b1doaXRlQ29uZjp3aGl0ZV8yNDEyMDJfNSxSVEFfRElWSURFX0VYUF9UQUdfODgzOnJ0YV9kaXZpZGVfZXhwXzg4M181LGVuYWJsZUlubGluZUV4cDpiYXNlLFJUQV9ESVZJREVfRVhQX1RBR184ODg6cnRhX2RpdmlkZV9leHBfODg4XzIsaWFhX3VuaXRfZWE6ZXhwMSxTbWFsbEJ1ZGdldFRvbGVyYXRlOmV4cF83MixhdXRvX2FkX2Fzc2lzdDpiYXNlLG1peGVyX2JyYW5kX29wdDpiYXNlLGxheWVyZWRfYmlkZGluZzpiYXNlMDkyMixzdG9yeVllbGxvd0NhcnROZXc6ZXhwX2Jhc2UyXzAyMTMseHN0X2NodWRpYW46YmFzZSxkdWFuanVfbW9kZWw6ZGVmYXVsdCxnZF9waWQ6ZXhwX3JlYWQsY3BjMV9leHRlbmRlZDpxdW90YV8xMCxicnVzaF9pbm5lcjpiYXNlLHN0b3J5X3N0eWxlX3NlbGVjdDpyYW5kLGVuYWJsZV9wbGF5cGFnZV9pbmxpbmVfd3hfanVtcDpleHBfMDQwOSxkY3ZyZl8yMDI1UTE6cmV2ZXJzZSxmcmVTOmJhc2UsYWR2dl9waWRfZml4OmJhc2UsQ3JlYXRpdmVRdWFsaXR5OmF1dG8sSW5kdXN0cnlCb29zdDpnYW1lbGl2ZSxmbHlfbTppY2ViZXJnX2Jhc2UsZWNwbV9jcm93ZHNfZmlsdGVyOnRlc3QsZ2Rfc2NoZV9yYXRpbzpiYXNlLHRlc3RfbWl4ZXJfY2NkOmJhc2Usa3Vha2VfbW9iaWxlX2FudG91X3BjOmFudG91X3BjLG5ld192aWRlb19ib29zdDpkZWZhdWx0LHVuZGVyZnJhbWVfdWVzY29yZTpiYXNlLEVBX2V4cDpjbG9zZV9lYV8xMjExLGFuY2hvckFwcERvd25sb2FkU3R5bGVFeHA6YmFzZSwyMzI0NDpiYXNlLFJUQV9ESVZJREVfRVhQX1RBR183MDM6cnRhX2RpdmlkZV9leHBfNzAzXzMsZHVhbmp1X21vZGVsX2N0cjpkZWZhdWx0LGNvbG9yX21hc2s6YmFzZSxwdl9hYTpleHBfMSxwY19jbGllbnRfbm9fYWQ6bm9fYWRfYmFzZSxwcm9nQ3JlYVQ6djEuMCxuZWdhdGl2ZV9zdHJhdGVneV90ZXN0OmJhc2UsZW5hYmxlTmF0aXZlRmVlZHNUb1N0b3J5OmV4cF9oYXJkLGx0dl9pbnNfbG9nOmJhc2UxMCxmbHlfYnVfdW5kZXJmcmFtZTpiYXNlLHNwcmluZ2Zlc3RpdmFsX3N0YWJpbGl0eV9pbmR1c3RyeTpiYXNlLGdpZl9leHA6YmFzZSxjYXNlX2ludmVyc3RpZ2F0ZTpiYXNlLHByZXJhbmtfc2RwYTp4c2RqXzAxMTcscmVzZXJ2ZV9wcmljZTpnc3BfYWxsLHBheV83ZF9udW06ZXhwX2dhbWVfMSx0aW1lRnJlcTpkZWZhdWx0LGZyZXFDaGVja0R1cGxpY2F0ZTpiYXNlLFJUQV9ESVZJREVfRVhQX1RBR183MjQ6cnRhX2RpdmlkZV9leHBfNzI0XzMsc3RvcnlGbHlNb2RlbENvbmY6YWRkX2VhX2V4cCxBcHBDb2V4aXN0RmlsdGVyOmNsb3NlLHVzdWFsX2FyZWFzOmJhc2UsYXBwU3RvcmVQcmlvcml0eVhpYW9ndW9BY2NvdW50SWRzOmJhc2UsbWFiaWRfZW5hYmxlOmJhc2VfMDEwOCxSVEFfRElWSURFX0VYUF9UQUdfODM2OnJ0YV9kaXZpZGVfZXhwXzgzNl8xMCxzb2Z0X2FkOjEyLHN0b3J5X3BsYXkzc190b3VjaF9yYXRpbzpyYXRpb18xMDAsZHVhbmp1X3JldGFyZ2V0OmJhc2UsUlRBX0RJVklERV9FWFBfVEFHXzEwMzc6cnRhX2RpdmlkZV9leHBfMTAzN181LGNhdGVnb3J5X3YzOmJhc2UsaWFhM19vdXRfdXBfYWRzOmV4cF9pYWFfb3V0X3VwLHByb2dDcmVhUmFuZG9tXzE6YmFzZV9tb2RlbDAzMTksZmx5X3lzYW50b3U6YmFzZV8wODIxLGZseV9jdHJfaW5saW5lX3RhcmdldDpjbG9zZSx0ZW1wbGF0ZV9maXg6YmFzZSxicmFuZER5bmFtaWNDYXJkSW5kZXhFeHA6ZXhwLGlubGluZUVjcG06ZGVmYXVsdCxmb3JjZUV4cG9zdXJlLWNhc3Npbmk6ZGFpaHVvX29wZW5fMjMxMTAxLHNwbGFzaF9uZXdfc3R5bGVfZmlsdGVyOmRlZmF1bHQsc2VhcmNoX3RyaXRvbjpiYXNlLGN2cl9mOmluZHVzdHJ5X29wdF9leHAsaW5uZXJfb3ZlcmxvYWRfY3RybDpkZWZhdWx0LHVnX3VuaXRfbGltaXQ6ZXhwLGNsZWFuX3Nsb3Q1MHA6ZXhwLG1lcmdlX2ZpbHRlcjplbmFibGVfc3luY19wcmltYXJ5X2ZpbHRlcixoeV9hcnB1X3JvdXRlX3NwbGl0OnN0YWxsX29yX3VuZGVsZXRlZF9mZWFzX2V4cCwxNTA2OmJhc2UsZ2RGZWVkc0VuYWJsZUJydXNoOmJhc2UsaW5saW5lX2Zsb3dfbm9fYWQ6YmFzZSxlbmFibGVfbGFuY2VyX3JlY29yZF9kbXNfZmVhdHVyZTowNDE0X3Rlc3QsdW5kZXJmcmFtZV9tYXJrX3N3dGljaDpleHAxXzA0MDksQWlFeHBQbGF5UGFnZTpiYXNlXzAsMjRoX3JvaV9hcnB1OmJhc2UzLG9wZW5QcmV2aWV3OmV4cDIsZ3NwX2V4cDpzZWFyY2hfZGVmYXVsdCxydW5uaW5nX29jcGM6YmFzZSxmbHlfcmFua19jb25mX21lcmdlOmJhc2UsbHRyQXBwTG9nOmNscyxzZWFyY2hfYWRzX3F1ZXJ5X3Jld3JpdGU6Y29tYmluZV9leHAxLHJhbmtfZGl2XzE6ZGVmYXVsdCx1bmRlcmZyYW1lX2Rvd25sb2FkX2FkYnV0dG9uOmJhc2UsQnNPZmZsaW5lTG9jYWxDcGFDb25maWdOZXc6ZGVmYXVsdCx1cFNwYWNlQ2hlY2tEaWZmUmF0aW9FeHA6ZXhwX21icyxzcGxhc2hfaW50ZXJmYWNlX2Rvd25ncmFkZTpiYXNlLGZvcmJpZGRlbl9kaXJlY3RfanVtcDpiYXNlLG1pbmlnYW1lX2JvbnVzX2V4cDpyZW1haW4sZW5hYmxlQXBwc3RvcmVEaXJlY3Q6ZXhwXzEsZnJlcV9pbmZvX3JvdXRpbmc6c2hqZF9zeWNwYl9mcmVxX3Rhc2tfY2x1c3Rlcl8xLHNlYXJjaF9hZHNfbWluX2JpZDpkZWZhdWx0LG9wZW5OZXdHZFByZXZpZXc6ZXhwLGRpc2FibGVfaWxsZWdhbF9vbmVfanVtcDpiYXNlLGNvYXJzZV9xdW90YV9jb250cm9sOmJhc2VfMDMyNCxmbHlfZHluYW1pY0FudG91OmJhc2UsQWlFeHBTdG9yeTpiYXNlLGRwYTJSZWNhbGw6Y2hvb3NlX3Byb2R1Y3RzX2Jhc2VfNTAsc2VhcmNoX25ld190YXJnZXRpbmc6YmFzZSxlbmFibGVfbW9kZWxfZGV0YWlsX3RyYWNrZXI6YmFzZSxEcGEyQ1ZSVGhyZXNob2xkOmpkX2N2cl8yMDAsY3RyX3RfZXhwOnQxLjAscGNTZWFyY2g6ZXhwLGVjb21fbWFpbl9zZWFyY2g65a+554Wn57uELGNvYXJzZTpjb2Fyc2VfY3ZyX25ld2NvbnYsZnJlcV9taWdyYXRlOmV4cF9lbmdpbmVfd2l0aF9zdHJpY3RfYnJ1c2g1LHN3aXRjaEJzUGdSZXFSYXRpbzpjbG9zZSxzZWFyY2hfcmVhbHRpbWVfdHJpZ2dlcjpjb25zdGFudCxBaUV4cEZlZWRzOmJhc2UsbWJzX3JlZmFjdG9yOmV4cDIsdWVzX3NlYXJjaDpkZWZhdWx0LHVuZGVyZnJhbWVfbXVsdGlfYWRzOmJhc2UsYWlnY19hbnRvdV9pbWFnZTpiYXNlXzAzMjYsbWl4ZXJfZnVzaW9uX2RpbWVuc2lvbjpnMixyb2xsb3V0X2xpc3R3aXNlX2Jpem1peGVyX2J1Z19maXg6YmFzZSx1c2VCc0ZpbmRhOmZpbmRhX3gsZmx5X3B1cF9lY3BtOmNvbnN0YW50LGZseV9jdHJfaW5saW5lOm1vZGVsLHRlc3RfcGVnYXN1c19wb3M6YmFzZSx0ZXN0X3N0b3J5X3BhY2s6ZXhwIDIsc3RvcnlfYWRsb2FkXzM6MTQsc2RwYV9kaXZlcnNpZnk6Y29uc3RhbnQyLG1pbmlfZ2FtZV9zY2VuZTpiYXNlLGN0cl9kaWx1Y19lbWJfbGF5ZXI6ZXhwcl9lbWJfZGlsdWMscm9pX2J4aWFveW91X25ldzpkZWZhdWx0LEluZHVzdHJ5Tm9UYXJnZXRGaWx0ZXJMYXllcjpleHAsY3JlYXRpdmVfYXZpZF90YWIzOmV4cF8wNTI3LHN0eWxlX2FiaWxpdHlfb2ZmbGluZTpiYXNlLHVuZGVyZnJhbWVfYnJhbmRfaGlnaDpiYXNlLGNyb3dkX2VjcGM6b3Blbl92Mix0c21fdjJfbGF5ZXI6YmFzZSxtaXhlcl9saXN0d2lzZV9wZWdhc3VzOmc1LHVzZUFzUGc6bWFpbl8yNDEyMjcsc3BsaXRfYnVja2V0OmJ1Y2tldF8zLGdsb2JhbF9yZXZlcnNlOmJhc2UscGxhdGZvcm06ZGVmYXVsdKABALIBICjf18utGMJMWQj0kF8utyJl8gRyHD1TIq1K6aKZR3vRugFCaHR0cHM6Ly9xcnNqLmJpbGlnYW1lLmNvbS9nY3h6L2g1Lz9zb3VyY2VGcm9tPTc3NyZzb3VyY2VUeXBlPWFkUHV0wgEA0gEA2AHQAeABAOgBAPABAIACAogCALgCAMACANACANgCAOoCAPACrIYl+AIAiAMGkgMAqAMAsAMAuAMAwgMAyAMX0gOWAXsiMTYiOiIxMjE1NDYwXzAiLCIxNyI6IjQzMzYiLCIxIjoiMTAxNzg0NjY0OTk1OTc0NzU4NCIsIjIiOiIxMjUyMzkzIiwiMyI6IjEyNTIzOTMiLCI2IjoiMTI1MjM5M18wIiwiMTIiOiI0MzM4IiwiMTMiOiIxMjE1NDYwIiwiMTQiOiI4ODciLCIxNSI6IjEzNjkifeADAOgDAPADAPoDBW90aGVyggQJbnVsbDpudWxsmAQAoAQAqgQECAAQBLAEAOIEwwE1Ni57InBzSWQiOjUyMTE4LCJ2MiI6IkFXVXMyZTBidEhmWTVCSzJ0LUQ0U3lNRGJtN2Z1SGIyYmlIREhsTnBjQlB1U2dVRzdLaW80dUkyNXlSdFJXQU5WUnRMbll1OVpxOElrdkVYZURfUmlER25BeTE0UV9CMlAtSzJmQ3pzMWZLQmY5WjZPUSJ9OzYzLnsicHNJZCI6NTIwNjYsInYyIjoiUWcifTs3MC57InBzSWQiOjUwMDQxLCJ2MiI6IktBIn2gBQDIBQPSBQA=", + "client_ip": "182.89.224.34", + "server_type": 1, + "resource_id": 4336, + "index": 2, + "cm_mark": 1, + "extra": { + "use_ad_web_v2": false, + "show_urls": [ + "" + ], + "click_urls": [], + "download_whitelist": [], + "card": { + "card_type": 0, + "title": "今日全球首发,千件外观福利免费领", + "covers": [ + { + "url": "https://i0.hdslb.com/bfs/sycp/creative_img/202504/bbd7cc4e6a74508e9ccee467541cc06a.jpg", + "loop": 0, + "image_height": 0, + "image_width": 0, + "gif_tag_show": false, + "jump_url": "", + "title": "", + "desc": "" + } + ], + "jump_url": "https://qrsj.biligame.com/gcxz/h5/?sourceFrom=777&sourceType=adPut", + "desc": "", + "callup_url": "", + "long_desc": "", + "ad_tag": "", + "extra_desc": "", + "universal_app": "", + "duration": "", + "adver": { + "adver_id": 1252393, + "adver_type": 3 + }, + "extreme_team_status": false, + "support_transition": false, + "under_player_interaction_style": 0, + "referral_pop_active_time": 10000, + "grade_denominator": 0, + "star_level": 0, + "live_booking_population_threshold": 0, + "ori_mark_hidden": 0, + "use_multi_cover": false, + "custom_feedback_panels": [], + "yellow_cart_pannel_pullup": 0, + "yellow_cart_pannel_version": 0, + "goods_item_id": 0, + "story_interaction_style": 0, + "videos": [], + "download_area": 0, + "goods_pannel_show": 0, + "goods_panel_show": 0, + "show_pop_window": 0, + "search_show_adbutton": 0, + "jump_interaction_style": 0, + "live_page_type": 0, + "ad_tag_style": { + "type": 4, + "text": "", + "text_color": "", + "bg_border_color": "", + "bg_color": "", + "border_color": "", + "img_url": "https://i0.hdslb.com/bfs/sycp/mng/202408/34463051f8d45a6d3c20f8aff31aad9b.png", + "img_height": 48, + "img_width": 72 + }, + "feedback_panel": { + "panel_type_text": "广告", + "feedback_panel_detail": [], + "toast": "将减少相似广告推荐", + "close_rec_tips": "操作成功", + "open_rec_tips": "将减少展示此类广告" + }, + "fold_time": 0, + "live_room_popularity": 0, + "live_tag_show": false, + "quality_infos": [], + "dynamic_text": "今日全球首发,千件外观福利免费领", + "choose_button_list": [], + "grade_level": 0, + "anim_in_enable": 0, + "underframe_card_style": 0, + "playpage_card_style": 0, + "live_auto_play": false, + "original_style_level": 0, + "live_card_show": false, + "enable_tag_move_up": 0, + "item_source": 0, + "closed_loop_item": 0, + "desc_type": 0, + "comment_use_game_page": 0, + "story_takeoff_interaction_style": 0 + }, + "report_time": 2000, + "sales_type": 31, + "special_industry": false, + "preload_landingpage": 0, + "enable_share": true, + "share_info": { + "title": "今日全球首发,千件外观福利免费领", + "subtitle": "", + "image_url": "https://i0.hdslb.com/bfs/sycp/creative_img/202504/3eba2979cb9525f14633a39c9f2ec2ab.jpg" + }, + "upzone_entrance_type": 0, + "upzone_entrance_report_id": 0, + "click_area": 0, + "shop_id": 0, + "up_mid": 0, + "track_id": "pbaes.DXUvRhr8IAhiFZ60KoOBStL0Na80m-kKS6CwFKDBtlzOwGJZu7il0VbEU3j2A_dZ96EXDGonAHs9Qx-5X2XbovyGP-xL4lyr_c_3rDZs4q3frmVjEGhu2VPOE5MRHF3AdryKsZiIGCl_f6ZD0y-cNQ==", + "enable_store_direct_launch": 0, + "enable_double_jump": false, + "from_track_id": "all_49.router-pegasus-2021478-7d7955f987-td5kj.1745482993998.1007", + "store_callup_card": false, + "enable_h5_alert": false, + "special_industry_style": 0, + "macro_replace_priority": 1, + "feedback_panel_style": 0, + "ad_content_type": 0, + "enable_h5_pre_load": 0, + "hot_activity_id": 0, + "middle_show_urls": [], + "middle_click_urls": [], + "product_id": 0, + "landingpage_download_style": 2, + "download_url_type": 0, + "enable_auto_callup": 0, + "top_live_stay_time_seconds": 0, + "vipshop_fast_framework": 0, + "lottery_id": 0, + "enable_openapk_dialog": false, + "user_cancel_jump_type": 0, + "comment_toast_open": 0, + "comment_biz_type": 0, + "app_exp_params": "{\"pegasus_live_inline_background_fill\":0,\"story_live_goods_card_style\":{\"first_type\":1,\"second_type\":2,\"delay_time\":3000}}" + } + } +} +``` + +为普通视频时 则对应最开始的视频类型 也就是 + +```json +{ + "card_type": "small_cover_v2", + "card_goto": "av", + "goto": "av", + "param": "114375012651120", + "cover": "http://i1.hdslb.com/bfs/archive/05ec862caac777f9d7d06175becf0413b9c653ee.jpg", + "title": "「小白」红米Turbo 4 Pro 性能体验:首台8sGen4量产机表现如何?", + "uri": "bilibili://video/114375012651120?cid=29550644277&player_height=1890&player_preload=%7B%22expire_time%22%3A1745486594%2C%22cid%22%3A29550644277%2C%22quality%22%3A32%2C%22file_info%22%3A%7B%2216%22%3A%7B%22infos%22%3A%5B%7B%22filesize%22%3A2121663%2C%22timelength%22%3A230900%7D%5D%7D%2C%2232%22%3A%7B%22infos%22%3A%5B%7B%22filesize%22%3A3606019%2C%22timelength%22%3A230900%7D%5D%7D%2C%2264%22%3A%7B%22infos%22%3A%5B%7B%22filesize%22%3A6733527%2C%22timelength%22%3A230900%7D%5D%7D%2C%2280%22%3A%7B%22infos%22%3A%5B%7B%22filesize%22%3A10362311%2C%22timelength%22%3A230900%7D%5D%7D%7D%2C%22video_codecid%22%3A7%2C%22video_project%22%3Atrue%2C%22dash%22%3A%7B%22video%22%3A%5B%7B%22id%22%3A32%2C%22base_url%22%3A%22http%3A%2F%2F123.184.35.33%3A8000%2Fv1%2Fresource%2F29550644277-1-100047.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D125426%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mcdnid%3D50007224%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dcos%5Cu0026oi%3D3059343394%5Cu0026orderid%3D0%252C3%5Cu0026os%3Dmcdn%5Cu0026platform%3Dandroid%5Cu0026sign%3D158098%5Cu0026tag%3D%5Cu0026traceid%3DtrANPsmzTXNczh_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Ctag%252Cnbs%252Coi%252Cplatform%252Ctrid%252Cmid%252Cdeadline%252Cuipk%252Cgen%252Cos%252Cog%5Cu0026upsig%3Df6ea272dedd17383c1a7c43a39471036%22%2C%22bandwidth%22%3A124895%2C%22codecid%22%3A7%2C%22size%22%3A3606019%2C%22frame_rate%22%3A%2224.991%22%2C%22backup_url%22%3A%5B%22http%3A%2F%2F211.141.224.92%3A4480%2Fupgcxcode%2F77%2F42%2F29550644277%2F29550644277-1-100047.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026tag%3D%5Cu0026nbs%3D1%5Cu0026oi%3D3059343394%5Cu0026platform%3Dandroid%5Cu0026trid%3D000056fb961696ed4d6bb208acb9ce431b1U%5Cu0026mid%3D479396940%5Cu0026deadline%3D1745490194%5Cu0026uipk%3D5%5Cu0026gen%3Dplayurlv3%5Cu0026os%3Dmcdn%5Cu0026og%3Dcos%5Cu0026upsig%3Df6ea272dedd17383c1a7c43a39471036%5Cu0026uparams%3De%2Ctag%2Cnbs%2Coi%2Cplatform%2Ctrid%2Cmid%2Cdeadline%2Cuipk%2Cgen%2Cos%2Cog%5Cu0026mcdnid%3D50007224%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D125426%5Cu0026build%3D8410300%5Cu0026dl%3D0%5Cu0026f%3DU_0_0%5Cu0026agrr%3D1%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026orderid%3D0%2C3%22%2C%22http%3A%2F%2Fupos-sz-estgoss.bilivideo.com%2Fupgcxcode%2F77%2F42%2F29550644277%2F29550644277-1-100047.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026tag%3D%5Cu0026gen%3Dplayurlv3%5Cu0026os%3Dupos%5Cu0026og%3Dcos%5Cu0026trid%3D56fb961696ed4d6bb208acb9ce431b1U%5Cu0026mid%3D479396940%5Cu0026deadline%3D1745490194%5Cu0026nbs%3D1%5Cu0026oi%3D3059343394%5Cu0026uipk%3D5%5Cu0026platform%3Dandroid%5Cu0026upsig%3D464e03491d78d3249012e6c9affbb768%5Cu0026uparams%3De%2Ctag%2Cgen%2Cos%2Cog%2Ctrid%2Cmid%2Cdeadline%2Cnbs%2Coi%2Cuipk%2Cplatform%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D125426%5Cu0026agrr%3D1%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026build%3D8410300%5Cu0026dl%3D0%5Cu0026f%3DU_0_0%5Cu0026orderid%3D1%2C3%22%5D%2C%22audio_id%22%3A30216%7D%2C%7B%22id%22%3A32%2C%22base_url%22%3A%22http%3A%2F%2F59.47.230.23%3A8000%2Fv1%2Fresource%2F29550644277-1-30033.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D131973%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mcdnid%3D50007224%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dcos%5Cu0026oi%3D3059343394%5Cu0026orderid%3D0%252C3%5Cu0026os%3Dmcdn%5Cu0026platform%3Dandroid%5Cu0026sign%3D2d5ae2%5Cu0026tag%3D%5Cu0026traceid%3DtrQICyqgrXBqnY_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Cnbs%252Coi%252Cuipk%252Cmid%252Cdeadline%252Cog%252Cplatform%252Ctrid%252Ctag%252Cgen%252Cos%5Cu0026upsig%3D855d6f99090897394e531af9d9cc6dc8%22%2C%22bandwidth%22%3A131411%2C%22codecid%22%3A12%2C%22size%22%3A3794237%2C%22frame_rate%22%3A%2224.991%22%2C%22backup_url%22%3A%5B%22http%3A%2F%2F122.191.18.170%3A8000%2Fv1%2Fresource%2F29550644277-1-30033.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D131973%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dcos%5Cu0026oi%3D3059343394%5Cu0026orderid%3D1%252C3%5Cu0026os%3Dcoso1bv%5Cu0026platform%3Dandroid%5Cu0026sign%3D2d5ae2%5Cu0026tag%3D%5Cu0026traceid%3DtrxqpZsZboLcyN_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Cuipk%252Cplatform%252Ctag%252Cos%252Cog%252Cnbs%252Coi%252Ctrid%252Cmid%252Cdeadline%252Cgen%5Cu0026upsig%3D42f974aacd3f2a9a6ba659f11e469614%22%2C%22http%3A%2F%2F211.141.224.92%3A4480%2Fupgcxcode%2F77%2F42%2F29550644277%2F29550644277-1-30033.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026nbs%3D1%5Cu0026oi%3D3059343394%5Cu0026uipk%3D5%5Cu0026mid%3D479396940%5Cu0026deadline%3D1745490194%5Cu0026og%3Dcos%5Cu0026platform%3Dandroid%5Cu0026trid%3D000056fb961696ed4d6bb208acb9ce431b1U%5Cu0026tag%3D%5Cu0026gen%3Dplayurlv3%5Cu0026os%3Dmcdn%5Cu0026upsig%3D855d6f99090897394e531af9d9cc6dc8%5Cu0026uparams%3De%2Cnbs%2Coi%2Cuipk%2Cmid%2Cdeadline%2Cog%2Cplatform%2Ctrid%2Ctag%2Cgen%2Cos%5Cu0026mcdnid%3D50007224%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D131973%5Cu0026build%3D8410300%5Cu0026dl%3D0%5Cu0026f%3DU_0_0%5Cu0026agrr%3D1%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026orderid%3D0%2C3%22%5D%2C%22audio_id%22%3A30216%7D%5D%2C%22audio%22%3A%5B%7B%22id%22%3A30216%2C%22base_url%22%3A%22http%3A%2F%2F121.31.234.218%3A8000%2Fv1%2Fresource%2F29550644277-1-30216.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D43505%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mcdnid%3D50007224%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dhw%5Cu0026oi%3D3059343394%5Cu0026orderid%3D0%252C3%5Cu0026os%3Dmcdn%5Cu0026platform%3Dandroid%5Cu0026sign%3Db0263a%5Cu0026tag%3D%5Cu0026traceid%3DtrDHNJjmfaaueG_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Cplatform%252Ctrid%252Cmid%252Cdeadline%252Cnbs%252Cgen%252Coi%252Cuipk%252Ctag%252Cos%252Cog%5Cu0026upsig%3De92887e43514a81bad4594c670c509d1%22%2C%22bandwidth%22%3A43292%2C%22size%22%3A1250775%2C%22backup_url%22%3A%5B%22http%3A%2F%2F211.141.225.131%3A8000%2Fv1%2Fresource%2F29550644277-1-30216.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D43505%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dhw%5Cu0026oi%3D3059343394%5Cu0026orderid%3D1%252C3%5Cu0026os%3D08hbv%5Cu0026platform%3Dandroid%5Cu0026sign%3Db0263a%5Cu0026tag%3D%5Cu0026traceid%3DtrnTeKCShifUBc_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Cgen%252Cog%252Cdeadline%252Ctag%252Cnbs%252Cplatform%252Ctrid%252Cos%252Cmid%252Coi%252Cuipk%5Cu0026upsig%3D313f602e2d41ebe9637a95fc20bceb93%22%2C%22http%3A%2F%2F211.141.224.92%3A4480%2Fupgcxcode%2F77%2F42%2F29550644277%2F29550644277-1-30216.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026platform%3Dandroid%5Cu0026trid%3D000056fb961696ed4d6bb208acb9ce431b1U%5Cu0026mid%3D479396940%5Cu0026deadline%3D1745490194%5Cu0026nbs%3D1%5Cu0026gen%3Dplayurlv3%5Cu0026oi%3D3059343394%5Cu0026uipk%3D5%5Cu0026tag%3D%5Cu0026os%3Dmcdn%5Cu0026og%3Dhw%5Cu0026upsig%3De92887e43514a81bad4594c670c509d1%5Cu0026uparams%3De%2Cplatform%2Ctrid%2Cmid%2Cdeadline%2Cnbs%2Cgen%2Coi%2Cuipk%2Ctag%2Cos%2Cog%5Cu0026mcdnid%3D50007224%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D43505%5Cu0026f%3DU_0_0%5Cu0026agrr%3D1%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026build%3D8410300%5Cu0026dl%3D0%5Cu0026orderid%3D0%2C3%22%5D%7D%2C%7B%22id%22%3A30280%2C%22base_url%22%3A%22http%3A%2F%2F211.97.94.165%3A8000%2Fv1%2Fresource%2F29550644277-1-30280.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D43504%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mcdnid%3D50007224%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dcos%5Cu0026oi%3D3059343394%5Cu0026orderid%3D0%252C3%5Cu0026os%3Dmcdn%5Cu0026platform%3Dandroid%5Cu0026sign%3D3f3ed4%5Cu0026tag%3D%5Cu0026traceid%3DtrQHmKzoFdDeCw_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Cuipk%252Ctag%252Cnbs%252Cgen%252Cos%252Cog%252Coi%252Cplatform%252Ctrid%252Cmid%252Cdeadline%5Cu0026upsig%3D808cd1429841f75b1ccd7ccdc5de7bc3%22%2C%22bandwidth%22%3A43292%2C%22size%22%3A1250767%2C%22backup_url%22%3A%5B%22http%3A%2F%2F123.184.35.19%3A8000%2Fv1%2Fresource%2F29550644277-1-30280.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D43504%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dcos%5Cu0026oi%3D3059343394%5Cu0026orderid%3D1%252C3%5Cu0026os%3Dupos%5Cu0026platform%3Dandroid%5Cu0026sign%3D3f3ed4%5Cu0026tag%3D%5Cu0026traceid%3DtrtSntUkmmkWVz_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Cplatform%252Ctag%252Cnbs%252Cog%252Ctrid%252Cmid%252Cdeadline%252Coi%252Cuipk%252Cgen%252Cos%5Cu0026upsig%3D070e2e2176dd7e2d87777b20161c8d1f%22%2C%22http%3A%2F%2F211.141.224.92%3A4480%2Fupgcxcode%2F77%2F42%2F29550644277%2F29550644277-1-30280.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026uipk%3D5%5Cu0026tag%3D%5Cu0026nbs%3D1%5Cu0026gen%3Dplayurlv3%5Cu0026os%3Dmcdn%5Cu0026og%3Dcos%5Cu0026oi%3D3059343394%5Cu0026platform%3Dandroid%5Cu0026trid%3D000056fb961696ed4d6bb208acb9ce431b1U%5Cu0026mid%3D479396940%5Cu0026deadline%3D1745490194%5Cu0026upsig%3D808cd1429841f75b1ccd7ccdc5de7bc3%5Cu0026uparams%3De%2Cuipk%2Ctag%2Cnbs%2Cgen%2Cos%2Cog%2Coi%2Cplatform%2Ctrid%2Cmid%2Cdeadline%5Cu0026mcdnid%3D50007224%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D43504%5Cu0026dl%3D0%5Cu0026f%3DU_0_0%5Cu0026agrr%3D1%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026build%3D8410300%5Cu0026orderid%3D0%2C3%22%5D%7D%2C%7B%22id%22%3A30232%2C%22base_url%22%3A%22http%3A%2F%2F125.106.124.64%3A8000%2Fv1%2Fresource%2F29550644277-1-30232.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D43504%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mcdnid%3D50007224%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dhw%5Cu0026oi%3D3059343394%5Cu0026orderid%3D0%252C3%5Cu0026os%3Dmcdn%5Cu0026platform%3Dandroid%5Cu0026sign%3D3ad163%5Cu0026tag%3D%5Cu0026traceid%3DtrsSvqSMaoCcOa_1_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Ctag%252Cuipk%252Cgen%252Cos%252Cog%252Ctrid%252Cmid%252Cdeadline%252Cnbs%252Coi%252Cplatform%5Cu0026upsig%3D219bdbd1641753ddc8555f788bc21711%22%2C%22bandwidth%22%3A43292%2C%22size%22%3A1250767%2C%22backup_url%22%3A%5B%22http%3A%2F%2F220.200.12.159%3A5889%2Fv1%2Fresource%2F29550644277-1-30232.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D43504%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dhw%5Cu0026oi%3D3059343394%5Cu0026orderid%3D1%252C3%5Cu0026os%3D08hbv%5Cu0026platform%3Dandroid%5Cu0026sign%3D3ad163%5Cu0026tag%3D%5Cu0026traceid%3DtrQVqwCtxAuTKK_2_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Ctag%252Coi%252Ctrid%252Cdeadline%252Cgen%252Cos%252Cnbs%252Cuipk%252Cplatform%252Cmid%252Cog%5Cu0026upsig%3Dc45e0be8a46a1b1456b066fc447dcf4a%22%2C%22http%3A%2F%2F211.141.224.92%3A4480%2Fupgcxcode%2F77%2F42%2F29550644277%2F29550644277-1-30232.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026tag%3D%5Cu0026uipk%3D5%5Cu0026gen%3Dplayurlv3%5Cu0026os%3Dmcdn%5Cu0026og%3Dhw%5Cu0026trid%3D000056fb961696ed4d6bb208acb9ce431b1U%5Cu0026mid%3D479396940%5Cu0026deadline%3D1745490194%5Cu0026nbs%3D1%5Cu0026oi%3D3059343394%5Cu0026platform%3Dandroid%5Cu0026upsig%3D219bdbd1641753ddc8555f788bc21711%5Cu0026uparams%3De%2Ctag%2Cuipk%2Cgen%2Cos%2Cog%2Ctrid%2Cmid%2Cdeadline%2Cnbs%2Coi%2Cplatform%5Cu0026mcdnid%3D50007224%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D43504%5Cu0026f%3DU_0_0%5Cu0026agrr%3D1%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026build%3D8410300%5Cu0026dl%3D0%5Cu0026orderid%3D0%2C3%22%5D%7D%5D%7D%2C%22fnval%22%3A272%2C%22accept_formats%22%3A%5B%7B%22quality%22%3A116%2C%22format%22%3A%22flv_p60%22%2C%22description%22%3A%22%E9%AB%98%E6%B8%85%201080P60%22%2C%22new_description%22%3A%221080P%2060%E5%B8%A7%22%2C%22display_desc%22%3A%221080P%22%2C%22superscript%22%3A%2260%E5%B8%A7%22%2C%22need_vip%22%3Atrue%2C%22need_login%22%3Atrue%7D%2C%7B%22quality%22%3A80%2C%22format%22%3A%22flv%22%2C%22description%22%3A%22%E9%AB%98%E6%B8%85%201080P%22%2C%22new_description%22%3A%221080P%20%E9%AB%98%E6%B8%85%22%2C%22display_desc%22%3A%221080P%22%2C%22need_login%22%3Atrue%7D%2C%7B%22quality%22%3A64%2C%22format%22%3A%22flv720%22%2C%22description%22%3A%22%E9%AB%98%E6%B8%85%20720P%22%2C%22new_description%22%3A%22720P%20%E5%87%86%E9%AB%98%E6%B8%85%22%2C%22display_desc%22%3A%22720P%22%2C%22need_login%22%3Atrue%7D%2C%7B%22quality%22%3A32%2C%22format%22%3A%22flv480%22%2C%22description%22%3A%22%E6%B8%85%E6%99%B0%20480P%22%2C%22new_description%22%3A%22480P%20%E6%A0%87%E6%B8%85%22%2C%22display_desc%22%3A%22480P%22%7D%2C%7B%22quality%22%3A16%2C%22format%22%3A%22mp4%22%2C%22description%22%3A%22%E6%B5%81%E7%95%85%20360P%22%2C%22new_description%22%3A%22360P%20%E6%B5%81%E7%95%85%22%2C%22display_desc%22%3A%22360P%22%7D%5D%2C%22volume%22%3A%7B%22measured_i%22%3A-18.2%2C%22measured_lra%22%3A5.9%2C%22measured_tp%22%3A-1.3%2C%22measured_threshold%22%3A-28.3%2C%22target_offset%22%3A0.5%2C%22target_i%22%3A-14%2C%22target_tp%22%3A-1%2C%22multi_scene_args%22%3A%7B%22high_dynamic_target_i%22%3A%22-24%22%2C%22normal_target_i%22%3A%22-14%22%2C%22undersized_target_i%22%3A%22-28%22%7D%7D%2C%22union_player%22%3A%7B%22biz_type%22%3A1%2C%22dimension%22%3A%7B%22width%22%3A4096%2C%22height%22%3A1890%7D%2C%22aid%22%3A114375012651120%7D%2C%22auto_qn_ctl%22%3A%7B%22login_half%22%3A32%2C%22nologin_half%22%3A32%2C%22login_full%22%3A80%2C%22nologin_full%22%3A32%2C%22mobile_login_full%22%3A80%2C%22mobile_nologin_full%22%3A32%7D%2C%22qn_exp%22%3A%7B%22qn_exp_1%22%3Atrue%7D%7D&player_rotate=0&player_width=4096&report_flow_data=%7B%22flow_card_type%22%3A%22av%22%2C%22flow_source%22%3A%22click_u2i%24ann_dssm_u2i_28d%24dssm_u2u%22%7D&trackid=all_49.router-pegasus-2021478-7d7955f987-td5kj.1745482993998.1007" + ... +} +``` + +**示例:** + +获取短视频模式视频列表 + +```shell +curl -G 'https://app.bilibili.com/x/v2/feed/index' +``` + +
+查看响应示例: + +```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 + } +} +``` + +
+ +
+查看登录后的响应示例(精简 包含横幅 热门视频 普通视频): + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "items": [ + { + "card_type": "banner_v8", + "card_goto": "banner", + "args": {}, + "idx": 1745482992, + "track_id": "all_49.router-pegasus-2021478-7d7955f987-td5kj.1745482993998.1007", + "hash": "4708571670781279769", + "banner_item": [ + { + "type": "static", + "resource_id": 4336, + "id": 1674508, + "index": 1, + "static_banner": { + "id": 1674508, + "title": "火凤燎原第二季完结!新的战神,来了!", + "image": "http://i0.hdslb.com/bfs/banner/b1fc0b68f727c2d4ea57bee154f531c3b7f13fca.png", + "hash": "a6cee3b5b1c05227159f734f68289ba5", + "uri": "https://www.bilibili.com/bangumi/play/ep1365959?goto=static_banner", + "request_id": "1745482994326q172a27a87a21q3087", + "src_id": 4337, + "is_ad_loc": true, + "client_ip": "182.89.224.34", + "server_type": 0, + "resource_id": 4336, + "index": 1, + "cm_mark": 0 + } + }, + { + "type": "ad", + "resource_id": 4336, + "id": 0, + "index": 2, + "ad_banner": { + "id": 0, + "title": "今日全球首发,千件外观福利免费领", + "image": "https://i0.hdslb.com/bfs/sycp/creative_img/202504/bbd7cc4e6a74508e9ccee467541cc06a.jpg", + "hash": "46cbecfe04e047692acfd4a149e81ebd", + "uri": "https://qrsj.biligame.com/gcxz/h5/?sourceFrom=777&sourceType=adPut", + "request_id": "1745482994326q172a27a87a21q3087", + "creative_id": 1017846649959747584, + "src_id": 4338, + "is_ad": true, + "is_ad_loc": true, + "ad_cb": "CAAQABiAoLC1qsSHkA4gACgAMKm4TDjyIUIfMTc0NTQ4Mjk5NDMyNnExNzJhMjdhODdhMjFxMzA4N0iWpZO35jJSBuafs+W3nloG5bm/6KW/YgbkuK3lm71oAXAAeICAgICAGoABAIgBpYgEkgENMTgyLjg5LjIyNC4zNJoBj0BjcGNfcXVvdGE6Y29uc3RhbnQsZWNvbV9mb3JjZV9yZWNhbGw6YmFzZV8wNjI4XzIwLGJyYW5kX3NwbGFzaF9saXN0X2J5X3RpbWU6YnJhbmRfc3BsYXNoX2xpc3RfYnlfdGltZV80MF90dW5uZWwsdWVzX2VycWk6MTcsamtfY2FydDpqazEsZmVlZHNQcmltYXJ5TW9kZWxDb25mOmJzbDIsY29tbWVudENvbXBvbmVudEFudG91UmF0aW86YmFzZSxTbWFsbEJ1ZGdldFJhdGlvOmRlZmF1bHQsc2VhcmNoX2Fkc19jcmVhdGl2ZTpsbG1fZXhwMSxkYWlodW9fYm9vc3RfZXhwOmJvb3N0X2V4cCxzZWFyY2hfYWRzX3JlbGV2YW5jZTp0b3BfYmxhY2tsaXN0X2NhbGksc3BsYXNoX2lubmVyX291dGVyX2V4cDpiYXNlLGNjZF9leHBfZGVtbzpjY2RfYmFzZSxmcmVxUm91dGluZzpiYXNlLHZpZGVvX3RlbXBsYXRlX3N1cHBvcnQ6ZXhwMyxpYWFfb25seV9lY3BtOjAwLHRlc3RfbW9kZWxfbmFtZTpiYXNlXzExLGZseV9qdW1wX2NvbW1lbnQ6ZXhwMyxsb2dnaW5nX2FkaW5mb19saXN0OmJhc2UsdXNlTmV3WWVsbG93Q2FydFBhbm5lbDpleHAyLGhpZ2hfcXVhbGl0eV9hdmlkX3R1cm5fYmFjazpiYXNlLG5ld19kaXJlY3RfYWRtaXNzaW9uX3YyOm9wZW5fc2hvdXRhb193dWR1YW4sdHJhZGVfcmVjYWxsOmRlZmF1bHQsb3R0X2VjcG1fdGhyZDpiYXNlLGVuYWJsZV9hbHRfZGF2aW5jaTpkZWZhdWx0LGlubmVyX291dGVyX2JpZF9leHA6bmV3X3JhbmtmcmFtZV8wNDAyLG9mZmxpbmVfbWlkX2ZlYV92MjpleHAzLGRjdnJfd29ybGRfMjAyNVEyOmJhc2UxLHVuZGVyZnJhbWVfcHVsbF91cDpleHAxLGVuYWJsZV9pbmR1c3RyeV92Ml9maWx0ZXI6YmFzZSxuRmVkQmFjazE6bG9vc2UsRHBhMlJ0YVBpY2tQcm9kdWN0OnNoYXJlZF8zMCxmaWx0ZXJfY2xlYW46YmFzZSxhY2NvdW50RnJlcUNvbmY6YmFzZSxtaW5pZ2FtZV9iaWRfZXhwOmV4cF8wMzA3LHN0b3J5X2RhaWh1b19zdHlsZTpleHAsbm9fYWdlX2dlbmRlcl9leHA6YWdlMCxvdHRjb25maWc6ZXhwXzE1LE1peGVyRUNvbW1lcmNlOmVuYWJsZSxzc3BEaXJlY3REaXNwYXRjaEFkVm9FeHA6ZXhwXzIscmlza3lfYWRfb3B0OmhpZGRlbl9jb3N0XzAsc0ZCcnU6MyxCaXpNaXhlclJvdXRlcjpiaXpfbWl4ZXJfcGcsMjUzOTkxOmJhc2UsdHNtdjJfdHJhZGU6YmFzZSxmbHlfZGVxOm9yZGVyX2xpdmUsdHNtXzE6ZWR1dGFnX3JlY2FsbF8wMjA2LHJldHJpZXZlX2xvZzpvcGVuLGdkX21vZGVsOmV4cDEsY3BhX3NlYXJjaDpjcGFfdjIsdHNtdjJfc3dpbmdmbHlfb3RoZXJzY2VuZTpiYXNlLGFkeF9yZXF1ZXN0X29wdGltaXphdGlvbl90ZXN0OmRlZmF1bHQsc3RfdnZfbW9kZWw6YmFzZSxicnVzaF9kdXA6ZGVmYXVsdCxzdG9yeV9saXZlX3Z2OmRlZixpbmxpbmVfemVyb19jYXJkX2luZGV4OmV4cCxyZXFfbG9nX3JhdGlvOmJhc2UsZHBhVW5kZXJmcmFtZU5ld1N0eWxlOmV4cDIsZHluYW1pY1RpbWVvdXRNaW5zOjI0MCxtb2RlbF9jYWxpOmV4cDEsZmx5X2NwY19jYWxpX25ldzpvcmRlcl9hY2NfZXhwLGVuYWJsZVNtYXJ0Q292ZXJVcmw6YmFzZV9hYV8wMTE1LG1pbmlfZ2FtZV9sb25nX3RpbWVfZmxpcF9leHA6ZXhwX2dyb3VwLHV2X2FhOmRlZmF1bHQsYWNjb3VudF9ibGFjazpiYXNlLGFzQ29tbWVudENoZWNrRGlmZlJhdGlvRXhwOmV4cDIsY3RyX21vZGVsOmV4cF8wMSxic0R1cEFkOm9wZW4sb3JkZXJfbGF4aW46bGF4aW5fYmFzZV92Ml8xLHByb2dDcmVhRmVlZEN0cjpkaXN0X2x0cix1bmlvbl9mbHlfY3BjOmV4cDAxMjQsQ3VzdG9tQ3JlYXRpdmVTZWxlY3RFeHA6a3Vhbmd4aWFfMDQwMixuZXdCc0ZpbHRlckxvZzpvcGVuLHNlYXJjaF9xdWlja19wbGFjZW1lbnQ6ZXhwMSxib29zdF9leHA6ZXhwMyx0c212Ml9tb2RlbF9yZWNhbGw6YmFzZSxjY2RfdWVzY29yZTpjY2RfYmFzZSxkQWR4MTpvcGVuLGRhbGFvX2NhcmRfb25seV90b3A6ZXhwLGNhc3NpbmlFeHA6c21hbGxfYnVkZ2V0X2Nsb3NlLHNwbGFzaF90d2lzdF9hbmdsZV9leHA6YmFzZSx0c212Ml9vdGhlcnM6YmFzZSxzcGxhc2hNaW5JbnRlcnZhbEV4cDpiYXNlXzFoLGR5bmFtaWNfaW5kZXg6YmFzZSxyZWNhbGxfbGltaXRfcmF0aW86YmFzZSxmbHlfY3BhOmZseV92MyxnYW9uZW5nX2FidGVzdDpiYXNlLHBFTjpQUixzZWFyY2hfY3RyX21vZGVsOmV4cF95LGxpdmVfY2FyZF90YWdfbW92ZTpleHAxXzAzMTgsYmVzdENyZWF0aXZlOmVjcG0yLHN0b3J5X3N0eWxlX3NlbGVjdF9jb25mOmJhc2UyMDI1MDIyNyxjbG9zZV9zcmNfZWZmOmV4cF8wNzI1X25vX3J1bGUsMTA3MjpiYXNlLHNvZnRfYWRfZXhwOjA2LGZseV9saWtlX3RoOmNsb3NlLG1peGVyX3N0b3J5X2FkX3dlaWdodDo2LGFpZ2NfYW50b3U6TFJfYmFzZV8yMDI1MDMxNCxqZzpleHAyLHBkY3ZyX3RocmVzaG9sZDpleHAxLGRjdnJfcmV0ZW50aW9uX25ldzpjb21ib19iYXNlLHBlZ2FzdXNfbWl4ZXI6MDEsZHBhMjpiYXNlLHVuZGVyX2ZyYW1lX2VjcG1fZXhwOmJhc2UsSW5kdXN0cnlFeGNsdWRlSW5mb0NvbmZfdjI6YmFzZSxlbmFibGVfdXNlcl9mZWF0dXJlX2J1Y2tldDpiYXNlbGluZSxlY29tX3JlY2FsbDpMSFVDX0IsZW5hYmxlVGFnTW92ZVVwOmV4cDRfbW92ZV90YWdfZGlzbGlrZWFkaixhZF9icmFuZF9nZF9lbmFibGVfZGlmZjpiYXNlLGZkX3BjdHI6YmFzZV8xLDI1NzM4OmJhc2UscHJvZ0NyZWFEaWN0VmVyOmRlZmF1bHQsc2VhcmNoX3BhcmFsbGVsX3JlcV9yZWRpczpleHAxLHByb2dyYW1DcmVhdGl2ZTpkZWZhdWx0LGRwczpkZWZhdWx0LHBhZF9pbm5lcl9hZGxvYWQ6YmFzZV8yMF8wLHVuZGVyZnJhbWVfcHVsbF91cF9uZXc6YmFzZV9hYWEsY29hcnNlRXhwbG9yZUZhY3RvckNvbmY6ZGVmYXVsdCxmbHlfc3RvcnlfeWVsbG93Y2FyX3N0eWxlOnlvdXh1YW5fYmFzZV9rZmMsZmx5X2NwYV9wYzpleHAxMCxEcGFTdnJQcmVzc3VyZTpiYXNlLGNwYTpiYXNlLGJvb3N0X2JzOmJhc2UsZmx5Q2FyZFF1YWxpdHk6ZXhwNCxhbGw6Y3BjX2Nyb3dkX3RhcmdldCxmbHlfY3BhX2JvdHRvbTpjbG9zZSxSVEFfRElWSURFX0VYUF9UQUdfODkyOnJ0YV9kaXZpZGVfZXhwXzg5Ml81LEluZHVzdHJ5THRyQ29hcnNlQ29uZjpnYW1lbGl2ZSxlZGdlX3JlcmFuazpiYXNlLFJUQV9ESVZJREVfRVhQX1RBR182NTc6cnRhX2RpdmlkZV9leHBfNjU3XzQsaGVhcnRfYm94OmV4cCwyMzUzMTpub3JtYWwscHVwX25hdGl2ZV9hZDpkZWZhdWx0LG90dF9lZHVjYXRpb25fYW50b3U6ZXhwLGg1X3Y6Y29tcGFyZSx1c2VMdWFTY3JpcHQ6YmFzZSxjb2Fyc2VfZGFpaHVvOmJhc2UsZmxvd1J1bGU6b3BlbkZsb3dSdWxlQ2hlY2tTd2l0Y2gsc3Rvcnlfc3R5bGVfc2VsZWN0aW9uX2NvbmY6YmFzZTIwMjQxMTI5LG5ld192aWRlb191cF9taWRfZmlsdGVyOmJhc2UsZmx5X2NvYXJzZTpjb25zdGFudCxkZWxldGVGcmVxQ29kZTpiYXNlMyxob25nZ3VvX25vdF9zaG93X2luX2NoYXJnaW5nX3BhZ2U6YmFzZSxEcGFDcmVhdGl2ZVN0cmF0ZWd5RXhwZXJpbWVudDpzZWFyY2hfbWVyZ2VfaW1hZ2VfZXhwLHNzcF9yZXBsYXlfYXM6YmFzZSxiZnNfc2RwYV9kaXZlcnNpZnk6cmVtYWluLHNlYXJjaF9zdWJjYXJkX3N0eWxlOmZvcm1fYnV0dG9uLGJzLXg6YnMsd2hpdGVfYm94OmNsb3NlLGR1YW5qdV9hcnB1OmFkZF9ub3ZlbF8wMzI3LE1vZGVsRmVhdHVyZXNIaXZlTG9nOmNsb3NlLGZseV9zdXBfZmFjdG9yczpleHAsY2x0cmNvbmY6YnNsMyxkYXZpbmNpX3JlcV9sb2c6ZGVmYXVsdCxmbHdfbGlrZV9lbmdhZ2U6YmFzZSxzdG9yeV9jdXN0b21pemVfZGFubXU6YmFzZSxhZHhQbGF5UGFnZVJhc2lvOmV4cDAsZHBhMlByb21vdGVQcm9kdWN0TWF0ZXJpYWw6YmFzZSxsaXZlX21vZGVsOmxpdmVfYmFzZV8wNDA4LHVzZUFpR2NUaXRsZTpiYXNlLHBlZ2FzdXNfYWRsb2FkXzM6MTQsbGFuY2VyX25hdHVyZTpleHAsc3RvcnlfZGFubXVfY29uZjpkYW5tdV9udW1fMzgsdHNtdjJfdG9rZW5fc2RwYTpiYXNlLDI0aF9yb2lfYXJwdV9uZXc6c3RhbGxfYmFzZV92MyxzcGxhc2hfaGFyZF9maWx0ZXJzOmV4cCxnYW1lX2VjcG1fcm9pX2ZhY3Rvcl9zd2l0Y2g6ZXhwX291dGVyLGJ1cGNwY19nc3A6ZGVmYXVsdCxuRmVkQmFjazpsb29zZSxVbml0RGV0YWlsSW5mbzpjbG9zZSzogIHkuInov57lub/lkYrlsY/olL06YmFzZSxnZF9mb3JjZV9zZWxlY3Q6ZXhwMixjb2xkX2Jvb3RfY2xlYXJfZnJlcTpiYXNlLGdhbWVfb3Blbl9pbnRlcmVzdF9vcmllbnRhdGlvbjpleHBfb3Blbl9ib3RoLGNsb3NlX3BlcnNvbmFsX3JlY29tbWVuZF8yMDI1OmV4cF9vcGVuX2FsbF8wMjI4LFJUQV9ESVZJREVfRVhQX1RBR183MzE6cnRhX2RpdmlkZV9leHBfNzMxXzMsbm9fYWRfc2V0OmJhc2UsUlRBX0RJVklERV9FWFBfVEFHXzg1NTpydGFfZGl2aWRlX2V4cF84NTVfNyxhY2NvdW50X2V4cGxvcmVfc2hvd19saW1pdDpkZWZhdWx0LGZseV9nb29kc19jb21tZW50X3VybDpibHVlbGlua19yZXBsYWNlXzA1LG9yZGVyX2xhcmdlOmRlbGF5MSxlY3BtX3RocmVzaG9sZF9sYXllcjowOCxyZWNhbGxfdW5pdF9saW1pdDpiYXNlLFJUQV9ESVZJREVfRVhQX1RBR182NDA6cnRhX2RpdmlkZV9leHBfNjQwXzE2LGRhaWh1b1doaXRlQ29uZjp3aGl0ZV8yNDEyMDJfNSxSVEFfRElWSURFX0VYUF9UQUdfODgzOnJ0YV9kaXZpZGVfZXhwXzg4M181LGVuYWJsZUlubGluZUV4cDpiYXNlLFJUQV9ESVZJREVfRVhQX1RBR184ODg6cnRhX2RpdmlkZV9leHBfODg4XzIsaWFhX3VuaXRfZWE6ZXhwMSxTbWFsbEJ1ZGdldFRvbGVyYXRlOmV4cF83MixhdXRvX2FkX2Fzc2lzdDpiYXNlLG1peGVyX2JyYW5kX29wdDpiYXNlLGxheWVyZWRfYmlkZGluZzpiYXNlMDkyMixzdG9yeVllbGxvd0NhcnROZXc6ZXhwX2Jhc2UyXzAyMTMseHN0X2NodWRpYW46YmFzZSxkdWFuanVfbW9kZWw6ZGVmYXVsdCxnZF9waWQ6ZXhwX3JlYWQsY3BjMV9leHRlbmRlZDpxdW90YV8xMCxicnVzaF9pbm5lcjpiYXNlLHN0b3J5X3N0eWxlX3NlbGVjdDpyYW5kLGVuYWJsZV9wbGF5cGFnZV9pbmxpbmVfd3hfanVtcDpleHBfMDQwOSxkY3ZyZl8yMDI1UTE6cmV2ZXJzZSxmcmVTOmJhc2UsYWR2dl9waWRfZml4OmJhc2UsQ3JlYXRpdmVRdWFsaXR5OmF1dG8sSW5kdXN0cnlCb29zdDpnYW1lbGl2ZSxmbHlfbTppY2ViZXJnX2Jhc2UsZWNwbV9jcm93ZHNfZmlsdGVyOnRlc3QsZ2Rfc2NoZV9yYXRpbzpiYXNlLHRlc3RfbWl4ZXJfY2NkOmJhc2Usa3Vha2VfbW9iaWxlX2FudG91X3BjOmFudG91X3BjLG5ld192aWRlb19ib29zdDpkZWZhdWx0LHVuZGVyZnJhbWVfdWVzY29yZTpiYXNlLEVBX2V4cDpjbG9zZV9lYV8xMjExLGFuY2hvckFwcERvd25sb2FkU3R5bGVFeHA6YmFzZSwyMzI0NDpiYXNlLFJUQV9ESVZJREVfRVhQX1RBR183MDM6cnRhX2RpdmlkZV9leHBfNzAzXzMsZHVhbmp1X21vZGVsX2N0cjpkZWZhdWx0LGNvbG9yX21hc2s6YmFzZSxwdl9hYTpleHBfMSxwY19jbGllbnRfbm9fYWQ6bm9fYWRfYmFzZSxwcm9nQ3JlYVQ6djEuMCxuZWdhdGl2ZV9zdHJhdGVneV90ZXN0OmJhc2UsZW5hYmxlTmF0aXZlRmVlZHNUb1N0b3J5OmV4cF9oYXJkLGx0dl9pbnNfbG9nOmJhc2UxMCxmbHlfYnVfdW5kZXJmcmFtZTpiYXNlLHNwcmluZ2Zlc3RpdmFsX3N0YWJpbGl0eV9pbmR1c3RyeTpiYXNlLGdpZl9leHA6YmFzZSxjYXNlX2ludmVyc3RpZ2F0ZTpiYXNlLHByZXJhbmtfc2RwYTp4c2RqXzAxMTcscmVzZXJ2ZV9wcmljZTpnc3BfYWxsLHBheV83ZF9udW06ZXhwX2dhbWVfMSx0aW1lRnJlcTpkZWZhdWx0LGZyZXFDaGVja0R1cGxpY2F0ZTpiYXNlLFJUQV9ESVZJREVfRVhQX1RBR183MjQ6cnRhX2RpdmlkZV9leHBfNzI0XzMsc3RvcnlGbHlNb2RlbENvbmY6YWRkX2VhX2V4cCxBcHBDb2V4aXN0RmlsdGVyOmNsb3NlLHVzdWFsX2FyZWFzOmJhc2UsYXBwU3RvcmVQcmlvcml0eVhpYW9ndW9BY2NvdW50SWRzOmJhc2UsbWFiaWRfZW5hYmxlOmJhc2VfMDEwOCxSVEFfRElWSURFX0VYUF9UQUdfODM2OnJ0YV9kaXZpZGVfZXhwXzgzNl8xMCxzb2Z0X2FkOjEyLHN0b3J5X3BsYXkzc190b3VjaF9yYXRpbzpyYXRpb18xMDAsZHVhbmp1X3JldGFyZ2V0OmJhc2UsUlRBX0RJVklERV9FWFBfVEFHXzEwMzc6cnRhX2RpdmlkZV9leHBfMTAzN181LGNhdGVnb3J5X3YzOmJhc2UsaWFhM19vdXRfdXBfYWRzOmV4cF9pYWFfb3V0X3VwLHByb2dDcmVhUmFuZG9tXzE6YmFzZV9tb2RlbDAzMTksZmx5X3lzYW50b3U6YmFzZV8wODIxLGZseV9jdHJfaW5saW5lX3RhcmdldDpjbG9zZSx0ZW1wbGF0ZV9maXg6YmFzZSxicmFuZER5bmFtaWNDYXJkSW5kZXhFeHA6ZXhwLGlubGluZUVjcG06ZGVmYXVsdCxmb3JjZUV4cG9zdXJlLWNhc3Npbmk6ZGFpaHVvX29wZW5fMjMxMTAxLHNwbGFzaF9uZXdfc3R5bGVfZmlsdGVyOmRlZmF1bHQsc2VhcmNoX3RyaXRvbjpiYXNlLGN2cl9mOmluZHVzdHJ5X29wdF9leHAsaW5uZXJfb3ZlcmxvYWRfY3RybDpkZWZhdWx0LHVnX3VuaXRfbGltaXQ6ZXhwLGNsZWFuX3Nsb3Q1MHA6ZXhwLG1lcmdlX2ZpbHRlcjplbmFibGVfc3luY19wcmltYXJ5X2ZpbHRlcixoeV9hcnB1X3JvdXRlX3NwbGl0OnN0YWxsX29yX3VuZGVsZXRlZF9mZWFzX2V4cCwxNTA2OmJhc2UsZ2RGZWVkc0VuYWJsZUJydXNoOmJhc2UsaW5saW5lX2Zsb3dfbm9fYWQ6YmFzZSxlbmFibGVfbGFuY2VyX3JlY29yZF9kbXNfZmVhdHVyZTowNDE0X3Rlc3QsdW5kZXJmcmFtZV9tYXJrX3N3dGljaDpleHAxXzA0MDksQWlFeHBQbGF5UGFnZTpiYXNlXzAsMjRoX3JvaV9hcnB1OmJhc2UzLG9wZW5QcmV2aWV3OmV4cDIsZ3NwX2V4cDpzZWFyY2hfZGVmYXVsdCxydW5uaW5nX29jcGM6YmFzZSxmbHlfcmFua19jb25mX21lcmdlOmJhc2UsbHRyQXBwTG9nOmNscyxzZWFyY2hfYWRzX3F1ZXJ5X3Jld3JpdGU6Y29tYmluZV9leHAxLHJhbmtfZGl2XzE6ZGVmYXVsdCx1bmRlcmZyYW1lX2Rvd25sb2FkX2FkYnV0dG9uOmJhc2UsQnNPZmZsaW5lTG9jYWxDcGFDb25maWdOZXc6ZGVmYXVsdCx1cFNwYWNlQ2hlY2tEaWZmUmF0aW9FeHA6ZXhwX21icyxzcGxhc2hfaW50ZXJmYWNlX2Rvd25ncmFkZTpiYXNlLGZvcmJpZGRlbl9kaXJlY3RfanVtcDpiYXNlLG1pbmlnYW1lX2JvbnVzX2V4cDpyZW1haW4sZW5hYmxlQXBwc3RvcmVEaXJlY3Q6ZXhwXzEsZnJlcV9pbmZvX3JvdXRpbmc6c2hqZF9zeWNwYl9mcmVxX3Rhc2tfY2x1c3Rlcl8xLHNlYXJjaF9hZHNfbWluX2JpZDpkZWZhdWx0LG9wZW5OZXdHZFByZXZpZXc6ZXhwLGRpc2FibGVfaWxsZWdhbF9vbmVfanVtcDpiYXNlLGNvYXJzZV9xdW90YV9jb250cm9sOmJhc2VfMDMyNCxmbHlfZHluYW1pY0FudG91OmJhc2UsQWlFeHBTdG9yeTpiYXNlLGRwYTJSZWNhbGw6Y2hvb3NlX3Byb2R1Y3RzX2Jhc2VfNTAsc2VhcmNoX25ld190YXJnZXRpbmc6YmFzZSxlbmFibGVfbW9kZWxfZGV0YWlsX3RyYWNrZXI6YmFzZSxEcGEyQ1ZSVGhyZXNob2xkOmpkX2N2cl8yMDAsY3RyX3RfZXhwOnQxLjAscGNTZWFyY2g6ZXhwLGVjb21fbWFpbl9zZWFyY2g65a+554Wn57uELGNvYXJzZTpjb2Fyc2VfY3ZyX25ld2NvbnYsZnJlcV9taWdyYXRlOmV4cF9lbmdpbmVfd2l0aF9zdHJpY3RfYnJ1c2g1LHN3aXRjaEJzUGdSZXFSYXRpbzpjbG9zZSxzZWFyY2hfcmVhbHRpbWVfdHJpZ2dlcjpjb25zdGFudCxBaUV4cEZlZWRzOmJhc2UsbWJzX3JlZmFjdG9yOmV4cDIsdWVzX3NlYXJjaDpkZWZhdWx0LHVuZGVyZnJhbWVfbXVsdGlfYWRzOmJhc2UsYWlnY19hbnRvdV9pbWFnZTpiYXNlXzAzMjYsbWl4ZXJfZnVzaW9uX2RpbWVuc2lvbjpnMixyb2xsb3V0X2xpc3R3aXNlX2Jpem1peGVyX2J1Z19maXg6YmFzZSx1c2VCc0ZpbmRhOmZpbmRhX3gsZmx5X3B1cF9lY3BtOmNvbnN0YW50LGZseV9jdHJfaW5saW5lOm1vZGVsLHRlc3RfcGVnYXN1c19wb3M6YmFzZSx0ZXN0X3N0b3J5X3BhY2s6ZXhwIDIsc3RvcnlfYWRsb2FkXzM6MTQsc2RwYV9kaXZlcnNpZnk6Y29uc3RhbnQyLG1pbmlfZ2FtZV9zY2VuZTpiYXNlLGN0cl9kaWx1Y19lbWJfbGF5ZXI6ZXhwcl9lbWJfZGlsdWMscm9pX2J4aWFveW91X25ldzpkZWZhdWx0LEluZHVzdHJ5Tm9UYXJnZXRGaWx0ZXJMYXllcjpleHAsY3JlYXRpdmVfYXZpZF90YWIzOmV4cF8wNTI3LHN0eWxlX2FiaWxpdHlfb2ZmbGluZTpiYXNlLHVuZGVyZnJhbWVfYnJhbmRfaGlnaDpiYXNlLGNyb3dkX2VjcGM6b3Blbl92Mix0c21fdjJfbGF5ZXI6YmFzZSxtaXhlcl9saXN0d2lzZV9wZWdhc3VzOmc1LHVzZUFzUGc6bWFpbl8yNDEyMjcsc3BsaXRfYnVja2V0OmJ1Y2tldF8zLGdsb2JhbF9yZXZlcnNlOmJhc2UscGxhdGZvcm06ZGVmYXVsdKABALIBICjf18utGMJMWQj0kF8utyJl8gRyHD1TIq1K6aKZR3vRugFCaHR0cHM6Ly9xcnNqLmJpbGlnYW1lLmNvbS9nY3h6L2g1Lz9zb3VyY2VGcm9tPTc3NyZzb3VyY2VUeXBlPWFkUHV0wgEA0gEA2AHQAeABAOgBAPABAIACAogCALgCAMACANACANgCAOoCAPACrIYl+AIAiAMGkgMAqAMAsAMAuAMAwgMAyAMX0gOWAXsiMTYiOiIxMjE1NDYwXzAiLCIxNyI6IjQzMzYiLCIxIjoiMTAxNzg0NjY0OTk1OTc0NzU4NCIsIjIiOiIxMjUyMzkzIiwiMyI6IjEyNTIzOTMiLCI2IjoiMTI1MjM5M18wIiwiMTIiOiI0MzM4IiwiMTMiOiIxMjE1NDYwIiwiMTQiOiI4ODciLCIxNSI6IjEzNjkifeADAOgDAPADAPoDBW90aGVyggQJbnVsbDpudWxsmAQAoAQAqgQECAAQBLAEAOIEwwE1Ni57InBzSWQiOjUyMTE4LCJ2MiI6IkFXVXMyZTBidEhmWTVCSzJ0LUQ0U3lNRGJtN2Z1SGIyYmlIREhsTnBjQlB1U2dVRzdLaW80dUkyNXlSdFJXQU5WUnRMbll1OVpxOElrdkVYZURfUmlER25BeTE0UV9CMlAtSzJmQ3pzMWZLQmY5WjZPUSJ9OzYzLnsicHNJZCI6NTIwNjYsInYyIjoiUWcifTs3MC57InBzSWQiOjUwMDQxLCJ2MiI6IktBIn2gBQDIBQPSBQA=", + "client_ip": "182.89.224.34", + "server_type": 1, + "resource_id": 4336, + "index": 2, + "cm_mark": 1, + "extra": { + "use_ad_web_v2": false, + "show_urls": [ + "" + ], + "click_urls": [], + "download_whitelist": [], + "card": { + "card_type": 0, + "title": "今日全球首发,千件外观福利免费领", + "covers": [ + { + "url": "https://i0.hdslb.com/bfs/sycp/creative_img/202504/bbd7cc4e6a74508e9ccee467541cc06a.jpg", + "loop": 0, + "image_height": 0, + "image_width": 0, + "gif_tag_show": false, + "jump_url": "", + "title": "", + "desc": "" + } + ], + "jump_url": "https://qrsj.biligame.com/gcxz/h5/?sourceFrom=777&sourceType=adPut", + "desc": "", + "callup_url": "", + "long_desc": "", + "ad_tag": "", + "extra_desc": "", + "universal_app": "", + "duration": "", + "adver": { + "adver_id": 1252393, + "adver_type": 3 + }, + "extreme_team_status": false, + "support_transition": false, + "under_player_interaction_style": 0, + "referral_pop_active_time": 10000, + "grade_denominator": 0, + "star_level": 0, + "live_booking_population_threshold": 0, + "ori_mark_hidden": 0, + "use_multi_cover": false, + "custom_feedback_panels": [], + "yellow_cart_pannel_pullup": 0, + "yellow_cart_pannel_version": 0, + "goods_item_id": 0, + "story_interaction_style": 0, + "videos": [], + "download_area": 0, + "goods_pannel_show": 0, + "goods_panel_show": 0, + "show_pop_window": 0, + "search_show_adbutton": 0, + "jump_interaction_style": 0, + "live_page_type": 0, + "ad_tag_style": { + "type": 4, + "text": "", + "text_color": "", + "bg_border_color": "", + "bg_color": "", + "border_color": "", + "img_url": "https://i0.hdslb.com/bfs/sycp/mng/202408/34463051f8d45a6d3c20f8aff31aad9b.png", + "img_height": 48, + "img_width": 72 + }, + "feedback_panel": { + "panel_type_text": "广告", + "feedback_panel_detail": [], + "toast": "将减少相似广告推荐", + "close_rec_tips": "操作成功", + "open_rec_tips": "将减少展示此类广告" + }, + "fold_time": 0, + "live_room_popularity": 0, + "live_tag_show": false, + "quality_infos": [], + "dynamic_text": "今日全球首发,千件外观福利免费领", + "choose_button_list": [], + "grade_level": 0, + "anim_in_enable": 0, + "underframe_card_style": 0, + "playpage_card_style": 0, + "live_auto_play": false, + "original_style_level": 0, + "live_card_show": false, + "enable_tag_move_up": 0, + "item_source": 0, + "closed_loop_item": 0, + "desc_type": 0, + "comment_use_game_page": 0, + "story_takeoff_interaction_style": 0 + }, + "report_time": 2000, + "sales_type": 31, + "special_industry": false, + "preload_landingpage": 0, + "enable_share": true, + "share_info": { + "title": "今日全球首发,千件外观福利免费领", + "subtitle": "", + "image_url": "https://i0.hdslb.com/bfs/sycp/creative_img/202504/3eba2979cb9525f14633a39c9f2ec2ab.jpg" + }, + "upzone_entrance_type": 0, + "upzone_entrance_report_id": 0, + "click_area": 0, + "shop_id": 0, + "up_mid": 0, + "track_id": "pbaes.DXUvRhr8IAhiFZ60KoOBStL0Na80m-kKS6CwFKDBtlzOwGJZu7il0VbEU3j2A_dZ96EXDGonAHs9Qx-5X2XbovyGP-xL4lyr_c_3rDZs4q3frmVjEGhu2VPOE5MRHF3AdryKsZiIGCl_f6ZD0y-cNQ==", + "enable_store_direct_launch": 0, + "enable_double_jump": false, + "from_track_id": "all_49.router-pegasus-2021478-7d7955f987-td5kj.1745482993998.1007", + "store_callup_card": false, + "enable_h5_alert": false, + "special_industry_style": 0, + "macro_replace_priority": 1, + "feedback_panel_style": 0, + "ad_content_type": 0, + "enable_h5_pre_load": 0, + "hot_activity_id": 0, + "middle_show_urls": [], + "middle_click_urls": [], + "product_id": 0, + "landingpage_download_style": 2, + "download_url_type": 0, + "enable_auto_callup": 0, + "top_live_stay_time_seconds": 0, + "vipshop_fast_framework": 0, + "lottery_id": 0, + "enable_openapk_dialog": false, + "user_cancel_jump_type": 0, + "comment_toast_open": 0, + "comment_biz_type": 0, + "app_exp_params": "{\"pegasus_live_inline_background_fill\":0,\"story_live_goods_card_style\":{\"first_type\":1,\"second_type\":2,\"delay_time\":3000}}" + } + } + }, + { + "card_type": "small_cover_v2", + "card_goto": "av", + "goto": "av", + "param": "114375012651120", + "cover": "http://i1.hdslb.com/bfs/archive/05ec862caac777f9d7d06175becf0413b9c653ee.jpg", + "title": "「小白」红米Turbo 4 Pro 性能体验:首台8sGen4量产机表现如何?", + "uri": "bilibili://video/114375012651120?cid=29550644277&player_height=1890&player_preload=%7B%22expire_time%22%3A1745486594%2C%22cid%22%3A29550644277%2C%22quality%22%3A32%2C%22file_info%22%3A%7B%2216%22%3A%7B%22infos%22%3A%5B%7B%22filesize%22%3A2121663%2C%22timelength%22%3A230900%7D%5D%7D%2C%2232%22%3A%7B%22infos%22%3A%5B%7B%22filesize%22%3A3606019%2C%22timelength%22%3A230900%7D%5D%7D%2C%2264%22%3A%7B%22infos%22%3A%5B%7B%22filesize%22%3A6733527%2C%22timelength%22%3A230900%7D%5D%7D%2C%2280%22%3A%7B%22infos%22%3A%5B%7B%22filesize%22%3A10362311%2C%22timelength%22%3A230900%7D%5D%7D%7D%2C%22video_codecid%22%3A7%2C%22video_project%22%3Atrue%2C%22dash%22%3A%7B%22video%22%3A%5B%7B%22id%22%3A32%2C%22base_url%22%3A%22http%3A%2F%2F123.184.35.33%3A8000%2Fv1%2Fresource%2F29550644277-1-100047.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D125426%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mcdnid%3D50007224%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dcos%5Cu0026oi%3D3059343394%5Cu0026orderid%3D0%252C3%5Cu0026os%3Dmcdn%5Cu0026platform%3Dandroid%5Cu0026sign%3D158098%5Cu0026tag%3D%5Cu0026traceid%3DtrANPsmzTXNczh_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Ctag%252Cnbs%252Coi%252Cplatform%252Ctrid%252Cmid%252Cdeadline%252Cuipk%252Cgen%252Cos%252Cog%5Cu0026upsig%3Df6ea272dedd17383c1a7c43a39471036%22%2C%22bandwidth%22%3A124895%2C%22codecid%22%3A7%2C%22size%22%3A3606019%2C%22frame_rate%22%3A%2224.991%22%2C%22backup_url%22%3A%5B%22http%3A%2F%2F211.141.224.92%3A4480%2Fupgcxcode%2F77%2F42%2F29550644277%2F29550644277-1-100047.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026tag%3D%5Cu0026nbs%3D1%5Cu0026oi%3D3059343394%5Cu0026platform%3Dandroid%5Cu0026trid%3D000056fb961696ed4d6bb208acb9ce431b1U%5Cu0026mid%3D479396940%5Cu0026deadline%3D1745490194%5Cu0026uipk%3D5%5Cu0026gen%3Dplayurlv3%5Cu0026os%3Dmcdn%5Cu0026og%3Dcos%5Cu0026upsig%3Df6ea272dedd17383c1a7c43a39471036%5Cu0026uparams%3De%2Ctag%2Cnbs%2Coi%2Cplatform%2Ctrid%2Cmid%2Cdeadline%2Cuipk%2Cgen%2Cos%2Cog%5Cu0026mcdnid%3D50007224%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D125426%5Cu0026build%3D8410300%5Cu0026dl%3D0%5Cu0026f%3DU_0_0%5Cu0026agrr%3D1%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026orderid%3D0%2C3%22%2C%22http%3A%2F%2Fupos-sz-estgoss.bilivideo.com%2Fupgcxcode%2F77%2F42%2F29550644277%2F29550644277-1-100047.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026tag%3D%5Cu0026gen%3Dplayurlv3%5Cu0026os%3Dupos%5Cu0026og%3Dcos%5Cu0026trid%3D56fb961696ed4d6bb208acb9ce431b1U%5Cu0026mid%3D479396940%5Cu0026deadline%3D1745490194%5Cu0026nbs%3D1%5Cu0026oi%3D3059343394%5Cu0026uipk%3D5%5Cu0026platform%3Dandroid%5Cu0026upsig%3D464e03491d78d3249012e6c9affbb768%5Cu0026uparams%3De%2Ctag%2Cgen%2Cos%2Cog%2Ctrid%2Cmid%2Cdeadline%2Cnbs%2Coi%2Cuipk%2Cplatform%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D125426%5Cu0026agrr%3D1%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026build%3D8410300%5Cu0026dl%3D0%5Cu0026f%3DU_0_0%5Cu0026orderid%3D1%2C3%22%5D%2C%22audio_id%22%3A30216%7D%2C%7B%22id%22%3A32%2C%22base_url%22%3A%22http%3A%2F%2F59.47.230.23%3A8000%2Fv1%2Fresource%2F29550644277-1-30033.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D131973%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mcdnid%3D50007224%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dcos%5Cu0026oi%3D3059343394%5Cu0026orderid%3D0%252C3%5Cu0026os%3Dmcdn%5Cu0026platform%3Dandroid%5Cu0026sign%3D2d5ae2%5Cu0026tag%3D%5Cu0026traceid%3DtrQICyqgrXBqnY_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Cnbs%252Coi%252Cuipk%252Cmid%252Cdeadline%252Cog%252Cplatform%252Ctrid%252Ctag%252Cgen%252Cos%5Cu0026upsig%3D855d6f99090897394e531af9d9cc6dc8%22%2C%22bandwidth%22%3A131411%2C%22codecid%22%3A12%2C%22size%22%3A3794237%2C%22frame_rate%22%3A%2224.991%22%2C%22backup_url%22%3A%5B%22http%3A%2F%2F122.191.18.170%3A8000%2Fv1%2Fresource%2F29550644277-1-30033.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D131973%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dcos%5Cu0026oi%3D3059343394%5Cu0026orderid%3D1%252C3%5Cu0026os%3Dcoso1bv%5Cu0026platform%3Dandroid%5Cu0026sign%3D2d5ae2%5Cu0026tag%3D%5Cu0026traceid%3DtrxqpZsZboLcyN_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Cuipk%252Cplatform%252Ctag%252Cos%252Cog%252Cnbs%252Coi%252Ctrid%252Cmid%252Cdeadline%252Cgen%5Cu0026upsig%3D42f974aacd3f2a9a6ba659f11e469614%22%2C%22http%3A%2F%2F211.141.224.92%3A4480%2Fupgcxcode%2F77%2F42%2F29550644277%2F29550644277-1-30033.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026nbs%3D1%5Cu0026oi%3D3059343394%5Cu0026uipk%3D5%5Cu0026mid%3D479396940%5Cu0026deadline%3D1745490194%5Cu0026og%3Dcos%5Cu0026platform%3Dandroid%5Cu0026trid%3D000056fb961696ed4d6bb208acb9ce431b1U%5Cu0026tag%3D%5Cu0026gen%3Dplayurlv3%5Cu0026os%3Dmcdn%5Cu0026upsig%3D855d6f99090897394e531af9d9cc6dc8%5Cu0026uparams%3De%2Cnbs%2Coi%2Cuipk%2Cmid%2Cdeadline%2Cog%2Cplatform%2Ctrid%2Ctag%2Cgen%2Cos%5Cu0026mcdnid%3D50007224%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D131973%5Cu0026build%3D8410300%5Cu0026dl%3D0%5Cu0026f%3DU_0_0%5Cu0026agrr%3D1%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026orderid%3D0%2C3%22%5D%2C%22audio_id%22%3A30216%7D%5D%2C%22audio%22%3A%5B%7B%22id%22%3A30216%2C%22base_url%22%3A%22http%3A%2F%2F121.31.234.218%3A8000%2Fv1%2Fresource%2F29550644277-1-30216.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D43505%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mcdnid%3D50007224%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dhw%5Cu0026oi%3D3059343394%5Cu0026orderid%3D0%252C3%5Cu0026os%3Dmcdn%5Cu0026platform%3Dandroid%5Cu0026sign%3Db0263a%5Cu0026tag%3D%5Cu0026traceid%3DtrDHNJjmfaaueG_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Cplatform%252Ctrid%252Cmid%252Cdeadline%252Cnbs%252Cgen%252Coi%252Cuipk%252Ctag%252Cos%252Cog%5Cu0026upsig%3De92887e43514a81bad4594c670c509d1%22%2C%22bandwidth%22%3A43292%2C%22size%22%3A1250775%2C%22backup_url%22%3A%5B%22http%3A%2F%2F211.141.225.131%3A8000%2Fv1%2Fresource%2F29550644277-1-30216.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D43505%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dhw%5Cu0026oi%3D3059343394%5Cu0026orderid%3D1%252C3%5Cu0026os%3D08hbv%5Cu0026platform%3Dandroid%5Cu0026sign%3Db0263a%5Cu0026tag%3D%5Cu0026traceid%3DtrnTeKCShifUBc_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Cgen%252Cog%252Cdeadline%252Ctag%252Cnbs%252Cplatform%252Ctrid%252Cos%252Cmid%252Coi%252Cuipk%5Cu0026upsig%3D313f602e2d41ebe9637a95fc20bceb93%22%2C%22http%3A%2F%2F211.141.224.92%3A4480%2Fupgcxcode%2F77%2F42%2F29550644277%2F29550644277-1-30216.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026platform%3Dandroid%5Cu0026trid%3D000056fb961696ed4d6bb208acb9ce431b1U%5Cu0026mid%3D479396940%5Cu0026deadline%3D1745490194%5Cu0026nbs%3D1%5Cu0026gen%3Dplayurlv3%5Cu0026oi%3D3059343394%5Cu0026uipk%3D5%5Cu0026tag%3D%5Cu0026os%3Dmcdn%5Cu0026og%3Dhw%5Cu0026upsig%3De92887e43514a81bad4594c670c509d1%5Cu0026uparams%3De%2Cplatform%2Ctrid%2Cmid%2Cdeadline%2Cnbs%2Cgen%2Coi%2Cuipk%2Ctag%2Cos%2Cog%5Cu0026mcdnid%3D50007224%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D43505%5Cu0026f%3DU_0_0%5Cu0026agrr%3D1%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026build%3D8410300%5Cu0026dl%3D0%5Cu0026orderid%3D0%2C3%22%5D%7D%2C%7B%22id%22%3A30280%2C%22base_url%22%3A%22http%3A%2F%2F211.97.94.165%3A8000%2Fv1%2Fresource%2F29550644277-1-30280.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D43504%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mcdnid%3D50007224%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dcos%5Cu0026oi%3D3059343394%5Cu0026orderid%3D0%252C3%5Cu0026os%3Dmcdn%5Cu0026platform%3Dandroid%5Cu0026sign%3D3f3ed4%5Cu0026tag%3D%5Cu0026traceid%3DtrQHmKzoFdDeCw_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Cuipk%252Ctag%252Cnbs%252Cgen%252Cos%252Cog%252Coi%252Cplatform%252Ctrid%252Cmid%252Cdeadline%5Cu0026upsig%3D808cd1429841f75b1ccd7ccdc5de7bc3%22%2C%22bandwidth%22%3A43292%2C%22size%22%3A1250767%2C%22backup_url%22%3A%5B%22http%3A%2F%2F123.184.35.19%3A8000%2Fv1%2Fresource%2F29550644277-1-30280.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D43504%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dcos%5Cu0026oi%3D3059343394%5Cu0026orderid%3D1%252C3%5Cu0026os%3Dupos%5Cu0026platform%3Dandroid%5Cu0026sign%3D3f3ed4%5Cu0026tag%3D%5Cu0026traceid%3DtrtSntUkmmkWVz_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Cplatform%252Ctag%252Cnbs%252Cog%252Ctrid%252Cmid%252Cdeadline%252Coi%252Cuipk%252Cgen%252Cos%5Cu0026upsig%3D070e2e2176dd7e2d87777b20161c8d1f%22%2C%22http%3A%2F%2F211.141.224.92%3A4480%2Fupgcxcode%2F77%2F42%2F29550644277%2F29550644277-1-30280.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026uipk%3D5%5Cu0026tag%3D%5Cu0026nbs%3D1%5Cu0026gen%3Dplayurlv3%5Cu0026os%3Dmcdn%5Cu0026og%3Dcos%5Cu0026oi%3D3059343394%5Cu0026platform%3Dandroid%5Cu0026trid%3D000056fb961696ed4d6bb208acb9ce431b1U%5Cu0026mid%3D479396940%5Cu0026deadline%3D1745490194%5Cu0026upsig%3D808cd1429841f75b1ccd7ccdc5de7bc3%5Cu0026uparams%3De%2Cuipk%2Ctag%2Cnbs%2Cgen%2Cos%2Cog%2Coi%2Cplatform%2Ctrid%2Cmid%2Cdeadline%5Cu0026mcdnid%3D50007224%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D43504%5Cu0026dl%3D0%5Cu0026f%3DU_0_0%5Cu0026agrr%3D1%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026build%3D8410300%5Cu0026orderid%3D0%2C3%22%5D%7D%2C%7B%22id%22%3A30232%2C%22base_url%22%3A%22http%3A%2F%2F125.106.124.64%3A8000%2Fv1%2Fresource%2F29550644277-1-30232.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D43504%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mcdnid%3D50007224%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dhw%5Cu0026oi%3D3059343394%5Cu0026orderid%3D0%252C3%5Cu0026os%3Dmcdn%5Cu0026platform%3Dandroid%5Cu0026sign%3D3ad163%5Cu0026tag%3D%5Cu0026traceid%3DtrsSvqSMaoCcOa_1_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Ctag%252Cuipk%252Cgen%252Cos%252Cog%252Ctrid%252Cmid%252Cdeadline%252Cnbs%252Coi%252Cplatform%5Cu0026upsig%3D219bdbd1641753ddc8555f788bc21711%22%2C%22bandwidth%22%3A43292%2C%22size%22%3A1250767%2C%22backup_url%22%3A%5B%22http%3A%2F%2F220.200.12.159%3A5889%2Fv1%2Fresource%2F29550644277-1-30232.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D43504%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dhw%5Cu0026oi%3D3059343394%5Cu0026orderid%3D1%252C3%5Cu0026os%3D08hbv%5Cu0026platform%3Dandroid%5Cu0026sign%3D3ad163%5Cu0026tag%3D%5Cu0026traceid%3DtrQVqwCtxAuTKK_2_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Ctag%252Coi%252Ctrid%252Cdeadline%252Cgen%252Cos%252Cnbs%252Cuipk%252Cplatform%252Cmid%252Cog%5Cu0026upsig%3Dc45e0be8a46a1b1456b066fc447dcf4a%22%2C%22http%3A%2F%2F211.141.224.92%3A4480%2Fupgcxcode%2F77%2F42%2F29550644277%2F29550644277-1-30232.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026tag%3D%5Cu0026uipk%3D5%5Cu0026gen%3Dplayurlv3%5Cu0026os%3Dmcdn%5Cu0026og%3Dhw%5Cu0026trid%3D000056fb961696ed4d6bb208acb9ce431b1U%5Cu0026mid%3D479396940%5Cu0026deadline%3D1745490194%5Cu0026nbs%3D1%5Cu0026oi%3D3059343394%5Cu0026platform%3Dandroid%5Cu0026upsig%3D219bdbd1641753ddc8555f788bc21711%5Cu0026uparams%3De%2Ctag%2Cuipk%2Cgen%2Cos%2Cog%2Ctrid%2Cmid%2Cdeadline%2Cnbs%2Coi%2Cplatform%5Cu0026mcdnid%3D50007224%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D43504%5Cu0026f%3DU_0_0%5Cu0026agrr%3D1%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026build%3D8410300%5Cu0026dl%3D0%5Cu0026orderid%3D0%2C3%22%5D%7D%5D%7D%2C%22fnval%22%3A272%2C%22accept_formats%22%3A%5B%7B%22quality%22%3A116%2C%22format%22%3A%22flv_p60%22%2C%22description%22%3A%22%E9%AB%98%E6%B8%85%201080P60%22%2C%22new_description%22%3A%221080P%2060%E5%B8%A7%22%2C%22display_desc%22%3A%221080P%22%2C%22superscript%22%3A%2260%E5%B8%A7%22%2C%22need_vip%22%3Atrue%2C%22need_login%22%3Atrue%7D%2C%7B%22quality%22%3A80%2C%22format%22%3A%22flv%22%2C%22description%22%3A%22%E9%AB%98%E6%B8%85%201080P%22%2C%22new_description%22%3A%221080P%20%E9%AB%98%E6%B8%85%22%2C%22display_desc%22%3A%221080P%22%2C%22need_login%22%3Atrue%7D%2C%7B%22quality%22%3A64%2C%22format%22%3A%22flv720%22%2C%22description%22%3A%22%E9%AB%98%E6%B8%85%20720P%22%2C%22new_description%22%3A%22720P%20%E5%87%86%E9%AB%98%E6%B8%85%22%2C%22display_desc%22%3A%22720P%22%2C%22need_login%22%3Atrue%7D%2C%7B%22quality%22%3A32%2C%22format%22%3A%22flv480%22%2C%22description%22%3A%22%E6%B8%85%E6%99%B0%20480P%22%2C%22new_description%22%3A%22480P%20%E6%A0%87%E6%B8%85%22%2C%22display_desc%22%3A%22480P%22%7D%2C%7B%22quality%22%3A16%2C%22format%22%3A%22mp4%22%2C%22description%22%3A%22%E6%B5%81%E7%95%85%20360P%22%2C%22new_description%22%3A%22360P%20%E6%B5%81%E7%95%85%22%2C%22display_desc%22%3A%22360P%22%7D%5D%2C%22volume%22%3A%7B%22measured_i%22%3A-18.2%2C%22measured_lra%22%3A5.9%2C%22measured_tp%22%3A-1.3%2C%22measured_threshold%22%3A-28.3%2C%22target_offset%22%3A0.5%2C%22target_i%22%3A-14%2C%22target_tp%22%3A-1%2C%22multi_scene_args%22%3A%7B%22high_dynamic_target_i%22%3A%22-24%22%2C%22normal_target_i%22%3A%22-14%22%2C%22undersized_target_i%22%3A%22-28%22%7D%7D%2C%22union_player%22%3A%7B%22biz_type%22%3A1%2C%22dimension%22%3A%7B%22width%22%3A4096%2C%22height%22%3A1890%7D%2C%22aid%22%3A114375012651120%7D%2C%22auto_qn_ctl%22%3A%7B%22login_half%22%3A32%2C%22nologin_half%22%3A32%2C%22login_full%22%3A80%2C%22nologin_full%22%3A32%2C%22mobile_login_full%22%3A80%2C%22mobile_nologin_full%22%3A32%7D%2C%22qn_exp%22%3A%7B%22qn_exp_1%22%3Atrue%7D%7D&player_rotate=0&player_width=4096&report_flow_data=%7B%22flow_card_type%22%3A%22av%22%2C%22flow_source%22%3A%22click_u2i%24ann_dssm_u2i_28d%24dssm_u2u%22%7D&trackid=all_49.router-pegasus-2021478-7d7955f987-td5kj.1745482993998.1007", + "three_point": { + "dislike_reasons": [ + { + "id": 4, + "name": "UP主:小白测评", + "toast": "将减少相似内容推荐" + }, + { + "id": 3, + "name": "频道:骁龙8s Gen4", + "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": 8969156, + "up_name": "小白测评", + "tid": 74460002, + "tname": "骁龙8s Gen4", + "aid": 114375012651120 + }, + "player_args": { + "aid": 114375012651120, + "cid": 29550644277, + "type": "av", + "duration": 231 + }, + "idx": 1745482990, + "three_point_v2": [ + { + "title": "添加至稍后再看", + "type": "watch_later", + "icon": "https://i0.hdslb.com/bfs/activity-plat/static/20240103/0977767b2e79d8ad0a36a731068a83d7/8VhmmUeWnO.png", + "icon_night": "https://i0.hdslb.com/bfs/activity-plat/static/20240103/0977767b2e79d8ad0a36a731068a83d7/eIyDu5U7GA.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": 3, + "name": "频道:骁龙8s Gen4", + "toast": "将减少相似内容推荐", + "extend": "{\"tid\":\"74460002\"}" + }, + { + "id": 3, + "name": "频道:科技猎手2025·1.0计划", + "toast": "将减少相似内容推荐", + "extend": "{\"tid\":\"74338017\"}" + }, + { + "id": 12, + "name": "此类内容过多", + "toast": "将减少相似内容推荐" + }, + { + "id": 13, + "name": "推荐过", + "toast": "将减少相似内容推荐" + }, + { + "id": 1, + "name": "这个内容", + "toast": "将减少相似内容推荐" + } + ], + "type": "dislike" + } + ], + "track_id": "all_49.router-pegasus-2021478-7d7955f987-td5kj.1745482993998.1007", + "talk_back": "视频,「小白」红米Turbo 4 Pro 性能体验:首台8sGen4量产机表现如何?,39.5万观看,1654弹幕,时长3分钟51秒,UP主小白测评,", + "report_flow_data": "{\"flow_card_type\":\"av\",\"flow_source\":\"click_u2i$ann_dssm_u2i_28d$dssm_u2u\"}", + "three_point_v": "v2", + "cover_left_text_1": "39.5万", + "cover_left_icon_1": 1, + "cover_left_1_content_description": "39.5万观看", + "cover_left_text_2": "1654", + "cover_left_icon_2": 3, + "cover_left_2_content_description": "1654弹幕", + "cover_right_text": "3:51", + "cover_right_content_description": "3分钟51秒", + "desc_button": { + "text": "小白测评", + "uri": "bilibili://space/8969156", + "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 + }, + "cover_info_priority": 123 + }, + { + "type": "static", + "resource_id": 4336, + "id": 1674583, + "index": 3, + "static_banner": { + "id": 1674583, + "title": "神舟二十号载人飞船今日发射", + "image": "http://i0.hdslb.com/bfs/banner/3d3f17726926194173a2db2a68ff51fbe1081458.jpg", + "hash": "e39cbd594c34ac3a0ec12a45dd6db0b5", + "uri": "https://live.bilibili.com/21686237", + "request_id": "1745482994326q172a27a87a21q3087", + "src_id": 4339, + "is_ad_loc": true, + "client_ip": "182.89.224.34", + "server_type": 0, + "resource_id": 4336, + "index": 3, + "cm_mark": 0 + } + } + ] + }, + { + "card_type": "small_cover_v2", + "card_goto": "av", + "goto": "av", + "param": "114369442680801", + "cover": "http://i1.hdslb.com/bfs/archive/13d3bace40c362db92d5752aef3ebce24bbcbea3.jpg", + "title": "【仿】《明日方舟》六周年庆典活动宣传PV", + "uri": "bilibili://video/114369442680801?cid=29516958739&player_height=1080&player_preload=%7B%22expire_time%22%3A1745486594%2C%22cid%22%3A29516958739%2C%22quality%22%3A32%2C%22file_info%22%3A%7B%2216%22%3A%7B%22infos%22%3A%5B%7B%22filesize%22%3A8427938%2C%22timelength%22%3A239258%7D%5D%7D%2C%2232%22%3A%7B%22infos%22%3A%5B%7B%22filesize%22%3A14979728%2C%22timelength%22%3A239238%7D%5D%7D%2C%2264%22%3A%7B%22infos%22%3A%5B%7B%22filesize%22%3A28834092%2C%22timelength%22%3A239238%7D%5D%7D%2C%2280%22%3A%7B%22infos%22%3A%5B%7B%22filesize%22%3A48620682%2C%22timelength%22%3A239238%7D%5D%7D%7D%2C%22video_codecid%22%3A7%2C%22video_project%22%3Atrue%2C%22dash%22%3A%7B%22video%22%3A%5B%7B%22id%22%3A32%2C%22base_url%22%3A%22http%3A%2F%2F118.184.254.3%3A4480%2Fupgcxcode%2F39%2F87%2F29516958739%2F29516958739-1-100047.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026nbs%3D1%5Cu0026oi%3D3059343394%5Cu0026uipk%3D5%5Cu0026platform%3Dandroid%5Cu0026gen%3Dplayurlv3%5Cu0026tag%3D%5Cu0026trid%3D000056fb961696ed4d6bb208acb9ce431b1U%5Cu0026mid%3D479396940%5Cu0026deadline%3D1745490194%5Cu0026os%3Dmcdn%5Cu0026og%3Dcos%5Cu0026upsig%3D83d78984e6c66cf9fb8f44e16af524dc%5Cu0026uparams%3De%2Cnbs%2Coi%2Cuipk%2Cplatform%2Cgen%2Ctag%2Ctrid%2Cmid%2Cdeadline%2Cos%2Cog%5Cu0026mcdnid%3D50021694%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D501413%5Cu0026f%3DU_0_0%5Cu0026agrr%3D1%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026build%3D8410300%5Cu0026dl%3D0%5Cu0026orderid%3D0%2C3%22%2C%22bandwidth%22%3A500862%2C%22codecid%22%3A7%2C%22size%22%3A14979728%2C%22frame_rate%22%3A%2229.966%22%2C%22backup_url%22%3A%5B%22http%3A%2F%2Fupos-sz-estgoss.bilivideo.com%2Fupgcxcode%2F39%2F87%2F29516958739%2F29516958739-1-100047.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026trid%3D56fb961696ed4d6bb208acb9ce431b1U%5Cu0026os%3Dupos%5Cu0026og%3Dcos%5Cu0026oi%3D3059343394%5Cu0026uipk%3D5%5Cu0026platform%3Dandroid%5Cu0026mid%3D479396940%5Cu0026deadline%3D1745490194%5Cu0026tag%3D%5Cu0026gen%3Dplayurlv3%5Cu0026nbs%3D1%5Cu0026upsig%3D4a9372dc47ff187acaddd4b1bb7ff762%5Cu0026uparams%3De%2Ctrid%2Cos%2Cog%2Coi%2Cuipk%2Cplatform%2Cmid%2Cdeadline%2Ctag%2Cgen%2Cnbs%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D501413%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026build%3D8410300%5Cu0026dl%3D0%5Cu0026f%3DU_0_0%5Cu0026agrr%3D1%5Cu0026orderid%3D1%2C3%22%2C%22http%3A%2F%2Fupos-sz-estgoss.bilivideo.com%2Fupgcxcode%2F39%2F87%2F29516958739%2F29516958739-1-100047.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026deadline%3D1745490194%5Cu0026gen%3Dplayurlv3%5Cu0026os%3Dupos%5Cu0026oi%3D3059343394%5Cu0026uipk%3D5%5Cu0026platform%3Dandroid%5Cu0026trid%3D56fb961696ed4d6bb208acb9ce431b1U%5Cu0026mid%3D479396940%5Cu0026tag%3D%5Cu0026nbs%3D1%5Cu0026og%3Dcos%5Cu0026upsig%3Df4d94d26f589bd25736ae575f46117cb%5Cu0026uparams%3De%2Cdeadline%2Cgen%2Cos%2Coi%2Cuipk%2Cplatform%2Ctrid%2Cmid%2Ctag%2Cnbs%2Cog%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D501413%5Cu0026f%3DU_0_0%5Cu0026agrr%3D1%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026build%3D8410300%5Cu0026dl%3D0%5Cu0026orderid%3D2%2C3%22%5D%2C%22audio_id%22%3A30216%7D%2C%7B%22id%22%3A32%2C%22base_url%22%3A%22http%3A%2F%2F123.184.30.75%3A8000%2Fv1%2Fresource%2F29516958739-1-30033.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D261105%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mcdnid%3D50021694%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dcos%5Cu0026oi%3D3059343394%5Cu0026orderid%3D0%252C3%5Cu0026os%3Dmcdn%5Cu0026platform%3Dandroid%5Cu0026sign%3D6c5944%5Cu0026tag%3D%5Cu0026traceid%3DtrrIoIfTKBmhJG_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Cnbs%252Cgen%252Cos%252Cog%252Cplatform%252Ctrid%252Cmid%252Ctag%252Coi%252Cuipk%252Cdeadline%5Cu0026upsig%3D20c184de73caf9072d6615826d43a023%22%2C%22bandwidth%22%3A260788%2C%22codecid%22%3A12%2C%22size%22%3A7800527%2C%22frame_rate%22%3A%2229.966%22%2C%22backup_url%22%3A%5B%22http%3A%2F%2F123.184.30.71%3A8000%2Fv1%2Fresource%2F29516958739-1-30033.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D261105%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dcos%5Cu0026oi%3D3059343394%5Cu0026orderid%3D1%252C3%5Cu0026os%3Dcoso1bv%5Cu0026platform%3Dandroid%5Cu0026sign%3D6c5944%5Cu0026tag%3D%5Cu0026traceid%3DtrKFqEZMFxtfGx_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Cplatform%252Cnbs%252Ctrid%252Cmid%252Cdeadline%252Ctag%252Coi%252Cuipk%252Cgen%252Cos%252Cog%5Cu0026upsig%3D026e2862050e3c63ac42d8c153b140bd%22%2C%22http%3A%2F%2F118.184.254.3%3A4480%2Fupgcxcode%2F39%2F87%2F29516958739%2F29516958739-1-30033.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026nbs%3D1%5Cu0026gen%3Dplayurlv3%5Cu0026os%3Dmcdn%5Cu0026og%3Dcos%5Cu0026platform%3Dandroid%5Cu0026trid%3D000056fb961696ed4d6bb208acb9ce431b1U%5Cu0026mid%3D479396940%5Cu0026tag%3D%5Cu0026oi%3D3059343394%5Cu0026uipk%3D5%5Cu0026deadline%3D1745490194%5Cu0026upsig%3D20c184de73caf9072d6615826d43a023%5Cu0026uparams%3De%2Cnbs%2Cgen%2Cos%2Cog%2Cplatform%2Ctrid%2Cmid%2Ctag%2Coi%2Cuipk%2Cdeadline%5Cu0026mcdnid%3D50021694%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D261105%5Cu0026agrr%3D1%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026build%3D8410300%5Cu0026dl%3D0%5Cu0026f%3DU_0_0%5Cu0026orderid%3D0%2C3%22%5D%2C%22audio_id%22%3A30216%7D%5D%2C%22audio%22%3A%5B%7B%22id%22%3A30216%2C%22base_url%22%3A%22http%3A%2F%2F183.229.247.224%3A6809%2Fv1%2Fresource%2F29516958739-1-30216.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D57268%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mcdnid%3D50021694%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dhw%5Cu0026oi%3D3059343394%5Cu0026orderid%3D0%252C3%5Cu0026os%3Dmcdn%5Cu0026platform%3Dandroid%5Cu0026sign%3Dc6f08b%5Cu0026tag%3D%5Cu0026traceid%3DtrOVFXiUwisFJo_1_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Ctrid%252Cdeadline%252Ctag%252Cos%252Cog%252Cnbs%252Coi%252Cuipk%252Cplatform%252Cmid%252Cgen%5Cu0026upsig%3D65fa2495f72b1652c93ae3e8ed18f2f6%22%2C%22bandwidth%22%3A57154%2C%22size%22%3A1710889%2C%22backup_url%22%3A%5B%22http%3A%2F%2F123.138.84.79%3A8000%2Fv1%2Fresource%2F29516958739-1-30216.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D57268%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dhw%5Cu0026oi%3D3059343394%5Cu0026orderid%3D1%252C3%5Cu0026os%3D08hbv%5Cu0026platform%3Dandroid%5Cu0026sign%3Dc6f08b%5Cu0026tag%3D%5Cu0026traceid%3DtrZvPCHsGisbaS_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Cnbs%252Coi%252Cplatform%252Cmid%252Cgen%252Cos%252Cog%252Cdeadline%252Ctag%252Cuipk%252Ctrid%5Cu0026upsig%3Dc6eeb5169558ca73c36ff87b7925515c%22%2C%22http%3A%2F%2F118.184.254.3%3A4480%2Fupgcxcode%2F39%2F87%2F29516958739%2F29516958739-1-30216.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026trid%3D000056fb961696ed4d6bb208acb9ce431b1U%5Cu0026deadline%3D1745490194%5Cu0026tag%3D%5Cu0026os%3Dmcdn%5Cu0026og%3Dhw%5Cu0026nbs%3D1%5Cu0026oi%3D3059343394%5Cu0026uipk%3D5%5Cu0026platform%3Dandroid%5Cu0026mid%3D479396940%5Cu0026gen%3Dplayurlv3%5Cu0026upsig%3D65fa2495f72b1652c93ae3e8ed18f2f6%5Cu0026uparams%3De%2Ctrid%2Cdeadline%2Ctag%2Cos%2Cog%2Cnbs%2Coi%2Cuipk%2Cplatform%2Cmid%2Cgen%5Cu0026mcdnid%3D50021694%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D57268%5Cu0026f%3DU_0_0%5Cu0026agrr%3D1%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026build%3D8410300%5Cu0026dl%3D0%5Cu0026orderid%3D0%2C3%22%5D%7D%2C%7B%22id%22%3A30280%2C%22base_url%22%3A%22http%3A%2F%2F125.74.62.233%3A8000%2Fv1%2Fresource%2F29516958739-1-30280.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D201462%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mcdnid%3D50021694%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dcos%5Cu0026oi%3D3059343394%5Cu0026orderid%3D0%252C3%5Cu0026os%3Dmcdn%5Cu0026platform%3Dandroid%5Cu0026sign%3Db1164b%5Cu0026tag%3D%5Cu0026traceid%3DtrkxYWIjABzQnP_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Cuipk%252Ctrid%252Cmid%252Cnbs%252Cog%252Coi%252Cdeadline%252Ctag%252Cgen%252Cos%252Cplatform%5Cu0026upsig%3D5f5a3ee9562beef98824c40a28a6cf00%22%2C%22bandwidth%22%3A201184%2C%22size%22%3A6018701%2C%22backup_url%22%3A%5B%22http%3A%2F%2F118.182.248.130%3A8000%2Fv1%2Fresource%2F29516958739-1-30280.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D201462%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dcos%5Cu0026oi%3D3059343394%5Cu0026orderid%3D1%252C3%5Cu0026os%3Dcoso1bv%5Cu0026platform%3Dandroid%5Cu0026sign%3Db1164b%5Cu0026tag%3D%5Cu0026traceid%3DtrLzIEoLxgCnJA_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Ctrid%252Cog%252Cnbs%252Coi%252Cuipk%252Cdeadline%252Cgen%252Cos%252Ctag%252Cplatform%252Cmid%5Cu0026upsig%3D67dde445db5a37fb52a4bcf508e81318%22%2C%22http%3A%2F%2F118.184.254.3%3A4480%2Fupgcxcode%2F39%2F87%2F29516958739%2F29516958739-1-30280.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026uipk%3D5%5Cu0026trid%3D000056fb961696ed4d6bb208acb9ce431b1U%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026og%3Dcos%5Cu0026oi%3D3059343394%5Cu0026deadline%3D1745490194%5Cu0026tag%3D%5Cu0026gen%3Dplayurlv3%5Cu0026os%3Dmcdn%5Cu0026platform%3Dandroid%5Cu0026upsig%3D5f5a3ee9562beef98824c40a28a6cf00%5Cu0026uparams%3De%2Cuipk%2Ctrid%2Cmid%2Cnbs%2Cog%2Coi%2Cdeadline%2Ctag%2Cgen%2Cos%2Cplatform%5Cu0026mcdnid%3D50021694%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D201462%5Cu0026agrr%3D1%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026build%3D8410300%5Cu0026dl%3D0%5Cu0026f%3DU_0_0%5Cu0026orderid%3D0%2C3%22%5D%7D%2C%7B%22id%22%3A30232%2C%22base_url%22%3A%22http%3A%2F%2F218.200.4.197%3A6768%2Fv1%2Fresource%2F29516958739-1-30232.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D107268%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mcdnid%3D50021694%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dhw%5Cu0026oi%3D3059343394%5Cu0026orderid%3D0%252C3%5Cu0026os%3Dmcdn%5Cu0026platform%3Dandroid%5Cu0026sign%3Df944bf%5Cu0026tag%3D%5Cu0026traceid%3DtrxuDVFEVzmgrz_1_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Cuipk%252Cgen%252Cplatform%252Ctrid%252Cmid%252Ctag%252Cnbs%252Coi%252Cog%252Cdeadline%252Cos%5Cu0026upsig%3Db3eef15ee3382742abc7374c9113a398%22%2C%22bandwidth%22%3A107097%2C%22size%22%3A3204643%2C%22backup_url%22%3A%5B%22http%3A%2F%2F123.184.35.27%3A8000%2Fv1%2Fresource%2F29516958739-1-30232.m4s%3Fagrr%3D1%5Cu0026build%3D8410300%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026bvc%3Dvod%5Cu0026bw%3D107268%5Cu0026deadline%3D1745490194%5Cu0026dl%3D0%5Cu0026e%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026f%3DU_0_0%5Cu0026gen%3Dplayurlv3%5Cu0026mid%3D479396940%5Cu0026nbs%3D1%5Cu0026nettype%3D0%5Cu0026og%3Dhw%5Cu0026oi%3D3059343394%5Cu0026orderid%3D1%252C3%5Cu0026os%3Dcoso1bv%5Cu0026platform%3Dandroid%5Cu0026sign%3Df944bf%5Cu0026tag%3D%5Cu0026traceid%3DtrEEpUqSymBxaq_0_U_a%5Cu0026uipk%3D5%5Cu0026uparams%3De%252Cplatform%252Cmid%252Cdeadline%252Ctag%252Coi%252Ctrid%252Cnbs%252Cuipk%252Cgen%252Cos%252Cog%5Cu0026upsig%3D3727194e76cf963df693733c2427f660%22%2C%22http%3A%2F%2F118.184.254.3%3A4480%2Fupgcxcode%2F39%2F87%2F29516958739%2F29516958739-1-30232.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026uipk%3D5%5Cu0026gen%3Dplayurlv3%5Cu0026platform%3Dandroid%5Cu0026trid%3D000056fb961696ed4d6bb208acb9ce431b1U%5Cu0026mid%3D479396940%5Cu0026tag%3D%5Cu0026nbs%3D1%5Cu0026oi%3D3059343394%5Cu0026og%3Dhw%5Cu0026deadline%3D1745490194%5Cu0026os%3Dmcdn%5Cu0026upsig%3Db3eef15ee3382742abc7374c9113a398%5Cu0026uparams%3De%2Cuipk%2Cgen%2Cplatform%2Ctrid%2Cmid%2Ctag%2Cnbs%2Coi%2Cog%2Cdeadline%2Cos%5Cu0026mcdnid%3D50021694%5Cu0026bvc%3Dvod%5Cu0026nettype%3D0%5Cu0026bw%3D107268%5Cu0026f%3DU_0_0%5Cu0026agrr%3D1%5Cu0026buvid%3DXY6CBD464C1BC5767CE40A77F12B89222B6E7%5Cu0026build%3D8410300%5Cu0026dl%3D0%5Cu0026orderid%3D0%2C3%22%5D%7D%5D%7D%2C%22fnval%22%3A272%2C%22accept_formats%22%3A%5B%7B%22quality%22%3A112%2C%22format%22%3A%22hdflv2%22%2C%22description%22%3A%22%E9%AB%98%E6%B8%85%201080P%2B%22%2C%22new_description%22%3A%221080P%20%E9%AB%98%E7%A0%81%E7%8E%87%22%2C%22display_desc%22%3A%221080P%22%2C%22superscript%22%3A%22%E9%AB%98%E7%A0%81%E7%8E%87%22%2C%22need_vip%22%3Atrue%2C%22need_login%22%3Atrue%7D%2C%7B%22quality%22%3A80%2C%22format%22%3A%22flv%22%2C%22description%22%3A%22%E9%AB%98%E6%B8%85%201080P%22%2C%22new_description%22%3A%221080P%20%E9%AB%98%E6%B8%85%22%2C%22display_desc%22%3A%221080P%22%2C%22need_login%22%3Atrue%7D%2C%7B%22quality%22%3A64%2C%22format%22%3A%22flv720%22%2C%22description%22%3A%22%E9%AB%98%E6%B8%85%20720P%22%2C%22new_description%22%3A%22720P%20%E5%87%86%E9%AB%98%E6%B8%85%22%2C%22display_desc%22%3A%22720P%22%2C%22need_login%22%3Atrue%7D%2C%7B%22quality%22%3A32%2C%22format%22%3A%22flv480%22%2C%22description%22%3A%22%E6%B8%85%E6%99%B0%20480P%22%2C%22new_description%22%3A%22480P%20%E6%A0%87%E6%B8%85%22%2C%22display_desc%22%3A%22480P%22%7D%2C%7B%22quality%22%3A16%2C%22format%22%3A%22mp4%22%2C%22description%22%3A%22%E6%B5%81%E7%95%85%20360P%22%2C%22new_description%22%3A%22360P%20%E6%B5%81%E7%95%85%22%2C%22display_desc%22%3A%22360P%22%7D%5D%2C%22volume%22%3A%7B%22measured_i%22%3A-10.8%2C%22measured_lra%22%3A8.6%2C%22measured_tp%22%3A3.5%2C%22measured_threshold%22%3A-21%2C%22target_offset%22%3A-1.1%2C%22target_i%22%3A-14%2C%22target_tp%22%3A-1%2C%22multi_scene_args%22%3A%7B%22high_dynamic_target_i%22%3A%22-24%22%2C%22normal_target_i%22%3A%22-14%22%2C%22undersized_target_i%22%3A%22-28%22%7D%7D%2C%22union_player%22%3A%7B%22biz_type%22%3A1%2C%22dimension%22%3A%7B%22width%22%3A1920%2C%22height%22%3A1080%7D%2C%22aid%22%3A114369442680801%7D%2C%22auto_qn_ctl%22%3A%7B%22login_half%22%3A32%2C%22nologin_half%22%3A32%2C%22login_full%22%3A80%2C%22nologin_full%22%3A32%2C%22mobile_login_full%22%3A80%2C%22mobile_nologin_full%22%3A32%7D%2C%22qn_exp%22%3A%7B%22qn_exp_1%22%3Atrue%7D%7D&player_rotate=0&player_width=1920&report_flow_data=%7B%22flow_card_type%22%3A%22av%22%2C%22flow_source%22%3A%22dssm_u2u%22%7D&trackid=all_49.router-pegasus-2021478-7d7955f987-td5kj.1745482993998.1007", + "three_point": { + "dislike_reasons": [ + { + "id": 4, + "name": "UP主:罗德岛蜜饼工坊", + "toast": "将减少相似内容推荐" + }, + { + "id": 3, + "name": "频道:明日方舟UP主应援计划 – 离解复合", + "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": 8412516, + "up_name": "罗德岛蜜饼工坊", + "tid": 74654031, + "tname": "明日方舟UP主应援计划 – 离解复合", + "aid": 114369442680801 + }, + "player_args": { + "aid": 114369442680801, + "cid": 29516958739, + "type": "av", + "duration": 240 + }, + "idx": 1745482982, + "three_point_v2": [ + { + "title": "添加至稍后再看", + "type": "watch_later", + "icon": "https://i0.hdslb.com/bfs/activity-plat/static/20240103/0977767b2e79d8ad0a36a731068a83d7/8VhmmUeWnO.png", + "icon_night": "https://i0.hdslb.com/bfs/activity-plat/static/20240103/0977767b2e79d8ad0a36a731068a83d7/eIyDu5U7GA.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": 3, + "name": "频道:明日方舟UP主应援计划 – 离解复合", + "toast": "将减少相似内容推荐", + "extend": "{\"tid\":\"74654031\"}" + }, + { + "id": 3, + "name": "频道:泰拉探索协会", + "toast": "将减少相似内容推荐", + "extend": "{\"tid\":\"22177849\"}" + }, + { + "id": 12, + "name": "此类内容过多", + "toast": "将减少相似内容推荐" + }, + { + "id": 13, + "name": "推荐过", + "toast": "将减少相似内容推荐" + }, + { + "id": 1, + "name": "这个内容", + "toast": "将减少相似内容推荐" + } + ], + "type": "dislike" + } + ], + "track_id": "all_49.router-pegasus-2021478-7d7955f987-td5kj.1745482993998.1007", + "talk_back": "视频,【仿】《明日方舟》六周年庆典活动宣传PV,45.4万观看,1074弹幕,时长4分钟00秒,UP主罗德岛蜜饼工坊,3万点赞,", + "report_flow_data": "{\"flow_card_type\":\"av\",\"flow_source\":\"dssm_u2u\"}", + "three_point_v": "v2", + "cover_left_text_1": "45.4万", + "cover_left_icon_1": 1, + "cover_left_1_content_description": "45.4万观看", + "cover_left_text_2": "1074", + "cover_left_icon_2": 3, + "cover_left_2_content_description": "1074弹幕", + "cover_right_text": "4:00", + "cover_right_content_description": "4分钟00秒", + "rcmd_reason": "3万点赞", + "official_icon": 16, + "can_play": 1, + "rcmd_reason_style": { + "text": "3万点赞", + "text_color": "#FF6633", + "bg_color": "#FFF1ED", + "border_color": "#FFF1ED", + "text_color_night": "#BF5330", + "bg_color_night": "#3D2D29", + "border_color_night": "#3D2D29", + "bg_style": 1 + }, + "cover_info_priority": 123 + } + ], + "config": { + "column": 2, + "autoplay_card": 11, + "feed_clean_abtest": 0, + "home_transfer_test": 0, + "auto_refresh_time": 1200, + "show_inline_danmaku": 1, + "toast": {}, + "single_autoplay_flag": 1, + "is_back_to_homepage": true, + "enable_rcmd_guide": true, + "auto_refresh_time_by_appear": 1800, + "auto_refresh_time_by_active": 1800, + "trigger_loadmore_left_line_num": -1, + "history_cache_size": 10, + "visible_area": 80, + "card_density_exp": 1, + "small_cover_wh_ratio": 1.333333, + "video_mode": 1, + "space_enlarge_exp": 1, + "auto_refresh_time_by_behavior": 5, + "story_mode_v2_guide_exp": 6, + "auto_refresh_by_behavior": 1, + "three_point_style": 1, + "exposure_duration_start_ratio": 0.800000011920929, + "exposure_duration_end_ratio": 0.800000011920929, + "exposure_duration_min_ms": 1, + "rcmd_label_mng_entrance": 1 + }, + "interest_choose": null + } +} +``` + +
\ No newline at end of file diff --git a/bb-api-collect/docs/video/report.md b/bb-api-collect/docs/video/report.md new file mode 100644 index 0000000000..ef141bc60b --- /dev/null +++ b/bb-api-collect/docs/video/report.md @@ -0,0 +1,246 @@ +# 视频观看数据上报 + +## 上报观看进度(双端) + +> https://api.bilibili.com/x/v2/history/report + +*请求方式:POST* + +认证方式:APP或Cookie(SESSDATA) + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ---------- | ---- | ------------------------ | -------------- | --------------------- | +| access_key | str | APP登录Token | APP方式必要 | | +| aid | num | 稿件avid | 必要 | | +| cid | num | 视频cid | 必要 | 用于识别分P | +| progress | num | 观看进度 | 非必要 | 单位为秒
默认为0 | +| platform | str | 平台标识 | 非必要 | 可为android | +| csrf | str | CSRF Token(位于cookie) | Cookie方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-101:账号未登录
-111:csrf校验失败
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +记录视频`av13662970`(`cid=126654047`)的观看记录位于`1248`秒 + +Cookie方式: + +```shell +curl 'https://api.bilibili.com/x/v2/history/report' \ +--data-urlencode 'aid=13662970' \ +--data-urlencode 'cid=126654047' \ +--data-urlencode 'progress=1248' \ +--data-urlencode 'platform=android' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +APP方式: + +```shell +curl 'https://api.bilibili.com/x/v2/history/report' \ +--data-urlencode 'access_key=xxx' \ +--data-urlencode 'aid=13662970' \ +--data-urlencode 'cid=126654047' \ +--data-urlencode 'progress=1248' \ +--data-urlencode 'platform=android' +``` + + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
+ +## 上报视频播放心跳(web端) + +> https://api.bilibili.com/x/click-interface/web/heartbeat + +*请求方式:POST* + +认证方式:仅可Cookie(SESSDATA) + +默认间隔15秒一次, 亦可记录播放历史 + +该接口较为复杂, 且参数计算方法均为推测, 实际过程不明, 可能含有错误, 若要正式使用可以把已播放的持续时间全都设为相同值 + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------------------------- | ---- | ------------------------------ | ------ | ------- | +| w_start_ts | num | 参见请求正文同名无`w_`前缀参数 | 非必要 | UNIX 秒级时间戳 | +| w_mid | num | 参见请求正文同名无`w_`前缀参数 | 非必要 | | +| w_aid | num | 参见请求正文同名无`w_`前缀参数 | 非必要 | | +| w_dt | num | 2 | 非必要 | | +| w_realtime | num | 参见请求正文同名无`w_`前缀参数 | 非必要 | 单位 秒 | +| w_playedtime | num | 参见请求正文同名无`w_`前缀参数 | 非必要 | 单位 秒 | +| w_real_played_time | num | 参见请求正文同名无`w_`前缀参数 | 非必要 | 单位 秒 | +| w_video_duration | num | 参见请求正文同名无`w_`前缀参数 | 非必要 | 单位 秒 | +| w_last_play_progress_time | num | 参见请求正文同名无`w_`前缀参数 | 非必要 | 单位 秒 | +| web_location | num | 网页位置 | 非必要 | 视频详情页播放器: 1315873 | +| w_rid | num | WBI 签名 | 非必要 | 参见[WBI 签名](../misc/sign/wbi.md) | +| wts | num | UNIX 秒级时间戳 | 非必要 | 参见[WBI 签名](../misc/sign/wbi.md) | + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ----------------------- | ---- | ---------------------------------- | ------------ | ----------------------------------------------------------- | +| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个(网页端请求默认仅使用aid) | +| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 | +| cid | num | 视频cid | 非必要 | 用于识别分P | +| epid | num | 番剧epid | 非必要 | | +| sid | num | 番剧ssid | 非必要 | | +| mid | num | 当前用户mid | 非必要 | | +| played_time | num | 视频播放进度 | 非必要 | 单位 秒
播放完成为 -1 | +| realtime | num | 本轮页面会话真实播放时间 | 非必要 | 单位 秒 | +| real_played_time | num | 本轮页面会话真实视频播放持续时间 | 非必要 | 单位 秒 | +| refer_url | str | 与请求头 Referer 字段相同 | 非必要 | | +| quality | num | 视频清晰度 | 非必要 | 参见[qn视频清晰度标识](videostream_url.md#qn视频清晰度标识) | +| video_duration | num | 视频时长 | 非必要 | 单位 秒 | +| last_play_progress_time | num | play_time 与 本轮页面会话开始时 played_time 之和 | 非必要 | 单位 秒 | +| max_play_progress_time | num | 本轮页面会话所有最大 last_play_progress_time 与 本轮页面会话开始时 played_time 之和 | 非必要 | 单位 秒 | +| start_ts | num | 开始播放时刻 | 非必要 | 时间戳 | +| type | num | 视频类型 | 非必要 | 3:投稿视频
4:剧集
10:课程 | +| sub_type | num | 剧集副类型 | 非必要 | 0: 普通投稿视频
1:番剧
2:电影
3:纪录片
4:国创
5:电视剧
7:综艺 | +| dt | num | 2 | 非必要 | | +| outer | num | 0 | 非必要 | | +| spmid | str | 333.788.0.0 | 非必要 | 作用尚不明确 | +| from_spmid | str | 播放来源? | 非必要 | 也可为空, 如: `444.41.list.card_archive.click` `333.999.0.0` | +| session | str | 会话信息? | 非必要 | 一串无分隔小写 UUID | +| extra | obj | 额外信息, 如播放器版本 | 非必要 | 如: `{"player_version":"4.8.36"}` | +| play_type | num | 播放动作 | 非必要 | 0:播放中
1:开始播放
2:暂停
3:继续播放
4: 结束播放 | +| csrf | str | CSRF Token (即 Cookie 中 bili_jct) | 非必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +上报一次视频`av2`/`BV1xx411c7mD`的心跳数据 + +```shell +curl 'https://api.bilibili.com/x/click-interface/web/heartbeat' \ +--data-urlencode 'aid=2' \ +--data-urlencode 'bvid=BV1xx411c7mD' \ +--data-urlencode 'cid=62131' \ +--data-urlencode 'played_time=60' \ +--data-urlencode 'realtime=60' \ +--data-urlencode 'start_ts=1592720840' \ +--data-urlencode 'type=3' \ +--data-urlencode 'dt=2' \ +--data-urlencode 'play_type=0' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
+ +## 开始观看视频 (web端) + +> https://api.bilibili.com/x/click-interface/click/web/h5 + +*请求方式: POST* + +认证方式: Cookie (SESSDATA) + +该接口亦被用于计算播放量, 播放量更新不是实时的
+该接口使用似乎存在 200 播放限制, **请勿滥用!** + +**URL参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| w_aid | num | 稿件 aid | 不必要 | | +| w_part | num | 视频分 P 编号 | 不必要 | | +| w_ftime | num | 点击时间戳? | 不必要 | UNIX 秒级时间戳 | +| w_stime | num | 开始播放时间戳? | 不必要 | UNIX 秒级时间戳 | +| w_type | num | 视频类型 | 不必要 | 见[上报视频播放心跳(web端)](#上报视频播放心跳web端) | +| web_location | num | 网页位置? | 不必要 | 1315873 | +| w_rid | num | WBI 签名 | 不必要 | 参见[WBI 签名](../misc/sign/wbi.md) | +| wts | num | UNIX 秒级时间戳 | 不必要 | 参见[WBI 签名](../misc/sign/wbi.md) | + +**正文参数 (application/x-www-form-urlencoded):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| mid | num | 当前用户 mid | 不必要 | | +| aid | num | 稿件 aid | 必要 | | +| cid | num | 视频 cid | 不必要 | | +| part | num | 视频分 P 编号 | 不必要 | | +| lv | num | 当前用户等级 | 不必要 | | +| ftime | num | 同 URL 参数中带有 `w_` 前缀的同名参数 | 不必要 | | +| stime | num | 同 URL 参数中带有 `w_` 前缀的同名参数 | 不必要 | | +| type | num | 视频类型 | 不必要 | 见[上报视频播放心跳(web端)](#上报视频播放心跳web端) | +| sub_type | num | 视频子类型 | 不必要 | 见[上报视频播放心跳(web端)](#上报视频播放心跳web端) | +| referer_url | str | 与请求头 Referer 字段相同 | 不必要 | | +| outer | num | 0 | 不必要 | | +| spmid | str | 333.788.0.0 | 不必要 | 作用尚不明确 | +| from_spmid | str | 播放来源? | 不必要 | 见[上报视频播放心跳(web端)](#上报视频播放心跳web端) | +| session | str | 会话信息? | 不必要 | 一串无分隔小写 UUID | +| csrf | str | CSRF Token (即 Cookie 中 bili_jct) | 不必要 | | + +**JSON回复:** + +根对象: + +|字段|类型|内容|备注| +|-|-|-|-| +|code|num|返回值|0:成功
-400:请求错误| +|message|str|错误信息|默认为 `0`| +|ttl|num|1|| + +**示例:** + +```shell +curl 'https://api.bilibili.com/x/click-interface/click/web/h5' \ +--data-urlencode 'aid=2' \ +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
diff --git a/bb-api-collect/docs/video/snapshot.md b/bb-api-collect/docs/video/snapshot.md new file mode 100644 index 0000000000..3bc1bb0c47 --- /dev/null +++ b/bb-api-collect/docs/video/snapshot.md @@ -0,0 +1,319 @@ +# 视频快照 + +快照的截取时间根据视频画面变化程度决定,各视频不相同 + +截取时间表的时间根据视频画面变化程度决定,各每个视频不相同 + +截取时间表的时间和快照一一对应,并按照从左到右 从上到下的顺序排布 + +## 获取视频快照(web端) +> https://api.bilibili.com/x/player/videoshot + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------ | ------------ | ----------------------------------- | +| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 | +| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 | +| cid | num | 分P cid | 非必要 | 默认为1P | +| index | num | json数组截取时间表 | 非必要 | 1:需要
0:不需要
默认为0 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------ | +| code | num | 返回值 | 0:成功
40001:请求错误
40003:无视频 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | ---------------------- | --------- | +| pvdata | str | bin格式截取时间表url | | +| img_x_len | num | 每行图片数 | 一般为10 | +| img_y_len | num | 每列图片数 | 一般为10 | +| img_x_size | num | 每张图片长 | 一般为160 | +| img_y_size | num | 每张图片宽 | 一般为90 | +| image | array | 图片拼版 | | +| index | array | json数组格式截取时间表 | 无为空 | + +`data`中的`image`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------------- | -------------------------- | +| 0 | str | 图片拼版1 url | | +| n | str | 图片拼版(n+1) url | 第一张拼版占满时延续第二张 | +| …… | str | …… | …… | + +`data`中的`index`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | --------------- | +| 0 | num | 恒为0 | | +| 1 | num | 图片1 截取时间 | 视频0秒截取时间 | +| n | num | 图片n 截取时间 | 单位为秒 | +| …… | num | …… | 单位为秒 | + +**示例:** + +获取视频`av26273789`/`BV1os411H7wm`的快照 + +avid方式: + +```shell +curl -G 'https://api.bilibili.com/x/player/videoshot' \ +--data-urlencode 'aid=26273789' \ +--data-urlencode 'index=1' +``` + +bvid方式: + +```shell +curl -G 'https://api.bilibili.com/x/player/videoshot' \ +--data-urlencode 'bvid=BV1os411H7wm' \ +--data-urlencode 'index=1' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "pvdata": "//i0.hdslb.com/bfs/videoshot/49075258.bin", + "img_x_len": 10, + "img_y_len": 10, + "img_x_size": 160, + "img_y_size": 90, + "image": ["//i0.hdslb.com/bfs/videoshot/49075258.jpg", "//i0.hdslb.com/bfs/videoshot/49075258-1.jpg"], + "index": [0, 0, 8, 14, 19, 25, 34, 40, 46, 56, 63, 70, 80, 87, 93, 100, 109, 117, 124, 133, 142, 148, 156, 164, 171, 179, 184, 192, 198, 206, 214, 223, 232, 239, 246, 254, 261, 269, 275, 283, 289, 299, 305, 310, 315, 322, 330, 339, 348, 358, 364, 371, 376, 382, 391, 404, 413, 421, 426, 434, 441, 452, 458, 463, 473, 479, 491, 497, 504, 514, 521, 528, 533, 540, 546, 552, 558, 567, 575, 586, 591, 602, 609, 615, 623, 629, 639, 647, 653, 658, 664, 670, 675, 684, 691, 698, 713, 724, 729, 737, 743, 754, 762, 772, 779, 784, 797, 803, 810, 817, 825, 834, 845, 851, 857, 867, 878, 888, 896, 903, 909, 914, 919, 928, 935, 944, 958, 970, 977, 988, 996, 1004, 1011, 1018, 1026, 1035, 1041, 1048, 1055, 1063, 1073, 1079, 1086, 1095, 1106, 1111, 1124, 1135, 1147, 1153, 1159, 1165, 1171, 1184, 1198, 1209, 1215, 1221, 1228, 1236, 1242, 1253, 1258, 1269, 1276, 1284, 1289, 1300, 1306, 1315, 1321, 1328, 1340, 1347, 1354, 1361, 1366, 1371, 1383, 1390, 1396, 1403, 1415] + } +} +``` + +
+ +## 获取视频快照(APP端) + +> https://app.bilibili.com/x/v2/view/video/shot + +*请求方式:GET* + +鉴权方式:appkey + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---------- | ----------- | ---- | +| aid | num | 稿件avid | 必要 | | +| appkey | str | APP密钥 | APP方式必要 | | +| cid | num | 分P cid | 必要 | | +| ts | num | 当前时间戳 | APP方式必要 | | +| sign | str | APP签名 | APP方式必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
10008:稿件的缩略图不存在 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | -------------------- | --------- | +| pvdata | str | bin格式截取时间表url | | +| img_x_len | num | 每行图片数 | 一般为10 | +| img_y_len | num | 每列图片数 | 一般为10 | +| img_x_size | num | 每张图片长 | 一般为160 | +| img_y_size | num | 每张图片宽 | 一般为90 | +| image | array | 图片拼版 | | + +`data`中的`image`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------------- | -------------------------- | +| 0 | str | 图片拼版1 url | | +| n | str | 图片拼版(n+1) url | 第一张拼版占满时延续第二张 | +| …… | str | …… | …… | + +示例: + +获取视频`av26273789`(`cid=49075258`)的快照 + +```shell +curl -G 'https://app.bilibili.com/x/v2/view/video/shot' \ +--data-urlencode 'appkey=1d8b6e7d45233436' \ +--data-urlencode 'aid=26273789' \ +--data-urlencode 'cid=49075258' \ +--data-urlencode 'ts=0' \ +--data-urlencode 'sign=06c0a4f2ede21984313552bd9439db18' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "pvdata": "https://i0.hdslb.com/bfs/videoshot/49075258.bin", + "img_x_len": 10, + "img_y_len": 10, + "img_x_size": 160, + "img_y_size": 90, + "image": [ + "https://i0.hdslb.com/bfs/videoshot/49075258.jpg", + "https://i0.hdslb.com/bfs/videoshot/49075258-1.jpg" + ] + } +} +``` + +
+ +## 获取视频快照(web端)(用于封面预览) + +> https://api.bilibili.com/pvideo + +*请求方式:GET* + +内容与「获取视频快照1」加参数index=1相同,但url带有转义,仅限第1P + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| aid | num | 稿件avid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------------------------------------------- | +| code | num | 返回值 | 0:成功
40001:请求错误
-404:无视频 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ----- | ---------------------- | --------- | +| pvdata | str | bin格式截取时间表url | | +| img_x_len | num | 每行图片数 | 一般为10 | +| img_y_len | num | 每列图片数 | 一般为10 | +| img_x_size | num | 每张图片长 | 一般为160 | +| img_y_size | num | 每张图片宽 | 一般为90 | +| image | array | 图片拼版 | | +| index | array | json数组格式截取时间表 | 无为空 | + +`data`中的`image`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------------- | -------------------------- | +| 0 | str | 图片拼版1 url | | +| n | str | 图片拼版(n+1) url | 第一张拼版占满时延续第二张 | +| …… | str | …… | …… | + +`data`中的`index`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | --------------- | +| 0 | num | 恒为0 | | +| 1 | num | 图片1 截取时间 | 视频0秒截取时间 | +| n | num | 图片n 截取时间 | 单位为秒 | +| …… | num | …… | 单位为秒 | + +**示例:** + +获取视频`av26273789`的快照 + +```shell +curl -G 'https://api.bilibili.com/pvideo' \ +--data-urlencode 'aid=26273789' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "pvdata": "\/\/i0.hdslb.com\/bfs\/videoshot\/49075258.bin", + "img_x_len": 10, + "img_y_len": 10, + "img_x_size": 160, + "img_y_size": 90, + "image": ["\/\/i0.hdslb.com\/bfs\/videoshot\/49075258.jpg", "\/\/i0.hdslb.com\/bfs\/videoshot\/49075258-1.jpg"], + "index": [0, 0, 8, 14, 19, 25, 34, 40, 46, 56, 63, 70, 80, 87, 93, 100, 109, 117, 124, 133, 142, 148, 156, 164, 171, 179, 184, 192, 198, 206, 214, 223, 232, 239, 246, 254, 261, 269, 275, 283, 289, 299, 305, 310, 315, 322, 330, 339, 348, 358, 364, 371, 376, 382, 391, 404, 413, 421, 426, 434, 441, 452, 458, 463, 473, 479, 491, 497, 504, 514, 521, 528, 533, 540, 546, 552, 558, 567, 575, 586, 591, 602, 609, 615, 623, 629, 639, 647, 653, 658, 664, 670, 675, 684, 691, 698, 713, 724, 729, 737, 743, 754, 762, 772, 779, 784, 797, 803, 810, 817, 825, 834, 845, 851, 857, 867, 878, 888, 896, 903, 909, 914, 919, 928, 935, 944, 958, 970, 977, 988, 996, 1004, 1011, 1018, 1026, 1035, 1041, 1048, 1055, 1063, 1073, 1079, 1086, 1095, 1106, 1111, 1124, 1135, 1147, 1153, 1159, 1165, 1171, 1184, 1198, 1209, 1215, 1221, 1228, 1236, 1242, 1253, 1258, 1269, 1276, 1284, 1289, 1300, 1306, 1315, 1321, 1328, 1340, 1347, 1354, 1361, 1366, 1371, 1383, 1390, 1396, 1403, 1415] + } +} +``` + +
+ +## 图片拼版 + +以160x90像素为一张,横向10张,纵向10张,从左到右从上到下进行裁剪 + +图1为0s,图2为8s,图3为14s,以此类推…… + +示例拼版图片url:http://i0.hdslb.com/bfs/videoshot/49075258.jpg + + + +## bin格式截取时间表 + +bin的内容为uint16数组(2Byte对齐),与json数组一一对应 + +第0项恒为0,从第1项开始作为截取图片的时间(秒) + +示例bin格式截取时间表:http://i0.hdslb.com/bfs/videoshot/49075258.bin + +hex内容如下: + +``` +00000000 00 00 00 00 00 08 00 0e 00 13 00 19 00 22 00 28 |.............".(| +00000010 00 2e 00 38 00 3f 00 46 00 50 00 57 00 5d 00 64 |...8.?.F.P.W.].d| +00000020 00 6d 00 75 00 7c 00 85 00 8e 00 94 00 9c 00 a4 |.m.u.|..........| +00000030 00 ab 00 b3 00 b8 00 c0 00 c6 00 ce 00 d6 00 df |................| +00000040 00 e8 00 ef 00 f6 00 fe 01 05 01 0d 01 13 01 1b |................| +00000050 01 21 01 2b 01 31 01 36 01 3b 01 42 01 4a 01 53 |.!.+.1.6.;.B.J.S| +00000060 01 5c 01 66 01 6c 01 73 01 78 01 7e 01 87 01 94 |.\.f.l.s.x.~....| +00000070 01 9d 01 a5 01 aa 01 b2 01 b9 01 c4 01 ca 01 cf |................| +00000080 01 d9 01 df 01 eb 01 f1 01 f8 02 02 02 09 02 10 |................| +00000090 02 15 02 1c 02 22 02 28 02 2e 02 37 02 3f 02 4a |.....".(...7.?.J| +000000a0 02 4f 02 5a 02 61 02 67 02 6f 02 75 02 7f 02 87 |.O.Z.a.g.o.u....| +000000b0 02 8d 02 92 02 98 02 9e 02 a3 02 ac 02 b3 02 ba |................| +000000c0 02 c9 02 d4 02 d9 02 e1 02 e7 02 f2 02 fa 03 04 |................| +000000d0 03 0b 03 10 03 1d 03 23 03 2a 03 31 03 39 03 42 |.......#.*.1.9.B| +000000e0 03 4d 03 53 03 59 03 63 03 6e 03 78 03 80 03 87 |.M.S.Y.c.n.x....| +000000f0 03 8d 03 92 03 97 03 a0 03 a7 03 b0 03 be 03 ca |................| +00000100 03 d1 03 dc 03 e4 03 ec 03 f3 03 fa 04 02 04 0b |................| +00000110 04 11 04 18 04 1f 04 27 04 31 04 37 04 3e 04 47 |.......'.1.7.>.G| +00000120 04 52 04 57 04 64 04 6f 04 7b 04 81 04 87 04 8d |.R.W.d.o.{......| +00000130 04 93 04 a0 04 ae 04 b9 04 bf 04 c5 04 cc 04 d4 |................| +00000140 04 da 04 e5 04 ea 04 f5 04 fc 05 04 05 09 05 14 |................| +00000150 05 1a 05 23 05 29 05 30 05 3c 05 43 05 4a 05 51 |...#.).0.<.C.J.Q| +00000160 05 56 05 5b 05 67 05 6e 05 74 05 7b 05 87 |.V.[.g.n.t.{..| +``` diff --git a/bb-api-collect/docs/video/status_number.md b/bb-api-collect/docs/video/status_number.md new file mode 100644 index 0000000000..89dc0bc381 --- /dev/null +++ b/bb-api-collect/docs/video/status_number.md @@ -0,0 +1,210 @@ +# 视频状态数 + +本页接口均已失效 + +## 视频状态数(仅avid) + +
+该接口已弃用 (HTTP 403) + +> https://api.bilibili.com/archive_stat/stat + +*请求方式:GET* + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------ | ---- | +| aid | num | 稿件avid | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ----------------------------------------------- | +| code | num | 返回值 | 0:成功
40001:请求错误
40003:无视频 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ------------------------ | ------------------------------ | -------------------- | +| aid | num | 稿件avid | | +| view | 正常:num
屏蔽:str | 正常:播放次数
屏蔽:"--" | | +| danmaku | num | 弹幕条数 | | +| reply | num | 评论条数 | | +| favorite | num | 收藏人数 | | +| coin | num | 投币枚数 | | +| share | num | 分享次数 | | +| now_rank | num | 0 | 作用尚不明确 | +| his_rank | num | 历史最高排行 | | +| like | num | 获赞次数 | | +| dislike | num | 0 | 作用尚不明确 | +| no_reprint | num | 禁止转载标志 | 0:无
1:禁止 | +| copyright | num | 版权标志 | 1:自制
2:转载 | + +**示例:** + +查询视频`av91572143`的状态数 + +avid方式: + +```shell +curl -G 'https://api.bilibili.com/archive_stat/stat' \ +--data-urlencode 'aid=91572143' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "aid": 91572143, + "view": 2236510, + "danmaku": 37856, + "reply": 5723, + "favorite": 131317, + "coin": 143389, + "share": 44598, + "now_rank": 0, + "his_rank": 4, + "like": 264314, + "dislike": 0, + "no_reprint": 1, + "copyright": 1 + } +} +``` + +
+ +
+ +## 视频状态数(bvid/avid) + +
+该接口已失效 (HTTP 404) + +> https://api.bilibili.com/x/web-interface/archive/stat + +*请求方式:GET* + +此接口请求头中UA值存在`python`字串,会返回-412错误 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------------ | ------------------ | +| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 | +| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ------------------------------------------------------------ | +| code | num | 返回值 | 0:成功
-400:请求错误
-412:请求被拦截
40003:无视频 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 信息本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ------------------------ | ------------------------------ | -------------------- | +| aid | num | 稿件avid | | +| bvid | str | 稿件bvid | | +| view | 正常:num
屏蔽:str | 正常:播放次数
屏蔽:"--" | | +| danmaku | num | 弹幕条数 | | +| reply | num | 评论条数 | | +| favorite | num | 收藏人数 | | +| coin | num | 投币枚数 | | +| share | num | 分享次数 | | +| now_rank | num | 0 | 作用尚不明确 | +| his_rank | num | 历史最高排行 | | +| like | num | 获赞次数 | | +| dislike | num | 0 | 作用尚不明确 | +| no_reprint | num | 禁止转载标志 | 0:无
1:禁止 | +| copyright | num | 版权标志 | 1:自制
2:转载 | +| argue_msg | str | 警告信息 | 默认为空 | +| evaluation | str | 视频评分 | 默认为空 | + +**示例:** + +查询视频`av2271112`/`BV1es411D7sW`的状态数 + +avid方式: + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/archive/stat' \ +--data-urlencode 'aid=2271112' +``` + +bvid方式: + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/archive/stat' \ +--data-urlencode 'bvid=BV1es411D7sW' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "aid": 2271112, + "bvid": "BV1es411D7sW", + "view": 26408224, + "danmaku": 161919, + "reply": 52825, + "favorite": 892560, + "coin": 599649, + "share": 240573, + "like": 628592, + "now_rank": 0, + "his_rank": 4, + "no_reprint": 0, + "copyright": 1, + "argue_msg": "", + "evaluation": "" + } +} +``` + +
+ +当UA为`2333python2333`时,则无法访问此接口: + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/archive/stat' \ +--data-urlencode 'aid=2271112' \ +-A '2333python2333' +``` + +
+查看响应示例: + +```json +{ + "code":-412, + "message":"请求被拦截", + "ttl":1, + "data":null +} +``` + +
+ +
diff --git a/bb-api-collect/docs/video/summary.md b/bb-api-collect/docs/video/summary.md new file mode 100644 index 0000000000..55d9fb1c1d --- /dev/null +++ b/bb-api-collect/docs/video/summary.md @@ -0,0 +1,287 @@ +# 视频AI总结 + + + +## 获取AI总结内容 + +> https://api.bilibili.com/x/web-interface/view/conclusion/get + +*请求方式: GET* + +认证方式:Cookie(SESSDATA) + +鉴权方式:[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: 成功
-101: 账号未登录
-400:请求错误
-403: 访问权限不足 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | obj | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +|--------------|-----|------|----------------------| +| code | num | 返回值 | -1: 不支持AI摘要(敏感内容等)或其他因素导致请求异常
0: 有摘要
1:无摘要(未识别到语音) | +| model_result | obj | 摘要内容 | | +| stid | str | 摘要 id | 如`code=1`且该字段为`0`时,则未进行 AI 总结,即添加总结队列
如`code=1`且该字段为空时未识别到语音 | +| status | num | (?) | | +| like_num | num | 点赞数 | 默认为`0` | +| dislike_num | num | 点踩数 | 默认为`0` | + +`data`中的`model_result`对象: + +| 字段 | 类型 | 内容 | 备注 | +|-------------|-----|----------|------------------------------------------| +| result_type | num | 数据类型 | 0: 没有摘要
1:仅存着摘要总结
2:存着摘要以及提纲 | +| summary | str | 视频摘要 | 通常为一段概括整个视频内容的文本 | +| outline | 有数据时:array
无数据时:空数组 | 分段提纲 | 通常为视频中叙述的各部分及其要点 | +| subtitle | 有数据时:array
无数据时:空数组 | AI字幕 | 由AI识别生成的字幕列表,自动翻译英文,固定返回中文字幕 | + +`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 | 小结内容 | 其中一个分段的要点 | + +`model_result`对象中`subtitle`数组: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|----------|-----| +| 0 | obj | 字幕列表1 | 若有结果,该数组长度仅为1 | + +`subtitle`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|-----|-----|---------|-----| +| part_subtitle | array | 字幕分段 | 当前分段中的字幕信息 | +| timestamp | num | 字幕识别起始时间 | 单位为秒 | +| title | str | 字幕标题 | 固定为空字符串 | + +`subtitle`数组中的对象中的`part_subtitle`数组: + +| 项 | 类型 | 内容 | 备注 | +|-----|-----|---------|-----| +| 0 | obj | 字幕分段1 | | +| n | obj | 字幕分段n | | +| …… | obj | …… | …… | + +`part_subtitle`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +|-----------|-----|-------|----| +| content | str | 字幕内容 | 其中一个分段的字幕内容 | +| start_timestamp | num | 分段开始时间 | 单位为秒 | +| end_timestamp | num | 分段结束时间 | 单位为秒 | + +**示例:** + +得到视频`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' +``` + +
+查看响应示例: + +```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 + } + ], + "subtitle": [ + { + "part_subtitle": [ + { + "content": "有时候上网啊", + "start_timestamp": 0, + "end_timestamp": 1 + }, + { + "content": "看网友的评论内容", + "start_timestamp": 1, + "end_timestamp": 3 + }, + { + "content": "一句话好几个错别字", + "start_timestamp": 3, + "end_timestamp": 5 + }, + // ... + { + "content": "黄一刀有毒", + "start_timestamp": 352, + "end_timestamp": 355 + } + ], + "timestamp": 1, + "title": "" + } + ], + }, + "stid": "5117037934391059183", + "status": 0, + "like_num": 6, + "dislike_num": 2 + } +} +``` + +
+ +## 点赞&点踩摘要 + +> 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: 点赞
2: 取消点赞
3: 点踩
4: 取消点踩 | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +|---------|-----|------|------------------------------------------| +| code | num | 返回值 | 0: 成功
-400: 请求错误
65002:origin id 错误
65004:取消赞失败 未点赞过
65005:取消踩失败 未点踩过
65006: 已赞过
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' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
diff --git a/bb-api-collect/docs/video/tags.md b/bb-api-collect/docs/video/tags.md new file mode 100644 index 0000000000..2ee6fdefcd --- /dev/null +++ b/bb-api-collect/docs/video/tags.md @@ -0,0 +1,434 @@ +# 视频TAG + +## 获取视频TAG信息(新) + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------------ | -------------------------------- | +| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 | +| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 | +| cid | num | 分P cid | 非必要 | 提供此参数可返回对应分P的BGM信息 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | array | TAG列表 | 无TAG为空 | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | ---- | +| 0 | obj | 第1个TAG | | +| n | obj | 第(n+1)个TAG | | +| …… | obj | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------- | ---- | ---------- | ------------------------------------------------------------ | +| tag_id | num | tag_id | 当`tag_type`不为`bgm`时有效 | +| tag_name | str | TAG名称 | | +| music_id | str | 背景音乐id | 当`tag_type`为`bgm`时有效,以`MA`开头 | +| tag_type | str | TAG类型 | `old_channel`:普通标签
`topic`:话题
`bgm`:背景音乐 | +| jump_url | str | 跳转url | 当`tag_type`为`topic`或`bgm`时有效 | + +**示例:** + +查询视频`av89772773`/`BV1M741177Kg`的TAG + +avid方式: + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/view/detail/tag' \ +--data-urlencode 'aid=89772773' \ +--data-urlencode 'cid=153322313' \ +-b 'SESSDATA=xxx' +``` + +bvid方式: + +```shell +curl -G 'https://api.bilibili.com/x/web-interface/view/detail/tag' \ +--data-urlencode 'bvid=BV1M741177Kg' \ +--data-urlencode 'cid=153322313' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "tag_id": 0, + "tag_name": "发现《Other Side》", + "music_id": "MA456128506519140428", + "tag_type": "bgm", + "jump_url": "https://music.bilibili.com/h5/music-detail?music_id=MA456128506519140428&cid=153322313&aid=89772773&na_close_hide=1" + }, + { + "tag_id": 12620189, + "tag_name": "异度侵入", + "music_id": "", + "tag_type": "old_channel", + "jump_url": "" + }, + { + "tag_id": 707, + "tag_name": "ED", + "music_id": "", + "tag_type": "old_channel", + "jump_url": "" + }, + { + "tag_id": 1394, + "tag_name": "动漫", + "music_id": "", + "tag_type": "old_channel", + "jump_url": "" + }, + { + "tag_id": 13289329, + "tag_name": "异度侵入ed原图", + "music_id": "", + "tag_type": "old_channel", + "jump_url": "" + }, + { + "tag_id": 7520816, + "tag_name": "bilibili新星计划", + "music_id": "", + "tag_type": "old_channel", + "jump_url": "" + } + ] +} +``` + +
+ +## 获取视频TAG信息(旧) + +> + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | -------- | ------------ | ------------------ | +| aid | num | 稿件avid | 必要(可选) | avid与bvid任选一个 | +| bvid | str | 稿件bvid | 必要(可选) | avid与bvid任选一个 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----- | -------- | --------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | array | TAG列表 | 无TAG为空 | + +`data`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | -------------- | ---- | +| 0 | obj | 第1个TAG | | +| n | obj | 第(n+1)个TAG | | +| …… | obj | …… | …… | + +`data`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ---- | -------------- | ------------------------------------------------------------ | +| tag_id | num | tag_id | | +| tag_name | str | TAG名称 | | +| cover | str | TAG图片url | | +| head_cover | str | TAG页面头图url | | +| content | str | TAG介绍 | | +| short_content | str | TAG简介 | | +| type | num | ??? | | +| state | num | 0 | | +| ctime | num | 创建时间 | 秒级时间戳 | +| count | obj | 状态数 | | +| is_atten | num | 是否关注 | 0:未关注
1:已关注
需要登录(Cookie)
未登录为0 | +| likes | num | 0 | 作用尚不明确 | +| hates | num | 0 | 作用尚不明确 | +| attribute | num | 0 | 作用尚不明确 | +| liked | num | 是否已经点赞 | 0:未点赞
1:已点赞
需要登录(Cookie)
未登录为0 | +| hated | num | 是否已经点踩 | 0:未点踩
1:已点踩
需要登录(Cookie)
未登录为0 | +| extra_attr | num | ? ? ? | | + +`data`数组中的对象中的`count`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ----- | ---- | ------------- | ------------ | +| view | num | 0 | 作用尚不明确 | +| use | num | 视频添加TAG数 | | +| atten | num | TAG关注 | | + +**示例:** + +查询视频`av89772773`/`BV1M741177Kg`的TAG + +avid方式: + +```shell +curl -G 'https://api.bilibili.com/x/tag/archive/tags' \ +--data-urlencode 'aid=89772773' \ +-b 'SESSDATA=xxx' +``` + +bvid方式: + +```shell +curl -G 'https://api.bilibili.com/x/tag/archive/tags' \ +--data-urlencode 'bvid=BV1M741177Kg' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [{ + "tag_id": 12620189, + "tag_name": "异度侵入", + "cover": "", + "head_cover": "", + "content": "", + "short_content": "", + "type": 1, + "state": 0, + "ctime": 1576235749, + "count": { + "view": 0, + "use": 6392, + "atten": 8938 + }, + "is_atten": 1, + "likes": 1, + "hates": 0, + "attribute": 0, + "liked": 0, + "hated": 0 + }, { + "tag_id": 7520816, + "tag_name": "bilibili新星计划", + "cover": "", + "head_cover": "", + "content": "", + "short_content": "", + "type": 4, + "state": 0, + "ctime": 1529717850, + "count": { + "view": 0, + "use": 1967314, + "atten": 65082 + }, + "is_atten": 0, + "likes": 0, + "hates": 0, + "attribute": 0, + "liked": 0, + "hated": 0 + }, { + "tag_id": 707, + "tag_name": "ED", + "cover": "", + "head_cover": "", + "content": "", + "short_content": "", + "type": 3, + "state": 0, + "ctime": 1436866637, + "count": { + "view": 0, + "use": 62646, + "atten": 75642 + }, + "is_atten": 1, + "likes": 0, + "hates": 0, + "attribute": 0, + "liked": 0, + "hated": 0 + }, { + "tag_id": 1394, + "tag_name": "动漫", + "cover": "http://i0.hdslb.com/bfs/tag/d08c5fe17ceb793e7ce95d9c67392743b33b46d0.jpg", + "head_cover": "", + "content": " “动漫”是动画和漫画的合称与缩写。在其他语言相当少用。随着现代传媒技术的发展,动画(animation或anime)和漫画(comics,manga;特别是故事性漫画)之间联系日趋紧密,两者常被合而为“动漫”。\n  由于漫画本身的发展形成了现代故事漫画的表现形式,将影视艺术融入漫画之中,使得漫画与动画更容易结合,影视艺术独特的地方在于它能通过镜头的推拉摇移和片段剪辑的蒙太奇技巧来表达想法和感受。漫画正是吸收了影视艺术的这两个特点。当讲述的故事越发复杂、人物越发丰富的时候,传统单线式叙事的方法就越行不通,蒙太奇的介入就成为一种需要了;当漫画家在传统表现手段中无法找到更合适的抒发感情的方法的时候,当读者需要作品有更强的冲击力和表现力的时候,各种镜头的灵活运用就成为一种必需了。一部现代故事漫画往往集远、中、近、特四种镜头于一身,漫画家往往能熟练地运用镜头的移动和各种蒙太奇剪接,对故事特定部分的情绪和氛围进行渲染。这就是现代故事漫画容易和动画结合的一个原因,因为它天生就像动画的分镜头剧本,读者在看漫画时如同在看一部电影。正是有着这样的相似性所以如今将动画和漫画合称为“动漫”。", + "short_content": "", + "type": 3, + "state": 0, + "ctime": 1436866637, + "count": { + "view": 0, + "use": 1134143, + "atten": 113030 + }, + "is_atten": 0, + "likes": 0, + "hates": 0, + "attribute": 0, + "liked": 0, + "hated": 0 + }, { + "tag_id": 13289329, + "tag_name": "异度侵入ed原图", + "cover": "", + "head_cover": "", + "content": "", + "short_content": "", + "type": 1, + "state": 0, + "ctime": 1581948411, + "count": { + "view": 0, + "use": 3, + "atten": 0 + }, + "is_atten": 0, + "likes": 0, + "hates": 0, + "attribute": 0, + "liked": 0, + "hated": 0 + }] +} +``` + +
+ +## 点赞&取消点赞视频TAG + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +重复请求为取消 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------ | ------ | ---- | +| aid | num | 稿件avid | 必要 | | +| tag_id | num | tag_id | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +为视频`av89772773`的TAG`12620189`点赞 + +```shell +curl 'https://api.bilibili.com/x/tag/archive/like2' \ +--data-urlencode 'aid=89772773' \ +--data-urlencode 'tag_id=12620189' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
+ +## 点踩&取消点踩视频TAG + +> + +*请求方式:POST* + +认证方式:Cookie(SESSDATA) + +重复请求为取消 + +**正文参数( application/x-www-form-urlencoded ):** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ------------------------ | ------ | ---- | +| aid | num | 稿件avid | 必要 | | +| tag_id | num | tag_id | 必要 | | +| csrf | str | CSRF Token(位于cookie) | 必要 | | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ---- | -------- | ---------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | + +**示例:** + +为视频`av89772773`的TAG`7520816`点踩 + +```shell +curl 'https://pi.bilibili.com/x/tag/archive/hate2' \ +--data-urlencode 'aid=89772773' \ +--data-urlencode 'tag_id=7520816' \ +--data-urlencode 'csrf=xxx' \ +-b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1 +} +``` + +
diff --git a/bb-api-collect/docs/video/video_zone.md b/bb-api-collect/docs/video/video_zone.md new file mode 100644 index 0000000000..14fe503d7a --- /dev/null +++ b/bb-api-collect/docs/video/video_zone.md @@ -0,0 +1,336 @@ +# 视频分区一览 + +用于判断视频所在的分区,或推荐分区视频等…… + +亦可用于更深♂入了解B站的分区 + +本文档中的内容适用于 `tid`、`tname` 等字段,关于 `tid_v2`、`tname_v2` 等字段请参阅 “[视频分区一览 (v2)](./video_zone_v2.md)” 文档 + +## 动画 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|-----------------------|------------|-----|------------------------------------------------------------------|--------------------------------------------------------------------| +| 动画(主分区) | douga | 1 | | [/v/douga](https://www.bilibili.com/v/douga) | +| MAD·AMV | mad | 24 | 具有一定制作程度的动画或静画的二次创作视频 | [/v/douga/mad](https://www.bilibili.com/v/douga/mad) | +| MMD·3D | mmd | 25 | 使用MMD(MikuMikuDance)和其他3D建模类软件制作的视频 | [/v/douga/mmd](https://www.bilibili.com/v/douga/mmd) | +| 同人·手书
(~~原短片·手书~~) | handdrawn | 47 | 追求个人特色和创意表达的手书(绘)、以及同人作品展示、宣传为主的内容 | [/v/douga/handdrawn](https://www.bilibili.com/v/douga/handdrawn) | +| 配音 | voice | 257 | 使用ACGN相关画面或台本素材进行人工配音创作的内容 | [/v/douga/voice](https://www.bilibili.com/v/douga/voice) | +| 手办·模玩 | garage_kit | 210 | 手办模玩的测评、改造或其他衍生内容 | [/v/douga/garage_kit](https://www.bilibili.com/v/douga/garage_kit) | +| 特摄 | tokusatsu | 86 | 特摄相关衍生视频 | [/v/douga/tokusatsu](https://www.bilibili.com/v/douga/tokusatsu) | +| 动漫杂谈 | acgntalks | 253 | 以谈话形式对ACGN文化圈进行的鉴赏、吐槽、评点、解说、推荐、科普等内容 | [/v/douga/acgntalks](https://www.bilibili.com/v/douga/acgntalks) | +| 综合 | other | 27 | 以动画及动画相关内容为素材,包括但不仅限于音频替换、恶搞改编、排行榜等内容 | [/v/douga/other](https://www.bilibili.com/v/douga/other) | + +## 番剧 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|---------|-------------|-----|---------------------------|----------------------------------------------------------------------| +| 番剧(主分区) | anime | 13 | | [/anime](https://www.bilibili.com/anime) | +| 资讯 | information | 51 | 动画番剧相关资讯视频 | [/v/anime/information](https://www.bilibili.com/v/anime/information) | +| 官方延伸 | offical | 152 | 动画番剧为主题的宣传节目、采访视频,及声优相关视频 | [/v/anime/offical](https://www.bilibili.com/v/anime/offical) | +| 完结动画 | finish | 32 | 已完结的动画番剧合集 | [/v/anime/finish](https://www.bilibili.com/v/anime/finish) | +| 连载动画 | serial | 33 | 当季连载的动画番剧 | [/v/anime/serial](https://www.bilibili.com/v/anime/serial) | + +## 国创 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|---------|-------------|-----|------------|------------------------------------------------------------------------------| +| 国创(主分区) | guochuang | 167 | | [/guochuang](https://www.bilibili.com/guochuang) | +| 国产动画 | chinese | 153 | 我国出品的PGC动画 | [/v/guochuang/chinese](https://www.bilibili.com/v/guochuang/chinese) | +| 国产原创相关 | original | 168 | | [/v/guochuang/original](https://www.bilibili.com/v/guochuang/original) | +| 布袋戏 | puppetry | 169 | | [/v/guochuang/puppetry](https://www.bilibili.com/v/guochuang/puppetry) | +| 资讯 | information | 170 | | [/v/guochuang/information](https://www.bilibili.com/v/guochuang/information) | +| 动态漫·广播剧 | motioncomic | 195 | | [/v/guochuang/motioncomic](https://www.bilibili.com/v/guochuang/motioncomic) | + +## 音乐 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|---------------|----------------|---------|----------------------------------------------------------|--------------------------------------------------------------------| +| 音乐(主分区) | music | 3 | | [/v/music](https://www.bilibili.com/v/music) | +| 原创音乐 | original | 28 | 原创歌曲及纯音乐,包括改编、重编曲及remix | [/v/music/original](https://www.bilibili.com/v/music/original) | +| 音乐现场 | live | 29 | 音乐表演的实况视频,包括官方的综艺节目、音乐剧、音乐节、演唱会、打歌舞台现场等,以及个人演出/街头表演现场等 | [/v/music/live](https://www.bilibili.com/v/music/live) | +| 翻唱 | cover | 31 | 对曲目的人声再演绎视频 | [/v/music/cover](https://www.bilibili.com/v/music/cover) | +| 演奏 | perform | 59 | 乐器和非传统乐器器材的演奏作品 | [/v/music/perform](https://www.bilibili.com/v/music/perform) | +| 乐评盘点 | commentary | 243 | 音乐类新闻、盘点、点评、reaction、榜单、采访、幕后故事、唱片开箱等 | [/v/music/commentary](https://www.bilibili.com/v/music/commentary) | +| VOCALOID·UTAU | vocaloid | 30 | 以VOCALOID等歌声合成引擎为基础,运用各类音源进行的创作 | [/v/music/vocaloid](https://www.bilibili.com/v/music/vocaloid) | +| MV | mv | 193 | 为音乐作品配合拍摄或制作的音乐录影带(Music Video),以及自制拍摄、剪辑、翻拍MV | [/v/music/mv](https://www.bilibili.com/v/music/mv) | +| 音乐粉丝饭拍 | fan_videos | 266 | 在音乐演出现场由粉丝团体或个人拍摄的非官方记录视频,包括但不限于粉丝自制饭拍、直拍、Vlog以及衍生的内容混剪等 | [/v/music/fan_videos](https://www.bilibili.com/v/music/fan_videos) | +| AI音乐 | ai_music | 265 | 以AI合成技术为基础,运用各类工具进行的AI作编曲、AI作词、AI语音、AI变声、AI翻唱、AI MV等创作 | [/v/music/ai_music](https://www.bilibili.com/v/music/ai_music) | +| 电台 | radio | 267 | 音乐分享、播单、白噪音、有声读物等以听为主的播放内容 | [/v/music/radio](https://www.bilibili.com/v/music/radio) | +| 音乐教学 | tutorial | 244 | 以音乐教学为目的的内容 | [/v/music/tutorial](https://www.bilibili.com/v/music/tutorial) | +| 音乐综合 | other | 130 | 所有无法被收纳到其他音乐二级分区的音乐类视频 | [/v/music/other](https://www.bilibili.com/v/music/other) | +| ~~电音~~(已下线) | ~~electronic~~ | ~~194~~ | ~~以电子合成器、音乐软体等产生的电子声响制作的音乐~~ | ~~/v/music/electronic~~ | + +## 舞蹈 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|-------------------------|----------|-----|--------------------------------------|----------------------------------------------------------------| +| 舞蹈(主分区) | dance | 129 | | [/v/dance](https://www.bilibili.com/v/dance) | +| 宅舞 | otaku | 20 | 与ACG相关的翻跳、原创舞蹈 | [/v/dance/otaku](https://www.bilibili.com/v/dance/otaku) | +| 街舞 | hiphop | 198 | 收录街舞相关内容,包括赛事现场、舞室作品、个人翻跳、FREESTYLE等 | [/v/dance/hiphop](https://www.bilibili.com/v/dance/hiphop) | +| 明星舞蹈 | star | 199 | 国内外明星发布的官方舞蹈及其翻跳内容 | [/v/dance/star](https://www.bilibili.com/v/dance/star) | +| 国风舞蹈 | china | 200 | 收录国风向舞蹈内容,包括中国舞、民族民间舞、汉唐舞、国风爵士等 | [/v/dance/china](https://www.bilibili.com/v/dance/china) | +| 颜值·网红舞
(~~原手势·网红舞~~) | gestures | 255 | 手势舞及网红流行舞蹈、短视频舞蹈等相关视频 | [/v/dance/gestures](https://www.bilibili.com/v/dance/gestures) | +| 舞蹈综合 | three_d | 154 | 收录无法定义到其他舞蹈子分区的舞蹈视频 | [/v/dance/three_d](https://www.bilibili.com/v/dance/three_d) | +| 舞蹈教程 | demo | 156 | 镜面慢速,动作分解,基础教程等具有教学意义的舞蹈视频 | [/v/dance/demo](https://www.bilibili.com/v/dance/demo) | + +## 游戏 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|---------|-------------|-----|---------------------------------------------------------------|--------------------------------------------------------------------| +| 游戏(主分区) | game | 4 | | [/v/game](https://www.bilibili.com/v/game) | +| 单机游戏 | stand_alone | 17 | 以所有平台(PC、主机、移动端)的单机或联机游戏为主的视频内容,包括游戏预告、CG、实况解说及相关的评测、杂谈与视频剪辑等 | [/v/game/stand_alone](https://www.bilibili.com/v/game/stand_alone) | +| 电子竞技 | esports | 171 | 具有高对抗性的电子竞技游戏项目,其相关的赛事、实况、攻略、解说、短剧等视频。 | [/v/game/esports](https://www.bilibili.com/v/game/esports) | +| 手机游戏 | mobile | 172 | 以手机及平板设备为主要平台的游戏,其相关的实况、攻略、解说、短剧、演示等视频。 | [/v/game/mobile](https://www.bilibili.com/v/game/mobile) | +| 网络游戏 | online | 65 | 由网络运营商运营的多人在线游戏,以及电子竞技的相关游戏内容。包括赛事、攻略、实况、解说等相关视频 | [/v/game/online](https://www.bilibili.com/v/game/online) | +| 桌游棋牌 | board | 173 | 桌游、棋牌、卡牌对战等及其相关电子版游戏的实况、攻略、解说、演示等视频。 | [/v/game/board](https://www.bilibili.com/v/game/board) | +| GMV | gmv | 121 | 由游戏素材制作的MV视频。以游戏内容或CG为主制作的,具有一定创作程度的MV类型的视频 | [/v/game/gmv](https://www.bilibili.com/v/game/gmv) | +| 音游 | music | 136 | 各个平台上,通过配合音乐与节奏而进行的音乐类游戏视频 | [/v/game/music](https://www.bilibili.com/v/game/music) | +| Mugen | mugen | 19 | 以Mugen引擎为平台制作、或与Mugen相关的游戏视频 | [/v/game/mugen](https://www.bilibili.com/v/game/mugen) | + +## 知识 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|-----------------------------|-------------------|--------|-----------------------------|----------------------------------------------------------------------------------------| +| 知识(主分区) | knowledge | 36 | | [/v/knowledge](https://www.bilibili.com/v/knowledge) | +| 科学科普 | science | 201 | 回答你的十万个为什么 | [/v/knowledge/science](https://www.bilibili.com/v/knowledge/science) | +| 社科·法律·心理(~~原社科人文、原趣味科普人文~~) | social_science | 124 | 基于社会科学、法学、心理学展开或个人观点输出的知识视频 | [/v/knowledge/social_science](https://www.bilibili.com/v/knowledge/social_science) | +| 人文历史 | humanity_history | 228 | 看看古今人物,聊聊历史过往,品品文学典籍 | [/v/knowledge/humanity_history](https://www.bilibili.com/v/knowledge/humanity_history) | +| 财经商业 | business | 207 | 说金融市场,谈宏观经济,一起畅聊商业故事 | [/v/knowledge/finance](https://www.bilibili.com/v/knowledge/finance) | +| 校园学习 | campus | 208 | 老师很有趣,学生也有才,我们一起搞学习 | [/v/knowledge/campus](https://www.bilibili.com/v/knowledge/campus) | +| 职业职场 | career | 209 | 职业分享、升级指南,一起成为最有料的职场人 | [/v/knowledge/career](https://www.bilibili.com/v/knowledge/career) | +| 设计·创意 | design | 229 | 天马行空,创意设计,都在这里 | [/v/knowledge/design](https://www.bilibili.com/v/knowledge/design) | +| 野生技术协会 | skill | 122 | 技能党集合,是时候展示真正的技术了 | [/v/knowledge/skill](https://www.bilibili.com/v/knowledge/skill) | +| ~~演讲·公开课~~(已下线) | ~~speech_course~~ | ~~39~~ | ~~涨知识的好地方,给爱学习的你~~ | ~~/v/technology/speech_course~~ | +| ~~星海~~(已下线) | ~~military~~ | ~~96~~ | ~~军事类内容的圣地~~ | ~~/v/technology/military~~ | +| ~~机械~~(已下线) | ~~mechanical~~ | ~~98~~ | ~~机械设备展示或制作视频~~ | ~~/v/technology/mechanical~~ | + +## 科技 + +新:旧: + +~~原数码分区~~ + +| 名称 | 代号 | tid | 简介 | url路由 | +|----------------------|---------------------|---------|----------------------------------|------------------------------------------------------------------------| +| 科技(主分区) | tech | 188 | | [/v/tech](https://www.bilibili.com/v/tech) | +| 数码(~~原手机平板~~) | digital | 95 | 科技数码产品大全,一起来做发烧友 | [/v/tech/digital](https://www.bilibili.com/v/tech/digital) | +| 软件应用 | application | 230 | 超全软件应用指南 | [/v/tech/application](https://www.bilibili.com/v/tech/application) | +| 计算机技术 | computer_tech | 231 | 研究分析、教学演示、经验分享......有关计算机技术的都在这里 | [/v/tech/computer_tech](https://www.bilibili.com/v/tech/computer_tech) | +| 科工机械 (~~原工业·工程·机械~~) | industry | 232 | 从小芯片到大工程,一起见证科工力量 | [/v/tech/industry](https://www.bilibili.com/v/tech/industry) | +| 极客DIY | diy | 233 | 炫酷技能,极客文化,硬核技巧,准备好你的惊讶 | [/v/tech/diy](https://www.bilibili.com/v/tech/diy) | +| ~~电脑装机~~(已下线) | ~~pc~~ | ~~189~~ | ~~电脑、笔记本、装机配件、外设和软件教程等相关视频~~ | ~~/v/digital/pc~~ | +| ~~摄影摄像~~(已下线) | ~~photography~~ | ~~190~~ | ~~摄影摄像器材、拍摄剪辑技巧、拍摄作品分享等相关视频~~ | ~~/v/digital/photography~~ | +| ~~影音智能~~(已下线) | ~~intelligence_av~~ | ~~191~~ | ~~影音设备、智能产品等相关视频~~ | ~~/v/digital/intelligence_av~~ | + +## 运动 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|---------|---------------|-----|--------------------------------------------------------|----------------------------------------------------------------------------| +| 运动(主分区) | sports | 234 | | [/v/sports](https://www.bilibili.com/v/sports) | +| 篮球 | basketball | 235 | 与篮球相关的视频,包括但不限于篮球赛事、教学、评述、剪辑、剧情等相关内容 | [/v/sports/basketball](https://www.bilibili.com/v/sports/basketball) | +| 足球 | football | 249 | 与足球相关的视频,包括但不限于足球赛事、教学、评述、剪辑、剧情等相关内容 | [/v/sports/football](https://www.bilibili.com/v/sports/football) | +| 健身 | aerobics | 164 | 与健身相关的视频,包括但不限于瑜伽、CrossFit、健美、力量举、普拉提、街健等相关内容 | [/v/sports/aerobics](https://www.bilibili.com/v/sports/aerobics) | +| 竞技体育 | athletic | 236 | 与竞技体育相关的视频,包括但不限于乒乓、羽毛球、排球、赛车等竞技项目的赛事、评述、剪辑、剧情等相关内容 | [/v/sports/culture](https://www.bilibili.com/v/sports/culture) | +| 运动文化 | culture | 237 | 与运动文化相关的视频,包络但不限于球鞋、球衣、球星卡等运动衍生品的分享、解读,体育产业的分析、科普等相关内容 | [/v/sports/culture](https://www.bilibili.com/v/sports/culture) | +| 运动综合 | comprehensive | 238 | 与运动综合相关的视频,包括但不限于钓鱼、骑行、滑板等日常运动分享、教学、Vlog等相关内容 | [/v/sports/comprehensive](https://www.bilibili.com/v/sports/comprehensive) | + +## 汽车 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|---------------|------------------|---------|---------------------------------------------------------------|----------------------------------------------------------------------------| +| 汽车(主分区) | car | 223 | | [/v/car](https://www.bilibili.com/v/car) | +| 汽车知识科普 | knowledge | 258 | 关于汽车技术与文化的硬核科普,以及生活中学车、用车、养车的相关知识 | [/v/car/knowledge](https://www.bilibili.com/v/car/knowledge) | +| 购车攻略 | strategy | 227 | 丰富详实的购车建议和新车体验 | [/v/car/strategy](https://www.bilibili.com/v/car/strategy) | +| 新能源车 | newenergyvehicle | 247 | 新能源汽车相关内容,包括电动汽车、混合动力汽车等车型种类,包含不限于新车资讯、试驾体验、专业评测、技术解读、知识科普等内容 | [/v/car/newenergyvehicle](https://www.bilibili.com/v/car/newenergyvehicle) | +| 赛车 | racing | 245 | F1等汽车运动相关 | [/v/car/racing](https://www.bilibili.com/v/car/racing) | +| 改装玩车 | modifiedvehicle | 246 | 汽车文化及改装车相关内容,包括改装车、老车修复介绍、汽车聚会分享等内容 | [/v/car/modifiedvehicle](https://www.bilibili.com/v/car/modifiedvehicle) | +| 摩托车 | motorcycle | 240 | 骑士们集合啦 | [/v/car/motorcycle](https://www.bilibili.com/v/car/motorcycle) | +| 房车 | touringcar | 248 | 房车及营地相关内容,包括不限于产品介绍、驾驶体验、房车生活和房车旅行等内容 | [/v/car/touringcar](https://www.bilibili.com/v/car/touringcar) | +| 汽车生活 | life | 176 | 分享汽车及出行相关的生活体验类视频 | [/v/car/life](https://www.bilibili.com/v/car/life) | +| ~~汽车文化~~(已下线) | ~~culture~~ | ~~224~~ | ~~车迷的精神圣地,包括汽车赛事、品牌历史、汽车改装、经典车型和汽车模型等~~ | ~~/v/car/culture~~ | +| ~~汽车极客~~(已下线) | ~~geek~~ | ~~225~~ | ~~汽车硬核达人聚集地,包括DIY造车、专业评测和技术知识分享~~ | ~~/v/car/geek~~ | +| ~~智能出行~~(已下线) | ~~smart~~ | ~~226~~ | ~~探索新能源汽车和未来智能出行的前沿阵地~~ | ~~/v/car/smart~~ | + +## 生活 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|--------------|----------------|---------|-----------------------------------|----------------------------------------------------------------| +| 生活(主分区) | life | 160 | | [/v/life](https://www.bilibili.com/v/life) | +| 搞笑 | funny | 138 | 各种沙雕有趣的搞笑剪辑,挑战,表演,配音等视频 | [/v/life/funny](https://www.bilibili.com/v/life/funny) | +| 亲子 | parenting | 254 | 分享亲子、萌娃、母婴、育儿相关的视频 | [/v/life/parenting](https://www.bilibili.com/v/life/parenting) | +| 出行 | travel | 250 | 为达到观光游览、休闲娱乐为目的的远途旅行、中近途户外生活、本地探店 | [/v/life/travel](https://www.bilibili.com/v/life/travel) | +| 三农 | rurallife | 251 | 分享美好农村生活 | [/v/life/rurallife](https://www.bilibili.com/v/life/rurallife) | +| 家居房产 | home | 239 | 与买房、装修、居家生活相关的分享 | [/v/life/home](https://www.bilibili.com/v/life/home) | +| 手工 | 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) | +| ~~美食圈~~(重定向) | ~~food~~ | ~~76~~ | ~~美食鉴赏&料理制作教程~~ | ~~/v/life/food~~ | +| ~~动物圈~~(重定向) | ~~animal~~ | ~~75~~ | ~~萌萌的动物都在这里哦~~ | ~~/v/life/animal~~ | +| ~~运动~~(重定向) | ~~sports~~ | ~~163~~ | ~~运动相关的记录、教程、装备评测和精彩瞬间剪辑视频~~ | ~~/v/life/sports~~ | +| ~~汽车~~(重定向) | ~~automobile~~ | ~~176~~ | ~~专业汽车资讯,分享车生活~~ | ~~/v/life/automobile~~ | +| ~~其他~~(已下线) | ~~other~~ | ~~174~~ | ~~对于分区归属不明的视频进行归纳整合的特定分区~~ | ~~/v/life/other~~ | + +## 美食 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|------------------------|-------------|-----|------------------|--------------------------------------------------------------------| +| 美食(主分区) | food | 211 | | [/v/food](https://www.bilibili.com/v/food) | +| 美食制作(~~原[生活]->[美食圈]~~) | make | 76 | 学做人间美味,展示精湛厨艺 | [/v/food/make](https://www.bilibili.com/v/food/make) | +| 美食侦探 | detective | 212 | 寻找美味餐厅,发现街头美食 | [/v/food/detective](https://www.bilibili.com/v/food/detective) | +| 美食测评 | measurement | 213 | 吃货世界,品尝世间美味 | [/v/food/measurement](https://www.bilibili.com/v/food/measurement) | +| 田园美食 | rural | 214 | 品味乡野美食,寻找山与海的味道 | [/v/food/rural](https://www.bilibili.com/v/food/rural) | +| 美食记录 | record | 215 | 记录一日三餐,给生活添一点幸福感 | [/v/food/record](https://www.bilibili.com/v/food/record) | + +## 动物圈 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|----------|------------------|-----|-------------------------------------------|----------------------------------------------------------------------------------| +| 动物圈(主分区) | animal | 217 | | [/v/animal](https://www.bilibili.com/v/animal) | +| 喵星人 | cat | 218 | 喵喵喵喵喵 | [/v/animal/cat](https://www.bilibili.com/v/animal/cat) | +| 汪星人 | dog | 219 | 汪汪汪汪汪 | [/v/animal/dog](https://www.bilibili.com/v/animal/dog) | +| 小宠异宠 | reptiles | 222 | 奇妙宠物大赏 | [/v/animal/reptiles](https://www.bilibili.com/v/animal/reptiles) | +| 野生动物 | wild_animal | 221 | 内有“猛兽”出没 | [/v/animal/wild_animal](https://www.bilibili.com/v/animal/wild_animal) | +| 动物二创 | second_edition | 220 | 解说、配音、剪辑、混剪 | [/v/animal/second_edition](https://www.bilibili.com/v/animal/second_edition) | +| 动物综合 | animal_composite | 75 | 收录除上述子分区外,其余动物相关视频以及非动物主体或多个动物主体的动物相关延伸内容 | [/v/animal/animal_composite](https://www.bilibili.com/v/animal/animal_composite) | + +## 鬼畜 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|------------|-----------------|-----|-----------------------------------------|----------------------------------------------------------------------------------| +| 鬼畜(主分区) | kichiku | 119 | | [/v/kichiku](https://www.bilibili.com/v/kichiku) | +| 鬼畜调教 | guide | 22 | 使用素材在音频、画面上做一定处理,达到与BGM一定的同步感 | [/v/kichiku/guide](https://www.bilibili.com/v/kichiku/guide) | +| 音MAD | mad | 26 | 使用素材音频进行一定的二次创作来达到还原原曲的非商业性质稿件 | [/v/kichiku/mad/v/kichiku/mad](https://www.bilibili.com/v/kichiku/mad) | +| 人力VOCALOID | manual_vocaloid | 126 | 将人物或者角色的无伴奏素材进行人工调音,使其就像VOCALOID一样歌唱的技术 | [/v/kichiku/manual_vocaloid](https://www.bilibili.com/v/kichiku/manual_vocaloid) | +| 鬼畜剧场 | theatre | 216 | 使用素材进行人工剪辑编排的有剧情的作品 | [/v/kichiku/theatre](https://www.bilibili.com/v/kichiku/theatre) | +| 教程演示 | course | 127 | 鬼畜相关的教程演示 | [/v/kichiku/course](https://www.bilibili.com/v/kichiku/course) | + +## 时尚 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|--------------|--------------|---------|---------------------------------------------|--------------------------------------------------------------------| +| 时尚(主分区) | fashion | 155 | | [/v/fashion](https://www.bilibili.com/v/fashion) | +| 美妆护肤 | makeup | 157 | 彩妆护肤、美甲美发、仿妆、医美相关内容分享或产品测评 | [/v/fashion/makeup](https://www.bilibili.com/v/fashion/makeup) | +| 仿妆cos | cos | 252 | 对二次元、三次元人物角色进行模仿、还原、展示、演绎的内容 | [/v/fashion/cos](https://www.bilibili.com/v/fashion/cos) | +| 穿搭 | clothing | 158 | 穿搭风格、穿搭技巧的展示分享,涵盖衣服、鞋靴、箱包配件、配饰(帽子、钟表、珠宝首饰)等 | [/v/fashion/clothing](https://www.bilibili.com/v/fashion/clothing) | +| 时尚潮流 | catwalk | 159 | 时尚街拍、时装周、时尚大片,时尚品牌、潮流等行业相关记录及知识科普 | [/v/fashion/catwalk](https://www.bilibili.com/v/fashion/catwalk) | +| ~~健身~~(重定向) | ~~aerobics~~ | ~~164~~ | ~~器械、有氧、拉伸运动等,以达到强身健体、减肥瘦身、形体塑造目的~~ | ~~/v/fashion/aerobics~~ | +| ~~风尚标~~(已下线) | ~~trends~~ | ~~192~~ | ~~时尚明星专访、街拍、时尚购物相关知识科普~~ | ~~/v/fashion/trends~~ | + +## 资讯 + +**注:该分区无排名功能** + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|---------|-------------|-----|------------------------|----------------------------------------------------------------------------| +| 资讯(主分区) | information | 202 | | [/v/information](https://www.bilibili.com/v/information) | +| 热点 | hotspot | 203 | 全民关注的时政热门资讯 | [/v/information/hotspot](https://www.bilibili.com/v/information/hotspot) | +| 环球 | global | 204 | 全球范围内发生的具有重大影响力的事件动态 | [/v/information/global](https://www.bilibili.com/v/information/global) | +| 社会 | social | 205 | 日常生活的社会事件、社会问题、社会风貌的报道 | [/v/information/social](https://www.bilibili.com/v/information/social) | +| 综合 | multiple | 206 | 除上述领域外其它垂直领域的综合资讯 | [/v/information/multiple](https://www.bilibili.com/v/information/multiple) | + +## 广告 + + + +**该分区已下线** + +| 名称 | 代号 | tid | 简介 | url路由 | +|-------------|--------|---------|-----|--------------| +| ~~广告(主分区)~~ | ~~ad~~ | ~~165~~ | | ~~/v/ad~~ | +| ~~广告~~(已下线) | ~~ad~~ | ~~166~~ | | ~~/v/ad/ad~~ | + +## 娱乐 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|-----------------------|--------------------|---------|------------------------------------------|--------------------------------------------------------------------------------| +| 娱乐(主分区) | ent | 5 | | [/v/ent](https://www.bilibili.com/v/ent) | +| 娱乐杂谈 | talker | 241 | 娱乐人物解读、娱乐热点点评、娱乐行业分析 | [/v/ent/talker](https://www.bilibili.com/v/ent/talker) | +| CP安利 | cp_recommendation | 262 | 以安利各类娱乐名人、角色CP之间默契于火花为主题的混剪、解说,观点表达类视频 | [/v/ent/cp_recommendation](https://www.bilibili.com/v/ent/cp_recommendation) | +| 颜值安利 | beauty | 263 | 以各类娱乐名人、角色的颜值、气质魅力为核心的混剪视频 | [/v/ent/beauty](https://www.bilibili.com/v/ent/beauty) | +| 娱乐粉丝创作
(~~原粉丝创作~~) | fans | 242 | 粉丝向创作视频 | [/v/ent/fans](https://www.bilibili.com/v/ent/fans) | +| 娱乐资讯 | entertainment_news | 264 | 具备趣味价值的文化娱乐新闻与动态报道,如名人动态,作品发布,舞台演出,趣闻盘点等 | [/v/ent/entertainment_news](https://www.bilibili.com/v/ent/entertainment_news) | +| 明星综合 | celebrity | 137 | 娱乐圈动态、明星资讯相关 | [/v/ent/celebrity](https://www.bilibili.com/v/ent/celebrity) | +| 综艺 | variety | 71 | 所有综艺相关,全部一手掌握! | [/v/ent/variety](https://www.bilibili.com/v/ent/variety) | +| ~~Korea相关~~(已下线) | ~~korea~~ | ~~131~~ | ~~Korea相关音乐、舞蹈、综艺等视频~~ | ~~/v/ent/korea~~ | + +## 影视 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|---------|---------------|-----|-------------------------------|----------------------------------------------------------------------------------| +| 影视(主分区) | cinephile | 181 | | [/v/cinephile](https://www.bilibili.com/v/cinephile) | +| 影视杂谈 | cinecism | 182 | 影视评论、解说、吐槽、科普等 | [/v/cinephile/cinecism](https://www.bilibili.com/v/cinephile/cinecism) | +| 影视剪辑 | montage | 183 | 对影视素材进行剪辑再创作的视频 | [/v/cinephile/montage](https://www.bilibili.com/v/cinephile/montage) | +| 影视整活 | mashup | 260 | 使用影视素材制造的有趣、有梗的创意混剪、配音、特效玩梗视频 | [/v/cinephile/mashup](https://www.bilibili.com/v/cinephile/mashup) | +| AI影像 | ai_imaging | 259 | 分享AI制作的影像作品、创作历程、技术风向 | [/v/cinephile/ai_imaging](https://www.bilibili.com/v/cinephile/ai_imaging) | +| 预告·资讯 | trailer_info | 184 | 影视类相关资讯,预告,花絮等视频 | [/v/cinephile/trailer_info](https://www.bilibili.com/v/cinephile/trailer_info) | +| 小剧场 | shortplay | 85 | 有场景、有剧情的演绎类内容 | [/v/cinephile/shortplay](https://www.bilibili.com/v/cinephile/shortplay) | +| 短片 | shortfilm | 256 | 各种类型的短片 | [/v/cinephile/shortfilm](https://www.bilibili.com/v/cinephile/shortfilm) | +| 影视综合 | comprehensive | 261 | 一切无法被收纳其他影视二级分区的影视相关内容 | [/v/cinephile/comprehensive](https://www.bilibili.com/v/cinephile/comprehensive) | + +## 纪录片 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|----------|-------------|-----|----|----------------------------------------------------------------------------| +| 纪录片(主分区) | documentary | 177 | | [/documentary](https://www.bilibili.com/documentary) | +| 人文·历史 | history | 37 | | [/v/documentary/history](https://www.bilibili.com/v/documentary/history) | +| 科学·探索·自然 | science | 178 | | [/v/documentary/science](https://www.bilibili.com/v/documentary/science) | +| 军事 | military | 179 | | [/v/documentary/military](https://www.bilibili.com/v/documentary/military) | +| 社会·美食·旅行 | travel | 180 | | [/v/documentary/travel](https://www.bilibili.com/v/documentary/travel) | + +## 电影 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|---------|---------|-----|-----|--------------------------------------------------------------| +| 电影(主分区) | movie | 23 | | [/movie](https://www.bilibili.com/movie) | +| 华语电影 | chinese | 147 | | [/v/movie/chinese](https://www.bilibili.com/v/movie/chinese) | +| 欧美电影 | west | 145 | | [/v/movie/west](https://www.bilibili.com/v/movie/west) | +| 日本电影 | japan | 146 | | [/v/movie/japan](https://www.bilibili.com/v/movie/japan) | +| 其他国家 | movie | 83 | | [/v/movie/movie](https://www.bilibili.com/v/movie/movie) | + +## 电视剧 + + + +| 名称 | 代号 | tid | 简介 | url路由 | +|----------|----------|-----|-----|----------------------------------------------------------| +| 电视剧(主分区) | tv | 11 | | [/tv](https://www.bilibili.com/tv) | +| 国产剧 | mainland | 185 | | [/v/tv/mainland](https://www.bilibili.com/v/tv/mainland) | +| 海外剧 | overseas | 187 | | [/v/tv/overseas](https://www.bilibili.com/v/tv/overseas) | diff --git a/bb-api-collect/docs/video/video_zone_v2.md b/bb-api-collect/docs/video/video_zone_v2.md new file mode 100644 index 0000000000..247c122ea5 --- /dev/null +++ b/bb-api-collect/docs/video/video_zone_v2.md @@ -0,0 +1,458 @@ +# 视频分区一览 (v2) + +本文档中的内容适用于 `tid_v2`(部分接口写为 `tidv2`)、`tname_v2`(部分接口写为 `tnamev2`)等字段,关于 `tid`、`tname` 等字段请参阅 “[视频分区一览](./video_zone.md)” 文档 + +目前 B 站尚未启用子分区 + +## 动画 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ------------- | ----------- | ---- | --------- | ---------------------------------------------- | +| 动画 (主分区) | douga | 1005 | 7 | [/c/douga/](https://www.bilibili.com/c/douga/) | +| 同人动画 | fan_anime | 2037 | | | +| 模玩周边 | garage_kit | 2038 | | | +| cosplay | cosplay | 2039 | | | +| 二次元线下 | offline | 2040 | | | +| 动漫剪辑 | editing | 2041 | | | +| 动漫评论 | commentary | 2042 | | | +| 动漫速读 | quick_view | 2043 | | | +| 动漫配音 | voice | 2044 | | | +| 动漫资讯 | information | 2045 | | | +| 网文解读 | interpret | 2046 | | | +| 虚拟up主 | vup | 2047 | | | +| 特摄 | tokusatsu | 2048 | | | +| 布袋戏 | puppetry | 2049 | | | +| 漫画·动态漫 | comic | 2050 | | | +| 广播剧 | motion | 2051 | | | +| 动漫reaction | reaction | 2052 | | | +| 动漫教学 | tutorial | 2053 | | | +| 二次元其他 | other | 2054 | | | + +## 游戏 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| -------------- | ----------- | ---- | --------- | -------------------------------------------- | +| 游戏 (主分区) | game | 1008 | 8 | [/c/game/](https://www.bilibili.com/c/game/) | +| 单人RPG游戏 | rpg | 2064 | | | +| MMORPG游戏 | mmorpg | 2065 | | | +| 单机主机类游戏 | stand_alone | 2066 | | | +| SLG游戏 | slg | 2067 | | | +| 回合制策略游戏 | tbs | 2068 | | | +| 即时策略游戏 | rts | 2069 | | | +| MOBA游戏 | moba | 2070 | | | +| 射击游戏 | stg | 2071 | | | +| 体育竞速游戏 | spg | 2072 | | | +| 动作竞技游戏 | act | 2073 | | | +| 音游舞游 | msc | 2074 | | | +| 模拟经营游戏 | sim | 2075 | | | +| 女性向游戏 | otome | 2076 | | | +| 休闲/小游戏 | puz | 2077 | | | +| 沙盒类 | sandbox | 2078 | | | +| 其他游戏 | other | 2079 | | | + +## 鬼畜 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ------------- | --------------- | ---- | --------- | -------------------------------------------------- | +| 鬼畜 (主分区) | kichiku | 1007 | 9 | [/c/kichiku/](https://www.bilibili.com/c/kichiku/) | +| 鬼畜调教 | guide | 2059 | | | +| 鬼畜剧场 | theatre | 2060 | | | +| 人力VOCALOID | manual_vocaloid | 2061 | | | +| 音MAD | mad | 2062 | | | +| 鬼畜综合 | other | 2063 | | | + +## 音乐 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ------------- | ---------- | ---- | --------- | ---------------------------------------------- | +| 音乐 (主分区) | music | 1003 | 10 | [/c/music/](https://www.bilibili.com/c/music/) | +| 原创音乐 | original | 2016 | | | +| MV | mv | 2017 | | | +| 音乐现场 | live | 2018 | | | +| 乐迷饭拍 | fan_videos | 2019 | | | +| 翻唱 | cover | 2020 | | | +| 演奏 | perform | 2021 | | | +| VOCALOID | vocaloid | 2022 | | | +| AI音乐 | ai_music | 2023 | | | +| 电台·歌单 | radio | 2024 | | | +| 音乐教学 | tutorial | 2025 | | | +| 乐评盘点 | commentary | 2026 | | | +| 音乐综合 | other | 2027 | | | + +## 舞蹈 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ------------- | -------- | ---- | --------- | ---------------------------------------------- | +| 舞蹈 (主分区) | dance | 1004 | 11 | [/c/dance/](https://www.bilibili.com/c/dance/) | +| 宅舞 | otaku | 2028 | | | +| 街舞 | hiphop | 2029 | | | +| 颜值·网红舞 | gestures | 2030 | | | +| 明星舞蹈 | star | 2031 | | | +| 国风舞蹈 | china | 2032 | | | +| 舞蹈教学 | tutorial | 2033 | | | +| 芭蕾舞 | ballet | 2034 | | | +| wota艺 | wota | 2035 | | | +| 舞蹈综合 | other | 2036 | | | + +## 影视 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ------------- | ----------- | ---- | --------- | ------------------------------------------------------ | +| 影视 (主分区) | cinephile | 1001 | 12 | [/c/cinephile/](https://www.bilibili.com/c/cinephile/) | +| 影视解读 | commentary | 2001 | | | +| 影视剪辑 | montage | 2002 | | | +| 影视资讯 | information | 2003 | | | +| 影视正片搬运 | porterage | 2004 | | | +| 短剧短片 | shortfilm | 2005 | | | +| AI影视 | ai | 2006 | | | +| 影视reaction | reaction | 2007 | | | +| 影视综合 | other | 2008 | | | + +## 娱乐 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ------------- | ----------- | ---- | --------- | ------------------------------------------ | +| 娱乐 (主分区) | ent | 1002 | 13 | [/c/ent/](https://www.bilibili.com/c/ent/) | +| 娱乐评论 | commentary | 2009 | | | +| 明星剪辑 | montage | 2010 | | | +| 娱乐饭拍&现场 | fans_video | 2011 | | | +| 娱乐资讯 | information | 2012 | | | +| 娱乐reaction | reaction | 2013 | | | +| 娱乐综艺正片 | variety | 2014 | | | +| 娱乐综合 | other | 2015 | | | + +## 知识 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| -------------- | ------------------ | ---- | --------- | ------------------------------------------------------ | +| 知识 (主分区) | knowledge | 1010 | 14 | [/c/knowledge/](https://www.bilibili.com/c/knowledge/) | +| 应试教育 | exam | 2084 | | | +| 非应试语言学习 | lang_skill | 2085 | | | +| 大学专业知识 | campus | 2086 | | | +| 商业财经 | business | 2087 | | | +| 社会观察 | social_observation | 2088 | | | +| 时政解读 | politics | 2089 | | | +| 人文历史 | humanity_history | 2090 | | | +| 设计艺术 | design | 2091 | | | +| 心理杂谈 | psychology | 2092 | | | +| 职场发展 | career | 2093 | | | +| 科学科普 | science | 2094 | | | +| 其他知识杂谈 | other | 2095 | | | + +## 科技数码 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ----------------- | ----------- | ---- | --------- | -------------------------------------------- | +| 科技数码 (主分区) | tech | 1012 | 15 | [/c/tech/](https://www.bilibili.com/c/tech/) | +| 电脑 | computer | 2099 | | | +| 手机 | phone | 2100 | | | +| 平板电脑 | pad | 2101 | | | +| 摄影摄像 | photography | 2102 | | | +| 工程机械 | machine | 2103 | | | +| 自制发明/设备 | create | 2104 | | | +| 科技数码综合 | other | 2105 | | | + +## 资讯 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ------------- | ----------- | ---- | --------- | ---------------------------------------------------------- | +| 资讯 (主分区) | information | 1009 | 16 | [/c/information/](https://www.bilibili.com/c/information/) | +| 时政资讯 | politics | 2080 | | | +| 海外资讯 | overseas | 2081 | | | +| 社会资讯 | social | 2082 | | | +| 综合资讯 | other | 2083 | | | + +## 美食 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ------------- | ---------- | ---- | --------- | -------------------------------------------- | +| 美食 (主分区) | food | 1020 | 17 | [/c/food/](https://www.bilibili.com/c/food/) | +| 美食制作 | make | 2149 | | | +| 美食探店 | detective | 2150 | | | +| 美食测评 | commentary | 2151 | | | +| 美食记录 | record | 2152 | | | +| 美食综合 | other | 2153 | | | + +## 小剧场 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| --------------- | ---------- | ---- | --------- | ------------------------------------------------------ | +| 小剧场 (主分区) | shortplay | 1021 | 18 | [/c/shortplay/](https://www.bilibili.com/c/shortplay/) | +| 剧情演绎 | plot | 2154 | | | +| 语言类小剧场 | lang | 2155 | | | +| UP主小综艺 | up_variety | 2156 | | | +| 街头采访 | interview | 2157 | | | + +## 汽车 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ------------- | ---------- | ---- | --------- | ---------------------------------------- | +| 汽车 (主分区) | car | 1013 | 19 | [/c/car](https://www.bilibili.com/c/car) | +| 汽车测评 | commentary | 2106 | | | +| 汽车文化 | culture | 2107 | | | +| 汽车生活 | life | 2108 | | | +| 汽车技术 | tech | 2109 | | | +| 汽车综合 | other | 2110 | | | + +## 时尚美妆 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ----------------- | ----------- | ---- | --------- | -------------------------------------------------- | +| 时尚美妆 (主分区) | fashion | 1014 | 20 | [/c/fashion/](https://www.bilibili.com/c/fashion/) | +| 美妆 | makeup | 2111 | | | +| 护肤 | skincare | 2112 | | | +| 仿装cos | cos | 2113 | | | +| 鞋服穿搭 | outfits | 2114 | | | +| 箱包配饰 | accessories | 2115 | | | +| 珠宝首饰 | jewelry | 2116 | | | +| 三坑 | trick | 2117 | | | +| 时尚解读 | commentary | 2118 | | | +| 时尚综合 | other | 2119 | | | + +## 体育运动 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ----------------- | ----------- | ---- | --------- | ------------------------------------------------ | +| 体育运动 (主分区) | sports | 1018 | 21 | [/c/sports/](https://www.bilibili.com/c/sports/) | +| 潮流运动 | trend | 2133 | | | +| 足球 | football | 2134 | | | +| 篮球 | basketball | 2135 | | | +| 跑步 | running | 2136 | | | +| 武术 | kungfu | 2137 | | | +| 格斗 | fighting | 2138 | | | +| 羽毛球 | badminton | 2139 | | | +| 体育资讯 | information | 2140 | | | +| 体育赛事 | match | 2141 | | | +| 体育综合 | other | 2142 | | | + +## 动物 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| --------------------- | -------- | ---- | --------- | ------------------------------------------------ | +| 动物 (主分区) | animal | 1024 | 22 | [/c/animal/](https://www.bilibili.com/c/animal/) | +| 猫 | cat | 2167 | | | +| 狗 | dog | 2168 | | | +| 小宠异宠 | reptiles | 2169 | | | +| 野生动物·动物解说科普 | science | 2170 | | | +| 动物综合·二创 | other | 2171 | | | + +## vlog + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ------------- | ------- | ---- | --------- | -------------------------------------------- | +| vlog (主分区) | vlog | 1029 | 23 | [/c/vlog/](https://www.bilibili.com/c/vlog/) | +| 中外生活vlog | life | 2194 | | | +| 学生vlog | student | 2195 | | | +| 职业vlog | career | 2196 | | | +| 其他vlog | other | 2197 | | | + +## 绘画 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ------------- | -------- | ---- | --------- | ---------------------------------------------------- | +| 绘画 (主分区) | painting | 1006 | 24 | [/c/painting/](https://www.bilibili.com/c/painting/) | +| 二次元绘画 | acg | 2055 | | | +| 非二次元绘画 | none_acg | 2056 | | | +| 绘画学习 | tutorial | 2057 | | | +| 绘画综合 | other | 2058 | | | + +## 人工智能 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ----------------- | ----------- | ---- | --------- | ---------------------------------------- | +| 人工智能 (主分区) | ai | 1011 | 25 | [/c/ai/](https://www.bilibili.com/c/ai/) | +| AI学习 | tutorial | 2096 | | | +| AI资讯 | information | 2097 | | | +| AI杂谈 | other | 2098 | | | + +## 家装房产 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ----------------- | ---------- | ---- | --------- | -------------------------------------------- | +| 家装房产 (主分区) | home | 1015 | 26 | [/c/home/](https://www.bilibili.com/c/home/) | +| 买房租房 | trade | 2120 | | | +| 家庭装修 | renovation | 2121 | | | +| 家居展示 | furniture | 2122 | | | +| 家用电器 | appliances | 2123 | | | + +## 户外潮流 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ----------------- | -------- | ---- | --------- | ---------------------------------------------------- | +| 户外潮流 (主分区) | outdoors | 1016 | 27 | [/c/outdoors/](https://www.bilibili.com/c/outdoors/) | +| 露营 | camping | 2124 | | | +| 徒步 | hiking | 2125 | | | +| 户外探秘 | explore | 2126 | | | +| 户外综合 | other | 2127 | | | + +## 健身 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ------------- | -------- | ---- | --------- | ------------------------------------------ | +| 健身 (主分区) | gym | 1017 | 28 | [/c/gym/](https://www.bilibili.com/c/gym/) | +| 健身科普 | science | 2128 | | | +| 健身跟练教学 | tutorial | 2129 | | | +| 健身记录 | record | 2130 | | | +| 健身身材展示 | figure | 2131 | | | +| 健身综合 | other | 2132 | | | + +## 手工 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ------------- | ----------- | ---- | --------- | ---------------------------------------------------- | +| 手工 (主分区) | handmake | 1019 | 29 | [/c/handmake/](https://www.bilibili.com/c/handmake/) | +| 文具手帐 | handbook | 2143 | | | +| 轻手作 | light | 2144 | | | +| 传统手工艺 | traditional | 2145 | | | +| 解压手工 | relief | 2146 | | | +| DIY玩具 | diy | 2147 | | | +| 其他手工 | other | 2148 | | | + +## 旅游出行 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ----------------- | --------- | ---- | --------- | ------------------------------------------------ | +| 旅游出行 (主分区) | travel | 1022 | 30 | [/c/travel/](https://www.bilibili.com/c/travel/) | +| 旅游记录 | record | 2158 | | | +| 旅游攻略 | strategy | 2159 | | | +| 城市出行 | city | 2160 | | | +| 公共交通 | transport | 2161 | | | + +## 三农 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ------------- | -------- | ---- | --------- | ---------------------------------------------- | +| 三农 (主分区) | rural | 1023 | 31 | [/c/rural/](https://www.bilibili.com/c/rural/) | +| 农村种植 | planting | 2162 | | | +| 赶海捕鱼 | fishing | 2163 | | | +| 打野采摘 | harvest | 2164 | | | +| 农业技术 | tech | 2165 | | | +| 农村生活 | life | 2166 | | | + +## 亲子 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ------------- | ------------- | ---- | --------- | ------------------------------------------------------ | +| 亲子 (主分区) | parenting | 1025 | 32 | [/c/parenting/](https://www.bilibili.com/c/parenting/) | +| 孕产护理 | pregnant_care | 2172 | | | +| 婴幼护理 | infant_care | 2173 | | | +| 儿童才艺 | talent | 2174 | | | +| 萌娃 | cute | 2175 | | | +| 亲子互动 | interaction | 2176 | | | +| 亲子教育 | education | 2177 | | | +| 亲子综合 | other | 2178 | | | + +## 健康 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ------------- | ---------- | ---- | --------- | ------------------------------------------------ | +| 健康 (主分区) | health | 1026 | 33 | [/c/health/](https://www.bilibili.com/c/health/) | +| 健康科普 | science | 2179 | | | +| 养生 | regimen | 2180 | | | +| 两性知识 | sexes | 2181 | | | +| 心理健康 | psychology | 2182 | | | +| 助眠视频·ASMR | asmr | 2183 | | | +| 医疗保健综合 | other | 2184 | | | + +## 情感 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ------------- | ------------- | ---- | --------- | -------------------------------------------------- | +| 情感 (主分区) | emotion | 1027 | 34 | [/c/emotion/](https://www.bilibili.com/c/emotion/) | +| 家庭关系 | family | 2185 | | | +| 恋爱关系 | romantic | 2186 | | | +| 人际关系 | interpersonal | 2187 | | | +| 自我成长 | growth | 2188 | | | + +## 生活兴趣 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ----------------- | ----------------- | ---- | --------- | ---------------------------------------------------- | +| 生活兴趣 (主分区) | life_joy | 1030 | 35 | [/c/life_joy/](https://www.bilibili.com/c/life_joy/) | +| 休闲玩乐 | leisure | 2198 | | | +| 线下演出 | on_site | 2199 | | | +| 文玩文创 | artistic_products | 2200 | | | +| 潮玩玩具 | trendy_toys | 2201 | | | +| 兴趣综合 | other | 2202 | | | + +## 生活经验 + + + +| 名称 | 代号 | tid | channelId | url 路由 | +| ----------------- | --------------- | ---- | --------- | ------------------------------------------------------------------ | +| 生活经验 (主分区) | life_experience | 1031 | 36 | [/c/life_experience/](https://www.bilibili.com/c/life_experience/) | +| 生活技能 | skills | 2203 | | | +| 办事流程 | procedures | 2204 | | | +| 婚嫁 | marriage | 2205 | | | + +## 神秘学 (未公开) + +该分区未出现在 B 站前端的界面中,也无图标 + +| 名称 | 代号 | tid | channelId | url 路由 | +| --------------- | ----------- | ---- | --------- | ------------------------------------------------------ | +| 神秘学 (主分区) | mysticism | 1028 | 44 | [/c/mysticism/](https://www.bilibili.com/c/mysticism/) | +| 塔罗占卜 | tarot | 2189 | | | +| 星座占星 | horoscope | 2190 | | | +| 传统玄学 | metaphysics | 2191 | | | +| 疗愈成长 | healing | 2192 | | | +| 其他神秘学 | other | 2193 | | | diff --git a/bb-api-collect/docs/video/videostream_url.md b/bb-api-collect/docs/video/videostream_url.md new file mode 100644 index 0000000000..d808d71268 --- /dev/null +++ b/bb-api-collect/docs/video/videostream_url.md @@ -0,0 +1,1951 @@ +# 视频流URL + + + +视频为 DASH 或 MP4 流媒体,需调用取流 API 传参视频 id 获取 + +## qn视频清晰度标识 + +注:该值在 DASH 格式下无效,因为 DASH 格式会取到所有分辨率的流地址 + +又注: B站对于新的视频更新了播放设置, 较高分辨率均采用 DASH, 较低分辨率与老视频还保留了 MP4, 这导致较新视频无法获取 MP4 格式的高分辨率视频, 参见 [#606](https://github.com/SocialSisterYi/bilibili-API-collect/issues/606) 或 [cv949156](https://www.bilibili.com/read/cv949156/) + +| 值 | 含义 | 备注 | +| ---- | -------------- | ------------------------------------------------------------ | +| 6 | 240P 极速 | 仅 MP4 格式支持
仅`platform=html5`时有效 | +| 16 | 360P 流畅 | | +| 32 | 480P 清晰 | | +| 64 | 720P 高清 | WEB 端默认值
~~B站前端需要登录才能选择,但是直接发送请求可以不登录就拿到 720P 的取流地址~~
**无 720P 时则为 720P60** | +| 74 | 720P60 高帧率 | 登录认证 | +| 80 | 1080P 高清 | TV 端与 APP 端默认值
登录认证 | +| 100 | 智能修复 | 人工智能增强画质
大会员认证 +| 112 | 1080P+ 高码率 | 大会员认证 | +| 116 | 1080P60 高帧率 | 大会员认证 | +| 120 | 4K 超清 | 需要`fnval&128=128`且`fourk=1`
大会员认证 | +| 125 | HDR 真彩色 | 仅支持 DASH 格式
需要`fnval&64=64`
大会员认证 | +| 126 | 杜比视界 | 仅支持 DASH 格式
需要`fnval&512=512`
大会员认证 | +| 127 | 8K 超高清 | 仅支持 DASH 格式
需要`fnval&1024=1024`
大会员认证 | +| 129 | HDR Vivid | 大会员认证 | + +例如:请求 1080P+ 的视频,则`qn=112` + +## fnver视频流版本标识 + +目前该值恒为 0,即`fnver=0` + +## fnval视频流格式标识 + +该代码为二进制属性位,如需组合功能需要使用`OR`运算结合一下数值 + +目前 FLV 格式已下线,应避免使用`fnval=0` + +| 值 | 含义 | 备注 | +| ---- | ------------------ | ------------------------------------------------------------ | +| ~~0~~ | ~~FLV 格式~~ | FLV 格式已下线
~~仅 H.264 编码
部分老视频存在分段现象
与 MP4、DASH 格式互斥~~ | +| 1 | MP4 格式 | 仅 H.264 编码
与 ~~FLV~~、DASH 格式互斥 | +| 16 | DASH 格式 | 与 MP4、~~FLV~~ 格式互斥 | +| 64 | 是否需求 HDR 视频 | 需求 DASH 格式
仅 H.265 编码
需要`qn=125`
大会员认证 | +| 128 | 是否需求 4K 分辨率 | 该值与`fourk`字段协同作用
需要`qn=120`
大会员认证 | +| 256 | 是否需求杜比音频 | 需求 DASH 格式
大会员认证 | +| 512 | 是否需求杜比视界 | 需求 DASH 格式
大会员认证 | +| 1024 | 是否需求 8K 分辨率 | 需求 DASH 格式
需要`qn=127`
大会员认证 | +| 2048 | 是否需求 AV1 编码 | 需求 DASH 格式 | +| 4048 | 所有可用 DASH 视频流 | 即一次性返回所有可用 DASH 格式视频流 | +| 16384 | 是否需要 HDR Vivid | 需要`qn=129`
大会员认证
仅 APP 接口可用 | + +例如:请求 DASH 格式,且需要 HDR 的视频流,则`fnval=16|64=80` + +## 视频编码代码 + +| 值 | 含义 | 备注 | +| ---- | ---------- | ---------------- | +| 7 | AVC 编码 | 8K 视频不支持该格式 | +| 12 | HEVC 编码 | | +| 13 | AV1 编码 | | + +## 视频伴音音质代码 + +| 值 | 含义 | +| ----- | ---- | +| 30216 | 64K | +| 30232 | 132K | +| 30280 | 192K | +| 30250 | 杜比全景声 | +| 30251 | Hi-Res无损 | + +## 获取视频流地址_web端 + +> https://api.bilibili.com/x/player/wbi/playurl + +> ~~https://api.bilibili.com/x/player/playurl~~ (旧链接) + +*请求方式:GET* + +认证方式:Cookie(SESSDATA) + +鉴权方式:[Wbi 签名](../misc/sign/wbi.md) + +--- + +关于视频流会员鉴权: + +- 获取 720P 及以上清晰度视频时需要登录(Cookie) + +- 获取高帧率(1080P60)/ 高码率(1080P+)/ HDR / 杜比视界 视频时需要有大会员的账号登录(Cookie) + +- 获取会员专属视频时需要登录(Cookie) + +- 部分特殊视频(如平台宣传片、活动视频等)不需要大会员账号认证 + +--- + +获取 url 有效时间为 120min,超时失效需要重新获取 + +~~部分视频会有分段,需要特别注意~~(FLV 格式已下线,不可能出现分段 + +若视频有分P,仅为单P视频的 url,换P则需传参对应 CID 重新获取 + +**url参数:** + +| 参数名 | 类型 | 内容 | 必要性 | 备注 | +| ------ | ---- | ---------------- | ------------ | ------------------------------------------------------------ | +| avid | num | 稿件 avid | 必要(可选) | avid 与 bvid 任选一个 | +| bvid | str | 稿件 bvid | 必要(可选) | avid 与 bvid 任选一个 | +| cid | num | 视频 cid | 必要 | | +| gaia_source | str | view-card
pre-load | 必要(非必要) | 有Cookie(SESSDATA)时无需此参数
暂未找到两个内容值区别 | +| isGaiaAvoided| bool| true/false| 非必要|未知作用 | +| qn | num | 视频清晰度选择 | 非必要 | 未登录默认 32(480P),登录后默认 64(720P)
含义见 [上表](#qn视频清晰度标识)
**DASH 格式时无效** | +| fnval | num | 视频流格式标识 | 非必要 | 默认值为`1`(MP4 格式)
含义见 [上表](#fnval视频流格式标识) | +| fnver | num | 0 | 非必要 | | +| fourk | num | 是否允许 4K 视频 | 非必要 | 画质最高 1080P:0(默认)
画质最高 4K:1 | +| session | str | | 非必要 | 从视频播放页的 HTML 中设置 window.\_\_playinfo\_\_ 处获取,或者通过 buvid3 + 当前UNIX毫秒级时间戳 经过md5获取 | +| otype | str | | 非必要 | 固定为`json` | +| type | str | | 非必要 | 目前为空 | +| platform | str | | 非必要 | pc:web播放(默认值,视频流存在 referer鉴权)
html5:移动端 HTML5 播放(仅支持 MP4 格式,无 referer 鉴权可以直接使用`video`标签播放) | +| high_quality | num | 是否高画质 | 非必要 | platform=html5时,此值为1可使画质为1080p | +| try_look | num | 未登录高画质 | 非必要 | 为 `1` 时可以不登录拉到 `64` 和 `80` 清晰度 | +| cur_language | str | 使用AI原声翻译 | 非必要 | 可以填写`en`、`ja`等参数。
不填写时,默认拉取原音频。填写后,音频链接替换为指定的AI语音 | + +**json回复:** + +根对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------- | ----------------------------- | -------- | ---------------------------------------------- | +| code | num | 返回值 | 0:成功
-400:请求错误
-404:无视频 | +| message | str | 错误信息 | 默认为0 | +| ttl | num | 1 | | +| data | 有效时:obj
无效时:null | 数据本体 | | + +`data`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------ | ----- | ----------------------------------------------- | ----------------------------------------------- | +| v_voucher | str | (?) | 需要参数`gaia_source` | +| from | str | `local`? | | +| result | str | `suee`? | | +| message | str | 空? | | +| quality | num | 清晰度标识 | 含义见 [上表](#qn视频清晰度标识) | +| format | str | 视频格式 | `mp4`/`flv` | +| timelength | num | 视频长度 | 单位为毫秒
不同分辨率 / 格式可能有略微差异 | +| accept_format | str | 支持的全部格式 | 每项用`,`分隔 | +| accept_description | array | 支持的清晰度列表(文字说明) | | +| accept_quality | array | 支持的清晰度列表(代码) | 含义见 [上表](#qn视频清晰度标识) | +| video_codecid | num | 默认选择视频流的编码id | 含义见 [上表](#视频编码代码) | +| seek_param | str | `start`? | | +| seek_type | str | `offset`(DASH / FLV)?
`second`(MP4)? | | +| durl | array | 视频分段流信息 | **注:仅 FLV / MP4 格式存在此字段** | +| dash | obj | DASH 流信息 | **注:仅 DASH 格式存在此字段** | +| support_formats | array | 支持格式的详细信息 | | +| high_format | null | (?) | | +| last_play_time | num | 上次播放进度 | 毫秒值 | +| last_play_cid | num | 上次播放分P的 cid | | +| cur_language | str | 当前的AI原声翻译语言 | `en`、`ja`等,未使用AI原声翻译时,此项为空字符串 | +| language | obj | 视频的AI原声翻译信息 | 视频不支持时,不存在此字段 | + +`data`中的`accept_description`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | str | 分辨率名称1 | | +| n | str | 分辨率名称(n+1) | | +| …… | str | …… | | + +`data`中的`accept_quality`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | -------------------------------- | +| 0 | num | 分辨率代码1 | 含义见 [上表](#qn视频清晰度标识) | +| n | num | 分辨率代码(n+1) | | +| …… | num | …… | | + +`data`中的`support_formats`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | obj | 播放格式详细信息1 | | +| n | obj | 播放格式详细信息(n+1) | | +| …… | obj | …… | | + +`support_formats`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ------ | ------------ | ---------------------------------- | +| quality | num | 视频清晰度代码 | 含义见 [上表](#qn视频清晰度标识) | +| format | str | 视频格式 | | +| new_description | str | 格式描述 | | +| display_desc | str | 格式描述 | | +| superscript | str | (?) | | +| codecs | array | 可用编码格式列表 | | + +`support_formats`中的`codecs`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | --------------- | ---- | +| 0 | str | 例:av01.0.13M.08.0.110.01.01.01.0 | 使用AV1编码 | +| 1 | str | 例子:avc1.640034 | 使用AVC编码 | +| 2 | str | 例子:hev1.1.6.L153.90 | 使用HEVC编码 | + +`data`中的`language`对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------- | ------- | -------------------------- | ---- | +| support | boolean | 视频是否支持AI原声? | | +| items | array | 支持的原声翻译列表 | | +| open_toast | str | 启用AI原声翻译时的提示? | | +| close_toast | str | 关闭AI原声翻译时的提示? | | +| default_title | str | (?) | | +| bubble | obj | (?) | | + +`language`中的`items`数组: + +| 项 | 类型 | 内容 | 备注 | +| --- | ---- | ---------------- | ---- | +| 0 | obj | AI原声信息1 | | +| n | obj | AI原声信息(n+1) | | +| ... | obj | ... | | + +`items`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ------------------------ | ------- | ------------------- | ----------------------- | +| lang | str | AI原声翻译的语言值 | 可用于cur_language参数 | +| title | str | 语言显示文本 | 如:`English` | +| subtitle_lang | str | (?) | | +| video_detext | boolean | (?) | | +| video_mouth_shape_change | boolean | (?) | | +| production_type | num | 产品类型? | | + +由于 MP4 / ~~FLV~~ 与 DASH 格式的返回结构不同,以下内容需要分类讨论`durl`与`dash`字段的内容 + + +--- + +### FLV/MP4格式 + +`data`中的`durl`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ----------------- | ------------------------- | +| 0 | obj | 视频分段 1 信息 | **目前由于 FLV 格式已经下线,不会存在分段现象,故无需关心** | +| n | obj | 视频分段 (n+1) 信息 | | +| …… | obj | …… | | + +`durl`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| ---------- | ------ | ------------ | ---------------------------------- | +| order | num | 视频分段序号 | 某些视频会分为多个片段(从1顺序增长) | +| length | num | 视频长度 | 单位为毫秒 | +| size | num | 视频大小 | 单位为 Byte | +| ahead | str | (?) | | +| vhead | str | (?) | | +| url | str | 默认流 URL | **注意 unicode 转义符**
有效时间为120min | +| backup_url | array | 备用视频流 | | + +`durl`数组中的对象中的`backup_url`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------------- | --------------------------------------------- | +| 0 | str | 备用流 URL 1 | **注意 unicode 转义符**
有效时间为120min | +| n | str | 备用流 URL (n+1) | | +| …… | str | …… | | + +**示例:** + +**视频无分段时:** + +获取视频`av99999999`/`BV1y7411Q7Eq`中的 1P(cid=`171776208`)的视频流 URL,清晰度为 1080P+,使用 FLV 方式获取 + +avid方式: + +```shell +curl -G 'https://api.bilibili.com/x/player/playurl' \ + --data-urlencode 'avid=99999999' \ + --data-urlencode 'cid=171776208' \ + --data-urlencode 'qn=112' \ + --data-urlencode 'fnval=0' \ + --data-urlencode 'fnver=0' \ + --data-urlencode 'fourk=1' \ + -b 'SESSDATA=xxx' +``` + + bvid方式: + +```shell +curl -G 'https://api.bilibili.com/x/player/playurl' \ + --data-urlencode 'bvid=BV1y7411Q7Eq' \ + --data-urlencode 'cid=171776208' \ + --data-urlencode 'qn=112' \ + --data-urlencode 'fnval=0' \ + --data-urlencode 'fnver=0' \ + --data-urlencode 'fourk=1' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "from": "local", + "result": "suee", + "message": "", + "quality": 64, + "format": "flv720", + "timelength": 283801, + "accept_format": "hdflv2,flv,flv720,flv480,mp4", + "accept_description": [ + "高清 1080P+", + "高清 1080P", + "高清 720P", + "清晰 480P", + "流畅 360P" + ], + "accept_quality": [ + 112, + 80, + 64, + 32, + 16 + ], + "video_codecid": 7, + "seek_param": "start", + "seek_type": "offset", + "durl": [ + { + "order": 1, + "length": 283801, + "size": 70486426, + "ahead": "", + "vhead": "", + "url": "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/08/62/171776208/171776208_nb2-1-64.flv?e=ig8euxZM2rNcNbNMnwdVhwdlhbK3hwdVhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1662808778&gen=playurlv2&os=cosbv&oi=3719461929&trid=31dc1934e77141bfbdf5ae88aca0b29fu&mid=0&platform=pc&upsig=a4d5f1713e1ba313041d034a958c2414&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform&bvc=vod&nettype=0&orderid=0,3&agrr=1&bw=249068&logo=80000000", + "backup_url": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/08/62/171776208/171776208_nb2-1-64.flv?e=ig8euxZM2rNcNbNMnwdVhwdlhbK3hwdVhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1662808778&gen=playurlv2&os=cosbv&oi=3719461929&trid=31dc1934e77141bfbdf5ae88aca0b29fu&mid=0&platform=pc&upsig=a4d5f1713e1ba313041d034a958c2414&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform&bvc=vod&nettype=0&orderid=1,3&agrr=1&bw=249068&logo=40000000", + "https://upos-sz-mirrorcosb.bilivideo.com/upgcxcode/08/62/171776208/171776208_nb2-1-64.flv?e=ig8euxZM2rNcNbNMnwdVhwdlhbK3hwdVhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1662808778&gen=playurlv2&os=cosbbv&oi=3719461929&trid=31dc1934e77141bfbdf5ae88aca0b29fu&mid=0&platform=pc&upsig=7b8a6924948864944815ec0748cc108f&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform&bvc=vod&nettype=0&orderid=2,3&agrr=1&bw=249068&logo=40000000" + ] + } + ], + "support_formats": [ + { + "quality": 112, + "format": "hdflv2", + "new_description": "1080P 高码率", + "display_desc": "1080P", + "superscript": "高码率", + "codecs": null + }, + { + "quality": 80, + "format": "flv", + "new_description": "1080P 高清", + "display_desc": "1080P", + "superscript": "", + "codecs": null + }, + { + "quality": 64, + "format": "flv720", + "new_description": "720P 高清", + "display_desc": "720P", + "superscript": "", + "codecs": null + }, + { + "quality": 32, + "format": "flv480", + "new_description": "480P 清晰", + "display_desc": "480P", + "superscript": "", + "codecs": null + }, + { + "quality": 16, + "format": "mp4", + "new_description": "360P 流畅", + "display_desc": "360P", + "superscript": "", + "codecs": null + } + ], + "high_format": null, + "last_play_time": 0, + "last_play_cid": 0 + } +} +``` + +
+ +**视频有分段时:** + +以下内容无参考价值,仅做历史保存 + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "from": "local", + "result": "suee", + "message": "", + "quality": 16, + "format": "flv360", + "timelength": 1437918, + "accept_format": "flv,flv720,flv480,flv360", + "accept_description": [ + "高清 1080P", + "高清 720P", + "清晰 480P", + "流畅 360P" + ], + "accept_quality": [ + 80, + 64, + 32, + 16 + ], + "video_codecid": 7, + "seek_param": "start", + "seek_type": "offset", + "durl": [ + { + "order": 1, + "length": 364417, + "size": 23018310, + "ahead": "", + "vhead": "", + "url": "http://upos-sz-mirrorhw.bilivideo.com/upgcxcode/98/24/872498/872498-1-15.flv?e=ig8euxZM2rNcNbRB7zUVhoM17WuBhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNo8g2ENvNo8i8o859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859r1qXg8gNEVE5XREto8z5JZC2X2gkX5L5F1eTX1jkXlsTXHeux_f2o859IB_&uipk=5&nbs=1&deadline=1589874109&gen=playurl&os=hwbv&oi=1965551630&trid=ceac015d41e04a7b90ec972db710524fu&platform=pc&upsig=f99db2dc9b8c65c245515b29b9ca8b16&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=293793435&logo=80000000", + "backup_url": [ + "http://upos-sz-mirrorks3c.bilivideo.com/upgcxcode/98/24/872498/872498-1-15.flv?e=ig8euxZM2rNcNbRB7zUVhoM17WuBhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNo8g2ENvNo8i8o859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859r1qXg8gNEVE5XREto8z5JZC2X2gkX5L5F1eTX1jkXlsTXHeux_f2o859IB_&uipk=5&nbs=1&deadline=1589874109&gen=playurl&os=ks3cbv&oi=1965551630&trid=ceac015d41e04a7b90ec972db710524fu&platform=pc&upsig=74d0d62697364346f88d9c39430ce23c&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=293793435&logo=40000000" + ] + }, + { + "order": 2, + "length": 364395, + "size": 23694756, + "ahead": "", + "vhead": "", + "url": "http://upos-sz-mirrorcos.bilivideo.com/upgcxcode/98/24/872498/872498-2-15.flv?e=ig8euxZM2rNcNbRjhbUVhoM17bNBhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNo8g2ENvNo8i8o859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859r1qXg8gNEVE5XREto8z5JZC2X2gkX5L5F1eTX1jkXlsTXHeux_f2o859IB_&uipk=5&nbs=1&deadline=1589874109&gen=playurl&os=cosbv&oi=1965551630&trid=ceac015d41e04a7b90ec972db710524fu&platform=pc&upsig=308c87c55f3325bdaac2a3e8632948ee&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=293793435&logo=80000000", + "backup_url": [ + "http://upos-sz-mirrorks3c.bilivideo.com/upgcxcode/98/24/872498/872498-2-15.flv?e=ig8euxZM2rNcNbRjhbUVhoM17bNBhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNo8g2ENvNo8i8o859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859r1qXg8gNEVE5XREto8z5JZC2X2gkX5L5F1eTX1jkXlsTXHeux_f2o859IB_&uipk=5&nbs=1&deadline=1589874109&gen=playurl&os=ks3cbv&oi=1965551630&trid=ceac015d41e04a7b90ec972db710524fu&platform=pc&upsig=eb8f043e0f36f82ab9c62fd002143438&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=293793435&logo=40000000" + ] + }, + { + "order": 3, + "length": 352333, + "size": 22835734, + "ahead": "", + "vhead": "", + "url": "http://upos-sz-mirrorhw.bilivideo.com/upgcxcode/98/24/872498/872498-3-15.flv?e=ig8euxZM2rNcNbRjhwdVhoM17bdVhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNo8g2ENvNo8i8o859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859r1qXg8gNEVE5XREto8z5JZC2X2gkX5L5F1eTX1jkXlsTXHeux_f2o859IB_&uipk=5&nbs=1&deadline=1589874109&gen=playurl&os=hwbv&oi=1965551630&trid=ceac015d41e04a7b90ec972db710524fu&platform=pc&upsig=2685b7649f4bb6eb90f986f125432d78&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=293793435&logo=80000000", + "backup_url": [ + "http://upos-sz-mirrorks3c.bilivideo.com/upgcxcode/98/24/872498/872498-3-15.flv?e=ig8euxZM2rNcNbRjhwdVhoM17bdVhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNo8g2ENvNo8i8o859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859r1qXg8gNEVE5XREto8z5JZC2X2gkX5L5F1eTX1jkXlsTXHeux_f2o859IB_&uipk=5&nbs=1&deadline=1589874109&gen=playurl&os=ks3cbv&oi=1965551630&trid=ceac015d41e04a7b90ec972db710524fu&platform=pc&upsig=922543bfb26184f901187bf9c39c69b2&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=293793435&logo=40000000" + ] + }, + { + "order": 4, + "length": 356773, + "size": 23466279, + "ahead": "", + "vhead": "", + "url": "http://upos-sz-mirrorkodo.bilivideo.com/upgcxcode/98/24/872498/872498-4-15.flv?e=ig8euxZM2rNcNbRjhbUVhoM17bNBhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNo8g2ENvNo8i8o859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859r1qXg8gNEVE5XREto8z5JZC2X2gkX5L5F1eTX1jkXlsTXHeux_f2o859IB_&uipk=5&nbs=1&deadline=1589874109&gen=playurl&os=kodobv&oi=1965551630&trid=ceac015d41e04a7b90ec972db710524fu&platform=pc&upsig=9d29707faf012797ef2b6de21523fcf2&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=293793435&logo=80000000", + "backup_url": [ + "http://upos-sz-mirrorks3c.bilivideo.com/upgcxcode/98/24/872498/872498-4-15.flv?e=ig8euxZM2rNcNbRjhbUVhoM17bNBhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNo8g2ENvNo8i8o859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859r1qXg8gNEVE5XREto8z5JZC2X2gkX5L5F1eTX1jkXlsTXHeux_f2o859IB_&uipk=5&nbs=1&deadline=1589874109&gen=playurl&os=ks3cbv&oi=1965551630&trid=ceac015d41e04a7b90ec972db710524fu&platform=pc&upsig=9ad4524d31c8d9695ae07b400b73ed29&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=293793435&logo=40000000" + ] + } + ] + } +} +``` + +
+ +--- + +### DASH格式 + +`data`中的`dash`对象: + +| 字段 | 类型 | 内容 | 备注 | +| --------------- | ----- | ---------- | ------------ | +| duration | num | 视频长度 | 秒值 | +| minBufferTime | num | 1.5? | | +| min_buffer_time | num | 1.5? | | +| video | array | 视频流信息 | | +| audio | array | 伴音流信息 | 当视频没有音轨时,此项为 null | +| dolby | obj | 杜比全景声伴音信息 | | +| flac | obj | 无损音轨伴音信息 | 当视频没有无损音轨时,此项为 null | + +`dash`中的`video`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------------------- | ---- | +| 0 | obj | 视频码流 1 | 同一清晰度可拥有 H.264 / H.265 / AV1 多种码流
**HDR 仅支持 H.265** | +| n | obj | 视频码流(n+1) | | +| …… | obj | …… | | + +`dash`中的`audio`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------- | ---- | +| 0 | obj | 清晰度1 | | +| n | obj | 清晰度(n+1) | | +| …… | obj | …… | | + +`video`及`audio`数组中的对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ----- | --------------------- | ----------------------------------------------- | +| id | num | 音视频清晰度代码 | 参考上表
[qn视频清晰度标识](#qn视频清晰度标识)
[视频伴音音质代码](#视频伴音音质代码) | +| baseUrl | str | 默认流 URL | **注意 unicode 转义符**
有效时间为 120min | +| base_url | str | **同上** | | +| backupUrl | array | 备用流 URL | | +| backup_url | array | **同上** | | +| bandwidth | num | 所需最低带宽 | 单位为 Byte | +| mimeType | str | 格式 mimetype 类型 | | +| mime_type | str | **同上** | | +| codecs | str | 编码/音频类型 | eg:`avc1.640032` | +| width | num | 视频宽度 | 单位为像素
**仅视频流存在该字段** | +| height | num | 视频高度 | 单位为像素
**仅视频流存在该字段** | +| frameRate | str | 视频帧率 | **仅视频流存在该字段** | +| frame_rate | str | **同上** | | +| sar | str | Sample Aspect Ratio(单个像素的宽高比) | 音频流该值恒为空 | +| startWithSap | num | Stream Access Point(流媒体访问位点) | 音频流该值恒为空 | +| start_with_sap | num | **同上** | | +| SegmentBase | obj | 见下表 | url 对应 m4s 文件中,头部的位置
音频流该值恒为空 | +| segment_base | obj | **同上** | | +| codecid | num | 码流编码标识代码 | 含义见 [上表](#视频编码代码)
音频流该值恒为`0` | + +`video`数组中的对象中的`backup_url`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ---------------- | --------------------------------------------- | +| 0 | str | 备用流 URL 1 | **注意 unicode 转义符**
有效时间为120min | +| n | str | 备用流 URL (n+1) | | +| …… | str | …… | | + +`video`数组中的对象中的`SegmentBase`对象: + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | ---------------------------- | ------------------------------------------------------------ | +| initialization | str | `${init_first}-${init_last}` | eg:`0-821`
ftyp (file type) box 加上 moov box 在 m4s 文件中的范围(单位为 bytes)
如 0-821 表示开头 820 个字节 | +| index_range | str | `${sidx_first}-${sidx_last}` | eg:`822-1309`
sidx (segment index) box 在 m4s 文件中的范围(单位为 bytes)
sidx 的核心是一个数组,记录了各关键帧的时间戳及其在文件中的位置,
其作用是索引 (拖进度条) | + +> 常规 MP4 文件的索引信息放在 moov box 中,其中包含每一帧 (不止是关键帧) 的一些信息。在 DASH 方式下,关键帧信息移到了 sidx box 里,其他的则分散到了各个 moof (movie fragment) box 中。 + +对这里的文件结构感兴趣的,可以参考标准文档 [ISO/IEC 14496-12](https://www.iso.org/standard/83102.html),如果不想那么深入的话可以百度「[MP4 文件结构](https://baike.baidu.com/item/mp4/9218018)」 + +`dash`中的`dolby`对象: + +此项为”杜比视界“视频独有 + +| 字段 | 类型 | 内容 | 备注 | +| -------------- | ---- | --------------------------------------------- | ------------------------------------------------------------ | +| type | num | 杜比音效类型 | 1:普通杜比音效
2:全景杜比音效 | +| audio | array | 杜比伴音流列表 | | + +`dolby`对象中的`audio`数组: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------------------ | ----------------------------------------------- | +| 0 | obj | 杜比伴音流信息 | 同上文 DASH 流中`video`及`audio`数组中的对象 | + +`dash`中的`flac`对象: + +| 项 | 类型 | 内容 | 备注 | +| ---- | ---- | ------------------------ | ----------------------------------------------- | +| display | bool | 是否在播放器显示切换Hi-Res无损音轨按钮 | | +| audio | obj | 音频流信息 | 同上文 DASH 流中`video`及`audio`数组中的对象 | + +**示例:** + +获取视频`av969628065`/`BV1rp4y1e745`中的 1P(cid=`244954665`)的视频流 URL,使用 DASH 方式获取 + +avid 方式: + +```shell +curl -G 'https://api.bilibili.com/x/player/playurl' \ + --data-urlencode 'avid=969628065' \ + --data-urlencode 'cid=244954665' \ + --data-urlencode 'fnval=4048' \ # 4048 为所有 dash 选项或运算的结果 + --data-urlencode 'fnver=0' \ + --data-urlencode 'fourk=1' \ + -b 'SESSDATA=xxx' +``` + + bvid 方式: + +```shell +curl -G 'https://api.bilibili.com/x/player/playurl' \ + --data-urlencode 'bvid=BV1rp4y1e745' \ + --data-urlencode 'cid=244954665' \ + --data-urlencode 'fnval=4048' \ + --data-urlencode 'fnver=0' \ + --data-urlencode 'fourk=1' \ + -b 'SESSDATA=xxx' +``` + +
+查看响应示例: + +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": { + "from": "local", + "result": "suee", + "message": "", + "quality": 64, + "format": "flv720", + "timelength": 346495, + "accept_format": "hdflv2,hdflv2,flv_p60,flv,flv720,flv480,mp4", + "accept_description": [ + "真彩 HDR", + "超清 4K", + "高清 1080P60", + "高清 1080P", + "高清 720P", + "清晰 480P", + "流畅 360P" + ], + "accept_quality": [ + 125, + 120, + 116, + 80, + 64, + 32, + 16 + ], + "video_codecid": 7, + "seek_param": "start", + "seek_type": "offset", + "dash": { + "duration": 347, + "minBufferTime": 1.5, + "min_buffer_time": 1.5, + "video": [ + { + "id": 80, + "baseUrl": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_f9-1-100113.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026og=hw\u0026oi=3028829496\u0026tag=\u0026nbs=1\u0026gen=playurlv3\u0026uipk=5\u0026os=mcdn\u0026platform=pc\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026mid=59442895\u0026deadline=1745411269\u0026upsig=71821c3a1f0d596b8a0f79861695de67\u0026uparams=e,og,oi,tag,nbs,gen,uipk,os,platform,trid,mid,deadline\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=773719\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026orderid=0,3", + "base_url": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_f9-1-100113.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026og=hw\u0026oi=3028829496\u0026tag=\u0026nbs=1\u0026gen=playurlv3\u0026uipk=5\u0026os=mcdn\u0026platform=pc\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026mid=59442895\u0026deadline=1745411269\u0026upsig=71821c3a1f0d596b8a0f79861695de67\u0026uparams=e,og,oi,tag,nbs,gen,uipk,os,platform,trid,mid,deadline\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=773719\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/65/46/244954665/244954665_f9-1-100113.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026mid=59442895\u0026uipk=5\u0026gen=playurlv3\u0026os=08cbv\u0026og=hw\u0026deadline=1745411269\u0026tag=\u0026nbs=1\u0026upsig=585675af7dc762a4d21572f939196248\u0026uparams=e,platform,trid,oi,mid,uipk,gen,os,og,deadline,tag,nbs\u0026bvc=vod\u0026nettype=0\u0026bw=773719\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026orderid=1,3", + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/65/46/244954665/244954665_f9-1-100113.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026oi=3028829496\u0026nbs=1\u0026uipk=5\u0026gen=playurlv3\u0026platform=pc\u0026mid=59442895\u0026deadline=1745411269\u0026tag=\u0026os=08cbv\u0026og=hw\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026upsig=9fc6a3e3e0eaf3847c5c0f1c32047c09\u0026uparams=e,oi,nbs,uipk,gen,platform,mid,deadline,tag,os,og,trid\u0026bvc=vod\u0026nettype=0\u0026bw=773719\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/65/46/244954665/244954665_f9-1-100113.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026mid=59442895\u0026uipk=5\u0026gen=playurlv3\u0026os=08cbv\u0026og=hw\u0026deadline=1745411269\u0026tag=\u0026nbs=1\u0026upsig=585675af7dc762a4d21572f939196248\u0026uparams=e,platform,trid,oi,mid,uipk,gen,os,og,deadline,tag,nbs\u0026bvc=vod\u0026nettype=0\u0026bw=773719\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026orderid=1,3", + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/65/46/244954665/244954665_f9-1-100113.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026oi=3028829496\u0026nbs=1\u0026uipk=5\u0026gen=playurlv3\u0026platform=pc\u0026mid=59442895\u0026deadline=1745411269\u0026tag=\u0026os=08cbv\u0026og=hw\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026upsig=9fc6a3e3e0eaf3847c5c0f1c32047c09\u0026uparams=e,oi,nbs,uipk,gen,platform,mid,deadline,tag,os,og,trid\u0026bvc=vod\u0026nettype=0\u0026bw=773719\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=2,3" + ], + "bandwidth": 772828, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "hev1.1.6.L150.90", + "width": 1920, + "height": 960, + "frameRate": "30.303", + "frame_rate": "30.303", + "sar": "1:1", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-1159", + "indexRange": "1160-2019" + }, + "segment_base": { + "initialization": "0-1159", + "index_range": "1160-2019" + }, + "codecid": 12 + }, + { + "id": 80, + "baseUrl": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_nb3-1-30080.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026deadline=1745411269\u0026uipk=5\u0026og=cos\u0026gen=playurlv3\u0026os=mcdn\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026mid=59442895\u0026tag=\u0026nbs=1\u0026upsig=134e6b8516a05db7ef97a18b68b94cb5\u0026uparams=e,platform,deadline,uipk,og,gen,os,trid,oi,mid,tag,nbs\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=1918964\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026orderid=0,3", + "base_url": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_nb3-1-30080.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026deadline=1745411269\u0026uipk=5\u0026og=cos\u0026gen=playurlv3\u0026os=mcdn\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026mid=59442895\u0026tag=\u0026nbs=1\u0026upsig=134e6b8516a05db7ef97a18b68b94cb5\u0026uparams=e,platform,deadline,uipk,og,gen,os,trid,oi,mid,tag,nbs\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=1918964\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30080.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026gen=playurlv3\u0026os=cosbv\u0026og=cos\u0026deadline=1745411269\u0026uipk=5\u0026nbs=1\u0026mid=59442895\u0026tag=\u0026upsig=d3f4bbcd7c490effdfdf0b9f8375f9a2\u0026uparams=e,platform,trid,oi,gen,os,og,deadline,uipk,nbs,mid,tag\u0026bvc=vod\u0026nettype=0\u0026bw=1918964\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30080.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026gen=playurlv3\u0026os=cosbv\u0026mid=59442895\u0026tag=\u0026nbs=1\u0026uipk=5\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026og=cos\u0026oi=3028829496\u0026deadline=1745411269\u0026upsig=584b3a331daefde16b118f612d43c1c6\u0026uparams=e,platform,gen,os,mid,tag,nbs,uipk,trid,og,oi,deadline\u0026bvc=vod\u0026nettype=0\u0026bw=1918964\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30080.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026gen=playurlv3\u0026os=cosbv\u0026og=cos\u0026deadline=1745411269\u0026uipk=5\u0026nbs=1\u0026mid=59442895\u0026tag=\u0026upsig=d3f4bbcd7c490effdfdf0b9f8375f9a2\u0026uparams=e,platform,trid,oi,gen,os,og,deadline,uipk,nbs,mid,tag\u0026bvc=vod\u0026nettype=0\u0026bw=1918964\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30080.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026gen=playurlv3\u0026os=cosbv\u0026mid=59442895\u0026tag=\u0026nbs=1\u0026uipk=5\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026og=cos\u0026oi=3028829496\u0026deadline=1745411269\u0026upsig=584b3a331daefde16b118f612d43c1c6\u0026uparams=e,platform,gen,os,mid,tag,nbs,uipk,trid,og,oi,deadline\u0026bvc=vod\u0026nettype=0\u0026bw=1918964\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=2,3" + ], + "bandwidth": 1916748, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "avc1.640032", + "width": 1920, + "height": 960, + "frameRate": "29.412", + "frame_rate": "29.412", + "sar": "1:1", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-994", + "indexRange": "995-1854" + }, + "segment_base": { + "initialization": "0-994", + "index_range": "995-1854" + }, + "codecid": 7 + }, + { + "id": 64, + "baseUrl": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_f9-1-100112.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026deadline=1745411269\u0026gen=playurlv3\u0026os=mcdn\u0026og=cos\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026mid=59442895\u0026tag=\u0026upsig=fcba1f000ead402f2ab2748df6e8d127\u0026uparams=e,deadline,gen,os,og,nbs,uipk,platform,trid,oi,mid,tag\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=1238263\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026orderid=0,3", + "base_url": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_f9-1-100112.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026deadline=1745411269\u0026gen=playurlv3\u0026os=mcdn\u0026og=cos\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026mid=59442895\u0026tag=\u0026upsig=fcba1f000ead402f2ab2748df6e8d127\u0026uparams=e,deadline,gen,os,og,nbs,uipk,platform,trid,oi,mid,tag\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=1238263\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_f9-1-100112.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026mid=59442895\u0026gen=playurlv3\u0026deadline=1745411269\u0026tag=\u0026og=cos\u0026oi=3028829496\u0026os=cosbv\u0026upsig=9ab39b34d214780c30147af36a862d89\u0026uparams=e,nbs,uipk,platform,trid,mid,gen,deadline,tag,og,oi,os\u0026bvc=vod\u0026nettype=0\u0026bw=1238263\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_f9-1-100112.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026oi=3028829496\u0026nbs=1\u0026uipk=5\u0026tag=\u0026gen=playurlv3\u0026os=cosbv\u0026og=cos\u0026platform=pc\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026mid=59442895\u0026deadline=1745411269\u0026upsig=bea70709fec064c8f384ee24eb5ccd1a\u0026uparams=e,oi,nbs,uipk,tag,gen,os,og,platform,trid,mid,deadline\u0026bvc=vod\u0026nettype=0\u0026bw=1238263\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_f9-1-100112.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026mid=59442895\u0026gen=playurlv3\u0026deadline=1745411269\u0026tag=\u0026og=cos\u0026oi=3028829496\u0026os=cosbv\u0026upsig=9ab39b34d214780c30147af36a862d89\u0026uparams=e,nbs,uipk,platform,trid,mid,gen,deadline,tag,og,oi,os\u0026bvc=vod\u0026nettype=0\u0026bw=1238263\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_f9-1-100112.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026oi=3028829496\u0026nbs=1\u0026uipk=5\u0026tag=\u0026gen=playurlv3\u0026os=cosbv\u0026og=cos\u0026platform=pc\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026mid=59442895\u0026deadline=1745411269\u0026upsig=bea70709fec064c8f384ee24eb5ccd1a\u0026uparams=e,oi,nbs,uipk,tag,gen,os,og,platform,trid,mid,deadline\u0026bvc=vod\u0026nettype=0\u0026bw=1238263\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=2,3" + ], + "bandwidth": 1236894, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "hev1.1.6.L120.90", + "width": 1280, + "height": 640, + "frameRate": "58.824", + "frame_rate": "58.824", + "sar": "1:1", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-1060", + "indexRange": "1061-1920" + }, + "segment_base": { + "initialization": "0-1060", + "index_range": "1061-1920" + }, + "codecid": 12 + }, + { + "id": 64, + "baseUrl": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_nb3-1-30074.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026oi=3028829496\u0026mid=59442895\u0026deadline=1745411269\u0026tag=\u0026gen=playurlv3\u0026platform=pc\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026nbs=1\u0026uipk=5\u0026os=mcdn\u0026og=hw\u0026upsig=0b3aae3388cb52b436e591615c048007\u0026uparams=e,oi,mid,deadline,tag,gen,platform,trid,nbs,uipk,os,og\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=1224265\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "base_url": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_nb3-1-30074.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026oi=3028829496\u0026mid=59442895\u0026deadline=1745411269\u0026tag=\u0026gen=playurlv3\u0026platform=pc\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026nbs=1\u0026uipk=5\u0026os=mcdn\u0026og=hw\u0026upsig=0b3aae3388cb52b436e591615c048007\u0026uparams=e,oi,mid,deadline,tag,gen,platform,trid,nbs,uipk,os,og\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=1224265\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30074.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026mid=59442895\u0026deadline=1745411269\u0026tag=\u0026nbs=1\u0026gen=playurlv3\u0026uipk=5\u0026platform=pc\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026os=08cbv\u0026og=hw\u0026upsig=9dc7c021d5094eab92053fc58e84a48d\u0026uparams=e,mid,deadline,tag,nbs,gen,uipk,platform,trid,oi,os,og\u0026bvc=vod\u0026nettype=0\u0026bw=1224265\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=1,3", + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30074.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026mid=59442895\u0026deadline=1745411269\u0026tag=\u0026og=hw\u0026oi=3028829496\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026gen=playurlv3\u0026os=08cbv\u0026upsig=d2a75ae893a23a5d90630725d57efe72\u0026uparams=e,trid,mid,deadline,tag,og,oi,nbs,uipk,platform,gen,os\u0026bvc=vod\u0026nettype=0\u0026bw=1224265\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30074.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026mid=59442895\u0026deadline=1745411269\u0026tag=\u0026nbs=1\u0026gen=playurlv3\u0026uipk=5\u0026platform=pc\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026os=08cbv\u0026og=hw\u0026upsig=9dc7c021d5094eab92053fc58e84a48d\u0026uparams=e,mid,deadline,tag,nbs,gen,uipk,platform,trid,oi,os,og\u0026bvc=vod\u0026nettype=0\u0026bw=1224265\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=1,3", + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30074.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026mid=59442895\u0026deadline=1745411269\u0026tag=\u0026og=hw\u0026oi=3028829496\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026gen=playurlv3\u0026os=08cbv\u0026upsig=d2a75ae893a23a5d90630725d57efe72\u0026uparams=e,trid,mid,deadline,tag,og,oi,nbs,uipk,platform,gen,os\u0026bvc=vod\u0026nettype=0\u0026bw=1224265\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026orderid=2,3" + ], + "bandwidth": 1222911, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "avc1.640020", + "width": 1280, + "height": 640, + "frameRate": "62.500", + "frame_rate": "62.500", + "sar": "1:1", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-994", + "indexRange": "995-1854" + }, + "segment_base": { + "initialization": "0-994", + "index_range": "995-1854" + }, + "codecid": 7 + }, + { + "id": 32, + "baseUrl": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_f9-1-100110.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026oi=3028829496\u0026uipk=5\u0026og=cos\u0026gen=playurlv3\u0026os=mcdn\u0026platform=pc\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026mid=59442895\u0026deadline=1745411269\u0026tag=\u0026nbs=1\u0026upsig=68bd74999864b4a96ac0dbb730b53612\u0026uparams=e,oi,uipk,og,gen,os,platform,trid,mid,deadline,tag,nbs\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=246761\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026orderid=0,3", + "base_url": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_f9-1-100110.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026oi=3028829496\u0026uipk=5\u0026og=cos\u0026gen=playurlv3\u0026os=mcdn\u0026platform=pc\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026mid=59442895\u0026deadline=1745411269\u0026tag=\u0026nbs=1\u0026upsig=68bd74999864b4a96ac0dbb730b53612\u0026uparams=e,oi,uipk,og,gen,os,platform,trid,mid,deadline,tag,nbs\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=246761\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_f9-1-100110.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026deadline=1745411269\u0026tag=\u0026gen=playurlv3\u0026uipk=5\u0026platform=pc\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026os=cosbv\u0026og=cos\u0026oi=3028829496\u0026mid=59442895\u0026nbs=1\u0026upsig=25c03095d15e721ca7a7e80f9e831319\u0026uparams=e,deadline,tag,gen,uipk,platform,trid,os,og,oi,mid,nbs\u0026bvc=vod\u0026nettype=0\u0026bw=246761\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_f9-1-100110.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026uipk=5\u0026os=cosbv\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026nbs=1\u0026platform=pc\u0026gen=playurlv3\u0026og=cos\u0026mid=59442895\u0026deadline=1745411269\u0026tag=\u0026upsig=c879e409a7bf7995c12ae5e22cb82b97\u0026uparams=e,uipk,os,trid,oi,nbs,platform,gen,og,mid,deadline,tag\u0026bvc=vod\u0026nettype=0\u0026bw=246761\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_f9-1-100110.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026deadline=1745411269\u0026tag=\u0026gen=playurlv3\u0026uipk=5\u0026platform=pc\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026os=cosbv\u0026og=cos\u0026oi=3028829496\u0026mid=59442895\u0026nbs=1\u0026upsig=25c03095d15e721ca7a7e80f9e831319\u0026uparams=e,deadline,tag,gen,uipk,platform,trid,os,og,oi,mid,nbs\u0026bvc=vod\u0026nettype=0\u0026bw=246761\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_f9-1-100110.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026uipk=5\u0026os=cosbv\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026nbs=1\u0026platform=pc\u0026gen=playurlv3\u0026og=cos\u0026mid=59442895\u0026deadline=1745411269\u0026tag=\u0026upsig=c879e409a7bf7995c12ae5e22cb82b97\u0026uparams=e,uipk,os,trid,oi,nbs,platform,gen,og,mid,deadline,tag\u0026bvc=vod\u0026nettype=0\u0026bw=246761\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026orderid=2,3" + ], + "bandwidth": 246476, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "hev1.1.6.L120.90", + "width": 854, + "height": 426, + "frameRate": "30.303", + "frame_rate": "30.303", + "sar": "426:427", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-1163", + "indexRange": "1164-2023" + }, + "segment_base": { + "initialization": "0-1163", + "index_range": "1164-2023" + }, + "codecid": 12 + }, + { + "id": 32, + "baseUrl": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_nb3-1-30032.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026deadline=1745411269\u0026nbs=1\u0026uipk=5\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026mid=59442895\u0026os=mcdn\u0026og=cos\u0026tag=\u0026platform=pc\u0026oi=3028829496\u0026gen=playurlv3\u0026upsig=99b3ff6929d865dafbbdf21301c3889b\u0026uparams=e,deadline,nbs,uipk,trid,mid,os,og,tag,platform,oi,gen\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=629530\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "base_url": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_nb3-1-30032.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026deadline=1745411269\u0026nbs=1\u0026uipk=5\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026mid=59442895\u0026os=mcdn\u0026og=cos\u0026tag=\u0026platform=pc\u0026oi=3028829496\u0026gen=playurlv3\u0026upsig=99b3ff6929d865dafbbdf21301c3889b\u0026uparams=e,deadline,nbs,uipk,trid,mid,os,og,tag,platform,oi,gen\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=629530\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30032.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026uipk=5\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026deadline=1745411269\u0026gen=playurlv3\u0026nbs=1\u0026platform=pc\u0026oi=3028829496\u0026mid=59442895\u0026tag=\u0026os=cosbv\u0026og=cos\u0026upsig=2e6bf8c0c1fc96618294d917f21192e7\u0026uparams=e,uipk,trid,deadline,gen,nbs,platform,oi,mid,tag,os,og\u0026bvc=vod\u0026nettype=0\u0026bw=629530\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30032.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026mid=59442895\u0026gen=playurlv3\u0026tag=\u0026nbs=1\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026os=cosbv\u0026og=cos\u0026deadline=1745411269\u0026uipk=5\u0026upsig=cc07c04afd6ac07b10f46241ef4c5fbc\u0026uparams=e,platform,mid,gen,tag,nbs,trid,oi,os,og,deadline,uipk\u0026bvc=vod\u0026nettype=0\u0026bw=629530\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30032.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026uipk=5\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026deadline=1745411269\u0026gen=playurlv3\u0026nbs=1\u0026platform=pc\u0026oi=3028829496\u0026mid=59442895\u0026tag=\u0026os=cosbv\u0026og=cos\u0026upsig=2e6bf8c0c1fc96618294d917f21192e7\u0026uparams=e,uipk,trid,deadline,gen,nbs,platform,oi,mid,tag,os,og\u0026bvc=vod\u0026nettype=0\u0026bw=629530\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30032.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026mid=59442895\u0026gen=playurlv3\u0026tag=\u0026nbs=1\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026os=cosbv\u0026og=cos\u0026deadline=1745411269\u0026uipk=5\u0026upsig=cc07c04afd6ac07b10f46241ef4c5fbc\u0026uparams=e,platform,mid,gen,tag,nbs,trid,oi,os,og,deadline,uipk\u0026bvc=vod\u0026nettype=0\u0026bw=629530\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026orderid=2,3" + ], + "bandwidth": 628803, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "avc1.64001F", + "width": 854, + "height": 426, + "frameRate": "29.412", + "frame_rate": "29.412", + "sar": "426:427", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-999", + "indexRange": "1000-1859" + }, + "segment_base": { + "initialization": "0-999", + "index_range": "1000-1859" + }, + "codecid": 7 + }, + { + "id": 16, + "baseUrl": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_f9-1-100109.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026og=hw\u0026oi=3028829496\u0026deadline=1745411269\u0026uipk=5\u0026platform=pc\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026mid=59442895\u0026gen=playurlv3\u0026os=mcdn\u0026tag=\u0026nbs=1\u0026upsig=cdb471486fa3908a2790ba9ef0fd0a44\u0026uparams=e,og,oi,deadline,uipk,platform,trid,mid,gen,os,tag,nbs\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=168083\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026orderid=0,3", + "base_url": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_f9-1-100109.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026og=hw\u0026oi=3028829496\u0026deadline=1745411269\u0026uipk=5\u0026platform=pc\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026mid=59442895\u0026gen=playurlv3\u0026os=mcdn\u0026tag=\u0026nbs=1\u0026upsig=cdb471486fa3908a2790ba9ef0fd0a44\u0026uparams=e,og,oi,deadline,uipk,platform,trid,mid,gen,os,tag,nbs\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=168083\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/65/46/244954665/244954665_f9-1-100109.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026tag=\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026mid=59442895\u0026deadline=1745411269\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026gen=playurlv3\u0026os=08cbv\u0026og=hw\u0026oi=3028829496\u0026upsig=340b5f721a89f6dd90ae6153225cf808\u0026uparams=e,tag,trid,mid,deadline,nbs,uipk,platform,gen,os,og,oi\u0026bvc=vod\u0026nettype=0\u0026bw=168083\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=1,3", + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/65/46/244954665/244954665_f9-1-100109.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026oi=3028829496\u0026mid=59442895\u0026tag=\u0026nbs=1\u0026uipk=5\u0026os=08cbv\u0026platform=pc\u0026deadline=1745411269\u0026gen=playurlv3\u0026og=hw\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026upsig=e6c5646fd0e0d9cbb16296d2c8d8649f\u0026uparams=e,oi,mid,tag,nbs,uipk,os,platform,deadline,gen,og,trid\u0026bvc=vod\u0026nettype=0\u0026bw=168083\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/65/46/244954665/244954665_f9-1-100109.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026tag=\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026mid=59442895\u0026deadline=1745411269\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026gen=playurlv3\u0026os=08cbv\u0026og=hw\u0026oi=3028829496\u0026upsig=340b5f721a89f6dd90ae6153225cf808\u0026uparams=e,tag,trid,mid,deadline,nbs,uipk,platform,gen,os,og,oi\u0026bvc=vod\u0026nettype=0\u0026bw=168083\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=1,3", + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/65/46/244954665/244954665_f9-1-100109.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026oi=3028829496\u0026mid=59442895\u0026tag=\u0026nbs=1\u0026uipk=5\u0026os=08cbv\u0026platform=pc\u0026deadline=1745411269\u0026gen=playurlv3\u0026og=hw\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026upsig=e6c5646fd0e0d9cbb16296d2c8d8649f\u0026uparams=e,oi,mid,tag,nbs,uipk,os,platform,deadline,gen,og,trid\u0026bvc=vod\u0026nettype=0\u0026bw=168083\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=2,3" + ], + "bandwidth": 167889, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "hev1.1.6.L120.90", + "width": 640, + "height": 320, + "frameRate": "30.303", + "frame_rate": "30.303", + "sar": "1:1", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-1157", + "indexRange": "1158-2017" + }, + "segment_base": { + "initialization": "0-1157", + "index_range": "1158-2017" + }, + "codecid": 12 + }, + { + "id": 16, + "baseUrl": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_nb3-1-30016.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026oi=3028829496\u0026mid=59442895\u0026deadline=1745411269\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026gen=playurlv3\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026os=mcdn\u0026og=hw\u0026tag=\u0026upsig=93d8e429ac6dcf654df688457f138820\u0026uparams=e,oi,mid,deadline,nbs,uipk,platform,gen,trid,os,og,tag\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=353034\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026orderid=0,3", + "base_url": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_nb3-1-30016.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026oi=3028829496\u0026mid=59442895\u0026deadline=1745411269\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026gen=playurlv3\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026os=mcdn\u0026og=hw\u0026tag=\u0026upsig=93d8e429ac6dcf654df688457f138820\u0026uparams=e,oi,mid,deadline,nbs,uipk,platform,gen,trid,os,og,tag\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=353034\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30016.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026mid=59442895\u0026deadline=1745411269\u0026nbs=1\u0026gen=playurlv3\u0026os=08cbv\u0026og=hw\u0026uipk=5\u0026platform=pc\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026tag=\u0026upsig=87f32943e6cfcb2957f0b90e9be210f3\u0026uparams=e,mid,deadline,nbs,gen,os,og,uipk,platform,trid,oi,tag\u0026bvc=vod\u0026nettype=0\u0026bw=353034\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026orderid=1,3", + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30016.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026uipk=5\u0026platform=pc\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026mid=59442895\u0026og=hw\u0026tag=\u0026nbs=1\u0026deadline=1745411269\u0026gen=playurlv3\u0026os=08cbv\u0026upsig=0de6ac37eecd7261cc83e9e55f438747\u0026uparams=e,uipk,platform,trid,oi,mid,og,tag,nbs,deadline,gen,os\u0026bvc=vod\u0026nettype=0\u0026bw=353034\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30016.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026mid=59442895\u0026deadline=1745411269\u0026nbs=1\u0026gen=playurlv3\u0026os=08cbv\u0026og=hw\u0026uipk=5\u0026platform=pc\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026tag=\u0026upsig=87f32943e6cfcb2957f0b90e9be210f3\u0026uparams=e,mid,deadline,nbs,gen,os,og,uipk,platform,trid,oi,tag\u0026bvc=vod\u0026nettype=0\u0026bw=353034\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026orderid=1,3", + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30016.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026uipk=5\u0026platform=pc\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026mid=59442895\u0026og=hw\u0026tag=\u0026nbs=1\u0026deadline=1745411269\u0026gen=playurlv3\u0026os=08cbv\u0026upsig=0de6ac37eecd7261cc83e9e55f438747\u0026uparams=e,uipk,platform,trid,oi,mid,og,tag,nbs,deadline,gen,os\u0026bvc=vod\u0026nettype=0\u0026bw=353034\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=2,3" + ], + "bandwidth": 352627, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "avc1.64001E", + "width": 640, + "height": 320, + "frameRate": "29.412", + "frame_rate": "29.412", + "sar": "1:1", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-1002", + "indexRange": "1003-1862" + }, + "segment_base": { + "initialization": "0-1002", + "index_range": "1003-1862" + }, + "codecid": 7 + } + ], + "audio": [ + { + "id": 30232, + "baseUrl": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_nb3-1-30232.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026deadline=1745411269\u0026tag=\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026mid=59442895\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026gen=playurlv3\u0026os=mcdn\u0026og=cos\u0026upsig=c9f074f7fc113d3d06b928f74a1427d4\u0026uparams=e,deadline,tag,nbs,uipk,platform,mid,trid,oi,gen,os,og\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=76527\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "base_url": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_nb3-1-30232.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026deadline=1745411269\u0026tag=\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026mid=59442895\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026gen=playurlv3\u0026os=mcdn\u0026og=cos\u0026upsig=c9f074f7fc113d3d06b928f74a1427d4\u0026uparams=e,deadline,tag,nbs,uipk,platform,mid,trid,oi,gen,os,og\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=76527\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-estgoss.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30232.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026deadline=1745411269\u0026uipk=5\u0026platform=pc\u0026gen=playurlv3\u0026og=cos\u0026oi=3028829496\u0026mid=59442895\u0026nbs=1\u0026os=upos\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026tag=\u0026upsig=d563b613434d1b8d4c2acc1717a82dfa\u0026uparams=e,deadline,uipk,platform,gen,og,oi,mid,nbs,os,trid,tag\u0026bvc=vod\u0026nettype=0\u0026bw=76527\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=1,3", + "https://upos-sz-estgoss.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30232.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026nbs=1\u0026uipk=5\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026mid=59442895\u0026deadline=1745411269\u0026gen=playurlv3\u0026tag=\u0026platform=pc\u0026os=upos\u0026og=cos\u0026upsig=0d401aeaea4a51b01605e5155ccf2e34\u0026uparams=e,nbs,uipk,trid,oi,mid,deadline,gen,tag,platform,os,og\u0026bvc=vod\u0026nettype=0\u0026bw=76527\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-estgoss.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30232.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026deadline=1745411269\u0026uipk=5\u0026platform=pc\u0026gen=playurlv3\u0026og=cos\u0026oi=3028829496\u0026mid=59442895\u0026nbs=1\u0026os=upos\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026tag=\u0026upsig=d563b613434d1b8d4c2acc1717a82dfa\u0026uparams=e,deadline,uipk,platform,gen,og,oi,mid,nbs,os,trid,tag\u0026bvc=vod\u0026nettype=0\u0026bw=76527\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=1,3", + "https://upos-sz-estgoss.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30232.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026nbs=1\u0026uipk=5\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026mid=59442895\u0026deadline=1745411269\u0026gen=playurlv3\u0026tag=\u0026platform=pc\u0026os=upos\u0026og=cos\u0026upsig=0d401aeaea4a51b01605e5155ccf2e34\u0026uparams=e,nbs,uipk,trid,oi,mid,deadline,gen,tag,platform,os,og\u0026bvc=vod\u0026nettype=0\u0026bw=76527\u0026dl=0\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026orderid=2,3" + ], + "bandwidth": 76436, + "mimeType": "audio/mp4", + "mime_type": "audio/mp4", + "codecs": "mp4a.40.2", + "width": 0, + "height": 0, + "frameRate": "", + "frame_rate": "", + "sar": "", + "startWithSap": 0, + "start_with_sap": 0, + "SegmentBase": { + "Initialization": "0-933", + "indexRange": "934-1805" + }, + "segment_base": { + "initialization": "0-933", + "index_range": "934-1805" + }, + "codecid": 0 + }, + { + "id": 30280, + "baseUrl": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_nb3-1-30280.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026mid=59442895\u0026gen=playurlv3\u0026tag=\u0026os=mcdn\u0026og=cos\u0026deadline=1745411269\u0026upsig=3d3484b4a91783d0d7277e073d947fad\u0026uparams=e,nbs,uipk,platform,trid,oi,mid,gen,tag,os,og,deadline\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=155073\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "base_url": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_nb3-1-30280.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026mid=59442895\u0026gen=playurlv3\u0026tag=\u0026os=mcdn\u0026og=cos\u0026deadline=1745411269\u0026upsig=3d3484b4a91783d0d7277e073d947fad\u0026uparams=e,nbs,uipk,platform,trid,oi,mid,gen,tag,os,og,deadline\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=155073\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30280.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026og=cos\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026deadline=1745411269\u0026tag=\u0026gen=playurlv3\u0026os=cosbv\u0026platform=pc\u0026mid=59442895\u0026nbs=1\u0026uipk=5\u0026upsig=f7cc870e2a4925c24e46ad9425cf39a8\u0026uparams=e,og,trid,oi,deadline,tag,gen,os,platform,mid,nbs,uipk\u0026bvc=vod\u0026nettype=0\u0026bw=155073\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30280.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026og=cos\u0026mid=59442895\u0026tag=\u0026nbs=1\u0026platform=pc\u0026gen=playurlv3\u0026os=cosbv\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026deadline=1745411269\u0026uipk=5\u0026upsig=d380844ae7ac21f8484650ba59a15d97\u0026uparams=e,og,mid,tag,nbs,platform,gen,os,trid,oi,deadline,uipk\u0026bvc=vod\u0026nettype=0\u0026bw=155073\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30280.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026og=cos\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026deadline=1745411269\u0026tag=\u0026gen=playurlv3\u0026os=cosbv\u0026platform=pc\u0026mid=59442895\u0026nbs=1\u0026uipk=5\u0026upsig=f7cc870e2a4925c24e46ad9425cf39a8\u0026uparams=e,og,trid,oi,deadline,tag,gen,os,platform,mid,nbs,uipk\u0026bvc=vod\u0026nettype=0\u0026bw=155073\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30280.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026og=cos\u0026mid=59442895\u0026tag=\u0026nbs=1\u0026platform=pc\u0026gen=playurlv3\u0026os=cosbv\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026deadline=1745411269\u0026uipk=5\u0026upsig=d380844ae7ac21f8484650ba59a15d97\u0026uparams=e,og,mid,tag,nbs,platform,gen,os,trid,oi,deadline,uipk\u0026bvc=vod\u0026nettype=0\u0026bw=155073\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026orderid=2,3" + ], + "bandwidth": 154889, + "mimeType": "audio/mp4", + "mime_type": "audio/mp4", + "codecs": "mp4a.40.2", + "width": 0, + "height": 0, + "frameRate": "", + "frame_rate": "", + "sar": "", + "startWithSap": 0, + "start_with_sap": 0, + "SegmentBase": { + "Initialization": "0-933", + "indexRange": "934-1805" + }, + "segment_base": { + "initialization": "0-933", + "index_range": "934-1805" + }, + "codecid": 0 + }, + { + "id": 30216, + "baseUrl": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_nb3-1-30216.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026os=mcdn\u0026deadline=1745411269\u0026tag=\u0026nbs=1\u0026uipk=5\u0026mid=59442895\u0026gen=playurlv3\u0026og=cos\u0026upsig=77babed89168a38118c16f99396e3fb6\u0026uparams=e,platform,trid,oi,os,deadline,tag,nbs,uipk,mid,gen,og\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=31750\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "base_url": "https://xy113x200x108x47xy.mcdn.bilivideo.cn:4483/upgcxcode/65/46/244954665/244954665_nb3-1-30216.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026trid=0000cc6424a6fb564074a7704d5b300496eu\u0026oi=3028829496\u0026os=mcdn\u0026deadline=1745411269\u0026tag=\u0026nbs=1\u0026uipk=5\u0026mid=59442895\u0026gen=playurlv3\u0026og=cos\u0026upsig=77babed89168a38118c16f99396e3fb6\u0026uparams=e,platform,trid,oi,os,deadline,tag,nbs,uipk,mid,gen,og\u0026mcdnid=50017754\u0026bvc=vod\u0026nettype=0\u0026bw=31750\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30216.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026gen=playurlv3\u0026os=cosbv\u0026og=cos\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026mid=59442895\u0026tag=\u0026nbs=1\u0026oi=3028829496\u0026deadline=1745411269\u0026uipk=5\u0026platform=pc\u0026upsig=d76799fe0f76dea02c775c8667fc3f82\u0026uparams=e,gen,os,og,trid,mid,tag,nbs,oi,deadline,uipk,platform\u0026bvc=vod\u0026nettype=0\u0026bw=31750\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30216.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=cosbv\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026oi=3028829496\u0026mid=59442895\u0026tag=\u0026gen=playurlv3\u0026og=cos\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026deadline=1745411269\u0026upsig=5cb2a5242aa474a5a0ba70e16b3d04f6\u0026uparams=e,os,nbs,uipk,platform,oi,mid,tag,gen,og,trid,deadline\u0026bvc=vod\u0026nettype=0\u0026bw=31750\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30216.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026gen=playurlv3\u0026os=cosbv\u0026og=cos\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026mid=59442895\u0026tag=\u0026nbs=1\u0026oi=3028829496\u0026deadline=1745411269\u0026uipk=5\u0026platform=pc\u0026upsig=d76799fe0f76dea02c775c8667fc3f82\u0026uparams=e,gen,os,og,trid,mid,tag,nbs,oi,deadline,uipk,platform\u0026bvc=vod\u0026nettype=0\u0026bw=31750\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/65/46/244954665/244954665_nb3-1-30216.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=cosbv\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026oi=3028829496\u0026mid=59442895\u0026tag=\u0026gen=playurlv3\u0026og=cos\u0026trid=cc6424a6fb564074a7704d5b300496eu\u0026deadline=1745411269\u0026upsig=5cb2a5242aa474a5a0ba70e16b3d04f6\u0026uparams=e,os,nbs,uipk,platform,oi,mid,tag,gen,og,trid,deadline\u0026bvc=vod\u0026nettype=0\u0026bw=31750\u0026f=u_0_0\u0026agrr=1\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=2,3" + ], + "bandwidth": 31705, + "mimeType": "audio/mp4", + "mime_type": "audio/mp4", + "codecs": "mp4a.40.5", + "width": 0, + "height": 0, + "frameRate": "", + "frame_rate": "", + "sar": "", + "startWithSap": 0, + "start_with_sap": 0, + "SegmentBase": { + "Initialization": "0-943", + "indexRange": "944-1815" + }, + "segment_base": { + "initialization": "0-943", + "index_range": "944-1815" + }, + "codecid": 0 + } + ], + "dolby": { + "type": 0, + "audio": null + }, + "flac": null + }, + "support_formats": [ + { + "quality": 125, + "format": "hdflv2", + "new_description": "HDR 真彩", + "display_desc": "HDR", + "superscript": "", + "codecs": [ + "hev1.2.4.L156.90" + ] + }, + { + "quality": 120, + "format": "hdflv2", + "new_description": "4K 超清", + "display_desc": "4K", + "superscript": "", + "codecs": [ + "avc1.640034", + "hev1.1.6.L156.90" + ] + }, + { + "quality": 116, + "format": "flv_p60", + "new_description": "1080P 60帧", + "display_desc": "1080P", + "superscript": "60帧", + "codecs": [ + "avc1.640032", + "hev1.1.6.L150.90" + ] + }, + { + "quality": 80, + "format": "flv", + "new_description": "1080P 高清", + "display_desc": "1080P", + "superscript": "", + "codecs": [ + "avc1.640032", + "hev1.1.6.L150.90" + ] + }, + { + "quality": 64, + "format": "flv720", + "new_description": "720P 高清", + "display_desc": "720P", + "superscript": "", + "codecs": [ + "avc1.640020", + "hev1.1.6.L120.90" + ] + }, + { + "quality": 32, + "format": "flv480", + "new_description": "480P 清晰", + "display_desc": "480P", + "superscript": "", + "codecs": [ + "avc1.64001F", + "hev1.1.6.L120.90" + ] + }, + { + "quality": 16, + "format": "mp4", + "new_description": "360P 流畅", + "display_desc": "360P", + "superscript": "", + "codecs": [ + "avc1.64001E", + "hev1.1.6.L120.90" + ] + } + ], + "high_format": null, + "last_play_time": 0, + "last_play_cid": 0, + "view_info": null, + "play_conf": { + "is_new_description": false + }, + "cur_language": "" + } +} +``` + +
+ +获取视频`av115871406101538`/`BV1pR6UB3ENW`中的 1P(cid=`35306865840`)使用英文AI原声配音的视频流 URL,使用 DASH 方式获取 + +请求示例: + +```shell +curl -G 'https://api.bilibili.com/x/player/playurl' \ + --data-urlencode 'avid=115871406101538' \ + --data-urlencode 'bvid=BV1pR6UB3ENW' \ + --data-urlencode 'cid=35306865840' \ + --data-urlencode 'fnval=4048' \ + --data-urlencode 'fnver=0' \ + --data-urlencode 'fourk=1' \ + --data-urlencode 'cur_language=en' \ + -b 'SESSDATA=xxx' +``` + +
+查看相应示例: + +```json +{ + "code": 0, + "message": "OK", + "ttl": 1, + "data": { + "from": "local", + "result": "suee", + "message": "", + "quality": 64, + "format": "flv720", + "timelength": 173100, + "accept_format": "hdflv2,flv,flv720,flv480,mp4", + "accept_description": [ + "高清 1080P+", + "高清 1080P", + "高清 720P", + "清晰 480P", + "流畅 360P" + ], + "accept_quality": [ + 112, + 80, + 64, + 32, + 16 + ], + "video_codecid": 7, + "seek_param": "start", + "seek_type": "offset", + "dash": { + "duration": 174, + "minBufferTime": 1.5, + "min_buffer_time": 1.5, + "video": [ + { + "id": 112, + "baseUrl": "https://cn-hbyc-ct-01-01.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30112.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026deadline=1768921888\u0026oi=605423425\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026og=hw\u0026nbs=1\u0026uipk=5\u0026mid=38331014\u0026os=bcache\u0026upsig=10c7088d7924086772708970dd475753\u0026uparams=e,platform,deadline,oi,trid,gen,og,nbs,uipk,mid,os\u0026cdnid=88801\u0026bvc=vod\u0026nettype=0\u0026bw=1974380\u0026lrs=42\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "base_url": "https://cn-hbyc-ct-01-01.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30112.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026deadline=1768921888\u0026oi=605423425\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026og=hw\u0026nbs=1\u0026uipk=5\u0026mid=38331014\u0026os=bcache\u0026upsig=10c7088d7924086772708970dd475753\u0026uparams=e,platform,deadline,oi,trid,gen,og,nbs,uipk,mid,os\u0026cdnid=88801\u0026bvc=vod\u0026nettype=0\u0026bw=1974380\u0026lrs=42\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30112.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026uipk=5\u0026platform=pc\u0026deadline=1768921888\u0026trid=e20dd754d5964994878fd44815ac690u\u0026nbs=1\u0026mid=38331014\u0026oi=605423425\u0026gen=playurlv3\u0026os=cosbv\u0026og=hw\u0026upsig=e25487dea1f18e2176ffd47f78e21dcc\u0026uparams=e,uipk,platform,deadline,trid,nbs,mid,oi,gen,os,og\u0026bvc=vod\u0026nettype=0\u0026bw=1974380\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30112.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026og=hw\u0026nbs=1\u0026platform=pc\u0026os=cosbv\u0026oi=605423425\u0026trid=e20dd754d5964994878fd44815ac690u\u0026uipk=5\u0026mid=38331014\u0026deadline=1768921888\u0026gen=playurlv3\u0026upsig=35315a9f898f3fbdc8820e1b36c2d670\u0026uparams=e,og,nbs,platform,os,oi,trid,uipk,mid,deadline,gen\u0026bvc=vod\u0026nettype=0\u0026bw=1974380\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30112.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026uipk=5\u0026platform=pc\u0026deadline=1768921888\u0026trid=e20dd754d5964994878fd44815ac690u\u0026nbs=1\u0026mid=38331014\u0026oi=605423425\u0026gen=playurlv3\u0026os=cosbv\u0026og=hw\u0026upsig=e25487dea1f18e2176ffd47f78e21dcc\u0026uparams=e,uipk,platform,deadline,trid,nbs,mid,oi,gen,os,og\u0026bvc=vod\u0026nettype=0\u0026bw=1974380\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30112.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026og=hw\u0026nbs=1\u0026platform=pc\u0026os=cosbv\u0026oi=605423425\u0026trid=e20dd754d5964994878fd44815ac690u\u0026uipk=5\u0026mid=38331014\u0026deadline=1768921888\u0026gen=playurlv3\u0026upsig=35315a9f898f3fbdc8820e1b36c2d670\u0026uparams=e,og,nbs,platform,os,oi,trid,uipk,mid,deadline,gen\u0026bvc=vod\u0026nettype=0\u0026bw=1974380\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026orderid=2,3" + ], + "bandwidth": 1973175, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "avc1.640033", + "width": 1920, + "height": 1080, + "frameRate": "30.000", + "frame_rate": "30.000", + "sar": "1:1", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-947", + "indexRange": "948-1399" + }, + "segment_base": { + "initialization": "0-947", + "index_range": "948-1399" + }, + "codecid": 7 + }, + { + "id": 112, + "baseUrl": "https://xy60x163x166x213xy.mcdn.bilivideo.cn:8082/v1/resource/35306865840-1-30102.m4s?agrr=0\u0026build=0\u0026buvid=\u0026bvc=vod\u0026bw=1249475\u0026cdnid=88802\u0026deadline=1768921888\u0026dl=0\u0026e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M%3D\u0026f=u_0_0\u0026gen=playurlv3\u0026lrs=42\u0026mid=38331014\u0026nbs=1\u0026nettype=0\u0026og=cos\u0026oi=605423425\u0026orderid=0%2C3\u0026os=bcache\u0026platform=pc\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026sign=b18765\u0026traceid=trdtUXpzcYtlvQ_0_e_N\u0026uipk=5\u0026uparams=e%2Coi%2Ctrid%2Cuipk%2Cplatform%2Cmid%2Cos%2Cog%2Cnbs%2Cdeadline%2Cgen\u0026upsig=a936808f3c612338e01ea479490f27ef", + "base_url": "https://xy60x163x166x213xy.mcdn.bilivideo.cn:8082/v1/resource/35306865840-1-30102.m4s?agrr=0\u0026build=0\u0026buvid=\u0026bvc=vod\u0026bw=1249475\u0026cdnid=88802\u0026deadline=1768921888\u0026dl=0\u0026e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M%3D\u0026f=u_0_0\u0026gen=playurlv3\u0026lrs=42\u0026mid=38331014\u0026nbs=1\u0026nettype=0\u0026og=cos\u0026oi=605423425\u0026orderid=0%2C3\u0026os=bcache\u0026platform=pc\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026sign=b18765\u0026traceid=trdtUXpzcYtlvQ_0_e_N\u0026uipk=5\u0026uparams=e%2Coi%2Ctrid%2Cuipk%2Cplatform%2Cmid%2Cos%2Cog%2Cnbs%2Cdeadline%2Cgen\u0026upsig=a936808f3c612338e01ea479490f27ef", + "backupUrl": [ + "https://cn-hbyc-ct-01-02.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30102.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026oi=605423425\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026uipk=5\u0026platform=pc\u0026mid=38331014\u0026os=bcache\u0026og=cos\u0026nbs=1\u0026deadline=1768921888\u0026gen=playurlv3\u0026upsig=a936808f3c612338e01ea479490f27ef\u0026uparams=e,oi,trid,uipk,platform,mid,os,og,nbs,deadline,gen\u0026cdnid=88802\u0026bvc=vod\u0026nettype=0\u0026bw=1249475\u0026lrs=42\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026orderid=0,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30102.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026og=cos\u0026oi=605423425\u0026nbs=1\u0026gen=playurlv3\u0026trid=e20dd754d5964994878fd44815ac690u\u0026uipk=5\u0026platform=pc\u0026mid=38331014\u0026deadline=1768921888\u0026os=cosbv\u0026upsig=4340534fb442c116e39cdd86f92e52b9\u0026uparams=e,og,oi,nbs,gen,trid,uipk,platform,mid,deadline,os\u0026bvc=vod\u0026nettype=0\u0026bw=1249475\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026orderid=1,3" + ], + "backup_url": [ + "https://cn-hbyc-ct-01-02.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30102.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026oi=605423425\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026uipk=5\u0026platform=pc\u0026mid=38331014\u0026os=bcache\u0026og=cos\u0026nbs=1\u0026deadline=1768921888\u0026gen=playurlv3\u0026upsig=a936808f3c612338e01ea479490f27ef\u0026uparams=e,oi,trid,uipk,platform,mid,os,og,nbs,deadline,gen\u0026cdnid=88802\u0026bvc=vod\u0026nettype=0\u0026bw=1249475\u0026lrs=42\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026orderid=0,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30102.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026og=cos\u0026oi=605423425\u0026nbs=1\u0026gen=playurlv3\u0026trid=e20dd754d5964994878fd44815ac690u\u0026uipk=5\u0026platform=pc\u0026mid=38331014\u0026deadline=1768921888\u0026os=cosbv\u0026upsig=4340534fb442c116e39cdd86f92e52b9\u0026uparams=e,og,oi,nbs,gen,trid,uipk,platform,mid,deadline,os\u0026bvc=vod\u0026nettype=0\u0026bw=1249475\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026orderid=1,3" + ], + "bandwidth": 1248689, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "hev1.1.6.L150.90", + "width": 1920, + "height": 1080, + "frameRate": "30.000", + "frame_rate": "30.000", + "sar": "1:1", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-1108", + "indexRange": "1109-1560" + }, + "segment_base": { + "initialization": "0-1108", + "index_range": "1109-1560" + }, + "codecid": 12 + }, + { + "id": 112, + "baseUrl": "https://xy60x163x162x27xy.mcdn.bilivideo.cn:8082/v1/resource/35306865840-1-100027.m4s?agrr=0\u0026build=0\u0026buvid=\u0026bvc=vod\u0026bw=1018351\u0026cdnid=88801\u0026deadline=1768921888\u0026dl=0\u0026e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M%3D\u0026f=u_0_0\u0026gen=playurlv3\u0026lrs=42\u0026mid=38331014\u0026nbs=1\u0026nettype=0\u0026og=ali\u0026oi=605423425\u0026orderid=0%2C3\u0026os=bcache\u0026platform=pc\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026sign=fcd44e\u0026traceid=trWWkCQiOPSqwK_0_e_N\u0026uipk=5\u0026uparams=e%2Cnbs%2Cuipk%2Ctrid%2Cos%2Cplatform%2Cmid%2Cdeadline%2Coi%2Cgen%2Cog\u0026upsig=b957000962f2d3f2e47fb8028ba32243", + "base_url": "https://xy60x163x162x27xy.mcdn.bilivideo.cn:8082/v1/resource/35306865840-1-100027.m4s?agrr=0\u0026build=0\u0026buvid=\u0026bvc=vod\u0026bw=1018351\u0026cdnid=88801\u0026deadline=1768921888\u0026dl=0\u0026e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M%3D\u0026f=u_0_0\u0026gen=playurlv3\u0026lrs=42\u0026mid=38331014\u0026nbs=1\u0026nettype=0\u0026og=ali\u0026oi=605423425\u0026orderid=0%2C3\u0026os=bcache\u0026platform=pc\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026sign=fcd44e\u0026traceid=trWWkCQiOPSqwK_0_e_N\u0026uipk=5\u0026uparams=e%2Cnbs%2Cuipk%2Ctrid%2Cos%2Cplatform%2Cmid%2Cdeadline%2Coi%2Cgen%2Cog\u0026upsig=b957000962f2d3f2e47fb8028ba32243", + "backupUrl": [ + "https://cn-hbyc-ct-01-01.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100027.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026nbs=1\u0026uipk=5\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026os=bcache\u0026platform=pc\u0026mid=38331014\u0026deadline=1768921888\u0026oi=605423425\u0026gen=playurlv3\u0026og=ali\u0026upsig=b957000962f2d3f2e47fb8028ba32243\u0026uparams=e,nbs,uipk,trid,os,platform,mid,deadline,oi,gen,og\u0026cdnid=88801\u0026bvc=vod\u0026nettype=0\u0026bw=1018351\u0026lrs=42\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=0,3", + "https://upos-sz-estgoss.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100027.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=estgoss\u0026og=ali\u0026deadline=1768921888\u0026trid=e20dd754d5964994878fd44815ac690u\u0026nbs=1\u0026mid=38331014\u0026gen=playurlv3\u0026oi=605423425\u0026uipk=5\u0026platform=pc\u0026upsig=b57ff8f1fa6786700e0b1dfbeea110f5\u0026uparams=e,os,og,deadline,trid,nbs,mid,gen,oi,uipk,platform\u0026bvc=vod\u0026nettype=0\u0026bw=1018351\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026orderid=1,3" + ], + "backup_url": [ + "https://cn-hbyc-ct-01-01.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100027.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026nbs=1\u0026uipk=5\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026os=bcache\u0026platform=pc\u0026mid=38331014\u0026deadline=1768921888\u0026oi=605423425\u0026gen=playurlv3\u0026og=ali\u0026upsig=b957000962f2d3f2e47fb8028ba32243\u0026uparams=e,nbs,uipk,trid,os,platform,mid,deadline,oi,gen,og\u0026cdnid=88801\u0026bvc=vod\u0026nettype=0\u0026bw=1018351\u0026lrs=42\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=0,3", + "https://upos-sz-estgoss.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100027.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=estgoss\u0026og=ali\u0026deadline=1768921888\u0026trid=e20dd754d5964994878fd44815ac690u\u0026nbs=1\u0026mid=38331014\u0026gen=playurlv3\u0026oi=605423425\u0026uipk=5\u0026platform=pc\u0026upsig=b57ff8f1fa6786700e0b1dfbeea110f5\u0026uparams=e,os,og,deadline,trid,nbs,mid,gen,oi,uipk,platform\u0026bvc=vod\u0026nettype=0\u0026bw=1018351\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026orderid=1,3" + ], + "bandwidth": 1017695, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "av01.0.00M.10.0.110.01.01.01.0", + "width": 1920, + "height": 1080, + "frameRate": "30.000", + "frame_rate": "30.000", + "sar": "1:1", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-1010", + "indexRange": "1011-1462" + }, + "segment_base": { + "initialization": "0-1010", + "index_range": "1011-1462" + }, + "codecid": 13 + }, + { + "id": 80, + "baseUrl": "https://cn-hbyc-ct-01-02.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30080.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026deadline=1768921888\u0026oi=605423425\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026nbs=1\u0026mid=38331014\u0026os=bcache\u0026og=hw\u0026uipk=5\u0026upsig=374297c208206f6a1fce3e540d87a385\u0026uparams=e,platform,deadline,oi,trid,gen,nbs,mid,os,og,uipk\u0026cdnid=88802\u0026bvc=vod\u0026nettype=0\u0026bw=1282889\u0026lrs=42\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=0,3", + "base_url": "https://cn-hbyc-ct-01-02.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30080.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026deadline=1768921888\u0026oi=605423425\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026nbs=1\u0026mid=38331014\u0026os=bcache\u0026og=hw\u0026uipk=5\u0026upsig=374297c208206f6a1fce3e540d87a385\u0026uparams=e,platform,deadline,oi,trid,gen,nbs,mid,os,og,uipk\u0026cdnid=88802\u0026bvc=vod\u0026nettype=0\u0026bw=1282889\u0026lrs=42\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirrorzos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30080.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026deadline=1768921888\u0026trid=e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026os=zosbv\u0026og=hw\u0026platform=pc\u0026mid=38331014\u0026oi=605423425\u0026nbs=1\u0026uipk=5\u0026upsig=c9ba6df1df78621fffba26716c5e87ff\u0026uparams=e,deadline,trid,gen,os,og,platform,mid,oi,nbs,uipk\u0026bvc=vod\u0026nettype=0\u0026bw=1282889\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026orderid=1,3", + "https://upos-sz-mirrorzos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30080.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026oi=605423425\u0026trid=e20dd754d5964994878fd44815ac690u\u0026uipk=5\u0026gen=playurlv3\u0026os=zosbv\u0026mid=38331014\u0026deadline=1768921888\u0026nbs=1\u0026og=hw\u0026upsig=5390019aa2418cfc08085bc992b04b18\u0026uparams=e,platform,oi,trid,uipk,gen,os,mid,deadline,nbs,og\u0026bvc=vod\u0026nettype=0\u0026bw=1282889\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirrorzos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30080.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026deadline=1768921888\u0026trid=e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026os=zosbv\u0026og=hw\u0026platform=pc\u0026mid=38331014\u0026oi=605423425\u0026nbs=1\u0026uipk=5\u0026upsig=c9ba6df1df78621fffba26716c5e87ff\u0026uparams=e,deadline,trid,gen,os,og,platform,mid,oi,nbs,uipk\u0026bvc=vod\u0026nettype=0\u0026bw=1282889\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026orderid=1,3", + "https://upos-sz-mirrorzos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30080.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026oi=605423425\u0026trid=e20dd754d5964994878fd44815ac690u\u0026uipk=5\u0026gen=playurlv3\u0026os=zosbv\u0026mid=38331014\u0026deadline=1768921888\u0026nbs=1\u0026og=hw\u0026upsig=5390019aa2418cfc08085bc992b04b18\u0026uparams=e,platform,oi,trid,uipk,gen,os,mid,deadline,nbs,og\u0026bvc=vod\u0026nettype=0\u0026bw=1282889\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=2,3" + ], + "bandwidth": 1282083, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "avc1.640033", + "width": 1920, + "height": 1080, + "frameRate": "30.000", + "frame_rate": "30.000", + "sar": "1:1", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-947", + "indexRange": "948-1399" + }, + "segment_base": { + "initialization": "0-947", + "index_range": "948-1399" + }, + "codecid": 7 + }, + { + "id": 80, + "baseUrl": "https://xy115x231x44x139xy.mcdn.bilivideo.cn:8082/v1/resource/35306865840-1-30077.m4s?agrr=0\u0026build=0\u0026buvid=\u0026bvc=vod\u0026bw=647865\u0026cdnid=88801\u0026deadline=1768921888\u0026dl=0\u0026e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M%3D\u0026f=u_0_0\u0026gen=playurlv3\u0026lrs=42\u0026mid=38331014\u0026nbs=1\u0026nettype=0\u0026og=hw\u0026oi=605423425\u0026orderid=0%2C3\u0026os=bcache\u0026platform=pc\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026sign=598634\u0026traceid=trVvyEMqEnCxMO_0_e_N\u0026uipk=5\u0026uparams=e%2Cnbs%2Coi%2Ctrid%2Cos%2Cuipk%2Cplatform%2Cmid%2Cdeadline%2Cgen%2Cog\u0026upsig=5edd114e5a0ae886fec8fa2e82a47e2e", + "base_url": "https://xy115x231x44x139xy.mcdn.bilivideo.cn:8082/v1/resource/35306865840-1-30077.m4s?agrr=0\u0026build=0\u0026buvid=\u0026bvc=vod\u0026bw=647865\u0026cdnid=88801\u0026deadline=1768921888\u0026dl=0\u0026e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M%3D\u0026f=u_0_0\u0026gen=playurlv3\u0026lrs=42\u0026mid=38331014\u0026nbs=1\u0026nettype=0\u0026og=hw\u0026oi=605423425\u0026orderid=0%2C3\u0026os=bcache\u0026platform=pc\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026sign=598634\u0026traceid=trVvyEMqEnCxMO_0_e_N\u0026uipk=5\u0026uparams=e%2Cnbs%2Coi%2Ctrid%2Cos%2Cuipk%2Cplatform%2Cmid%2Cdeadline%2Cgen%2Cog\u0026upsig=5edd114e5a0ae886fec8fa2e82a47e2e", + "backupUrl": [ + "https://cn-hbyc-ct-01-01.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30077.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026nbs=1\u0026oi=605423425\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026os=bcache\u0026uipk=5\u0026platform=pc\u0026mid=38331014\u0026deadline=1768921888\u0026gen=playurlv3\u0026og=hw\u0026upsig=5edd114e5a0ae886fec8fa2e82a47e2e\u0026uparams=e,nbs,oi,trid,os,uipk,platform,mid,deadline,gen,og\u0026cdnid=88801\u0026bvc=vod\u0026nettype=0\u0026bw=647865\u0026lrs=42\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026orderid=0,3", + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30077.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=08cbv\u0026og=hw\u0026nbs=1\u0026uipk=5\u0026oi=605423425\u0026gen=playurlv3\u0026platform=pc\u0026mid=38331014\u0026deadline=1768921888\u0026trid=e20dd754d5964994878fd44815ac690u\u0026upsig=5b3e14c8e8c9775d77a9c4ed906af794\u0026uparams=e,os,og,nbs,uipk,oi,gen,platform,mid,deadline,trid\u0026bvc=vod\u0026nettype=0\u0026bw=647865\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=1,3" + ], + "backup_url": [ + "https://cn-hbyc-ct-01-01.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30077.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026nbs=1\u0026oi=605423425\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026os=bcache\u0026uipk=5\u0026platform=pc\u0026mid=38331014\u0026deadline=1768921888\u0026gen=playurlv3\u0026og=hw\u0026upsig=5edd114e5a0ae886fec8fa2e82a47e2e\u0026uparams=e,nbs,oi,trid,os,uipk,platform,mid,deadline,gen,og\u0026cdnid=88801\u0026bvc=vod\u0026nettype=0\u0026bw=647865\u0026lrs=42\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026orderid=0,3", + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30077.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=08cbv\u0026og=hw\u0026nbs=1\u0026uipk=5\u0026oi=605423425\u0026gen=playurlv3\u0026platform=pc\u0026mid=38331014\u0026deadline=1768921888\u0026trid=e20dd754d5964994878fd44815ac690u\u0026upsig=5b3e14c8e8c9775d77a9c4ed906af794\u0026uparams=e,os,og,nbs,uipk,oi,gen,platform,mid,deadline,trid\u0026bvc=vod\u0026nettype=0\u0026bw=647865\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=1,3" + ], + "bandwidth": 647422, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "hev1.1.6.L150.90", + "width": 1920, + "height": 1080, + "frameRate": "30.000", + "frame_rate": "30.000", + "sar": "1:1", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-1108", + "indexRange": "1109-1560" + }, + "segment_base": { + "initialization": "0-1108", + "index_range": "1109-1560" + }, + "codecid": 12 + }, + { + "id": 80, + "baseUrl": "https://xy60x163x166x209xy.mcdn.bilivideo.cn:8082/v1/resource/35306865840-1-100026.m4s?agrr=0\u0026build=0\u0026buvid=\u0026bvc=vod\u0026bw=517936\u0026cdnid=88802\u0026deadline=1768921888\u0026dl=0\u0026e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M%3D\u0026f=u_0_0\u0026gen=playurlv3\u0026lrs=42\u0026mid=38331014\u0026nbs=1\u0026nettype=0\u0026og=cos\u0026oi=605423425\u0026orderid=0%2C3\u0026os=bcache\u0026platform=pc\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026sign=f7d612\u0026traceid=trwIKbxttngxnj_0_e_N\u0026uipk=5\u0026uparams=e%2Cuipk%2Cmid%2Coi%2Cgen%2Cnbs%2Cplatform%2Cdeadline%2Ctrid%2Cos%2Cog\u0026upsig=803da73a35b39b2513c4ef8ed01fe686", + "base_url": "https://xy60x163x166x209xy.mcdn.bilivideo.cn:8082/v1/resource/35306865840-1-100026.m4s?agrr=0\u0026build=0\u0026buvid=\u0026bvc=vod\u0026bw=517936\u0026cdnid=88802\u0026deadline=1768921888\u0026dl=0\u0026e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M%3D\u0026f=u_0_0\u0026gen=playurlv3\u0026lrs=42\u0026mid=38331014\u0026nbs=1\u0026nettype=0\u0026og=cos\u0026oi=605423425\u0026orderid=0%2C3\u0026os=bcache\u0026platform=pc\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026sign=f7d612\u0026traceid=trwIKbxttngxnj_0_e_N\u0026uipk=5\u0026uparams=e%2Cuipk%2Cmid%2Coi%2Cgen%2Cnbs%2Cplatform%2Cdeadline%2Ctrid%2Cos%2Cog\u0026upsig=803da73a35b39b2513c4ef8ed01fe686", + "backupUrl": [ + "https://cn-hbyc-ct-01-02.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100026.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026uipk=5\u0026mid=38331014\u0026oi=605423425\u0026gen=playurlv3\u0026nbs=1\u0026platform=pc\u0026deadline=1768921888\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026os=bcache\u0026og=cos\u0026upsig=803da73a35b39b2513c4ef8ed01fe686\u0026uparams=e,uipk,mid,oi,gen,nbs,platform,deadline,trid,os,og\u0026cdnid=88802\u0026bvc=vod\u0026nettype=0\u0026bw=517936\u0026lrs=42\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=0,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100026.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026gen=playurlv3\u0026mid=38331014\u0026oi=605423425\u0026os=cosbv\u0026og=cos\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026deadline=1768921888\u0026trid=e20dd754d5964994878fd44815ac690u\u0026upsig=2ce2b39750969fc9e8f03691cd572c2e\u0026uparams=e,gen,mid,oi,os,og,nbs,uipk,platform,deadline,trid\u0026bvc=vod\u0026nettype=0\u0026bw=517936\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026orderid=1,3" + ], + "backup_url": [ + "https://cn-hbyc-ct-01-02.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100026.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026uipk=5\u0026mid=38331014\u0026oi=605423425\u0026gen=playurlv3\u0026nbs=1\u0026platform=pc\u0026deadline=1768921888\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026os=bcache\u0026og=cos\u0026upsig=803da73a35b39b2513c4ef8ed01fe686\u0026uparams=e,uipk,mid,oi,gen,nbs,platform,deadline,trid,os,og\u0026cdnid=88802\u0026bvc=vod\u0026nettype=0\u0026bw=517936\u0026lrs=42\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=0,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100026.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026gen=playurlv3\u0026mid=38331014\u0026oi=605423425\u0026os=cosbv\u0026og=cos\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026deadline=1768921888\u0026trid=e20dd754d5964994878fd44815ac690u\u0026upsig=2ce2b39750969fc9e8f03691cd572c2e\u0026uparams=e,gen,mid,oi,os,og,nbs,uipk,platform,deadline,trid\u0026bvc=vod\u0026nettype=0\u0026bw=517936\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026orderid=1,3" + ], + "bandwidth": 517569, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "av01.0.00M.10.0.110.01.01.01.0", + "width": 1920, + "height": 1080, + "frameRate": "30.000", + "frame_rate": "30.000", + "sar": "1:1", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-1010", + "indexRange": "1011-1462" + }, + "segment_base": { + "initialization": "0-1010", + "index_range": "1011-1462" + }, + "codecid": 13 + }, + { + "id": 64, + "baseUrl": "https://cn-hbyc-ct-01-05.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30064.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026gen=playurlv3\u0026og=cos\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026mid=38331014\u0026oi=605423425\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026os=bcache\u0026deadline=1768921888\u0026upsig=43e5c50e0e538112a14dd05323ac50ee\u0026uparams=e,gen,og,nbs,uipk,platform,mid,oi,trid,os,deadline\u0026cdnid=88805\u0026bvc=vod\u0026nettype=0\u0026bw=518391\u0026lrs=42\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=0,3", + "base_url": "https://cn-hbyc-ct-01-05.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30064.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026gen=playurlv3\u0026og=cos\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026mid=38331014\u0026oi=605423425\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026os=bcache\u0026deadline=1768921888\u0026upsig=43e5c50e0e538112a14dd05323ac50ee\u0026uparams=e,gen,og,nbs,uipk,platform,mid,oi,trid,os,deadline\u0026cdnid=88805\u0026bvc=vod\u0026nettype=0\u0026bw=518391\u0026lrs=42\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30064.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026uipk=5\u0026deadline=1768921888\u0026os=cosbv\u0026nbs=1\u0026platform=pc\u0026mid=38331014\u0026gen=playurlv3\u0026og=cos\u0026oi=605423425\u0026trid=e20dd754d5964994878fd44815ac690u\u0026upsig=3ca661cdda109d65c246178f8e20896e\u0026uparams=e,uipk,deadline,os,nbs,platform,mid,gen,og,oi,trid\u0026bvc=vod\u0026nettype=0\u0026bw=518391\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30064.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=cosbv\u0026oi=605423425\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026mid=38331014\u0026deadline=1768921888\u0026gen=playurlv3\u0026og=cos\u0026trid=e20dd754d5964994878fd44815ac690u\u0026upsig=2ba66dedf2e1dfcc33a1bdb97e0aa49b\u0026uparams=e,os,oi,nbs,uipk,platform,mid,deadline,gen,og,trid\u0026bvc=vod\u0026nettype=0\u0026bw=518391\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30064.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026uipk=5\u0026deadline=1768921888\u0026os=cosbv\u0026nbs=1\u0026platform=pc\u0026mid=38331014\u0026gen=playurlv3\u0026og=cos\u0026oi=605423425\u0026trid=e20dd754d5964994878fd44815ac690u\u0026upsig=3ca661cdda109d65c246178f8e20896e\u0026uparams=e,uipk,deadline,os,nbs,platform,mid,gen,og,oi,trid\u0026bvc=vod\u0026nettype=0\u0026bw=518391\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30064.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=cosbv\u0026oi=605423425\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026mid=38331014\u0026deadline=1768921888\u0026gen=playurlv3\u0026og=cos\u0026trid=e20dd754d5964994878fd44815ac690u\u0026upsig=2ba66dedf2e1dfcc33a1bdb97e0aa49b\u0026uparams=e,os,oi,nbs,uipk,platform,mid,deadline,gen,og,trid\u0026bvc=vod\u0026nettype=0\u0026bw=518391\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=2,3" + ], + "bandwidth": 518027, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "avc1.640033", + "width": 1280, + "height": 720, + "frameRate": "30.000", + "frame_rate": "30.000", + "sar": "1:1", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-945", + "indexRange": "946-1397" + }, + "segment_base": { + "initialization": "0-945", + "index_range": "946-1397" + }, + "codecid": 7 + }, + { + "id": 64, + "baseUrl": "https://xy60x163x166x210xy.mcdn.bilivideo.cn:8082/v1/resource/35306865840-1-30066.m4s?agrr=0\u0026build=0\u0026buvid=\u0026bvc=vod\u0026bw=298292\u0026cdnid=88802\u0026deadline=1768921888\u0026dl=0\u0026e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M%3D\u0026f=u_0_0\u0026gen=playurlv3\u0026lrs=42\u0026mid=38331014\u0026nbs=1\u0026nettype=0\u0026og=hw\u0026oi=605423425\u0026orderid=0%2C3\u0026os=bcache\u0026platform=pc\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026sign=5f63a8\u0026traceid=trxmPMoVQLDXJM_0_e_N\u0026uipk=5\u0026uparams=e%2Cos%2Cnbs%2Cog%2Ctrid%2Cuipk%2Cplatform%2Cmid%2Cdeadline%2Coi%2Cgen\u0026upsig=4557aa74f373b297e0a6a04b5038ed0a", + "base_url": "https://xy60x163x166x210xy.mcdn.bilivideo.cn:8082/v1/resource/35306865840-1-30066.m4s?agrr=0\u0026build=0\u0026buvid=\u0026bvc=vod\u0026bw=298292\u0026cdnid=88802\u0026deadline=1768921888\u0026dl=0\u0026e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M%3D\u0026f=u_0_0\u0026gen=playurlv3\u0026lrs=42\u0026mid=38331014\u0026nbs=1\u0026nettype=0\u0026og=hw\u0026oi=605423425\u0026orderid=0%2C3\u0026os=bcache\u0026platform=pc\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026sign=5f63a8\u0026traceid=trxmPMoVQLDXJM_0_e_N\u0026uipk=5\u0026uparams=e%2Cos%2Cnbs%2Cog%2Ctrid%2Cuipk%2Cplatform%2Cmid%2Cdeadline%2Coi%2Cgen\u0026upsig=4557aa74f373b297e0a6a04b5038ed0a", + "backupUrl": [ + "https://cn-hbyc-ct-01-02.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30066.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=bcache\u0026nbs=1\u0026og=hw\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026uipk=5\u0026platform=pc\u0026mid=38331014\u0026deadline=1768921888\u0026oi=605423425\u0026gen=playurlv3\u0026upsig=4557aa74f373b297e0a6a04b5038ed0a\u0026uparams=e,os,nbs,og,trid,uipk,platform,mid,deadline,oi,gen\u0026cdnid=88802\u0026bvc=vod\u0026nettype=0\u0026bw=298292\u0026lrs=42\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026orderid=0,3", + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30066.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026trid=e20dd754d5964994878fd44815ac690u\u0026uipk=5\u0026deadline=1768921888\u0026gen=playurlv3\u0026og=hw\u0026nbs=1\u0026platform=pc\u0026mid=38331014\u0026os=08cbv\u0026oi=605423425\u0026upsig=eda15c18ff3427591234a8cfcf0a4a88\u0026uparams=e,trid,uipk,deadline,gen,og,nbs,platform,mid,os,oi\u0026bvc=vod\u0026nettype=0\u0026bw=298292\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026orderid=1,3" + ], + "backup_url": [ + "https://cn-hbyc-ct-01-02.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30066.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=bcache\u0026nbs=1\u0026og=hw\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026uipk=5\u0026platform=pc\u0026mid=38331014\u0026deadline=1768921888\u0026oi=605423425\u0026gen=playurlv3\u0026upsig=4557aa74f373b297e0a6a04b5038ed0a\u0026uparams=e,os,nbs,og,trid,uipk,platform,mid,deadline,oi,gen\u0026cdnid=88802\u0026bvc=vod\u0026nettype=0\u0026bw=298292\u0026lrs=42\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026orderid=0,3", + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30066.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026trid=e20dd754d5964994878fd44815ac690u\u0026uipk=5\u0026deadline=1768921888\u0026gen=playurlv3\u0026og=hw\u0026nbs=1\u0026platform=pc\u0026mid=38331014\u0026os=08cbv\u0026oi=605423425\u0026upsig=eda15c18ff3427591234a8cfcf0a4a88\u0026uparams=e,trid,uipk,deadline,gen,og,nbs,platform,mid,os,oi\u0026bvc=vod\u0026nettype=0\u0026bw=298292\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026orderid=1,3" + ], + "bandwidth": 298050, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "hev1.1.6.L120.90", + "width": 1280, + "height": 720, + "frameRate": "30.000", + "frame_rate": "30.000", + "sar": "1:1", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-1107", + "indexRange": "1108-1559" + }, + "segment_base": { + "initialization": "0-1107", + "index_range": "1108-1559" + }, + "codecid": 12 + }, + { + "id": 64, + "baseUrl": "https://xy60x188x71x66xy.mcdn.bilivideo.cn:8082/v1/resource/35306865840-1-100024.m4s?agrr=0\u0026build=0\u0026buvid=\u0026bvc=vod\u0026bw=251176\u0026cdnid=88805\u0026deadline=1768921888\u0026dl=0\u0026e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M%3D\u0026f=u_0_0\u0026gen=playurlv3\u0026lrs=42\u0026mid=38331014\u0026nbs=1\u0026nettype=0\u0026og=ali\u0026oi=605423425\u0026orderid=0%2C3\u0026os=bcache\u0026platform=pc\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026sign=df86d8\u0026traceid=trJKelwVBuuosq_0_e_N\u0026uipk=5\u0026uparams=e%2Cplatform%2Cdeadline%2Ctrid%2Cgen%2Cnbs%2Cuipk%2Cmid%2Coi%2Cos%2Cog\u0026upsig=c62f2453cb175f09c7087b48492a0890", + "base_url": "https://xy60x188x71x66xy.mcdn.bilivideo.cn:8082/v1/resource/35306865840-1-100024.m4s?agrr=0\u0026build=0\u0026buvid=\u0026bvc=vod\u0026bw=251176\u0026cdnid=88805\u0026deadline=1768921888\u0026dl=0\u0026e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M%3D\u0026f=u_0_0\u0026gen=playurlv3\u0026lrs=42\u0026mid=38331014\u0026nbs=1\u0026nettype=0\u0026og=ali\u0026oi=605423425\u0026orderid=0%2C3\u0026os=bcache\u0026platform=pc\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026sign=df86d8\u0026traceid=trJKelwVBuuosq_0_e_N\u0026uipk=5\u0026uparams=e%2Cplatform%2Cdeadline%2Ctrid%2Cgen%2Cnbs%2Cuipk%2Cmid%2Coi%2Cos%2Cog\u0026upsig=c62f2453cb175f09c7087b48492a0890", + "backupUrl": [ + "https://cn-hbyc-ct-01-05.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100024.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026deadline=1768921888\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026nbs=1\u0026uipk=5\u0026mid=38331014\u0026oi=605423425\u0026os=bcache\u0026og=ali\u0026upsig=c62f2453cb175f09c7087b48492a0890\u0026uparams=e,platform,deadline,trid,gen,nbs,uipk,mid,oi,os,og\u0026cdnid=88805\u0026bvc=vod\u0026nettype=0\u0026bw=251176\u0026lrs=42\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "https://upos-sz-estgoss.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100024.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026deadline=1768921888\u0026og=ali\u0026mid=38331014\u0026oi=605423425\u0026trid=e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026os=estgoss\u0026upsig=fcb46de4b4593935875c7abd5ccc37ac\u0026uparams=e,nbs,uipk,platform,deadline,og,mid,oi,trid,gen,os\u0026bvc=vod\u0026nettype=0\u0026bw=251176\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=1,3" + ], + "backup_url": [ + "https://cn-hbyc-ct-01-05.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100024.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026deadline=1768921888\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026nbs=1\u0026uipk=5\u0026mid=38331014\u0026oi=605423425\u0026os=bcache\u0026og=ali\u0026upsig=c62f2453cb175f09c7087b48492a0890\u0026uparams=e,platform,deadline,trid,gen,nbs,uipk,mid,oi,os,og\u0026cdnid=88805\u0026bvc=vod\u0026nettype=0\u0026bw=251176\u0026lrs=42\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "https://upos-sz-estgoss.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100024.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026deadline=1768921888\u0026og=ali\u0026mid=38331014\u0026oi=605423425\u0026trid=e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026os=estgoss\u0026upsig=fcb46de4b4593935875c7abd5ccc37ac\u0026uparams=e,nbs,uipk,platform,deadline,og,mid,oi,trid,gen,os\u0026bvc=vod\u0026nettype=0\u0026bw=251176\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=1,3" + ], + "bandwidth": 250963, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "av01.0.00M.10.0.110.01.01.01.0", + "width": 1280, + "height": 720, + "frameRate": "30.000", + "frame_rate": "30.000", + "sar": "1:1", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-1010", + "indexRange": "1011-1462" + }, + "segment_base": { + "initialization": "0-1010", + "index_range": "1011-1462" + }, + "codecid": 13 + }, + { + "id": 32, + "baseUrl": "https://xy115x231x44x139xy.mcdn.bilivideo.cn:8082/v1/resource/35306865840-1-30032.m4s?agrr=0\u0026build=0\u0026buvid=\u0026bvc=vod\u0026bw=262520\u0026cdnid=88805\u0026deadline=1768921888\u0026dl=0\u0026e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M%3D\u0026f=u_0_0\u0026gen=playurlv3\u0026lrs=42\u0026mid=38331014\u0026nbs=1\u0026nettype=0\u0026og=cos\u0026oi=605423425\u0026orderid=0%2C3\u0026os=bcache\u0026platform=pc\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026sign=fd840d\u0026traceid=trxsurzRqeJgoi_0_e_N\u0026uipk=5\u0026uparams=e%2Ctrid%2Cgen%2Cog%2Cuipk%2Cmid%2Cdeadline%2Cos%2Cnbs%2Cplatform%2Coi\u0026upsig=de3812cc9f42e8cb4f652ae93ad03c7d", + "base_url": "https://xy115x231x44x139xy.mcdn.bilivideo.cn:8082/v1/resource/35306865840-1-30032.m4s?agrr=0\u0026build=0\u0026buvid=\u0026bvc=vod\u0026bw=262520\u0026cdnid=88805\u0026deadline=1768921888\u0026dl=0\u0026e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M%3D\u0026f=u_0_0\u0026gen=playurlv3\u0026lrs=42\u0026mid=38331014\u0026nbs=1\u0026nettype=0\u0026og=cos\u0026oi=605423425\u0026orderid=0%2C3\u0026os=bcache\u0026platform=pc\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026sign=fd840d\u0026traceid=trxsurzRqeJgoi_0_e_N\u0026uipk=5\u0026uparams=e%2Ctrid%2Cgen%2Cog%2Cuipk%2Cmid%2Cdeadline%2Cos%2Cnbs%2Cplatform%2Coi\u0026upsig=de3812cc9f42e8cb4f652ae93ad03c7d", + "backupUrl": [ + "https://cn-hbyc-ct-01-05.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30032.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026og=cos\u0026uipk=5\u0026mid=38331014\u0026deadline=1768921888\u0026os=bcache\u0026nbs=1\u0026platform=pc\u0026oi=605423425\u0026upsig=de3812cc9f42e8cb4f652ae93ad03c7d\u0026uparams=e,trid,gen,og,uipk,mid,deadline,os,nbs,platform,oi\u0026cdnid=88805\u0026bvc=vod\u0026nettype=0\u0026bw=262520\u0026lrs=42\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "https://upos-sz-estgoss.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30032.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026oi=605423425\u0026trid=e20dd754d5964994878fd44815ac690u\u0026nbs=1\u0026mid=38331014\u0026deadline=1768921888\u0026gen=playurlv3\u0026os=estgoss\u0026uipk=5\u0026platform=pc\u0026og=cos\u0026upsig=38ca77338127572828ddb3aaf81c967c\u0026uparams=e,oi,trid,nbs,mid,deadline,gen,os,uipk,platform,og\u0026bvc=vod\u0026nettype=0\u0026bw=262520\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026orderid=1,3" + ], + "backup_url": [ + "https://cn-hbyc-ct-01-05.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30032.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026og=cos\u0026uipk=5\u0026mid=38331014\u0026deadline=1768921888\u0026os=bcache\u0026nbs=1\u0026platform=pc\u0026oi=605423425\u0026upsig=de3812cc9f42e8cb4f652ae93ad03c7d\u0026uparams=e,trid,gen,og,uipk,mid,deadline,os,nbs,platform,oi\u0026cdnid=88805\u0026bvc=vod\u0026nettype=0\u0026bw=262520\u0026lrs=42\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "https://upos-sz-estgoss.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30032.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026oi=605423425\u0026trid=e20dd754d5964994878fd44815ac690u\u0026nbs=1\u0026mid=38331014\u0026deadline=1768921888\u0026gen=playurlv3\u0026os=estgoss\u0026uipk=5\u0026platform=pc\u0026og=cos\u0026upsig=38ca77338127572828ddb3aaf81c967c\u0026uparams=e,oi,trid,nbs,mid,deadline,gen,os,uipk,platform,og\u0026bvc=vod\u0026nettype=0\u0026bw=262520\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026orderid=1,3" + ], + "bandwidth": 262304, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "avc1.640033", + "width": 852, + "height": 480, + "frameRate": "30.000", + "frame_rate": "30.000", + "sar": "640:639", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-950", + "indexRange": "951-1402" + }, + "segment_base": { + "initialization": "0-950", + "index_range": "951-1402" + }, + "codecid": 7 + }, + { + "id": 32, + "baseUrl": "https://cn-hbyc-ct-01-05.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30033.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026deadline=1768921888\u0026gen=playurlv3\u0026os=bcache\u0026oi=605423425\u0026mid=38331014\u0026og=ali\u0026upsig=13a4c3d43c0c34bf5105bab7d8f1e66c\u0026uparams=e,trid,nbs,uipk,platform,deadline,gen,os,oi,mid,og\u0026cdnid=88805\u0026bvc=vod\u0026nettype=0\u0026bw=177469\u0026lrs=42\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=0,3", + "base_url": "https://cn-hbyc-ct-01-05.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30033.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026deadline=1768921888\u0026gen=playurlv3\u0026os=bcache\u0026oi=605423425\u0026mid=38331014\u0026og=ali\u0026upsig=13a4c3d43c0c34bf5105bab7d8f1e66c\u0026uparams=e,trid,nbs,uipk,platform,deadline,gen,os,oi,mid,og\u0026cdnid=88805\u0026bvc=vod\u0026nettype=0\u0026bw=177469\u0026lrs=42\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-estgoss.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30033.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026oi=605423425\u0026trid=e20dd754d5964994878fd44815ac690u\u0026mid=38331014\u0026deadline=1768921888\u0026gen=playurlv3\u0026os=estgoss\u0026og=ali\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026upsig=7ab9c18be58382ad92b015e60b1d81d1\u0026uparams=e,oi,trid,mid,deadline,gen,os,og,nbs,uipk,platform\u0026bvc=vod\u0026nettype=0\u0026bw=177469\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=1,3", + "https://upos-sz-estgoss.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30033.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026trid=e20dd754d5964994878fd44815ac690u\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026deadline=1768921888\u0026gen=playurlv3\u0026oi=605423425\u0026mid=38331014\u0026os=estgoss\u0026og=ali\u0026upsig=a3db99b9a34d473e111d9462d705b848\u0026uparams=e,trid,nbs,uipk,platform,deadline,gen,oi,mid,os,og\u0026bvc=vod\u0026nettype=0\u0026bw=177469\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-estgoss.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30033.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026oi=605423425\u0026trid=e20dd754d5964994878fd44815ac690u\u0026mid=38331014\u0026deadline=1768921888\u0026gen=playurlv3\u0026os=estgoss\u0026og=ali\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026upsig=7ab9c18be58382ad92b015e60b1d81d1\u0026uparams=e,oi,trid,mid,deadline,gen,os,og,nbs,uipk,platform\u0026bvc=vod\u0026nettype=0\u0026bw=177469\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=1,3", + "https://upos-sz-estgoss.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30033.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026trid=e20dd754d5964994878fd44815ac690u\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026deadline=1768921888\u0026gen=playurlv3\u0026oi=605423425\u0026mid=38331014\u0026os=estgoss\u0026og=ali\u0026upsig=a3db99b9a34d473e111d9462d705b848\u0026uparams=e,trid,nbs,uipk,platform,deadline,gen,oi,mid,os,og\u0026bvc=vod\u0026nettype=0\u0026bw=177469\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026orderid=2,3" + ], + "bandwidth": 177295, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "hev1.1.6.L120.90", + "width": 852, + "height": 480, + "frameRate": "30.000", + "frame_rate": "30.000", + "sar": "640:639", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-1112", + "indexRange": "1113-1564" + }, + "segment_base": { + "initialization": "0-1112", + "index_range": "1113-1564" + }, + "codecid": 12 + }, + { + "id": 32, + "baseUrl": "https://xy218x60x39x73xy.mcdn.bilivideo.cn:8082/v1/resource/35306865840-1-100023.m4s?agrr=0\u0026build=0\u0026buvid=\u0026bvc=vod\u0026bw=150725\u0026cdnid=88801\u0026deadline=1768921888\u0026dl=0\u0026e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M%3D\u0026f=u_0_0\u0026gen=playurlv3\u0026lrs=42\u0026mid=38331014\u0026nbs=1\u0026nettype=0\u0026og=ali\u0026oi=605423425\u0026orderid=0%2C3\u0026os=bcache\u0026platform=pc\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026sign=7bb757\u0026traceid=trnydvRtRCjubG_0_e_N\u0026uipk=5\u0026uparams=e%2Cos%2Cog%2Cnbs%2Cplatform%2Cmid%2Cdeadline%2Coi%2Cgen%2Cuipk%2Ctrid\u0026upsig=dd02a985b8ddc3b4a71cbb2587940f33", + "base_url": "https://xy218x60x39x73xy.mcdn.bilivideo.cn:8082/v1/resource/35306865840-1-100023.m4s?agrr=0\u0026build=0\u0026buvid=\u0026bvc=vod\u0026bw=150725\u0026cdnid=88801\u0026deadline=1768921888\u0026dl=0\u0026e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M%3D\u0026f=u_0_0\u0026gen=playurlv3\u0026lrs=42\u0026mid=38331014\u0026nbs=1\u0026nettype=0\u0026og=ali\u0026oi=605423425\u0026orderid=0%2C3\u0026os=bcache\u0026platform=pc\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026sign=7bb757\u0026traceid=trnydvRtRCjubG_0_e_N\u0026uipk=5\u0026uparams=e%2Cos%2Cog%2Cnbs%2Cplatform%2Cmid%2Cdeadline%2Coi%2Cgen%2Cuipk%2Ctrid\u0026upsig=dd02a985b8ddc3b4a71cbb2587940f33", + "backupUrl": [ + "https://cn-hbyc-ct-01-01.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100023.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=bcache\u0026og=ali\u0026nbs=1\u0026platform=pc\u0026mid=38331014\u0026deadline=1768921888\u0026oi=605423425\u0026gen=playurlv3\u0026uipk=5\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026upsig=dd02a985b8ddc3b4a71cbb2587940f33\u0026uparams=e,os,og,nbs,platform,mid,deadline,oi,gen,uipk,trid\u0026cdnid=88801\u0026bvc=vod\u0026nettype=0\u0026bw=150725\u0026lrs=42\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "https://upos-sz-estgoss.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100023.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026gen=playurlv3\u0026os=estgoss\u0026og=ali\u0026oi=605423425\u0026trid=e20dd754d5964994878fd44815ac690u\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026mid=38331014\u0026deadline=1768921888\u0026upsig=b9bb2f0770330407ae725c1c340f1afc\u0026uparams=e,gen,os,og,oi,trid,nbs,uipk,platform,mid,deadline\u0026bvc=vod\u0026nettype=0\u0026bw=150725\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026orderid=1,3" + ], + "backup_url": [ + "https://cn-hbyc-ct-01-01.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100023.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=bcache\u0026og=ali\u0026nbs=1\u0026platform=pc\u0026mid=38331014\u0026deadline=1768921888\u0026oi=605423425\u0026gen=playurlv3\u0026uipk=5\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026upsig=dd02a985b8ddc3b4a71cbb2587940f33\u0026uparams=e,os,og,nbs,platform,mid,deadline,oi,gen,uipk,trid\u0026cdnid=88801\u0026bvc=vod\u0026nettype=0\u0026bw=150725\u0026lrs=42\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "https://upos-sz-estgoss.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100023.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026gen=playurlv3\u0026os=estgoss\u0026og=ali\u0026oi=605423425\u0026trid=e20dd754d5964994878fd44815ac690u\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026mid=38331014\u0026deadline=1768921888\u0026upsig=b9bb2f0770330407ae725c1c340f1afc\u0026uparams=e,gen,os,og,oi,trid,nbs,uipk,platform,mid,deadline\u0026bvc=vod\u0026nettype=0\u0026bw=150725\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026orderid=1,3" + ], + "bandwidth": 150571, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "av01.0.00M.10.0.110.01.01.01.0", + "width": 852, + "height": 480, + "frameRate": "30.000", + "frame_rate": "30.000", + "sar": "640:639", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-1010", + "indexRange": "1011-1462" + }, + "segment_base": { + "initialization": "0-1010", + "index_range": "1011-1462" + }, + "codecid": 13 + }, + { + "id": 16, + "baseUrl": "https://cn-hbyc-ct-01-02.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30011.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026uipk=5\u0026platform=pc\u0026deadline=1768921888\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026og=hw\u0026nbs=1\u0026mid=38331014\u0026oi=605423425\u0026os=bcache\u0026upsig=fa94c40e060692230803ac1c6663332a\u0026uparams=e,uipk,platform,deadline,trid,gen,og,nbs,mid,oi,os\u0026cdnid=88802\u0026bvc=vod\u0026nettype=0\u0026bw=123644\u0026lrs=42\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026orderid=0,3", + "base_url": "https://cn-hbyc-ct-01-02.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30011.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026uipk=5\u0026platform=pc\u0026deadline=1768921888\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026og=hw\u0026nbs=1\u0026mid=38331014\u0026oi=605423425\u0026os=bcache\u0026upsig=fa94c40e060692230803ac1c6663332a\u0026uparams=e,uipk,platform,deadline,trid,gen,og,nbs,mid,oi,os\u0026cdnid=88802\u0026bvc=vod\u0026nettype=0\u0026bw=123644\u0026lrs=42\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30011.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=08cbv\u0026og=hw\u0026platform=pc\u0026deadline=1768921888\u0026oi=605423425\u0026nbs=1\u0026uipk=5\u0026mid=38331014\u0026trid=e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026upsig=907903b6cf872d695824c7c90d5a8215\u0026uparams=e,os,og,platform,deadline,oi,nbs,uipk,mid,trid,gen\u0026bvc=vod\u0026nettype=0\u0026bw=123644\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026orderid=1,3", + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30011.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026uipk=5\u0026oi=605423425\u0026nbs=1\u0026platform=pc\u0026mid=38331014\u0026deadline=1768921888\u0026gen=playurlv3\u0026os=08cbv\u0026og=hw\u0026trid=e20dd754d5964994878fd44815ac690u\u0026upsig=50d4bf9786979cdbed40d0f0a55bbe60\u0026uparams=e,uipk,oi,nbs,platform,mid,deadline,gen,os,og,trid\u0026bvc=vod\u0026nettype=0\u0026bw=123644\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30011.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=08cbv\u0026og=hw\u0026platform=pc\u0026deadline=1768921888\u0026oi=605423425\u0026nbs=1\u0026uipk=5\u0026mid=38331014\u0026trid=e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026upsig=907903b6cf872d695824c7c90d5a8215\u0026uparams=e,os,og,platform,deadline,oi,nbs,uipk,mid,trid,gen\u0026bvc=vod\u0026nettype=0\u0026bw=123644\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026orderid=1,3", + "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30011.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026uipk=5\u0026oi=605423425\u0026nbs=1\u0026platform=pc\u0026mid=38331014\u0026deadline=1768921888\u0026gen=playurlv3\u0026os=08cbv\u0026og=hw\u0026trid=e20dd754d5964994878fd44815ac690u\u0026upsig=50d4bf9786979cdbed40d0f0a55bbe60\u0026uparams=e,uipk,oi,nbs,platform,mid,deadline,gen,os,og,trid\u0026bvc=vod\u0026nettype=0\u0026bw=123644\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026orderid=2,3" + ], + "bandwidth": 123502, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "hev1.1.6.L120.90", + "width": 640, + "height": 360, + "frameRate": "30.000", + "frame_rate": "30.000", + "sar": "1:1", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-1108", + "indexRange": "1109-1560" + }, + "segment_base": { + "initialization": "0-1108", + "index_range": "1109-1560" + }, + "codecid": 12 + }, + { + "id": 16, + "baseUrl": "https://cn-hbyc-ct-01-05.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30016.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026nbs=1\u0026uipk=5\u0026deadline=1768921888\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026platform=pc\u0026mid=38331014\u0026oi=605423425\u0026gen=playurlv3\u0026os=bcache\u0026og=cos\u0026upsig=97252202334105cf4efc0af956642565\u0026uparams=e,nbs,uipk,deadline,trid,platform,mid,oi,gen,os,og\u0026cdnid=88805\u0026bvc=vod\u0026nettype=0\u0026bw=170409\u0026lrs=42\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=0,3", + "base_url": "https://cn-hbyc-ct-01-05.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30016.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026nbs=1\u0026uipk=5\u0026deadline=1768921888\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026platform=pc\u0026mid=38331014\u0026oi=605423425\u0026gen=playurlv3\u0026os=bcache\u0026og=cos\u0026upsig=97252202334105cf4efc0af956642565\u0026uparams=e,nbs,uipk,deadline,trid,platform,mid,oi,gen,os,og\u0026cdnid=88805\u0026bvc=vod\u0026nettype=0\u0026bw=170409\u0026lrs=42\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30016.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026mid=38331014\u0026os=cosbv\u0026nbs=1\u0026uipk=5\u0026deadline=1768921888\u0026oi=605423425\u0026trid=e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026og=cos\u0026platform=pc\u0026upsig=6e6496389af268a0e3ef31c904316024\u0026uparams=e,mid,os,nbs,uipk,deadline,oi,trid,gen,og,platform\u0026bvc=vod\u0026nettype=0\u0026bw=170409\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30016.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026mid=38331014\u0026deadline=1768921888\u0026gen=playurlv3\u0026os=cosbv\u0026nbs=1\u0026oi=605423425\u0026trid=e20dd754d5964994878fd44815ac690u\u0026og=cos\u0026uipk=5\u0026platform=pc\u0026upsig=e7c6a3eb7904090ee54f538e8a5be530\u0026uparams=e,mid,deadline,gen,os,nbs,oi,trid,og,uipk,platform\u0026bvc=vod\u0026nettype=0\u0026bw=170409\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30016.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026mid=38331014\u0026os=cosbv\u0026nbs=1\u0026uipk=5\u0026deadline=1768921888\u0026oi=605423425\u0026trid=e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026og=cos\u0026platform=pc\u0026upsig=6e6496389af268a0e3ef31c904316024\u0026uparams=e,mid,os,nbs,uipk,deadline,oi,trid,gen,og,platform\u0026bvc=vod\u0026nettype=0\u0026bw=170409\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-30016.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026mid=38331014\u0026deadline=1768921888\u0026gen=playurlv3\u0026os=cosbv\u0026nbs=1\u0026oi=605423425\u0026trid=e20dd754d5964994878fd44815ac690u\u0026og=cos\u0026uipk=5\u0026platform=pc\u0026upsig=e7c6a3eb7904090ee54f538e8a5be530\u0026uparams=e,mid,deadline,gen,os,nbs,oi,trid,og,uipk,platform\u0026bvc=vod\u0026nettype=0\u0026bw=170409\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026orderid=2,3" + ], + "bandwidth": 170245, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "avc1.640033", + "width": 640, + "height": 360, + "frameRate": "30.000", + "frame_rate": "30.000", + "sar": "1:1", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-954", + "indexRange": "955-1406" + }, + "segment_base": { + "initialization": "0-954", + "index_range": "955-1406" + }, + "codecid": 7 + }, + { + "id": 16, + "baseUrl": "https://cn-hbyc-ct-01-05.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100022.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026mid=38331014\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026deadline=1768921888\u0026oi=605423425\u0026os=bcache\u0026og=cos\u0026upsig=0b2259ac082418fa252561d2212a7a1f\u0026uparams=e,mid,trid,gen,nbs,uipk,platform,deadline,oi,os,og\u0026cdnid=88805\u0026bvc=vod\u0026nettype=0\u0026bw=105933\u0026lrs=42\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "base_url": "https://cn-hbyc-ct-01-05.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100022.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026mid=38331014\u0026trid=0000e20dd754d5964994878fd44815ac690u\u0026gen=playurlv3\u0026nbs=1\u0026uipk=5\u0026platform=pc\u0026deadline=1768921888\u0026oi=605423425\u0026os=bcache\u0026og=cos\u0026upsig=0b2259ac082418fa252561d2212a7a1f\u0026uparams=e,mid,trid,gen,nbs,uipk,platform,deadline,oi,os,og\u0026cdnid=88805\u0026bvc=vod\u0026nettype=0\u0026bw=105933\u0026lrs=42\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026buvid=\u0026build=0\u0026dl=0\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100022.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=cosbv\u0026og=cos\u0026trid=e20dd754d5964994878fd44815ac690u\u0026nbs=1\u0026mid=38331014\u0026oi=605423425\u0026uipk=5\u0026platform=pc\u0026deadline=1768921888\u0026gen=playurlv3\u0026upsig=b520fb3213cc68b776d6c80ad6c725ae\u0026uparams=e,os,og,trid,nbs,mid,oi,uipk,platform,deadline,gen\u0026bvc=vod\u0026nettype=0\u0026bw=105933\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100022.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026trid=e20dd754d5964994878fd44815ac690u\u0026platform=pc\u0026deadline=1768921888\u0026oi=605423425\u0026gen=playurlv3\u0026os=cosbv\u0026og=cos\u0026nbs=1\u0026uipk=5\u0026mid=38331014\u0026upsig=45869a9e7b2887d4a2db7891498543ed\u0026uparams=e,trid,platform,deadline,oi,gen,os,og,nbs,uipk,mid\u0026bvc=vod\u0026nettype=0\u0026bw=105933\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100022.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=cosbv\u0026og=cos\u0026trid=e20dd754d5964994878fd44815ac690u\u0026nbs=1\u0026mid=38331014\u0026oi=605423425\u0026uipk=5\u0026platform=pc\u0026deadline=1768921888\u0026gen=playurlv3\u0026upsig=b520fb3213cc68b776d6c80ad6c725ae\u0026uparams=e,os,og,trid,nbs,mid,oi,uipk,platform,deadline,gen\u0026bvc=vod\u0026nettype=0\u0026bw=105933\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026orderid=1,3", + "https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/40/58/35306865840/35306865840-1-100022.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026trid=e20dd754d5964994878fd44815ac690u\u0026platform=pc\u0026deadline=1768921888\u0026oi=605423425\u0026gen=playurlv3\u0026os=cosbv\u0026og=cos\u0026nbs=1\u0026uipk=5\u0026mid=38331014\u0026upsig=45869a9e7b2887d4a2db7891498543ed\u0026uparams=e,trid,platform,deadline,oi,gen,os,og,nbs,uipk,mid\u0026bvc=vod\u0026nettype=0\u0026bw=105933\u0026buvid=\u0026build=0\u0026dl=0\u0026f=u_0_0\u0026qn_dyeid=bd71451926ffa1a0002987df696f7f00\u0026agrr=0\u0026orderid=2,3" + ], + "bandwidth": 105804, + "mimeType": "video/mp4", + "mime_type": "video/mp4", + "codecs": "av01.0.00M.10.0.110.01.01.01.0", + "width": 640, + "height": 360, + "frameRate": "30.000", + "frame_rate": "30.000", + "sar": "1:1", + "startWithSap": 1, + "start_with_sap": 1, + "SegmentBase": { + "Initialization": "0-1010", + "indexRange": "1011-1462" + }, + "segment_base": { + "initialization": "0-1010", + "index_range": "1011-1462" + }, + "codecid": 13 + } + ], + "audio": [ + { + "id": 30216, + "baseUrl": "https://upos-sz-mirrorzos.bilivideo.com/neoxcode/bb/9w/_000031h2ibmcia0ym2o1hkbfu8e9wbb-1-30216.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026mid=38331014\u0026nbs=1\u0026deadline=1768921888\u0026os=zosbv\u0026og=hw\u0026trid=9543b281ee9c4f23b7eb20e6520c75bN\u0026uipk=5\u0026oi=605423425\u0026gen=playurlv3\u0026upsig=61c3da9028e753debb845ff14bfdfc5a\u0026uparams=e,platform,mid,nbs,deadline,os,og,trid,uipk,oi,gen\u0026bvc=vod\u0026nettype=0\u0026bw=65723\u0026f=N_0_0\u0026dl=0\u0026iptv=\u0026agrr=0\u0026orderid=0,3", + "base_url": "https://upos-sz-mirrorzos.bilivideo.com/neoxcode/bb/9w/_000031h2ibmcia0ym2o1hkbfu8e9wbb-1-30216.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026mid=38331014\u0026nbs=1\u0026deadline=1768921888\u0026os=zosbv\u0026og=hw\u0026trid=9543b281ee9c4f23b7eb20e6520c75bN\u0026uipk=5\u0026oi=605423425\u0026gen=playurlv3\u0026upsig=61c3da9028e753debb845ff14bfdfc5a\u0026uparams=e,platform,mid,nbs,deadline,os,og,trid,uipk,oi,gen\u0026bvc=vod\u0026nettype=0\u0026bw=65723\u0026f=N_0_0\u0026dl=0\u0026iptv=\u0026agrr=0\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirrorzos.bilivideo.com/neoxcode/bb/9w/_000031h2ibmcia0ym2o1hkbfu8e9wbb-1-30216.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026gen=playurlv3\u0026oi=605423425\u0026platform=pc\u0026nbs=1\u0026os=zosbv\u0026og=hw\u0026trid=9543b281ee9c4f23b7eb20e6520c75bN\u0026mid=38331014\u0026uipk=5\u0026deadline=1768921888\u0026upsig=8ec954270bab827008a6567cfd4aa73a\u0026uparams=e,gen,oi,platform,nbs,os,og,trid,mid,uipk,deadline\u0026bvc=vod\u0026nettype=0\u0026bw=65723\u0026dl=0\u0026iptv=\u0026agrr=0\u0026f=N_0_0\u0026orderid=1,3", + "https://upos-sz-mirror14b.bilivideo.com/neoxcode/bb/9w/_000031h2ibmcia0ym2o1hkbfu8e9wbb-1-30216.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=14bbv\u0026oi=605423425\u0026platform=pc\u0026trid=9543b281ee9c4f23b7eb20e6520c75bN\u0026uipk=5\u0026deadline=1768921888\u0026gen=playurlv3\u0026og=hw\u0026mid=38331014\u0026nbs=1\u0026upsig=c79070c6fa0d721fc75836ec64a18995\u0026uparams=e,os,oi,platform,trid,uipk,deadline,gen,og,mid,nbs\u0026bvc=vod\u0026nettype=0\u0026bw=65723\u0026agrr=0\u0026f=N_0_0\u0026dl=0\u0026iptv=\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirrorzos.bilivideo.com/neoxcode/bb/9w/_000031h2ibmcia0ym2o1hkbfu8e9wbb-1-30216.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026gen=playurlv3\u0026oi=605423425\u0026platform=pc\u0026nbs=1\u0026os=zosbv\u0026og=hw\u0026trid=9543b281ee9c4f23b7eb20e6520c75bN\u0026mid=38331014\u0026uipk=5\u0026deadline=1768921888\u0026upsig=8ec954270bab827008a6567cfd4aa73a\u0026uparams=e,gen,oi,platform,nbs,os,og,trid,mid,uipk,deadline\u0026bvc=vod\u0026nettype=0\u0026bw=65723\u0026dl=0\u0026iptv=\u0026agrr=0\u0026f=N_0_0\u0026orderid=1,3", + "https://upos-sz-mirror14b.bilivideo.com/neoxcode/bb/9w/_000031h2ibmcia0ym2o1hkbfu8e9wbb-1-30216.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=14bbv\u0026oi=605423425\u0026platform=pc\u0026trid=9543b281ee9c4f23b7eb20e6520c75bN\u0026uipk=5\u0026deadline=1768921888\u0026gen=playurlv3\u0026og=hw\u0026mid=38331014\u0026nbs=1\u0026upsig=c79070c6fa0d721fc75836ec64a18995\u0026uparams=e,os,oi,platform,trid,uipk,deadline,gen,og,mid,nbs\u0026bvc=vod\u0026nettype=0\u0026bw=65723\u0026agrr=0\u0026f=N_0_0\u0026dl=0\u0026iptv=\u0026orderid=2,3" + ], + "bandwidth": 65625, + "mimeType": "audio/mp4", + "mime_type": "audio/mp4", + "codecs": "mp4a.40.2", + "width": 0, + "height": 0, + "frameRate": "", + "frame_rate": "", + "sar": "", + "startWithSap": 0, + "start_with_sap": 0, + "SegmentBase": { + "Initialization": "0-821", + "indexRange": "822-1273" + }, + "segment_base": { + "initialization": "0-821", + "index_range": "822-1273" + }, + "codecid": 0 + }, + { + "id": 30232, + "baseUrl": "https://upos-sz-estghw.bilivideo.com/neoxcode/bb/9w/_000031h2ibmcia0ym2o1hkbfu8e9wbb-1-30232.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026nbs=1\u0026deadline=1768921888\u0026oi=605423425\u0026platform=pc\u0026trid=9543b281ee9c4f23b7eb20e6520c75bN\u0026mid=38331014\u0026gen=playurlv3\u0026os=estghw\u0026uipk=5\u0026og=hw\u0026upsig=211824fb8890123667f7aa37e286efea\u0026uparams=e,nbs,deadline,oi,platform,trid,mid,gen,os,uipk,og\u0026bvc=vod\u0026nettype=0\u0026bw=84945\u0026iptv=\u0026agrr=0\u0026f=N_0_0\u0026dl=0\u0026orderid=0,3", + "base_url": "https://upos-sz-estghw.bilivideo.com/neoxcode/bb/9w/_000031h2ibmcia0ym2o1hkbfu8e9wbb-1-30232.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026nbs=1\u0026deadline=1768921888\u0026oi=605423425\u0026platform=pc\u0026trid=9543b281ee9c4f23b7eb20e6520c75bN\u0026mid=38331014\u0026gen=playurlv3\u0026os=estghw\u0026uipk=5\u0026og=hw\u0026upsig=211824fb8890123667f7aa37e286efea\u0026uparams=e,nbs,deadline,oi,platform,trid,mid,gen,os,uipk,og\u0026bvc=vod\u0026nettype=0\u0026bw=84945\u0026iptv=\u0026agrr=0\u0026f=N_0_0\u0026dl=0\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirror08c.bilivideo.com/neoxcode/bb/9w/_000031h2ibmcia0ym2o1hkbfu8e9wbb-1-30232.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=08cbv\u0026nbs=1\u0026gen=playurlv3\u0026og=hw\u0026oi=605423425\u0026platform=pc\u0026trid=9543b281ee9c4f23b7eb20e6520c75bN\u0026mid=38331014\u0026uipk=5\u0026deadline=1768921888\u0026upsig=647abf350d884239d06e172a7125667d\u0026uparams=e,os,nbs,gen,og,oi,platform,trid,mid,uipk,deadline\u0026bvc=vod\u0026nettype=0\u0026bw=84945\u0026f=N_0_0\u0026dl=0\u0026iptv=\u0026agrr=0\u0026orderid=1,3", + "https://upos-sz-mirrorhwb.bilivideo.com/neoxcode/bb/9w/_000031h2ibmcia0ym2o1hkbfu8e9wbb-1-30232.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026trid=9543b281ee9c4f23b7eb20e6520c75bN\u0026mid=38331014\u0026nbs=1\u0026uipk=5\u0026og=hw\u0026oi=605423425\u0026deadline=1768921888\u0026gen=playurlv3\u0026os=hwbbv\u0026upsig=b34a257648941adb939b72f9e4d62eaf\u0026uparams=e,platform,trid,mid,nbs,uipk,og,oi,deadline,gen,os\u0026bvc=vod\u0026nettype=0\u0026bw=84945\u0026iptv=\u0026agrr=0\u0026f=N_0_0\u0026dl=0\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirror08c.bilivideo.com/neoxcode/bb/9w/_000031h2ibmcia0ym2o1hkbfu8e9wbb-1-30232.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026os=08cbv\u0026nbs=1\u0026gen=playurlv3\u0026og=hw\u0026oi=605423425\u0026platform=pc\u0026trid=9543b281ee9c4f23b7eb20e6520c75bN\u0026mid=38331014\u0026uipk=5\u0026deadline=1768921888\u0026upsig=647abf350d884239d06e172a7125667d\u0026uparams=e,os,nbs,gen,og,oi,platform,trid,mid,uipk,deadline\u0026bvc=vod\u0026nettype=0\u0026bw=84945\u0026f=N_0_0\u0026dl=0\u0026iptv=\u0026agrr=0\u0026orderid=1,3", + "https://upos-sz-mirrorhwb.bilivideo.com/neoxcode/bb/9w/_000031h2ibmcia0ym2o1hkbfu8e9wbb-1-30232.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026platform=pc\u0026trid=9543b281ee9c4f23b7eb20e6520c75bN\u0026mid=38331014\u0026nbs=1\u0026uipk=5\u0026og=hw\u0026oi=605423425\u0026deadline=1768921888\u0026gen=playurlv3\u0026os=hwbbv\u0026upsig=b34a257648941adb939b72f9e4d62eaf\u0026uparams=e,platform,trid,mid,nbs,uipk,og,oi,deadline,gen,os\u0026bvc=vod\u0026nettype=0\u0026bw=84945\u0026iptv=\u0026agrr=0\u0026f=N_0_0\u0026dl=0\u0026orderid=2,3" + ], + "bandwidth": 84835, + "mimeType": "audio/mp4", + "mime_type": "audio/mp4", + "codecs": "mp4a.40.2", + "width": 0, + "height": 0, + "frameRate": "", + "frame_rate": "", + "sar": "", + "startWithSap": 0, + "start_with_sap": 0, + "SegmentBase": { + "Initialization": "0-821", + "indexRange": "822-1273" + }, + "segment_base": { + "initialization": "0-821", + "index_range": "822-1273" + }, + "codecid": 0 + }, + { + "id": 30280, + "baseUrl": "https://upos-sz-estgcos.bilivideo.com/neoxcode/bb/9w/_000031h2ibmcia0ym2o1hkbfu8e9wbb-1-30280.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026trid=9543b281ee9c4f23b7eb20e6520c75bN\u0026uipk=5\u0026os=estgcos\u0026platform=pc\u0026mid=38331014\u0026nbs=1\u0026deadline=1768921888\u0026gen=playurlv3\u0026og=cos\u0026oi=605423425\u0026upsig=cc453cbbfbd3ac754f34bca5ee177365\u0026uparams=e,trid,uipk,os,platform,mid,nbs,deadline,gen,og,oi\u0026bvc=vod\u0026nettype=0\u0026bw=137816\u0026dl=0\u0026iptv=\u0026agrr=0\u0026f=N_0_0\u0026orderid=0,3", + "base_url": "https://upos-sz-estgcos.bilivideo.com/neoxcode/bb/9w/_000031h2ibmcia0ym2o1hkbfu8e9wbb-1-30280.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026trid=9543b281ee9c4f23b7eb20e6520c75bN\u0026uipk=5\u0026os=estgcos\u0026platform=pc\u0026mid=38331014\u0026nbs=1\u0026deadline=1768921888\u0026gen=playurlv3\u0026og=cos\u0026oi=605423425\u0026upsig=cc453cbbfbd3ac754f34bca5ee177365\u0026uparams=e,trid,uipk,os,platform,mid,nbs,deadline,gen,og,oi\u0026bvc=vod\u0026nettype=0\u0026bw=137816\u0026dl=0\u0026iptv=\u0026agrr=0\u0026f=N_0_0\u0026orderid=0,3", + "backupUrl": [ + "https://upos-sz-mirrorcos.bilivideo.com/neoxcode/bb/9w/_000031h2ibmcia0ym2o1hkbfu8e9wbb-1-30280.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026nbs=1\u0026uipk=5\u0026deadline=1768921888\u0026gen=playurlv3\u0026og=cos\u0026trid=9543b281ee9c4f23b7eb20e6520c75bN\u0026mid=38331014\u0026os=cosbv\u0026oi=605423425\u0026platform=pc\u0026upsig=29dedc9eeb4ce9ac312e522b938191db\u0026uparams=e,nbs,uipk,deadline,gen,og,trid,mid,os,oi,platform\u0026bvc=vod\u0026nettype=0\u0026bw=137816\u0026iptv=\u0026agrr=0\u0026f=N_0_0\u0026dl=0\u0026orderid=1,3", + "https://upos-sz-mirrorcosb.bilivideo.com/neoxcode/bb/9w/_000031h2ibmcia0ym2o1hkbfu8e9wbb-1-30280.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026mid=38331014\u0026gen=playurlv3\u0026os=cosbbv\u0026nbs=1\u0026uipk=5\u0026deadline=1768921888\u0026oi=605423425\u0026platform=pc\u0026og=cos\u0026trid=9543b281ee9c4f23b7eb20e6520c75bN\u0026upsig=18818c6927fdab510b78de98435c4718\u0026uparams=e,mid,gen,os,nbs,uipk,deadline,oi,platform,og,trid\u0026bvc=vod\u0026nettype=0\u0026bw=137816\u0026iptv=\u0026agrr=0\u0026f=N_0_0\u0026dl=0\u0026orderid=2,3" + ], + "backup_url": [ + "https://upos-sz-mirrorcos.bilivideo.com/neoxcode/bb/9w/_000031h2ibmcia0ym2o1hkbfu8e9wbb-1-30280.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026nbs=1\u0026uipk=5\u0026deadline=1768921888\u0026gen=playurlv3\u0026og=cos\u0026trid=9543b281ee9c4f23b7eb20e6520c75bN\u0026mid=38331014\u0026os=cosbv\u0026oi=605423425\u0026platform=pc\u0026upsig=29dedc9eeb4ce9ac312e522b938191db\u0026uparams=e,nbs,uipk,deadline,gen,og,trid,mid,os,oi,platform\u0026bvc=vod\u0026nettype=0\u0026bw=137816\u0026iptv=\u0026agrr=0\u0026f=N_0_0\u0026dl=0\u0026orderid=1,3", + "https://upos-sz-mirrorcosb.bilivideo.com/neoxcode/bb/9w/_000031h2ibmcia0ym2o1hkbfu8e9wbb-1-30280.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=\u0026mid=38331014\u0026gen=playurlv3\u0026os=cosbbv\u0026nbs=1\u0026uipk=5\u0026deadline=1768921888\u0026oi=605423425\u0026platform=pc\u0026og=cos\u0026trid=9543b281ee9c4f23b7eb20e6520c75bN\u0026upsig=18818c6927fdab510b78de98435c4718\u0026uparams=e,mid,gen,os,nbs,uipk,deadline,oi,platform,og,trid\u0026bvc=vod\u0026nettype=0\u0026bw=137816\u0026iptv=\u0026agrr=0\u0026f=N_0_0\u0026dl=0\u0026orderid=2,3" + ], + "bandwidth": 137674, + "mimeType": "audio/mp4", + "mime_type": "audio/mp4", + "codecs": "mp4a.40.2", + "width": 0, + "height": 0, + "frameRate": "", + "frame_rate": "", + "sar": "", + "startWithSap": 0, + "start_with_sap": 0, + "SegmentBase": { + "Initialization": "0-821", + "indexRange": "822-1273" + }, + "segment_base": { + "initialization": "0-821", + "index_range": "822-1273" + }, + "codecid": 0 + } + ], + "dolby": { + "type": 0, + "audio": null + }, + "flac": null + }, + "support_formats": [ + { + "quality": 112, + "format": "hdflv2", + "new_description": "1080P 高码率", + "display_desc": "1080P", + "superscript": "高码率", + "codecs": [ + "av01.0.00M.10.0.110.01.01.01.0", + "avc1.640033", + "hev1.1.6.L150.90" + ], + "can_watch_qn_reason": 3, + "limit_watch_reason": 0, + "report": { + "EXT_VIP_REPORT_PARAMS": "" + } + }, + { + "quality": 80, + "format": "flv", + "new_description": "1080P 高清", + "display_desc": "1080P", + "superscript": "", + "codecs": [ + "av01.0.00M.10.0.110.01.01.01.0", + "avc1.640033", + "hev1.1.6.L150.90" + ], + "can_watch_qn_reason": 0, + "limit_watch_reason": 0, + "report": {} + }, + { + "quality": 64, + "format": "flv720", + "new_description": "720P 准高清", + "display_desc": "720P", + "superscript": "", + "codecs": [ + "av01.0.00M.10.0.110.01.01.01.0", + "avc1.640033", + "hev1.1.6.L120.90" + ], + "can_watch_qn_reason": 0, + "limit_watch_reason": 0, + "report": {} + }, + { + "quality": 32, + "format": "flv480", + "new_description": "480P 标清", + "display_desc": "480P", + "superscript": "", + "codecs": [ + "av01.0.00M.10.0.110.01.01.01.0", + "avc1.640033", + "hev1.1.6.L120.90" + ], + "can_watch_qn_reason": 0, + "limit_watch_reason": 0, + "report": {} + }, + { + "quality": 16, + "format": "mp4", + "new_description": "360P 流畅", + "display_desc": "360P", + "superscript": "", + "codecs": [ + "av01.0.00M.10.0.110.01.01.01.0", + "avc1.640033", + "hev1.1.6.L120.90" + ], + "can_watch_qn_reason": 0, + "limit_watch_reason": 0, + "report": {} + } + ], + "high_format": null, + "last_play_time": 5000, + "last_play_cid": 35306865840, + "view_info": null, + "play_conf": { + "is_new_description": false + }, + "cur_language": "en", + "language": { + "support": true, + "items": [ + { + "lang": "en", + "title": "English", + "subtitle_lang": "", + "video_detext": false, + "video_mouth_shape_change": false, + "production_type": 2 + }, + { + "lang": "ja", + "title": "日本語", + "subtitle_lang": "", + "video_detext": false, + "video_mouth_shape_change": false, + "production_type": 2 + } + ], + "open_toast": "原声翻译开启中,请稍候", + "close_toast": "原声翻译关闭中,请稍候", + "default_title": "翻译", + "list_title": "AI原声翻译(Beta)", + "bubble": { + "title": "试试AI原声翻译", + "type": 2 + } + }, + "cur_production_type": 2, + "auto_qn_resp": { + "dyeid": "bd71451926ffa1a0002987df696f7f00" + } + } +} +``` + +
+ +## 视频取流说明 + +关于拉流: + +1. MP4 / ~~FLV~~ 格式仅需拉视频流,DASH 格式需同时拉视频与伴音流 +2. 如 DASH 格式需要杜比或无损的伴音,需要取对应`dolby`或`flac`字段中的流 +3. **注意 Unicode 转义符** + +~~关于分段:~~ + +~~FLV 格式可能产生分段情况,将`$.data.durl[1-n].url`或`$.data.durl[1-n].backup_url[0]`中的内容作为 URL 进行 GET 请求进行分段播放,如需下载需要合并~~(FLV 格式已下线,不会存在分段现象) + +关于鉴权: + +1. WEB 端取流需要验证防盗链,即`referer`为 `.bilibili.com`域名下且 UA 不能为空 +2. APP 端也需要验证防盗链,即 UA 需要含有`Mozilla/5.0 BiliDroid/*.*.* (bbcallen@gmail.com)`(*为版本) +3. 如`referer`或 UA 错误的情况会被判定为盗链,返回`403 Forbidden`故无法取流 +4. 若传`platform=html5`参数取流,则不会进行防盗链验证,即可通过 HTML 标签`