Php讀取網絡文件 Curl, Fsockopen ,file_get_contents 幾個方法的效率對比
curl效率及穩定原來可以遠遠超越file_get_contents
至近需要獲取别人網站上的音樂數據。用瞭file_get_contents函數,但是總是會遇到獲取失敗的問題,盡管按照手冊中的 例子設置瞭超時,可多數時候不會奏效:
$config[\'context\'] = stream_context_create(array(‘http’ => array(‘method’ => “GET”,
’timeout’ => 5//這個超時時間不穩定,經常不奏效
)
));
這時候,看一下服務器的連接池,會發現一堆類似的錯誤,讓我頭疼萬分:
file_get_contents(http://***): failed to open stream…
現在改用瞭curl庫,寫瞭一個函數替換:
function curl_file_get_contents($durl){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $durl);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_USERAGENT, _USERAGENT_);
curl_setopt($ch, CURLOPT_REFERER,_REFERER_);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$r = curl_exec($ch);
curl_close($ch);
return $r;
}
如此,除瞭真正的網絡問題外,沒再出現任何問題。
這是别人做過的關於curl和file_get_contents的測試:
file_get_contents抓取google.com需用秒數:
2.31319094
2.30374217
2.21512604
3.30553889
2.30124092
curl使用的時間:
0.68719101
0.64675593
0.64326
0.81983113
0.63956594
差距很大?呵呵,從我使用的經驗來說,這兩個工具不隻是速度有差異,穩定性也相差很大。
建議對網絡數據抓取穩定性要求比較髙的朋友使用上麵的 curl_file_get_contents函數,不但穩定速度快,還能假冒浏覽器欺騙目標地址哦!
看到的其他文章收藏於此===============================
php fsockopen
方法1: 用file_get_contents 以get方式獲取内容
<?php
$url=\'http://www.domain.com/\';
$html = file_get_contents($url);
echo $html;
?>
方法2: 用fopen打開url, 以get方式獲取内容
<?php
$fp = fopen($url, \'r\');
stream_get_meta_data($fp);
while(!feof($fp)) {
$result .= fgets($fp, 1024);
}
echo \"url body: $result\";
fclose($fp);
?>
方法3:用file_get_contents函數,以post方式獲取url
<?php
$data = array (\'foo\' => \'bar\');
$data = http_build_query($data);
$opts = array (
\'http\' => array (
\'method\' => \'POST\',
\'header\'=> \"Content-type: application/x-www-form-urlencoded\\r\\n\" .
\"Content-Length: \" . strlen($data) . \"\\r\\n\",
\'content\' => $data
)
);
$context = stream_context_create($opts);
$html = file_get_contents(\'http://localhost/e/admin/test.html\', false, $context);
echo $html;
?>
方法4:用fsockopen函數打開url,以get方式獲取完整的數據,包括header和body
<?php
function get_url ($url,$cookie=false)
{
$url = parse_url($url);
$query = $url[path].\"?\".$url[query];
echo \"Query:\".$query;
$fp = fsockopen( $url[host], $url[port]?$url[port]:80 , $errno, $errstr, 30);
if (!$fp) {
return false;
} else {
$request = \"GET $query HTTP/1.1\\r\\n\";
$request .= \"Host: $url[host]\\r\\n\";
$request .= \"Connection: Close\\r\\n\";
if($cookie) $request.=\"Cookie: $cookie\\n\";
$request.=\"\\r\\n\";
fwrite($fp,$request);
while()) {
$result .= @fgets($fp, 1024);
}
fclose($fp);
return $result;
}
}
//獲取url的html部分,去掉header
function GetUrlHTML($url,$cookie=false)
{
$rowdata = get_url($url,$cookie);
if($rowdata)
{
$body= stristr($rowdata,\"\\r\\n\\r\\n\");
$body=substr($body,4,strlen($body));
return $body;
}
return false;
}
?>
方法5:用fsockopen函數打開url,以POST方式獲取完整的數據,包括header和body
<?php
function HTTP_Post($URL,$data,$cookie, $referrer=\"\")
{
// parsing the given URL
$URL_Info=parse_url($URL);
// Building referrer
if($referrer==\"\") // if not given use this script as referrer
$referrer=\"111\";
// making string from $data
foreach($data as $key=>$value)
$values[]=\"$key=\".urlencode($value);
$data_string=implode(\"&\",$values);
// Find out which port is needed - if not given use standard (=80)
if(!isset($URL_Info[\"port\"]))
$URL_Info[\"port\"]=80;
// building POST-request:
$request.=\"POST \".$URL_Info[\"path\"].\" HTTP/1.1\\n\";
$request.=\"Host: \".$URL_Info[\"host\"].\"\\n\";
$request.=\"Referer: $referer\\n\";
$request.=\"Content-type: application/x-www-form-urlencoded\\n\";
$request.=\"Content-length: \".strlen($data_string).\"\\n\";
$request.=\"Connection: close\\n\";
$request.=\"Cookie: $cookie\\n\";
$request.=\"\\n\";
$request.=$data_string.\"\\n\";
$fp = fsockopen($URL_Info[\"host\"],$URL_Info[\"port\"]);
fputs($fp, $request);
while(!feof($fp)) {
$result .= fgets($fp, 1024);
}
fclose($fp);
return $result;
}
?>
方法6:使用curl庫,使用curl庫之前,可能需要查看一下php.ini是否已經打開瞭curl擴展
<?php
$ch = curl_init();
$timeout = 5;
curl_setopt ($ch, CURLOPT_URL, \'http://www.domain.com/\');
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$file_contents = curl_exec($ch);
curl_close($ch);
echo $file_contents;
?>
php中 curl, fsockopen ,file_get_contents 三個函數 都可以實現採集模擬發言 。 三者有什麽區别,或者講究麽
趙永斌:
有些時候用file_get_contents()調用外部文件,容易超時報錯。換成curl後就可以.具體原因不清楚
curl 效率比file_get_contents()和fsockopen()髙一些,原因是CURL會自動對DNS信息進行緩存(亮點啊 有我待親測)
範佳鵬:
file_get_contents curl fsockopen
在當前所請求環境下選擇性操作,沒有一概而論:
具我們公司開發KBI應用來看:
剛開始採用:file_get_contents
後來採用:fsockopen
至後到至今採用:curl
(遠程)我個人理解到的錶述如下(不對請指出,不到位請補充)
file_get_contents 需要php.ini裏開啓allow_url_fopen,請求http時,使用的是http_fopen_wrapper,不會keeplive.curl是可以的。
file_get_contents()單個執行效率髙,返回沒有頭的信息。
這個是讀取一般文件的時候並沒有什麽問題,但是在讀取遠程問題的時候就會出現問題。
如果是要打一個持續連接,多次請求多個頁麵。那麽file_get_contents和fopen就會出問題。
取得的内容也可能會不對。所以做一些類似採集工作的時候,肯定就有問題瞭。
sock較底層,配置麻煩,不易操作。 返回完整信息。
潘少甯-騰訊:
file_get_contents 雖然可以獲得某URL的内容,但不能post get啊。
curl 則可以post和get啊。還可以獲得head信息
而socket則更底層。可以設置基於UDP或是TCP協議去交互
file_get_contents 和 curl 能幹的,socket都能幹。
socket能幹的,curl 就不一定能幹瞭
file_get_contents 更多的時候 隻是去拉取數據。效率比較髙 也比較簡單。
趙的情況這個我也遇到過,我通過CURL設置host 就OK瞭。 這和網絡環境有關係