什么是curl

curl 是一个利用URL语法规定来传输文件和数据的工具,支持很多协议,如HTTP、FTP、TELNET等。
PHP也支持 curl 库。
本文将先容 curl 的一些高等特性,本期文章会教大家如何利用它。

为什么要用 curl?

phpcurl大量任务CURL功效本来这么壮大PHP年夜神都在用 Python

是的,我们可以通过其他办法获取网页内容。
大多数时候,我由于想偷

代码演示

$content = file_get_contents(\"大众http://www.xxx.com\公众); //直接获取网页上的内容

$lines = file(\公众http://www.xxx.com\"大众);

readfile(http://www.xxx.com);

不过,这种做法缺少灵巧性和有效的缺点处理。
而且,你也不能用它完成一些高难度任务——比如处理coockies、验证、表单提交、文件上传等等,那么这个时候curl就派上用途。

由于curl本身是一种功能强大的库,支持很多不同的协议能供应 URL 要求干系的各种细节信息。

下面直接教大家如何利用curl

在学习更为繁芜的功能之前,先来看一下要求的基本步骤:

// 1. 初始化

$ch = curl_init();

// 2. 设置选项,包括URL

curl_setopt($ch, CURLOPT_URL, \"大众http://www.baidu.com\"大众);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($ch, CURLOPT_HEADER, 0);

// 3. 实行并获取HTML文档内容

$output = curl_exec($ch);

// 4. 开释curl句柄

curl_close($ch);

第二步(也便是 curl_setopt() 有一长串cURL参数可供设置,它们能指定URL要求的各个细节。
要一次性全部先容完比较难,本日我们只试一下那些更常用也更有用的选项。

$output = curl_exec($ch);

if ($output === FALSE) {//检测是否缺点

echo \公众curl Error: \公众 . curl_error($ch);

}

curl_exec($ch);

$info = curl_getinfo($ch);//直接返回结果给info

返回的数组中包括了以下信息:

curl_setopt设置的参数

\"大众URL\公众 //资源网络地址

\"大众CONTENT_TYPE\"大众 //内容编码

\"大众HTTP_CODE\公众 //HTTP状态码

\公众HEADER_SIZE\公众 //header的大小

\"大众REQUEST_SIZE\"大众 //要求的大小

\"大众FILETIME\公众 //文件创建韶光

\"大众SSL_VERIFY_RESULT\"大众 //SSL验证结果

\公众REDIRECT_COUNT\公众 //跳转技能

\"大众TOTAL_TIME\"大众 //总耗时

\公众NAMELOOKUP_TIME\公众 //DNS查询耗时

\公众CONNECT_TIME\"大众 //等待连接耗时

\"大众PRETRANSFER_TIME\"大众 //传输前准备耗时

\"大众SIZE_UPLOAD\"大众 //上传数据的大小

\"大众SIZE_DOWNLOAD\"大众 //下载数据的大小

\公众SPEED_DOWNLOAD\公众 //下载速率

\"大众SPEED_UPLOAD\公众 //上传速率

\公众DOWNLOAD_CONTENT_LENGTH\"大众 /下载内容的长度

\"大众UPLOAD_CONTENT_LENGTH\"大众 //上传内容的长度

\公众STARTTRANSFER_TIME\公众 //开始传输的韶光

\公众REDIRECT_TIME\"大众 //重定向耗时

我们利用 CURLOPT_HTTPHEADER 选项来设定我们发送出的HTTP要求头信息(http headers),包括user agent信息和默认措辞。
然后我们来看看这些特定网站是否会把我们重定向到不同的URL。

以下为引用的内容:

// 测试用的URL

$urls = array(

\"大众http://www.aaa.com\"大众,

\"大众http://www.bbb.com\公众,

\公众http://www.ccc.com\"大众

);

$browsers = array(

\"大众standard\公众 => array (

\"大众user_agent\"大众 => \公众Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 (.NET CLR 3.5.30729)\"大众,

\"大众language\"大众 => \公众en-us,en;q=0.5\公众

),

\"大众iphone\"大众 => array (

\"大众user_agent\公众 => \"大众Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A537a Safari/419.3\"大众,

\"大众language\"大众 => \"大众en\"大众

),

\"大众french\"大众 => array (

\"大众user_agent\"大众 => \"大众Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GTB6; .NET CLR 2.0.50727)\"大众,

\"大众language\"大众 => \公众fr,fr-FR;q=0.5\"大众

)

);

foreach ($urls as $url) {

echo \"大众URL: $url\n\公众;

foreach ($browsers as $test_name => $browser) {

$ch = curl_init();

// 设置 url

curl_setopt($ch, CURLOPT_URL, $url);

// 设置浏览器的特定header

curl_setopt($ch, CURLOPT_HTTPHEADER, array(

\"大众User-Agent: {$browser['user_agent']}\"大众,

\公众Accept-Language: {$browser['language']}\"大众

));

// 页面内容我们并不须要

curl_setopt($ch, CURLOPT_NOBODY, 1);

// 只需返回HTTP header

curl_setopt($ch, CURLOPT_HEADER, 1);

// 返回结果,而不是输出它

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

$output = curl_exec($ch);

curl_close($ch);

// 有重定向的HTTP头信息吗?

if (preg_match(\"大众!Location: (.)!\"大众, $output, $matches)) {

echo \公众$test_name: redirects to $matches[1]\n\"大众;

} else {

echo \"大众$test_name: no redirection\n\"大众;

}

}

echo \"大众\n\n\公众;

}

用POST方法发送数据

当发起GET要求时,数据可以通过查询字串(query string)通报给一个URL:

http://www.google.com/search?q=demo

这种情形下你可能并不须要cURL来仿照。
把这个URL丢给“file_get_contents()”就能得到相同结果。

不过有一些HTML表单是用POST方法提交的。
这种表单提交时,数据是通过 HTTP要求体(request body) 发送,而不是查询字串。
例如,当利用CodeIgniter论坛的表单,无论你输入什么关键字,总是被POST到如下页面:

http://cc.com/a/b/

你可以用PHP脚本来仿照这种URL要求。
首先,新建一个可以接管并显示POST数据的文件,我们给它命名为post_output.php:

print_r($_POST);

接下来,写一段PHP脚本来实行cURL要求:

以下为引用的内容:

$url = \"大众http://localhost/post_demo.php\公众;

$post_data = array (

\公众foo\"大众 => \公众bar\公众,

\"大众query\"大众 => \"大众demo\"大众,

\"大众action\"大众 => \"大众Submit\公众

);

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

// 我们在POST数据哦!

curl_setopt($ch, CURLOPT_POST, 1);

// 把post的变量加上

curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);

$output = curl_exec($ch);

curl_close($ch);

echo $output;

这段脚本发送一个POST要求给 post_demo.php ,这个页面 $_POST 变量并返回输出。

文件上传

上传文件和前面的POST十分相似。
由于所有的文件上传表单都是通过POST方法提交的。

首先新建一个吸收文件的页面,命名为 upload_info.php:

print_r($_FILES);

以下为引用的内容:

$url = \"大众http://localhost/upload_info.php\"大众;

$post_data = array (

\"大众foo\"大众 => \公众bar\"大众,

// 要上传确当地文件地址

\"大众upload\公众 => \公众@C:/wamp/www/a.zip\"大众

);

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($ch, CURLOPT_POST, 1);

curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);

$output = curl_exec($ch);

curl_close($ch);

echo $output;

如果你须要上传一个文件,只须要把文件路径像一个post变量一样传过去,不过记得在前面加上@符号。
实行这段脚本该当会得到如下输出:

cURL批处理(multi cURL)

cURL还有一个高等特性——批处理句柄(handle)。
这一特性许可你同时或异步地打开多个URL连接。

下面是来自来自php.net的示例代码:

以下为引用的内容:

// 创建两个cURL资源

$ch1 = curl_init();

$ch2 = curl_init();

// 指定URL和适当的参数

curl_setopt($ch1, CURLOPT_URL, \"大众http://lxr.php.net/\公众);

curl_setopt($ch1, CURLOPT_HEADER, 0);

curl_setopt($ch2, CURLOPT_URL, \"大众http://www.php.net/\公众);

curl_setopt($ch2, CURLOPT_HEADER, 0);

// 创建cURL批处理句柄

$mh = curl_multi_init();

// 加上前面两个资源句柄

curl_multi_add_handle($mh,$ch1);

curl_multi_add_handle($mh,$ch2);

// 预定义一个状态变量

$active = null;

// 实行批处理

do {

$mrc = curl_multi_exec($mh, $active);

} while ($mrc == CURLM_CALL_MULTI_PERFORM);

while ($active && $mrc == CURLM_OK) {

if (curl_multi_select($mh) != -1) {

do {

$mrc = curl_multi_exec($mh, $active);

} while ($mrc == CURLM_CALL_MULTI_PERFORM);

}

}

// 关闭各个句柄

curl_multi_remove_handle($mh, $ch1);

curl_multi_remove_handle($mh, $ch2);

curl_multi_close($mh);

这里要做的便是打开多个cURL句柄并指派给一个批处理句柄。
然后你就只需在一个while循环里等它实行完毕。

这个示例中有两个紧张循环。
第一个 do-while 循环重复调用 curl_multi_exec() 。
这个函数是无隔断(non-blocking)的,但会尽可能少地实行。
它返回一个状态值,只要这个值即是常量 CURLM_CALL_MULTI_PERFORM ,就代表还有一些刻不容缓的事情要做(例如,把对应URL的http头信息发送出去)。
也便是说,我们须要不断调用该函数,直到返回值发生改变。

而接下来的 while 循环,只在 $active 变量为 true 时连续。
这一变量之前作为第二个参数传给了 curl_multi_exec() ,代表只要批处理句柄中是否还有活动连接。
接着,我们调用 curl_multi_select() ,在活动连接(例如接管做事器相应)涌现之前,它都是被“屏蔽”的。
这个函数成功实行后,我们又会进入另一个 do-while 循环,连续下一条URL。

HTTP 认证

如果某个URL要求须要基于 HTTP 的身份验证,你可以利用下面的代码:

复制内容到剪贴板代码:

以下为引用的内容:

$url = \"大众http://www.somesite.com/members/\"大众;

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

// 发送用户名和密码

curl_setopt($ch, CURLOPT_USERPWD, \"大众myusername:mypassword\公众);

// 你可以许可其重定向

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

// 下面的选项让 cURL 在重定向后

// 也能发送用户名和密码

curl_setopt($ch, CURLOPT_UNRESTRICTED_AUTH, 1);

$output = curl_exec($ch);

curl_close($ch);

FTP 上传

PHP 自带有 FTP 类库, 但你也能用 cURL:

以下为引用的内容:

// 开一个文件指针

$file = fopen(\"大众/path/to/file\"大众, \公众r\"大众);

// url里包含了大部分所需信息

$url = \"大众ftp://username:password@mydomain.com:21/path/to/new/file\"大众;

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

// 上传干系的选项

curl_setopt($ch, CURLOPT_UPLOAD, 1);

curl_setopt($ch, CURLOPT_INFILE, $fp);

curl_setopt($ch, CURLOPT_INFILESIZE, filesize(\"大众/path/to/file\公众));

// 是否开启ASCII模式 (上传文本文件时有用)

curl_setopt($ch, CURLOPT_FTPASCII, 1);

$output = curl_exec($ch);

curl_close($ch);

本日我们一起学习了cURL库的强大功能和灵巧的扩展性,希望大家看完之后有大家也能够快速上手