我试图使用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
}
}
CCD_ 3具有
// 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']
是curl
类型的有效resource
,但我无法将其添加到$mh
中,并且错误在line 0
上的文件unknown
中。事实上,我甚至可以执行句柄并从中得到正确的响应,所以我确信它是有效的。我只是无法将其添加到$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
我检查了Richard在上面评论中提到的问题#61141,pierrick给出的解决方案确实为我修复了错误。
这是基本的多卷曲exec设置,如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
我在使用PHP 5.3.23、curl 7.30.0的OSX上遇到了这种情况。
修复是确保在curl_multi_init()之前调用所有curl_init();
从未在其他平台(如Linux)上看到过这种情况