搜索
博主信息
博文 142
粉丝 5
评论 0
访问量 157063
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
获取斗鱼弹幕php版(原创)
php开发大牛
原创
1453人浏览过

根据github https://github.com/brucezz/DouyuCrawler 的java版,

无聊时用php重写了下,使用了swoole扩展,命令行下使用,如 php yu.php 265593 (265593为房间id), 代码如下:


实例

<?php
error_reporting(0);
$config = array(
    'roomId'=>$argv[1],//房间ID
    'dmServerIp'=>gethostbyname('openbarrage.douyutv.com'),
    'dmServerPort'=> 8601,//
    'groupId'=>-9999,//据说目前填-9999就行不须获取gid了
    'gidServerIp'=>'119.90.49.110',//119.90.49.111  119.90.49.104
    'gidServerPort'=>8046,//8020
);
 
function checkRoomOnline($html){
    $reg = '#"show_status":(\d*),#';
 
    preg_match($reg,$html,$match);
 
    if(count($match)==0){
        return -1;
    }
 
    return $match[1];
}
 
function packMsg($str){
    $length = pack('V', 4 + 4 + strlen($str) + 1);
    $code = $length;
    $magic = chr(0xb1).chr(0x02).chr(0x00).chr(0x00);
    $end = chr(0x00);
    return $length.$code.$magic.$str.$end;
}
 
 
function guid(){
    mt_srand((double)microtime()*10000);//optional for php 4.2.0 and up.
    $charid = strtoupper(md5(uniqid(rand(), true)));
    $hyphen = chr(45);// "-"
    $uuid = //chr(123)// "{"
         substr($charid, 0, 8).$hyphen
        .substr($charid, 8, 4).$hyphen
        .substr($charid,12, 4).$hyphen
        .substr($charid,16, 4).$hyphen
        .substr($charid,20,12);
       // .chr(125);// "}"
    return $uuid;
}
 
function getGidMsg(){
    global $config;
    $time = time();
    $uuid = str_replace('-','',guid());
    $msg = 'type@=loginreq/username@=/password@=/roomid@='.$config['roomId'].'/';
    $msg.='ct@=2/';
    $msg.='devid@='.$uuid.'/';
    $msg.='rt@='.$time;
    $msg.='vk@='.md5($time.'7oE9nPEG9xXV69phU31FYCLUagKeYtsF'.$uuid).'/';
    $msg.='ver@=20150929/';
    return $msg;
}
 
function msg_decode($str)
{
    if(empty($str)){
        return '';
    }
    $data = array();
    $key = $val = '';
    if ($str[strlen($str) - 1] !== '/') {
        $str .= '/';
    }
    for ($i = 0; $i < strlen($str); $i++) {
        if ($str[$i] == '/') {
            $data[$key] = $val;
            if(strpos($val,'@S/')!==false){
                $arr = explode('@S/',$val);
                $data[$key] = array();
                foreach($arr as $v){
                    $data[$key][] = msg_decode(decodeStr($v));
                }
            }
            $key=$val='';
        } else {
            if($str[$i]=='@'){
                $i++;
                if($str[$i]=='A'){
                    $val.='@';
                }else{
                    if($str[$i]=='S'){
                        $val.='/';
                    }else{
                        if($str[$i]=='='){
                            $key = $val;
                            $val='';
                        }
                    }
                }
            }else{
                $val.=$str[$i];
            }
 
        }
    }
 
    return $data;
}
 
function decodeStr($str){
    return str_replace('@S','/',str_replace('@A','@',$str));
}
 
function getServerConfig($html){
    global $config;
    $reg = '#server_config":"(.*?)"#';
 
 
    preg_match($reg,$html,$match);
 
    $t = urldecode($match[1]);
    $list = (json_decode($t,true));
    if(!empty($list)){
        $config['gidServerIp'] = $list[0]['ip'];
        $config['gidServerPort'] = $list[0]['port'];
        echo "get gidServerIp success ip:{$config['gidServerIp']},
        port:{$config['gidServerPort']}\r\n";
    }else{
        echo 'get gidServerIp error '."\r\n";
    }
 
}
 
