• curl 请求类 数据采集 何苦


    <?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;
    //            $options[CURLOPT_COOKIE]  = $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();
        }
    }
        
    
  • 相关阅读:
    初步学习vue.js
    ie兼容CSS3渐变写法
    关于javascript dom扩展:Selector API
    jquery 性能优化高级技巧
    三行代码CSS竖向居中
    JS中 (function(){...})()立即执行函数
    Null 和 undefined 的区别
    CSS 交集选择器和并集选择器
    Vue-cli 构建项目后 npm run build 如何在本地运行查看
    Cubic-bezier 曲线
  • 原文地址:https://www.cnblogs.com/fuqian/p/16026560.html
Copyright © 2020-2023  润新知