基于asyncio异步协程框架实现收集B站直播弹幕详细介绍
本文给大家分享的是基于asyncio 异步协程框架实现收集B站直播弹幕收集系统的简单设计,并附上源码,有需要的小伙伴可以参考下
">
前言
虽然标题是全站,但目前只做了等级 top 100 直播间的全天弹幕收集。
弹幕收集系统基于之前的B 站直播弹幕姬 Python 版修改而来。具体协议分析可以看上一篇文章。
直播弹幕协议是直接基于 TCP 协议,所以如果 B 站对类似我这种行为做反制措施,比较困难。应该有我不知道的技术手段来检测类似我这种恶意行为。
我试过同时连接 100 个房间,和连接单个房间 100 次的实验,都没有问题。>150 会被关闭链接。
直播间的选取
现在弹幕收集系统在选取直播间上比较简单,直接选取了等级 top100。
以后会修改这部分,改成定时去 http://live.bilibili.com/all 查看新开播的直播间,并动态添加任务。
异步任务和弹幕存储
收集系统仍旧使用了 asyncio 异步协程框架,对于每一个直播间都使用如下方法来加进 loop 中。
danmuji = bilibiliClient(url, self.lock, self.commentq, self.numq) task1 = asyncio.ensure_future(danmuji.connectServer()) task2 = asyncio.ensure_future(danmuji.HeartbeatLoop())
其实若将心跳任务 HeartbeatLoop 放入 connectorServer 中去启动,代码看起来更优雅一些。但这么做是因为我需要维护一个任务列表,后面会有描述。
在弹幕存储上我花了些时间选择。
数据库存储是一个同步 IO 的过程,Insert 的时候会阻塞弹幕收集的任务。虽然有 aiomysql 这种异步接口,但配置数据库太麻烦,我的设想是这个小系统能够方便地部署。
最终我选择使用自带的 sqlite3。但 sqlite3 无法做并行操作,故开了一个线程单独进行数据库存储。在另一个线程中,100 * 2 个任务搜集所有的弹幕、人数信息,并塞进队列 commentq, numq 中。存储线程每隔 10s 唤醒一次,将队列中的数据写进 sqlite3 中,并清空队列。
在多线程和异步的配合下,网络流量没有被阻塞。
可能的连接失败场景处理
弹幕协议是直接基于 TCP,位与位直接关联性较强,一旦解析错误,很容易就抛 Exception(个人感觉,虽然 TCP 是可靠传输,但B站服务器自身发生错误也是有可能的)。所以有必要设计一个自动重连机制。
在 asyncio 文档中提到,
Done means either that a result / exception are available, or that the future was cancelled.
函数正常返回、抛出异常或者是被 cancel,都会退出当前任务。可以使用 done() 来判断。
每一个直播间对应两个任务,解析任务是最容易挂的,但并不会影响心跳任务,所以必须找出并将对应心跳任务结束。
在创建任务的时候使用字典记录每个房间的两个任务,
self.tasks[url] = [task1, task2]
在运行过程中,每隔 10s 做一次检查,
for url in self.tasks: item = self.tasks[url] task1 = item[0] task2 = item[1] if task1.done() == True or task2.done() == True: if task1.done() == False: task1.cancel() if task2.done() == False: task2.cancel() danmuji = bilibiliClient(url, self.lock, self.commentq, self.numq) task11 = asyncio.ensure_future(danmuji.connectServer()) task22 = asyncio.ensure_future(danmuji.HeartbeatLoop()) self.tasks[url] = [task11, task22]
实际我只见过一次任务失败的场景,是因为主播房间被封了,导致无法进入直播间。
结论
B站人数是按照连接弹幕服务器的链接数量统计的。通过操纵链接量,可以瞬间增加任意人数观看,有商机?
运行的这几天中,发现即使大部分房间不在直播,也能有 >5 的人数,包括凌晨。我只能猜测也有和我一样的人在 24h 收集弹幕。
top100 平均一天 40M 弹幕数据。
收集的弹幕能做什么?还没想好,可能可以拿来做用户行为分析 -_^
以上是基于asyncio异步协程框架实现收集B站直播弹幕详细介绍的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

