offline-ant

斗鱼直播弹幕爬虫

斗鱼弹幕服务器和一般的网页内容不一样,通过socket通信连接。斗鱼规定了弹幕的协议。

过程如下:

向斗鱼弹幕服务器发起连接房间请求,服务器回应;发起进入弹幕组请求,服务器回应;然后服务器持续发送弹幕消息,服务器要求每45s发送一次心跳包。

具体协议内容请搜索斗鱼弹幕服务协议。

我找了8个房间,获取房间id(少数房间id不在地址栏显示,一般网页标签中会显示主播和房间id),设置了主播名(自己随便写,主要用来给文件起名)。

每个房间的爬虫都是一个进程,开启8个进程后,主进程结束。由于跨进程通讯很麻烦,每次循环进程会寻找当前目录是否存在‘运行.txt’,删除该文件,子进程即可停止。下次运行之前手动创建该文件即可。

源代码如下:

# -*- coding: utf-8 -*-
"""
Created on Thu Apr 26 15:15:38 2018

@author: 蚂蚁不在线

多进程模式,每个进程负责一个直播间的弹幕。输入房间id号,和网址。一般两者相同。少数房间网址为字母
"""
import socket
import time
import datetime
import requests
from bs4 import BeautifulSoup
import multiprocessing
import sys
import re
import os
####发送信息
def sendmsg(client,msgstr):
    msg=msgstr.encode(\'utf-8\')
    data_length=len(msg)+8
    code=689
    msg=int.to_bytes(data_length,4,\'little\')*2+ b\'\xb1\x02\x00\x00\'+msg
    ##十进制转换为二进制
    sent=0
    while sent<len(msg):
        tn=client.send(msg[sent:])
        sent=sent+tn

def keeplive(t,t0,client):
    if int(time.time())>t0:
        msg=\'type@=keeplive/tick@=\' + str(int(time.time())) + \'/\x00\'
        sendmsg(client,msg)
        print(\'程序已启动\',int(time.time())-t,\'s\')
        return t0+40
    else:
        return t0
       
def start(roomid,zbname):
    ####连接弹幕服务器
    client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    host=socket.gethostbyname("openbarrage.douyutv.com")
    port=8601
    client.connect((host,port))
    ####申请加入房间,用户名密码随意
    msg=\'type@=loginreq/username@=蚂蚁不在线/password@=就看看/roomid@={}/\x00\'.format(roomid)
    sendmsg(client,msg)
    client.recv(1024)
    ####加入全弹幕讨论组
    msg_more=\'type@=joingroup/rid@=%s/gid@=-9999/\x00\'%roomid
    sendmsg(client,msg_more)
    client.recv(1024)
    ####下次发送心跳包的时间
    t=int(time.time())
    t0=int(time.time())+40
    flg=True
    while flg:
        flg=os.path.exists(\'运行.txt\')
        data=client.recv(1024)
        mlist=re.findall(b\'type@=(.+?)/\x00\',data)
        for i in mlist:
            msgd={}
            j=b\'type@=\'+i
            m=j.split(b\'/\')
            for n0 in m:
                n=n0.split(b\'@=\')
                try:
                    msgd[n[0].decode()]=n[1].replace(b\'@S\',b\'/\').replace(b\'@A\',b\'@\').decode()
                except:
                    pass
            #### 发言信息记录
            if msgd[\'type\']==\'chatmsg\':
                try:
                    f=open(\'%s.txt\'%(roomid+\'_\'+zbname),\'a\',encoding=\'utf-8\')
                    f.write( msgd[\'type\']+\',\' \
                             +msgd[\'uid\']+\',\' \
                             +msgd[\'nn\']+\',\' \
                             +msgd[\'txt\']+\',\' \
                             +msgd[\'level\']+\',\' \
                             +datetime.datetime.now().strftime(\'%Y-%m-%d %H:%M:%S\') \
                             +\'\n\')
                    f.close()
                except:
                    pass
        t0=keeplive(t,t0,client)
if __name__==\'__main__\':
    roomid=[\'102411\',\'606118\',\'1126960\',\'475252\',\'846805\',\'288016\',\'12313\',\'71017\']
    zbname=[\'神超\',\'大司马\',\'余小c\',\'孙悟空\',\'赏金术士\',\'lpl\',\'叶音符\',\'冯提莫\']
    for i in range(len(roomid)):
        p1=multiprocessing.Process(target=start,args=(roomid[i],zbname[i],))
        p1.start()

 

分类:

技术点:

相关文章:

  • 2021-12-26
  • 2021-11-13
  • 2021-11-17
  • 2021-12-25
  • 2021-12-25
  • 2021-04-12
  • 2021-12-25
  • 2021-12-09
猜你喜欢
  • 2021-12-25
  • 2021-10-13
  • 2021-09-01
  • 2021-12-25
  • 2021-10-03
  • 2021-12-25
相关资源
相似解决方案