目录
回复内容:
首页 后端开发 Python教程 如何获取斗鱼直播间的弹幕信息?

如何获取斗鱼直播间的弹幕信息?

Jun 06, 2016 pm 04:11 PM

如何获取如图红色框中的弹幕信息呢?想做一些基于弹幕信息的二次开发。


如何获取斗鱼直播间的弹幕信息?

回复内容:

在参考顶楼的回答和评论后,正确获取到了弹幕,来回报下社会,代码已经放在Github上了! douyu/danmu.cc at master · fishioon/douyu · GitHub
代码是C写的,本来用的python,感觉C更好用(在处理数据的时候)。

比较喜欢看yyf的dota2直播,但是最近yyf经常吹B,说有网友弹幕问“枫哥枫哥,你的XX怎么这么厉害啊”,水友们纷纷表示不信,所以就想着把弹幕爬下来,同时还有那些说赢了直播吃翔的,我通通都要记录下来!!!

回答正题,那我们该如何弄清楚这个协议呢?
弹幕属于实时消息,第一反应应该用websocket实现,打开chrome,F12,websocket中竟然找不到!那估计是通过Flash实现了。前端不熟,找了半天也没找到JS实现代码,只好祭出wireshark来分析了。
看了顶楼的提示,在wireshark中查看端口为8601的数据包,如下图所示。
如何获取斗鱼直播间的弹幕信息?
前三个数据包就是TCP的三次握手啦,复习下;接着我们看第四个数据包,如下图所示
如何获取斗鱼直播间的弹幕信息?一般来说通信协议设计“内容长度”+“内容”,我们来看tcp数据包内容,前四个字节为0x59 = 5*16+9 = 89,再看整个数据包长度为93,正好符合长度+内容,差不多我们可以确定通信协议如下:
struct {
int len; //数据包长度
int code; //经抓包发现该字段一直与len字段一致
int magic; //不知道啥意思,发现请求都是0x2b1, 返回都是0x2b2
char content[0]; //消息具体内容
}
从图中的内容中可以看到:
1. 登录弹幕服务器: "type@=loginreq/username@%s=/password@=%s/roomid@=%d/ct@=2/",输入自己的账号密码(经测试发现,账号密码随便填都能成功),要看的房间id,如yyf的房间id为52428
通过socket发送上面的内容后,你回收到这样的一条数据,格式与发送格式一样:
“type@=loginres/userid@=0/roomgroup@=0/pg@=0/sessionid@=0/username@=/nickname@=/live_stat@=0/is_illegal@=0/npv@=0/best_dlev@=0/cur_lev@=0/”,没发现有啥有用的数据。
2. 收到上面的消息后,这时候要加入一个组,格式如下:
"type@=joingroup/rid@=%d/gid@=%d/",rid就是房间id,要注意的问题来了:
gid应该是group id,登录不同房间该id都不一样,每次我都是抓包来查看该id是多少,有知情人告诉我吗?(一楼评论中也提到这个问题)
发送上面的消息后,我们就可以安心的接收数据了,然后从数据中提取我们想要的就可以了,其中很多数据都不懂啥意思。
最后我们看下yyf房间的弹幕哈!(节奏带的飞起)
如何获取斗鱼直播间的弹幕信息? Update 20160214 : 更新Python和Ruby客户端(请大家不要问我为什么情人节这一天为什么闲着没事更新代码)
Update 20160220 : 更新Python客户端,增加直播视频的Live获取,以及Mac平台下面的Mplayer的视频播放.代码均放在Github上面. GitHub - twocucao/danmu.fm: douyutv danmu 斗鱼TV 弹幕助手

由于zhihu没有法子贴动态图,那只好移步到我的博客一看了.(看博客之前记得点赞╮(╯_╰)╭)

Python程序员如何优雅的看斗鱼TV

===================优雅的看斗鱼TV的分割线==================================

-1.如果不想看长文,直接使用.则在安装好Python3或者Ruby2.0以上版本.

<span class="c">#安装Python客户端</span>
pip3 install danmu.fm

<span class="c"># 比如主播的直播间</span>
danmu.fm http://www.douyutv.com/16789
<span class="c">#或者</span>
danmu.fm 16789
<span class="c">#安装Ruby客户端</span>
gem install danmu
<span class="c">#使用</span>
danmu douyu <span class="o">[</span>room_id/url<span class="o">]</span>
<span class="c">#比如</span>
danmu douyu qiuri
danmu douyu http://www.douyutv.com/13861
登录后复制
[多图预警]