0.基础在《PythonAsyncio调度原理》中介绍了Asyncio的两种调度基本单位,Handler和TimeHandler,他们只能被loop.call_xx函数调用,开发者从表面上不知道他们的存在,他们和loop.call_xx属于事件循环的基础功能,但是这些操作都属于单一操作,需要开发者自己编写代码把他们的操作给串联起来。而在《Python的可等待对象在Asyncio的作用》中介绍了协程链的发起者asyncio.Task能通过loop.call_soon跟事件循环进行交互,并串联整个协

1.为什么要使用异步编程?传统编程使用阻塞式I/O,这意味着程序会等待某个操作完成,然后才能继续执行。这对于处理单个任务来说可能很有效,但对于处理大量任务时,可能会导致程序变慢。异步编程则打破了传统阻塞式I/O的限制,它使用非阻塞式I/O,这意味着程序可以将任务分发到不同的线程或事件循环中执行,而无需等待任务完成。这允许程序同时处理多个任务,提高程序的性能和效率。2.python异步编程的基础Python异步编程的基础是协程和事件循环。协程是允许函数在暂停和恢复之间切换的函数。事件循环则负责调度

并发和异步编程并发编程处理同时执行的多个任务,异步编程是一种并发编程,其中任务不会阻塞线程。asyncio是python中用于异步编程的库,它允许程序在不阻塞主线程的情况下执行I/O操作。事件循环asyncio的核心是事件循环,它监控I/O事件并调度相应的任务。当一个协程准备就绪时,事件循环会执行它,直到它等待I/O操作。然后,它会暂停协程并继续执行其他协程。协程协程是可暂停和恢复执行的函数。asyncdef关键字用于创建协程。协程使用await关键字等待I/O操作完成。asyncio的基础以下

Golang协程和Pythonasyncio都是并发编程工具。协程是轻量级线程,在同一线程并发运行;asyncio使用事件循环处理I/O事件。Golang协程语法简洁,性能优于asyncio,适合密集型计算;asyncio异步特性适合处理大量I/O事件,语法更易用,适合Python开发者。根据应用程序需求和开发者偏好选择最合适的技术尤为重要。

python的全局解释器锁(GIL)是一种同步机制,它确保Python解释器一次只能执行一个线程。这有助于防止数据竞争和保证线程安全性,但也会限制并行计算的性能,尤其是在多核系统中。GIL的作用GIL的作用是防止多个线程同时访问共享数据,从而导致竞争条件。它通过在每次执行字节码时获取锁来实现这一点。当一个线程获取GIL时,其他线程将被阻塞,直到锁被释放。GIL的缺点虽然GIL提供了线程安全,但它也对多线程Python程序的性能产生了负面影响。由于GIL限制了并行执行,因此在多核系统上无法充分利用

什么是异步编程?异步编程是一种编程范式,它允许程序在不阻塞的情况下并发执行多个任务。与传统的同步编程不同,异步编程中,当一个任务需要等待其他任务完成时,它不会被阻塞,而是可以继续执行其他任务。这样,程序可以同时处理多个任务,从而提高程序的整体性能。python中的异步编程Python3.4及更高版本支持异步编程。异步编程在Python中主要通过协程和asyncio模块来实现。协程是Python中一种特殊的函数,它允许程序在不阻塞的情况下暂停和恢复执行。asyncio模块是Python中的一个异步

协程的定义需要使用asyncdef语句协程可以做哪些事:1、等待一个future结果2、等待另一个协程(产生一个结果或引发一个异常)3、产生一个结果给正在等它的协程4、引发一个异常给正在等它的协程协程的运行调用协程函数,协程不会开始运行,只是返回一个协程对象要让协程对象运行有两种方式:1、在另一个已经运行的协程中用await等待它2、通过ensure_future函数计划它的执行只有某线程的loop运行了,协程才可能运行下面的例子:先拿到当前线程缺省的loop,然后将协程对象交给loop.run

1.基本介绍Python.Asyncio是一个大而全的库,它包括很多功能,而跟核心调度相关的逻辑除了三种可等待对象外,还有其它一些功能,它们分别位于runners.py,base_event.py,event.py三个文件中。runners.py文件有一个主要的类--Runner,它的主要职责是做好进入协程模式的事件循环等到初始化工作,以及在退出协程模式时清理还在内存的协程,生成器等对象。协程模式只是为了能方便理解,对于计算机而言,并没有这样区分event.py文件除了存放着EventLoop对
