在还没有接触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扩展库使用详解的更多相关文章

  1. PHP扩展代码结构详解

    PHP扩展代码结构详解: 这个是继:使用ext_skel和phpize构建php5扩展  内容 (拆分出来) Zend_API:深入_PHP_内核:http://cn2.php.net/manual/ ...

  2. Python爬虫之selenium库使用详解

    Python爬虫之selenium库使用详解 本章内容如下: 什么是Selenium selenium基本使用 声明浏览器对象 访问页面 查找元素 多个元素查找 元素交互操作 交互动作 执行JavaS ...

  3. STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解)

    目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) 前面 ...

  4. IOC和AOP使用扩展之AOP详解实现类

    摘要:   “Depend on yourself” is what nature says to every man.  Parents can help you. Teachers can hel ...

  5. 标准I/O库(详解)(Standard I/O Library)

    文章转自:https://www.cnblogs.com/kingcat/archive/2012/05/09/2491847.html 自己在学习中,对此原文的基础之上进行补充. 什么是缓冲区 缓冲 ...

  6. Linux 库文件详解

    转自: http://www.cppblog.com/deane/articles/165216.html http://blog.sciencenet.cn/blog-1225851-904348. ...

  7. 扩展中国剩余定理(扩展CRT)详解

    今天在$xsy$上翻题翻到了一道扩展CRT的题,就顺便重温了下(扩展CRT模板也在里面) 中国剩余定理是用于求一个最小的$x$,满足$x\equiv c_i \pmod{m_i}$. 正常的$CRT$ ...

  8. 扩展欧几里得算法详解(exgcd)

    一.前言 本博客适合已经学会欧几里得算法的人食用~~~ 二.扩展欧几里得算法 为了更好的理解扩展欧几里得算法,首先你要知道一个叫做贝祖定理的玄学定理: 即如果a.b是整数,那么一定存在整数x.y使得$ ...

  9. STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解)

    介绍 FwLib_STC8 是一个针对STC8G, STC8H系列MCU的C语言封装库, 适用于基于这些MCU的快速原型验证. 项目地址: Gitee FwLib_STC8 镜像地址: GitHub ...

随机推荐

  1. day19_生成器

    20180730 初次上传 20180731 更新,4.列表生成式,以及部分注释 #!/usr/bin/env python # -*- coding:utf-8 -*- # ************ ...

  2. this关键字、static关键字、block块、封装类以及继承、import、修饰符的初步了解

    this关键字 定义 在类的方法定义中使用this关键字代表使用该方法的引用. this即"自己",代表对象本身,谁调用代表谁.在成员方法中或构造器中隐式的传递. this的两种用 ...

  3. springcloud系列13 config的客户端使用

    config客户端的使用: 也是首先要引入依赖: <dependency> <groupId>org.springframework.cloud</groupId> ...

  4. HTML中被废弃的标签<b><u><i><s>

    <strong>代替<b>给文字加粗 <ins>代替<u>给文本添加下划线 <em>代替<i>将文本倾斜 <del> ...

  5. Activiti业务键(businessKey)

    问题:如何让业务对象和对应的流程 关联? 发现ProcessInstance 有个方法getBusinessKey()可以得到一个businessKey. ProcessInstance 对应数据库中 ...

  6. 《我是一只IT小小鸟》读书笔记 PB16110698 第四周(~3.29)

    <我是一只IT小小鸟>读书笔记 本周在邓老师的推荐下,我阅读了<我是一只IT小小鸟>,这本书由21位初入职场的IT人的传记组成,记录了他们成长道路上的酸甜苦辣.书中一段段鲜活生 ...

  7. 笔记:Python操作sql

    python操作mysql步骤: 创建connect连接 conn = connect(host='127.0.0.1', port=3306, user='root', password='1234 ...

  8. 【珍惜时间】iReport

    项目很点意思,感觉很高超的样子 先放下项目的github地址:https://github.com/tctangyanan/iReport 感谢各位伟大的程序员无私的分享自己的技术 老规矩,我们会运行 ...

  9. Ubuntu vi命令

    最近在使用ubuntu,在linux下,要编辑文件或者其他的文本文件,哪那么一个ubuntu linux下的强大的文本编辑工具就不得不提了,那就是VI编辑器.下面把VI常用到的命令行贴出来. :w  ...

  10. React在componentWillMount中请求接口数据结束后再执行render

    1.在getInitialState中初始化isloading,初始值false getInitialState() { return { editionid: '', isloading:false ...