Update:2016.1.16
总结在博客里:抓取斗鱼直播弹幕
Github 项目地址:brucezz/DouyuCrawler
欢迎去提各种 issue & PR (代码水平不高)...


/********************************************************************************************/
Update:2016.1.14
最近几天会把 Java 项目发布到 Github 上面,大家提提意见 :)

/********************************************************************************************/
之前看到这个问题,感觉挺好玩的,就研究了下。
照着前面的思路,抓包分析。其他几位的回答,基本能抓到弹幕数据了,但是其中一个参数gid,需要手动抓包得到。我也查看了浏览器加载的js文件,没看到相关线索。最后看到排名第一的回答评论里有人说可以通过请求页面里server_config的ip。
然后我就顺着这条线索探索下去了。
具体过程如下:

先获取到直播页面中的server_config相关字段,发现是经过urlencode的。
如何获取斗鱼直播间的弹幕信息?然后进行urldecode,得到json数据,再格式化一下,
UrlEncode编码/UrlDecode解码
JSON在线编辑
就变成这样:
<span class="p">[{</span><span class="nt">"ip"</span><span class="p">:</span><span class="s2">"119.90.49.107"</span><span class="p">,</span><span class="nt">"port"</span><span class="p">:</span><span class="s2">"8035"</span><span class="p">},{</span><span class="nt">"ip"</span><span class="p">:</span><span class="s2">"119.90.49.102"</span><span class="p">,</span><span class="nt">"port"</span><span class="p">:</span><span class="s2">"8008"</span><span class="p">},{</span><span class="nt">"ip"</span><span class="p">:</span><span class="s2">"119.90.49.110"</span><span class="p">,</span><span class="nt">"port"</span><span class="p">:</span><span class="s2">"8050"</span><span class="p">},{</span><span class="nt">"ip"</span><span class="p">:</span><span class="s2">"119.90.49.104"</span><span class="p">,</span><span class="nt">"port"</span><span class="p">:</span><span class="s2">"8020"</span><span class="p">},{</span><span class="nt">"ip"</span><span class="p">:</span><span class="s2">"119.90.49.107"</span><span class="p">,</span><span class="nt">"port"</span><span class="p">:</span><span class="s2">"8034"</span><span class="p">},{</span><span class="nt">"ip"</span><span class="p">:</span><span class="s2">"119.90.49.92"</span><span class="p">,</span><span class="nt">"port"</span><span class="p">:</span><span class="s2">"8059"</span><span class="p">},{</span><span class="nt">"ip"</span><span class="p">:</span><span class="s2">"119.90.49.95"</span><span class="p">,</span><span class="nt">"port"</span><span class="p">:</span><span class="s2">"8071"</span><span class="p">},{</span><span class="nt">"ip"</span><span class="p">:</span><span class="s2">"119.90.49.101"</span><span class="p">,</span><span class="nt">"port"</span><span class="p">:</span><span class="s2">"8001"</span><span class="p">},{</span><span class="nt">"ip"</span><span class="p">:</span><span class="s2">"119.90.49.93"</span><span class="p">,</span><span class="nt">"port"</span><span class="p">:</span><span class="s2">"8063"</span><span class="p">},{</span><span class="nt">"ip"</span><span class="p">:</span><span class="s2">"119.90.49.91"</span><span class="p">,</span><span class="nt">"port"</span><span class="p">:</span><span class="s2">"8053"</span><span class="p">}]</span>
登录后复制
##################20160325更新##########################
最近斗鱼修改了弹幕格式,大概长这个样子
<span class="n">b</span><span class="s">'</span><span class="se">\x81\x00\x00\x00\x81\x00\x00\x00\xb2\x02\x00\x00</span><span class="s">type@=chatmsg/rid@=9401/uid@=12635840/nn@=</span><span class="se">\xe8\xb6\x85\xe8\xb6\x8a\xe7\xa5\x9e\xe7\x9a\x84</span><span class="s">boy/txt@=</span><span class="se">\xe6\x89\x93\xe8\x84\xb8\xe5\x90\xa7</span><span class="s">/cid@=20e4e3fe427e410c67c5010000000000/level@=5/</span><span class="se">\x00</span><span class="s">'</span>
登录后复制
优雅的获取弹幕和看弹幕:

如何获取斗鱼直播间的弹幕信息?

随便抓了100个房间大概半小时。
优雅的抓出那些说“屎尿屁”的“精神周星驰”:
(那么大家都发现了,疯狂说这些一般都是20级以下的人。斗鱼要到20级大概是充值3000-4000左右好像。那么你们明白什么了吗)
如何获取斗鱼直播间的弹幕信息?如何获取斗鱼直播间的弹幕信息?如何获取斗鱼直播间的弹幕信息?如何获取斗鱼直播间的弹幕信息?

最后还有更好玩的(大家来找壕,看看壕都喜欢去什么房间):
如何获取斗鱼直播间的弹幕信息?






















当然编程的方式也要优雅:Python

至于方法,最高赞已经很干净清晰了的解答了,我这里做小小补充。

其实不需要那么多工序,用socket直接3个命令就可以了:

下面伪代码:

client_danmu = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#在客户端开启心跳维护
client_danmu.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) 


#官方弹幕服务器'openbarrage.douyutv.com'
SERVER = socket.gethostbyname('openbarrage.douyutv.com')
PORT = 8601

client_danmu.connect((SERVER,PORT))
client_danmu.settimeout(2)    #记得设置延迟,不然卡着recv

#这里发的要处理下发送内容,用最高赞的方法获取封包格式就好了
封包1 = 'type@=loginreq/username@=visitor1234567/password@=/roomid@=房间号/'
#登陆弹幕服务器
client_danmu.send(封包1)

封包2 =  'type@=joingroup/rid@=房间号/gid@=-9999/'
#加入弹幕组,这里要注意,gid就是弹幕组号。-9999是斗鱼开放的第三方获取弹幕的组别。是能获取所有弹幕的。因为有些主播动辄几十万人,那弹幕量如果都发给所有用户,那卡死用户事小,斗鱼自己流量事大啊。所以一般都是分组发送,所以你平时在浏览器看的并不一定是所有弹幕。用-9999这个组别号是可以获取所有的
client_danmu.send(封包2)

#这里开始就是用while循环获取弹幕了,记得大概每30秒发一个心跳包过去。
封包3 =  'type@=mrkl/'
client_danmu.send(封包3)
登录后复制
那我说说?
是这样的,斗鱼的弹幕信息有个自己的服务器
danmu.douyutv.com 可以抓包看到,他通过TCP连接到斗鱼弹幕服务器,然后获取的信息,那么想要对它进行二次开发只需要模拟用户连接并登入弹幕服务器即可。
 弹幕连接 OnConn
(program):1  弹幕 UserLogin [type@=loginreq/username@=xxxx/password@=1234567890123456/roomid@=58718/]
(program):1 弹幕 网络数据 [type@=loginres/userid@=0/roomgroup@=67108896/pg@=0/sessionid@=6/username@=/nickname@=/is_signined@=432003648/signin_count@=32756/s@=% ô/live_stat@=125387584/npv@=32756/]
(program):1 弹幕登录成功
VM160:1 弹幕分组 [type@=joingroup/rid@=58718/gid@=0/]
2VM171:1 FMPNetStream连接状态:NetStream.Buffer.Full
VM175:1 弹幕 网络数据 [type@=userenter/rid@=58718/gid@=0/userinfo@=id@A=4295897@Sname@A=auto_DJUziSYiJo@Snick@A=芙苏不语丶怪力乱神@Srg@A=1@Spg@A=1@Srt@A=1416480352@Sbg@A=0@Sweight@A=12800@Sstrength@A=51800@Scps_id@A=0@Sps@A=1@Sver@A=0@Sm_deserve_lev@A=0@S/]
VM176:1 新用户进入信息: [id@=4295897/name@=auto_DJUziSYiJo/nick@=芙苏不语丶怪力乱神/rg@=1/bg@=0/pg@=1/rt@=1416480352/weight@=12800/strength@=51800/cps_id@=0/]
登录后复制
我记录了下抓取弹幕的流程,可以参考下。
地址: 斗鱼弹幕抓取
代码:github.com/ndrlslz/Douy 既然没人发nodejs版,那我就发一个吧
<span class="kd">var</span> <span class="nx">net</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'net'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">uuid</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'node-uuid'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">md5</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'md5'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'request'</span><span class="p">);</span>

<span class="kd">var</span> <span class="nx">HOST</span> <span class="o">=</span> <span class="s1">'danmu.douyutv.com'</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">PORT</span> <span class="o">=</span> <span class="mi">8602</span><span class="p">;</span>

