PHP教程之基于PHP的cURL疾速入门教程 (小偷收集程...
到现在,对排版还是不很熟练,经常会排不好。 最爽的是,PHP也撑持 cURL 库。本文将引见 cURL 的一些初级特征,和在PHP中若何应用它。 为何要用 cURL?是的,咱们可以经由过程其他举措获得网页内容。大多半时分,我由于想偷懒,都直接用复杂的PHP函数:
$content = file_get_contents("http://www.jb51.net");
// or
$lines = file("http://www.jb51.net");
// or
readfile(http://www.jb51.net);
不外,这类做法缺少天真性和无效的毛病处置。并且,你也不克不及用它完成一些高难度义务――好比处置coockies、验证、表单提交、文件上传等等。
援用:
cURL 是一种功效壮大的库,撑持良多分歧的协定、选项,能供应 URL 恳求相干的各类细节信息。
根基布局
在进修更加庞杂的功效之前,先来看一下在PHP中创立cURL恳求的根基步调:
[*]初始化
[*]设置变量
[*]履行并获得了局
[*]释放cURL句柄
// 1. 初始化
$ch = curl_init();
// 2. 设置选项,包含URL
curl_setopt($ch, CURLOPT_URL, "http://www.jb51.net");
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);
}
// ...
请注重,对照的时分咱们用的是“=== FALSE”,而非“== FALSE”。由于咱们得辨别 空输入 和 布尔值FALSE,后者才是真实的毛病。
获得信息
这是另外一个可选的设置项,可以在cURL履行后获得这一恳求的有关信息:
// ...
curl_exec($ch);
$info = curl_getinfo($ch);
echo "获得". $info["url"] . "耗时". $info["total_time"] . "秒";
// ...
前往的数组中包含了以下信息:
[*]“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.cnn.com",
"http://www.mozilla.com",
"http://www.facebook.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\n";
} else {
echo "$test_name: no redirection\n";
}
}
echo "\n\n";
}
起首,咱们创立一组需求测试的URL,接着指定一组需求测试的阅读器信息。最初经由过程轮回测试各类URL和阅读器婚配能够发生的情形。
由于咱们指定了cURL选项,所以前往的输入内容则只包含HTTP头信息(被寄存于 $output 中)。使用一个复杂的正则,咱们反省这个头信息中是不是包括了“Location:”字样。
运转这段代码应当会前往以下了局:
用POST办法发送数据
当倡议GET恳求时,数据可以经由过程“查询字串”(query string)传递给一个URL。例如,在谷歌中搜刮时,搜刮关头即为URL的查询字串的一局部:
http://www.谷歌.com/search?q=nettuts
这类情形下你能够其实不需求cURL来摹拟。把这个URL丢给“file_get_contents()”就可以失掉不异了局。
不外有一些HTML表单是用POST办法提交的。这类表单提交时,数据是经由过程 HTTP恳求体(request body) 发送,而不是查询字串。例如,当利用CodeIgniter服装论坛的表单,不管你输出甚么关头字,老是被POST到以下页面:
http://codeigniter.com/forums/do_search/
你可以用PHP剧本来摹拟这类URL恳求。起首,新建一个可以承受并显示POST数据的文件,咱们给它定名为post_output.php:
print_r($_POST);
接上去,写一段PHP剧本来履行cURL恳求:
$url = "http://localhost/post_output.php";
$post_data = array (
"foo" => "bar",
"query" => "Nettuts",
"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_output.php ,这个页面 $_POST 变量并前往,咱们使用cURL捕获了这个输入。
文件上传
上传文件和后面的POST非常类似。由于一切的文件上传表单都是经由过程POST办法提交的。
起首新建一个吸收文件的页面,定名为 upload_output.php:
print_r($_FILES);
以下是真正履行文件上传义务的剧本:
$url = "http://localhost/upload_output.php";
$post_data = array (
"foo" => "bar",
// 要上传的当地文件地址
"upload" => "@C:/wamp/www/test.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。
仍是来看一看怎样把这一功效用到实处吧:
WordPress 毗连反省器
想象一下你有一个文章数量复杂的博客,这些文章中包括了大批内部网站链接。一段工夫以后,由于如许那样的缘由,这些链接中相当数目都生效了。要末是被协调了,要末是全部站点都被工夫网了...
咱们上面创立一个剧本,剖析一切这些链接,找出打不开或404的网站/网页,并生成一个呈报。
请注重,以下并非一个真正可用的WordPress插件,仅仅是一段自力功效的剧本罢了,仅供演示,感谢。
好,入手下手吧。起首,从数据库中读取一切这些链接:
// CONFIG
$db_host = "localhost";
$db_user = "root";
$db_pass = "";
$db_name = "wordpress";
$excluded_domains = array(
"localhost", "www.mydomain.com");
$max_connections = 10;
// 初始化一些变量
$url_list = array();
$working_urls = array();
$dead_urls = array();
$not_found_urls = array();
$active = null;
// 连到 MySQL
if (!mysql_connect($db_host, $db_user, $db_pass)) {
die("Could not connect: " . mysql_error());
}
if (!mysql_select_db($db_name)) {
die("Could not select db: " . mysql_error());
}
// 找出一切含有链接的文章
$q = "SELECT post_content FROM wp_posts
WHERE post_content LIKE "%href=%"
AND post_status = "publish"
AND post_type = "post"";
$r = mysql_query($q) or die(mysql_error());
while ($d = mysql_fetch_assoc($r)) {
// 用正则婚配链接
if (preg_match_all("!href=\"(.*?)\"!", $d["post_content"], $matches)) {
foreach ($matches as $url) {
// exclude some domains
$tmp = parse_url($url);
if (in_array($tmp["host"], $excluded_domains)) {
continue;
}
// store the url
$url_list []= $url;
}
}
}
// 移除反复链接
$url_list = array_values(array_unique($url_list));
if (!$url_list) {
die("No URL to check");
}
咱们起首设置装备摆设好数据库,一系列要扫除的域名($excluded_domains),和最大并发毗连数($max_connections)。然后,毗连数据库,获得文章和包括的链接,把它们搜集到一个数组中($url_list)。
上面的代码有点庞杂了,因而我将一小步一小步地具体注释:
// 1. 批处置器
$mh = curl_multi_init();
// 2. 到场需批量处置的URL
for ($i = 0; $i < $max_connections; $i++) {
add_url_to_multi_handle($mh, $url_list);
}
// 3. 初始处置
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
// 4. 主轮回
while ($active && $mrc == CURLM_OK) {
// 5. 有举动毗连
if (curl_multi_select($mh) != -1) {
// 6. 干活
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
// 7. 有信息否?
if ($mhinfo = curl_multi_info_read($mh)) {
// 意味着该毗连正常停止
// 8. 从curl句柄获得信息
$chinfo = curl_getinfo($mhinfo["handle"]);
// 9. 逝世链么?
if (!$chinfo["http_code"]) {
$dead_urls []= $chinfo["url"];
// 10. 404了?
} else if ($chinfo["http_code"] == 404) {
$not_found_urls []= $chinfo["url"];
// 11. 还能用
} else {
$working_urls []= $chinfo["url"];
}
// 12. 移除句柄
curl_multi_remove_handle($mh, $mhinfo["handle"]);
curl_close($mhinfo["handle"]);
// 13. 到场新URL,干活
if (add_url_to_multi_handle($mh, $url_list)) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
}
}
// 14. 完了
curl_multi_close($mh);
echo "==Dead URLs==\n";
echo implode("\n",$dead_urls) . "\n\n";
echo "==404 URLs==\n";
echo implode("\n",$not_found_urls) . "\n\n";
echo "==Working URLs==\n";
echo implode("\n",$working_urls);
// 15. 向批处置器添加url
function add_url_to_multi_handle($mh, $url_list) {
static $index = 0;
// 假如还剩url没用
if ($url_list[$index]) {
// 新建curl句柄
$ch = curl_init();
// 设置装备摆设url
curl_setopt($ch, CURLOPT_URL, $url_list[$index]);
// 不想输入前往的内容
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// 重定向到哪儿咱们就去哪儿
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
// 不需求内容体,可以勤俭带宽和工夫
curl_setopt($ch, CURLOPT_NOBODY, 1);
// 到场到批处置器中
curl_multi_add_handle($mh, $ch);
// 拨一下计数器,下次挪用该函数就可以添加下一个url了
$index++;
return true;
} else {
// 没有新的URL需求处置了
return false;
}
}
上面注释一下以上代码。列表的序号对应着代码正文中的按次数字。
[*]新建一个批处置器。Created a multi handle.
[*]稍后咱们将创立一个把URL到场批处置器的函数 add_url_to_multi_handle() 。每当这个函数被挪用,就有一个新url被到场批处置器。一入手下手,咱们给批处置器添加了10个URL(这一数字由 $max_connections 所决意)。
[*] 运转 curl_multi_exec() 停止初始化任务是必需的,只需它前往 CURLM_CALL_MULTI_PERFORM 就还有工作要做。这么做次要是为了创立毗连,它不会守候完全的URL呼应。
[*]只需批处置中还有举动毗连主轮回就会一向延续。
[*]curl_multi_select() 会一向守候,直到某个URL查询发生举动毗连。
[*]cURL的活儿又来了,次要是获得呼应数据。
[*]反省各类信息。当一个URL恳求完成时,会前往一个数组。
[*]在前往的数组中有一个 cURL 句柄。咱们使用其获得单个cURL恳求的响应信息。
[*]假如这是一个逝世链或恳求超时,不会前往http形态码。
[*]假如这个页面找不到了,会前往404形态码。
[*]其他情形咱们都以为这个链接是可用的(固然,你也能够再反省一下500毛病之类...)。
[*]从该批次移除这个cURL句柄,由于它已没有益用价值了,关了它!
[*]很好,如今可以别的加一个URL出去了。再一次地,初始化任务又入手下手停止...
[*]嗯,该干的都干了。封闭批处置器,生成呈报。
[*]回过火来看给批处置器添加新URL的函数。这个函数每挪用一次,静态变量 $index 就递增一次,如许咱们才干晓得还剩几何URL没处置。
我把这个剧本在我的博客上跑了一遍(测试需求,有一些毛病链接是居心加上的),了局以下:
<img border="0" src="/program/UploadPic/2011-7/2011751305355.png" />
共反省约40个URL,只消耗两秒不到。当需求反省加倍大批的URL时,其省心省力的后果可想而知!假如你同时翻开10个毗连,还能再快上10倍!别的,你还可以使用cURL批处置的无间隔特征来处置大批URL恳求,而不会壅塞你的Web剧本。
另外一些有效的cURL 选项
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恳求:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://www.example.com");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// 指定代办署理地址
curl_setopt($ch, CURLOPT_PROXY, "11.11.11.11:8080");
// 假如需求的话,供应用户名和暗码
curl_setopt($ch, CURLOPT_PROXYUSERPWD,"user:pass");
$output = curl_exec($ch);
curl_close ($ch);
回调函数
可以在一个URL恳求过程当中,让cURL挪用某指定的回调函数。例如,在内容或呼应下载的过程当中立即入手下手使用数据,而不必比及完整下载完。
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://net.tutsplus.com");
curl_setopt($ch, CURLOPT_WRITEFUNCTION,"progress_function");
curl_exec($ch);
curl_close ($ch);
function progress_function($ch,$str) {
echo $str;
return strlen($str);
}
这个回调函数必需前往字串的长度,否则此功效将没法正常利用。
在URL呼应吸收的过程当中,只需收到一个数据包,这个函数就会被挪用。
小结
明天咱们一同进修了cURL库的壮大功效和天真的扩大性。但愿你喜好。下一主要倡议URL恳求时,思索下cURL吧!
原文:基于PHP的cURL疾速入门
英文原文:http://net.tutsplus.com/tutorial%20...%20for-mastering-curl/
原文作者:Burak Guzel
也或许是因为我还没有真正的学到深处吧,说实在的,PHP中的很多高级点的应用,如PHP类、PHP函数基本还是不懂吧! 基础有没有对学习php没有太大区别,关键是兴趣。 环境搭建好,当你看见你的浏览器输出“it works\\\\\\\"时你一定是喜悦的。在你解决问题的时候,我强烈建议多读php手册。 刚开始安装php的时候,我图了个省事,把php的扩展全都打开啦(就是把php.ini 那一片 extension 前面的冒号全去掉啦),这样自然有好处,以后不用再需要什么功能再来打开。 Apache不是非得用80或者8080端口的,我刚开始安得时候就是80端口老占用,就用了个 81端口,结果照常,就是输localhost的时候,应该输入为 localhost:81 基础有没有对学习php没有太大区别,关键是兴趣。 找到的的资料很多都是在论坛里的,需要注册,所以我一般没到一个论坛都注册一个id,所有的id都注册成一样的,这样下次再进来的时候就不用重复注册啦。当然有些论坛的某些资料是需要的付费的。 多看优秀程序员编写的代码,仔细理解他们解决问题的方法,对自身有很大的帮助。 先学习php和mysql,还有css(html语言很简单)我认为现在的效果比以前的方法好。 如果你已经到这种程度了,那么你已经可以做我的老师了。其实php也分很多的区域, 没接触过框架的人,也不用害怕,其实框架就是一种命名规范及插件,学会一个框架其余的框架都很好上手的。 真正的方向了,如果将来要去开发团队,你一定要学好smarty ,phplib这样的模板引擎, 真正的方向了,如果将来要去开发团队,你一定要学好smarty ,phplib这样的模板引擎, 建数据库表的时候,int型要输入长度的,其实是个摆设的输入几位都没影响的,只要大于4就行,囧。 说点我烦的低级错误吧,曾经有次插入mysql的时间 弄了300年结果老报错,其实mysql的时间是有限制的,大概是到203X年具体的记不清啦,囧。 你很难利用原理去编写自己的代码。对于php来说,系统的学习我认为还是很重要的,当你有一定理解后,你可你针对某种效果研究,我想那时你不会只是复制代码的水平了。 小鸟是第一次发帖(我习惯潜水的(*^__^*) 嘻嘻……),有错误之处还请大家批评指正,另外,前些日子听人说有高手能用php写驱动程序,真是学无止境,人外有人,天外有天。 至于模板嘛,各位高人一直以来就是争论不休,我一只小菜鸟就不加入战团啦,咱们新手还是多学点东西的好。 学好程序语言,多些才是王道,写两个小时代码的作用绝对超过看一天书,这个我是深有体会(顺便还能练打字速度)。
页:
[1]