下面的代碼有點復雜了,因此我將一小步一小步地詳細解釋:
// 1. 批處理器 $mh = curl_multi_init(); // 2. 加入需批量處理的URL for ($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. 有活動連接 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了? } else if ($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. 向批處理器添加url function add_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é)約帶寬和時間 curl_setopt($ch, CURLOPT_NOBODY, 1); // 加入到批處理器中 curl_multi_add_handle($mh, $ch); // 撥一下計數(shù)器,下次調(diào)用該函數(shù)就能添加下一個url了 $index++; return true; } else { // 沒有新的URL需要處理了 return false; } }
下面解釋一下以上代碼。列表的序號對應著代碼注釋中的順序數(shù)字。
- 新建一個批處理器。Created a multi handle.
- 稍后我們將創(chuàng)建一個把URL加入批處理器的函數(shù) add_url_to_multi_handle() 。每當這個函數(shù)被調(diào)用,就有一個新url被加入批處理器。一開始,我們給批處理器添加了10個URL(這一數(shù)字由 $max_connections 所決定)。
- 運行 curl_multi_exec() 進行初始化工作是必須的,只要它返回 CURLM_CALL_MULTI_PERFORM 就還有事情要做。這么做主要是為了創(chuàng)建連接,它不會等待完整的URL響應。
- 只要批處理中還有活動連接主循環(huán)就會一直持續(xù)。
- curl_multi_select() 會一直等待,直到某個URL查詢產(chǎn)生活動連接。
- cURL的活兒又來了,主要是獲取響應數(shù)據(jù)。
- 檢查各種信息。當一個URL請求完成時,會返回一個數(shù)組。
- 在返回的數(shù)組中有一個 cURL 句柄。我們利用其獲取單個cURL請求的相應信息。
- 如果這是一個死鏈或者請求超時,不會返回http狀態(tài)碼。
- 如果這個頁面找不到了,會返回404狀態(tài)碼。
- 其他情況我們都認為這個鏈接是可用的(當然,你也可以再檢查一下500錯誤之類...)。
- 從該批次移除這個cURL句柄,因為它已經(jīng)沒有利用價值了,關(guān)了它!
- 很好,現(xiàn)在可以另外加一個URL進來了。再一次地,初始化工作又開始進行...
- 嗯,該干的都干了。關(guān)閉批處理器,生成報告。
- 回過頭來看給批處理器添加新URL的函數(shù)。這個函數(shù)每調(diào)用一次,靜態(tài)變量 $index 就遞增一次,這樣我們才能知道還剩多少URL沒處理。
我把這個腳本在我的博客上跑了一遍(測試需要,有一些錯誤鏈接是故意加上的),結(jié)果如下:
<img border="0" src="http://nettuts.s3.cdn.plus.org/534_curl/ss_4.png" />
共檢查約40個URL,只耗費兩秒不到。當需要檢查更加大量的URL時,其省心省力的效果可想而知!如果你同時打開10個連接,還能再快上10倍!另外,你還可以利用cURL批處理的無隔斷特性來處理大量URL請求,而不會阻塞你的Web腳本。
出處:藍色理想
責任編輯:moby
上一頁 基于PHP的cURL快速入門 [4] 下一頁 基于PHP的cURL快速入門 [6]
◎進入論壇網(wǎng)絡編程版塊參加討論
|