<span class="kd">function</span> <span class="nx">send</span><span class="p">(</span><span class="nx">socket</span><span class="p">,</span> <span class="nx">payload</span><span class="p">)</span>
<span class="p">{</span>	
	<span class="kd">var</span> <span class="nx">data</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Buffer</span><span class="p">(</span><span class="mi">4</span> <span class="o">+</span> <span class="mi">4</span> <span class="o">+</span> <span class="mi">4</span> <span class="o">+</span> <span class="nx">payload</span><span class="p">.</span><span class="nx">length</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
	<span class="nx">data</span><span class="p">.</span><span class="nx">writeInt32LE</span><span class="p">(</span><span class="mi">4</span> <span class="o">+</span> <span class="mi">4</span> <span class="o">+</span> <span class="nx">payload</span><span class="p">.</span><span class="nx">length</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="c1">//length</span>
	<span class="nx">data</span><span class="p">.</span><span class="nx">writeInt32LE</span><span class="p">(</span><span class="mi">4</span> <span class="o">+</span> <span class="mi">4</span> <span class="o">+</span> <span class="nx">payload</span><span class="p">.</span><span class="nx">length</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span> <span class="c1">//code</span>
	<span class="nx">data</span><span class="p">.</span><span class="nx">writeInt32LE</span><span class="p">(</span><span class="mh">0x000002b1</span><span class="p">,</span> <span class="mi">8</span><span class="p">);</span> <span class="c1">//magic</span>
	<span class="nx">data</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">payload</span><span class="p">,</span> <span class="mi">12</span><span class="p">);</span> <span class="c1">//payload</span>
	<span class="nx">data</span><span class="p">.</span><span class="nx">writeInt8</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">4</span> <span class="o">+</span> <span class="mi">4</span> <span class="o">+</span> <span class="mi">4</span> <span class="o">+</span> <span class="nx">payload</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span> <span class="c1">//end of string</span>
	<span class="nx">socket</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nx">login</span><span class="p">(</span><span class="nx">socket</span><span class="p">,</span> <span class="nx">roomid</span><span class="p">,</span> <span class="nx">user</span><span class="p">,</span> <span class="nx">password</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kd">var</span> <span class="nx">req</span> <span class="o">=</span> <span class="s1">'type@=loginreq/username@='</span> <span class="o">+</span> <span class="nx">user</span> <span class="o">+</span> <span class="s1">'/password@='</span> <span class="o">+</span> <span class="nx">password</span> <span class="o">+</span> <span class="s1">'/roomid@='</span> <span class="o">+</span> <span class="nx">roomid</span><span class="p">;</span>
	<span class="nx">send</span><span class="p">(</span><span class="nx">socket</span><span class="p">,</span> <span class="nx">req</span><span class="p">);</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nx">getGroupServer</span><span class="p">(</span><span class="nx">roomid</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span>
<span class="p">{</span>
	<span class="nx">request</span><span class="p">({</span><span class="nx">uri</span><span class="o">:</span><span class="s1">'http://www.douyutv.com/'</span> <span class="o">+</span> <span class="nx">roomid</span><span class="p">},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">resp</span><span class="p">,</span> <span class="nx">body</span><span class="p">)</span> <span class="p">{</span>
		<span class="kd">var</span> <span class="nx">server_config</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">body</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="sr">/room_args = (.*?)\}\;/g</span><span class="p">)[</span><span class="mi">0</span><span class="p">].</span><span class="nx">replace</span><span class="p">(</span><span class="s1">'room_args = '</span><span class="p">,</span> <span class="s1">''</span><span class="p">).</span><span class="nx">replace</span><span class="p">(</span><span class="s1">';'</span><span class="p">,</span> <span class="s1">''</span><span class="p">));</span>
		<span class="nx">server_config</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">unescape</span><span class="p">(</span><span class="nx">server_config</span><span class="p">[</span><span class="s1">'server_config'</span><span class="p">]));</span>
		<span class="nx">callback</span><span class="p">(</span><span class="nx">server_config</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">ip</span><span class="p">,</span> <span class="nx">server_config</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">port</span><span class="p">);</span>
	<span class="p">});</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nx">getGroupId</span><span class="p">(</span><span class="nx">roomid</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kd">var</span> <span class="nx">rt</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">now</span><span class="p">;</span>
	<span class="kd">var</span> <span class="nx">devid</span> <span class="o">=</span> <span class="nx">uuid</span><span class="p">.</span><span class="nx">v4</span><span class="p">().</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/-/g</span><span class="p">,</span> <span class="s1">''</span><span class="p">);</span>
	<span class="kd">var</span> <span class="nx">vk</span> <span class="o">=</span> <span class="nx">md5</span><span class="p">(</span><span class="nx">rt</span> <span class="o">+</span> <span class="s1">'7oE9nPEG9xXV69phU31FYCLUagKeYtsF'</span> <span class="o">+</span> <span class="nx">devid</span><span class="p">)</span>
	<span class="kd">var</span> <span class="nx">req</span> <span class="o">=</span> <span class="s1">'type@=loginreq/username@=/password@=/roomid@='</span> <span class="o">+</span> 
		<span class="nx">roomid</span> <span class="o">+</span> <span class="s1">'/ct@=0/vk@='</span> <span class="o">+</span> <span class="nx">vk</span> <span class="o">+</span> <span class="s1">'/devid@='</span> <span class="o">+</span> 
		<span class="nx">devid</span> <span class="o">+</span> <span class="s1">'/rt@='</span> <span class="o">+</span> <span class="nx">rt</span> <span class="o">+</span> <span class="s1">'/ver=@20150929/'</span><span class="p">;</span>
	
	<span class="nx">getGroupServer</span><span class="p">(</span><span class="nx">roomid</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">server</span><span class="p">,</span> <span class="nx">port</span><span class="p">)</span> <span class="p">{</span>
		<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">'group server: '</span> <span class="o">+</span> <span class="nx">server</span> <span class="o">+</span> <span class="s1">':'</span> <span class="o">+</span> <span class="nx">port</span><span class="p">);</span>
		<span class="kd">var</span> <span class="nx">socket</span> <span class="o">=</span> <span class="nx">net</span><span class="p">.</span><span class="nx">connect</span><span class="p">(</span><span class="nx">port</span><span class="p">,</span> <span class="nx">server</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
			<span class="nx">send</span><span class="p">(</span><span class="nx">socket</span><span class="p">,</span> <span class="nx">req</span><span class="p">);</span>
		<span class="p">});</span>
		
		<span class="nx">socket</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
			<span class="k">if</span> <span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'type@=setmsggroup'</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
				<span class="kd">var</span> <span class="nx">gid</span> <span class="o">=</span> <span class="nx">data</span><span class="p">.</span><span class="nx">toString</span><span class="p">().</span><span class="nx">match</span><span class="p">(</span><span class="sr">/gid@=(.*?)\//g</span><span class="p">)[</span><span class="mi">0</span><span class="p">].</span><span class="nx">replace</span><span class="p">(</span><span class="s1">'gid@='</span><span class="p">,</span> <span class="s1">''</span><span class="p">);</span>
				<span class="nx">gid</span> <span class="o">=</span> <span class="nx">gid</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">gid</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
				<span class="nx">socket</span><span class="p">.</span><span class="nx">destroy</span><span class="p">();</span>
				<span class="nx">callback</span><span class="p">(</span><span class="nx">gid</span><span class="p">);</span>
			<span class="p">}</span>
		<span class="p">});</span>	
	<span class="p">});</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nx">monitorRoom</span><span class="p">(</span><span class="nx">roomid</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kd">var</span> <span class="nx">socket</span> <span class="o">=</span> <span class="nx">net</span><span class="p">.</span><span class="nx">connect</span><span class="p">(</span><span class="nx">PORT</span><span class="p">,</span> <span class="nx">HOST</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
		<span class="nx">login</span><span class="p">(</span><span class="nx">socket</span><span class="p">,</span> <span class="s1">'visitor1234567'</span><span class="p">,</span> <span class="s1">'1234567890123456'</span><span class="p">);</span>
	<span class="p">});</span>
	
	<span class="nx">setInterval</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
		<span class="nx">send</span><span class="p">(</span><span class="nx">socket</span><span class="p">,</span> <span class="s1">'type@=keeplive/tick@=70/'</span><span class="p">);</span> <span class="c1">//send keep alive message repeatly</span>
	<span class="p">},</span> <span class="mi">50000</span><span class="p">);</span>
	
	<span class="nx">socket</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
		<span class="c1">//data is a Buffer here</span>
		<span class="k">if</span> <span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'type@=loginres'</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
			<span class="nx">getGroupId</span><span class="p">(</span><span class="nx">roomid</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">gid</span><span class="p">)</span> <span class="p">{</span>
				<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">'gid of room['</span> <span class="o">+</span> <span class="nx">roomid</span> <span class="o">+</span><span class="s1">'] is '</span> <span class="o">+</span> <span class="nx">gid</span><span class="p">)</span>
				<span class="nx">send</span><span class="p">(</span><span class="nx">socket</span><span class="p">,</span> <span class="s1">'type@=joingroup/rid@='</span> <span class="o">+</span> <span class="nx">roomid</span> <span class="o">+</span> <span class="s1">'/gid@='</span> <span class="o">+</span> <span class="nx">gid</span> <span class="o">+</span> <span class="s1">'/'</span><span class="p">);</span>
			<span class="p">});</span>
		<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'type@=chatmessage'</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
			<span class="kd">var</span> <span class="nx">msg</span> <span class="o">=</span> <span class="nx">data</span><span class="p">.</span><span class="nx">toString</span><span class="p">();</span>
			<span class="kd">var</span> <span class="nx">snick</span> <span class="o">=</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="sr">/snick@=(.*?)\//g</span><span class="p">)[</span><span class="mi">0</span><span class="p">].</span><span class="nx">replace</span><span class="p">(</span><span class="s1">'snick@='</span><span class="p">,</span> <span class="s1">''</span><span class="p">);</span>
			<span class="kd">var</span> <span class="nx">content</span> <span class="o">=</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="sr">/content@=(.*?)\//g</span><span class="p">)[</span><span class="mi">0</span><span class="p">].</span><span class="nx">replace</span><span class="p">(</span><span class="s1">'content@='</span><span class="p">,</span> <span class="s1">''</span><span class="p">);</span>
			
			<span class="nx">snick</span> <span class="o">=</span> <span class="nx">snick</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">snick</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
			<span class="nx">content</span> <span class="o">=</span> <span class="nx">content</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">content</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
			<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">snick</span> <span class="o">+</span> <span class="s1">': '</span> <span class="o">+</span> <span class="nx">content</span><span class="p">);</span><span class="c1">// 弹幕</span>
		<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'type@=userenter'</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span> <span class="o">||</span>
			<span class="nx">data</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'type@=keeplive'</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span> <span class="o">||</span>
			<span class="nx">data</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'type@=dgn/gfid@=131'</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span> <span class="o">||</span>
			<span class="nx">data</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'type@=blackres'</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span> <span class="o">||</span>
			<span class="nx">data</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'type@=dgn/gfid@=129'</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span> <span class="o">||</span> 
			<span class="nx">data</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'type@=upgrade'</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span> <span class="o">||</span>
			<span class="nx">data</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'type@=ranklist'</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span> <span class="o">||</span>
			<span class="nx">data</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'type@=onlinegift'</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
			<span class="c1">//没用的消息</span>
		<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'type@=spbc'</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
			<span class="kd">var</span> <span class="nx">drid</span> <span class="o">=</span> <span class="nx">data</span><span class="p">.</span><span class="nx">toString</span><span class="p">().</span><span class="nx">match</span><span class="p">(</span><span class="sr">/drid@=(.*?)\//g</span><span class="p">)[</span><span class="mi">0</span><span class="p">].</span><span class="nx">replace</span><span class="p">(</span><span class="s1">'drid@='</span><span class="p">,</span> <span class="s1">''</span><span class="p">);</span>
			<span class="nx">drid</span> <span class="o">=</span> <span class="nx">drid</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">drid</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
			
			<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">'rocket! room id:'</span> <span class="o">+</span> <span class="nx">drid</span><span class="p">);</span>
		<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
			<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span>	<span class="c1">//在这里显示其它类型的消息</span>
		<span class="p">}</span>
	<span class="p">});</span>
