PHP+cURL扩展的使用

PHP 支持 Daniel Stenberg 创建的 libcurl 库,能够连接通讯各种服务器、使用各种协议。libcurl 目前支持的协议有 http、https、ftp、gopher、telnet、dict、file、ldap。 libcurl 同时支持 HTTPS 证书、HTTP POST、HTTP PUT、 FTP 上传(也能通过 PHP 的 FTP 扩展完成)、HTTP 基于表单的上传、代理、cookies、用户名+密码的认证。

一、使用CURL发送请求的基本流程

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

 1. 初始化连接句柄;        curl_init();
 2. 设置cURL选项;         curl_setopt();
 3. 执行并获取结果;        curl_exec();
 4. 释放cURL句柄。         curl_close();

二、使用cURL发送HTTP的典型过程


	 // 1. 初始化
	 $ch = curl_init();
	 
	 // 2. 设置选项,包括URL
	 curl_setopt($ch,CURLOPT_URL,"http://www.devdo.net");
	 curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
	 curl_setopt($ch,CURLOPT_HEADER,0);
	 
	 // 3. 执行并获取HTML文档内容
	 $output = curl_exec($ch);
	 if($output === FALSE ){
		 echo "CURL Error:".curl_error($ch);
	 }
	 
	 // 4. 释放curl句柄
	 curl_close($ch);
?>

