python进行B站av号和bv号的转换

为了保护稿件信息安全,容纳更多投稿,维护UP主的权益,自2020年3月23日起,AV号将全面升级为BV号。与纯数字的AV号不同,BV号是一段由数字和大小写字母组成的字符串,经过算法自动生成。未来将统一使用BV号作为稿件标识。

B站官方解释,BV号是通过算法自动生成的,那么BV号和之前的AV号之间有联系吗?或者说两者可以进行互推吗?

知乎上有大佬给出了解答,亲测有效。
快膜!

table='fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF'
tr={
    
    }
for i in range(58):
	tr[table[i]]=i
s=[11,10,3,8,4,6]
xor=177451812
add=8728348608

def dec(x):
	r=0
	for i in range(6):
		r+=tr[x[s[i]]]*58**i
	return (r-add)^xor

def enc(x):
	x=(x^xor)+add
	r=list('BV1  4 1 7  ')
	for i in range(6):
		r[s[i]]=table[x//58**i%58]
	return ''.join(r)

print(dec('BV1JK411p7pd'))
print(enc(498461045))

498461045
BV1JK411p7pd

具体思路如下:

互相转换脚本,如果算法没猜错,可以保证在 av 号 < 2 27 <2^{27} <227 也是正确的,同时在 < 2 30 <2^{30} <230时也是正确的。此代码以 WTFPL 开源。

UPD:之前的代码中,所有数位都被用到是乱凑的,实际上并不需要,目前只要低 6 位就足够了。(更大的 av 号需要 64 位整数存储,但是 b 站现在使用的应该还是 32 位整数,所以应该还要很久)

发现的方法:首先从各种渠道的信息来看,应该是 base58 编码的。设 x 是一个钦定的 av 号,查询 58 k + x , 5 8 2 k + x , 5 8 3 k + x , 5 8 4 + x ( k ∈ Z ) 。 58k+x,58^2k+x,58^3k+x,58^4+x(k\in Z)。 58k+x,582k+x,583k+x,584+x(kZ)这些 av 号对应的 bv 号,发现 bv 号的第 12、11、4、9、5 位分别会变化。所以猜测这些是 58 进制下的相应位。

但是直接 base58 是不行的,所以猜测异或了一个大数,并且 base58 的字符表可能打乱了。经过实验,bv 号最低位相同的数,av 号的奇偶性相同,这一定程度上印证了之前的猜想。

接下来找了一些 av 号 x,满足 x 和 x+1 对应 bv 号的第 11 位不同。设异或的数为 X X X,那么 [ X ⊕ x 58 ] ≠ X ⊕ ( x + 1 ) 58 [\frac{X\oplus x}{58}]\neq \frac{X\oplus( x+1)}{58} [58Xx]=58X(x+1) ⊕ \oplus 表示异或)。由于 av 号(除了最新的少量视频)最多只有 27 bits,所以可以设 X = 2 27 a + b ( 0 ⩽ b < 2 27 ) X=2^{27}a+b(0\leqslant b <2^{27}) X=227a+b(0b<227) 。然后可以发现 X X X只和 b b b 2 27 a   m o d   58 2^{27}a\ mod\ 58 227a mod 58有关,那么可以枚举这两个值(一共 2 27 × 58 = 7784628224 2^{27}\times 58=7784628224 227×58=7784628224种情况)然后使用上面的式子检查,就能得到若干可能的 2 27 a   m o d   58 2^{27}a\ mod\ 58 227a mod 58 b b b。这里我得到的可能值如下:(左边是 2 27 a   m o d   58 2^{27}a\ mod\ 58 227a mod 58 ,右边是 b b b

22 90983642
22 90983643
50 43234084
50 43234085

有奇有偶是因为异或 1 之后也能找到轮换表。而 90983642 + 43234085 = 2 27 − 1 90983642+43234085=2^{27}-1 90983642+43234085=2271 则使得模 58 的余数刚好变成 2 27 − 1 2^{27}-1 2271减它。我取了 b = 43234084 b=43234084 b=43234084,然后处理最低位,可以得到一个字符表,即

fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF

。对于更高位,实际上还需要知道 2 27 a   m o d   5 8 2 2^{27}a\ mod\ 58^{2} 227a mod 582 2 27 a   m o d   5 8 3 , … 2^{27}a\ mod\ 58^{3},… 227a mod 583,这些值也可以 枚举 58 次得到,最后我得到的值是 2 27 a   m o d   5 8 4 = 1749968 2^{27}a\ mod\ 58^{4}=1749968 227a mod 584=1749968

这时我发现,每一位的字符表是相同的(实际上只对 b = 43234084 b=43234084 b=43234084 是这样的),然后再微调一下参数(上面代码中的两个 magic number就相当于这里的 a , b a,b a,b ),最后处理了一下 ⩾ 2 27 \geqslant 2^{27} 227的情况就得到了这份代码。

作者:mcfx
链接:https://www.zhihu.com/question/381784377/answer/1099438784
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

更多文章:
用python爬取B站弹幕并绘制词云

python获取B站视频信息

猜你喜欢

转载自blog.csdn.net/weixin_46530492/article/details/107193198