PHP/Yii2批量检测http代理状态

175 阅读1分钟

前言

因为项目需要检测代理的状态和获取代理后的ip和地理位置,耗时等信息

过程

方法传值$ proxy()是数组存放代理连接信息,

$url我传的是自己项目里面检测ip的接口,访问我的接口然后拿到地理位置还有耗时一举两得

$mh是在在外面初始化cURL批处理句柄

话不多说直接上代码

		$url = 'http://******';
        //额,我测试本地环境一次检测超过两百个左右就不行了,所以分批一次200
        for ($i=0;count($proxy)>0;$i++){
            //初始化cURL批处理句柄
            $mh = curl_multi_init();
            //一次拿两百个去检测
            $checkProxy = array_splice($proxy,0,200);
            //方法
            $this->batchCheckProxy($checkProxy,$url,$mh);
        }
        
public function batchCheckProxy($proxy,$url,$mh)
    {
        $conn = array();
        foreach ($proxy as $key => $value){
            $conn[$key]['curl'] = curl_init(); //初始化各个子连接
            $conn[$key]['id'] = $value['id']; //顺便加个ip的id进去,方便后面修改他的状态
            //设置url和相应的选项
            curl_setopt ($conn[$key]['curl'], CURLOPT_CONNECTTIMEOUT, 1); //设置在发起连接前等待的最长时间,因为不设置是无限等待所以还是设置一下
            curl_setopt ($conn[$key]['curl'], CURLOPT_RETURNTRANSFER, 1); //将curl_exec()获取的信息以文件流的形式返回,而不是直接输出
            curl_setopt ($conn[$key]['curl'], CURLOPT_TIMEOUT, 1); //cURL允许执行的最长秒数
            curl_setopt($conn[$key]['curl'], CURLOPT_PROXY, $value['ip']); //使用代理ip
            curl_setopt($conn[$key]['curl'], CURLOPT_PROXYPORT, $value['port']); //代理ip的端口
            curl_setopt($conn[$key]['curl'], CURLOPT_PROXYUSERPWD, $value['user'].':'.$value['password']); //检测的http代理是带账密的,不需要的同学把这一行去掉即可
            curl_setopt($conn[$key]['curl'], CURLOPT_URL, $url); //需要获取的URL地址
            curl_setopt($conn[$key]['curl'], CURLOPT_HEADER, 0);
            curl_setopt($conn[$key]['curl'], CURLOPT_RETURNTRANSFER, 1);; //不直接输出到浏览器,而是返回字符串
            curl_multi_add_handle($mh, $conn[$key]['curl']); //增加 ch 句柄到批处理会话mh
        }

        $active = null; //连接数

        //防卡死写法:执行批处理句柄
        do {
            $mrc = curl_multi_exec($mh, $active);
            //这个循环的目的是尽可能地读写,直到无法继续读写为止
            //返回 CURLM_CALL_MULTI_PERFORM 表示还能继续向网络读写
        } while($mrc == CURLM_CALL_MULTI_PERFORM);

        while ($active && $mrc == CURLM_OK) {
            if (curl_multi_select($mh) != -1) {
                do {
                    $mrc = curl_multi_exec($mh, $active);
                } while ($mrc == CURLM_CALL_MULTI_PERFORM);
            }
        }

        foreach ($conn as $k => $ch) {
            $result = curl_multi_getcontent($ch['curl']); //返回获取的输出的文本流
            $getInfo = curl_getinfo($ch['curl']);
            curl_multi_remove_handle($mh,$ch['curl']); //从给定的批处理句柄mh中移除ch句柄
            curl_close($conn[$k]['curl']); //关闭cURL 会话并且释放所有资源
            //返回的文本不是string0就说明连上
            if (empty($result)) {
                IpLibraryModel::updateInfo(['status'=>0],['id'=>$ch['id']]);
            }else{
                $ipData = json_decode($result,true);
                IpLibraryModel::updateInfo([
                    'status' => 1,
                    'country' => $ipData['countryCode'],
                    'region' => $ipData['region'],
                    'city' => $ipData['city'],
                    'ping' => $getInfo['total_time'],
                    'ext' => $result
                ],['id'=>$ch['id']]);
            }
        }
        curl_multi_close($mh); //关闭一组cURL句柄
    }