使用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