首发于编程专栏
[我叫以赏]BiliBili AV与BV互转

[我叫以赏]BiliBili AV与BV互转

BiliBili于2020年3月23日14点30秒将av号转化成为bv号,许多人高呼BV号来了!爷的青春结束了!

对于B站用户不习惯BV号只是一时的,但是B站用户对AV号的怀念是永久不变的,B站将AV号改为BV号时,并未将AV号完全移除,使用BV号可以获得更加安全的体验。AV号或许也将在不久的未来用尽,我万万没想到的是,BV号来临之时,用户开始纷纷解析转化算法,可见B站对于我们的影响力有多大!废话不多说看看如何将AV与BV号互相转化吧!

B站官方提供了一个接口,

api.bilibili.com/x/web- (输入av号)

api.bilibili.com/x/web- (输入BV号)

通过这两个接口,可以将BV与AV号互相转化,使用Python编程,接口会返回字典,只要取出字典内的数据就可以了。

当然,知乎上的大佬 mcfx 也反推出了算法,知乎地址:zhihu.com/question/3817

并且提供了Python源码用于转化,

我将代码进行加工,

# -*- coding:utf-8 -*-
import requests  # 引入 requests 模块
import json  # 引入 json 模块

Str = 'fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF'  # 准备的一串指定字符串
Dict = {}  # 建立一个空字典

# 将字符串的每一个字符放入字典一一对应 , 如 f对应0 Z对应1 一次类推。
for i in range(58):
    Dict[Str[i]] = i
# print(tr) #如果你实在不理解请将前面的注释去掉,查看字典的构成

s = [11, 10, 3, 8, 4, 6, 2, 9, 5, 7]  # 必要的解密列表
xor = 177451812  # 必要的解密数字 通过知乎大佬的观察计算得出 网址:https://www.zhihu.com/question/381784377
add = 100618342136696320  # 这串数字最后要被减去或加上


# 解密BV号
def algorithm_dec(bv):
    if bv.find('BV') == -1:
        bv = 'BV' + bv

    r = 0
    # 下面的代码是将BV号的编码对照字典转化并进行相乘相加操作 **为乘方
    for i in range(10):
        r += Dict[bv[s[i]]] * 58 ** i
    # 将结果与add相减并进行异或计算

    print('计算成功!请求返回的视频av号为:av' +  str((r - add) ^ xor))
    print('输入网址访问视频: https://www.bilibili.com/video/av' + str((r - add) ^ xor))
    print('输入网址访问视频: https://www.bilibili.com/video/' + bv)


