python3网络爬虫--爬取B站视频弹幕(附源码)

news2024/11/29 22:45:50

文章目录

  • 一.前言
  • 二.配置Protobuf 环境&生成编译文件
    • 1.配置Protobuf 环境
    • 2.生成编译文件
  • 三.解析弹幕
  • 四.自动解析弹幕
  • 五.总结
  • 六.参考

本篇博文记录一下爬取B站弹幕的主要思路以及完整代码

一.前言

B站在2023年将弹幕接口的返回值从.xml改成了.so文件
比如下面这个地址:

https://api.bilibili.com/x/v2/dm/wbi/web/seg.so?type=1&oid=1258114431&pid=575703555&segment_index=1&pull_mode=1&ps=0&pe=120000&web_location=1315873&w_rid=fec78ad870a48b68b35024304ba8460f&wts=1694223505

返回值示例:
在这里插入图片描述
很明显部分数据是被加密了。

二.配置Protobuf 环境&生成编译文件

1.配置Protobuf 环境

通过搜索知道了,这种格式叫做**Protobuf **,这个格式为二进制编码传输

Protobuf(Protocol Buffers)是一种轻量级的数据序列化协议,由Google开发。它可以用于结构化数据的序列化和反序列化,常用于网络通信、数据存储和配置文件等场景。
Protobuf使用简洁的语法定义数据结构,然后通过编译器生成相应的代码,用于在不同的编程语言中进行数据的序列化和反序列化操作。相比于其他序列化协议,Protobuf具有更高的性能和更小的数据体积。
使用Protobuf,你可以定义消息的字段类型、字段名称和字段顺序等信息,然后通过编译器生成的代码来进行数据的读写操作。Protobuf支持多种编程语言,包括C++、Java、Python等,因此可以在不同的平台和语言之间进行数据的传输和交换。
总的来说,Protobuf协议是一种高效、灵活和可扩展的数据序列化协议,适用于各种场景下的数据交换和存储需求。

简单来说就是一种比XML还轻量的数据。
需要解密这种格式数据需要我们下载Protobuf 的编译器(我的电脑是windows64位的,直接下载win64位即可)

https://github.com/protocolbuffers/protobuf/releases/tag/v3.17.3
在这里插入图片描述

下载完成后,解压出来
在这里插入图片描述
其中bin目录为可执行程序存放目录,我们把它加到环境变量里来:
win10的操作步骤是:
右击“此电脑”-高级系统设置-环境变量-双击path-新建-输入值-确定在这里插入图片描述

在cmd中输入protoc来验证我们的配置是否成功,如果你的控制台输出结果和我的一样,那么恭喜你,环境配置成功
在这里插入图片描述

2.生成编译文件

首先要去下载dm.proto

https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/grpc_api/bilibili/community/service/dm/v1/dm.proto

然后在控制台中输入

protoc --python_out=. dm.proto

在这里插入图片描述

就会在同目录下生成一个dm_pb2.py的文件
在这里插入图片描述
这个文件很关键。

三.解析弹幕

将上一步编译出来的dm_pb2.py文件放在脚本的同一级,这里演示解析本地.so文件
撰写代码

import dm_pb2
from google.protobuf import text_format

my_seg = dm_pb2.DmSegMobileReply()
with open('./seg.so', 'rb') as f:
    DATA = f.read()
my_seg.ParseFromString(DATA)

parse_data = text_format.MessageToString(my_seg.elems[0], as_utf8=True)
print(parse_data)

输出结果
在这里插入图片描述

四.自动解析弹幕

这里本人贡献出一种自动解析弹幕,输入视频的BVID即可

import json

import requests
import google.protobuf.text_format as text_format
import dm_pb2 as Danmaku
import re


