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

感谢阅读

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355

推荐阅读更多精彩内容