<span class="p">}</span>

<span class="nx">monitorRoom</span><span class="p">(</span><span class="s1">'<这里填roomid>'</span><span class="p">);</span>
登录后复制
以前我们是做视频聊天站的。2014年8月-9月我们一个月的时间抄了一个斗鱼,没错是整个站。开始的时候由于内容上的高度重合,比如蜡笔小新、RM等,房间也没有人气,我将斗鱼某房间的弹幕扒下来转播到对应内容的房间中,并过滤掉一些关键字,足以以假乱真。虽然平台最终半死不活,且『技术本身并不可耻』,然而还是匿了。

技术核心我看大家都没答到一点,就是反编译flash播放器,因为所有与socket相关的实现都在flash里,反编译出源码后的逻辑、协议,一目了然,然后用python实现出来,很简单,不上码了。

这问题应该是纯技术交流吧,我这么想。 斗鱼已经开放第三方接口了,获取弹幕的流程变得简单了许多:
《斗鱼弹幕服务器第三方接入协议v1.4.1》发布信息 斗鱼开发者论坛
以下为大概流程
第三方接入弹幕服务器:
IP 地址:openbarrage.douyutv.com 端口:8601
1.客户端向服务器端发送登录请求,格式为;
type@=loginreq/roomid@=****/
登录后复制
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
2 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

