聽歡哥講PHP之輕松搞定cURL

cURL是一個(gè)利用URL語法規(guī)定來傳輸文件和數(shù)據(jù)的工具,支持很多協(xié)議和選項(xiàng),如HTTP、FTP、TELNET等,能提供 URL 請(qǐng)求相關(guān)的各種細(xì)節(jié)信息。最爽的是,PHP 也支持cURL 庫。

本文將介紹 cURL 的一些高級(jí)特性,以及在 PHP 中如何運(yùn)用它。

1 為什么要用cURL?

是的,我們可以通過其他辦法獲取網(wǎng)頁內(nèi)容。大多數(shù)時(shí)候,我因?yàn)橄胪祽校贾苯佑煤?jiǎn)單的 PHP 的file_get_contents()函數(shù):

$content = file_get_contents("http://www.awaimai.com");$lines = file("http://www.awaimai.com");readfile(http://www.awaimai.com);

不過,這種做法缺乏靈活性和有效的錯(cuò)誤處理。而且,你也不能用它完成一些高難度任務(wù),比如處理:coockies、驗(yàn)證、表單提交、文件上傳等等。

2 啟用cURL

首先,我們得先要確定 PHP 是否開啟了這個(gè)庫,你可以通過使用phpinfo()函數(shù)來得到這一信息。如果在網(wǎng)頁上看到下面的輸出,那么表示 cURL 庫已開啟。

如果 curl 沒有開啟,那么就需要開啟這個(gè)庫。如果是在Windows平臺(tái)下,那么非常簡(jiǎn)單,你需要改一改php.ini文件的設(shè)置,找到php_curl.dll,并取消前面的分號(hào)注釋就行了。如下所示:

# 取消下面的注釋extension=php_curl.dll

如果是 Linux 服務(wù)器,需要重新編譯 PHP ,編譯時(shí)在configure命令上加上--with-curl參數(shù)。

3 基本結(jié)構(gòu)

在學(xué)習(xí)更為復(fù)雜的功能之前,先來看一下在 PHP 中建立 cURL 請(qǐng)求的基本步驟:

初始化

設(shè)置選項(xiàng)

執(zhí)行并獲取結(jié)果

釋放cURL句柄

實(shí)現(xiàn)代碼如下:

// 1. 初始化$ch = curl_init();// 2. 設(shè)置選項(xiàng)curl_setopt($ch, CURLOPT_URL,"http://www.awaimai.com");// 設(shè)置要抓取的頁面地址curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);// 抓取結(jié)果直接返回(如果為0,則直接輸出內(nèi)容到頁面)curl_setopt($ch, CURLOPT_HEADER, 0);// 不需要頁面的HTTP頭// 3. 執(zhí)行并獲取HTML文檔內(nèi)容,可用echo輸出內(nèi)容$output = curl_exec($ch);// 4. 釋放curl句柄

curl_close($ch);

第二步(也就是curl_setopt())最為重要,一切玄妙均在此。有一長(zhǎng)串cURL參數(shù)可供設(shè)置,它們能指定 URL 請(qǐng)求的各個(gè)細(xì)節(jié)。要一次性全部看完并理解可能比較困難,所以今天我們只試一下那些更常用也更有用的選項(xiàng)。

4 檢查錯(cuò)誤

你可以在cur_exec()后加一段檢查錯(cuò)誤的語句(雖然這并不是必需的):

$output = curl_exec($ch);if ($output ===FALSE) {echo"cURL Error: " . curl_error($ch);

}

請(qǐng)注意,比較的時(shí)候我們用的是=== FALSE,而非==FALSE。因?yàn)槲覀兊脜^(qū)分空輸出和布爾值FALSE,后者才是真正的錯(cuò)誤。

5 獲取信息

利用curl_getinfo()能夠在 cURL 執(zhí)行后獲取請(qǐng)求的有關(guān)信息,當(dāng)然,這也是一個(gè)可選的設(shè)置項(xiàng),:

curl_exec($ch);$info = curl_getinfo($ch);echo'獲取'.$info['url'] .'耗時(shí)'.$info['total_time'] .'秒';

返回的數(shù)組中包括了以下信息:

url//資源網(wǎng)絡(luò)地址

content_type//內(nèi)容編碼

http_code//HTTP狀態(tài)碼

header_size//header的大小

request_size//請(qǐng)求的大小

filetime//文件創(chuàng)建時(shí)間

ssl_verify_result//SSL驗(yàn)證結(jié)果

redirect_count//跳轉(zhuǎn)技術(shù)

total_time//總耗時(shí)

namelookup_time//DNS查詢耗時(shí)

connect_time//等待連接耗時(shí)

pretransfer_time//傳輸前準(zhǔn)備耗時(shí)

size_upload//上傳數(shù)據(jù)的大小

size_download//下載數(shù)據(jù)的大小

speed_download//下載速度

speed_upload//上傳速度

download_content_length//下載內(nèi)容的長(zhǎng)度

upload_content_length//上傳內(nèi)容的長(zhǎng)度

starttransfer_time//開始傳輸?shù)臅r(shí)間

redirect_time//重定向耗時(shí)

6 基于瀏覽器的重定向

在第一個(gè)例子中,我們將提供一段用于偵測(cè)服務(wù)器是否有基于瀏覽器的重定向的代碼。例如,有些網(wǎng)站會(huì)根據(jù)是否是手機(jī)瀏覽器甚至用戶來自哪個(gè)國(guó)家來重定向網(wǎng)頁。

我們利用CURLOPT_HTTPHEADER選項(xiàng)來設(shè)定發(fā)送出的HTTP請(qǐng)求頭信息(http headers),包括user agent信息和默認(rèn)語言。然后看看這些特定網(wǎng)站是否會(huì)把我們重定向到不同的URL。

// 測(cè)試用的URL$urls =array("http://www.bbc.com","http://www.baidu.com","http://www.ubuntu.com");// 測(cè)試用的瀏覽器信息$browsers =array("standard" =>array ("user_agent" =>"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 (.NET CLR 3.5.30729)","language" =>"en-us,en;q=0.5"? ? ? ? ? ? ? ? ),"iphone" =>array ("user_agent" =>"Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A537a Safari/419.3","language" =>"en"? ? ? ? ? ? ? ? ),"french" =>array ("user_agent" =>"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GTB6; .NET CLR 2.0.50727)","language" =>"fr,fr-FR;q=0.5"? ? ? ? ? ? ? ? ));foreach ($urlsas $url) {echo"URL: $url\n

";foreach ($browsersas $test_name => $browser) {? ? ? ? ? ? ? ? $ch = curl_init();// 設(shè)置 url? ? ? ? ? ? ? ? curl_setopt($ch, CURLOPT_URL, $url);// 設(shè)置瀏覽器的特定header? ? ? ? ? ? ? ? curl_setopt($ch, CURLOPT_HTTPHEADER,array("User-Agent: {$browser['user_agent']}","Accept-Language: {$browser['language']}"? ? ? ? ? ? ? ? ? ? ? ? ));// 頁面內(nèi)容我們并不需要? ? ? ? ? ? ? ? curl_setopt($ch, CURLOPT_NOBODY, 1);// 只需返回HTTP header? ? ? ? ? ? ? ? curl_setopt($ch, CURLOPT_HEADER, 1);// 返回結(jié)果,而不是輸出它? ? ? ? ? ? ? ? curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);? ? ? ? ? ? ? ? $output = curl_exec($ch);? ? ? ? ? ? ? ? curl_close($ch);// 有重定向的HTTP頭信息嗎?if (preg_match("!Location: (.*)!", $output, $matches)) {echo"$test_name: redirects to $matches[1]\n

";? ? ? ? ? ? ? ? }else {echo"$test_name: no redirection\n

";? ? ? ? ? ? ? ? }? ? ? ? }echo"\n\n

";}

首先,我們建立一組需要測(cè)試的URL,接著指定一組需要測(cè)試的瀏覽器信息。最后通過循環(huán)測(cè)試各種URL和瀏覽器匹配可能產(chǎn)生的情況。