class BEngine():
    """
    bilibili引擎
    """

    def __init__(self):
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"}

    def do_request(self, url):
        headers = {
            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"
        }
        r = requests.get(url, headers=headers)
        if r.status_code == 200:
            r.encoding = 'utf-8'
            return r.text
        else:
            return False

    def get_video_cid(self, bvid):
        """
        通过bvid获取cid
        :param bvid:
        :return:
        """
        api_url = f'https://api.bilibili.com/x/web-interface/view?bvid={bvid}'
        try:
            html = self.do_request(api_url)
            if html:
                _json = json.loads(html)
                cid = _json['data'].get('cid')
                return cid
            else:
                return False
        except:
            return False

    def bvid_to_avid(self, bvid):
        """
        通过bvid获取avid
        :param bvid:
        :return:
        """
        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

        return dec(bvid)

    def get_danmu(self, avid, cid):
        """
        通过so文件获取解密后的弹幕列表
        :return:
        """
        result = []
        url = 'http://api.bilibili.com/x/v2/dm/web/seg.so'
        params = {
            'type': 1,  # 弹幕类型
            'oid': cid,  # cid
            'pid': avid,  # avid
            'segment_index': 1  # 弹幕分段
        }
        resp = requests.get(url, params, headers=self.headers)
        data = resp.content
        danmaku_seg = Danmaku.DmSegMobileReply()
        danmaku_seg.ParseFromString(data)
        for j in danmaku_seg.elems:
            parse_data = text_format.MessageToString(j, as_utf8=True)
            result.append(parse_data.replace("\n", ",").rstrip(","))
        print(result)
        return result

    def parse_danmu(self, danmu_list):
        """
        解析出每个弹幕列表内容
        :param danmu_list:
        :return:
        """
        result = []
        for each_dm in danmu_list:
            res = re.findall(
                '''id: \d+,progress: (\d+),mode: (\d+),fontsize: (\d+),color: (\d+),midHash: "(.*?)",content: "(.*?)",ctime: (\d+),weight: (\d+),idStr: "(\d+)"''',
                each_dm)
            if res and len(res[0]) == 9:
                item = {
                    "progress": res[0][0],
                    "mode": res[0][1],
                    "fontsize": res[0][2],
                    "color": res[0][3],
                    "midHash": res[0][4],
                    "content": res[0][5],
                    "ctime": res[0][6],
                    "weight": res[0][7],
                    "idStr": res[0][8],
                }
                result.append(item)
            else:
                continue
        return result

    def getdanmu_format(self, bvid):
        """
        弹幕直接格式化
        :param bvid:
        :return:
        """
        avid = e.bvid_to_avid(bvid)
        cid = e.get_video_cid(bvid)
        danmu_raw = self.get_danmu(avid, cid)
        return self.parse_danmu(danmu_raw)


if __name__ == '__main__':
    e = BEngine()
    bvid = "BV1Dz4y1L7hj"
    print(e.getdanmu_format(bvid))

输出结果示例
在这里插入图片描述

五.总结

本次通过调研protobuf协议通过搭建环境,使用Python撰写代码实现了对B战弹幕的解析,对于大多数人而言,可能搭建本地环境那里有些难,在此奉上封装好的dm_pb2.py文件点击下载,大家放在自己的脚本同级目录下即可。最后祝大家玩得开心能给点个赞么?
在这里插入图片描述

六.参考

b站弹幕 Protobuf 格式解析

Python实现对Bilibili视频点赞等信息的爬取

b站弹幕 so文件解析/逆序列化

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/991838.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Pandas模块:Python科学计算神器之一

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据开发、数据分析等。 🐴欢迎小伙伴们点赞👍🏻、收藏⭐️、…

SpotBugs检查java代码:不应该依赖平台默认编码(DM_DEFAULT_ENCODING)

https://spotbugs.readthedocs.io/en/latest/bugDescriptions.html#internationalization-i18n 一个字节转换为字符串(或字符串转化为字节)的函数调用没有明确指明编码,而是依赖平台默认的编码,这可能导致应用在不同平台上的行为…

mac电脑做为开发机的一些初始化操作

Terminal设置 风格设置 修改Terminal提示符 /etc/zshrc 此处控制,大概70行左右 PS1"%n%m %1~ %# "目录颜色设置 编辑文件 vim ~/.bash_profile输入以下内容 export LS_OPTIONS--colorauto # 如果没有指定,则自动选择颜色 export CLICOLOR…

【C++漂流记】一文搞懂类与对象的封装

本篇文章主要说明了类与对象中封装的有关知识,包括属性和行为作为整体、访问权限、class与struct的区别、成员属性的私有化,希望这篇文章可以帮助你更好的了解类与对象这方面的知识。 文章目录 一、属性和行为作为整体二、访问权限三、class与struct的区…

spark集成hudi

启动spark-shell spark-shell \ > --jars /opt/software/hudi-spark3.1-bundle_2.12-0.12.0.jar \ > --conf spark.serializerorg.apache.spark.serializer.KryoSerializer\ > --conf spark.sql.extensionsorg.apache.spark.sql.hudi.HoodieSparkSessionExtension2…

腾讯云AI绘画:探究AI创意与技术的新边界

目录 一、2023的“网红词汇”——AI绘画二、智能文生图1、智能文生图的应用场景2、风格和配置的多样性3、输入一段话,腾讯云AI绘画给你生成一张图4、文本描述生成图像,惊艳全场 三、智能图生图:重新定义图像美学1、智能图生图的多元应用场景2…

Nginx 解析漏洞

