我一直在撞墙撞了几个小时,试图理解为什么cURL的cookie jar文件是空的,当我试着读它时。我刚刚发现,如果我两次调用curl_close()
而不是一次,我的代码就可以正常工作,但是,我想知道这是否是一个cURL错误。必须在句柄关闭并且可以读取cookie jar之前调用curl_close()两次。这是一个错误?
下面是一个例子:
curl_close($chInfo['handle']);
var_dump(is_resource($chInfo['handle']));
输出boolean true
。换句话说,尽管事实上我叫curl_close()
,但手柄并未关闭。
我的下一个想法是,可能需要一段时间才能关闭句柄,所以我在curl_close()
调用后尝试使用sleep()
几秒钟,但没有任何区别。
出于绝望,我试图复制curl_close()
线,像这样:
curl_close($chInfo['handle']);
curl_close($chInfo['handle']);
var_dump(is_resource($chInfo['handle']));
输出boolean false
,这意味着关闭句柄,并且我能够从cookie jar文件读取(卷曲写当手柄关闭时,Cookie将文件保存到文件中)。
那么这里发生了什么?这看起来很像一个bug!编辑:我不能发布我的完整代码(你不会想要阅读它!),但这里是一个简化的例子(请注意,在这个例子中只有一个url被提取,而在我的真实代码中curl_multi
被利用来同时获取多个网址):
$curlOptions = array(
CURLOPT_USERAGENT => 'Mozilla/5.001 (windows; U; NT4.0; en-US; rv:1.0) Gecko/25250101',
CURLOPT_CONNECTTIMEOUT => 5, // the number of seconds to wait while trying to connect.
CURLOPT_TIMEOUT => 5, // the maximum number of seconds to allow cURL functions to execute.
CURLOPT_RETURNTRANSFER => 1, // TRUE to return the transfer as a string of the return value of curl_exec() instead of outputting it out directly.
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_MAXREDIRS => 10,
CURLOPT_AUTOREFERER => 1,
CURLOPT_REFERER => null,
CURLOPT_POST => 0, // GET request by default
CURLOPT_POSTFIELDS => '', // no POST data by default
CURLINFO_HEADER_OUT => 1, // allows the request header to be retrieved
CURLOPT_HEADER => 1, // returns the response header along with the page body
CURLOPT_URL => 'http://www.example.com/',
CURLOPT_COOKIEJAR => __DIR__ . '/cookie.txt',
CURLOPT_COOKIEFILE => __DIR__ . '/cookie.txt'
);
$ch = curl_init();
curl_setopt_array($ch, $curlOptions); // set the options for this handle
$mh = curl_multi_init();
$responses = array();
curl_multi_add_handle($mh, $ch); // add the handle to the curl_multi object
do
{
$result = curl_multi_exec($mh, $running);
$activity = curl_multi_select($mh); // blocks until there's activity on the curl_multi connection (in which case it returns a number > 0), or until 1 sec has passed
while($chInfo = curl_multi_info_read($mh))
{
$chStatus = curl_getinfo($chInfo['handle']);
if($chStatus['http_code'] == 200) // if the page was retrieved successfully
{
$response = curl_multi_getcontent($chInfo['handle']); // get the response
curl_multi_remove_handle($mh, $chInfo['handle']); // remove the curl handle that was just completed
curl_close($chInfo['handle']); // close the curl handle that was just completed (cookies are saved when the handle is closed?)
curl_close($chInfo['handle']);
var_dump(is_resource($chInfo['handle']));
}
else // request failed
{
echo 'Error: Request failed with http_code: ' . $chStatus['http_code'] . ', curl error: ' . curl_error($chInfo['handle']). PHP_EOL;
}
}
} while ($running > 0);
curl_multi_close($mh);
如果运行上面的代码,输出将是
boolean false
指示手柄已关闭。但是,如果您删除第二个呼叫curl_close()
,则输出变为
boolean true
指示句柄是不关闭。
这真的很奇怪。我从来没有遇到过这样的问题,而且我经常使用cURL。什么是你的PHP版本?你可以分享cURL执行吗? – sunshinejr
@ailvenge我正在使用PHP版本5.4.12。我为你发布了示例代码。谢谢你的帮助。 – Nate
我很好奇你为什么用curl_close代替curl_multi_close?在使用curl_multi _...的其他地方,我认为使用curl_multi_close也是合乎逻辑的。这只是一个难题.. – bksi