php請求遠程url內容方法


php請求遠程url內容有兩個方法fopen/file_get_contents和curl。

1,fopen/file_get_contents與curl的差異

(1)fopen /file_get_contents 每次請求都會重新做DNS查詢,並不對DNS信息進行緩存。但是CURL會自動對DNS信息進行緩存。對同一域名下的網頁或者圖片的請求只需要一次DNS查詢。這大大減少了DNS查詢的次數。所以CURL的性能比fopen /file_get_contents 好很多。
(2)fopen /file_get_contents在請求HTTP時,使用的是http_fopen_wrapper,不會keeplive。而curl卻可以。這樣在多次請求多個鏈接時,curl效率會好一些。
(3)curl可以模擬多種請求,例如:POST數據,表單提交等,用戶可以按照自己的需求來定制請求。而fopen / file_get_contents只能使用get方式獲取數據。

2,如果遠程服務器關閉,file_get_contents處理方法,可以參考這篇文章,http://www.cnblogs.com/scofi/articles/3607529.html

公司里有經常有這樣的業務,需要調用第三方公司提供的HTTP接口,在把接口提供的信息顯示到網頁上,代碼是這樣寫的: file_get_contents("http://example.com/") 。

有一天突然接到運維同事的報告,說是服務器掛了,查出原因說是因為file_get_contents函數造成的,那么為什么一個函數會把服務器給搞掛掉呢?
經過詳細的查詢發現第三方公司提供接口已經壞掉了,就是因為接口壞掉了,才導致服務器掛掉。
問題分析如下:
       我們代碼是“file_get_contents("http://example.com/") “獲取一個 URL 的返回內容,如果第三方公司提供的URL響應速度慢,或者出現問題,我們服務器的PHP程序將會一直執行去獲得這個URL,我們知道,在 php.ini 中,有一個參數 max_execution_time 可以設置 PHP 腳本的最大執行時間,但是,在 php-cgi(php-fpm) 中,該參數不會起效。真正能夠控制 PHP 腳本最大執行時間的是 php-fpm.conf 配置文件中的以下參數:  <value name="request_terminate_timeout">0s</value>   默認值為 0 秒,也就是說,PHP 腳本會一直執行下去,當請求越來越多的情況下會導致php-cgi 進程都卡在 file_get_contents() 函數時,這台 Nginx+PHP 的 WebServer 已經無法再處理新的 PHP 請求了,Nginx 將給用戶返回“502 Bad Gateway”。CPU的利用率達到100% ,時間一長服務器就會掛掉。
問題的解決:
     已經找到問題,那么我們該怎么解決呢?
     當時想到的解決問題的辦法就是設置PHP的超時時間,用set_time_limit; 設置超時時間,這樣就不會卡住了。代碼上線后發現服務器還是會掛掉,好像根本不起作用。后來查了資料才知道,set_time_limit設置的是PHP程序的超時時間,而不是file_get_contents函數讀取URL的超時時間。set_time_limit和修改php.ini文件里max_execution_time  效果是一樣的。
要設置file_get_contents函數的超時時間,可以用resource $context的timeout參數,代碼如下:
 
$opts = array(
  'http'=>array(
    'method'=>"GET",
    'timeout'=>10,
  )
);
$context = stream_context_create($opts);
$html =file_get_contents('http://www.example.com', false, $context);
echo $html;

代碼中的timeout就是file_get_contents讀取url的超時時間。

另外還有一個說法也可以改變讀取url的超時時間,就是修改php.ini中的 default_socket_timeout的值,或者 ini_set('default_socket_timeout',    10);  但是我沒有測試過不知道行不行。
有了解決方法之后,服務器就不會掛掉了。
http://www.cnblogs.com/scofi/articles/3607533.html

上篇說到我們說到設置file_get_contents超時時間用到了 stream_context_create方法,那么這個方法到底是什么呢?

查了下資料, stream_context_create創建並返回一個文本數據流並應用各種選項,可用於fopen(),file_get_contents()等過程的超時設置、代理服務器、請求方式、頭信息設置的特殊過程。這樣看起來功能就強大了,不僅僅可以設置超時時間,還可以設置代理服務器,請求方式和頭信息,下面我們就測試下吧:
request.php請求頁面負責發起請求:
<?php
 $data = array("name" => 'test_name',"content" => 'test_con');
 $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" .
               "Cookie: foo=bar\r\n" .
               "\r\n",
     'content' => $data,
   )
 );
 $cxContext = stream_context_create($opts);
 $sFile = file_get_contents("http://127.0.0.1/reponse.php", false, $cxContext);   
 echo $sFile;
?>

reponse.php被請求的頁面:

<?php
var_dump($_POST);
var_dump($_COOKIE);
?>

  運行之后的結果為:

string(132) "array(2) { ["content"]=> string(8) "test_con" ["name"]=> string(9) "test_name" } array(1) { ["foo"]=> string(3) "bar" } "  
說明file_get_contents可以post數據和cookie數據到目標url,並獲得內容。
3,curl的用法總結, http://www.cnblogs.com/scofi/articles/3607538.html
(1)使用curl,get獲取數據
<?php
$url = 'http://www.example.com';
//初始化一個 cURL 對象 
$ch  = curl_init();
//設置你需要抓取的URL
curl_setopt($ch, CURLOPT_URL, $url);
// 設置cURL 參數,要求結果保存到字符串中還是輸出到屏幕上。
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//是否獲得跳轉后的頁面
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$data = curl_exec($ch);
curl_close($ch);
echo $data;
?>

(2)使用curl。post獲取數據

<?php
function curl_post($url, $arr_data){
   $post_data = http_build_query($url_data);
   $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch,  CURLOPT_POSTFLELDS, $post_data);
    $data = curl_exec($ch);
    curl_close($ch);
    echo $data;
}
$arr_post = array(
    'name'=>'test_name',
    'age'   => 1
);
curl_post("http://www.explame.com/", $arr_post);
?>

(3)使用代理抓取頁面,什么要使用代理進行抓取呢?以google為例吧,如果去抓google的數據,短時間內抓的很頻繁的話,你就抓取不到了。google對你的ip地址做限制這個時候,你可以換代理重新抓。

<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://google.com"); 
curl_setopt($ch, CURLOPT_HEADER, false);  
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//是否通過http代理來傳輸
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, TRUE);
curl_setopt($ch, CURLOPT_PROXY, 125.21.23.6:8080);  
//url_setopt($ch, CURLOPT_PROXYUSERPWD, 'user:password');如果要密碼的話,加上這個  
$result=curl_exec($ch); 
curl_close($ch);
?>

(4)繼續保持本站session調用,在實現用戶同步登錄的情況下需要共享session,如果要繼續保持本站的session,那么要把sessionid放到http請求中。

<?php
$session_str = session_name().'='.session_id().'; path=/; domain=.explame.com';
session_write_close(); //將數據寫入文件並且結束session
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_COOKIE, $session_str); 
$ret = curl_exec($ch);
curl_close($ch);
?>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM