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 ...
随机推荐
- 第十九篇:Mysql两次Group by和ip转数字作比较的一次优化
业务场景:两张表,ipconfig_group表存了单位和 ip 起始段信息 visit_info表存储了访问次数,失败次数,访问流量,用户ip等信息 两张表的关系为: 一个部门下有若干ip段, ...
- Post Office IOI 2000 /// 区间DP oj24077
题目大意: 给定n个村庄的坐标,两个村庄之间的距离是其坐标之差的绝对值 最多能选m个村庄设立邮局,求设立邮局的地点使得各村庄与邮局距离总和最小 一, 所有的村庄看做在一条直线上 考虑三个因素:i 当前 ...
- Spring 基于xml配置方式的AOP(8)
1.ArithmeticCalculator.java 1 package com.proc; 2 3 public interface ArithmeticCalculator { 4 int ad ...
- Leetcode93. Restore IP Addresses复原IP地址
给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式. 示例: 输入: "25525511135" 输出: ["255.255.11.135", ...
- Java中Arrys数组常用的方法
Arrys常用方法 1.toString() Arrays.toString(arr) //打印数组的内容,观察数组元素的值 2.sort() Arrays.sort(arr); ...
- WPF 多语言
1.http://www.cnblogs.com/bear831204/archive/2009/03/17/1414026.html 2.http://www.cnblogs.com/horan/a ...
- 21分钟教会你分析MaxCompute账单
背景 阿里云大计算服务MaxCompute是一款商业化的大数据分析平台,其计算资源有预付费和后付费两种计费方式.并且产品每天按照project为维度进行计量计费(账单基本情况下会第二天6点前产出).本 ...
- Django项目:CMDB(服务器硬件资产自动采集系统)--11--07CMDB文件模式测试采集硬件数据
#settings.py # ————————01CMDB获取服务器基本信息———————— import os BASEDIR = os.path.dirname(os.path.dirname(o ...
- arguments介绍(二)
1.1 将参数从一个函数传递到另一个函数 下面是将参数从一个函数传递到另一个函数的推荐做法. function foo() { bar.apply(this, arguments); } functi ...
- laravel框架中使用QueryList插件采集数据
laravel框架中使用queryList 采集数据 采集数据对我们来说真家常便饭,那么苦苦的写正则采集那么一点点东西,花费了自己大把的时间和精力而且没有一点技术含量,这个时候就是使用我们的好搭档Qu ...