PHP使用CURL抓取网页

CURL是一个非常强大的开源库,支持很多协议,包括HTTP、FTP、TELNET等,我们使用它来发送HTTP请求。它给我 们带来的好处是可以通过灵活的选项设置不同的HTTP协议参数,并且支持HTTPS。CURL可以根据URL前缀是“HTTP” 还是“HTTPS”自动选择是否加密发送内容。

使用CURL的PHP扩展完成一个HTTP请求的发送一般有以下几个步骤:

  1. 初始化连接句柄;
  2. 设置CURL选项;
  3. 执行并获取结果;
  4. 释放CURL连接句柄。
一、使用curl模拟GET请求

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. $curl=curl_init();  //初始化curl句柄  
  2. $url="http://www.conglinfeng.com/together/detail.php?show_ID=5";  //要请求的url地址  
  3. curl_setopt($curl, CURLOPT_URL,$url);  //设置curl的参数,即要请求的url是$url  
  4. curl_exec($curl);  //执行操作  
  5. curl_close($curl);  //关闭句柄  
执行curl_exec()时,成功时会输出网页代码,并且返回值为 TRUE,在失败时返回 FALSE。 然而,如果 CURLOPT_RETURNTRANSFER选
项被设置,函数执行成功时会返回执行的结果,失败时返回 FALSE 。

二、使用curl模拟post请求

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. $curl=curl_init();  
  2. $url="./register.php";  
  3. curl_setopt($curl, CURLOPT_URL,$url);  
  4. curl_setopt($curl, CURLOPT_POST, true);  //设置请求为post  
  5. $post_data=array('username'=>"嘿嘿",'password'=>'111111','confirm'=>'111111',  
  6.     'email'=>"986992484@qq.com");   //要发送的数据组装成一个数组  
  7. curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);  //post的数据内容  
  8. curl_exec($curl);   
  9. curl_close($curl);  
register.php:

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. var_dump($_POST);  

三、处理响应的数据

curl_exec()执行时会直接把响应数据输出,如果不需要直接输出,可以加:curl_setopt($curl, CURLOPT_RETURNTRANSFER, true) ; 

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. $url="./register.php";  
  2. curl_setopt($curl, CURLOPT_URL,$url);  
  3. curl_setopt($curl, CURLOPT_POST, true);  //设置请求为post  
  4. $post_data=array('username'=>"嘿嘿",'password'=>'111111','confirm'=>'111111',  
  5.     'email'=>"986992484@qq.com");  
  6. curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);  //post的数据内容  
  7. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true) ; //请求执行时,不将响应数据直接输出,而是以返回值的形式输出响应数据  
  8. $res=curl_exec($curl);   
  9. echo $res;  //少了这句就输不出来了  
  10. curl_close($curl);  
四、模拟post 文件上传

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. $url="./register.php";  
  2. curl_setopt($curl, CURLOPT_URL,$url);  
  3. curl_setopt($curl, CURLOPT_POST, true);  //设置请求为post  
  4. $post_data=array('logo'=>'@D:\wamp\wamp\www\czbk\php&mysql\1.png'); // logo是$_FILES的name,后面的是图片路径,加@表示这是一个文件而不是字符串  
  5. curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);  //post的数据内容  
  6. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true) ; //请求执行时,不将响应数据直接输出,而是以返回值的形式输出响应数据  
  7. $res=curl_exec($curl);   
  8. echo $res;   
  9. curl_close($curl);  
五、输出响应头

curl默认是不输出响应头的,如果要输出,则要加:curl_setopt($curl, CURLOPT_HEADER, true); 

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. $url="http://www.conglinfeng.com/together/member/index.php";  
  2. curl_setopt($curl, CURLOPT_URL,$url);  
  3. curl_setopt($curl, CURLOPT_HEADER, true);  //将响应头输出,默认是不输出的  
  4. //  HTTP/1.1 200 OK Date: Thu, 15 Sep 2016 14:49:28 GMT Server: Apache/2.4.4 (Win32) PHP/5.4.16 X-Powered-By: PHP/5.4.16 Content-Length: 692 Content-Type: text/html  
  5. curl_exec($curl);   
  6. curl_close($curl);  
