比 file_get_contents() 更优的 cURL 详解(附实例)

 

PHP 可以使用 file_get_content() 函数抓取网页内容,但却无法进行更复杂的处理,譬如文件的上传或下载、 Cookie 操作等等。而 cURL 提供了这些功能。

 

一、cURL简介

在 PHP 中,cURL 是一个扩展库。它可以与各种类型的服务器、使用各种类型的协议进行连接和通讯。

它目前支持 http、https、ftp、gopher、telnet、dict、file 和 ldap 协议,同时也支持 HTTPS 认证、HTTP POST、 FTP 上传、代理、cookies 和 用户名 + 密码的认证等。

 

二、cURL函数库

常用函数

函数描述
 curl_init() 初始化 cURL 会话
 curl_setopt() 设置 cURL 选项
 curl_exec()
 执行 cURL 会话
 curl_getinfo()  获取当前会话信息
 curl_errno() 返回最后一次的错误代码  
 curl_error() 返回当前会话最后一次的错误字符串
 curl_close() 关闭 cURL 会话

其他函数

函数描述
curl_copy_handle()复制一个 cURL 句柄和它的所有选项。
curl_escape()返回转义字符串,对给定的字符串进行URL编码。
curl_file_create()创建一个 CURLFile 对象。
curl_multi_add_handle()向 cURL 批处理会话中添加单独的curl句柄。
curl_multi_close()关闭一组 cURL 句柄。
curl_multi_exec()运行当前 cURL 句柄的子连接。
curl_multi_getcontent()如果设置了 CURLOPT_RETURNTRANSFER ,则返回获取的输出的文本流。
curl_multi_info_read()获取当前解析的 cURL 的相关传输信息。
curl_multi_init()返回一个新 cURL 批处理句柄。
curl_multi_remove_handle() 移除 cURL 批处理句柄资源中的某个句柄资源。
curl_multi_select()等待所有 cURL 批处理中的活动连接。
curl_multi_setopt()设置一个批处理 cURL 传输选项。
curl_multi_strerror()返回描述错误码的字符串文本。
curl_pause()暂停及恢复连接。
curl_reset()重置 libcurl 的会话句柄的所有选项。
curl_setopt_array()为 cURL 传输会话批量设置选项。
curl_share_close()关闭 cURL 共享句柄。
curl_share_init()初始化 cURL 共享句柄。
curl_share_setopt()设置一个共享句柄的 cURL 传输选项。
curl_strerror()返回错误代码的字符串描述。
curl_unescape()解码 URL 编码后的字符串。
curl_version()获取 cURL 版本信息。

 

三、实现流程

1. 初始化 cURL 会话

2. 设置 cURL 选项

3. 执行 cURL 会话

4. 获取 cURL 信息和(或)错误信息(这一步可以没有)

5. 关闭 cURL 句柄

这里面最复杂的是第 2 步,cURL 的设置选项有很多,下面会结合实例来了解。查看所有选项请看这里:http://www.runoob.com/php/func-curl_setopt.html

 

四、实例1.GET请求

GET 请求的流程就是 cURL 的一般流程。

在本地服务器 localserver.com 根目录准备一个测试脚本 index.php,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
     $url  'http://www.baidu.com' ;
 
     // 初始化,获得一个cURL句柄
     $ch  = curl_init();
     
     // 设置选项
     curl_setopt( $ch , CURLOPT_URL,  $url );  // 请求URL
     curl_setopt( $ch , CURLOPT_RETURNTRANSFER, 1);  //返回数据流,而不直接输出
     curl_setopt( $ch , CURLOPT_HEADER, 0);  // 无需响应的header头
     curl_setopt( $ch , CURLOPT_CONNECTTIMEOUT, 30);  //连接超时,单位为秒
 
     // 执行并获取返回内容
     $output  = curl_exec( $ch );
     if ( $output  === false){
         $output  'cURL error: '  . curl_error( $ch );
     }
 
     // 释放 cURL 句柄资源
     curl_close( $ch );
 
     print_r( $output );
?>

浏览器访问本地服务器首页 localserver.com/index.php,显示百度首页。

 

五、实例2.POST请求

POST 请求需要设置两个选项:

1
2
curl_setopt( $ch , CURLOPT_POST, 1);  // 表明POST请求
curl_setopt( $ch , CURLOPT_POSTFIELDS,  $postData ));  // POST提交数据

先在远程服务器 remoteserver.com 根目录准备一个用于接收的脚本 index.php,内容如下:

1
2
3
4
<?php
     $input  file_get_contents ( 'php://input' );
     echo  $input ;
?>

然后在本地服务器 localserver.com 根目录来写用于 POST 请求的脚本 index.php,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
     $url  'http://remoteserver.com/index.php' ;
     $data  array (
         'fname' =>  'Daniel' ,
         'lname'  =>  'Stenberg'
     );
 
      // 初始化
     $ch  = curl_init();
     
     // 设置选项
     curl_setopt( $ch , CURLOPT_URL,  $url );
     curl_setopt( $ch , CURLOPT_RETURNTRANSFER, 1);
     curl_setopt( $ch , CURLOPT_HEADER, 0);
     curl_setopt( $ch , CURLOPT_CONNECTTIMEOUT, 30);
     curl_setopt( $ch , CURLOPT_POST, 1);  // POST请求
     curl_setopt( $ch , CURLOPT_POSTFIELDS, http_build_query( $data ));  //POST数据。用http_build_query()转换为“&”拼接的字符串
 
     // 执行并获取返回内容
     $output  = curl_exec( $ch );
     if ( $output  === false){
         $output  =   'cURL error: '  . curl_error( $ch );
     }
 
     // 释放 cURL 句柄资源
     curl_close( $ch );
 
     print_r( $output );
?>

浏览器访问 localserver.com/index.php,显示如下:

1
fname=Daniel&lname=Stenberg

 

六、实例3.上传文件

cURL 上传文件的思路是:在文件路径的前面添加"@"符号,并装在请求字段里实现上传。后台可以通过 $_FILES 获取上传文件信息。但 PHP5.6 以后,废除了"@"符号,可以使用 CURLFile 类实现上传。

先在远程服务器 remoteserver.com 根目录准备一个用于接收的脚本 index.php,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
     $action  $_POST [ 'action' ];
     if ( $action  ==  'uploadImage' ){
         $name  $_FILES [ 'file' ][ 'name' ];
         $tmpname  $_FILES [ 'file' ][ 'tmp_name' ];
         
         // 保存到当前脚本所在目录
         move_uploaded_file( $tmpname , dirname( __FILE__ ). '/' . $name );
 
         $error  $_FILES [ 'file' ][ 'error' ];
         switch  ( $error ) {
             case  0:  echo  '上传成功' break ;
             case  1:  echo  '文件大小超出 php.ini 限制' break ;
             case  2:  echo  '文件大小超出 表单 MAX_FILE_SIZE 限制' break ;
             case  3:  echo  '文件部分被上传' break ;
             case  4:  echo  '没有文件被上传' break ;
             case  6:  echo  '找不到临时文件夹' break ;
             case  7:  echo  '文件写入失败' break ;
             default $output  '未知错误' ;
         }
     }
?>

然后在本地服务器 localserver.com 根目录准备一个图片文件 test.jpg 和 cURL 上传脚本 index.php, 脚本内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
     $url  'http://remoteserver.com/index.php' ;
     $file  realpath ( getcwd () .  '/test.jpg' );
     $data  array (
         'action'  =>  'uploadImage' ,
         'file'  =>  '@'  $file
     );
     if (version_compare(PHP_VERSION,  '5.6.0' ) > 0){
         $data [ 'file' ] =  new  CURLFile( $file );
     }
     
     // 初始化
     $ch  = curl_init();
     
     // 设置选项
     curl_setopt( $ch , CURLOPT_URL,  $url );
     curl_setopt( $ch , CURLOPT_RETURNTRANSFER, 1);
     curl_setopt( $ch , CURLOPT_HEADER, 0);
     curl_setopt( $ch , CURLOPT_CONNECTTIMEOUT, 30);
     curl_setopt( $ch , CURLOPT_POST, 1);
     curl_setopt( $ch , CURLOPT_POSTFIELDS,  $data );
 
     // 执行并获取返回内容
     $output  = curl_exec( $ch );
     if ( $output  === false){
         $output  =   'cURL error: '  . curl_error( $ch );
     }
 
     // 释放 cURL 句柄资源
     curl_close( $ch );
 
     print_r( $output );
