教学之友,学习之友。

站长教学网

当前位置: 站长教学网 > 网站编程 > PHP教程 >

php使用curl实现多线程采集下载文件或图片

时间:2013-12-04 15:06来源:未知 作者:ken 点击:

 

直接贴出代码,可自行包装成一个类:

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_close($conn[$k]);//关闭语柄
            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

实例扩展:
可以下载多张图片或下载多个页面,
将下载的数据文本流全部保存至数组中,
然后将其生成图片或页面数据

可优化部分:站长教学网 eduyo.com
curl获取的输出的文本流部分可以优化,获取后直接执行想要对数据的操作,这样可以减少很多内存的使用,执行时间更短
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
如果成功只将结果返回,不自动输出任何内容
如果失败返回FALSE

curl_setopt($ch, CURLOPT_RETURNTRANSFER,0); 或着不使用这个选项:
如果成功只返回TRUE,自动输出返回的内容
如果失败返回FALSE
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);
/**
* @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;
}
(责任编辑:ken)
TAG标签: php curl 多线程 采集
顶一下
(3)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
注册登录:不允许匿名留言,登录后留言无需输入验证码。
栏目列表
最新内容