1

我正在尝试同时curl_multi_*获取多个(大约 50 个)URL,因为连续这样做需要很长时间。但是,我在执行时收到以下错误消息curl_multi_add_handle

警告:(null)(): 10 不是第0未知中的有效 cURL 句柄资源

这是代码:

//create the multiple cURL handle
$mh = curl_multi_init();

// Loop over pages and get set the URL to the cURL queue
foreach ($htmltogetlist as $source) {

    [...]

    // Get a cURL handle of the current URL
    $urls[$id]['ch'] = $this->_getCurlHandle($urls[$id]['url']);

    // Success
    if (gettype($urls[$id]['ch']) == 'resource' && get_resource_type($urls[$id]['ch']) == 'curl') {
        curl_multi_add_handle($mh, $urls[$id]['ch']); // << Produces error
    }
}

并且$this->_getCurlHandle有:

// Set cURL handle
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_ENCODING , "gzip");
curl_setopt($ch, CURLOPT_REFERER, $url);
curl_setopt($ch, CURLOPT_USERAGENT, 'PHP');
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);

return $ch;

奇怪的是这$urls[$id]['ch']是一个有效resource的类型curl,但我不能将它添加到$mh文件中,错误unknownline 0. 实际上,我什至可以执行句柄并从中获得正确的响应,所以我肯定它是有效的。我只是无法将其添加到$mh.

$content = curl_exec($urls[$id]['ch']);
$response = curl_getinfo($urls[$id]['ch']);
print_r($response); // Works

我知道 cURL 适用于多次传输。例如,下面的代码(本质上做同样的事情)有效。我也确定不是导致问题的 URL 数量,因为在将数据库查询限制为 1 时出现相同的错误:

$ch1 = curl_init();
$ch2 = curl_init();

// set URL and other appropriate options
curl_setopt($ch1, CURLOPT_URL, "http://lxr.php.net/");
curl_setopt($ch2, CURLOPT_URL, "http://www.php.net/");

curl_setopt($ch1,CURLOPT_ENCODING , "gzip");
curl_setopt($ch1, CURLOPT_REFERER, $url);
curl_setopt($ch1, CURLOPT_USERAGENT, 'PHP');
curl_setopt($ch1, CURLOPT_HEADER, true);
curl_setopt($ch1, CURLOPT_AUTOREFERER, true);
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch1, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch1, CURLOPT_TIMEOUT, 10);

curl_setopt($ch2,CURLOPT_ENCODING , "gzip");
curl_setopt($ch2, CURLOPT_REFERER, $url);
curl_setopt($ch2, CURLOPT_USERAGENT, 'PHP');
curl_setopt($ch2, CURLOPT_HEADER, true);
curl_setopt($ch2, CURLOPT_AUTOREFERER, true);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch2, CURLOPT_TIMEOUT, 10);

//create the multiple cURL handle
$mh = curl_multi_init();

//add the two handles
curl_multi_add_handle($mh,$ch1); // Works
curl_multi_add_handle($mh,$ch2); // Works
4

2 回答 2

3

我检查了 Richard 在上面的评论中提到的问题 #61141,pierrick 给出的解决方案确实为我解决了这个错误。

这是基本的多卷曲执行设置,如 PHP 手册中所示:

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

但是,正确的设置是这样的:

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

如果curl_multi_select返回 -1,则暂停脚本一会儿,然后继续运行curl_mutli_exec

更多详情:https ://bugs.php.net/bug.php?id=61141

于 2014-01-27T14:05:02.443 回答
0

我在 OSX 上使用 PHP 5.3.23,curl 7.30.0 遇到了这个问题。

修复是确保所有 curl_init() 在 curl_multi_init() 之前被调用;

从未在其他平台(即 Linux)上看到过这种情况

于 2013-08-14T16:54:19.400 回答