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參數,代碼如下:
 
?
1
2
3
4
5
6
7
8
9
$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請求頁面負責發起請求:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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被請求的頁面:

?
1
2
3
4
<?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獲取數據
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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獲取數據

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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地址做限制這個時候,你可以換代理重新抓。

?
1
2
3
4
5
6
7
8
9
10
11
12
<?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請求中。

?
1
2
3
4
5
6
7
8
9
10
11
<?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