使用PHP提供的CURL模块采集任意网页 已经封装一个类超级好用 请拿走
来源:互联网 发布:php判断原生语句查询 编辑:程序博客网 时间:2024/06/05 14:39
<?php/** * 类名称:curl * 1.支持单个get,post请求 * 2.支持多个目标未登录get请求 * 3.支持单个目标并行多个get,post请求 * 4.支持ajax请求 * 5.支持自定义header请求 * 6.支持自定义编码数据请求(该情况比较特殊) * 7.支持代理登陆 * 8.支持自定义来路 * 9.支持自定义超时 * 10.支持文件上传 *//** * demo1 get 请求 * curl()->get("http://www.baidu.com")->body(); *//** * demo2 post请求 * curl()->post("http://www.xxx.com/say.php",array( * 'data' => array( * 'title' => 'test title', * 'content' => 'test content', * ), * ))->body(); *//** * demo3 post请求 ajax请求 并设置cookie * curl()->post("http://www.xxx.com/save.php",array( * 'data' => array( * 'username' => 'test', * 'password' => 'test' * ), * 'cookie_file' => '/tmp/cookie.txt', * 'ajax' => 1, * ))->body(); *//*** * demo4 批处理get请求 * curl()->get(array( * 'http://www.xxx.com/test1.php?aaa=111', * 'http://www.xxx.com/test2.php?aaa=222', * 'http://www.xxx.com/test3.php?aaa=333', * ))->body(); *//*** * demo5 批处理post请求 post请求,目前只支持单个网站的批处理post请求 * curl()->post(array( * 'http://www.xxx.com/test1.php', * 'http://www.xxx.com/test2.php', * 'http://www.xxx.com/test3.php', * ),array( * 'data' => array( * array( * 'uid' => 'aabbccdd', * ), * array( * 'uid' => 'eeeeeeee', * ), * array( * 'uid' => 'ffffffff', * ), * ), * 'cookie_file' => '/tmp/cookie.txt' * ))->body(); *//** * demo6 文件上传 * curl()->post('填写url地址',array( * 'files' => array( * 'pic' => '/tmp/a.gif' , * ), * ))->body(); *//** * 其他方法未一一列举,可查看源码进行测试 */class Curl { //单例对象 private static $ins = null; //请求结果 private $body = null; //cookie文件 private $cookieFile = null; //支持的请求方法 private $method = array('get','post'); //禁用初始化方法 final private function __construct() { } /** * 单例化对象 */ public static function exec() { if (self::$ins) { return self::$ins; } return self::$ins = new self(); } /** * 禁止克隆对象 */ public function __clone() { throw new curlException('错误:不能克隆对象'); } /** * 调用不存在的方法被调用 */ public function __call($method, $args) { if(!in_array($method,$this->method)) { throw new curlException("错误:不支持{$method}方法,支持的方法有" . join(',',$this->method)); } return $this->request($method, $args); } /** * 返回执行结果 */ public function body() { return $this->body; } /** * 执行请求 * @param type $method * @param type $args * @return 返回对象本身 */ private function request($method, $args) { if (isset($args[1]['multi'])) { $this->body = $this->multiExecCurl($method, $args); } else { $this->body = $this->execCurl($method, $args); } return $this; } /** * curl 批处理请求 * @param type $method * @param type $args * @return type */ public function multiExecCurl($method, $args) { $urls = isset($args[0]) ? $args[0] : ""; $data = isset($args[1]['data']) ? $args[1]['data'] : ""; $ajax = isset($args[1]['ajax']) ? $args[1]['ajax'] : ""; $timeout = isset($args[1]['timeout']) ? $args[1]['timeout'] : 30; $referer = isset($args[1]['referer']) ? $args[1]['referer'] : ""; $proxy = isset($args[1]['proxy']) ? $args[1]['proxy'] : ""; $headers = isset($args[1]['headers']) ? $args[1]['headers'] : ""; if (!is_array($urls) || (is_array($urls) && empty($urls))) { throw new curlException("错误信息:批处理url必须是数组并且不能为空"); } //创建批处理cURL句柄 $queue = curl_multi_init(); //取得cookie文件路径 if(!$this->cookieFile) { $this->cookieFile = isset($args[1]['cookie_file']) ? $args[1]['cookie_file'] : ""; } //如果未获取到浏览器环境信息,就手动指定一个 $userAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:23.0) ' .'Gecko/20100101 Firefox/23.0'; //设置CURL OPT选项 $options = array( CURLOPT_TIMEOUT => $timeout, //超时 CURLOPT_RETURNTRANSFER => 1, //输出数据流 CURLOPT_HEADER => 0, //禁止头文件数据流输出 CURLOPT_FOLLOWLOCATION => 1, //自动跳转追踪 CURLOPT_AUTOREFERER => 1, //自动设置来路信息 CURLOPT_SSL_VERIFYPEER => 0, //认证证书检查 CURLOPT_SSL_VERIFYHOST => 0, //检查SSL加密算法 CURLOPT_HEADER => 0, //禁止头文件输出 CURLOPT_NOSIGNAL => 1, //忽略php所有的传递信号 CURLOPT_USERAGENT => $userAgent,//浏览器环境字符串 CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, //ipv4寻址方式 CURLOPT_ENCODING => 'gzip', //解析使用gzip压缩的网页 ); //检测是否存在代理请求 if (is_array($proxy) && !empty($proxy)) { $options[CURLOPT_PROXY] = $proxy['host']; $options[CURLOPT_PROXYPORT] = $proxy['port']; $options[CURLOPT_PROXYUSERPWD] = $proxy['user'] . ':' . $proxy['pass']; } //header选项 $headerOptions = array(); //模拟AJAX请求 if ($ajax) { $headerOptions['X-Requested-With'] = 'XMLHttpRequest'; } if ($this->cookieFile) { $options[CURLOPT_COOKIEFILE] = $this->cookieFile; $options[CURLOPT_COOKIEJAR] = $this->cookieFile; } if ($referer) { $options[CURLOPT_REFERER] = $referer; } if (!empty($headerOptions)) { $options[CURLOPT_HTTPHEADER] = $headerOptions; } //循环的进行初始化一个cURL会话 foreach ($urls as $k => $url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); if ($method == 'post') { //发送一个常规的POST请求, //类型为:application/x-www-form-urlencoded,就像表单提交的一样 $options[CURLOPT_POST] = 1; //使用HTTP协议中的"POST"操作来发送数据,支持键值对数组定义 //注意:即使不使用http_build_query也能自动编码 $options[CURLOPT_POSTFIELDS] = $data[$k]; } curl_setopt_array($ch,$options); curl_multi_add_handle($queue, $ch); } //初始化变量 $responses = array(); $active = null; //循环运行当前 cURL 句柄的子连接 do { while (($code = curl_multi_exec($queue, $active)) == CURLM_CALL_MULTI_PERFORM); if ($code != CURLM_OK) { break; } //循环获取当前解析的cURL的相关传输信息 while ($done = curl_multi_info_read($queue)) { //获取最后一次传输的相关信息 $info = curl_getinfo($done['handle']); //从最后一次传输的相关信息中找 http_code 等于200 if ($info['http_code'] == 200) { //如果设置了CURLOPT_RETURNTRANSFER,获取的输出的文本流 $responses[] = curl_multi_getcontent($done['handle']); } //移除curl批处理句柄资源中的某个句柄资源 curl_multi_remove_handle($queue, $done['handle']); //关闭某个批处理句柄会话 curl_close($done['handle']); } if ($active > 0) { //等待所有cURL批处理中的活动连接 curl_multi_select($queue, 0.5); } } while ($active); //关闭一组cURL句柄 curl_multi_close($queue); //返回结果 return $responses; } /** * curl 单句柄请求 * @param type $method * @param type $args * @return type */ private function execCurl($method, $args) { //解析参数 $url = isset($args[0]) ? $args[0] : ""; $multi = isset($args[1]['multi']) ? $args[1]['multi'] : ""; $data = isset($args[1]['data']) ? $args[1]['data'] : ""; $ajax = isset($args[1]['ajax']) ? $args[1]['ajax'] : ""; $timeout = isset($args[1]['timeout']) ? $args[1]['timeout'] : 30; $files = isset($args[1]['files']) ? $args[1]['files'] : ""; $referer = isset($args[1]['referer']) ? $args[1]['referer'] : ""; $proxy = isset($args[1]['proxy']) ? $args[1]['proxy'] : ""; $headers = isset($args[1]['headers']) ? $args[1]['headers'] : ""; //如果环境变量的浏览器信息不存在,就是用手动设置的浏览器信息 $userAgent = isset($_SERVER['HTTP_USER_AGENT'])? $_SERVER['HTTP_USER_AGENT']: 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0'; //检测url必须参数 不能为空 if (!$url) { throw new curlException("错误:curl请求地址不能为空"); } //设置curl选项 $options = array( CURLOPT_URL => $url, //目标url CURLOPT_TIMEOUT => $timeout, //超时 CURLOPT_RETURNTRANSFER => 1, //输出数据流 CURLOPT_FOLLOWLOCATION => 1, //自动跳转追踪 CURLOPT_AUTOREFERER => 1, //自动设置来路信息 CURLOPT_SSL_VERIFYPEER => 0, //认证证书检查 CURLOPT_SSL_VERIFYHOST => 0, //检查SSL加密算法 CURLOPT_HEADER => 0, //禁止头文件输出 CURLOPT_NOSIGNAL => 1, //忽略所有传递的信号 CURLOPT_USERAGENT => $userAgent,//浏览器环境字符串 CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, //ipv4寻址方式 CURLOPT_ENCODING => 'gzip', //解析使用gzip压缩的网页 ); //获取cookie文件地址路径 if(!$this->cookieFile) { $this->cookieFile = isset($args[1]['cookie_file']) ? $args[1]['cookie_file'] : ""; } //设置代理 必须是数组并且非空 if (is_array($proxy) && !empty($proxy)) { $options[CURLOPT_PROXY] = $proxy['host']; $options[CURLOPT_PROXYPORT] = $proxy['port']; $options[CURLOPT_PROXYUSERPWD] = $proxy['user'] . ':' . $proxy['pass']; } //检测是否未启用自定义urlencode编码 if (!isset($args[1]['build'])) { if ($data && $method == "post" && is_array($data)) { $data = http_build_query($data, '', '&'); } } //检测是否含有上传文件 if ($files && $method == "post" && is_array($files)) { foreach ($files as $k => $v) { $files[$k] = '@' . $v; } parse_str($data, $data); $data = $data + $files; } //检测判断是否是post请求 if ($method == 'post') { //发送一个常规的POST请求 $options[CURLOPT_POST] = 1; //使用HTTP协议中的"POST"操作来发送数据,支持键值对数组定义 $options[CURLOPT_POSTFIELDS] = $data; } //初始化header数组 $headerOptions = array(); //检测是否是ajax提交 if ($ajax) { $headerOptions['X-Requested-With'] = 'XMLHttpRequest'; } //设置cookie if ($this->cookieFile) { $options[CURLOPT_COOKIEFILE] = $this->cookieFile; $options[CURLOPT_COOKIEJAR] = $this->cookieFile; } //设置来路 if ($referer) { $options[CURLOPT_REFERER] = $referer; } //合并header if (!empty($headers) && is_array($headers)) { foreach ($headers as $k => $v) { $headerOptions[$k] = $v; } } //转换header选项为浏览器header格式 if (!empty($headerOptions) && is_array($headerOptions)) { $array = array(); foreach($headerOptions as $k => $v) { $array[] = $k . ": " . $v; } $options[CURLOPT_HTTPHEADER] = $array; } //创建curl句柄 $ch = curl_init(); //设置curl选项 curl_setopt_array($ch, $options); //获取返回内容 $content = curl_exec($ch); //关闭curl句柄 curl_close($ch); //返回内容 return $content; } /** * 对一个对象进行字符串echo输出 * 自动调用__toString方法 * @return type */ public function __toString() { return $this->body(); } }class curlException extends Exception {}//curl方法不存在就设置一个curl方法if (!function_exists('curl')) { function curl() { return curl::exec(); }}
说明:
该类仅仅支持get请求和post请求,已经足够采集使用
支持批量采集!但是请慎用 CURL的批量采集去采集网页,
批量采集比较不稳定容易丢失数据包
批量采集用于处理程序内部接口的并发使用,偶尔代替一下多线程并发处理操作
如果使用请自行测试!
就目前来说,使用该类足以应付大部分的采集工作需求!无需其他工具
采集回来的网页使用正则处理即可
例子以a5站长网为例 抓去目标栏目中的所有列表
分析出a5科技栏目中总所有的文章总数 将文章列表存入到list.txt文件中
如若采集文章,就循环list.txt中的url地址,进行正则匹配采集文章内容
<?php//采集演示 set_time_limit(0);//永久运行 ob_clean(); $start = 1; $end = 805; $preg1 = '#<a href="([a-zA-Z0-9\/\:\.]+?)" class="sherry_title">([\S\s]+?)</a>#is'; for ($i=$start;$i<=$end;$i++) { $arr = array(); $arc_list = $this->curl()->get("http://www.admin5.com/browse/177/list_{$i}.shtml")->body(); preg_match_all($preg1,$arc_list,$arr); $text = ""; foreach($arr[1] as $k => $v) { $text .= "{$v}|||{$arr[2][$k]}\r\n"; } $fp = fopen("d:/list.txt","a+");//存放到我的电脑d盘下中的list.txt文件 如测试此文件请换成自己的路径 fwrite($fp,$text); fclose($fp); ob_flush(); echo "第{$i}页列表抓取完成<br />"; flush(); usleep(500); }
0 0
- 使用PHP提供的CURL模块采集任意网页 已经封装一个类超级好用 请拿走
- 封装一个超级好用的ToastUtils帮助类
- curl 封装采集类
- php封装好的curl操作
- 使用PHP的CURL模拟POST采集开了viewstate的asp.net网页数据
- 使用PHP的CURL模拟POST采集开了viewstate的asp.net网页数据
- php的curl多线程采集网页的解决办法
- php的curl封装类
- php的curl封装类
- 一个好用的Curl的类
- 超级好用的PHP分页类
- php 使用CURL函数采集
- 用PHP的CURL写的一个采集Discuz的例子
- 用PHP的CURL写的一个采集Discuz的例子
- php - 封装 - curl类
- 如何向已经安装好的apache添加一个模块
- 如何向已经安装好的apache添加一个模块
- 一个简陋的支持HTTPS的PHP CURL封装函数
- 数据库水平拆分和垂直拆分区别(以mysql为例)
- Android:为什么声明控件和控件赋值要分开?
- 6.1二叉树的创建
- windows bat 开启关闭远程桌面
- 我是新生
- 使用PHP提供的CURL模块采集任意网页 已经封装一个类超级好用 请拿走
- [Android分享] 致自学的朋友们
- 记忆减退之---如何选择合适的电容
- Android笔记 notification
- UVA 674 - Coin Change
- 关于crontab无法编辑的问题
- 责任链模式随记
- cocos2d-x3.2在mac os下打包android系统apk
- 将异常(getStackTrace)转化成String