当前位置:首页 > PHP教程 > php高级应用 > 列表

php curl批处理实现可控并发异步操作示例

发布:smiling 来源: PHP粉丝网  添加日期:2021-09-17 09:54:44 浏览: 评论:0 

这篇文章主要介绍了php curl批处理实现可控并发异步操作,结合实例形式分析了php使用curl的curl_multi_*族函数进行并发操作相关实现技巧,需要的朋友可以参考下

本文实例讲述了php curl批处理实现可控并发异步操作,分享给大家供大家参考,具体如下:

通常情况下 PHP 中的 cURL 是阻塞运行的,就是说创建一个 cURL 请求以后必须等它执行成功或者超时才会执行下一个请求:API接口访问一般会首选CURL

在实际项目或者自己编写小工具(比如新闻聚合,商品价格监控,比价)的过程中, 通常需要从第3方网站或者API接口获取数据, 在需要处理1个URL队列时, 为了提高性能, 可以采用cURL提供的curl_multi_*族函数实现简单的并发.

  1. <?php 
  2. include 'curl.class.php'
  3. function callback($response$info$error$request
  4.  echo 'response:<br>'
  5.  print_r($response); 
  6.  echo '<br>' . date("Y-m-d H:i:s") . '&nbsp;&nbsp;&nbsp;<br>'
  7.  echo '<br>' . str_repeat("-", 100) . '<br>'
  8. $USER_COOKIE = (!emptyempty($_REQUEST['cookie'])) ? $_REQUEST['cookie'] : file_get_contents("cookie.txt"); 
  9. $curl = new Curl ("callback"); 
  10. $data = array
  11.  array
  12.   'url' => 'http://dyactive2.vip.xunlei.com/com_sign/?game=qmr&type=rec_gametime&referfrom=&rt=0.42521539455332336', //秦美人 
  13.   'method' => 'POST'
  14.   'post_data' => ''
  15.   'header' => null, 
  16.   'options' => array
  17.    CURLOPT_REFERER => "http://niu.xunlei.com/entergame/?gameNo=qmr&fenQuNum=3"
  18.    CURLOPT_COOKIE => $USER_COOKIE
  19.   ) 
  20.  ), 
  21.  array
  22.   'url' => 'http://dyactive2.vip.xunlei.com/com_sign/?game=sq&type=rec_gametime&referfrom=&rt=0.42521539455332336', //神曲 
  23.   'method' => 'POST'
  24.   'post_data' => ''
  25.   'header' => null, 
  26.   'options' => array
  27.    CURLOPT_REFERER => "http://niu.xunlei.com/entergame/?gameNo=sq&fenQuNum=41"
  28.    CURLOPT_COOKIE => $USER_COOKIE
  29.   ) 
  30.  ), 
  31.  array
  32.   'url' => 'http://dyactive2.vip.xunlei.com/com_sign/?game=frxz&type=rec_gametime&referfrom=&rt=0.42521539455332336', //凡人修真 
  33.   'method' => 'POST'
  34.   'post_data' => ''
  35.   'header' => null, 
  36.   'options' => array
  37.    CURLOPT_REFERER => "http://niu.xunlei.com/entergame/?gameNo=frxz&fenQuNum=3"
  38.    CURLOPT_COOKIE => $USER_COOKIE
  39.   ) 
  40.  ), 
  41.  array
  42.   'url' => 'http://dyactive2.vip.xunlei.com/com_sign/?game=smxj&type=rec_gametime&referfrom=&rt=0.42521539455332336', //神魔仙界 
  43.   'method' => 'POST'
  44.   'post_data' => ''
  45.   'header' => null, 
  46.   'options' => array
  47.    CURLOPT_REFERER => "http://niu.xunlei.com/entergame/?gameNo=smxj&fenQuNum=2"
  48.    CURLOPT_COOKIE => $USER_COOKIE
  49.   ) 
  50.  ), 
  51.  array
  52.   'url' => 'http://dyactive2.vip.xunlei.com/com_sign/?game=qsqy&type=rec_gametime&referfrom=&rt=0.42521539455332336', //倾世情缘 
  53.   'method' => 'POST'
  54.   'post_data' => ''
  55.   'header' => null, 
  56.   'options' => array
  57.    CURLOPT_REFERER => "http://niu.xunlei.com/entergame/?gameNo=qsqy&fenQuNum=11"
  58.    CURLOPT_COOKIE => $USER_COOKIE
  59.   ) 
  60.  ), 
  61. ); 
  62. foreach ($data as $val) { 
  63.  $request = new Curl_request ($val ['url'], $val ['method'], $val ['post_data'], $val ['header'], $val ['options']); 
  64.  $curl->add($request); 
  65. $curl->execute(); 
  66. echo $curl->display_errors(); 

使用下来效果很好,没有副作用,并发数可控,应用之处多多,自己发挥想象吧

  1. <?php 
  2. /** 
  3.  * cURL批量处理 工具类 
  4.  *  
  5.  * @since Version 1.0 
  6.  * @author Justmepzy <justmepzy@gmail.com> 
  7.  * @link http://t.qq.com/JustPzy 
  8.  */ 
  9. /** 
  10.  *单一的请求对象 
  11.  */ 
  12. class Curl_request { 
  13.  public $url   = ''
  14.  public $method   = 'GET'
  15.  public $post_data  = null; 
  16.  public $headers  = null; 
  17.  public $options  = null; 
  18.  /** 
  19.   *  
  20.   * @param string $url 
  21.   * @param string $method 
  22.   * @param string $post_data 
  23.   * @param string $headers 
  24.   * @param array $options 
  25.   * @return void 
  26.   */ 
  27.  public function __construct($url$method = 'GET'$post_data = null, $headers = null, $options = null) { 
  28.   $this->url = $url
  29.   $this->method = strtoupper$method ); 
  30.   $this->post_data = $post_data
  31.   $this->headers = $headers
  32.   $this->options = $options
  33.  } 
  34.  /** 
  35.   * @return void 
  36.   */ 
  37.  public function __destruct() { 
  38.   unset ( $this->url, $this->method, $this->post_data, $this->headers, $this->options ); 
  39.  } 
  40. /** 
  41.  * 包含请求列队处理 
  42.  */ 
  43. class Curl { 
  44.  /** 
  45.   * 请求url个数 
  46.   * @var int 
  47.   */ 
  48.  private $size    = 5; 
  49.  /** 
  50.   * 等待所有cURL批处理中的活动连接等待响应时间 
  51.   * @var int 
  52.   */ 
  53.  private $timeout   = 5; 
  54.  /** 
  55.   * 完成请求回调函数 
  56.   * @var string 
  57.   */ 
  58.  private $callback   = null; 
  59.  /** 
  60.   * cRUL配置 
  61.   * @var array 
  62.   */ 
  63.  private $options   = array (CURLOPT_SSL_VERIFYPEER => 0,CURLOPT_RETURNTRANSFER => 1,CURLOPT_CONNECTTIMEOUT => 30 ); 
  64.  /** 
  65.   * 请求头 
  66.   * @var array 
  67.   */ 
  68.  private $headers   = array (); 
  69.  /** 
  70.   * 请求列队 
  71.   * @var array 
  72.   */ 
  73.  private $requests   = array (); 
  74.  /** 
  75.   * 请求列队索引 
  76.   * @var array 
  77.   */ 
  78.  private $request_map  = array (); 
  79.  /** 
  80.   * 错误 
  81.   * @var array 
  82.   */ 
  83.  private $errors   = array (); 
  84.  /** 
  85.   * @access public 
  86.   * @param string $callback 回调函数 
  87.   * 该函数有4个参数($response,$info,$error,$request) 
  88.   * $response url返回的body 
  89.   * $info  cURL连接资源句柄的信息 
  90.   * $error  错误 
  91.   * $request  请求对象 
  92.   */ 
  93.  public function __construct($callback = null) { 
  94.   $this->callback = $callback
  95.  } 
  96.  /** 
  97.   * 添加一个请求对象到列队 
  98.   * @access public 
  99.   * @param object $request 
  100.   * @return boolean 
  101.   */ 
  102.  public function add($request) { 
  103.   $this->requests [] = $request
  104.   return TRUE; 
  105.  } 
  106.  /** 
  107.   * 创建一个请求对象并添加到列队 
  108.   * @access public 
  109.   * @param string $url 
  110.   * @param string $method 
  111.   * @param string $post_data 
  112.   * @param string $headers 
  113.   * @param array $options 
  114.   * @return boolean 
  115.   */ 
  116.  public function request($url$method = 'GET'$post_data = null, $headers = null, $options = null) { 
  117.   $this->requests [] = new Curl_request ( $url$method$post_data$headers$options ); 
  118.   return TRUE; 
  119.  } 
  120.  /** 
  121.   * 创建GET请求对象 
  122.   * @access public 
  123.   * @param string $url 
  124.   * @param string $headers 
  125.   * @param array $options 
  126.   * @return boolean 
  127.   */ 
  128.  public function get($url$headers = null, $options = null) { 
  129.   return $this->request ( $url"GET", null, $headers$options ); 
  130.  } 
  131.  /** 
  132.   * 创建一个POST请求对象 
  133.   * @access public 
  134.   * @param string $url 
  135.   * @param string $post_data 
  136.   * @param string $headers 
  137.   * @param array $options 
  138.   * @return boolean 
  139.   */ 
  140.  public function post($url$post_data = null, $headers = null, $options = null) { 
  141.   return $this->request ( $url"POST"$post_data$headers$options ); 
  142.  } 
  143.  /** 
  144.   * 执行cURL 
  145.   * @access public 
  146.   * @param int $size 最大连接数 
  147.   * @return Ambigous <boolean, mixed>|boolean 
  148.   */ 
  149.  public function execute($size = null) { 
  150.   if (sizeof ( $this->requests ) == 1) { 
  151.    return $this->single_curl (); 
  152.   } else { 
  153.    return $this->rolling_curl ( $size ); 
  154.   } 
  155.  } 
  156.  /** 
  157.   * 单个url请求 
  158.   * @access private 
  159.   * @return mixed|boolean 
  160.   */ 
  161.  private function single_curl() { 
  162.   $ch = curl_init (); 
  163.   $request = array_shift ( $this->requests ); 
  164.   $options = $this->get_options ( $request ); 
  165.   curl_setopt_array ( $ch$options ); 
  166.   $output = curl_exec ( $ch ); 
  167.   $info = curl_getinfo ( $ch ); 
  168.   // it's not neccesary to set a callback for one-off requests 
  169.   if ($this->callback) { 
  170.    $callback = $this->callback; 
  171.    if (is_callable ( $this->callback )) { 
  172.     call_user_func ( $callback$output$info$request ); 
  173.    } 
  174.   } else 
  175.    return $output
  176.   return true; 
  177.  } 
  178.  /** 
  179.   * 多个url请求 
  180.   * @access private 
  181.   * @param int $size 最大连接数 
  182.   * @return boolean 
  183.   */ 
  184.  private function rolling_curl($size = null) { 
  185.   if ($size
  186.    $this->size = $size
  187.   else 
  188.    $this->size = count($this->requests); 
  189.   if (sizeof ( $this->requests ) < $this->size) 
  190.    $this->size = sizeof ( $this->requests ); 
  191.   if ($this->size < 2) 
  192.    $this->set_error ( 'size must be greater than 1' ); 
  193.   $master = curl_multi_init (); 
  194.   //添加cURL连接资源句柄到map索引 
  195.   for($i = 0; $i < $this->size; $i ++) { 
  196.    $ch = curl_init (); 
  197.    $options = $this->get_options ( $this->requests [$i] ); 
  198.    curl_setopt_array ( $ch$options ); 
  199.    curl_multi_add_handle ( $master$ch ); 
  200.    $key = ( string ) $ch
  201.    $this->request_map [$key] = $i
  202.   } 
  203.   $active = $done = null; 
  204.   do { 
  205.    while ( ($execrun = curl_multi_exec ( $master$active )) == CURLM_CALL_MULTI_PERFORM ) 
  206.     ; 
  207.    if ($execrun != CURLM_OK) 
  208.     break
  209.    //有一个请求完成则回调 
  210.    while ( $done = curl_multi_info_read ( $master ) ) { 
  211.     //$done 完成的请求句柄 
  212.     $info = curl_getinfo ( $done ['handle'] );// 
  213.     $output = curl_multi_getcontent ( $done ['handle'] );// 
  214.     $error = curl_error ( $done ['handle'] );// 
  215.     $this->set_error ( $error ); 
  216.     //调用回调函数,如果存在的话 
  217.     $callback = $this->callback; 
  218.     if (is_callable ( $callback )) { 
  219.      $key = ( string ) $done ['handle']; 
  220.      $request = $this->requests [$this->request_map [$key]]; 
  221.      unset ( $this->request_map [$key] ); 
  222.      call_user_func ( $callback$output$info$error$request ); 
  223.     } 
  224.     curl_close ( $done ['handle'] ); 
  225.     //从列队中移除已经完成的request 
  226.     curl_multi_remove_handle ( $master$done ['handle'] ); 
  227.    } 
  228.    //等待所有cURL批处理中的活动连接 
  229.    if ($active
  230.     curl_multi_select ( $master$this->timeout ); 
  231.   } while ( $active ); 
  232.   //完成关闭 
  233.   curl_multi_close ( $master ); 
  234.   return true; 
  235.  } 
  236.  /** 
  237.   * 获取没得请求对象的cURL配置 
  238.   * @access private 
  239.   * @param object $request 
  240.   * @return array 
  241.   */ 
  242.  private function get_options($request) { 
  243.   $options = $this->__get ( 'options' ); 
  244.   if (ini_get ( 'safe_mode' ) == 'Off' || ! ini_get ( 'safe_mode' )) { 
  245.    $options [CURLOPT_FOLLOWLOCATION] = 1; 
  246.    $options [CURLOPT_MAXREDIRS] = 5; 
  247.   } 
  248.   $headers = $this->__get ( 'headers' ); 
  249.   if ($request->options) { 
  250.    $options = $request->options + $options
  251.   } 
  252.   $options [CURLOPT_URL] = $request->url; 
  253.   if ($request->post_data && strtolower($request->method) == 'post' ) { 
  254.    $options [CURLOPT_POST] = 1; 
  255.    $options [CURLOPT_POSTFIELDS] = $request->post_data; 
  256.   } 
  257.   if ($headers) { 
  258.    $options [CURLOPT_HEADER] = 0; 
  259.    $options [CURLOPT_HTTPHEADER] = $headers
  260.   } 
  261.   return $options
  262.  } 
  263.  /** 
  264.   * 设置错误信息 
  265.   * @access public 
  266.   * @param string $msg 
  267.   */ 
  268.  public function set_error($msg) { 
  269.   if (! emptyempty ( $msg )) 
  270.    $this->errors [] = $msg
  271.  } 
  272.  /** 
  273.   * 获取错误信息 
  274.   * @access public 
  275.   * @param string $open 
  276.   * @param string $close 
  277.   * @return string 
  278.   */ 
  279.  public function display_errors($open = '<p>'$close = '</p>') { 
  280.   $str = ''
  281.   foreach ( $this->errors as $val ) { 
  282.    $str .= $open . $val . $close
  283.   } 
  284.   return $str
  285.  } 
  286.  /** 
  287.   * @access public 
  288.   * @param string $name 
  289.   * @param string $value 
  290.   * @return boolean 
  291.   */ 
  292.  public function __set($name$value) { 
  293.   if ($name == 'options' || $name == 'headers') { 
  294.    $this->{$name} = $value + $this->{$name}; 
  295.   } else { 
  296.    $this->{$name} = $value
  297.   } 
  298.   return TRUE; 
  299.  } 
  300.  /** 
  301.   *  
  302.   * @param string $name 
  303.   * @return mixed 
  304.   * @access public 
  305.   */ 
  306.  public function __get($name) { 
  307.   return (isset ( $this->{$name} )) ? $this->{$name} : null; 
  308.  } 
  309.  /** 
  310.   * @return void 
  311.   * @access public 
  312.   */ 
  313.  public function __destruct() { 
  314.   unset ( $this->size, $this->timeout, $this->callback, $this->options, $this->headers, $this->requests, $this->request_map, $this->errors ); 
  315.  } 
  316. // END Curl Class 
  317. /* End of file curl.class.php */

Tags: curl批处理 php并发异步

分享到: