BV与AV号的算法流出?有点恐怖。

最近B站的最大改动就是将AV号改为了BV号,BV号在AV号的基础上更加难记,而且BV号使用了52进制,里面包括数字+小写字母+大写字母;
在常人看起来AV号和BV号之间并没有什么联系,而BiliBili其实只是添加了一个可以当做AV号的BV号,也就是说现在AV号还是可以用的,但你点进去的视频默认导航是BV号,所以很多人一时不知道怎么看到视频的AV号,一般的在BiliBili的官方Api接口中提供BV号便可解析出来视频的相关信息,里面也就包括了AV号和BV号,在这种解析方式下,很多规则是无法使用的,比如断网之后无法连接api接口,就会导致解析不出来,以及api接口的延迟等。
那么在知乎上就有位大佬,mcfx,他通过对大量av号和bv号的分析,以及对进制的理解,得到了Python版的算法;放图:

那么这篇代码因为使用的是python的代码,在Up的能力下无法得到解析,首先就是计算溢出的问题,其次就是对python代码过于生疏,所以Up在将其转换到一半的时候就放弃了,还是API接口真香~
那么今天的情况就比较好转,在其他的大佬带领下,很多关于BV和AV号的运算分析视频也相继出来了,那么易语言版的源码也是出来了,在我们的群内,Liv也是将C++版的写出来了;
那么根据源码大概是这个样子的:
原版{

.版本 2
.程序集 窗口程序集_启动窗口
.程序集变量 s, 整数型, , "10"
.程序集变量 TR, 文本型, , "58"
.子程序 __启动窗口_创建完毕
.局部变量 index, 整数型
s = { 10, 9, 2, 7, 3, 5 }
.计次循环首 (58, index)
TR [index] = 取文本中间 (“fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF”, index, 1)
.计次循环尾 ()

.版本 2
.支持库 eCalc
.子程序 AvToBv, 文本型
.参数 av, 长整数型
.局部变量 x, 大数
.局部变量 i, 大数
.局部变量 Bv, 文本型, , "10"
.局部变量 a58, 大数
.局部变量 index, 整数型
.局部变量 a, 大数
.局部变量 ret, 文本型
i.导入数字 (位异或 (av, 177451812))
x.导入文本 (“8728348608”)
x = x.加 (i)
a58.导入数字 (58)
Bv = { “1”, “”, “”, “4”, “”, “1”, “”, “7”, “”, “” }
.计次循环首 (6, index)
.如果 (index > 1)
i = a58
.计次循环首 (index - 2, )
i = i.乘 (a58)
.计次循环尾 ()
.否则
i.导入数字 (1)
.如果结束
Bv [s [index]] = TR [x.整除 (i).求余 (a58).导出整数 () + 1]
.计次循环尾 ()
ret = “BV”
index = 0
.计次循环首 (10, index)
ret = ret + Bv [index]
.计次循环尾 ()
返回 (ret)

.版本 2
.支持库 eCalc
.支持库 spec
.子程序 BvtoAv, 长整数型
.参数 BV号, 文本型
.局部变量 index, 整数型
.局部变量 av, 大数
.局部变量 a58, 大数
.局部变量 BV, 文本型, , "10"
.局部变量 index2, 整数型
.局部变量 i, 大数
.局部变量 i_, 大数
.计次循环首 (10, index)
BV [index] = 取文本中间 (BV号, index, 1)
.计次循环尾 ()
调试输出 (“BV:”, BV)
index = 0
a58.导入数字 (58)
.计次循环首 (6, index)
.如果 (index > 1)
i = a58
.计次循环首 (index - 2, )
i = i.乘 (a58)
.计次循环尾 ()
.否则
i.导入数字 (1)
.如果结束
.计次循环首 (58, index2)
.如果真 (TR [index2] = BV [s [index]])
i_.导入数字 (index2 - 1)
i = i.乘 (i_)
跳出循环 ()
.如果真结束
.计次循环尾 ()
av = av.加 (i)
调试输出 (AV号.导出长整数 ())
.计次循环尾 ()
i.导入文本 (“8728348608”)
返回 (位异或 (av.减 (i).导出长整数 (), 177451812))
}
那么这个代码和那篇的python代码是有很多不同的,Up也是有很多地方搞不懂,真让人头大;
UP主对照着代码流程自己写了一遍BV转AV的,用了中文的变量希望大家能看懂:
UP主版的{

.版本 2
.支持库 eCalc
.程序集 窗口程序集_窗口1
.程序集变量 table, 文本型, , "0"
.程序集变量 tr, 文本型, , "0"
.程序集变量 xor, 长整数型
.程序集变量 s, 整数型, , "10"
.程序集变量 add, 大数
.子程序 _窗口1_创建完毕
.局部变量 i, 整数型
' fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF
.计次循环首 (58, i)
加入成员 (table, 取文本中间 (“fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF”, i, 1))
.计次循环尾 ()
复制数组 (tr, table)
s = { 10, 9, 2, 7, 3, 5 }
xor = 177451812
add.导入文本 (“100618342136696320”)

.版本 2
.支持库 eCalc
.支持库 spec
.子程序 BVAV, 长整数型
.参数 BV号, 文本型
.局部变量 计次X, 整数型
.局部变量 计次X2, 整数型
.局部变量 BV, 文本型, , "10"
.局部变量 AV号, 大数
.局部变量 运算i, 大数
.局部变量 运算i2, 大数
.局部变量 临时处理大数, 大数
临时处理大数.导入数字 (58)
.如果真 (取文本左边 (BV号, 2) = “BV”)
BV号 = 取文本右边 (BV号, 取文本长度 (BV号) - 2)
.如果真结束
.计次循环首 (10, 计次X)
BV [计次X] = 取文本中间 (BV号, 计次X, 1)
.计次循环尾 ()
.计次循环首 (6, 计次X)
.判断开始 (计次X > 1)
运算i.导入数字 (58)
.计次循环首 (计次X - 2, )
运算i = 运算i.乘 (临时处理大数)
.计次循环尾 ()
.默认
运算i.导入数字 (1)
.判断结束
.计次循环首 (58, 计次X2)
.如果真 (tr [计次X2] = BV [s [计次X]])
运算i2.导入数字 (计次X2 - 1)
运算i = 运算i.乘 (运算i2)
调试输出 (运算i.导出长整数 (), 计次X2, 计次X)
跳出循环 ()
.如果真结束
.计次循环尾 ()
AV号 = AV号.加 (运算i)
.计次循环尾 ()
运算i.导入文本 (“8728348608”)
返回 (位异或 (AV号.减 (运算i).导出长整数 (), xor))
}
具体是哪点Up主没能搞懂,相信大家对照一下源码与Python的代码就知道了;
首先就是 tr 和 xor ,其次就是 add 彻底不见了;当然 s 也从 {11,10,3,8,4,6,2,9,5,7}
变为了:s = { 10, 9, 2, 7, 3, 5 }
讲了这么多,最后奉上下载地址吧。
原版的:https://www.lanzous.com/iam1qpe
UP主的:https://www.lanzous.com/iam1qqf