基于asyncio 异步协程框架实现收集B站直播弹幕

 更新时间:2016年09月11日 10:11:57   作者:liyiyang  
本文给大家分享的是基于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]

实际我只见过一次任务失败的场景,是因为主播房间被封了,导致无法进入直播间。

结论

  1. B站人数是按照连接弹幕服务器的链接数量统计的。通过操纵链接量,可以瞬间增加任意人数观看,有商机?
  2. 运行的这几天中,发现即使大部分房间不在直播,也能有 >5 的人数,包括凌晨。我只能猜测也有和我一样的人在 24h 收集弹幕。
  3. top100 平均一天 40M 弹幕数据。
  4. 收集的弹幕能做什么?还没想好,可能可以拿来做用户行为分析 -_^

最后附上本源码的GITHUB地址 https://github.com/lyyyuna/bilibili_danmu_colloector

相关文章

  • 基于Python制作个抢红包的工具

    基于Python制作个抢红包的工具

    快过年了,刚刚收到了两个消息,一个好消息,一个坏消息。好消息就是微信群里有人要发红包,坏消息是不一定能都抢到。所以本文就来用Python做一个抢红包工具,需要的可以参考一下
    2023-01-01
  • TensorFlow自定义损失函数来预测商品销售量

    TensorFlow自定义损失函数来预测商品销售量

    这篇文章主要介绍了TensorFlow自定义损失函数——预测商品销售量,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-02-02
  • Python原始字符串与Unicode字符串操作符用法实例分析

    Python原始字符串与Unicode字符串操作符用法实例分析

    这篇文章主要介绍了Python原始字符串与Unicode字符串操作符用法,结合实例形式分析了Python针对原始字符与Unicode字符的操作符用法,需要的朋友可以参考下
    2017-07-07
  • Python利用yield form实现异步协程爬虫

    Python利用yield form实现异步协程爬虫

    这篇文章主要为大家详细介绍了Python如何利用yield form实现异步协程爬虫。其实这是很古老的用法了,现在大多用的aiohttp库实现,这篇记录仅仅用做个人的协程底层实现的学习,希望对大家有所帮助
    2022-11-11
  • 纯Python实现遗传算法详解

    纯Python实现遗传算法详解

    遗传算法(GA)是七十年代被霍兰德提出来的,那还是8086的时代,但在如今的3nm时代,仍然散发着经典的光辉,下面我们就来看看如何利用Python实现遗传算法吧
    2023-08-08
  • 详解Python计算机视觉 图像扭曲(仿射扭曲)

    详解Python计算机视觉 图像扭曲(仿射扭曲)

    这篇文章主要介绍了Python计算机视觉 图像扭曲(仿射扭曲),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • 详解Python网络框架Django和Scrapy安装指南

    详解Python网络框架Django和Scrapy安装指南

    这篇文章主要介绍了详解Python网络框架Django和Scrapy安装指南,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-04-04
  • python实现修改固定模式的字符串内容操作示例

    python实现修改固定模式的字符串内容操作示例

    这篇文章主要介绍了python实现修改固定模式的字符串内容操作,结合实例形式详细分析了Python修改固定模式字符串原理、实现方法及相关操作注意事项,需要的朋友可以参考下
    2019-12-12
  • python 两个一样的字符串用==结果为false问题的解决

    python 两个一样的字符串用==结果为false问题的解决

    这篇文章主要介绍了python 两个一样的字符串用==结果为false问题的解决,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-03-03
  • TensorFlow实现创建分类器

    TensorFlow实现创建分类器

    这篇文章主要为大家详细介绍了TensorFlow实现创建分类器,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02

最新评论