本處是一個可以靈活的多執行緒的呼叫 cURL的。 這裡跟php手冊http://us2.php.net/manual/zh/function.curl-multi-select.php 提供的範例不同,程式碼執行效率高不少 本處兩個文件,一個是muti_curl的文件,裡麵包含兩個class 一個是運用的方法,這裡是批次檢查代理ip是否可用
- class request_setting {
- public $url = false;
- public $method = 'GET';
- public $ post_data = null;
- public $headers = null;
- public $options = null;
- function __construct($url, $method = "GET", $post_data = null, $headers = null, $options = "GET", $post_data = null, $headers = null, $options = null) {
- $this->url = $url;
- $this->method = $method;
- $this->post_data = $post_data;
- $this-> ;headers = $ headers;
- $this->options = $options;
- }
- public function __destruct() {
- unset($this->url, $this->method , $this->post_data, $this->headers, $this->options);
- }
- }
- /**************************************************** *******************************************
- 批次操作的類
- *********************************************** ********************************************/
- class muti_curl {
- protected $thread_size = 1000🎜>;
- ;
- ;
- ;
- ;
- ;
- ;
- ;
- ;
- ;
- ; protected $timeout = 30;
- private $callback;
- protected $options = array(
- CURLOPT_SSL_VERIFYPEER => false,//停用後cURL將終止從服務端進行驗證。選項設定憑證目錄CURLOPT_SSL_VERIFYPEER(預設值為2)啟用,CURLOPT_SSL_VERIFYHOST需要設定為TRUE否則設定為FALSE。 , //將以檔案流的形式傳回curl_exec()所取得的訊息,而不是直接輸出
- CURLOPT_CONNECTTIMEOUT =>; 15、
- CURLOPT_TIMEOUT => 30,
- // CURLOPT_HTTP_VERSION_SION_A_A_SSION_SA_RL_RL_RL_RL_RLS_45S_SP])_RL_RL_A_RLS_RL_RL_RLS4_S]_A_RL_RLS_SH)4A_RL_RL_RL_RL_RLS4_S]_A4_RL_SA_RLS_RL_RL_RLS_RL_RLS_RLS4_S]_A4_RL_SA_RLS_RL_RL_RLS_RL.使用代理的時候用這個去抓取數據,更爽
- // CURLOPT_AUTOREFERER=>false,//當根據Location:重定向時,自動header中的Referer:資訊設定。
- // CURLOPT_BINARYTRANSFER=>false, //在啟用CURLOPT_RETURNTRANSFER的時候,傳回間歇的(Raw)輸出不需要設定。
- // CURLOPT_COOKIESESSION=>true,/ / 啟用時curl會直接輸入一個會話cookie,忽略其他的cookie,預設情況下cURL保留所有的cookie回傳
- // CURLOPT_CRLF=>false,// 啟用時將Unix的換行符號轉換成回車
- // CURLOPT_DNS_USE_GLOBAL_CACHE=>false, // 啟用時會啟用一個全域的DNS緩存,這樣對於執行緒安全的,並且預設啟用。
- // CURLOPT_FAILONERROR=>false, //顯示HTTP狀態碼,預設行為是忽略編號小於等於400的HTTP訊息。
- // CURLOPT_FILETIME=>true, // 啟用時會嘗試遠端文件中的資訊。結果資訊會透過curl_getinfo()函數的CURLINFO_FILETIME 選項傳回。 curl_getinfo().
- // CURLOPT_FOLLOWLOCATION=>false, // 啟用時指派伺服器伺服器傳回的"Location: "放在header中遞歸的傳回伺服器,使用CURLOPT_MAXREDIRS可以限定遞歸回傳的數量。
- // CURLOPT_FORBID_REUSE =>true, //在互動完成後強迫斷開連接,不能重複使用。
- // CURLOPT_FRESH_CONNECT=>true,// 強制取得一個新的連接,替代伺服器中的連接。
- // CURLOPT_FTP_USE_EPRT=>false,//啟用時當FTP下載時,使用EPRT(或LPRT)。設定為FALSE時指令停用EPRT和LPRT,僅使用PORT指令。
- // CURLOPT_FTP_USE_EPSV=>false,// 啟用時,在FTP傳輸過程中回復到PASV模式前先嘗試EPSV指令。設定為FALSE時取消EPSV指令。
- // CURLOPT_FTPAPPEND=>false, // 啟用時追加寫入檔案而不是覆寫它。
- // CURLOPT_FTPASCII=>false,// CURLOPT_TRANSFERTEXT 的別名。
- // CURLOPT_FTPLISTONLY=>false,// 啟用時只匯入FTP目錄
- // CURLOPT_HEADER=>true,// 啟用時分割頭檔的資訊作為資料流輸出。 // CURLINFO_HEADER_OUT=>false, // 啟用時追蹤句柄的請求字串// CURLOPT_HTTPGET=>true,// 啟用時會設定HTTP的方法為GET,因為GET是預設是,所以只會是在被修改的情況下使用。 // CURLOPT_HTTPPROXYTUNNEL =>true ,// 啟用時會透過HTTP代理來傳送。 // CURLOPT_MUTE=>true,// 啟用時將cURL函數中所有修改過的參數預設恢復值。 // CURLOPT_NETRC=>false ,// 在連接建立以後,訪問~/.netrc檔案取得使用者名稱和密碼資訊連接遠端站點。 // CURLOPT_NOBODY=>true, 啟用時將不HTML中的BODY部分進行輸出。 / / CURLOPT_NOPROGRESS=>false,//啟用時關閉curl傳輸的進度條,這樣的預設設定為啟用。 // CURLOPT_NOSIGNAL=>false,//啟用時忽略所有的curl傳遞給php進行的訊號。在SAPI多執行緒傳輸時此項目被預設為啟用。 cURL 7.10時被加入。
- // CURLOPT_POST=>false,// 啟用時會傳送一個常規的POST請求,類型為:application/x-www-form-urlencoded,就像表單提交的一樣。
- // CURLOPT_PUT=>false,// 啟用時允許HTTP傳送文件,必須同時設定CURLOPT_INFILE和CURLOPT_INFILESIZE。
- // CURLOPT_TRANSFERTEXT=>false,// 啟用後對FTP傳輸使用ASCII模式。對於LDAP,它檢索純文字資訊而非HTML。在Windows系統上,系統不會把STDOUT設定成binary模式。
- // CURLOPT_UNRESTRICTED_AUTH=>true,// 在使用CURLOPT_FOLLOWLOCATION產生的header中的多個locations中持續追加使用者名稱和密碼訊息,即使網域已變更。
- // CURLOPT_UPLOAD=>false,// 啟用後允許檔案上傳。
- // CURLOPT_VERBOSE =>true,// 啟用時會報告所有的信息,存放在STDERR或指定的CURLOPT_STDERR中。
- );
- private $headers = array();
- private $requests = array();
- private $requestMap = array();
- /*********************
- 建構一個callback的函式
- ********************/
- $this->callback = $callback;
- }
-
- /**************************************************** ****************
- 重載__get的方法
- ********************** *********************************************/ public ftion __get($名稱) {
- return (isset($this->{$name})) ? $this->{$name} : null;
- }
-
- /**************************************************** *****************
- 重載__set的方法
- ********************* **********************************/
- public function __set($name, $value) {
- // 增加一個設定到headers
- if ($name == "options" || $name == "headers") {
- $this->{$name} = $value $this->{$name };
- } else {
- $this->{$name} = $value;
- }
- return true;
- }
- // 增加一個請求
- public function add($請求) {
- $this->requests[] = $request;
- return true;
- }
-
-
- public function request($url, $method) = "GET" , $post_data = null, $headers = null, $options = null) {
- $this->requests[] = new request_setting($url, $method, $post_data, $headers, $options );
- return true;
- }
-
- public function get($url, $headers = null, $options = null) {
- return $this->request($url, "GET", null, $headers, $options);
- }
-
- public function post($url, $post_data = null, $headers = null, $options = null) {
- return $this->request( $url, "POST", $post_data, $headers, $options);
- }
-
- private function single_curl() {
- $ch = curl_init(); //初始化
- $request = array_shift($this->requests);//將第一個單元移出並作為結果
- $options = $this->get_options($request);//獲得該單元的設定
- curl_setopt_array($ch, $options);//批次設定
- $output = curl_exec($ch);
- $curl_info = curl_getinfo($ch);
-
- $curl_info = curl_getinfo($ch);
-
- if ( $this->callback) {
- $callback = $this->callback;
- if (is_callable($this->callback)) {
- call_user_func($callback, $output, $curl_info, $request );
- }
- }
- else
- return $output;
- 傳回true;
- }
-
-
- 核武函數 {$ n )($ thull
- if ($thread_size){
- $this->thread_size = $thread_size;
- }
-
- if (count($this->requests)
- $this->thread_size) {
- $this->thread_size = count($this->requests);
- }
- if ($this->thread_size $errorinfo = '線程大小必須大於1! !!!';
- throw new Exception($errorinfo);
- }
- $queue = curl_multi_init();
-
- //在執行緒開始增加任務佇列
- for (> for (> //在執行緒裡開始增加任務佇列
- for (> for (> for (> for (>) $i = 0; $i thread_size;
- $ch =curl_init();
- $options = $this->get_options($this->requests[$i]) ;
- curl_setopt_array($ch, $options) ;//取得設定
- curl_multi_add_handle($queue, $ch);//新增佇列
- $key = (string) $ch;
- $this ->requestMap[ $key] = $i;
- }
- do {
- while (($statu_run_muti_exec = curl_multi_exec($queue, $active)) == CURLM_CALL_MULTI_PERFORM) ;
- if ($statc_run_run_MULTI_{Futi_) ;
- if ($statc_run_run_m; }
- // 發現完成的一個請求,進行處理
- while ($done = curl_multi_info_read($queue)) {
- $curl_info = curl_getinfo($done['handle']);
- $輸出=curl_multi_getcontent($done['handle']);
- $callback = $this->callback;
- if (is_callable($callback)){
- $key = (string) $done[ ' handle'];
- $request = $this->requests[$this->requestMap[$key]];
- unset($this->requestMap[$key]);//這個內部提示用非常帥
- call_user_func($callback, $output, $curl_info, $request);
- }
- // 增加一個未處理的請求加入到一個已經完成的佇列
- if ($i requests) && isset($this->requests[$i]) && $i requests)) {
- $ch =curl_init();
- $options = $this->get_options($this->requests[$i]);
- curl_setopt_array($ch, $options);
- curl_multi_add_handle($queue, $ch);
- $key = (string ) $ch; $this->requestMap[$key] = $i; $i ; }
- curl_multi_remove_handle($queue, $done['handle']);
- echo "done ";
- print_r($queue);
- print_r ($done);
- }
- // 這一步非常非常重要如果有一個完成後,要重新設定設定timeout的時間
- //這裡很關鍵的一點,就是要保證第一次所有的線程裡的請求最少有一個是有效的,否則就出現第一次所有的都沒有效果,導致$active=0,因此不執行下面的東西
- if ($active >0){
- curl_multi_select($queue, $this->timeout);
- }
-
- } while ($active);
- curl_multi_close($queue);
- return true;
- }
- public function execute($ullthread_cute($ullthread_
- //判斷thread_size的大小如果只有一個請求,就用單線程模式
- if (count($this->requests) == 1) {
- return $this->single_curl();
- } else {
- return $this->rolling_curl($thread_size);
- }
- }
- private function get_options($request) {
- $options = $this-this>__(' options');
- if (ini_get('safe_mode') == 'Off' || !ini_get('safe_mode')) {
- // $options[CURLOPT_FOLLOWLOCATION] = 1;
- // $
- / $ options[CURLOPT_MAXREDIRS] = 5;
- }
- $headers = $this->__get('headers');
-
- if ($request->options) {
- $options = $options = $ request->options $options;
- }
- $options[CURLOPT_URL] = $request->url;
- //以下分別對post選項與header選項設定
- if ($request-> post_data){
- $options[CURLOPT_POST] = 1;
- $options[CURLOPT_POSTFIELDS] = $request->post_data;
- }
- if ($headers) {
$options[CURLOPT_HTTPHEADER] = $headers;- }
- return $options;
- }
-
- public function __destruct() {
- thread_size, $this->callback, $this->options, $this->headers, $this->requests);
- }
- }
- ?>
複製程式碼
-
header("content-type:text/html; charset=utf-8");
- require("muti_curl_class.php");set_time_limit(0);
- $sucesesnum=0;
- $good_proxy=array();
- function request_callback($response, $info, $request) {
- global $ ;
- // 下面的正規可以選擇性地顯示回傳的結果
- /* if (preg_match("~(.*?)~i", $response, $out )) {
- $title = $out[1];
- }*/
- // echo '
'.$response .' ';
- echo '
';
- //對回應也就是 $response 進行偵測判斷裡面是否有設定的字符,如果有判斷運用該代理成功
- if( $response !== false && substr_count($response, 'User -agent: Baiduspider') >=1 ) {
- // $result = true;
- echo "true
";
- // echo $request[options][10004];
- // print_r ($request->options);
- echo $request->options[CURLOPT_PROXY];
- $good_proxy[]=$request->options[CURLOPT_PROXY];
- }
- }
- echo '
the-->'. $sucesesnum.'// print_r ($request);
- //echo $request-> url;
- $sucesesnum ;
- echo "
";
- }
- $params = array_merge($_GET, $_POST); //此處取得傳遞過來的代理ip的位址
- $result = $proxy_ip = trim($params['ip']);
- $timeout=intval(trim($params['timeout']));
- if($timeoutif($timeout>300){$timeout=300;}
- $thread_size=intval(trim($params['thread_size']));
- if($thread_sizeize if($thread_size>300){$thread_size =300;}
-
- if($proxy_ip == '') {
- echo '請輸入IP!!';
- return;
- }
- $replace_arr1 = array(' ', 'qq代理:', 'dn28.com', 'qqip', 'qq代理', 'qqqipip ', '代理ip:', 'ip:', '代理ip','"',"'",'\','/',' ');
- $result = str_replace($replace_arr1, array (''), $result);
- $result = str_replace(",", "n", $result);
- $resArr = explode("n", $result);
- foreach( $resArr as $k => $v) {
- $posProxy = getPos($v, '@');
- if($posProxy===false){
- if (!empty($v )){$proxyip_and_port = $v; }
- }else{
- $proxyip_and_port = substr($v, 0, $posProxy);
- }
- $newRes[] =trim($proxyip_and_port) ;
- }
- print_r($newRes);
- //die();
- $option_setting = array(
- CURLOPT_SSL_VERIFYPEER => 0,
- CURLOPT_SSL_VERIFYPEER => 0, 5,
- CURLOPT_TIMEOUT => 30,
- CURLOPT_HEADER=>false,
- CURLOPT_PROXY=>'',///這個地方設定代理的位置
- );$btime=time();
- $rc = new muti_curl("request_callback");
- $rc->timeout = $timeout ;
- $rc->thread_size = $thread_size;
- foreach ($newRes as $v) {
- $option_setting[CURLOPT_PROXY]=$v;
- $request = new request_ $setting($, $setting( method = "GET", $post_data = null,$header= null, $option_setting);
- $rc->add($request);
- }
- $rc->execute();
- $etime=time();
- $usedtime=$etime-$btime;
- echo 'all'. $sucesesnum.'use'. $usedtime;
- echo '
';
- $good_proxy= array_unique($good_proxy);
- $str='';
- foreach ($good_proxy as $v){
- $str.="'".trim($v)."' ,";
- }
- $str= str_replace ( ' ' , '' ,$str );
- $str = preg_replace('/s /', ' ', $str);
- echo $str.'
';
- var_export ($good_proxy);
- //var_dump ($good_proxy);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //*************************************** ************************************************** *********************
- //************************ *******只用了一個函數
-
- function parseProxyInfo ( $proxyStr ) {
- //$proxyStr = '202.115.207.25:80@HTTP;四川省成都市四川師範大學' ;
- $posIp = getPos($proxyStr, ':');
- $ip = substr($proxyStr, 0, $posIp);
- $posPort = getPos($proxyStr, '@');
- $port = substr($proxyStr, $posIp 1, $posPort-$posIp-1);
- $posType = getPos($proxyStr, ';');
- $type = substr($proxyStr , $posPort 1, $posType-$posPort-1);
- $location = substr(strstr($proxyStr, ';'), 1);
- return array(
- 'ip' => $ ip,
- 'port' => $port,
- 'type' => $type,
- 'location' => $location
- );
- }
- function getPos($haystack, $needle){ return strpos($haystack, $needle);}
-
- 函數check_proxy_is_useful($model, $proxy_info_arr = array()) {
- 全域$params, $config;
- if($model == 'single') {
- $proxy_port = intval(trim($params['port']));
- $check_proxy_url = $config['verify_url'];
- $proxy_time_out = intval(trim($params['timeout']));
- $retry = intval(trim($params['retry']));
- $proxy_ip = trim($params['ip']);
- $proxy = 新代理( $proxy_ip, $proxy_port, $check_proxy_url, $proxy_time_out, $retry );
- // 成功返回string success,失敗返回boolean false
- $result = $proxy -> check_proxy();
- //var_dump($result);
- $proxy_str_success = ''.$proxy_ip.':'.$proxy_port.'@'.'HTTP代理驗證成功! ';
- $proxy_str_failed = ''.$proxy_ip.':'.$proxy_port.'@'.'HTTP代理驗證失敗! ';
- 回傳$result !== false ? $proxy_str_success : $proxy_str_failed;
- } elseif ($model == 'collect') {
- $proxy_port = intval(triminfo_ ['port']));
- $check_proxy_url = $config['verify_url'];
- $proxy_time_out = intval(trim($params['timeout']));
- $retry = intval($params['timeout']));
- $retry = intval( trim($params['retry']));
- $proxy_ip = trim($proxy_info_arr[ 'ip']);
- /*echo $proxy_ip.'
';
- echo $ proxy_port.'
';
- echo $check_proxy_url.'';
- echo $proxy_time_out.'
';
- echo $retry.'
' ;*/
- if(!isset($proxy) )) {
- $proxy = new proxy( $proxy_ip, $proxy_port, $check_proxy_url, $proxy_time_out, $retry );
- }
- / / 成功回傳string success,失敗回傳boolean false
- $結果= $proxy -> check_proxy();
- return $result;
- }
- }
-
- function getget_single(){
- 全域$params, $config;
- $proxy_ip = trim($params ['ip']);
- if($proxy_ip == '') {
- echo '請輸入IP!! ';
- return;
- }
- echo check_proxy_is_useful('single' );
- }
-
- function get_proxy_by_collect(){
-
- function get_proxy_by_collect(){
- 38 美元, $config; $params['url'] = trim($params['url']);
- if($params['url'] == '') {
- echo '請輸入url!';
- return;
- }
- //$url = 'http:// www.dn28.com/html/75/n-5175.html';
- $con = iconv('GBK', ' UTF-8', file_get_contents($params['url']));
- preg_match ('/
|