利用Python脚本逆向解析Bilibili弹幕发送者UID

听雨眠
听雨眠
发布时间:2026-10-14 | 5人浏览过
原创

本文详细解析如何通过Python脚本获取Bilibili视频弹幕数据,并逆向分析其中的用户UID加密机制。文章介绍了获取弹幕CID的两种接口方式,重点阐述了利用CRC32算法生成的16进制校验码,通过构建无符号整型彩虹表来反查用户UID的技术方案,并结合Python与PHP实现了完整的查询工具。

Bilibili弹幕发送者查询原理概述

众所周知,Bilibili平台并未提供直接查看弹幕发送者身份的功能。这导致当用户看到令人不适的弹幕时,虽感愤怒却无从追究。然而,B站支持屏蔽特定用户发送的弹幕,这暗示其数据接口中必然包含用户身份信息。鉴于近期正在研究爬虫技术,我决定首先定位弹幕相关的数据接口,并深入分析其数据结构。

弹幕数据接口定位与获取

接口定位

定位接口的方法通常是打开任意视频页面并按下F12开发者工具。但在尝试搜索两圈后,我并未找到直接暴露弹幕发送者信息的接口。既然无法通过常规手段获取,便转向搜索引擎查找已知方案。果然,找到了两个返回XML格式数据的接口。

https://comment.bilibili.com/+cid https://api.bilibili.com/x/v1/dm/list.so?oid=+cid

上述接口中的cid是视频独有的数字标识,每一集视频对应一个唯一的cid。获取cid的方法是在视频页面按F12打开开发者工具,使用Ctrl+F搜索“cid”关键词,通常八九位数的数字即为所求的cid。

此外,我还发现了一个通过aid(视频作品ID)获取cid的接口。

https://www.bilibili.com/widget/getPageList?aid=+aid

弹幕数据结构分析与UID加密机制

数据分析

既然成功获取了弹幕数据,接下来需要解析这些数据的具体含义和用途。

CRC32校验码与数据库存储策略

通过对数据结构进行分析,可以提取出两个关键信息:第6个字段为时间戳,第8个字段则是用户UID经过某种加密处理后的结果。经查询确认,该字段是用户UID经过CRC32校验后转换成的16进制数。这意味着只能由UID生成校验码,而无法直接反向推导出UID。这似乎暗示需要通过彩虹表的方式进行数据查找。那么,在数据库中存储这串8位16进制数字应采用何种类型? 选项包括varchar和bigint。考虑到B站拥有约6亿用户,在6亿条数据中查找特定字符串的速度必然较慢(尽管有测试表明varchar与bigint的查找速度差异并不显著)。 在我决定使用bigint存储数据时,突然意识到8位16进制数对应的是2的32次方。有符号int类型的上限是2的31次方,但如果使用无符号整型(unsigned int)存储,其上限正好是2的32次方,即能容纳到0xffffffff这么大的数据,完全满足存储需求。因此,我果断改用无符号int类型,并将id也设为无符号int,以crc32b编码后的数据作为主键,构建彩虹表并存储至服务器。 (粗略估算,6亿条数据大约需要27G的存储空间……而我的服务器总容量仅为40G……)

Python与PHP全栈实现方案

Web应用开发

后续的操作逻辑相对顺畅。我编写了一个Python脚本,该脚本接收两个参数:视频cid和待搜索的弹幕关键字,返回结果包括发送弹幕的用户、该用户的crc32b编码值以及时间戳。随后,利用PHP的exec函数执行Python代码,并通过搜索本地数据库找出对应的用户UID,最后由PHP返回JSON格式的数据供前端展示。

Python代码实现(代码质量一般)


import requests
from bs4 import BeautifulSoup
import re
import io

import sys

sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8')
req = requests.get('https://comment.bilibili.com/'+sys.argv[1]+'.xml')
req.encoding = req.apparent_encoding
soup = BeautifulSoup(req.text, 'html.parser').find_all(name='d')
result = ""
for i in soup:
 s = re.sub('<(.*?)>', '', str(i))
 index = 0
 if(len(sys.argv[2])>0):
  index = s.find(str(sys.argv[2]))
 if(index!=-1):
  result+=str(i).split(",")[6]+","+s+","+str(i).split(",")[4]+","
print(result)

效果演示

前端代码为简易实现,主要目的是验证功能可行性。

此处显示为NULL的原因在于,我的服务器仍在缓慢地将彩虹表数据写入数据库,预计需要4天时间完成写入。 今日新增了一个暴力破解功能,以避免查询结果为NULL,但代价是查询速度会显著降低。

最后,附上该工具的使用链接:点我

总结与工具分享

总结

至此,关于利用Python脚本查找Bilibili弹幕发送者的介绍结束。更多关于Bilibili弹幕发送者的内容,请搜索本站历史文章或继续浏览相关文章,希望大家今后多多支持本站!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表