我如何使用美丽的汤来解析HTML? 我如何使用美丽的汤来解析HTML? Mar 10, 2025 pm 06:54 PM

本文解释了如何使用美丽的汤库来解析html。 它详细介绍了常见方法,例如find(),find_all(),select()和get_text(),以用于数据提取,处理不同的HTML结构和错误以及替代方案(SEL)

Python中的数学模块:统计 Python中的数学模块:统计 Mar 09, 2025 am 11:40 AM

Python的statistics模块提供强大的数据统计分析功能,帮助我们快速理解数据整体特征,例如生物统计学和商业分析等领域。无需逐个查看数据点,只需查看均值或方差等统计量,即可发现原始数据中可能被忽略的趋势和特征,并更轻松、有效地比较大型数据集。 本教程将介绍如何计算平均值和衡量数据集的离散程度。除非另有说明,本模块中的所有函数都支持使用mean()函数计算平均值,而非简单的求和平均。 也可使用浮点数。 import random import statistics from fracti

python对象的序列化和避难所化:第1部分 python对象的序列化和避难所化:第1部分 Mar 08, 2025 am 09:39 AM

Python 对象的序列化和反序列化是任何非平凡程序的关键方面。如果您将某些内容保存到 Python 文件中,如果您读取配置文件,或者如果您响应 HTTP 请求,您都会进行对象序列化和反序列化。 从某种意义上说,序列化和反序列化是世界上最无聊的事情。谁会在乎所有这些格式和协议?您想持久化或流式传输一些 Python 对象,并在以后完整地取回它们。 这是一种在概念层面上看待世界的好方法。但是,在实际层面上,您选择的序列化方案、格式或协议可能会决定程序运行的速度、安全性、维护状态的自由度以及与其他系

