越努力,越幸运

如何使用curl_multi来采集数据?

 1 year ago

1. 以前的用法

$url = ".....";
foreach($datas as $key => $val) {
    $results = $this->callCurl($url, $val);
}

这样采集是真的慢,如果需要循环个10万次,你能想象到要多久才能采集完吗?不敢想象,So使用curl_multi!!!下面把代码贴出来


2. curl_multi

function curlMulti(){
    $url = '...';
    $ch_list = array();
    $multi_ch = curl_multi_init();
    foreach ($datas as $key => $val){ // 这里开始循环处理你的数据
        $timeout = 10;
        $ch_list[$key] = curl_init($url); // $url:要采集的Url
        curl_setopt($ch_list[$key], CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch_list[$key], CURLOPT_CONNECTTIMEOUT, $timeout);
        curl_setopt($ch_list[$key], CURLOPT_POSTFIELDS, $val);
        curl_multi_add_handle($multi_ch, $ch_list[$key]);
    }
    $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);
        }
    }
    $result = array();
    // 获取http返回的结果
    foreach ($ch_list as $k => $ch) {
        $result[$k] = curl_multi_getcontent($ch);
        curl_multi_remove_handle($multi_ch, $ch);
        curl_close($ch);
    }
    curl_multi_close($multi_ch);
    return $result;
}

你可以发现,当你把上面这些代码copy之后运行,是没有问题的,但是我要提示一下就是,如果采集的时间执行很长并且PHP版本为5.3.10+,会提示Warning: (null)(): 10 is not a valid cURL handle resource in Unknown on line 0这样的Warning,那么要修改成如下的代码:


while ($active && $mrc == CURLM_OK) {
    if (curl_multi_select($multi_ch) != -1) { //阻塞直到cURL批处理连接中有活动连接。
        usleep(1000);
    }
    do {
        $mrc = curl_multi_exec($multi_ch, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);
}

当然,去php官网看手册查询curl_multi_init时在User Contributed Notes中第一个就可以看到这个 好了,分享的就是这个,还有就是没有找到curl_multi的配图,只能展示一下我的画画能力了,希望可以帮助到大家!
Notice:由本人亲自测试,如果采集的个数>=2万,那么采集的结果为空,如果采集的个数<=1.5万,那么采集是没问题的!