一、引言
這段時間比較忙,已經很久沒有寫部落格了。今天我就來聊聊我關於curl_multi_*函數集的使用心得,關於http請求的問題。
當我們使用者php發起一個http請求的時候。我們會首先想到用什嗎?沒錯,我們會建立curl來請求。當我們在一次執行中需要發起多個http請求呢。這簡單,對每一個URL發起一次url請求。請求玩第1個再請求第2個….這就完了?哪我們還說個啥。
官網連結:http://php.net/manual/zh/book.curl.php
二、多次簡單的curl請求弊端
我們舉個栗子。現在有三個http請求。每個請求耗時2s。如果按照簡單的curl請求(圖1-(1))。耗時6s.這是不能容忍的。如果請求的個數越多耗時約多。
有沒有一種方式來縮小查詢時間?能不能三個http請求同時執行(1-(1))?有很多方法來解決這個問題,將耗時減少到2s。如:多進程、線程、事件迴圈、curl_multi_*等等。最簡單的方式就是通過curl_multi_*函數來完成。事實上curl_multi_*內部實現就是用的事件迴圈。
三、簡單的curl_multi_*運用
/** * * curl_multi_*簡單運用 * * @author: rudy * @date: 2016/07/12 *//** * 根據url,postData擷取curl請求對象,這個比較簡單,可以看官方文檔 */functiongetCurlObject($url,$postData=array(),$header=array()){$options = array(); $url = trim($url); $options[CURLOPT_URL] = $url; $options[CURLOPT_TIMEOUT] = 10; $options[CURLOPT_USERAGENT] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36'; $options[CURLOPT_RETURNTRANSFER] = true; // $options[CURLOPT_PROXY] = '127.0.0.1:8888';foreach($headeras$key=>$value){ $options[$key] =$value; } if(!empty($postData) && is_array($postData)){ $options[CURLOPT_POST] = true; $options[CURLOPT_POSTFIELDS] = http_build_query($postData); } if(stripos($url,'https') === 0){ $options[CURLOPT_SSL_VERIFYPEER] = false; } $ch = curl_init(); curl_setopt_array($ch,$options); return$ch;}// 建立三個待請求的url對象$chList = array();$chList[] = getCurlObject('https://www.baidu.com');$chList[] = getCurlObject('http://www.jd.com');$chList[] = getCurlObject('http://www.jianshu.com/');// 建立多請求執行對象$downloader = curl_multi_init();// 將三個待請求對象放入下載器中foreach ($chListas$ch){ curl_multi_add_handle($downloader,$ch);}// 輪詢do { while (($execrun = curl_multi_exec($downloader, $running)) == CURLM_CALL_MULTI_PERFORM) ; if ($execrun != CURLM_OK) { break; } // 一旦有一個請求完成,找出來,處理,因為curl底層是select,所以最大受限於1024while ($done = curl_multi_info_read($downloader)) { // 從請求中擷取資訊、內容、錯誤$info = curl_getinfo($done['handle']); $output = curl_multi_getcontent($done['handle']); $error = curl_error($done['handle']); // 將請求結果儲存,我這裡是列印出來print$output;// print "一個請求下載完成!\n";// 把請求已經完成了得 curl handle 刪除 curl_multi_remove_handle($downloader, $done['handle']); } // 當沒有資料的時候進行堵塞,把 CPU 使用權交出來,避免上面 do 死迴圈空跑資料導致 CPU 100%if ($running) { $rel = curl_multi_select($downloader, 1); if($rel == -1){ usleep(1000); } } if( $running == false){ break; }} while (true);// 下載完畢,關閉下載器curl_multi_close($downloader);echo"所有請求下載完成!";
在該例子中,首先建立三個或多個要請求的url請求對象。通過curl_multi_*函數建立下載器。將請求寫入下載器中。最後輪詢。等待三個請求現在完成。做處理。
四、複雜的curl_multi_*運用
這就是curl_multi_*用法?too yong too simple!在上面的例子中。下載器$downloader中的請求是一開始就添加好了的。我們能不能動態向下載器中添加請求。動態從下載器中取出已經完成了的請求。想想。這是什嗎?這不就是爬蟲的核心部分-動態下載器。如何動態添加?我們可以用多進程通過IPC添加。我們可以通過協程通過隊列添加等待。
我這實現了一個通過協程+curl_multi_*的爬蟲架構。
Tspider:https://github.com/hirudy/Tspider。
單進程可處理請求2000-5000/min。
').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('
').text(i)); }; $numbering.fadeIn(1700); }); });
以上就介紹了 php中curl_multi函數集的用法,包括了方面的內容,希望對PHP教程有興趣的朋友有所協助。