function getGid(){
    global $config;
    $gid_client = new swoole_client(SWOOLE_SOCK_TCP);
    if (!$gid_client->connect($config['gidServerIp'], $config['gidServerPort'], -1))
    {
        exit("connect failed. Error: {$gid_client->errCode}\n");
    }
    $gid_client->send(packMsg(getGidMsg()));
    $str = $gid_client->recv();
    $str.= $gid_client->recv();
    print_r(msg_decode($str));
    $gid_client->close();
 
    preg_match_all('#gid@=(\d+)/#',decodeStr($str),$matchs);
 
    foreach($matchs as $gid){
        if(is_numeric($gid[0]) && $gid[0]>0){
            $config['groupId'] = $gid[0];
            break;
        }
    }
 
    preg_match('#@ASport@AA=(\d+)@#',$str,$ports);
    if($ports[1]>1){
        $config['dmServerPort'] = $ports[1];
    }
 
 
    echo 'gid is '.$config['groupId']."\r\n port is {$config['dmServerPort']}";
 
}
 
if(empty($argv[1])){
    die('参数有误,房间id不存在,Usage:php yu.php 265593'."\n");
}
 
$html = file_get_contents('http://www.douyutv.com/'.$config['roomId']);
 
$roomStatus = checkRoomOnline($html);
 
if($roomStatus==-1){
    die("房间{$config['roomId']}不存在\n");
}else if($roomStatus==2){
    echo "房间{$config['roomId']}还在直播路上\n";
}
 
getServerConfig($html);
 
//getGid();  //获取gid  //据说目前填-9999就行不须获取gid了
 
$client = new swoole_client(SWOOLE_SOCK_TCP,SWOOLE_SOCK_ASYNC);
$client->on("connect", function($cli) {
    global $config;
    $cli->send(packMsg(
    'type@=loginreq/username@=auto_KRLJbE8mZM/password@=1234567890123456/roomid@='
    .$config['roomId'].'/'));
    $cli->send(packMsg("type@=joingroup/rid@="
    .$config['roomId'] . "/gid@=".$config['groupId']."/"));
 
});
 
$client->on("receive", function($cli, $data){
    static $flag=true;
    $sub_data = substr($data,12,-1);
   //file_put_contents("msg.txt",$sub_data."\r\n",8);
   $dataArr = msg_decode($sub_data);
    if(empty($dataArr['type'])){
        echo '解析错误,原始数据:'.$data."\r\n";
        return;
    }
 
   switch($dataArr['type']){
        case "loginres":
            echo '已连接上服务器...'."\r\n";
            break;
        case "chatmsg":
            echo $dataArr['nn'].':'.$dataArr['txt']."\r\n";
            break;
        case "keeplive":
            //echo '心跳信息'."\r\n";
            break;
        case "dgb":
            empty($dataArr['gfcnt']) && $dataArr['gfcnt']=1;
            empty($dataArr['hits']) && $dataArr['hits']=1;
 
            echo "{$dataArr['nn']}送的礼物(gfid={$dataArr['gfid']}) 数量{$dataArr['gfcnt']},
            连击{$dataArr['hits']}\r\n";
            break;
        case "ranklist":
            echo '排名信息'."\r\n";
            break;
        case "uenter":
            echo "{$dataArr['nn']} 进入直播间\r\n";
            break;
        default:
            echo "未知消息type:{$dataArr['type']},data:$sub_data\r\n";
    }
 
    if($flag){
        swoole_timer_tick(45000,function() use ($cli){
            //echo date('Y-m-d H:i:s')."\r\n";
            $cli->send(packMsg("type@=keeplive/tick@=70/"));
        });
        $flag = false;
        echo "心跳进程启动\r\n";
    }
});
$client->on("error", function($cli){
    echo "Connect failed\n";
});
$client->on("close", function($cli){
    echo "Connection close\n";
});
//发起网络连接
$client->connect($config['dmServerIp'], $config['dmServerPort'], 1);

运行实例 »

点击 "运行实例" 按钮查看在线实例

只需修改房间号roomId即可,暂时没有检测房间是否开播了,下次可以加下这个小功能

运行效果图如下:

消息类型有好多种,这里暂时写了几种,可以研究继续完善下。

本博文版权归博主所有,转载请注明地址!如有侵权、违法,请联系admin@php.cn举报处理!
全部评论 文明上网理性发言,请遵守新闻评论服务协议
0条评论
作者最新博文
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号

  • 登录PHP中文网,和优秀的人一起学习!
    全站2000+教程免费学