文章目录 Nginx 解析漏洞1. 空字节漏洞1.1 漏洞描述1.2 漏洞复现1.3 修复方案 2. Nginx 解析漏洞复现2.1 漏洞描述2.2 漏洞复现2.3 获取GetShell2.4 修复方案 3. Nginx 文件名逻辑漏洞3.1 漏洞描述3.2 漏洞原理3.3 漏洞复现3.3.1 环境启动3.3.2 漏洞验证 3.4 漏洞利用3.5 修复方…

X(推特)“鸡贼”手段曝光:这些广告并没有标注,你知道吗?

在使用推特的时候,有些人可能会注意到,一些广告并没有正确地标注,看起来很像普通的内容,十分难以区分。美国的联邦贸易委员会(FTC)和欧盟的欧洲广告标准局(EASA)等机构都对广告标签有…

WhatsApp的两个商业模式该如何选择

WhatsApp Business 是什么 目前 WhatsApp 提供两种商业模式,企业应根据自身需求选择相应版本。 第一个版本是 WhatsApp Business:初创企业只需一个手机应用程序,便可以个体单位与客户轻松互动; 另一个版本是 WhatsApp Business API&#xff…

如何优雅地实现接口防刷

背景 最近在学习redis,想到了之前的写的一个案例demo,实现了接口的流量防刷。主要是为了防止爬虫爬取接口,当然可以适用于那些需要进行流控的系统,shigen画了一张草图展示主要的原理和过程: 首先用户请求系统的接口&a…

一篇文章教会你如何降低代码的冗余度——探索指针数组,数组指针,函数指针,函数指针数组,回调函数的奥妙

前言:人们总说指针是c语言的灵魂,是因为指针的使用技巧是“千姿百态”的,程序员可以通过指针来直接访问内存,这就赋予了它功能的多样性以及更多意想不到的编程技巧与方式,在本篇文章中,笔者就给大家带来指针…

同时安装python2和3解决方案

我先安装python3后,按照网上步骤,继续安装好python2,直接运行python -v只能显示python2,运行python3找不到此命令,通过https://blog.csdn.net/qq_64409509/article/details/131514944这篇文章找到了解决方案&#xff0…

MindFusion.Diagramming for ASP.NET MVC 4.2 Crack

ASP.NET MVC 4.2 的 MindFusion.Diagramming 添加对多个图表页面和选项卡式图表视图的支持。 2023 年 9 月 8 日 - 16:57新版本 特征 多个图表页面-添加了DiagramDocument 类,它表示图表页面或工作表的集合。 可以将新页面添加到文档中,并且可以删除或重…

功率放大器主要用作什么用途

功率放大器是一种用于增大输入信号功率的器件,有着广泛的应用。其主要作用是提供足够的功率输出,以满足各种系统和设备对信号放大的需要。下面西安安泰电子详细介绍功率放大器的主要应用领域。 音频放大:功率放大器在音频领域有着广泛的应用。…

9.8day58 单调栈

739. 每日温度 - 力扣(LeetCode) 知识点:1.建栈 2.如果后面要加入的数小于栈顶元素就把数组的下标压进栈里 3.反之 就让该数于栈顶元素进行比较 如果该数大于栈顶元素(while) 就把栈顶元素下表对应的arr数组的值进行…

创建n维空间每个维度(轴)的刻度值numpy.ogrid[]

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 创建n维空间每个维度(轴)的刻度值 numpy.ogrid[] [太阳]选择题 下列代码y[1].shape输出的结果是? import numpy as np x np.ogrid[1:5:1] print("【显…

沿着管道或者巷道流动的烟雾或者液体的Shader参考

这个Shader正确其作用的前提是管道或者巷道和周围的物体要拉开一定距离,如果和周围的物体紧挨着是不行的。 首先看液体: 使用的贴图参考: 然后是气体: 使用的贴图参考:

如何将WPS设置为默认的办公软件

很多小伙伴的电脑中有好几种办公软件,每次打开文档表格都要进行选择,有小伙伴想要将WPS设置成默认的办公软件该怎么操作呢,下面小编就给大家详细介绍一下将WPS设置为默认的办公软件的方法,有需要的小伙伴快来和小编一起看一看吧。…

Tableau自学四部曲_Part3:基础图表制作

文章目录 一、 对比分析:比大小1. 柱状图2. 条形图3. 热力图(突出显示表)4. 气泡图5. 词云 二、变化分析:看趋势1. 折线图2. 基于连续时间序列的折线图预测接下来的数据走向3. 面积图 三、构成分析:看占比1. 饼图2. 【…

Unity 之 定时调用函数的方法

文章目录 1. **Invoke方法:**2. **InvokeRepeating方法:**3. **协程(Coroutines):**4. **Time.deltaTime:**5. **使用Invoke延迟执行方法并取消:** 在Unity中,你可以使用多种方式来实…