基于PHP的cURL使用入门

本文介绍了cURL在PHP中的强大功能,包括基本使用方法、错误处理、信息获取及高级特性,如POST数据提交、文件上传、批处理、HTTP认证等。

cURL 是一个利用URL语法规定来传输文件和数据的工具,支持很多协议,如HTTP、FTP、TELNET等。PHP提供了对cURL 库的支持。

1. 为什么使用cURL

为了获取网页内容,我们当然可以使用file_get_contents、 file、readfile等函数,但它们缺乏灵活性和有效的错误处理。而且,也不能完成一些高难度任务—如处理coockies、验证、表单提交、文件上传等。PHP获取网页内容的更多方法:http://www.ucooper.com/php-get-webpage-content.html

2. PHP中建立cURL请求的基本步骤

  • 初始化
  • 设置选项
  • 执行并获取结果
  • 释放cURL句柄
    // 1. 初始化 
    $ch  =  curl_init  (  )  ; 
    // 2. 设置选项,包括URL 
    curl_setopt  (  $ch  , CURLOPT_URL ,  "http://www.ucooper.com"  )  ; 
    curl_setopt  (  $ch  , CURLOPT_RETURNTRANSFER ,  1  )  ; 
    curl_setopt  (  $ch  , CURLOPT_HEADER ,  0  )  ; 
    // 3. 执行并获取HTML文档内容 
    $output  =  curl_exec  (  $ch  )  ; 
    // 4. 释放curl句柄 
    curl_close  (  $ch  )  ;
    • CURLOPT_URL:目标URL
    • CURLOPT_PORT:目标端口
    • CURLOPT_RETURNTRANSFER:把输出转化为字符串,而不是直接输出到屏幕
    • CURLOPT_HTTPHEADER:请求头信息,参数是一数组,如“基于浏览器的重定向”例子所示
    • CURLOPT_FOLLOWLOCATION: 跟随重定向
    • CURLOPT_FRESH_CONNECT:强制重新获取内容,而不是从缓存
    • CURLOPT_HEADER:包含头部
    • CURLOPT_NOBODY:输出中不包含网页主体内容
    • CURLOPT_POST:进行post表单提交
    • CURLOPT_POSTFIELDS:POST提交的字段,参数是一数组,如“ 用POST方法发送数据 ”所示
    • CURLOPT_PROXY:代理设置,IP 和 端口
    • CURLOPT_PROXYUSERPWD:代理设置,用户名和密码
    • CURLOPT_PROXYTYPE:代理类型,http 或 socket

    更多选项:http://www.programfan.com/doc/php_manual/function.curl-setopt.html

    3.检查错误

    $output  =  curl_exec  (  $ch  )  ; 
    if  (  $output  ===  FALSE  )  { 
         echo  "cURL Error: "  .  curl_error  (  $ch  )  ; 
    }

    4.获取信息

      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”//重定向耗时

    5.基于浏览器的重定向

    在第一个例子中,我们将提供一段用于侦测服务器是否有基于浏览器的重定向的代码。例如,有些网站会根据是否是手机浏览器甚至用户来自哪个国家来重定向网页。

    我们利用 CURLOPT_HTTPHEADER 选项来设定我们发送出的HTTP请求头信息(http headers),包括user agent信息和默认语言。然后我们来看看这些特定网站是否会把我们重定向到不同的URL。 

       
    // 测试用的URL  $urls  =  array  (       "http://www.cnn.com"  ,       "http://www.mozilla.com"  ,       "http://www.facebook.com"  )  ;  // 测试用的浏览器信息  $browsers  =  array  (       "standard"  =>  array  (           "user_agent"  =>  "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 (.NET CLR 3.5.30729)"  ,          "language"  =>  "en-us,en;q=0.5"           )  ,       "iphone"  =>  array  (           "user_agent"  =>  "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A537a Safari/419.3"  ,          "language"  =>  "en"           )  ,       "french"  =>  array  (           "user_agent"  =>  "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GTB6; .NET CLR 2.0.50727)"  ,          "language"  =>  "fr,fr-FR;q=0.5"           )  )  ;  foreach  (  $urls  as  $url  )  {       echo  "URL: $url /n "  ;       foreach  (  $browsers  as  $test_name  =>  $browser  )  {           $ch  =  curl_init  (  )  ;           // 设置 url           curl_setopt  (  $ch  , CURLOPT_URL ,  $url  )  ;           // 设置浏览器的特定header           curl_setopt  (  $ch  , CURLOPT_HTTPHEADER ,  array  (                   "User-Agent: {$browser['user_agent']} "  ,                   "Accept-Language: {$browser['language']} "               )  )  ;           // 页面内容我们并不需要           curl_setopt  (  $ch  , CURLOPT_NOBODY ,  1  )  ;           // 只需返回HTTP header           curl_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 : redirects to $matches[1] /n "  ;           }  else  {               echo  "$test_name : no redirection/n "  ;           }       }       echo  "/n /n "  ;  }

    首先,我们建立一组需要测试的URL,接着指定一组需要测试的浏览器信息。最后通过循环测试各种URL和浏览器匹配可能产生的情况。

    因为我们指定了cURL选项,所以返回的输出内容则只包括HTTP头信息(被存放于 $output 中)。利用一个简单的正则,我们检查这个头信息中是否包含了“Location:”字样。

    运行这段代码应该会返回如下结果: 

    6. 用POST方法发送数据

    借此我们可以实现表单提交的效果。

    表单提交有get和post两种方式,对于get方式我们可以直接生成URL用file_get_content等函数直接获取内容;但对于post方式,数据是通过 HTTP请求体(request body)发送,而不是查询字串,用这类函数就不可以了。

    首先,制作一个接收页面(action),post_output.php,内容为:print_r($_POST); 即可。即把POST数组直接输出。

    然后,编写我们用cURL来以post方式提交数据

       
    $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  ;  

    这段脚本发送一个POST请求给 post_output.php ,该页面接收并输出$_POST 变量,我们利用cURL捕捉了这个输出。

    7. 文件上传

    上传文件和前面的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变量一样传过去,不过记得在前面加上@符号。执行这段脚本应该会得到如下输出