如何使用TensorFlow或Pytorch进行深度学习? 如何使用TensorFlow或Pytorch进行深度学习? Mar 10, 2025 pm 06:52 PM

本文比较了Tensorflow和Pytorch的深度学习。 它详细介绍了所涉及的步骤:数据准备,模型构建,培训,评估和部署。 框架之间的关键差异,特别是关于计算刻度的

哪些流行的Python库及其用途? 哪些流行的Python库及其用途? Mar 21, 2025 pm 06:46 PM

本文讨论了诸如Numpy,Pandas,Matplotlib,Scikit-Learn,Tensorflow,Tensorflow,Django,Blask和请求等流行的Python库,并详细介绍了它们在科学计算,数据分析,可视化,机器学习,网络开发和H中的用途

如何使用Python创建命令行接口(CLI)? 如何使用Python创建命令行接口(CLI)? Mar 10, 2025 pm 06:48 PM

本文指导Python开发人员构建命令行界面(CLIS)。 它使用Typer,Click和ArgParse等库详细介绍,强调输入/输出处理,并促进用户友好的设计模式,以提高CLI可用性。

用美丽的汤在Python中刮擦网页:搜索和DOM修改 用美丽的汤在Python中刮擦网页:搜索和DOM修改 Mar 08, 2025 am 10:36 AM

该教程建立在先前对美丽汤的介绍基础上,重点是简单的树导航之外的DOM操纵。 我们将探索有效的搜索方法和技术,以修改HTML结构。 一种常见的DOM搜索方法是EX

如何解决Linux终端中查看Python版本时遇到的权限问题? 如何解决Linux终端中查看Python版本时遇到的权限问题? Apr 01, 2025 pm 05:09 PM

Linux终端中查看Python版本时遇到权限问题的解决方法当你在Linux终端中尝试查看Python的版本时,输入python...

See all articles