php curl批处理实现可控并发异步操作示例
本文实例讲述了phpcurl批处理实现可控并发异步操作。分享给大家供大家参考,具体如下:
通常情况下PHP中的cURL是阻塞运行的,就是说创建一个cURL请求以后必须等它执行成功或者超时才会执行下一个请求:API接口访问一般会首选CURL
在实际项目或者自己编写小工具(比如新闻聚合,商品价格监控,比价)的过程中,通常需要从第3方网站或者API接口获取数据,在需要处理1个URL队列时,为了提高性能,可以采用cURL提供的curl_multi_*族函数实现简单的并发.
'; print_r($response); echo'
'.date("Y-m-dH:i:s").'
'; echo'
'.str_repeat("-",100).'
'; } $USER_COOKIE=(!empty($_REQUEST['cookie']))?$_REQUEST['cookie']:file_get_contents("cookie.txt"); $curl=newCurl("callback"); $data=array( array( 'url'=>'http://dyactive2.vip.xunlei.com/com_sign/?game=qmr&type=rec_gametime&referfrom=&rt=0.42521539455332336',//秦美人 'method'=>'POST', 'post_data'=>'', 'header'=>null, 'options'=>array( CURLOPT_REFERER=>"http://niu.xunlei.com/entergame/?gameNo=qmr&fenQuNum=3", CURLOPT_COOKIE=>$USER_COOKIE, ) ), array( 'url'=>'http://dyactive2.vip.xunlei.com/com_sign/?game=sq&type=rec_gametime&referfrom=&rt=0.42521539455332336',//神曲 'method'=>'POST', 'post_data'=>'', 'header'=>null, 'options'=>array( CURLOPT_REFERER=>"http://niu.xunlei.com/entergame/?gameNo=sq&fenQuNum=41", CURLOPT_COOKIE=>$USER_COOKIE, ) ), array( 'url'=>'http://dyactive2.vip.xunlei.com/com_sign/?game=frxz&type=rec_gametime&referfrom=&rt=0.42521539455332336',//凡人修真 'method'=>'POST', 'post_data'=>'', 'header'=>null, 'options'=>array( CURLOPT_REFERER=>"http://niu.xunlei.com/entergame/?gameNo=frxz&fenQuNum=3", CURLOPT_COOKIE=>$USER_COOKIE, ) ), array( 'url'=>'http://dyactive2.vip.xunlei.com/com_sign/?game=smxj&type=rec_gametime&referfrom=&rt=0.42521539455332336',//神魔仙界 'method'=>'POST', 'post_data'=>'', 'header'=>null, 'options'=>array( CURLOPT_REFERER=>"http://niu.xunlei.com/entergame/?gameNo=smxj&fenQuNum=2", CURLOPT_COOKIE=>$USER_COOKIE, ) ), array( 'url'=>'http://dyactive2.vip.xunlei.com/com_sign/?game=qsqy&type=rec_gametime&referfrom=&rt=0.42521539455332336',//倾世情缘 'method'=>'POST', 'post_data'=>'', 'header'=>null, 'options'=>array( CURLOPT_REFERER=>"http://niu.xunlei.com/entergame/?gameNo=qsqy&fenQuNum=11", CURLOPT_COOKIE=>$USER_COOKIE, ) ), ); foreach($dataas$val){ $request=newCurl_request($val['url'],$val['method'],$val['post_data'],$val['header'],$val['options']); $curl->add($request); } $curl->execute(); echo$curl->display_errors();
使用下来效果很好,没有副作用,并发数可控,应用之处多多,自己发挥想象吧
*@linkhttp://t.qq.com/JustPzy */ /** *单一的请求对象 */ classCurl_request{ public$url=''; public$method='GET'; public$post_data=null; public$headers=null; public$options=null; /** * *@paramstring$url *@paramstring$method *@paramstring$post_data *@paramstring$headers *@paramarray$options *@returnvoid */ publicfunction__construct($url,$method='GET',$post_data=null,$headers=null,$options=null){ $this->url=$url; $this->method=strtoupper($method); $this->post_data=$post_data; $this->headers=$headers; $this->options=$options; } /** *@returnvoid */ publicfunction__destruct(){ unset($this->url,$this->method,$this->post_data,$this->headers,$this->options); } } /** *包含请求列队处理 */ classCurl{ /** *请求url个数 *@varint */ private$size=5; /** *等待所有cURL批处理中的活动连接等待响应时间 *@varint */ private$timeout=5; /** *完成请求回调函数 *@varstring */ private$callback=null; /** *cRUL配置 *@vararray */ private$options=array(CURLOPT_SSL_VERIFYPEER=>0,CURLOPT_RETURNTRANSFER=>1,CURLOPT_CONNECTTIMEOUT=>30); /** *请求头 *@vararray */ private$headers=array(); /** *请求列队 *@vararray */ private$requests=array(); /** *请求列队索引 *@vararray */ private$request_map=array(); /** *错误 *@vararray */ private$errors=array(); /** *@accesspublic *@paramstring$callback回调函数 *该函数有4个参数($response,$info,$error,$request) *$responseurl返回的body *$infocURL连接资源句柄的信息 *$error错误 *$request请求对象 */ publicfunction__construct($callback=null){ $this->callback=$callback; } /** *添加一个请求对象到列队 *@accesspublic *@paramobject$request *@returnboolean */ publicfunctionadd($request){ $this->requests[]=$request; returnTRUE; } /** *创建一个请求对象并添加到列队 *@accesspublic *@paramstring$url *@paramstring$method *@paramstring$post_data *@paramstring$headers *@paramarray$options *@returnboolean */ publicfunctionrequest($url,$method='GET',$post_data=null,$headers=null,$options=null){ $this->requests[]=newCurl_request($url,$method,$post_data,$headers,$options); returnTRUE; } /** *创建GET请求对象 *@accesspublic *@paramstring$url *@paramstring$headers *@paramarray$options *@returnboolean */ publicfunctionget($url,$headers=null,$options=null){ return$this->request($url,"GET",null,$headers,$options); } /** *创建一个POST请求对象 *@accesspublic *@paramstring$url *@paramstring$post_data *@paramstring$headers *@paramarray$options *@returnboolean */ publicfunctionpost($url,$post_data=null,$headers=null,$options=null){ return$this->request($url,"POST",$post_data,$headers,$options); } /** *执行cURL *@accesspublic *@paramint$size最大连接数 *@returnAmbigous|boolean */ publicfunctionexecute($size=null){ if(sizeof($this->requests)==1){ return$this->single_curl(); }else{ return$this->rolling_curl($size); } } /** *单个url请求 *@accessprivate *@returnmixed|boolean */ privatefunctionsingle_curl(){ $ch=curl_init(); $request=array_shift($this->requests); $options=$this->get_options($request); curl_setopt_array($ch,$options); $output=curl_exec($ch); $info=curl_getinfo($ch); //it'snotneccesarytosetacallbackforone-offrequests if($this->callback){ $callback=$this->callback; if(is_callable($this->callback)){ call_user_func($callback,$output,$info,$request); } }else return$output; returntrue; } /** *多个url请求 *@accessprivate *@paramint$size最大连接数 *@returnboolean */ privatefunctionrolling_curl($size=null){ if($size) $this->size=$size; else $this->size=count($this->requests); if(sizeof($this->requests)<$this->size) $this->size=sizeof($this->requests); if($this->size<2) $this->set_error('sizemustbegreaterthan1'); $master=curl_multi_init(); //添加cURL连接资源句柄到map索引 for($i=0;$i<$this->size;$i++){ $ch=curl_init(); $options=$this->get_options($this->requests[$i]); curl_setopt_array($ch,$options); curl_multi_add_handle($master,$ch); $key=(string)$ch; $this->request_map[$key]=$i; } $active=$done=null; do{ while(($execrun=curl_multi_exec($master,$active))==CURLM_CALL_MULTI_PERFORM) ; if($execrun!=CURLM_OK) break; //有一个请求完成则回调 while($done=curl_multi_info_read($master)){ //$done完成的请求句柄 $info=curl_getinfo($done['handle']);// $output=curl_multi_getcontent($done['handle']);// $error=curl_error($done['handle']);// $this->set_error($error); //调用回调函数,如果存在的话 $callback=$this->callback; if(is_callable($callback)){ $key=(string)$done['handle']; $request=$this->requests[$this->request_map[$key]]; unset($this->request_map[$key]); call_user_func($callback,$output,$info,$error,$request); } curl_close($done['handle']); //从列队中移除已经完成的request curl_multi_remove_handle($master,$done['handle']); } //等待所有cURL批处理中的活动连接 if($active) curl_multi_select($master,$this->timeout); }while($active); //完成关闭 curl_multi_close($master); returntrue; } /** *获取没得请求对象的cURL配置 *@accessprivate *@paramobject$request *@returnarray */ privatefunctionget_options($request){ $options=$this->__get('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=$request->options+$options; } $options[CURLOPT_URL]=$request->url; if($request->post_data&&strtolower($request->method)=='post'){ $options[CURLOPT_POST]=1; $options[CURLOPT_POSTFIELDS]=$request->post_data; } if($headers){ $options[CURLOPT_HEADER]=0; $options[CURLOPT_HTTPHEADER]=$headers; } return$options; } /** *设置错误信息 *@accesspublic *@paramstring$msg */ publicfunctionset_error($msg){ if(!empty($msg)) $this->errors[]=$msg; } /** *获取错误信息 *@accesspublic *@paramstring$open *@paramstring$close *@returnstring */ publicfunctiondisplay_errors($open=' ',$close='
'){ $str=''; foreach($this->errorsas$val){ $str.=$open.$val.$close; } return$str; } /** *@accesspublic *@paramstring$name *@paramstring$value *@returnboolean */ publicfunction__set($name,$value){ if($name=='options'||$name=='headers'){ $this->{$name}=$value+$this->{$name}; }else{ $this->{$name}=$value; } returnTRUE; } /** * *@paramstring$name *@returnmixed *@accesspublic */ publicfunction__get($name){ return(isset($this->{$name}))?$this->{$name}:null; } /** *@returnvoid *@accesspublic */ publicfunction__destruct(){ unset($this->size,$this->timeout,$this->callback,$this->options,$this->headers,$this->requests,$this->request_map,$this->errors); } } //ENDCurlClass /*Endoffilecurl.class.php*/
更多关于PHP相关内容感兴趣的读者可查看本站专题:《phpcurl用法总结》、《PHP网络编程技巧总结》、《PHP数组(Array)操作技巧大全》、《php字符串(string)用法总结》、《PHP数据结构与算法教程》、《php程序设计算法总结》、《PHP运算与运算符用法总结》及《php常见数据库操作技巧汇总》
希望本文所述对大家PHP程序设计有所帮助。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。