page contents

php创建多个请求实现多进程

以下内容希望帮助到大家!

attachments-2020-03-F96m3hrI5e82df18edf8d.jpg


1:引入第三方类库

v2-f30bc40a8617e91fbbaf1fe223bd11ba_720w.jpg

vendor下:

<?php
namespace Curlroll;
class CurlRoll
{
    /**
     * @var int
     * 并发请求数,设置此值过大,同一时间内如果请求远端主机会很容易被判定为DDos攻击
     */
    private $window_size = 5;
    /**
     * @var float
     * curl_multi_select 处理超时时间.
     */
    private $timeout = 10;
    /**
     * @var array
     * 请求对象 CurlRequest 实例数组
     */
    private $requests = array();
    /**
     * @var array
     * 并发请求map
     */
    private $requestMap = array();
    /**
     * @var string|array
     * callback function,结果处理回调函数.
     */
    private $callback;
    /**
     * @var array
     * HTTP request default options.
     */
    private $options = array(
        CURLOPT_SSL_VERIFYPEER => 0, //不开启https请求
        CURLOPT_RETURNTRANSFER => 1, //请求信息以文件流方式返回
        CURLOPT_CONNECTTIMEOUT => 10, //连接超时时间
        CURLOPT_TIMEOUT => 20, //设置curl执行最大时间
        CURLOPT_FOLLOWLOCATION => 1, //curl允许根据response location的值重定向请求
        CURLOPT_MAXREDIRS => 5, //CURLOPT_FOLLOWLOCATION为真后,此值设定重定向递归最大次数
        CURLOPT_HEADER => 0, //设置为true,请求返回的文件流中就会包含response header
        CURLOPT_AUTOREFERER => true, //当根据Location重定向时,自动设置header中的referer信息
        CURLOPT_ENCODING => "", //HTTP请求头中"Accept-Encoding"的值,为空发送所有支持的编码类型
    );
    /**
     * @var array
     * HTTP Request发送的header信息
     */
    private $headers = array(
        'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3',
        'Connection: close',
        'Cache-Control: max-age=0',
        //'X-FORWARD-FOR:8.8.8.8',      //代理ip地址
        //'CLIENT-IP:3.3.3.3',          //客户端ip,REMOTE_ADDR不为空的情况下,是比较真是ip,不好伪造
    );
    private static $agent = array(
        //google chrome
        'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.17 Safari/537.36',
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36',
        'Mozilla/5.0 (X11; CrOS i686 4319.74.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36',
        'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36',
        'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0',
        //firefox
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:25.0) Gecko/20100101 Firefox/25.0',
        'Mozilla/5.0 (Windows NT 6.0; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:24.0) Gecko/20100101 Firefox/24.0',
        'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)',
        //ie
        'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)',
        'Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)',
        'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.4; InfoPath.2; SV1; .NET CLR 3.3.69573; WOW64; en-US)',
    );
    /**
     * @param int
     * $window_size
     */
    public function __construct($window_size = 5)
    {
        $this->window_size = (int)$window_size ? : 5;
    }
    /**
     * @return void
     */
    public function __destruct()
    {
        unset($this->window_size, $this->callback, $this->options, $this->headers, $this->requests);
    }
    /**
     * @param string $name
     * @return mixed
     */
    public function __get($name)
    {
        return isset($this->{$name}) ? $this->{$name} : null;
    }
    /**
     * @param string $name
     * @param mixed $value
     * @return bool
     */
    public function __set($name, $value)
    {
        // append the base options & headers
        if ($name == "options" || $name == "headers")
        {
            $this->{$name} = $value + $this->{$name};
        } else
        {
            $this->{$name} = $value;
        }
        return true;
    }
    /**
     * Add a request to the request queue
     *
     * @param $url
     * @return bool
     */
    public function add($url)
    {
        $this->requests[] = $this->createRequest($url, 'GET', $this->headers, $this->options);
        return true;
    }
    /**
     * Perform GET request
     *
     * @param string $url
     * @param  $headers 不是key-value数组,http请求request header部分的内容
     * $headers = array(
     * "POST ".$page." HTTP/1.0",
     * "Content-type: text/xml;charset=\"utf-8\"",
     * "Accept: text/xml",
     * "Cache-Control: no-cache",
     * "Pragma: no-cache",
     * "SOAPAction: \"run\"",
     * "Content-length: ".strlen($xml_data),
     * "Authorization: Basic " . base64_encode($credentials)
     * );
     * @param  $options
     * @return bool
     */
    public function get($url, $headers = array(), $options = array())
    {
        $this->requests[] = $this->createRequest($url, "GET", $headers, $options);
        return true;
    }
    /**
     * Perform POST request
     *
     * @param string $url
     * @param  $post_data
     * @param  $headers
     * @param  $options
     * @return bool
     */
    public function post($url, $headers = array(), $options = array(), $post_data)
    {
        $this->requests[] = $this->createRequest($url, "POST", $headers, $options, $post_data);
        return true;
    }
    /**
     * Execute processing
     *
     * @param mixed $callback
     * @return string|null
     */
    public function execute($callback = null)
    {
        $ret = null;
        if ($callback)
        {
            $this->callback = $callback;
        }
        if (count($this->requests) == 1)
        {
            $ret = $this->single_curl();
        } else
        {
            $ret = $this->rolling_curl();
        }
        //clear all request once time
        $this->requests = $this->requestMap = array();
        return $ret;
    }
    /**
     * Performs a single curl request
     *
     * @access private
     * @return string
     */
    private function single_curl()
    {
        $ch = curl_init();
        $request = array_shift($this->requests);
        $options = $this->get_options($request);
        curl_setopt_array($ch, $options);
        $output = curl_exec($ch);
        $info = curl_getinfo($ch);
        if ($this->callback && is_callable($this->callback))
        {
            $callback = $this->callback;
            return call_user_func($callback, $output, $info, $request);
        } else
        {
            return $output;
        }
    }
    /**
     * Performs multiple curl requests
     *
     * @access private
     * @return bool
     */
    private function rolling_curl()
    {
        $n = count($this->requests);
        if ($n < $this->window_size)
        {
            $this->window_size = $n;
        }
        if ($this->window_size < 2)
        {
            return false;
        }
        $master = curl_multi_init();
        // start the first batch of requests
        //注意变量i的作用域不是for循环体内,在后续还是可以使用的
        for($i = 0; $i < $this->window_size; $i++)
        {
            $ch = curl_init();
            $options = $this->get_options($this->requests[$i]);
            curl_setopt_array($ch, $options);
            curl_multi_add_handle($master, $ch);
            $key = (string)$ch;
            $this->requestMap[$key] = $i;
        }
        do
        {
            while (($execrun = curl_multi_exec($master, $running)) == CURLM_CALL_MULTI_PERFORM) ;
            if ($execrun != CURLM_OK)
            {
                break;
            }
            // a request was just completed -- find out which one
            while ($done = curl_multi_info_read($master))
            {
                // get the info and content returned on the request
                $info = curl_getinfo($done['handle']);
                $output = curl_multi_getcontent($done['handle']);
                // send the return values to the callback function.
                $callback = $this->callback;
                if (is_callable($callback))
                {
                    $key = (string)$done['handle'];
                    $request = $this->requests[$this->requestMap[$key]];
                    unset($this->requestMap[$key]);
                    call_user_func($callback, $output, $info, $request);
                }
                // start a new request (it's important to do this before removing the old one)
                $n = count($this->requests);
                if (($i < $n) && isset($this->requests[$i]))
                {
                    $ch = curl_init();
                    $options = $this->get_options($this->requests[$i]);
                    curl_setopt_array($ch, $options);
                    curl_multi_add_handle($master, $ch);
                    // Add to our request Maps
                    $key = (string)$ch;
                    $this->requestMap[$key] = $i;
                    $i++;
                }
                // remove the curl handle that just completed
                curl_multi_remove_handle($master, $done['handle']);
            }
            // Block for data in / output; error handling is done by curl_multi_exec
            if ($running)
            {
                curl_multi_select($master, $this->timeout);
            }
        } while ($running);
        return true;
    }
    /**
     * Helper function to set up a new request by setting the appropriate options
     *
     * @access private
     * @param Request $request
     * @return array
     */
    private function get_options($request)
    {
        $options = $this->__get('options');
        $headers = $this->__get('headers');
        // set the request URL
        $options[CURLOPT_URL] = $request->url;
        // set the request method
        // curl默认就是get,设定post_data,既可认为请求是post请求
        // posting data w/ this request?
        if ($request->post_data)
        {
            $options[CURLOPT_POST] = true;
            $options[CURLOPT_POSTFIELDS] = $request->post_data;
        }
        // append custom options for this specific request
        if ($request->options)
        {
            $options = $options + $request->options;
        }
        // 添加个性header
        if ($request->headers)
        {
            $headers = $headers + $request->headers;
        }
        $options[CURLOPT_HTTPHEADER] = $headers;
        return $options;
    }
    private function createRequest($url, $method, $headers, $options, $data = array())
    {
        $o = new \stdClass();
        $o->url = $url;
        $o->method = $method;
        $o->headers = $headers;
        $o->options = $options;
        $o->post_data = $data;
        if (!isset($options[CURLOPT_USERAGENT]))
        {
            $o->options[CURLOPT_USERAGENT] = self::$agent[array_rand(self::$agent)];
        }
        return $o;
    }
}


2:创建对象

v2-946baf4f01c155bca5bbf8408c2091cc_720w.jpg



attachments-2020-03-9lSLx9Rr5e82dec806e1d.jpg

  • 发表于 2020-03-31 14:11
  • 阅读 ( 701 )
  • 分类:PHP开发

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
Pack
Pack

1135 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1316 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章