PHP的cURL扩展库使用详解
在还没有接触curl的时候,相信大家在获取网页内容的时,使用得最多的一个函数就是:file_get_contents(),但是它的可控制性不够灵活,无法处理错误情况,对于各种复杂情况的采集更是显得有点无能为力。因此,本文将为你介绍另外一种工具:cURL的使用方法,在后面也还会给出相关的几个案例,这些都是你使用file_get_contents()无法做到的。
一、cURL库的介绍
为了更好的理解下面的内容,这里先给出一个curl的最简单的案例
入门案例:
$url = "http://nosee123.com/test_post.php";
$ch = curl_init($url); //初始化一个cURL会话
curl_exec($ch); //执行一个cURL会话
curl_close($ch); //关闭一个cURL会话
该案例的执行结果就是把$url的网页内容输出到你的浏览器上,其实这个案例的效果和使用file_get_contents()的结果是一样的,这是因为它没有设置任何的参数。但cURL的功能远远不止这些,下面我们开始讲解cURL更详细的使用方法。
cURL是一个可以使用URL的语法模拟浏览器来传输数据的工具库(libcurl库),libcurl目前支持http、https、ftp、gopher、telnet、dict、file和ldap协议。libcurl同时也支持HTTPS认证、HTTP POST、HTTP PUT、 FTP 上传(这个也能通过PHP的FTP扩展完成)、HTTP 基于表单的上传、代理、cookies和用户名+密码的认证。
注意:在使用cURL库之前,记得要先将你的配置文件(php.ini)中打开的你cURL模块,可以使用phpinfo()查看curl模块是否开启,如没有开启就直接使用相关的方法则会报错。
二、使用基本步骤
使用 cURL 函数的基本思想是先使用curl_init() 初始化 cURL会话,接着可以通过 curl_setopt() 设置需要的全部选项,然后使用 curl_exec()来执行会话,当执行完会话后使用curl_close()关闭会话。
简单来说,使用cURL完成简单的请求主要分为以下四个步骤:
//(1)初始化cURL
$url = "http://nosee123.com/test_post.php";
$ch = curl_init($url); //初始化一个cURL会话
//(2)设置URL和相应的选项
//将curl_exec()获取的信息以字符串返回,而不是直接输出。
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//(3)抓取URL并把它传递给浏览器
//由于步骤2对CURLOPT_RETURNTRANSFER的设置,curl_exec()不会直接输出内容
$str = curl_exec($ch); //执行一个cURL会话
//(4)关闭cURL资源,并且释放系统资源
curl_close($ch); //关闭一个cURL会话
echo $str; //输出步骤3获取的页面内容
上面的4个步骤将会把获取到的网页内容输出,这是使用cURL最基本的四个步骤。
三、curl_setopt常用参数
cURL之所以强大,只要是体现在它的第二个步骤中。你可以通过curl_setopt灵活地设置请求选项,更多的参数设置查看官网:http://php.net/manual/zh/function.curl-setopt.php
官方上罗列的是所有的参数列表,全部都记住也没有什么必要。然而实际开发中,我们常用的也就来来去去那几个,所以在这我也顺便把常用的几个都详细讲讲,这样也方便我们更好的快速的用到实际开发中。但建议有时间的话最好把官网上的都看一篇,这样至少自己心里也有个底,知道里面有些什么方法,当真正需要的时候也方便过来查找。
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);//将curl_exec()获取的信息以字符串返回,而不是直接输出。
curl_setopt($ch, CURLOPT_HEADER,false);//不输出头文件,如果设为true,获得的网页源代码最前边会带有'HTTP/1.1 200 OK'等内容
curl_setopt($ch, CURLOPT_FILE, $fp);//设置输出文件,默认为STDOUT (浏览器)。
curl_setopt($ch, CURLOPT_POST, 1);// 设置请求为post类型
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);// 添加post数据到请求中
四、cURL常用函数
除了上面基本的4个步骤用到的4个函数,cURL还提供了其他很多实用的函数,如curl_error、curl_getinfo等。
获取curl请求的具体信息: curl_getinfo()
在执行一个cURL请求后,你也可以使用curl_getinfo获取该请求的具体信息:
curl_exec($ch);
$curl_info= curl_getinfo($ch);
echo "收到的http回复的code为: {$curl_info['http_code']}";
上述$curl_info是一个关联数组,可以从中获取很多的具体请求信息。
参考:http://php.net/manual/zh/function.curl-getinfo.php
错误处理:curl_error()
$response = curl_exec($ch);
if ($response === FALSE) {
echo "cURL 具体出错信息: " . curl_error($ch);
}
注意了,在做上述判断时务必要使用===,因为请求的回复可能是空字符串,curl在请求出错的情况下回返回FALSE值,所以我们必须使用===,而不是==
参考:http://php.net/manual/zh/function.curl-error.php
五、实用案例
案例1:使用curl发送post请求
$url = "http://nosee123.com/test_post.php";
$post_data = array (
"name" => "nosee",
"url" => "http://www.nosee123.com",
"action" => "Submit"
);
$ch = curl_init($url );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST, 1);// 设置请求为post类型
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);// 添加post数据到请求中
$str = curl_exec($ch);// 执行post请求,获得回复
curl_close($ch);
echo $str ;
案例2:将获取到的内容输出到文件(文件下载)
$url = "http://nosee123.com/86-1.zip"; //远程服务器上要下载的文件
$fp = fopen("output.zip", "w"); //打开一个本地文件指针资源
$ch = curl_init($url); //初始化一个cURL会话
curl_setopt($ch, CURLOPT_FILE, $fp); //设置输出文件,默认为STDOUT (浏览器)。
$str = curl_exec($ch); //执行一个cURL会话
if ($str === FALSE) {
echo "cURL 具体出错信息: " . curl_error($ch);
}
curl_close($ch); //关闭一个cURL会话
fclose($fp); //关闭一个已打开的文件指针
案例3:文件上传
PHP使用CURL上传文件只需发送一个POST请求就可以了,在请求中设置某个字段为需要上传的文件全路径,并且以“@”开头,然后使用CURL把该变量以POST方式发送到服务器,在服务端即可以从超级全局变量$_FILES中取到相应的上传文件信息。需要注意的是,上传文件的变量不是存在着$_POST中,而是在$_FILES中。
以下代码是存在我本地服务器的脚本:
$url = "http://nosee123.com/test_post.php";
$post_data = array (
//要上传的本地的文件地址
"attachment" => "@D:/web/www/wp70/readme.html""
);
//初始化cURL会话
$ch = curl_init();
//设置请求的url
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
//设置为post请求类型
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);//重点!下面详细讲解
//设置具体的post数据
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
$response = curl_exec($ch);
if ($response === FALSE) {
echo "cURL 具体出错信息: " . curl_error($ch);
}
curl_close($ch);
print_r($response);
我的远程服务端处理请求的脚本文件:test_post.php 如下:
//首先使用var_export将$_FILES变量输出到标准输出
echo var_export($_FILES,true);
//然后使用file_get_contents读取$_FILES[‘attachment’][‘tmp_name’]所指文件的内容,并输出到标准输出
echo file_get_contents($_FILES['attachment']['tmp_name']);
//然后把$_FILES[‘attachment’][‘tmp_name’]所指文件自制到当前目录的log_copy.txt文件中
copy($_FILES['attachment']['tmp_name'], "./testdata_copy.txt");
可以看到$_FILES变量中有一个attachment数组,对应到上传文件描述信息,其中name和type分别表示名称和类型。tmp_name比较关键,服务端在接收到上传文件之后,会把文件写在一个临时文件中,这个临时文件的名字就是tmp_name的值,这也是为什么我们读取该文件可以获取一testdata.txt的文件内容。一般在服务端接收到上传文件后都需要立即读取该文件或者把文件复制到别外一个文件中,因为tmp_name所指的临时文件在服务端脚本执行完毕后会被删除掉,test_post.php脚本的最后一行就是把临时文件复制到我们的目标文件中。
还有一个重点问题,这个问题也是折腾了我整整一天的,因为一开始我的请求代码里面没有加curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);这一段代码,上传文件一直失败,@后面的文件地址无法被解析。一直到最后我才发现了那是因为php版本兼容性的问题。对于PHP5.6及以上的版本是不会直接识别@绑定的后面的地址,那要怎么解决这个兼容性问题呢?有两种解决方法:
1)就如我上面的代码,使用配置参数 CURLOPT_SAFE_UPLOAD ,在 PHP5.5中默认值是 false ,而在 PHP5.6中已经默认为 true 了。 所以只需要增加一行强制设置为 false 就行,如下:
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
注意:该参数的设置顺序,必须在设置 CURLOPT_POSTFIELDS 参数之前才有效哦!!!
2)使用 CURLFile 类来处理文件
在上面代码的基础上,把变量$post_data修改为如下代码即可:
$post_data = array (
"attachment" => new CURLFile("D:/web/www/wp70/readme.html")
);
详细参考官方文档:http://php.net/manual/zh/class.curlfile.php
案例4:发送json数据
$posturl='http://nosee123.com/test_json.php';
$array=array ('key'=>'abc','phone'=>'18813912321','userid'=>'1234321');
$jsoninfo = json_encode($array); //把数组进行json编码
//模拟post请求
$ch = curl_init();//初始化curl
if ( $ch === FALSE ){
return 'ERROR: Sorry , you cannot open curl. --- nosee';
}
curl_setopt($ch, CURLOPT_URL,$posturl); //抓取指定网页
curl_setopt($ch, CURLOPT_HEADER, 0); //设置header
//这一步为最关键!!设置head头的请求数据格式为json
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Content-type:application/json;charset=utf-8",
"Content-Length: " . strlen($jsoninfo)
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_POST, 1); //post提交方式
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsoninfo); //添加请求的json数据
$data = curl_exec($ch); //运行curl 返回请求的json数据
$json = json_decode($data); //把json数据转为php的对象类型
curl_close($ch); //关闭curl
使用用curl传输json数据的实际案例可查看我的上一篇文章:使用php接入图灵机器人的方法
向图灵机器人的API提交json数据的POST请求中,本人使用的就是这个方法。
更多cURL的案例和使用方法可查看官方文档,地址如下:
http://php.net/manual/zh/book.curl.php
感谢阅读
原文地址:https://www.jianshu.com/p/97243d2153c2
PHP的cURL扩展库使用详解的更多相关文章
- PHP扩展代码结构详解
PHP扩展代码结构详解: 这个是继:使用ext_skel和phpize构建php5扩展 内容 (拆分出来) Zend_API:深入_PHP_内核:http://cn2.php.net/manual/ ...
- Python爬虫之selenium库使用详解
Python爬虫之selenium库使用详解 本章内容如下: 什么是Selenium selenium基本使用 声明浏览器对象 访问页面 查找元素 多个元素查找 元素交互操作 交互动作 执行JavaS ...
- STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解)
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) 前面 ...
- IOC和AOP使用扩展之AOP详解实现类
摘要: “Depend on yourself” is what nature says to every man. Parents can help you. Teachers can hel ...
- 标准I/O库(详解)(Standard I/O Library)
文章转自:https://www.cnblogs.com/kingcat/archive/2012/05/09/2491847.html 自己在学习中,对此原文的基础之上进行补充. 什么是缓冲区 缓冲 ...
- Linux 库文件详解
转自: http://www.cppblog.com/deane/articles/165216.html http://blog.sciencenet.cn/blog-1225851-904348. ...
- 扩展中国剩余定理(扩展CRT)详解
今天在$xsy$上翻题翻到了一道扩展CRT的题,就顺便重温了下(扩展CRT模板也在里面) 中国剩余定理是用于求一个最小的$x$,满足$x\equiv c_i \pmod{m_i}$. 正常的$CRT$ ...
- 扩展欧几里得算法详解(exgcd)
一.前言 本博客适合已经学会欧几里得算法的人食用~~~ 二.扩展欧几里得算法 为了更好的理解扩展欧几里得算法,首先你要知道一个叫做贝祖定理的玄学定理: 即如果a.b是整数,那么一定存在整数x.y使得$ ...
- STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解)
介绍 FwLib_STC8 是一个针对STC8G, STC8H系列MCU的C语言封装库, 适用于基于这些MCU的快速原型验证. 项目地址: Gitee FwLib_STC8 镜像地址: GitHub ...
随机推荐
- 求N!中素数的个数
int degree_in_fact(int n, int x)//求n!中素数x的次数 { if(m) return degree_in_fact(n/x,x)+n/x; ; }
- 生成器yield(17-06)
yield 执行以上代码,yield后面可以有返回值 next() 获取 next的使用次数,是你生成器中yield出现的次数 def p(): print("ok") yiel ...
- Django2.0+小程序技术打造微信小程序助手✍✍✍
Django2.0+小程序技术打造微信小程序助手 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课程本身没问题 ...
- java、jsp导出excel功能备份
问题踩坑: ajax请求不能下载文件 必须这样: <a href="/media">点击下载Excel</a> 或者 location.href = '/m ...
- 转载别人的ftp,觉得目录结构不错,学习
开发简单的FTP:1. 用户登陆2. 上传/下载文件3. 不同用户家目录不同4. 查看当前目录下文件5. 充分使用面向对象知识 REDMAE 1 用户登陆 2 3 1.查看用户目录文件 4 2.上传文 ...
- Widget Factory
Widget Factory 有N种零件,生产所需天数都为3~9天,有M条记录,记录开工星期几,和停工星期几,并告诉你这条记录所加工的零件,求每种零件的生产时间,\(1≤N,M≤300\). 解 显然 ...
- 2016.8.17上午纪中初中部NOIP普及组比赛
2016.8.17上午纪中初中部NOIP普及组比赛 链接:https://jzoj.net/junior/#contest/home/1335 本来觉得自己能考高分,但只得160分,并列第九.至少又挤 ...
- Idea安装Mevn
1.下载mevn安装包. 下载地址:http://maven.apache.org/ 点击Download 2.下面这两个选哪个都可以,取决于你用什么方式解压 3.把下载好的安装包解压到一个没有中文的 ...
- Python-线程(1)
目录 什么是线程 进程与线程的区别 开启线程 为什么要使用线程 线程之间数据是共享的 什么是线程 线程与进程都是虚拟单位,目的是为了更好的描述某种事物 进程与线程的区别 进程:资源单位 线程:执行单位 ...
- 线性回归和梯度下降代码demo
程序所用文件:https://files.cnblogs.com/files/henuliulei/%E5%9B%9E%E5%BD%92%E5%88%86%E7%B1%BB%E6%95%B0%E6%8 ...