2024年Python爬虫:斗鱼TV(1)

文章详细描述了如何通过分析斗鱼直播的JS脚本获取主播信息和弹幕认证服务器,以及利用Socket消息进行用户认证和接收弹幕的过程。重点涉及了Socket通信协议和发送特定消息的步骤,以及Python在学习和实践中的应用.
摘要由CSDN通过智能技术生成

1.2.房间信息和弹幕认证服务器获取

首先我们拿随便一个主播房间来说,比如,qiuri

Ta的房间链接分为两种

对这个主播房间页面请求,正常,所有的有用信息都不是放在HTML中渲染出来,而是有一条放在HTML中内置的JS脚本中,这是为了减少服务器渲染HTML的压力?可是渲染放在JS里面不也一样需要渲染?(不明白)总之,就是程序先加载没有具体数据填充页面,然后JS更新数据。

内置的两段JS脚本,JS脚本中有两个变量,该变量很容易转换成JSON数据,也就是两段JSON数据,一个是关于主播的个人信息,另一个是关于弹幕认证服务器的列表(该列表中的任意一个服务器均可以认证,但每一次请求主播页面得到的认证服务器列表都不一样)

Sc

Screen Shot 2016-02-09 at 1.01.51 PM.png

Screen Shot 2016-02-09 at 12.44.01 PM.png

通过这步,我们就拿到了主播的信息以及弹幕服务器的认证地址,端口。

1.3.发送Socket消息的流程简介

我们通过抓包,分析那一大坨数据包,可以确定以下通过以下的流程便可以获取弹幕消息。(分析过程比较繁琐)

首先建立两个Socket。一个用于认证(@danmu_auth_socket),另一个用户获取弹幕(@danmu_client)。

  • 步骤1: @danmu_auth_socket 发送消息登陆,获取消息1解析出匿名用户的用户名,再获取消息2解析出gid

  • 步骤2: @danmu_auth_socket 发送qrl消息,获取两个没有什么用的消息

  • 步骤3: @danmu_auth_socket 发送keeplive消息

  • 步骤4: @danmu_socket 发送伪登陆消息(所有匿名用户都一样只需要输入步骤一中用户名就行了,因为认证已经在上面做过了)

  • 步骤5: @danmu_socket 发送join_group消息需要步骤一中国的gid

  • 步骤6: @danmu_socket 不断的recv消息就可以获取弹幕消息了

后面会详细解释

2.1.消息Socket消息格式以及发送一条消息

既然是发消息,那么每条消息总是有些格式的。

斗鱼的消息格式大致如下:

douyutveachmsg.png

每一条消息并遵循下面的格式:

1.通信协议长度,后四个部分的长度,四个字节

2.第二部分与第一部分一样

3.请求代码,发送给斗鱼的话,内容为0xb1,0x02, 斗鱼返回的代码为0xb2,0x02

4.发送内容

5.末尾字节

-- encoding : utf-8 -- class Message # 向斗鱼发送的消息 # 1.通信协议长度,后四个部分的长度,四个字节 # 2.第二部分与第一部分一样 # 3.请求代码,发送给斗鱼的话,内容为0xb1,0x02, 斗鱼返回的代码为0xb2,0x02 # 4.发送内容 # 5.末尾字节 #pack(‘c*’)是字节数组转字符串的一种诡异的转化方式 def initialize(content) @length = [content.size + 9,0x00,0x00,0x00].pack(‘c*’) @code = @length.dup @magic = [0xb1,0x02,0x00,0x00].pack(‘c*’) @content = content @end = [0x00].pack(‘c*’) end def to_s @length + @code + @magic + @content + @end end end

经过封装,我们仅仅关注那些可见的字符串,也就是Content部分就可以了。

content部分,也就是发送消息的内容,在文章后面将会详解。

开启两个Socket,一个用户认证,另一个用于弹幕的获取。

用于用户弹幕认证的,是2.1中所说的认证服务器列表中任意一个。挑选出来一组ip和端口

@danmu_auth_socket = TCPSocket.new @auth_dst_ip,@auth_dst_port

用户获取弹幕的只要为

danmu.douyutv.com:8601 danmu.douyutv.com:8602 danmu.douyutv.com:12601 danmu.douyutv.com:12602

四组域名:端口均可以作为如下的DANMU_SERVER和PORT

@danmu_socket = TCPSocket.new DANMU_SERVER,DANMU_PORT

发送一条消息只需如此

data = "type@=loginreq/username@="+@username+"/password@=1234567890123456/roomid@=" + @room_id.to_s + "/" all_data = message(data) @danmu_socket.write all_data

把需要传输的字符串放进去就好了.

接下来,我们需处理上面说的六个步骤

2.2.发送消息详细流程之步骤一

发送消息内容为:

type@=loginreq/username@=/ct@=0/password@=/roomid@=156277/devid@=DF9E4515E0EE766B39F8D8A2E928BB7C/rt@=1453795822/vk@=4fc6e613fc650a058757331ed6c8a619/ver@=20150929/

我们需要注意的内容如下:

type 表示消息的类型登陆消息为loginreq username 不需要,请求登陆以后系统会自动的返回对应的游客账号。 ct 不清楚什么意思,默认为0并无影响 password 不需要 roomid 房间的id devid 为设备标识,无所谓,所以我们使用随机的UUID生成 rt 应该是runtime吧,时间戳 vk 为时间戳+“7oE9nPEG9xXV69phU31FYCLUagKeYtsF”+devid的字符串拼接结果的MD5值(这个是参考了一篇文章,关于这一处我也不大明白怎么探究出来的) ver 默认

通过这一步,我们可以获取两条消息,并从消息中使用正则表达式获取对应的用户名以及gid

str = @danmu_auth_socket.recv(4000) @username= str[/\/username@=(.+)\/nickname/,1] str = @danmu_auth_socket.recv(4000) @gid = str[/\/gid@=(\d+)\//,1]

2.3.发送消息详细流程之步骤二

发送的消息内容为

“type@=qrl/rid@=” + @room_id.to_s + “/”

无需多说,类型为qrl,rid为roomid,直接发送这条消息就好。返回的两条消息也没有什么价值。

data = "type@=qrl/rid@=" + @room_id.to_s + "/" msg = message(data) @danmu_auth_socket.write msg str = @danmu_auth_socket.recv(4000) str = @danmu_auth_socket.recv(4000)

2.4.发送消息详细流程之步骤三

发送的消息内容为

“type@=keeplive/tick@=” + timestamp + “/vbw@=0/k@=19beba41da8ac2b4c7895a66cab81e23/”

直接发送。无太大意义。

data = "type@=keeplive/tick@=" + timestamp + "/vbw@=0/k@=19beba41da8ac2b4c7895a66cab81e23/" msg = message(data) @danmu_auth_socket.write msg str = @danmu_auth_socket.recv(4000)

前三步,也就是2.2-2.3-2.4三步骤,也就是使用@danmu_auth_socket 完成获取username和gid的重要步骤。获取这两个字段以后,也就完成了它存在的使命。

接下来的就是@danmu_socket获取弹幕的时候了!

2.5.发送消息详细流程之步骤四

消息内容为:“type@=loginreq/username@=”+@username+“/password@=1234567890123456/roomid@=” + @room_id.to_s + “/”

和上面2.2中略有不同。但是,需要注意的是

username 为2.2中所得到的username password 的值得变化

data = "type@=loginreq/username@="+@username+"/password@=1234567890123456/roomid@=" + @room_id.to_s + "/" all_data = message(data) @danmu_socket.write all_data str = @danmu_socket.recv(4000)

2.6.发送消息详细流程之步骤五

接下来就是完成认证的最后一步了,join_group的消息内容为

“type@=joingroup/rid@=” + @room_id.to_s + “/gid@=”+@gid+“/”

gid为2.2中所得到的gid。

data = "type@=joingroup/rid@=" + @room_id.to_s + "/gid@="+@gid+"/" msg = message(data) @danmu_socket.write msg

2.7.发送消息详细流程之步骤六

获取弹幕,并且打印出来。

danmu_data = @danmu_socket.recv(4000) type = danmu_data[danmu_data.index("type@=")..-3] puts type.gsub('sui','').gsub('@S','/').gsub('@A=',':').gsub('@=',':').split('/')

后三步,则是@danmu_socket 获取弹幕的步骤。

于是,通过这些步骤,就可以完成了简单的danmu的核心代码,接下来的步骤就是完善,重构这些代码了。

总结

痛点一,至今还没有解决rtmp地址的获取

(1)Python所有方向的学习路线(新版)

这是我花了几天的时间去把Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

最近我才对这些路线做了一下新的更新,知识体系更全面了。

在这里插入图片描述

(2)Python学习视频

包含了Python入门、爬虫、数据分析和web开发的学习视频,总共100多个,虽然没有那么全面,但是对于入门来说是没问题的,学完这些之后,你可以按照我上面的学习路线去网上找其他的知识资源进行进阶。

在这里插入图片描述

(3)100多个练手项目

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了,只是里面的项目比较多,水平也是参差不齐,大家可以挑自己能做的项目去练练。

在这里插入图片描述

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里无偿获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
解之后运用它们,这时候练手项目就很适合了,只是里面的项目比较多,水平也是参差不齐,大家可以挑自己能做的项目去练练。

在这里插入图片描述

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里无偿获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值