六、实例:CURL模拟登陆

可以简单和有效地抓取网页并采集内容,设置cookie完成模拟登录网页,curl提供了丰富的函数,开发者可以从PHP手册中获取更多关于cURL信息。本文以模拟登录开源中国(oschina)为例,和大家分享cURL的使用。

PHP的curl()在抓取网页的效率方面是比较高的,而且支持多线程,而file_get_contents()效率就要稍低些,当然,使用curl时需要开启下curl扩展。

先来看登录部分的代码:

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //模拟登录   
  2. function login_post($url$cookie$post) {   
  3.     $curl = curl_init();//初始化curl模块   
  4.     curl_setopt($curl, CURLOPT_URL, $url);//登录提交的地址   
  5.     curl_setopt($curl, CURLOPT_HEADER, 0);//是否显示头信息   
  6.     curl_setopt($curl, CURLOPT_RETURNTRANSFER, 0);//是否自动显示返回的信息   
  7.     curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie); //设置Cookie信息保存在指定的文件中   
  8.     curl_setopt($curl, CURLOPT_POST, 1);//post方式提交   
  9.     curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post));//要提交的信息   
  10.     curl_exec($curl);//执行cURL   
  11.     curl_close($curl);//关闭cURL资源,并且释放系统资源   
  12. }   

函数login_post()首先初始化curl_init(),然后使用curl_setopt()设置相关选项信息,包括要提交的url地址,保存的cookie文件,post的数据(用户名和密码等信息),是否返回信息等等,然后curl_exec执行curl,最后curl_close()释放资源。注意PHP自带的http_build_query()可以将数组转换成相连接的字符串。

接下来如果登录成功后,我们要获取登录成功后的页面信息。

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //登录成功后获取数据   
  2. function get_content($url$cookie) {   
  3.     $ch = curl_init();   
  4.     curl_setopt($ch, CURLOPT_URL, $url);   
  5.     curl_setopt($ch, CURLOPT_HEADER, 0);   
  6.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);   
  7.     curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie); //读取cookie   
  8.     $rs = curl_exec($ch); //执行cURL抓取页面内容   
  9.     curl_close($ch);   
  10.     return $rs;   
  11. }   

函数get_content()中也是先初始化curl,然后设置相关选项,执行curl,释放资源。其中我们设置CURLOPT_RETURNTRANSFER为1即自动返回信息,而CURLOPT_COOKIEFILE可以读取到登录时保存的cookie信息,最后将页面内容返回。

我们的最终目的是要获取到模拟登录后的信息,也就是只有正常登录成功后才能获取的有用信息。接下来我们以登录开源中国的移动版为例,看看如何抓取到登录成功后的信息。

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //设置post的数据   
  2. $post = array (   
  3.     'email' => 'oschina账户',   
  4.     'pwd' => 'oschina密码',   
  5.     'goto_page' => '/my',   
  6.     'error_page' => '/login',   
  7.     'save_login' => '1',   
  8.     'submit' => '现在登录'   
  9. );   
  10.    
  11. //登录地址   
  12. $url = "http://m.oschina.net/action/user/login";   
  13. //设置cookie保存路径   
  14. $cookie = dirname(__FILE__) . '/cookie_oschina.txt';   
  15. //登录后要获取信息的地址   
  16. $url2 = "http://m.oschina.net/my";   
  17. //模拟登录   
  18. login_post($url$cookie$post);   
  19. //获取登录页的信息   
  20. $content = get_content($url2$cookie);   
  21. //删除cookie文件   
  22. @ unlink($cookie);   
  23. //匹配页面信息   
  24. $preg = "/<td class='portrait'>(.*)<\/td>/i";   
  25. preg_match_all($preg$content$arr);   
  26. $str = $arr[1][0];   
  27. //输出内容   
  28. echo $str;   
七、封装CURL

为了便于日后调用,我们可以把这些操作封装起来。

