Python爬取斗鱼弹幕——多房间同时抓取实现(一)从单个房间开始

技能储备需求
我们从零基础出发,但前提是假设我们已经有了基本python语法基础(比如我已经会了 Hello World!)现在需要学的:

  • 套接字socket
  • 正则表达式
  • 多线程爬虫
  • requests库的使用
  • json库的使用

以上五个是我们接下来会用到的,我们只要知道基本用法,如果只是单纯想实现爬弹幕功能,不需要深究。
斗鱼弹幕服务器第三方接入通讯协议

  • 此文档对斗鱼平台弹幕和相关消息通讯协议格式进行了详细说明,同时附带获取弹幕的详细操作步骤,意为第三方平台获取斗鱼弹幕等信息提供帮助。
  • 在谷歌上或者登陆官方论坛(http://dev-bbs.douyutv.com/forum.php) 都可以下载此文档

步入正题
Step1 建立与服务器连接
斗鱼弹幕通讯协议是一种基于 TCP 服务的应用层协议。我们可以从上文所提及文档中连接初始化的步骤。第三方客户端通过 TCP 协议连接到弹幕服务器(依据指定的 IP 和端口)。
第三方接入弹幕服务器列表:
IP 地址:openbarrage.douyutv.com 端口:8601
我们使用socket库来建立连接。
步骤很简单:

  1. 初始化socket
  2. 利用socket库中的connect方法建立连接

说明:connect方法需要的参数host我们可以通过IP地址来获取。
以下是代码

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # create a socket
host = socket.gethostbyname("openbarrage.douyutv.com")  # get the host(8601) of Douyu
port = 8601
s.connect((host, port))  # connect the socket to Douyu

连接成功之后,我们可以用socket库中的recv方法获取服务器返回消息。但是到这一步,我们还不能收到弹幕消息。(房间还没进呢)
step2 登录及进入弹幕分组
根据斗鱼弹幕服务器协议要求,第三方接入需要先向服务器发送登录请求,并加入分组,服务器才会将客户端添加到请求指定弹幕分组,并返回相关消息。
这也很好理解,我们得先告诉对方我们想要获取什么,对方才好返回消息。
步骤

  1. 登录
    客户端向弹幕服务器发送登录请求,登录弹幕服务器;弹幕服务器收到客户端登录请求并完成登录后,返回登录成功消息给客户端。
    在此之前,我们需要知道斗鱼对于第三方发送的消息格式有自己的一套协议,所以,我们发送的登录请求必须符合这一规定。
    斗鱼后台协议头设计如下:

    字段说明如下:
    消息长度:4 字节小端整数,表示整条消息(包括自身)长度(字节数)。
    消息长度出现两遍,二者相同。
    消息类型:2 字节小端整数,表示消息类型。取值如下:
    689 客户端发送给弹幕服务器的文本格式数据
    690 弹幕服务器发送给客户端的文本格式数据。
    加密字段:暂时未用,默认为 0。
    保留字段:暂时未用,默认为 0。
    数据部分:斗鱼独创序列化文本数据,结尾必须为‘\0’。详细序列化、反
    序列化算法见下节。(所有协议内容均为 UTF-8 编码)
    简述
    简而言之,上述协议是规定了一套协议头的格式,就是说,我们想要发送给服务器的任何消息之前都需要加上上面的协议头。所以我们接下来的工作就是要写好这一段协议头。
    以下是代码:
data_length = len(info) + 8
value = 689  # the type of information for client sending to the server
infohead = int.to_bytes(data_length, 4, 'little') + int.to_bytes(data_length, 4, 'little') \
+ int.to_bytes(value, 4, 'little')
# transfer int into bytes and form a protocol head

到这里还是没有结束,因为我们还需要加上我们要发送的消息。
为增强兼容性、可读性斗鱼后台通讯协议采用文本形式的明文数据。也就是说,斗鱼对第三方发来的消息也有一套自己的协议,在文档中称之为序列化。
详细说明可参见文档,我们只需要知道怎么用就好了。
登录请求消息用于完成登陆授权,完整的数据部分应包含的字段如下:
type@=loginreq/roomid@=58839/

例如我们想要爬取的房间号为688,那我们的登录消息就是:
‘type@=loginreq/roomid@=688/\0’
说明:
末尾加上‘\0’ 是斗鱼弹幕接入协议要求,详见上文所提文档。
此时我们只需加上上文所得协议头就可以向服务器发送登录请求了!代码如下:

login_info = 'type@=loginreq/username@=rieuse/password@=douyu/roomid@=688/\0' # sending login request
info = login_info.encode('utf-8')  # transfer it into utf-8 as requested
data_length = len(info) + 8
value = 689  # the type of information for client sending to the server
infohead = int.to_bytes(data_length, 4, 'little') + int.to_bytes(data_length, 4, 'little') \
+ int.to_bytes(value, 4, 'little')
s.send(infohead + info)
  1. 加入分组
    与登录类似,此时我们只需要把登录消息换成加入分组消息即可。这里我直接给出代码:
join_group = 'type@=joingroup/rid@=688/gid@=-9999/\0'# sending joingroup request
info = login_info.encode('utf-8')  # transfer it into utf-8 as requested
data_length = len(info) + 8
value = 689  # the type of information for client sending to the server
infohead = int.to_bytes(data_length, 4, 'little') + int.to_bytes(data_length, 4, 'little') \
+ int.to_bytes(value, 4, 'little')
s.send(infohead + info)
  1. 心跳消息
    斗鱼规定爬虫每间隔45s需要向服务器发送心跳消息,该消息用于维持与后台间的心跳,完整的数据部分应包含的字段如下:
    type@=keeplive/tick@=1439802131/

    这里,我写了一个函数来实现:
def keeplive(s):keeplive_info = 'type@=keeplive/tick@=' + str(int(time.time())) + '/\0'  # heartbeat infodata_length = len(info) + 8value = 689  # the type of information for client sending to the serverinfohead = int.to_bytes(data_length, 4, 'little') +int.to_bytes(data_length, 4, 'little') \
+ int.to_bytes(value, 4, 'little')while True:info = keeplive_info.encode('utf-8')  # transfer it into utf-8 as requesteds.send(infohead + info)time.sleep(45)

step3 弹幕获取
到此我们已经可以收到688房间返回的消息了!只需要利用socket库中的recv函数:

data = s.recv(1024)

但是你可能会发现它是这样的:
type@=chatmsg/rid@=58839/gid@=-9999/ct@=8/uid@=123456/nn@
=test/txt@=666/cid@=1111/ic@=icon/sahf@=0/level@=1/nl@=0/nc
@=0/cmt@=0/gt@=0/col@=0/rg@=0/pg@=0/dlv@=0/dc@=0/bdlv@
=0/gatin@=0/gatout@=0/chtin@=0/chtout@=0/repin@=0/repout@=
0/bnn@=test/bl@=0/brid@=58839/hc@=0/ol@=0/rev@=0/hl@=0/ifs
@=0/p2p@=0/el@=eid@AA=1@ASetp@AA=1@ASsc@AA=1@AS/

这和我们发送给服务器的消息是不是很像,这就是斗鱼独创的序列化消息格式,仔细阅读斗鱼给出的文档,发现这段消息中在’txt@=’ 后面是弹幕消息内容。那我们怎么提取出来呢?

此时就需要用到我们的第二项技能——正则表达式。没有接触过的话可以在菜鸟教程上简单学学,我们也只是需要用到很基础的部分。
在python中我们用re库来实现。为了匹配txt后面的弹幕内容,我们写出表达式:‘txt@=(.+?)/cid@’ 。 然后我们利用re中compile函数写出表达式。再利用findall函数进行全文匹配。代码如下:

data = s.recv(1024)
danmu = re.compile(b'txt@=(.+?)/cid@')
data_new = danmu.findall(data)

此时得到的还不是弹幕文本消息,我们还需要解码utf-8,再者,由于同一时间可能很多用户发弹幕,所以可能会同时收到多条弹幕消息,正则匹配出来的结果会是一个列表,此时我们需要做一些处理。

for i in range(0, len(data_new)):try:txt = data_new[0].decode(encoding='utf-8')  except AttributeError:print('Error')

到这里,得到的txt已经是解码成文本的弹幕消息了!我们已经完成了第一步。
后续我会继续更新如何同时爬取多个房间的弹幕消息。
说明
完整代码我会在第二部分里附上我在github上传的链接。

Python爬取斗鱼弹幕——多房间同时抓取实现(一)相关推荐

  1. python爬虫怎么爬同一个网站的多页数据-如何用Python爬数据?(一)网页抓取

    如何用Python爬数据?(一)网页抓取 你期待已久的Python网络数据爬虫教程来了.本文为你演示如何从网页里找到感兴趣的链接和说明文字,抓取并存储到Excel. 需求 我在公众号后台,经常可以收到 ...

  2. python爬网站数据实例-如何用Python爬数据?(一)网页抓取

    如何用Python爬数据?(一)网页抓取 你期待已久的Python网络数据爬虫教程来了.本文为你演示如何从网页里找到感兴趣的链接和说明文字,抓取并存储到Excel. 需求 我在公众号后台,经常可以收到 ...

  3. vs用Python爬数据?(一)网页抓取

    你期待已久的Python网络数据爬虫教程来了.本文为你演示如何从网页里找到感兴趣的链接和说明文字,抓取并存储到Excel. (由于微信公众号外部链接的限制,文中的部分链接可能无法正确打开.如有需要,请 ...

  4. python爬今日头条组图_python 爬虫抓取今日头条街拍图片

    1. 打开google浏览器,输入www.toutiao.com, 搜索街拍.html 2.打开开发者选项,network监看加载的xhr, 数据是ajax异步加载的,能够看到preview里面的da ...

  5. python爬取文本中的成语_python正则表达式抓取成语网站

    #anthor jiqunpeng #time 20121124 import urllib import re def getHtml(url): #从URL中读取html内容 page = url ...

  6. python爬斗鱼直播_Python爬虫:利用API实时爬取斗鱼弹幕

    原标题:Python爬虫:利用API实时爬取斗鱼弹幕 这些天一直想做一个斗鱼爬取弹幕,但是一直考试时间不够,而且这个斗鱼的api接口虽然开放了但是我在github上没有找到可以完美实现连接.我看了好多 ...

  7. python爬虫百度百科-python爬虫(一)_爬虫原理和数据抓取

    本篇将开始介绍Python原理,更多内容请参考:Python学习指南 为什么要做爬虫 著名的革命家.思想家.政治家.战略家.社会改革的主要领导人物马云曾经在2015年提到由IT转到DT,何谓DT,DT ...

  8. 小猪的Python学习之旅 —— 14.项目实战:抓取豆瓣音乐Top 250数据存到Excel中

    小猪的Python学习之旅 -- 14.项目实战:抓取豆瓣音乐Top 250数据存到Excel中 标签:Python 一句话概括本文: 利用Excel存储爬到的抓取豆瓣音乐Top 250数据信息,还有 ...

  9. Python爬虫采集抓取:Python3.x+Fiddler 采集抓取 APP 数据

    随着移动互联网的市场份额逐步扩大,手机 APP 已经占据我们的生活,以往的数据分析都借助于爬虫采集爬取网页数据进行分析,但是新兴的产品有的只有 APP,并没有网页端这对于想要提取数据的我们就遇到了些问 ...

  10. Python学习笔记——爬虫原理与Requests数据抓取

    目录 为什么要做网络爬虫? 通用爬虫和聚焦爬虫 HTTP和HTTPS 客户端HTTP请求 请求方法 HTTP请求主要分为Get和Post两种方法 常用的请求报头 1. Host (主机和端口号) 2. ...

最新文章

  1. C#调用浏览器的原理及实现浅析
  2. html里面执行js跳转页面,JS函数执行和指定跳转其他页面
  3. 从理论到实践,全方位认识HTTP/2
  4. 数据恢复错误卡住 linux,如何处理ORA-00376错误的恢复问题
  5. 计算机中减法的实现原理
  6. java B2B2C Springboot电子商城系统 (六) 分布式配置中心(Spring Cloud Config)
  7. mysql count 不等于_Mysql 不同的 count 区别
  8. uni-app微信小程序动态样式设置;微信小程序style行内式无效;微信小程序style行内式编译报错;微信小程序:style设置样式
  9. 开源商务智能软件Pentaho
  10. jvm面试 -- 谈谈ClassLoader ,ClassLoader的双亲委派机制 , loadClass和forName的区别
  11. MySQL中Checkpoint技术
  12. c ++中哈希表如何访问_C / C ++中的哈希表–完整的实现
  13. c语言函数库入门,C语言库函数
  14. 人工智能系统的形式化验证技术研究进展与趋势
  15. 三种不同的梯度下降算法和正则方程的线性回归预测结果对比
  16. java课程心得_Java课程的感想
  17. 计算机制作卡通插画,​电脑制作漫画有哪些方法?
  18. 智慧消防物联网落地案例(云南、福建、陕西) java 物联网智慧消防
  19. Keil MDK5工程文件不可修改(文件符号上带一个黄色的钥匙)
  20. 小黄的刷题之路(十六)——五行魔法(枚举/蛮力法)

热门文章

  1. android模拟器 adb 命令,安卓模拟器下 使用ADB命令
  2. TVB十大女星比美十大名花
  3. PT100铂电阻温度传感器详解
  4. java opennlp_java-使用openNLP maxent的训练模型
  5. 山西好点的计算机专科学校排名及分数线,2019山西十大专科学校排名及高考录取分数线...
  6. arm linux开发板自动配置IP地址
  7. iOS Orientation 屏幕旋转
  8. 厦门大学计算机专业录取分数线2019,厦门大学2019年各省录取分数线及各专业录取分数线...
  9. 苹果市值超过微软 重新成为全球市值最高上市公司
  10. 树莓派linux led字符设备驱动(互斥)