因?yàn)槲覀冎付薈URLOPT_NOBODY選項(xiàng),所以返回的輸出內(nèi)容則只包括HTTP頭信息(被存放于$output中)。利用一個(gè)簡(jiǎn)單的正則,我們檢查這個(gè)頭信息中是否包含了Location:字樣。

運(yùn)行這段代碼應(yīng)該會(huì)返回如下結(jié)果:

URL: http://www.bbc.comstandard: no redirectioniphone: no redirectionfrench: no redirectionURL: http://www.baidu.comstandard: redirects to https://www.baidu.com/iphone: no redirectionfrench: redirects to https://www.baidu.com/ URL: http://www.ubuntu.com standard: redirects to http://www.ubuntu.com/index_kylin iphone: redirects to http://www.ubuntu.com/index_kylin french: redirects to http://www.ubuntu.com/index_kylin

7 用POST方法發(fā)送數(shù)據(jù)

當(dāng)發(fā)起 GET 請(qǐng)求時(shí),數(shù)據(jù)可以通過“查詢字串”(Query String)傳遞給一個(gè)URL。例如,在必應(yīng)(鑒于 Google 需要FQ,用 Bing 代替)中搜索時(shí),搜索關(guān)鍵即為 URL 的查詢字串的一部分:

http://www.bing.com?q=awaimai.com

這種情況下你可能并不需要 cURL 來模擬。把這個(gè)URL丟給file_get_contents()就能得到相同結(jié)果。

不過有一些HTML表單是用 POST 方法提交的。這種表單提交時(shí),數(shù)據(jù)是通過 HTTP請(qǐng)求體(request body) 發(fā)送,而不是查詢字串。例如,當(dāng)使用ThinkPHP網(wǎng)站的搜索功能時(shí),無論輸入什么關(guān)鍵字,總是被 POST 到如下頁面:

http://www.thinkphp.cn/Search/

你可以用 PHP 腳本來模擬這種 URL 請(qǐng)求。首先,新建一個(gè)可以接受并顯示 POST 數(shù)據(jù)的文件,我們給它命名為post_output.php,腳本內(nèi)容為:

print_r($_POST);

接下來,寫一段 PHP 腳本來執(zhí)行 cURL 請(qǐng)求:

$url ="http://localhost/post_output.php";$post_data =array ("foo" =>"bar","query" =>"Nettuts","action" =>"Submit");$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);// 我們?cè)赑OST數(shù)據(jù)哦!curl_setopt($ch, CURLOPT_POST, 1);// 加上POST變量curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);$output = curl_exec($ch);curl_close($ch);echo $output;

執(zhí)行代碼后應(yīng)該會(huì)得到以下結(jié)果:

Array

(

[foo] => bar

[query] => Nettuts

[action] => Submit

)

這段腳本發(fā)送一個(gè) POST 請(qǐng)求給post_output.php?,這個(gè)頁面$_POST變量并返回,我們利用 cURL 捕捉了這個(gè)輸出。

8 文件上傳

上傳文件和前面的 POST 十分相似。因?yàn)樗械奈募蟼鞅韱味际峭ㄟ^POST方法提交的。首先新建一個(gè)接收文件的頁面,命名為upload_output.php,頁面內(nèi)容:

print_r($_FILES);

以下是真正執(zhí)行文件上傳任務(wù)的腳本,命名為upload.php,內(nèi)容:

$url ="http://localhost/upload_output.php";$post_data =array ("foo" =>"bar",// 要上傳的本地文件地址"upload" =>"@C:/wamp/www/test.zip");$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_POSTFIELDS, $post_data);$output = curl_exec($ch);curl_close($ch);echo $output;

如果你需要上傳一個(gè)文件,只需要把文件路徑賦給upload,作為POST變量傳過去,不過記得在前面加上@符號(hào)。執(zhí)行這段腳本應(yīng)該會(huì)得到類似如下輸出:

Array(? ? [upload] =>Array

(

[name] => test.zip

[type] => application/octet-stream

[tmp_name] => C:\Windows\php1BB4.tmp

[error] => 0

[size] => 487235

)

)

9 cURL批處理(multi cURL)

cURL還有一個(gè)高級(jí)特性:批處理句柄(handle)。這一特性允許你同時(shí)或異步地打開多個(gè)URL連接。下面是來自來自php.net的示例代碼

// 創(chuàng)建兩個(gè)cURL資源$ch1 = curl_init();$ch2 = curl_init();// 指定URL和適當(dāng)?shù)膮?shù)curl_setopt($ch1, CURLOPT_URL,"http://lxr.php.net/");curl_setopt($ch1, CURLOPT_HEADER, 0);curl_setopt($ch2, CURLOPT_URL,"http://www.php.net/");curl_setopt($ch2, CURLOPT_HEADER, 0);// 創(chuàng)建cURL批處理句柄$mh = curl_multi_init();// 加上前面兩個(gè)資源句柄curl_multi_add_handle($mh, $ch1);curl_multi_add_handle($mh, $ch2);// 預(yù)定義一個(gè)狀態(tài)變量$active =null;// 執(zhí)行批處理do {? ? $mrc = curl_multi_exec($mh, $active);}while ($mrc == CURLM_CALL_MULTI_PERFORM);while ($active && $mrc == CURLM_OK) {if (curl_multi_select($mh) != -1) {do {? ? ? ? ? ? $mrc = curl_multi_exec($mh, $active);? ? ? ? }while ($mrc == CURLM_CALL_MULTI_PERFORM);? ? }}// 關(guān)閉各個(gè)句柄

curl_multi_remove_handle($mh, $ch1);

curl_multi_remove_handle($mh, $ch2);

curl_multi_close($mh);

這里要做的就是打開多個(gè) cURL 句柄并指派給一個(gè)批處理句柄。然后你就只需在一個(gè)while循環(huán)里等它執(zhí)行完畢。

這個(gè)示例中有兩個(gè)主要循環(huán)。第一個(gè)do-while循環(huán)重復(fù)調(diào)用curl_multi_exec()。這個(gè)函數(shù)是無隔斷(non-blocking)的,但會(huì)盡可能少地執(zhí)行。它返回一個(gè)狀態(tài)值,只要這個(gè)值等于常量CURLM_CALL_MULTI_PERFORM,就代表還有一些刻不容緩的工作要做(例如,把對(duì)應(yīng)URL的http頭信息發(fā)送出去)。也就是說,我們需要不斷調(diào)用該函數(shù),直到返回值發(fā)生改變。

而接下來的while循環(huán),只在$active變量為true時(shí)繼續(xù)。這一變量之前作為第二個(gè)參數(shù)傳給了curl_multi_exec(),代表只要批處理句柄中是否還有活動(dòng)連接。接著,我們調(diào)用curl_multi_select(),在活動(dòng)連接(例如接受服務(wù)器響應(yīng))出現(xiàn)之前,它都是被“屏蔽”的。這個(gè)函數(shù)成功執(zhí)行后,我們又會(huì)進(jìn)入另一個(gè)do-while循環(huán),繼續(xù)下一條URL。

還是來看一看怎么把這一功能用到實(shí)處吧:

9.1 WordPress 鏈接檢查器

想象一下你有一個(gè)文章數(shù)目龐大的博客,這些文章中包含了大量外部網(wǎng)站鏈接。一段時(shí)間之后,因?yàn)檫@樣那樣的原因,這些鏈接中相當(dāng)數(shù)量都失效了。要么是被和諧了,要么是整個(gè)站點(diǎn)都被功夫網(wǎng)了…

我們下面建立一個(gè)腳本,分析所有這些鏈接,找出打不開或者404的網(wǎng)站/網(wǎng)頁,并生成一個(gè)報(bào)告。

請(qǐng)注意,以下并不是一個(gè)真正可用的WordPress插件,僅僅是一段獨(dú)立功能的腳本而已,僅供演示,謝謝。

好,開始吧。首先,從數(shù)據(jù)庫中讀取所有這些鏈接:

// 配置 MySQL 數(shù)據(jù)庫$db_host ='localhost';$db_user ='root';$db_pass ='';$db_name ='wordpress';$excluded_domains =array('localhost','www.mydomain.com');$max_connections = 10;// 初始化一些變量$url_list =array();$working_urls =array();$dead_urls =array();$not_found_urls =array();$active =null;// 連到 MySQLif (!mysql_connect($db_host, $db_user, $db_pass)) {die('Could not connect: ' . mysql_error());}if (!mysql_select_db($db_name)) {die('Could not select db: ' . mysql_error());}// 找出所有含有鏈接的文章$sql ="SELECT post_content FROM wp_posts? ? ? ? WHERE post_content LIKE '%href=%'? ? ? ? AND post_status = 'publish'? ? ? ? AND post_type = 'post'";$res = mysql_query($sql)ordie(mysql_error());while ($d = mysql_fetch_assoc($res)) {// 用正則匹配鏈接if (preg_match_all("!href=\"(.*?)\"!", $d['post_content'], $matches)) {foreach ($matches[1]as $url) {// 剔除排除的域名? ? ? ? ? ? ? ? ? ? ? ? $tmp = parse_url($url);if (in_array($tmp['host'], $excluded_domains)) {continue;? ? ? ? ? ? ? ? ? ? ? ? }// 保存 URL? ? ? ? ? ? ? ? ? ? ? ? $url_list []= $url;? ? ? ? ? ? ? ? }? ? ? ? }}// 移除重復(fù)鏈接$url_list = array_values(array_unique($url_list));if (!$url_list) {die('No URL to check');

}

我們首先配置好數(shù)據(jù)庫,一系列要排除的域名($excluded_domains),以及最大同時(shí)連接數(shù)量($max_connections)。然后,連接數(shù)據(jù)庫,獲取文章和包含的鏈接,把它們收集到一個(gè)數(shù)組中($url_list)。

下面的代碼有點(diǎn)復(fù)雜了,因此我將一小步一小步地詳細(xì)解釋:

// 1. 批處理器$mh = curl_multi_init();// 2. 加入需批量處理的URLfor ($i = 0; $i < $max_connections; $i++) {? ? ? ? add_url_to_multi_handle($mh, $url_list);}// 3. 初始處理do {? ? ? ? $mrc = curl_multi_exec($mh, $active);}while ($mrc == CURLM_CALL_MULTI_PERFORM);// 4. 主循環(huán)while ($active && $mrc == CURLM_OK) {// 5. 有活動(dòng)連接if (curl_multi_select($mh) != -1) {// 6. 干活do {? ? ? ? ? ? ? ? ? ? ? ? $mrc = curl_multi_exec($mh, $active);? ? ? ? ? ? ? ? }while ($mrc == CURLM_CALL_MULTI_PERFORM);// 7. 有信息否?if ($mhinfo = curl_multi_info_read($mh)) {// 意味著該連接正常結(jié)束// 8. 從curl句柄獲取信息? ? ? ? ? ? ? ? ? ? ? ? $chinfo = curl_getinfo($mhinfo['handle']);// 9. 死鏈么?if (!$chinfo['http_code']) {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? $dead_urls []= $chinfo['url'];// 10. 404了?? ? ? ? ? ? ? ? ? ? ? ? }elseif ($chinfo['http_code'] == 404) {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? $not_found_urls []= $chinfo['url'];// 11. 還能用? ? ? ? ? ? ? ? ? ? ? ? }else {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? $working_urls []= $chinfo['url'];? ? ? ? ? ? ? ? ? ? ? ? }// 12. 移除句柄? ? ? ? ? ? ? ? ? ? ? ? curl_multi_remove_handle($mh, $mhinfo['handle']);? ? ? ? ? ? ? ? ? ? ? ? curl_close($mhinfo['handle']);// 13. 加入新URL,干活if (add_url_to_multi_handle($mh, $url_list)) {do {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? $mrc = curl_multi_exec($mh, $active);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }while ($mrc == CURLM_CALL_MULTI_PERFORM);? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }? ? ? ? }}// 14. 完了curl_multi_close($mh);echo"==Dead URLs==\n";echo implode("\n",$dead_urls) ."\n\n";echo"==404 URLs==\n";echo implode("\n",$not_found_urls) ."\n\n";echo"==Working URLs==\n";echo implode("\n",$working_urls);// 15. 向批處理器添加urlfunctionadd_url_to_multi_handle($mh, $url_list) {static $index = 0;// 如果還剩url沒用if ($url_list[$index]) {// 新建curl句柄? ? ? ? ? ? ? ? $ch = curl_init();// 配置url? ? ? ? ? ? ? ? curl_setopt($ch, CURLOPT_URL, $url_list[$index]);// 不想輸出返回的內(nèi)容? ? ? ? ? ? ? ? curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);// 重定向到哪兒我們就去哪兒? ? ? ? ? ? ? ? curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);// 不需要內(nèi)容體,能夠節(jié)約帶寬和時(shí)間? ? ? ? ? ? ? ? curl_setopt($ch, CURLOPT_NOBODY, 1);// 加入到批處理器中? ? ? ? ? ? ? ? curl_multi_add_handle($mh, $ch);// 撥一下計(jì)數(shù)器,下次調(diào)用該函數(shù)就能添加下一個(gè)url了? ? ? ? ? ? ? ? $index++;returntrue;? ? ? ? }else {// 沒有新的URL需要處理了returnfalse;

}

}