8. cURL批处理

cURL还有一个高级特性——批处理句柄(handle)。这一特性允许你同时或异步地打开多个URL连接。

这里要做的就是打开多个cURL句柄并指派给一个批处理句柄。然后你就只需在一个while循环里等它执行完毕。

  
// 创建两个cURL资源  $ch1  =  curl_init  (  )  ;  $ch2  =  curl_init  (  )  ;  // 指定URL和适当的参数  curl_setopt  (  $ch1  , CURLOPT_URL ,  "<a href=" http :  //lxr.php.net/">http://lxr.php.net/</a>"); curl_setopt  (  $ch1  , CURLOPT_HEADER ,  0  )  ;  curl_setopt  (  $ch2  , CURLOPT_URL ,  "<a href=" http :  //www.php.net/">http://www.php.net/</a>"); curl_setopt  (  $ch2  , CURLOPT_HEADER ,  0  )  ;  // 创建cURL批处理句柄  $mh  =  curl_multi_init  (  )  ;  // 加上前面两个资源句柄  curl_multi_add_handle  (  $mh  ,  $ch1  )  ;  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  )  !=  -  1  )  {           do  {               $mrc  =  curl_multi_exec  (  $mh  ,  $active  )  ;           }  while  (  $mrc  == CURLM_CALL_MULTI_PERFORM )  ;       }  }  // 关闭各个句柄  curl_multi_remove_handle  (  $mh  ,  $ch1  )  ;  curl_multi_remove_handle  (  $mh  ,  $ch2  )  ;  curl_multi_close  (  $mh  )  ;

这个示例中有两个主要循环。第一个 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。

还是来看一看怎么把这一功能用到实处吧:

9.WordPress 连接检查器

10.其它cURL选项

HTTP 认证

如果某个URL请求需要基于 HTTP 的身份验证,你可以使用下面的代码:

  
$url  =  "<a href=" http :  //www.somesite.com/members/">http://www.somesite.com/members/</a>"; $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  )  ;  $output  =  curl_exec  (  $ch  )  ;  curl_close  (  $ch  )  ;

FTP 上传

PHP 自带有 FTP 类库, 但你也能用 cURL

  
// 开一个文件指针  $file  =  fopen  (  "/path/to/file"  ,  "r"  )  ;  // url里包含了大部分所需信息  $url  =  "ftp://username:password@mydomain.com:21/path/to/new/file"  ;  $ch  =  curl_init  (  )  ;  curl_setopt  (  $ch  , CURLOPT_URL ,  $url  )  ;  curl_setopt  (  $ch  , CURLOPT_RETURNTRANSFER ,  1  )  ;  // 上传相关的选项  curl_setopt  (  $ch  , CURLOPT_UPLOAD ,  1  )  ;  curl_setopt  (  $ch  , CURLOPT_INFILE ,  $fp  )  ;  curl_setopt  (  $ch  , CURLOPT_INFILESIZE ,  filesize  (  "/path/to/file"  )  )  ;  // 是否开启ASCII模式 (上传文本文件时有用)  curl_setopt  (  $ch  , CURLOPT_FTPASCII ,  1  )  ;  $output  =  curl_exec  (  $ch  )  ;  curl_close  (  $ch  )  ;

翻墙术

你可以用代理发起cURL请求:

  
$ch  =  curl_init  (  )  ;  curl_setopt  (  $ch  , CURLOPT_URL ,  'http://www.example.com'  )  ;  curl_setopt  (  $ch  , CURLOPT_RETURNTRANSFER ,  1  )  ;  // 指定代理地址  curl_setopt  (  $ch  , CURLOPT_PROXY ,  '11.11.11.11:8080'  )  ;  // 如果需要的话,提供用户名和密码  curl_setopt  (  $ch  , CURLOPT_PROXYUSERPWD ,  'user:pass'  )  ;  $output  =  curl_exec  (  $ch  )  ;  curl_close  (  $ch  )  ;

回调函数

可以在一个URL请求过程中,让cURL调用某指定的回调函数。例如,在内容或者响应下载的过程中立刻开始利用数据,而不用等到完全下载完。 

  
$ch  =  curl_init  (  )  ;  curl_setopt  (  $ch  , CURLOPT_URL ,  'http://net.tutsplus.com'  )  ;  curl_setopt  (  $ch  , CURLOPT_WRITEFUNCTION ,  "progress_function"  )  ;  curl_exec  (  $ch  )  ;  curl_close  (  $ch  )  ;  function progress_function (  $ch  ,  $str  )  {       echo  $str  ;       return  strlen  (  $str  )  ;  }

这个回调函数必须返回字串的长度,不然此功能将无法正常使用。

在URL响应接收的过程中,只要收到一个数据包,这个函数就会被调用。

小结:今天我们一起学习了cURL库的强大功能和灵活的扩展性。希望你喜欢。下一次要发起URL请求时,考虑下cURL吧! 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值