cURL库的强大功能和灵活的扩展性_第1页
cURL库的强大功能和灵活的扩展性_第2页
cURL库的强大功能和灵活的扩展性_第3页
cURL库的强大功能和灵活的扩展性_第4页
cURL库的强大功能和灵活的扩展性_第5页
已阅读5页,还剩6页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

cURL库的强大功能和灵活的扩展性cURL是一个利用URL语法规定来传输文件和数据的工具,支持很多协议,如HTTP、FTP、TELNET等。最爽的是,PHP也支持cURL库。本文将介绍cURL的一些高级特性,以及在PHP中如何运用它。为什么要用cURL?是的,我们可以通过其他办法获取网页内容。大多数时候,我因为想偷懒,都直接用简单的PHP函数:$content=file_get_contents("");//or$lines=file("");//orreadfile();不过,这种做法缺乏灵活性和有效的错误处理。而且,你也不能用它完成一些高难度任务——比如处理coockies、验证、表单提交、文件上传等等。引用:cURL是一种功能强大的库,支持很多不同的协议、选项,能提供URL请求相关的各种细节信息。基本结构在学习更为复杂的功能之前,先来看一下在PHP中建立cURL请求的基本步骤:初始化设置变量执行并获取结果释放cURL句柄//1.初始化$ch=curl_init();//2.设置选项,包括URLcurl_setopt($ch,CURLOPT_URL,"");curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);curl_setopt($ch,CURLOPT_HEADER,0);//3.执行并获取HTML文档内容$output=curl_exec($ch);//4.释放curl句柄curl_close($ch);第二步(也就是curl_setopt())最为重要,一切玄妙均在此。有一长串cURL参数可供设置,它们能指定URL请求的各个细节。要一次性全部看完并理解可能比较困难,所以今天我们只试一下那些更常用也更有用的选项。检查错误你可以加一段检查错误的语句(虽然这并不是必需的)://...$output=curl_exec($ch);if($output===FALSE){echo"cURLError:".curl_error($ch);}//...请注意,比较的时候我们用的是“===FALSE”,而非“==FALSE”。因为我们得区分空输出和布尔值FALSE,后者才是真正的错误。获取信息这是另一个可选的设置项,能够在cURL执行后获取这一请求的有关信息://...curl_exec($ch);$info=curl_getinfo($ch);echo'获取'.$info['url'].'耗时'.$info['total_time'].'秒';//...返回的数组中包括了以下信息:“url”//资源网络地址“content_type”//内容编码“http_code”//HTTP状态码“header_size”//header的大小“request_size”//请求的大小“filetime”//文件创建时间“ssl_verify_result”//SSL验证结果“redirect_count”//跳转技术“total_time”//总耗时“namelookup_time”//DNS查询耗时“connect_time”//等待连接耗时“pretransfer_time”//传输前准备耗时“size_upload”//上传数据的大小“size_download”//下载数据的大小“speed_download”//下载速度“speed_upload”//上传速度“download_content_length”//下载内容的长度“upload_content_length”//上传内容的长度“starttransfer_time”//开始传输的时间“redirect_time”//重定向耗时基于浏览器的重定向在第一个例子中,我们将提供一段用于侦测服务器是否有基于浏览器的重定向的代码。例如,有些网站会根据是否是手机浏览器甚至用户来自哪个国家来重定向网页。我们利用CURLOPT_HTTPHEADER选项来设定我们发送出的HTTP请求头信息(httpheaders),包括useragent信息和默认语言。然后我们来看看这些特定网站是否会把我们重定向到不同的URL。//测试用的URL$urls=array("","","");//测试用的浏览器信息$browsers=array("standard"=>array("user_agent"=>"Mozilla/5.0(Windows;U;WindowsNT6.1;en-US;rv:)Gecko/20091201Firefox/3.5.6(.NETCLR3.5.30729)","language"=>"en-us,en;q=0.5"),"iphone"=>array("user_agent"=>"Mozilla/5.0(iPhone;U;CPUlikeMacOSX;en)AppleWebKit/420+(KHTML,likeGecko)Version/3.0Mobile/1A537aSafari/419.3","language"=>"en"),"french"=>array("user_agent"=>"Mozilla/4.0(compatible;MSIE7.0;WindowsNT5.1;GTB6;.NETCLR2.0.50727)","language"=>"fr,fr-FR;q=0.5"));foreach($urlsas$url){echo"URL:$url\n";foreach($browsersas$test_name=>$browser){$ch=curl_init();//设置urlcurl_setopt($ch,CURLOPT_URL,$url);//设置浏览器的特定headercurl_setopt($ch,CURLOPT_HTTPHEADER,array("User-Agent:{$browser['user_agent']}","Accept-Language:{$browser['language']}"));//页面内容我们并不需要curl_setopt($ch,CURLOPT_NOBODY,1);//只需返回HTTPheadercurl_setopt($ch,CURLOPT_HEADER,1);//返回结果,而不是输出它curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);$output=curl_exec($ch);curl_close($ch);//有重定向的HTTP头信息吗?if(preg_match("!Location:(.*)!",$output,$matches)){echo"$test_name:redirectsto$matches[1]\n";}else{echo"$test_name:noredirection\n";echo"\n\n";}首先,我们建立一组需要测试的URL,接着指定一组需要测试的浏览器信息。最后通过循环测试各种URL和浏览器匹配可能产生的情况。因为我们指定了cURL选项,所以返回的输出内容则只包括HTTP头信息(被存放于$output中)。利用一个简单的正则,我们检查这个头信息中是否包含了“Location:”字样。运行这段代码应该会返回如下结果:URL:http://www.cnn.corestandard:noledirectionip-hone:redirectstohttp://it.cnn.corefrench:noredirectionURL:http://www.rtDzilla.corestandard:redirectstohttp://www.rtozilla.coic/en-US/ip-hone:redirectstohttp://www.itcizilla.coic/en-US/french:redirectstohttp://www.renzilla.coie/fr/URL:http://www.facebook,corestandard:noledirectioniphone:redirectstohttp://tQacii.facebook.coie/?w2iefrencii:noredirection用POST方法发送数据当发起GET请求时,数据可以通过“查询字串”(querystring)传递给一个URL。例如,在google中搜索时,搜索关键即为URL的查询字串的一部分:/search?q=nettuts这种情况下你可能并不需要cURL来模拟。把这个URL丢给“file_get_contents()”就能得到相同结果。不过有一些HTML表单是用POST方法提交的。这种表单提交时,数据是通过HTTP请求体(requestbody)发送,而不是查询字串。例如,当使用CodeIgniter论坛的表单,无论你输入什么关键字,总是被POST到如下页面:/forums/do_search/你可以用PHP脚本来模拟这种URL请求。首先,新建一个可以接受并显示POST数据的文件,我们给它命名为post_output.php:print_r($_POST);接下来,写一段PHP脚本来执行cURL请求:$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);//我们在POST数据哦!curl_setopt($ch,CURLOPT_POST,1);//把post的变量加上curl_setopt($ch,CURLOPT_POSTFIELDS,$post_data);$output=curl_exec($ch);curl_close($ch);echo$output;执行代码后应该会得到以下结果:Array[foo]=>tar[qjery]=>Netfjts[action]=>Suinuit这段脚本发送一个POST请求给post_output.php,这个页面$_POST变量并返回,我们利用cURL捕捉了这个输出。文件上传上传文件和前面的POST十分相似。因为所有的文件上传表单都是通过POST方法提交的。首先新建一个接收文件的页面,命名为upload_output.php:print_r($_FILES);以下是真正执行文件上传任务的脚本:$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;如果你需要上传一个文件,只需要把文件路径像一个post变量一样传过去,不过记得在前面加上@符号。执行这段脚本应该会得到如下输出:Array/jpload]=>Array;nane]=>test.zip;type]=>application/octet-streaiii[tmp_name]=>C:\wamp\trap\phpCC3.trap[error]=>0[size]=>1133642cURL批处理(multicURL)cURL还有一个高级特性——批处理句柄(handle)。这一特性允许你同时或异步地打开多个URL连接。下面是来自来自的示例代码://创建两个cURL资源$ch1=curl_init();$ch2=curl_init();//指定URL和适当的参数curl_setopt($chl,CURLOPT_URL,"/");curl_setopt($ch1,CURLOPT_HEADER,0);curl_setopt($ch2,CURLOPT_URL,"/");curl_setopt($ch2,CURLOPT_HEADER,0);//创建cURL批处理句柄$mh=curl_multi_init();//加上前面两个资源句柄curl_multi_add_handle($mh,$chl);curl_multi_add_handle($mh,$ch2);//预定义一个状态变量$active=null;//执行批处理do{$mrc=curl_multi_exec($mh,$active);}while($mrc==CURLM_CALL_MULTI_PERFORM);while($active&&$mrc==CURLM_OK){if(curl_multi_select($mh)!=-l){do{$mrc=curl_multi_exec($mh,$active);}while($mrc==CURLM_CALL_MULTI_PERFORM);}}//关闭各个句柄curl_multi_remove_handle($mh,$chl);curl_multi_remove_handle($mh,$ch2);curl_multi_close($mh);这里要做的就是打开多个cURL句柄并指派给一个批处理句柄。然后你就只需在一个while循环里等它执行完毕。这个示例中有两个主要循环。第一个do-while循环重复调用curl_multi_exec()。这个函数是无隔断(non-blocking)的,但会尽可能少地执行。它返回一个状态值,只要这个值等于常量CURLM_CALL_MULTI_PERFORM,就代表还有一些刻不容缓的工作要做(例如,把对应URL的http头信息发送出去)。也就是说,我们需要不断调用该函数,直到返回值发生改变。而接下来的while循环,只在$active变量为true时继续。这一变量之前作为第二个参数传给了curl_multi_exec(),代表只要批处理句柄中是否还有活动连接。接着,我们调用curl_multi_select(),在活动连接(例如接受服务器响应)出现之前,它都是被“屏蔽”的。这个函数成功执行后,我们又会进入另一个do-while循环,继续下一条URL。还是来看一看怎么把这一功能用到实处吧:WordPress连接检查器想象一下你有一个文章数目庞大的博客,这些文章中包含了大量外部网站链接。一段时间之后,因为这样那样的原因,这些链接中相当数量都失效了。要么是被和谐了,要么是整个站点都被功夫网了...我们下面建立一个脚本,分析所有这些链接,找出打不开或者404的网站/网页,并生成一个报告。请注意,以下并不是一个真正可用的WordPress插件,仅仅是一段独立功能的脚本而已,仅供演示,谢谢。好,开始吧。首先,从数据库中读取所有这些链接://CONFIG$db_host='localhost';$db_user='root';$db_pass='';$db_name='wordpress';$excluded_domains=array('localhost','');$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('Couldnotconnect:'.mysql_error());}if(!mysql_select_db($db_name)){die('Couldnotselectdb:'.mysql_error());}//找出所有含有链接的文章$q="SELECTpost_contentFROMwp_postsWHEREpost_contentLIKE'%href=%'ANDpost_status='publish'ANDpost_type='post'";$r=mysql_query($q)ordie(mysql_error());while($d=mysql_fetch_assoc($r)){//用正则匹配链接if(preg_match_all("!href=\"(.*?)\"!",$d['post_content'],$matches)){foreach($ches[1]as$url){//excludesomedomains$tmp=parse_url($url);if(in_array($tmp['host'],$excluded_domains)){continue;}//storetheurl$url_list[]=$url;}}}//移除重复链接$url_list=array_values(array_unique($url_list));if(!$url_list){die('NoURLtocheck');}我们首先配置好数据库,一系列要排除的域名($excluded_domains),以及最大并发连接数($max_connections)。然后,连接数据库,获取文章和包含的链接,把它们收集到一个数组中($url_list)。下面的代码有点复杂了,因此我将一小步一小步地详细解释://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.主循环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)){//意味着该连接正常结束//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"==DeadURLs==\n";echoimplode("\n",$dead_urls)."\n\n";echo"==404URLs==\n";echoimplode("\n",$not_found_urls)."\n\n";echo"==WorkingURLs==\n";echoimplode("\n",$working_urls);〃15.向批处理器添加urlfunctionadd_url_to_multi_handle($mh,$url_list){static$index=0;//如果还剩url没用if($url_list[$index]){//新建curl句柄$ch=curl_init();//配置urlcurl_setopt($ch,CURLOPT_URL,$url_list[$index]);//不想输出返回的内容curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);//重定向到哪儿我们就去哪儿curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);//不需要内容体,能够节约带宽和时间curl_setopt($ch,CURLOPT_NOBODY,1);//加入到批处理器中curl_multi_add_handle($mh,$ch);//拨一下计数器,下次调用该函数就能添加下一个url了$index++;returntrue;}else{//没有新的URL需要处理了returnfalse;}}下面解释一下以上代码。列表的序号对应着代码注释中的顺序数字。新建一个批处理器。Createdamultihandle.稍后我们将创建一个把URL加入批处理器的函数add_url_to_multi_handle()。每当这个函数被调用,就有一个新url被加入批处理器。一开始,我们给批处理器添加了10个URL(这一数字由$max_connections所决定)。运行curl_multi_exec()进行初始化工作是必须的,只要它返回CURLM_CALL_MULTI_PERFORM就还有事情要做。这么做主要是为了创建连接,它不会等待完整的URL响应。只要批处理中还有活动连接主循环就会一直持续。curl_multi_select()会一直等待,直到某个URL查询产生活动连接。cURL的活儿又来了,主要是获取响应数据。检查各种信息。当一个URL请求完成时,会返回一个数组。在返回的数组中有一个cURL句柄。我们利用其获取单个cURL请求的相应信息。如果这是一个死链或者请求超时,不会返回http状态码。如果这个页面找不到了,会返回404状态码。其他情况我们都认为这个链接是可用的(当然,你也可以再检查一下500错误之类...)。从该批次移除这个cURL句柄,因为它已经没有利用价值了,关了它!很好,现在可以另外加一个URL进来了。再一次地,初始化工作又开始进行...嗯,该干的都干了。关闭批处理器,生成报告。回过头来看给批处理器添加新URL的函数。这个函数每调用一次,静态变量$index就递增一次,这样我们才能知道还剩多少URL没处理。我把这个脚本在我的博客上跑了一遍(测试需要,有一些错误链接是故意加上的),结果如下:<imgborder="0"src="/534_curl/ss_4.png"/>共检查约40个URL,只耗费两秒不到。当需要检查更加大量的URL时,其省心省力的效果可想而知!如果你同时打开10个连接,还能再快上10倍!另外,你还可以利用cURL批处理的无隔断特性来处理大量URL请求,而不会阻塞你的Web脚本。另一些有用的cURL选项HTTP认证如果某个URL请求需要基于HTTP的身份验证,你可以使用下面的代码:复制内容到剪贴板代码:$url="/members/";$ch=curl_init();curl_setopt($ch,CURLOPT_URL,$url);curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);//发送用户名和密码curl_setopt($ch,CURLOPT_USERPWD,"myusername:mypassword");//你可以允许其重定向curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);//下面的选项让cURL在重定向后//也能发送用户名和密码curl_setopt($ch,CURLOPT_UNRESTRICTED_AUTH,1

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论