下面解釋一下以上代碼。列表的序號(hào)對(duì)應(yīng)著代碼注釋中的順序數(shù)字。

新建一個(gè)批處理句柄。

稍后我們將創(chuàng)建一個(gè)把URL加入批處理器的函數(shù)add_url_to_multi_handle()。每當(dāng)這個(gè)函數(shù)被調(diào)用,就有一個(gè)新url被加入批處理器。一開始,我們給批處理器添加了10個(gè)URL(這一數(shù)字由$max_connections所決定)。

運(yùn)行curl_multi_exec()進(jìn)行初始化工作是必須的,只要它返回CURLM_CALL_MULTI_PERFORM就還有事情要做。這么做主要是為了創(chuàng)建連接,它不會(huì)等待完整的URL響應(yīng)。

只要批處理中還有活動(dòng)連接主循環(huán)就會(huì)一直持續(xù)。

curl_multi_select()會(huì)一直等待,直到某個(gè)URL查詢產(chǎn)生活動(dòng)連接。

cURL的活兒又來了,主要是獲取響應(yīng)數(shù)據(jù)。

檢查各種信息。當(dāng)一個(gè)URL請(qǐng)求完成時(shí),會(huì)返回一個(gè)數(shù)組。

在返回的數(shù)組中有一個(gè) cURL 句柄。我們利用其獲取單個(gè) cURL 請(qǐng)求的相應(yīng)信息。

如果這是一個(gè)死鏈或者請(qǐng)求超時(shí),不會(huì)返回http狀態(tài)碼。

如果這個(gè)頁面找不到了,會(huì)返回404狀態(tài)碼。

其他情況我們都認(rèn)為這個(gè)鏈接是可用的(當(dāng)然,你也可以再檢查一下500錯(cuò)誤之類…)。

從該批次移除這個(gè) cURL 句柄,因?yàn)樗呀?jīng)沒有利用價(jià)值了,關(guān)了它!

很好,現(xiàn)在可以另外加一個(gè)URL進(jìn)來了。再一次地,初始化工作又開始進(jìn)行…

嗯,該干的都干了。關(guān)閉批處理器,生成報(bào)告。

回過頭來看給批處理器添加新 URL 的函數(shù)。這個(gè)函數(shù)每調(diào)用一次,靜態(tài)變量$index就遞增一次,這樣我們才能知道還剩多少 URL 沒處理。

我把這個(gè)腳本在我的博客上跑了一遍(測(cè)試需要,有一些錯(cuò)誤鏈接是故意加上的),共檢查約40個(gè)URL,只耗費(fèi)兩秒不到。當(dāng)需要檢查更加大量的URL時(shí),其省心省力的效果可想而知!如果你同時(shí)打開10個(gè)連接,還能再快上10倍!另外,你還可以利用cURL批處理的無隔斷特性,來處理大量URL請(qǐng)求,而不會(huì)阻塞你的Web腳本。

10 另一些有用的cURL 選項(xiàng)

10.1 HTTP 認(rèn)證

如果某個(gè)URL請(qǐng)求需要基于 HTTP 的身份驗(yàn)證,你可以使用下面的代碼:

$url ="http://www.somesite.com/members/";$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);// 發(fā)送用戶名和密碼curl_setopt($ch, CURLOPT_USERPWD,"myusername:mypassword");// 你可以允許其重定向curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);// 下面的選項(xiàng)讓 cURL 在重定向后// 也能發(fā)送用戶名和密碼

curl_setopt($ch, CURLOPT_UNRESTRICTED_AUTH, 1);

$output = curl_exec($ch);

curl_close($ch);

10.2 FTP 上傳

PHP 自帶有FTP 類庫, 但你也能用 cURL:

// 打開一個(gè)文件指針$file = fopen("/path/to/file","r");$size = filesize("/path/to/file");// url里包含了大部分所需信息$url ="ftp://username:password@mydomain.com:21/path/to/new/file";$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);// 上傳相關(guān)的選項(xiàng)curl_setopt($ch, CURLOPT_UPLOAD, 1);curl_setopt($ch, CURLOPT_INFILE, $file);curl_setopt($ch, CURLOPT_INFILESIZE, $size);// 是否開啟ASCII模式 (上傳文本文件時(shí)有用)

curl_setopt($ch, CURLOPT_FTPASCII, 1);

$output = curl_exec($ch);

curl_close($ch);

10.3 代理/FQ請(qǐng)求

你可以用代理發(fā)起 cURL 請(qǐng)求:

$ch = curl_init();curl_setopt($ch, CURLOPT_URL,'http://www.example.com');curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);// 指定代理地址curl_setopt($ch, CURLOPT_PROXY,'11.11.11.11:8080');// 如果需要的話,提供用戶名和密碼curl_setopt($ch, CURLOPT_PROXYUSERPWD,'username:password');

$output = curl_exec($ch);

curl_close ($ch);

10.4 回調(diào)函數(shù)

可以在一個(gè)URL請(qǐng)求過程中,讓 cURL 調(diào)用某指定的回調(diào)函數(shù)。例如,在內(nèi)容或者響應(yīng)下載的過程中,立刻開始利用數(shù)據(jù),而不用等到完全下載完。

$ch = curl_init();curl_setopt($ch, CURLOPT_URL,'http://net.tutsplus.com');curl_setopt($ch, CURLOPT_WRITEFUNCTION,"progress_function");curl_exec($ch);curl_close ($ch);functionprogress_function($ch, $str) {echo $str;return strlen($str);

}

這個(gè)回調(diào)函數(shù)必須返回字串的長(zhǎng)度,不然此功能將無法正常使用。在URL響應(yīng)接收的過程中,只要收到一個(gè)數(shù)據(jù)包,這個(gè)函數(shù)就會(huì)被調(diào)用。

更多信息請(qǐng)關(guān)注千鋒PHP,千鋒論壇

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 原文地址:PHPcURL庫函數(shù)抓取頁面內(nèi)容(轉(zhuǎn))作者:巴克 cURL是一個(gè)利用URL語法規(guī)定來傳輸文件和數(shù)據(jù)的工具...
    司馬東陽閱讀 1,267評(píng)論 0 3
  • cURL是一個(gè)利用URL語法規(guī)定來傳輸文件和數(shù)據(jù)的工具,支持很多協(xié)議和選項(xiàng),如HTTP、FTP、TELNET等,能...
    你很鬧i閱讀 367評(píng)論 0 1
  • 所有的事情:美好的或者糟糕的特別美好的或者特別糟糕的對(duì)我們來說唯一能做的便是----延緩 美好的事情和特別美好的事...
    asker閱讀 254評(píng)論 0 0
  • 2017營(yíng)銷最佳實(shí)踐論之五十二: 蘋果設(shè)計(jì)負(fù)責(zé)人Jonathan Ive參加一檔兒童電視節(jié)目,他以午餐盒為例向孩子...
    馬唐閱讀 136評(píng)論 0 0
  • 我越來越意識(shí)到,我總是在奔忙。 我從一件事沖向另一件事,在吃飯、速讀書籍和文章中搶時(shí)間。我總是急于完成手上的任務(wù)或...
    東方云逸閱讀 493評(píng)論 0 1

友情鏈接更多精彩內(nèi)容