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


Posted in Python onSeptember 11, 2016

前言

虽然标题是全站,但目前只做了等级 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中的多重继承
Apr 28 Python
Python提取Linux内核源代码的目录结构实现方法
Jun 24 Python
windows下Python实现将pdf文件转化为png格式图片的方法
Jul 21 Python
Python实现图片拼接的代码
Jul 02 Python
在python中pandas的series合并方法
Nov 12 Python
pandas 将索引值相加的方法
Nov 15 Python
对python调用RPC接口的实例详解
Jan 03 Python
Python流程控制 if else实现解析
Sep 02 Python
python实现单目标、多目标、多尺度、自定义特征的KCF跟踪算法(实例代码)
Jan 08 Python
tensorboard实现同时显示训练曲线和测试曲线
Jan 21 Python
OpenCV灰度化之后图片为绿色的解决
Dec 01 Python
Python 中数组和数字相乘时的注意事项说明
May 10 Python
asyncio 的 coroutine对象 与 Future对象使用指南
Sep 11 #Python
Python中使用asyncio 封装文件读写
Sep 11 #Python
Python 如何访问外围作用域中的变量
Sep 11 #Python
Python优化技巧之利用ctypes提高执行速度
Sep 11 #Python
Python 中的with关键字使用详解
Sep 11 #Python
Python冒泡排序注意要点实例详解
Sep 09 #Python
通过5个知识点轻松搞定Python的作用域
Sep 09 #Python
You might like
PHP 身份验证方面的函数
2009/10/11 PHP
PHP session有效期session.gc_maxlifetime
2011/04/20 PHP
解析php时间戳与日期的转换
2013/06/06 PHP
解析阿里云ubuntu12.04环境下配置Apache+PHP+PHPmyadmin+MYsql
2013/06/26 PHP
Yii分页用法实例详解
2014/12/04 PHP
php中有关合并某一字段键值相同的数组合并的改进
2015/03/10 PHP
php获取百度收录、百度热词及百度快照的方法
2015/04/02 PHP
脚本吧 - 幻宇工作室用到js,超强推荐share.js
2006/12/23 Javascript
javascript学习网址备忘
2007/05/29 Javascript
javascript 二维数组的实现与应用
2010/03/16 Javascript
jQuery News Ticker 基于jQuery的即时新闻行情展示插件
2011/11/05 Javascript
js前台判断开始时间是否小于结束时间
2012/02/23 Javascript
JavaScript将页面表格导出为Excel的具体实现
2013/12/27 Javascript
js 数组去重的四种实用方法
2014/09/09 Javascript
jquery实现仿Flash的横向滑动菜单效果代码
2015/09/17 Javascript
Laravel中常见的错误与解决方法小结
2016/08/30 Javascript
javascript工厂模式和构造函数模式创建对象方法解析
2016/12/30 Javascript
JS完成画圆圈的小球
2017/03/07 Javascript
bootstrap轮播图示例代码分享
2017/05/17 Javascript
Vue如何实现响应式系统
2018/07/11 Javascript
swiper在angularjs中使用循环轮播失效的解决方法
2018/09/27 Javascript
layui动态加载多表头的实例
2019/09/05 Javascript
layui 实现二级弹窗弹出之后 关闭一级弹窗的方法
2019/09/18 Javascript
Vue SSR 即时编译技术的实现
2020/05/06 Javascript
python 二分查找和快速排序实例详解
2017/10/13 Python
Python初学者常见错误详解
2019/07/02 Python
Python实现自动访问网页的例子
2020/02/21 Python
python利用递归方法实现求集合的幂集
2020/09/07 Python
英国空调、除湿机和通风设备排名第一:Air Con Centre
2019/02/25 全球购物
XD健身器材:Kevlar球、Crossfit健身球
2019/03/26 全球购物
幼儿教师自我鉴定
2013/11/02 职场文书
数据管理员的自我评价分享
2013/11/15 职场文书
教师个人自我评价范文
2014/04/13 职场文书
给市场的环保建议书
2014/05/14 职场文书
篮球比赛策划方案
2014/06/05 职场文书
Ajax请求超时与网络异常处理图文详解
2021/05/23 Javascript