使用PHP的cURL库可以简单有效地抓取页面。
它的函数库是蛮大的:
curl_init
初始化一个curl会话,函数唯一的一个参数是可选的,表示一个url地址。
curl_copy_handle
拷贝一个curl连接资源的所有内容和参数
curl_errno
返回一个包含当前会话错误信息的数字编号
curl_error
返回一个包含当前会话错误信息的字符串
curl_strerror
Return string descripbing the given error code
curl_escape
使用URL编码给定的字符串
curl_unescape
解码给定的URL编码的字符串
curl_file_create
Create a CURLFile object(创建文件对象)
curl_exec
执行一个curl会话,唯一的参数是curl_init()函数返回的句柄。
curl_getinfo
获取一个curl连接资源句柄的信息
curl_close
关闭curl会话,唯一的参数是curl_init()函数返回的句柄。
curl_setopt_array
以数组形式为一个curl设置会话参数
curl_setopt
为一个curl设置会话参数
curl_version
获取curl相关的版本信息
curl_multi_init
解析一个curl批处理句柄
curl_multi_add_handle
向curl批处理会话中添加单独的curl句柄资源
curl_multi_exec
解析一个curl批处理句柄
curl_multi_getcontent
返回获取的输出文本流
curl_multi_info_read
获取当前解析的curl的相关传输信息
curl_multi_close
关闭一个批处理句柄资源
curl_multi_remove_handle
移除curl批处理句柄资源中的某一个句柄资源
curl_multi_select
Get all the sockets associated with the cURL extension, which can then be “selected”(等待活跃链接进行选择执行)
curl_multi_perform
(不明)
curl_share_close
Close a cURL share handle
curl_share_init
Initialize a cURL share handle
curl_share_seropt
Set an option for a cURL share handle
curl_pause
Pause and unpause a connection
curl_reset
Reset all options of a libcurl session handle(重置curl句柄配置)
curl_version
获取cURL版本信息
基本例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
$link = "http://blog.1z5k.com/wp-admin/"; //初始化 $curl = curl_init(); //设置选项 curl_setopt($curl, CURLOPT_URL, $link); //设置URL,也可以直接把链接写到初始化中 curl_setopt($curl, CURLOPT_RETURNTRANSFER,1); //是否自动显示返回的信息 curl_setopt($curl, CURLOPT_HEADER, 0); //是否显示头信息 //获取引用的内容 $output = curl_exec($curl); //获取内容过程中的信息 /* $info = curl_getinfo($curl); var_dump($info); ['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'] //重定向耗时 */ //查错 if ($output === FALSE) { echo "cURL Error: " . curl_error($curl); } //关闭curl curl_close($curl); //输出抓取的页面 echo $output; |
post数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$url = "http://localhost/text.php"; $post_data = array ( "name" => "123", "pwd" => "132456", ); $curl= curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 我们在POST数据哦! curl_setopt($curl, CURLOPT_POST, 1); //把post的变量加上 curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data); $output = curl_exec($curl); curl_close($curl); echo $output; |
文件上传
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$url = "http://localhost/text.php"; $post_data = array ( "name" => "123", "pwd" => "132456", "upload" => "@C:/wamp/www/test.zip" //要上传的本地文件地址 ); $curl= curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data); $output = curl_exec($curl); curl_close($curl); echo $output; |
cURL还提供了批量处理会话,下面是cURL批量处理相关函数:
- curl_multi_init — 返回一个新cURL批处理句柄
- curl_multi_add_handle — 向curl批处理会话中添加单独的curl句柄
- curl_multi_exec — 解析一个cURL批处理句柄
- curl_multi_getcontent — 如果设置了CURLOPT_RETURNTRANSFER,则返回获取的输出的文本流
- curl_multi_select — 等待所有cURL批处理中的活动连接
- curl_multi_info_read — 获取当前解析的cURL的相关传输信息
- curl_multi_remove_handle — 移除curl批处理句柄资源中的某个句柄资源
- curl_multi_close — 关闭一组cURL句柄
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
$url_array = array( 'http://www.baidu.com', 'http://blog.1z5k.com' ); $handles = $contents = array(); //创建curl批处理句柄 $multi = curl_multi_init(); //添加curl批处理会话 foreach($url_array as $key=>$url){ $handles[$key] = curl_init($url); curl_setopt($handles[$key], CURLOPT_RETURNTRANSFER, 1); //不自动返回信息 curl_setopt($handles[$key], CURLOPT_TIMEOUT, 10); //延时 curl_setopt($handles[$key], CURLOPT_HEADER, 0); //不发送头信息 curl_multi_add_handle($multi, $handles[$key]); //添加句柄 } //预定义一个状态变量 $active = null; //开始处理 do{ $mrc = curl_multi_exec($multi,$active); } while($mrc==CURLM_CALL_MULTI_PERFORM); while($active && $mrc==CURLM_OK){ if(curl_multi_select($multi)===-1){ usleep(100); } do{ $mrc = curl_multi_exec($multi,$active); } while($mrc==CURLM_CALL_MULTI_PERFORM); } //移除句柄 foreach($handles as $i=>$ch){ //获取处理内容 $content = curl_multi_getcontent($ch); $contents[$i] = curl_errno($ch)==0 ? $content : ''; //移除批处理句柄 curl_multi_remove_handle($multi, $ch); } //关闭句柄 curl_multi_close($multi); //print_r($contents); foreach($contents as $k=>$v){ echo($v); } |
会造成CPU Loading过高,因为$active要等全部url数据接受完毕才变成false,所以这里用到了curl_multi_exec的返回值判断是否还有数据,当有数据的时候就不停调用curl_multi_exec,没有执行数据就会sleep,如此就会避免CPU Loading 100%了。
这个示例中有两个主要循环。第一个 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://www.phpddt.com/php/curl_multi.html
-
http://www.chinaz.com/program/2010/0119/104346.shtml