1.模拟get或post请求

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * curl()   curl模拟请求---一个参数是get请求,两个参数是post请求 
  3.  * 
  4.  * 上传文件$post=array('logo'=>'@D:\wamp\wamp\www\czbk\php&mysql\1.png');  
  5.  * logo是$_FILES的name,后面的是图片路径,加@表示这是一个文件而不是字符串 
  6.  * 
  7.  * @param string $url   模拟请求的url 
  8.  * @param array $post   post请求时要提交的数据 
  9.  * @param boolean $header  是否要将响应头输出 
  10.  * @return string $str   返回响应结果 
  11.  */  
  12. function curl($url,$post=array(),$header=false){  
  13.   if(!$url)   return;  
  14.   
  15.   //设置资源句柄  
  16.   $curl=curl_init();  
  17.   curl_setopt($curl, CURLOPT_URL,$url);  
  18.   
  19.   //如果传$post,则说明是post请求  
  20.   if($post && is_array($post) && count($post)>0){  
  21.        curl_setopt($curl, CURLOPT_POST, 1);  
  22.        curl_setopt($curl, CURLOPT_POSTFIELDS, $post);  
  23.        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); //不验证证书  
  24.        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); //不验证证书  
  25.   }  
  26.   
  27.   //请求执行时,不将响应数据直接输出,而是以返回值的形式输出响应数据  
  28.   curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);   
  29.   
  30.   //决定要不要将响应头输出  
  31.   curl_setopt($curl, CURLOPT_HEADER,$header);   
  32.   $str=curl_exec($curl);   
  33.     
  34.   //IGNORE 忽略转换时的错误,如果没有ignore参数,所有该字符后面的字符串都无法被保存。  
  35.   $str = iconv("UTF-8","GBK//IGNORE",$str);  
  36.   curl_close($curl);  
  37.   
  38.   return $str;  
  39. }  
  2.模拟登陆

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * curl_login()   curl模拟登陆 
  3.  * 
  4.  * @param string $logUrl   登陆地址url 
  5.  * @param string $desUrl   要访问页面的url 
  6.  * @param array $post    要提交的数据 
  7.  * @param string $cookie=''  存储cookie的文件路径 
  8.  * @return string $str   返回响应结果 
  9.  */  
  10. function curl_login($logUrl,$desUrl,$post,$cookie=''){  
  11.  /********模拟登陆**********/  
  12.     //初始化curl模块   
  13.     $curl = curl_init();  
  14.     //登录提交的地址   
  15.     curl_setopt($curl, CURLOPT_URL,$logUrl);  
  16.     //是否显示头信息  
  17.     curl_setopt($curl, CURLOPT_HEADER, 0);   
  18.     //是否自动显示返回的信息   
  19.     curl_setopt($curl, CURLOPT_RETURNTRANSFER, 0);  
  20.     //设置Cookie信息保存在指定的文件中   
  21.     if(!$cookie)  $cookie=dirname(__FILE__) . '/cookie.txt';  
  22.     if(!file_exists($cookie))}{  
  23.         $fp=fopen($cookie'w'); fclose($fp);  
  24.     }  
  25.     curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie);   
  26.     //post方式提交   
  27.     curl_setopt($curl, CURLOPT_POST, 1);  
  28.     //提交信息,http_build_query()可以将数组转换成相连接的字符串。  
  29.     curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post));   
  30.     //执行cURL并关闭cURL资源,并且释放系统资源   
  31.     curl_exec($curl);  
  32.     curl_close($curl);  
  33.  /********登陆后获取数据**********/  
  34.     $ch = curl_init();   
  35.     curl_setopt($ch, CURLOPT_URL, $desUrl);   
  36.     curl_setopt($ch, CURLOPT_HEADER, 0);   
  37.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);   
  38.     //读取cookie   
  39.     curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);   
  40.     $rs = curl_exec($ch); //执行cURL抓取页面内容   
  41.     curl_close($ch);   
  42.     return $rs;   
  43. }  

   也可以把curl的操作封装成一个类 Curl.class.php
