哔哩哔哩弹幕爬取以及BV与AV号之间的转换

作为b站老粉丝,我有义务向新人科普bilibili的发展与纪年史,本人持中立态度,仅做记录工作。

B站的API端口都是开放的,用一个很简单的调用命令就可以计算出BV号对应的AV号。

B站的源码已经在GitHub上流出,部分机制甚至还没有经过修改。

尊敬的各位用户:
一直以来,AV 号都是 B 站视频稿件的重要标识,在视频的传播和分享中起到了关键作用。
为了保护稿件信息安全,容纳更多投稿,维护 UP 主的权益,自 2020 年 3 月 23 日起,AV 号将全面升级为 BV 号。
与纯数字的 AV 号不同,BV 号是一段由数字和大小写字母组成的字符串,经过算法自动生成。未来将统一使用 BV 号作为稿件标识。
同时,2020 年 3 月 23 日前生成 AV 号的相关功能保持不变。例如,已分享的稿件链接,AV号搜索,以及动态、评论、私信中的高亮跳转。
此外,用户在复制 BV 号或者包含 BV 号的链接后,打开 B 站 APP 的同时会自动跳转至该视频。

1. BV与AV号互换

python源代码:

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('BV17x411w7KC'))
print(dec('BV1Q541167Qg'))
print(dec('BV1mK4y1C7Bz'))
print(enc(170001))
print(enc(455017605))
print(enc(882584971))

运行结果测试为:
170001 ==> BV17x411w7KC
455017605 === > BV1Q541167Qg

2. bilibili的弹幕api接口

bilibili的弹幕api接口主要通过如下方式来获取弹幕:

  1. 获取cid编码
    通过请求 https://api.bilibili.com/x/player/pagelist?bvid=BV号&jsonp=jsonp 这个接口,返回为json数据类型,提取其中的cid返回值

  2. 获取xml的弹幕列表
    接下来在通过请求 https://api.bilibili.com/x/v1/dm/list.so?oid=返回的cid值,返回值为xml数据类型,正则表达式提取出文本内容,便是我们需要的弹幕列表

python源代码:

# -*- coding:utf-8 -*-
import re
import jieba
import numpy as np
import requests
from PIL import Image
from wordcloud import WordCloud
from matplotlib import pyplot as plt
"""
获取哔哩哔哩弹幕
"""


# BV下载页面
def download_page(url):
    try:
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"
        }
        result = requests.get(url=url, headers=headers, timeout=10)
        if result.status_code == 200:
            return result

    except Exception as e:
        print(e)


# 获取cid编码
def get_cid(Bv):
    url = 'https://api.bilibili.com/x/player/pagelist?bvid={}&jsonp=jsonp'.format(Bv)
    response = download_page(url)
    res_dict = response.json()
    cid = res_dict['data'][0]['cid']
    return cid


# 根据cid请求弹幕
def get_dan_mu(cid):
    url = 'https://api.bilibili.com/x/v1/dm/list.so?oid={}'.format(cid)
    res = download_page(url)
    res_xml = res.content.decode('utf-8')
    pattern = re.compile('(.*?)', re.S)
    dan_mu_list = re.findall(pattern, res_xml)
    return dan_mu_list


# 把弹幕写入到文件中
def save_to_file(dan_mu_list):
    with open('./{}.txt'.format(bv), mode='w', encoding='utf-8') as f:
        for i in range(len(dan_mu_list)):
            # 将列表中的每个数去除首尾空格后,逐行写入txt文件
            f.write(str(dan_mu_list[i]).strip() + '\n')


# 弹幕爬虫主流程
def main(bv):
    # 根据视频av号获得cid
    cid = get_cid(bv)
    # 根据cid爬取弹幕
    dan_mu_list = get_dan_mu(cid)
    # 把弹幕写入到文件中
    save_to_file(dan_mu_list)


if __name__ == '__main__':
    bv = str(input("请输入目标BV号:BV17x411w7KC")).strip()
    main(bv)

你可能感兴趣的:(Python,python,正则表达式)