XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/bilibili-API-collect

更新 bvid 算法 (#857)

* 更新 bvid 算法 * 更新 bvid 算法相关说明

6430bff
LaMerChiang <catlair@qq.com>
提交于

代码差异

1 个文件 +187 -14
Modified docs/misc/bvid_desc.md +187 -14
@@ -19,14 +19,183 @@
19 19
20 20 ### avid发号方式的变化
21 21
22 从 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
22 从 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
23 23
24 24 ~~暗示B站东方要完?泪目~~
25 25
26 26 ## 算法概述
27 27
28 28 ~~算法以及程序主要参考[知乎@mcfx的回答](https://www.zhihu.com/question/381784377/answer/1099438784)~~
29 实际上该算法并不完整,新的算法参考自[【揭秘】av号转bv号的过程](https://www.bilibili.com/video/BV1N741127Tj)
29 ~~实际上该算法并不完整,新的算法参考自[【揭秘】av号转bv号的过程](https://www.bilibili.com/video/BV1N741127Tj)~~
30 实际上上面的算法依然不完整,新的算法参考自 <https://github.com/SocialSisterYi/bilibili-API-collect/issues/740>~~来自 B 站某个 JS 文件?~~
31
32 ### av->bv算法
33
34 **说明**
35
36 1. 目前的 BV 格式为 BV1XXXXXXXXX,以 BV1 开头,后面包含 9 位有效数据。
37 2. AV 最大值为 2⁵¹。
38
39 **算法**
40
41 - 定义一个包含初始值为 `['B', 'V', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0']` 的长度为 12 的数组`bytes`,用于存储转换后的字符。
42 - 定义变量 `bv_idx` 并初始化为数组 `bytes` 的最后一个索引。
43 - 将输入的"aid"与 avid 最大值(2⁵¹)进行按位或运算,并与常量 `XOR_CODE`(23442827791579)进行异或运算,得到变量 `tmp`。
44 - 当 `tmp` 大于0时,执行以下操作:
45 - 将 `tmp` 除以 58 的余数作为索引,从 `FcwAPNKTMug3GV5Lj7EJnHpWsx4tb8haYeviqBz6rkCy12mUSDQX9RdoZf` 码表中取出对应的字符,并将其赋值给 `bytes[bv_idx]`。
46 - 将 `tmp` 与 58 求模赋值给 `tmp`。
47 - 将 `bv_idx` 减1。
48 - 将 `bytes` 数组中索引为 3 和 9 的元素进行交换。
49 - 将 `bytes` 数组中索引为 4 和 7 的元素进行交换。
50 - 将 `bytes` 数组转换为字符串,并返回结果。
51
52 ### bv->av算法
53
54 - 将 `bvid` 中索引为 3 和 9 的字符进行交换。
55 - 将 `bvid` 中索引为 4 和 7 的字符进行交换。
56 - 删除 `bvid` 前3个字符(固定为 BV1)。
57 - 定义变量 `tmp` 并初始化为 0。
58 - 遍历 `bvid` 的每个字符,执行以下操作:
59 - 获取当前字符在 `FcwAPNKTMug3GV5Lj7EJnHpWsx4tb8haYeviqBz6rkCy12mUSDQX9RdoZf` 码表中的索引,并将其赋值给变量 `idx`。
60 - 将 `tmp` 乘以常量 58,并加上 `idx`。
61 - 将 `tmp` 与常量 2⁵¹ - 1 进行按位与运算,并与常量 `XOR_CODE`(23442827791579) 进行异或运算,得到最终结果。
62
63 ## 编程实现
64
65 ### JavaScript/TypeScript
66
67 <CodeGroup>
68 <CodeGroupItem title="JavaScript">
69
70 ```javascript
71 const XOR_CODE = 23442827791579n;
72 const MASK_CODE = 2251799813685247n;
73 const MAX_AID = 1n << 51n;
74 const BASE = 58n;
75
76 const data = 'FcwAPNKTMug3GV5Lj7EJnHpWsx4tb8haYeviqBz6rkCy12mUSDQX9RdoZf';
77
78 function av2bv(aid) {
79 const bytes = ['B', 'V', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0'];
80 let bv_idx = bytes.length - 1;
81 let tmp = (MAX_AID | BigInt(aid)) ^ XOR_CODE;
82 while (tmp > 0) {
83 bytes[bv_idx] = data[Number(tmp % BigInt(BASE))];
84 tmp = tmp / BASE;
85 bv_idx -= 1;
86 }
87 [bytes[3], bytes[9]] = [bytes[9], bytes[3]];
88 [bytes[4], bytes[7]] = [bytes[7], bytes[4]];
89 return bytes.join('');
90 }
91
92 function bv2av(bvid) {
93 const bvidArr = Array.from(bvid);
94 [bvidArr[3], bvidArr[9]] = [bvidArr[9], bvidArr[3]];
95 [bvidArr[4], bvidArr[7]] = [bvidArr[7], bvidArr[4]];
96 bvidArr.splice(0, 3);
97 let tmp = 0n;
98 for (let i = 0; i < bvidArr.length; i++) {
99 const idx = data.indexOf(bvidArr[i]);
100 tmp = tmp * BASE + BigInt(idx);
101 }
102 return Number((tmp & MASK_CODE) ^ XOR_CODE);
103 }
104
105 console.log(av2bv(111298867365120));
106 console.log(bv2av('BV1L9Uoa9EUx'));
107 ```
108
109 </CodeGroupItem>
110
111 <CodeGroupItem title="TypeScript">
112
113 ```typescript
114 const XOR_CODE = 23442827791579n;
115 const MASK_CODE = 2251799813685247n;
116 const MAX_AID = 1n << 51n;
117 const BASE = 58n;
118
119 const data = 'FcwAPNKTMug3GV5Lj7EJnHpWsx4tb8haYeviqBz6rkCy12mUSDQX9RdoZf';
120
121 function av2bv(aid: number) {
122 const bytes = ['B', 'V', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0'];
123 let bv_idx = bytes.length - 1;
124 let tmp = (MAX_AID | BigInt(aid)) ^ XOR_CODE;
125 while (tmp > 0) {
126 bytes[bv_idx] = data[Number(tmp % BigInt(BASE))];
127 tmp = tmp / BASE;
128 bv_idx -= 1;
129 }
130 [bytes[3], bytes[9]] = [bytes[9], bytes[3]];
131 [bytes[4], bytes[7]] = [bytes[7], bytes[4]];
132 return bytes.join('') as `BV1${string}`;
133 }
134
135 function bv2av(bvid: `BV1${string}`) {
136 const bvidArr = Array.from<string>(bvid);
137 [bvidArr[3], bvidArr[9]] = [bvidArr[9], bvidArr[3]];
138 [bvidArr[4], bvidArr[7]] = [bvidArr[7], bvidArr[4]];
139 bvidArr.splice(0, 3);
140 const tmp = bvidArr.reduce((pre, bvidChar) => pre * BASE + BigInt(data.indexOf(bvidChar)), 0n);
141 return Number((tmp & MASK_CODE) ^ XOR_CODE);
142 }
143
144 console.log(av2bv(111298867365120));
145 console.log(bv2av('BV1L9Uoa9EUx'));
146 ```
147 </CodeGroupItem>
148 </CodeGroup>
149
150 ### Python
151
152 来自:<https://github.com/SocialSisterYi/bilibili-API-collect/issues/847#issuecomment-1807020675>
153
154 ```python
155 XOR_CODE = 23442827791579
156 MASK_CODE = 2251799813685247
157 MAX_AID = 1 << 51
158
159 data = [b'F', b'c', b'w', b'A', b'P', b'N', b'K', b'T', b'M', b'u', b'g', b'3', b'G', b'V', b'5', b'L', b'j', b'7', b'E', b'J', b'n', b'H', b'p', b'W', b's', b'x', b'4', b't', b'b', b'8', b'h', b'a', b'Y', b'e', b'v', b'i', b'q', b'B', b'z', b'6', b'r', b'k', b'C', b'y', b'1', b'2', b'm', b'U', b'S', b'D', b'Q', b'X', b'9', b'R', b'd', b'o', b'Z', b'f']
160
161 BASE = 58
162 BV_LEN = 12
163 PREFIX = "BV1"
164
165 def av2bv(aid):
166 bytes = [b'B', b'V', b'1', b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'0']
167 bv_idx = BV_LEN - 1
168 tmp = (MAX_AID | aid) ^ XOR_CODE
169 while int(tmp) != 0:
170 bytes[bv_idx] = data[int(tmp % BASE)]
171 tmp /= BASE
172 bv_idx -= 1
173 bytes[3], bytes[9] = bytes[9], bytes[3]
174 bytes[4], bytes[7] = bytes[7], bytes[4]
175 return "".join([i.decode() for i in bytes])
176
177 def bv2av(bvid: str):
178 bvid = list(bvid)
179 bvid[3], bvid[9] = bvid[9], bvid[3]
180 bvid[4], bvid[7] = bvid[7], bvid[4]
181 bvid = bvid[3:]
182 tmp = 0
183 for i in bvid:
184 idx = data.index(i.encode())
185 tmp = tmp * BASE + idx
186 return (tmp & MASK_CODE) ^ XOR_CODE
187
188 print(av2bv(111298867365120))
189 print(bv2av("BV1L9Uoa9EUx"))
190 ```
191
192 ### Rust
193
194 参考 <https://github.com/Colerar/abv/blob/main/src/lib.rs>
195
196 ## 老版算法存档
197
198 算法参考自[【揭秘】av号转bv号的过程](https://www.bilibili.com/video/BV1N741127Tj)
30 199
31 200 ### av->bv算法
32 201
@@ -60,24 +229,24 @@
60 229 > 5 -> 4
61 230 >
62 231 > 6 -> 0
63 >
232 >
64 233 > 7 -> 7
65 234 >
66 235 > 8 -> 3
67 236 >
68 237 > 9 -> 5
69 238
70
71 239 ### bv->av算法
72 240
73 241 为以上算法的逆运算
74 242
75 ## 编程实现
243 ### 编程实现
76 244
77 245 使用 [Python](#Python) [C](#C) [TypeScript](#TypeScript) [Java](#Java) [Kotlin](#Kotlin) [Golang](#Golang) [Rust](#Rust) 等语言作为示例,欢迎社区提交更多例程
78 246
79 247 注: 新算法只提供了 [Python](#Python) 和 [Rust](#Rust) 版本
80 ### Python
248
249 #### Python
81 250
82 251 ```python
83 252 XOR = 177451812
@@ -121,8 +290,7 @@ if __name__ == "__main__":
121 290 main()
122 291 ```
123 292
124
125 ### C
293 #### C
126 294
127 295 ```c
128 296 #include <stdio.h>
@@ -175,7 +343,7 @@ BV17x411w7KC
175 343 170001
176 344 ```
177 345
178 ### TypeScript
346 #### TypeScript
179 347
180 348 感谢[#417](https://github.com/SocialSisterYi/bilibili-API-collect/issues/417#issuecomment-1186475063)提供
181 349
@@ -187,7 +355,7 @@ export default class BvCode {
187 355 private XOR = 177451812; // 固定异或值
188 356 private ADD = 8728348608; // 固定加法值
189 357 constructor() {
190 // 初始化反查码表
358 // 初始化反查码表
191 359 const len = this.TABEL.length;
192 360 for (let i = 0; i < len; i++) {
193 361 this.TR[this.TABEL[i]] = i;
@@ -223,7 +391,7 @@ BV17x411w7KC
223 391 170001
224 392 ```
225 393
226 ### Java
394 #### Java
227 395
228 396 ```java
229 397 /**
@@ -264,7 +432,8 @@ public class Util {
264 432 }
265 433 ```
266 434
267 ### Kotlin
435 #### Kotlin
436
268 437 ```kotlin
269 438 /**
270 439 * 此程序非完全原创,改编自GH站内某大佬的Java程序,修改了部分代码,且转换为Kotlin
@@ -331,7 +500,8 @@ object VideoUtils {
331 500 }
332 501 ```
333 502
334 ### Golang
503 #### Golang
504
335 505 ```go
336 506 package main
337 507
@@ -380,8 +550,11 @@ func main() {
380 550 BV17x411w7KC
381 551 170001
382 552 ```
383 ### Rust
553
554 #### Rust
555
384 556 crate: https://github.com/stackinspector/bvid
557
385 558 ```rust
386 559 // Copyright (c) 2023 stackinspector. MIT license.
387 560