[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?php  
  2.   
  3. /** 
  4.  *  CURL操作类,可用于模拟请求 
  5.  *  @author leshen <986992484@qq.com> 
  6.  *  @version 1.1 
  7.  *  usage: 
  8.  *  1.设置选项 
  9.  *  $options=array( 
  10.  *    'isReturn'=>true,   //将响应结果返回。如果不想获取源码而是想渲染页面,请设置为false 
  11.  *    'isHeader'=>true,   //将响应头返回 
  12.  *   ); 
  13.  *  $curl=new Curl($options); 
  14.  *  2.模拟一般的get请求 
  15.  *  $curl=new Curl(); 
  16.  *  $url="https://www.baidu.com"; 
  17.  *  var_dump($curl->curl_get($url)); 
  18.  *  3.模拟需要盗链的get请求(查询四六级为例) 
  19.  *  $curl=new Curl(); 
  20.  *  $url='http://www.chsi.com.cn/cet/query'; 
  21.  *  $referer="http://www.chsi.com.cn/cet"; 
  22.  *  $data=array('xm'=>'钟林生','zkzh'=>'360021161218718'); 
  23.  *  $respn=$curl->curl_get_chain($url,$data,$referer); 
  24.  *  var_dump($respn); 
  25.  *  4.模拟post请求(查询四六级为例) 
  26.  *   $data=array( 
  27.  *   'name'=>'王勇平', 
  28.  *   'province'=>'江西', 
  29.  *   'school'=>'江西师范大学', 
  30.  *   'type'=>'1' 
  31.  *  ); 
  32.  *  $url='http://cet.zy62.com/query/2'; 
  33.  *  $curl=new Curl(); 
  34.  *  var_dump($curl->curl_post($url,$data)); 
  35.  */  
  36.   
  37. class Curl{  
  38.   
  39.     /** 
  40.      * curl资源句柄 
  41.      * @var resource 
  42.      */  
  43.     private $curl;  
  44.   
  45.     /*curl选项*/  
  46.     private $isReturn;   //是否将响应结果返回  
  47.     private $isHeader;   //是否将响应头返回  
  48.     private $timeout;    //超时时间  
  49.     private $userAgent;  //客户端代理  
  50.     private $verifyPeer//是否终止cURL从服务端进行验证  
  51.     private $verifyHost//检查服务器SSL证书中是否存在一个公用名  
  52.   
  53.     /** 
  54.      * 构造方法,用于实例化一个curl对象 
  55.      */  
  56.     public function __construct($options=array()){  
  57.         /*初始化资源句柄*/  
  58.         $this->curl=curl_init();  
  59.         /*初始化curl选项*/  
  60.         $this->isReturn=isset($options['isReturn'])?$options['isReturn']:ture;  
  61.         $this->isHeader=isset($options['isHeader'])?$options['isHeader']:false;  
  62.         $this->timeout=isset($options['timeout'])?$options['timeout']:30;  
  63.         $this->userAgent=isset($options['userAgent'])?$options['timeout']:  
  64.            isset($_SERVER['HTTP_USER_AGENT'])?$_SERVER['HTTP_USER_AGENT']:   
  65.         'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0 FirePHP/0.7.4';  
  66.         $this->verifyPeer=isset($options['verifyPeer'])?$options['verifyPeer']:false;  
  67.         $this->verifyHost=isset($options['verifyHost'])?$options['verifyHost']:2;  
  68.     }     
  69.   
  70.     /** 
  71.      * 设置curl选项 
  72.      * @param  string   $url    请求的url 
  73.      * @param  boolean  $ssl    是否以https协议传输 
  74.      * @return void  
  75.      */   
  76.     private function setOption($url,$ssl){  
  77.         /*设置curl选项*/  
  78.         curl_setopt($this->curl, CURLOPT_URL, $url);//URL  
  79.         curl_setopt($this->curl, CURLOPT_USERAGENT, $this->userAgent);//userAgent,请求代理信息  
  80.         curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->timeout);//设置超时时间  
  81.   
  82.         /*SSL相关*/  
  83.         if ($ssl) {  
  84.             curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER,$this->verifyPeer);//禁用后cURL将终止从服务端进行验证  
  85.             curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST,$this->verifyHost);//检查服务器SSL证书中是否存在一个公用名(common name)。  
  86.         }  
  87.   
  88.         /*响应结果*/  
  89.         curl_setopt($this->curl, CURLOPT_HEADER, $this->isHeader);//是否返回响应头  
  90.         curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, $this->isReturn);//curl_exec()是否返回响应结果  
  91.     }  
  92.   
  93.     /** 
  94.      * 执行curl请求 
  95.      * @return string  返回响应内容 
  96.      */   
  97.     private function exec(){  
  98.         /*发出请求*/  
  99.         $response = curl_exec($this->curl);  
  100.         if (false === $response) {  
  101.             echo '<br>', curl_error($this->curl), '<br>';  
  102.             return false;  
  103.         }  
  104.         curl_close($this->curl);  
  105.         return $response;  
  106.     }  
  107.   
  108.     /** 
  109.      * curl模拟post请求,返回响应的内容 
  110.      * @param  string   $url        请求的url 
  111.      * @param  array    $data       发送的数据,数组 
  112.      * @param  boolean  $ssl        是否以https协议传输,默认为true 
  113.      * @return string   $response   返回响应的内容 
  114.      */   
  115.     public function curl_post($url$data$ssl=true) {  
  116.         /*设置选项*/  
  117.         $this->setOption($url,$ssl);  
  118.   
  119.         /*处理post相关选项*/  
  120.         curl_setopt($this->curl, CURLOPT_POST, true);// 是否为POST请求  
  121.         curl_setopt($this->curl, CURLOPT_POSTFIELDS, $data);// 设置post的内容  
  122.   
  123.         /*执行curl请求*/  
  124.         if($this->isReturn){  
  125.             return $this->exec();  
  126.         }  
  127.         $this->exec();  
  128.     }  
  129.   
  130.     /** 
  131.      * curl模拟一般的get请求,返回响应的内容 
  132.      * @param  string   $url        请求的url,可以带查询参数 
  133.      * @param  boolean  $ssl        是否以https协议传输,默认为true 
  134.      * @return string   $response   返回响应的内容 
  135.      */   
  136.     public function curl_get($url,$ssl=true) {  
  137.         /*设置选项*/  
  138.         $this->setOption($url,$ssl);  
  139.   
  140.         /*执行curl请求*/  
  141.         if($this->isReturn){  
  142.             return $this->exec();  
  143.         }  
  144.         $this->exec();  
  145.     }     
  146.   
  147.     /** 
  148.      * curl模拟需要盗链的get请求,返回响应的内容 
  149.      * @param  string   $url        请求的url 
  150.      * @param  array    $data       查询参数,数组形式,方法内会自动转换为字符串形式 
  151.      * @param  string   $referer    盗链的url 
  152.      * @param  boolean  $ssl        是否以https协议传输,默认为true 
  153.      * @return string   $response   返回响应的内容 
  154.      */   
  155.     public function curl_get_chain($url,$data,$referer,$ssl=true){  
  156.         /*设置选项*/  
  157.         $this->setOption($url,$ssl);  
  158.         $param='';  
  159.         foreach ($data as $k => $v) {  
  160.             $param.= urlencode($k).'='.urlencode($v).'&';  
  161.         }  
  162.         /*设置查询参数*/  
  163.         curl_setopt($this->curl, CURLOPT_POST, 0);  
  164.         curl_setopt($this->curl, CURLOPT_POSTFIELDS, $param);  
  165.   
  166.         /*设置referer盗链*/  
  167.         curl_setopt($this->curl, CURLOPT_REFERER, $referer);  
  168.   
  169.         /*执行curl请求*/  
  170.         if($this->isReturn){  
  171.             return $this->exec();  
  172.         }  
  173.         $this->exec();  
  174.     }  
  175. }  
转载来自:http://blog.csdn.net/zls986992484/article/details/52600241
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值