# 加密AV号
def algorithm_enc(av):
    ret = av
    av = int(av)
    # 将AV号传入结果进行异或计算并加上 100618342136696320
    av = (av ^ xor) + add
    # 将BV号的格式(BV + 10个字符) 转化成列表方便后面的操作
    r = list('BV          ')
    # 将传入的数字对照字典进行转化
    for i in range(10):
        r[s[i]] = Str[av // 58 ** i % 58]
    # 将转化好的列表数据重新整合成字符串

    print('计算成功!请求返回的视频BV号为:' + ''.join(r))
    print('输入网址访问视频: https://www.bilibili.com/video/av' + str(ret))
    print('输入网址访问视频: https://www.bilibili.com/video/' + ''.join(r))


def Online_dec(bv):
    bv = bv.strip()
    try:
        headers = {
            'Host': "api.bilibili.com",
            'User-Agent': "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36",
        }
        data = requests.get('http://api.bilibili.com/x/web-interface/archive/stat?bvid=%s' % (bv),
                            headers=headers)  # 获取视频源数据
        if data.content.decode('utf-8').find('由于触发哔哩哔哩安全风控策略,该次访问请求被拒绝。') != -1:
            raise BaseException('接口访问次数更多,触发了BiliBili安全机制!')
        information = json.loads(data.content.decode('utf-8'))  # 解析数据为字典
        if information['code'] != -400:  # 请求错误
            print('在线请求成功!请求返回的视频av号为:av' + str(information["data"]["aid"]))
            print('输入网址访问视频: https://www.bilibili.com/video/av' + str(information["data"]["aid"]))
            print('输入网址访问视频: https://www.bilibili.com/video/' + str(information["data"]["bvid"]))
        else:
            print('访问接口拒绝了我们的请求,可能是您的输入错误!返回代码:%d 返回消息:%s' % (information['code'], information['message']))  # 输出错误文本
    except BaseException as Error:
        print('访问在线接口时出现错误,原因:' + str(Error))

def Online_enc(av):
    av = av.strip()
    try:
        headers = {
            'Host': "api.bilibili.com",
            'User-Agent': "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36",
        }
        data = requests.get('http://api.bilibili.com/x/web-interface/archive/stat?aid=%s' % (av),
                            headers=headers)  # 获取视频源数据
        if data.content.decode('utf-8').find('由于触发哔哩哔哩安全风控策略,该次访问请求被拒绝。') != -1:
            raise BaseException('接口访问次数更多,触发了BiliBili安全机制!')
        information = json.loads(data.content.decode('utf-8'))  # 解析数据为字典
        if information['code'] != -400:  # 请求错误
            print('在线请求成功!请求返回的视频BV号为:BV' + str(information["data"]["bvid"]))
            print('输入网址访问视频: https://www.bilibili.com/video/' + str(information["data"]["bvid"]))
            print('输入网址访问视频: https://www.bilibili.com/video/av' + str(information["data"]["aid"]))
        else:
            print('访问接口拒绝了我们的请求,可能是您的输入错误!返回代码:%d 返回消息:%s' % (information['code'], information['message']))  # 输出错误文本
    except BaseException as Error:
        print('访问在线接口时出现错误,原因:' + str(Error))


def video_trbv(video: str):
    try:

        up = video.find('/BV')
        down = video.find('?', up + 3)
        if up != -1:  # 输入网址
            if down != -1:  # 结尾有东西
                return (video[up + 3:down])
            else:
                return (video[up + 3:]) 
        elif video.find('BV') != -1:  # 找到bv
            return (video[video.find('BV') + 2:])
        else:
            return (video)
    except:
        print('BV(网址)输入错误!无法转化!')

def video_trav(video: str):
    try:
        video = video.lower()
        up = video.find('/av')
        down = video.find('?', up + 3)
        if up != -1:  # 输入网址
            if down != -1:  # 结尾有东西
                return (video[up + 3:down])
            else:
                return (video[up + 3:])
        elif video.find('av') != -1:  # 找到bv
            return (video[video.find('av') + 2:])
        else:
            return (video)
    except:
        print('av(网址)输入错误!无法转化!')



if __name__ == '__main__':
    print("BiliBili于2020年3月23日14点30秒将av号转化成为bv号,但是大多数人对av号抱有怀念之情,\n"
          "这个制作的Python程序可以实现AV与BV互相转化,算法由知乎大佬 mcfx 提供,由 @我叫以赏 优化代码(指整理)\n"
          "网址:https://www.zhihu.com/question/381784377\n"
          "B站的av号总有一天会被BV号替代,时代也是不断进步的,所以此程序仅供研究调查使用,转载注明原作者,(也不要求注明我啦)\n"
          "程序展示 在线av与BV互转 与 算法av与BV互转 。\n")  # 输出版权信息

    while True:

        User = input("----------\n输入 1.在线转化 2.算法转化\n请输入功能代码:")  # 引导用户输入
        if User == '1':  # 在线功能转化
            video = input('输入AV号或BV号(可以加AV或BV,也可以是网址):')
            try:
                int(video)
            except:
                if video.find('av') != -1:  # av号
                    Online_enc(video_trav(video))
                else:
                    Online_dec(video_trbv(video))
            else:
                Online_enc(video_trav(video))
        elif User == "2":
            video = input('输入AV号或BV号(可以加AV或BV,也可以是网址):')
            try:
                int(video)
            except:
                if video.find('av') != -1:  # av号
                    algorithm_enc(video_trav(video))
                else:
                    algorithm_dec(video_trbv(video))
            else:
                algorithm_enc(video_trav(video))
            pass
        else:
            print("抱歉您输入的代码不正确!请输入1或者2。")

编辑于 03-26

文章被以下专栏收录