在尚未接觸curl的時候,相信你們在獲取網頁內容的時,使用得最多的一個函數就是:file_get_contents(),可是它的可控制性不夠靈活,沒法處理錯誤狀況,對於各類複雜狀況的採集更是顯得有點無能爲力。所以,本文將爲你介紹另一種工具:cURL的使用方法,在後面也還會給出相關的幾個案例,這些都是你使用file_get_contents()沒法作到的。
php
爲了更好的理解下面的內容,這裏先給出一個curl的最簡單的案例html
入門案例:web
$url = "http://nosee123.com/test_post.php";json
$ch = curl_init($url); //初始化一個cURL會話數組
curl_exec($ch); //執行一個cURL會話瀏覽器
curl_close($ch); //關閉一個cURL會話服務器
該案例的執行結果就是把$url的網頁內容輸出到你的瀏覽器上,其實這個案例的效果和使用file_get_contents()的結果是同樣的,這是由於它沒有設置任何的參數。但cURL的功能遠遠不止這些,下面咱們開始講解cURL更詳細的使用方法。cookie
cURL是一個可使用URL的語法模擬瀏覽器來傳輸數據的工具庫(libcurl庫),libcurl目前支持http、https、ftp、gopher、telnet、dict、file和ldap協議。libcurl同時也支持HTTPS認證、HTTP POST、HTTP PUT、 FTP 上傳(這個也能經過PHP的FTP擴展完成)、HTTP 基於表單的上傳、代理、cookies和用戶名+密碼的認證。app
注意:在使用cURL庫以前,記得要先將你的配置文件(php.ini)中打開的你cURL模塊,可使用phpinfo()查看curl模塊是否開啓,如沒有開啓就直接使用相關的方法則會報錯。curl
使用 cURL 函數的基本思想是先使用curl_init() 初始化 cURL會話,接着能夠經過 curl_setopt() 設置須要的所有選項,而後使用 curl_exec()來執行會話,當執行完會話後使用curl_close()關閉會話。
簡單來講,使用cURL完成簡單的請求主要分爲如下四個步驟:
//(1)初始化cURL
$url = "http://nosee123.com/test_post.php";
$ch = curl_init($url); //初始化一個cURL會話
//(2)設置URL和相應的選項
//將curl_exec()獲取的信息以字符串返回,而不是直接輸出。
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//(3)抓取URL並把它傳遞給瀏覽器
//因爲步驟2對CURLOPT_RETURNTRANSFER的設置,curl_exec()不會直接輸出內容
$str = curl_exec($ch); //執行一個cURL會話
//(4)關閉cURL資源,而且釋放系統資源
curl_close($ch); //關閉一個cURL會話
echo $str; //輸出步驟3獲取的頁面內容
上面的4個步驟將會把獲取到的網頁內容輸出,這是使用cURL最基本的四個步驟。
cURL之因此強大,只要是體如今它的第二個步驟中。你能夠經過curl_setopt靈活地設置請求選項,更多的參數設置查看官網:http://php.net/manual/zh/function.curl-setopt.php
官方上羅列的是全部的參數列表,所有都記住也沒有什麼必要。然而實際開發中,咱們經常使用的也就來來去去那幾個,因此在這我也順便把經常使用的幾個都詳細講講,這樣也方便咱們更好的快速的用到實際開發中。但建議有時間的話最好把官網上的都看一篇,這樣至少本身內心也有個底,知道里面有些什麼方法,當真正須要的時候也方便過來查找。
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);//將curl_exec()獲取的信息以字符串返回,而不是直接輸出。
curl_setopt($ch, CURLOPT_HEADER,false);//不輸出頭文件,若是設爲true,得到的網頁源代碼最前邊會帶有'HTTP/1.1 200 OK'等內容
curl_setopt($ch, CURLOPT_FILE, $fp);//設置輸出文件,默認爲STDOUT (瀏覽器)。
curl_setopt($ch, CURLOPT_POST, 1);// 設置請求爲post類型
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);// 添加post數據到請求中
除了上面基本的4個步驟用到的4個函數,cURL還提供了其餘不少實用的函數,如curl_error、curl_getinfo等。
在執行一個cURL請求後,你也可使用curl_getinfo獲取該請求的具體信息:
curl_exec($ch);
$curl_info= curl_getinfo($ch);
echo "收到的http回覆的code爲: {$curl_info['http_code']}";
上述$curl_info是一個關聯數組,能夠從中獲取不少的具體請求信息。
參考:http://php.net/manual/zh/function.curl-getinfo.php
$response = curl_exec($ch);
if ($response === FALSE) {
echo "cURL 具體出錯信息: " . curl_error($ch);
}
注意了,在作上述判斷時務必要使用===,由於請求的回覆多是空字符串,curl在請求出錯的狀況下回返回FALSE值,因此咱們必須使用===,而不是==
參考:http://php.net/manual/zh/function.curl-error.php
$url = "http://nosee123.com/test_post.php";
$post_data = array (
"name" => "nosee",
"url" => "http://www.nosee123.com",
"action" => "Submit"
);
$ch = curl_init($url );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST, 1);// 設置請求爲post類型
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);// 添加post數據到請求中
$str = curl_exec($ch);// 執行post請求,得到回覆
curl_close($ch);
echo $str ;
$url = "http://nosee123.com/86-1.zip"; //遠程服務器上要下載的文件
$fp = fopen("output.zip", "w"); //打開一個本地文件指針資源
$ch = curl_init($url); //初始化一個cURL會話
curl_setopt($ch, CURLOPT_FILE, $fp); //設置輸出文件,默認爲STDOUT (瀏覽器)。
$str = curl_exec($ch); //執行一個cURL會話
if ($str === FALSE) {
echo "cURL 具體出錯信息: " . curl_error($ch);
}
curl_close($ch); //關閉一個cURL會話
fclose($fp); //關閉一個已打開的文件指針
PHP使用CURL上傳文件只需發送一個POST請求就能夠了,在請求中設置某個字段爲須要上傳的文件全路徑,而且以「@」開頭,而後使用CURL把該變量以POST方式發送到服務器,在服務端便可以從超級全局變量$_FILES中取到相應的上傳文件信息。須要注意的是,上傳文件的變量不是存在着$_POST中,而是在$_FILES中。
如下代碼是存在我本地服務器的腳本:
$url = "http://nosee123.com/test_post.php";
$post_data = array (
//要上傳的本地的文件地址
"attachment" => "@D:/web/www/wp70/readme.html""
);
//初始化cURL會話
$ch = curl_init();
//設置請求的url
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
//設置爲post請求類型
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);//重點!下面詳細講解
//設置具體的post數據
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
$response = curl_exec($ch);
if ($response === FALSE) {
echo "cURL 具體出錯信息: " . curl_error($ch);
}
curl_close($ch);
print_r($response);
個人遠程服務端處理請求的腳本文件:test_post.php 以下:
//首先使用var_export將$_FILES變量輸出到標準輸出
echo var_export($_FILES,true);
//而後使用file_get_contents讀取$_FILES[‘attachment’][‘tmp_name’]所指文件的內容,並輸出到標準輸出
echo file_get_contents($_FILES['attachment']['tmp_name']);
//而後把$_FILES[‘attachment’][‘tmp_name’]所指文件自制到當前目錄的log_copy.txt文件中
copy($_FILES['attachment']['tmp_name'], "./testdata_copy.txt");
能夠看到$_FILES變量中有一個attachment數組,對應到上傳文件描述信息,其中name和type分別表示名稱和類型。tmp_name比較關鍵,服務端在接收到上傳文件以後,會把文件寫在一個臨時文件中,這個臨時文件的名字就是tmp_name的值,這也是爲何咱們讀取該文件能夠獲取一testdata.txt的文件內容。通常在服務端接收到上傳文件後都須要當即讀取該文件或者把文件複製到別外一個文件中,由於tmp_name所指的臨時文件在服務端腳本執行完畢後會被刪除掉,test_post.php腳本的最後一行就是把臨時文件複製到咱們的目標文件中。
還有一個重點問題,這個問題也是折騰了我整整一天的,由於一開始個人請求代碼裏面沒有加curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);這一段代碼,上傳文件一直失敗,@後面的文件地址沒法被解析。一直到最後我才發現了那是由於php版本兼容性的問題。對於PHP5.6及以上的版本是不會直接識別@綁定的後面的地址,那要怎麼解決這個兼容性問題呢?有兩種解決方法:
1)就如我上面的代碼,使用配置參數 CURLOPT_SAFE_UPLOAD ,在 PHP5.5中默認值是 false ,而在 PHP5.6中已經默認爲 true 了。 因此只須要增長一行強制設置爲 false 就行,以下:
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
注意:該參數的設置順序,必須在設置 CURLOPT_POSTFIELDS 參數以前纔有效哦!!!
2)使用 CURLFile 類來處理文件
在上面代碼的基礎上,把變量$post_data修改成以下代碼便可:
$post_data = array (
"attachment" => new CURLFile("D:/web/www/wp70/readme.html")
);
詳細參考官方文檔:http://php.net/manual/zh/class.curlfile.php
$posturl='http://nosee123.com/test_json.php';
$array=array ('key'=>'abc','phone'=>'18813912321','userid'=>'1234321');
$jsoninfo = json_encode($array); //把數組進行json編碼
//模擬post請求
$ch = curl_init();//初始化curl
if ( $ch === FALSE ){
return 'ERROR: Sorry , you cannot open curl. --- nosee';
}
curl_setopt($ch, CURLOPT_URL,$posturl); //抓取指定網頁
curl_setopt($ch, CURLOPT_HEADER, 0); //設置header
//這一步爲最關鍵!!設置head頭的請求數據格式爲json
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Content-type:application/json;charset=utf-8",
"Content-Length: " . strlen($jsoninfo)
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //要求結果爲字符串且輸出到屏幕上
curl_setopt($ch, CURLOPT_POST, 1); //post提交方式
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsoninfo); //添加請求的json數據
$data = curl_exec($ch); //運行curl 返回請求的json數據
$json = json_decode($data); //把json數據轉爲php的對象類型
curl_close($ch); //關閉curl
使用用curl傳輸json數據的實際案例可查看個人上一篇文章:使用php接入圖靈機器人的方法
向圖靈機器人的API提交json數據的POST請求中,本人使用的就是這個方法。
更多cURL的案例和使用方法可查看官方文檔,地址以下:
http://php.net/manual/zh/book.curl.php
感謝閱讀
原文地址:https://www.jianshu.com/p/97243d2153c2