php curl_multi 携带cookie访问如何提升速度?

新手上路,请多包涵

问题描述

工作中需要curl一个链接,需要登录后才能返回关键字段。之前是直接curl,然后用保存后的cookie文件访问,但是每页只返回20条结果,而且太慢,每一次curl大概1s-1.3s,而且如果结果太多(最多50页),curl就会超时。

问题出现的环境背景及自己尝试过哪些方法

后面限制了页数,即如果返回页数大于5页只让其curl 5次,这样虽然不至于太慢了,但是结果也少了。后面了解了curl_multi ,自己也试了,如果不用cookie这个多进程确实快了很多,原来curl 25次 大概28秒,多进程之后大概2秒,但是一旦加上cookie访问,速度变得和普通curl一样了,甚至略慢一点。不知道是不是我哪里写的不对,附上代码

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)
这个是普通curl
if($arr0['pcount']>1){

        $arr[0]['total']['pcount']=$arr[0]['total']['pcount']>10?10:$arr[0]['total']['pcount'];
        for ($i=2;$i<=$arr[0]['total']['pcount'];$i++){
            //带上cookie文件,访问
            $send_url='http://******.cn/ashx/GetList.ashx?pageIndex='.$i.'&keys='.htmlspecialchars($tj).'&Lx=3';
            $ch = curl_init($send_url);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            //curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file);
            curl_setopt($ch, CURLOPT_COOKIE, $cookie);
            $contents[] = curl_exec($ch);
            curl_close($ch);
        }
        $arr=array();
        foreach($contents as $k=>$v){
            $arr[$k]=(json_decode($v,true));
        }
    }
    
    
    //这个是调用curl_multi的
    
 if($arr[0]['total']['pcount']>1){
        $chArr=[];
        for($i=2;$i<=$arr[0]['total']['pcount'];$i++){
            $chArr[$i] = "http://*****.cn/ashx/GetList.ashx?pageIndex=$i&keys=".htmlspecialchars($tj)."&Lx=3";
        }
        $result = $this->postMulti($chArr,$cookie);
        $arr = array_merge($arr,$result);
    }
    
    //这个是curl_multi
    public static function postMulti($chArr,$cookie)
{
    $max_request = count($chArr);
    $ch_list = array();
    $multi_ch = curl_multi_init();
    for ($i = 2;$i <= $max_request+1;$i++) {
        $ch_list[$i] = curl_init($chArr[$i]);

        curl_setopt($ch_list[$i], CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch_list[$i], CURLOPT_COOKIE,$cookie) ;   //如果注释此行返回结果则很快
        curl_setopt($ch_list[$i], CURLOPT_TIMEOUT, 30);
        //curl_setopt($ch_list[$i], CURLOPT_COOKIEFILE, $cookie_file);
        curl_multi_add_handle($multi_ch, $ch_list[$i]);
    }

    $active = null;
    do {
        $mrc = curl_multi_exec($multi_ch, $active); //处理在栈中的每一个句柄。无论该句柄需要读取或写入数据都可调用此方法。
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    //Note:
    //该函数仅返回关于整个批处理栈相关的错误。即使返回 CURLM_OK 时单个传输仍可能有问题。
    while ($active && $mrc == CURLM_OK) {
        if (curl_multi_select($multi_ch) != -1) {
            //阻塞直到cURL批处理连接中有活动连接。
            do {
                $mrc = curl_multi_exec($multi_ch, $active);
            } while ($mrc == CURLM_CALL_MULTI_PERFORM);
        }
    }
    //获取http返回的结果
    $true_request = 0;
    foreach ($ch_list as $k => $ch) {
        $result[] = curl_multi_getcontent($ch);
        curl_multi_remove_handle($multi_ch,$ch);
        curl_close($ch);
        if ($result == 1) {
            $true_request += 1;
        }
    }
    curl_multi_close($multi_ch);
    foreach($result as $k=>$v){
        $arr[$k]=(json_decode($v,true));
    }
    return $arr;
}

你期待的结果是什么?实际看到的错误信息又是什么?

阅读 1.7k
1 个回答
  1. 抓住你要解决的问题的本质,不要局限在某种套路里面
  2. 你要解决的问题是如何爬取数据,遇到的阻力是效率不够,具体指单位时间内爬取的数据太少
  3. 这时候要做的是提升效率而不是一直研究curl
  4. 解决思路:降低时间增大请求并发数
  5. 降低时间:本身接口慢还是你调用的方法有问题,你可以记一下每一步操作消耗的时间来排查这个问题
  6. 增大请求并发数:curl_multi是模拟多线程,你可以创建多个进程来提高并发

开个脑洞:

  1. 能不能不读接口,直接读库
  2. 试试python的scrapy
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题