Php讀取網(wǎng)絡文件 Curl, Fsockopen ,file_get_contents 幾個方法的效率對比
curl效率及穩(wěn)定原來可以遠遠超越file_get_contents
至近需要獲取別人網(wǎng)站上的音樂數(shù)據(jù)。用了file_get_contents函數(shù),但是總是會遇到獲取失敗的問題,盡管按照手冊中的 例子設置了超時,可多數(shù)時候不會奏效:
$config[\'context\'] = stream_context_create(array(‘http’ => array(‘method’ => “GET”,
’timeout’ => 5//這個超時時間不穩(wěn)定,經(jīng)常不奏效
)
));
這時候,看一下服務器的連接池,會發(fā)現(xiàn)一堆類似的錯誤,讓我頭疼萬分:
file_get_contents(http://***): failed to open stream…
現(xiàn)在改用了curl庫,寫了一個函數(shù)替換:
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;
}
如此,除了真正的網(wǎng)絡問題外,沒再出現(xiàn)任何問題。
這是別人做過的關于curl和file_get_contents的測試:
file_get_contents抓取google.com需用秒數(shù):
2.31319094
2.30374217
2.21512604
3.30553889
2.30124092
curl使用的時間:
0.68719101
0.64675593
0.64326
0.81983113
0.63956594
差距很大?呵呵,從我使用的經(jīng)驗來說,這兩個工具不只是速度有差異,穩(wěn)定性也相差很大。
建議對網(wǎng)絡數(shù)據(jù)抓取穩(wěn)定性要求比較高的朋友使用上面的 curl_file_get_contents函數(shù),不但穩(wěn)定速度快,還能假冒瀏覽器欺騙目標地址哦!
看到的其他文章收藏于此===============================
php fsockopen
方法1: 用file_get_contents 以get方式獲取內(nèi)容
<?php
$url=\'http://www.domain.com/\';
$html = file_get_contents($url);
echo $html;
?>
方法2: 用fopen打開url, 以get方式獲取內(nèi)容
<?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函數(shù),以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函數(shù)打開url,以get方式獲取完整的數(shù)據(jù),包括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函數(shù)打開url,以POST方式獲取完整的數(shù)據(jù),包括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是否已經(jīng)打開了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 三個函數(shù) 都可以實現(xiàn)采集模擬發(fā)言 。 三者有什么區(qū)別,或者講究么
趙永斌:
有些時候用file_get_contents()調(diào)用外部文件,容易超時報錯。換成curl后就可以.具體原因不清楚
curl 效率比file_get_contents()和fsockopen()高一些,原因是CURL會自動對DNS信息進行緩存(亮點啊 有我待親測)
范佳鵬:
file_get_contents curl fsockopen
在當前所請求環(huán)境下選擇性操作,沒有一概而論:
具我們公司開發(fā)KBI應用來看:
剛開始采用:file_get_contents
后來采用:fsockopen
至后到至今采用:curl
(遠程)我個人理解到的表述如下(不對請指出,不到位請補充)
file_get_contents 需要php.ini里開啟allow_url_fopen,請求http時,使用的是http_fopen_wrapper,不會keeplive.curl是可以的。
file_get_contents()單個執(zhí)行效率高,返回沒有頭的信息。
這個是讀取一般文件的時候并沒有什么問題,但是在讀取遠程問題的時候就會出現(xiàn)問題。
如果是要打一個持續(xù)連接,多次請求多個頁面。那么file_get_contents和fopen就會出問題。
取得的內(nèi)容也可能會不對。所以做一些類似采集工作的時候,肯定就有問題了。
sock較底層,配置麻煩,不易操作。 返回完整信息。
潘少寧-騰訊:
file_get_contents 雖然可以獲得某URL的內(nèi)容,但不能post get啊。
curl 則可以post和get啊。還可以獲得head信息
而socket則更底層。可以設置基于UDP或是TCP協(xié)議去交互
file_get_contents 和 curl 能干的,socket都能干。
socket能干的,curl 就不一定能干了
file_get_contents 更多的時候 只是去拉取數(shù)據(jù)。效率比較高 也比較簡單。
趙的情況這個我也遇到過,我通過CURL設置host 就OK了。 這和網(wǎng)絡環(huán)境有關系