?>

浏览器访问 localserver.com/index.php,显示如下:

1
上传成功

查看远程服务器根目录,发现多了一张刚才上传的图片。

 

七、实例4.下载文件

cURL 下载文件的一个思路是:设置 cURL 选项 CURLOPT_FILE 为一个文件指针,以此将请求的资源文件关联到一个文件流里,这个文件流一般是 fopen()函数的返回值。使用文件流将远程文件写到本地,可以避免写(下载)大文件时可能的内存出错。

在本地服务器 localserver.com 根目录来写测试脚本 index.php,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
     $url  'http://remoteserver.com/test.jpg' ;
     $file  './test.jpg' ;
     $fp  fopen ( $file 'w' );
 
     // 初始化
     $ch  = curl_init();
 
     // 设置选项
     curl_setopt( $ch , CURLOPT_URL,  $url );
     curl_setopt( $ch , CURLOPT_RETURNTRANSFER, 1);
     curl_setopt( $ch , CURLOPT_HEADER, 0);
     curl_setopt( $ch , CURLOPT_CONNECTTIMEOUT, 30);
     curl_setopt( $ch , CURLOPT_FILE,  $fp );  // 用于传输的文件流,默认是STDOUT
 
     // 执行并获取返回内容
     $output  = curl_exec( $ch );
     if ( $output  === false){
         $output  =   'cURL error: '  . curl_error( $ch );
     }
 
     // 获取已下载大小
     $size_download  = curl_getinfo( $ch , CURLINFO_SIZE_DOWNLOAD);
 
     // 释放资源
     fclose( $fp );
     curl_close( $ch );
 
     if  ( $size_download  &&  $size_download  ==  filesize ( $file )) {
         echo  "下载成功" ;
     else  {
         echo  "下载失败或不完整" ;
     }  
?>

浏览器访问 localserver.com/index.php,显示如下:

1
下载成功

查看本地服务器根目录,发现下载到了远程的图片。 

 

八、实例5.批处理

cURL 有一个批处理句柄,通过打开多个 cURL 句柄,并将这些句柄绑定到一个批处理句柄,然后在循环中依次处理每个 cURL 连接,可以实现异步的批处理,类似“多线程”。

在本地服务器 localserver.com 根目录来写测试脚本 index.php,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php
     $urls  array (
         'http://www.baidu.com' ,
         'http://www.qidian.com'
     );
     $count  count ( $urls );
     $ch  array ();
 
     // 创建批处理cURL句柄
     $mh  = curl_multi_init();
 
     // 初始化每个cURL,并设置选项,绑定给批处理句柄
     for  ( $i  = 0;  $i  $count $i ++) {
         $ch [ $i ] = curl_init();
         curl_setopt( $ch [ $i ], CURLOPT_URL,  $urls [ $i ]);
         curl_setopt( $ch [ $i ], CURLOPT_RETURNTRANSFER, 1);
         curl_setopt( $ch [ $i ], CURLOPT_HEADER, 0);
         curl_setopt( $ch [ $i ], CURLOPT_CONNECTTIMEOUT, 30);
         curl_multi_add_handle( $mh $ch [ $i ]);
     }
 
     // 执行批处理
     $running  = null;
     do  {
         usleep(10000);  // 延迟0.01秒,单位为百万分之一秒
         curl_multi_exec( $mh $running );  // 异步实现批处理,类似“多线程”
     while ( $running  > 0);
 
     // 获取每个cURL的响应
     $res  array ();
     for  ( $i  = 0;  $i  $count $i ++) {
         $res [ $i ] = curl_multi_getcontent( $ch [ $i ]);
     }
 
     // 关闭全部句柄
     for  ( $i  = 0;  $i  $count $i ++) {
         curl_multi_remove_handle( $mh $ch [ $i ]);
     }
     curl_multi_close( $mh );
 
     print_r( $res );
?>

浏览器访问 localserver.com/index.php,显示了“连在一起”的百度首页和起点网首页。

转载:https://www.cnblogs.com/mingc/p/7425321.html

posted @ 2019-07-12 16:22  码农编程进阶笔记  阅读(120)  评论(0编辑  收藏  举报
返回顶部 有事您Q我