curl 多线程下载

curl 多线程下载

  • 批量下载图片:
            set_time_limit(0);
            function getMicrotime() {
            list ($usec, $sec) = explode(" ", microtime());
            return ((float) $usec + (float) $sec);
            }
            $stime = getMicrotime();//开始时间
            /**
            * curl 多线程下载图片
            *
            * @param array $array 并行网址
            * @param int $timeout 超时时间
            * @return mix
            */
            function Curl_down_image($array,$timeout='15')
            {
                $res = array();
                $mh = curl_multi_init();//创建多个curl语柄
                foreach($array as $k=>$url)
                {
                    $conn[$k]=curl_init($url);//创建cURL资源
                    curl_setopt($conn[$k], CURLOPT_TIMEOUT, $timeout);//设置超时时间
                    curl_setopt($conn[$k], CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
                    curl_setopt($conn[$k], CURLOPT_MAXREDIRS, 7);//HTTp定向级别 ,7最高
                    curl_setopt($conn[$k], CURLOPT_HEADER, false);//这里不要header,加块效率
                    curl_setopt($conn[$k], CURLOPT_FOLLOWLOCATION, 1); // 302 redirect
                    curl_setopt($conn[$k], CURLOPT_RETURNTRANSFER,1);//要求结果保存到字符串中(1)还是输出到屏幕上
                    curl_setopt($conn[$k], CURLOPT_HTTPGET, true);
                    curl_multi_add_handle ($mh,$conn[$k]);
                }
                $active = null;
                /*执行批处理句柄,防止死循环耗死cpu*/
                //当正在接受数据时
                do {
                $mrc = curl_multi_exec($mh,$active);//当无数据,active=true
                } while ($mrc == CURLM_CALL_MULTI_PERFORM);
                //当无数据时或请求暂停时,active=true
                while ($active && $mrc == CURLM_OK) {
                    if (curl_multi_select($mh) != -1) {
                        do {
                        $mrc = curl_multi_exec($mh, $active);
                        } while ($mrc == CURLM_CALL_MULTI_PERFORM);
                    }
                }
    
                /*curl获取的输出的文本流*/
                foreach ($array as $k => $url) {
                    if(!curl_errno($conn[$k])){
                    //curl解析正常
                    $data[$k]=curl_multi_getcontent($conn[$k]);//数据保存到array中
                    $header[$k]=curl_getinfo($conn[$k]);//返回http头信息
                    curl_multi_remove_handle($mh,$conn[$k]); //释放资源
                    }else{
                    //curl解析失败操作
                    }
                }
                unset($array,$conn);
                curl_multi_close($mh);
                return $data;
            }
            //图片地址数组集
            $array = array(
            'http://img842.ph.126.net/PJbIezP4bNn4WcG-vgTNwQ==/875105702595657274.jpg',
            'http://img842.ph.126.net/PJbIezP4bNn4WcG-vgTNwQ==/875105702595657274.jpg'
            );
            //根据$data数组中保存的图片文本流数据生成相应图片
            $data = Curl_down_image($array,$timeout='105');
            foreach ((array)$data as $k=>$v){
                if($v !=''){ //图片数据存在
                    $basename = getMicrotime().".jpg";//保存为jpg格式的文件
                    $fname = realpath('.').'/'.$basename;
                    file_put_contents($fname, $v);
                }else{
                 //图片数据不存在操作
                }
            }
            unset($data);
            //时间统计
            $etime = getMicrotime();//结束时间
            echo ($etime-$stime)."";
            
  •         curl 多线程下载流程:
            第一步:调用curl_multi_init
            第二步:循环调用curl_multi_add_handle
            这一步需要注意的是,curl_multi_add_handle的第二个参数是由curl_init而来的子handle。
            第三步:持续调用curl_multi_exec
            第四步:根据需要循环调用curl_multi_getcontent获取结果
            第五步:调用curl_multi_remove_handle,并为每个字handle调用curl_close
            第六步:调用curl_multi_close
            实例扩展:
            可以下载多张图片或下载多个页面,
            将下载的数据文本流全部保存至数组中,
            然后将其生成图片或页面数据
    
            可优化部分:
            curl获取的输出的文本流部分可以优化,获取后直接执行想要对数据的操作,这样可以减少很多内存的使用,执行时间更短
            
  • 理解:CURLOPT_RETURNTRANSFER
            curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
            如果成功只将结果返回,不自动输出任何内容
            如果失败返回FALSE
            curl_setopt($ch, CURLOPT_RETURNTRANSFER,0); 或着不使用这个选项:
            如果成功只返回TRUE,自动输出返回的内容
            如果失败返回FALSE
            
  • 关于do while的那段解释:
            do {
                $mrc = curl_multi_exec($mh,$active);
            } while ($mrc == CURLM_CALL_MULTI_PERFORM);
            while ($active and  $mrc == CURLM_OK) {
                if (curl_multi_select($mh) != -1) {
                    do {
                    $mrc = curl_multi_exec($mh, $active);
                    } while ($mrc == CURLM_CALL_MULTI_PERFORM);
                }
            }
        /*
        因为$active要等全部url数据接受完毕才变成false,所以这里用到了curl_multi_exec的返回值判断是否还有数据,当有数据的时候就不停调用curl_multi_exec,暂时没有数据就进入select阶段,新数据一来就可以被唤醒继续执行。这里的好处就是CPU的无谓消耗没有了。
        另外:还有一些细节的地方可能有时候要遇到:
        控制每一个请求的超时时间,在curl_multi_add_handle之前通过curl_setopt去做:
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        判断是否超时了或者其他错误,在curl_multi_getcontent之前用:curl_error($conn[$i]);
        */
        
  • 单张远程图片下载:
            /**
            * curl 远程单张图片下载
            * @param str $url 远程单张图url
            * @param str $fname 本地存储文件src
            * @param int $timeout 超时时间
            * @return $int 返回写入到文件内数据的字节数
            */
            function curl_down_image($url,$fname,$timeout='15')
            {
                $ch=curl_init($url);//创建cURL资源
                curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);//设置超时时间
                curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
                curl_setopt($ch, CURLOPT_MAXREDIRS, 7);//HTTp定向级别 ,7最高
                curl_setopt($ch, CURLOPT_HEADER, false);//这里不要header,加块效率
                curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 302 redirect
                curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);//要求结果为字符串且输出到屏幕上
                curl_setopt($ch, CURLOPT_HTTPGET, true);
    
                //如果 CURLOPT_RETURNTRANSFER选项被设置,函数执行成功时会返回执行的结果,失败时返回 FALSE
                $data = curl_exec($ch);
                if(!$data) die('无法获取图片');
                $int = file_put_contents($fname, $data);
                return $int;
            }
            function getMicrotime() {
                list ($usec, $sec) = explode(" ", microtime());
                return ((float) $usec + (float) $sec);
            }
            $url = 'http://img842.ph.126.net/PJbIezP4bNn4WcG-vgTNwQ==/875105702595657274.jpg';
            $basename = getMicrotime().".jpg";//保存为jpg格式的文件
            $fname = realpath('.').'/'.$basename;
            $int = curl_down_image($url,$fname);
            print_r($int);
            
  • API调用中常用的 curl和file_get_contents方法使用
            /**
            * @description curl method,post方法params字符串的位置不同于get
            *
            * @access public
            * @param mixed $url
            * @param string $params
            * @param string $method
            * @param mixed $connectTimeout
            * @param mixed $readTimeout
            * @return json
            */
            public function httpCall($url ,$params = '',$method = 'get', $connectTimeout = self::CONNECT_TIMEOUT,$readTimeout = self::READ_TIMEOUT) {
                if ($this->conf['print_request_params']) {
                    var_dump('url:'.$url,'params:'.$params);
                }
                $result = "";
                if (function_exists('curl_init')) {
                    $timeout = $connectTimeout + $readTimeout;
                    // Use CURL if installed...
                    $ch = curl_init();
                    curl_setopt($ch, CURLOPT_URL, $url);
                    if(strtolower($method)==='post'){
                    curl_setopt($ch, CURLOPT_POST, 1);
                    curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
                    }
                    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connectTimeout);
                    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                    curl_setopt($ch, CURLOPT_USERAGENT, '56.com API PHP5 Client 1.1 (curl) ' . phpversion());
                    $result = curl_exec($ch);
                } else{
                    if(isset($params) and $params){
                    $url = $url."?".http_build_query($params);
                    }
                    // Non-CURL based version...
                    $ctx = stream_context_create(
                        array(
                            'http' => array(
                            'timeout' => 5 /** 设置一个超时时间,单位为秒 */
                            )
                        )
                    );
                    $result = file_get_contents($url, 0, $ctx);
                }
                return $result;
            }
            

    尤其要注意file_get_contents的超时使用方法

相关文章
  1. * 暂无相关文章
本站版权
1、本站所有主题由该文章作者发表,该文章作者与尘埃享有文章相关版权
2、其他单位或个人使用、转载或引用本文时必须同时征得该文章作者和尘埃的同意
3、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
4、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
5、原文链接:
二维码
Posted in curl, php, 编程语言
Comments are closed.