上述代码中使用到了四个函数:
  curl_init()curl_close() 分别是初始化CURL连接和关闭CURL连接,都比较简单。
  curl_exec() 执行CURL请求,如果没有错误发生,该函数的返回是对应URL返回的数据,以字符串表示满意;如果发生错误,该函数返回 FALSE。需要注意的是,判断输出是否为FALSE用的是全等号,这是为了区分返回空串和出错的情况。
  CURL函数库里最重要的函数是curl_setopt(),它可以通过设定CURL函数库定义的选项来定制HTTP请求。上述代码片段中使用了三个重要的选项:

  1. CURLOPT_URL 指定请求的URL;
  2. CURLOPT_RETURNTRANSFER 设置为1表示稍后执行的curl_exec函数的返回是URL的返回字符串,而不是把返回字符串定向到标准输出并返回TRUE;
  3. CURLLOPT_HEADER设置为0表示不返回HTTP头部信息。
  4. CURL的选项还有很多,可以到PHP的官方网站(http://www.php.net/manual/en/function.curl-setopt.php)上查看CURL支持的所有选项列表。

三、获取CURL请求的输出信息

定义curl_getinfo — 获取一个cURL连接资源句柄的信息。获取最后一次传输的相关信息。
语法mixed curl_getinfo ( resource $ch [, int $opt = 0 ] );
参数
ch
 curl_init() 返回的 cURL

opt
 参数可能是以下常量之一:

  • CURLINFO_EFFECTIVE_URL - 最后一个有效的URL地址
  • CURLINFO_HTTP_CODE - 最后一个收到的HTTP代码
  • CURLINFO_FILETIME - 远程获取文档的时间,如果无法获取,则返回值为“-1”
  • CURLINFO_TOTAL_TIME - 最后一次传输所消耗的时间
  • CURLINFO_NAMELOOKUP_TIME - 名称解析所消耗的时间
  • CURLINFO_CONNECT_TIME - 建立连接所消耗的时间
  • CURLINFO_PRETRANSFER_TIME - 从建立连接到准备传输所使用的时间
  • CURLINFO_STARTTRANSFER_TIME - 从建立连接到传输开始所使用的时间
  • CURLINFO_REDIRECT_TIME - 在事务传输开始前重定向所使用的时间
  • CURLINFO_SIZE_UPLOAD - 以字节为单位返回上传数据量的总值
  • CURLINFO_SIZE_DOWNLOAD - 以字节为单位返回下载数据量的总值
  • CURLINFO_SPEED_DOWNLOAD - 平均下载速度
  • CURLINFO_SPEED_UPLOAD - 平均上传速度
  • CURLINFO_HEADER_SIZE - header部分的大小
  • CURLINFO_HEADER_OUT - 发送请求的字符串
  • CURLINFO_REQUEST_SIZE - 在HTTP请求中有问题的请求的大小
  • CURLINFO_SSL_VERIFYRESULT - 通过设置CURLOPT_SSL_VERIFYPEER返回的SSL证书验证请求的结果
  • CURLINFO_CONTENT_LENGTH_DOWNLOAD - 从Content-Length: field中读取的下载内容长度
  • CURLINFO_CONTENT_LENGTH_UPLOAD - 上传内容大小的说明
  • CURLINFO_CONTENT_TYPE -
    下载内容的Content-Type:值,NULL表示服务器没有发送有效的Content-Type: header
    实例
	curl_exec($ch);
	$url = curl_getinfo($ch,CURLINFO_EFFECTIVE_URL);
	$total_time= curl_getinfo($ch,CURLINFO_TOTAL_TIME);
	$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
	echo '获取 '.$url.' ,耗时'.$total_time.'秒,HTTP状态码:'.$status;

返回值
  如果 opt 被设置,以字符串形式返回它的值。否则,返回返回一个包含下列元素的关联数组(它们分别对应于 opt):

	curl_exec($ch);
	$info = curl_getinfo($sh);
	echo ' 获取 '.$info['url'].'耗时'.$info['total_time'].'秒,HTTP状态码:'.$info['http_code'];

上述代码中curl_getinfo返回的是一个关联数组,包含以下数据:

  1. url:网络地址。 content_type:内容编码。
  2. http_code:HTTP状态码。
  3. header_size:header的大小。
  4. filetime:文件创建的时间。
  5. ssl_verify_result:SSL验证结果。
  6. redirect_count:跳转计数。
  7. total_time:总耗时。
  8. namelookup_time:DNS查询耗时。
  9. connect_time:等待连接耗时。
  10. pretransfer_time:传输前准备耗时。
  11. size_uplpad:上传数据的大小。
  12. size_download:下载数据的大小。
  13. speed_download:下载速度。
  14. speed_upload:上传速度。
  15. download_content_length:下载内容的长度。
  16. upload_content_length:上传内容的长度。
  17. starttransfer_time:开始传输的时间表。
  18. redirect_time:重定向耗时。

注意
  curl_getinfo()函数还有一个可选择参数$opt ,通过这个参数可以设置一些常量,对应到上术这个字段,如果设置了第二个参数,那么返回的只有指定的信息。例如:设置$optCURLINFO_TOTAL_TIME,则curl_getinfo()函数只返回total_time,即总传输消耗的时间,在只需要关注某些传输信息时,设置$opt参数很有意义。

四、cURL-GET请求获取百度首页HTML文档内容

//1、初始化cURL
$ch= curl_init();

//2、设置抓取的url
curl_setopt($ch, CURLOPT_URL, 'http://www.baidu.com');

//3、设置头文件的信息作为数据流输出(false为不输出)
curl_setopt($ch, CURLOPT_HEADER, false);

//4、设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

//5、执行命令
$data = curl_exec($ch);

//6、关闭URL请求
curl_close($ch);

//7、显示获得的数据
print_r($data);

注意:
1、如果是https协议,添加代码如下:

//HTTPS协议添加下面一行代码:
// curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

五、cURL-通过GET请求传递数据

1、test.php代码


	header("content-type:text/html;charset=utf-8");
	$url = "http://127.0.0.1/test/get_data/get_data.php?name=laowang&age=16&sex=man";
	$ch= curl_init(); // 启动一个CURL会话
	curl_setopt($ch, CURLOPT_URL, $url); // 要访问的地址
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 对认证证书来源的检查
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
	curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
	curl_setopt($ch, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
	curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
	curl_setopt($ch, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
	$tmpInfo = curl_exec($ch); // 执行操作
	curl_close($ch); // 关闭CURL会话
	echo $tmpInfo; // 输出返回的数据
?>

2、get_data.php代码


	$data['name'] = $_GET['name'];
	$data['age'] = $_GET['age'];
	$data['sex'] = $_GET['sex'];
	if(empty($data)){
		echo 'fail';
	}else{
		file_put_contents('wd.txt',$data);
		echo 'success';
	}
?>

注意
  返回值为success则传值成功,返回fail则失败。

六、cURL通过POST请求传递数据

1、test.php代码


	header("content-type:text/html;charset=utf-8");
	$url = "http://127.0.0.1/test/get_data/get_data.php";
	$data = array('name'=>'laozhang','age'=>18,'sex'=>'woman');
	$ch= curl_init(); // 启动一个CURL会话
	curl_setopt($ch, CURLOPT_URL, $url); // 要访问的地址
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 对认证证书来源的检查
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
	curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
	curl_setopt($ch, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
	curl_setopt($ch, CURLOPT_POST, 1); // 发送一个常规的Post请求
	if ($data != ''){
		curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
	}
	curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
	curl_setopt($ch, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
	$tmpInfo = curl_exec($ch); // 执行操作
	curl_close($ch); // 关闭CURL会话
	echo $tmpInfo; // 返回数据
?>

2、get_data.php代码


	$data['name'] = $_POST['name'];
	$data['age'] = $_POST['age'];
	$data['sex'] = $_POST['sex'];
	if(empty($data)){
		echo 'fail';
	}else{
		file_put_contents('./wd.txt',$data);
		echo 'success';
	}
?>

3、注意:有时候需要传递json格式的数据,接收数据的方式就要改变了
1、test.php代码修改

$data = json_encode(array('name'=>'隔壁老王','age'=>18,'sex'=>'女'),JSON_UNESCAPED_UNICODE);
......
//设置http的请求头
$header[] = "Content-Type:application/json;charset=utf-8";//成功
curl_setopt($ch,CURLOPT_HTTPHEADER,$header);

2、get_data代码修改


	$postData = file_get_contents('php://input');
	$data = json_decode($postData,true);
		if(empty($data)){
		echo 'fail';
	}else{
		file_put_contents('wd.txt',$data);
		echo 'success';
	}
?>

4、test.php把GET请求和POST请求封装成方法


	function http($url, $data='', $method='GET'){ 
		$ch = curl_init(); // 启动一个CURL会话
		curl_setopt($ch, CURLOPT_URL, $url); // 要访问的地址
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 对认证证书来源的检查
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
		curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
		curl_setopt($ch, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
		if($method=='POST'){
			curl_setopt($ch, CURLOPT_POST, 1); // 发送一个常规的Post请求
			if ($data != ''){
				curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
			}
		}
		curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
		curl_setopt($ch, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
		$tmpInfo = curl_exec($ch); // 执行操作
		curl_close($ch); // 关闭CURL会话
		return $tmpInfo; // 返回数据
	}
?>

七、封装的方法

该段代码摘自《PHP中使用CURL模拟发送GET,POST,PUT,DELETE请求》

 
/* 
* $url		URL路径
* $method	传递参数的方法:get、post、put、delete
* $params	参数
* $auth	登录认证:账号和密码
 */
function curl($url,$method,$params,$auth=null){
//1、判断$url,$method,$params是否为空
	if(empty($url) || empty($method) || empty($params)){
		return '参数不能为空!';
	}
//1、初始化CURL句柄
	$curl = curl_init();

	curl_setopt($curl, CURLOPT_URL, $url);//设置请求的URL
	#curl_setopt($curl, CURLOPT_HEADER, false);// 不要http header 加快效率
	curl_setopt($curl, CURLOPT_RETURNTRANSFER,1); //设为TRUE把curl_exec()结果转化为字串,而不是直接输出

//2、SSL验证
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);    // https请求时要设置为false 不验证证书和hosts  FALSE 禁止 cURL 验证对等证书(peer's certificate), 自cURL 7.10开始默认为 TRUE。从 cURL 7.10开始默认绑定安装。 
	curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);//检查服务器SSL证书中是否存在一个公用名(common name)。
	
	//传送数据时,有的需要指定数据格式-下面是json格式,utf-8格式
	$header[] = "Content-Type:application/json;charset=utf-8";
	if(!empty($header)){
		curl_setopt ( $curl, CURLOPT_HTTPHEADER, $header );//设置 HTTP 头字段的数组。格式: array('Content-type: text/plain', 'Content-length: 100') 
	}

//3、请求时间
	$timeout = 30;
	curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, $timeout);//设置连接等待时间

//4、不同请求方法的数据提交
	switch ($method){
		case "GET" :
			curl_setopt($curl, CURLOPT_HTTPGET, true);//TRUE 时会设置 HTTP 的 method 为 GET,由于默认是 GET,所以只有 method 被修改时才需要这个选项。 
			break;
		case "POST":
			if(is_array($params)){
				$params = json_encode($params,320);
			}
			#curl_setopt($curl, CURLOPT_POST,true);//TRUE 时会发送 POST 请求,类型为:application/x-www-form-urlencoded,是 HTML 表单提交时最常见的一种。
			#curl_setopt($curl, CURLOPT_NOBODY, true);//TRUE 时将不输出 BODY 部分。同时 Mehtod 变成了 HEAD。修改为 FALSE 时不会变成 GET。
			// curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");//HTTP 请求时,使用自定义的 Method 来代替"GET"或"HEAD"。对 "DELETE" 或者其他更隐蔽的 HTTP 请求有用。 有效值如 "GET","POST","CONNECT"等等;
			//设置提交的信息
			// curl_setopt($curl, CURLOPT_POSTFIELDS,$params);//全部数据使用HTTP协议中的 "POST" 操作来发送。
			//设置请求方式是post方式
			curl_setopt($curl,CURLOPT_POST,true);
			//设置post请求提交的表单信息
			curl_setopt($curl,CURLOPT_POSTFIELDS,$params);
			break;
		case "PUT" :
			curl_setopt ($curl, CURLOPT_CUSTOMREQUEST, "PUT");
			curl_setopt($curl, CURLOPT_POSTFIELDS,json_encode($params,320));
			break;
		case "DELETE":
			curl_setopt ($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
			curl_setopt($curl, CURLOPT_POSTFIELDS,$params);
			break;
		default:
			echo '方法名不能为空!';
			break;
	}

//5、传递一个连接中需要的用户名和密码,格式为:"[username]:[password]"。
	if (!empty($auth) && isset($auth['username']) && isset($auth['password'])) {
		curl_setopt($curl, CURLOPT_USERPWD, "{$auth['username']}:{$auth['password']}");
	}

	//执行预定义的CURL
	$output = curl_exec($curl);
	//获取http返回值,最后一个收到的HTTP代码
	$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
	if($output === FALSE ){
		echo "CURL Error:".curl_error($curl);
	}else{
		if($status === 200){
			//如果返回值是json格式,就需要转换格式
			// $output = json_decode($output,true);
		}else{
			$output = 'fail:请咨询管理员';
		}
	}
	//关闭cURL会话
	curl_close($curl);
	return $output;

}
$arr = array('name'=>'wangdi');
var_dump(curl('http://127.0.0.1/test/get_data/get_data.php','POST',$arr)); 

你可能感兴趣的:(php)