• 售前

  • 售后

热门帖子
入门百科

php curl批处置处罚实现可控并发异步操纵示例

[复制链接]
路人52014 显示全部楼层 发表于 2021-10-25 20:14:50 |阅读模式 打印 上一主题 下一主题
本文实例报告了php curl批处理实现可控并发异步操作。分享给各人供各人参考,详细如下:
通常情况下 PHP 中的 cURL 是壅闭运行的,就是说创建一个 cURL 哀求以后必须等它执行乐成大概超时才会执行下一个哀求:API接口访问一样平常会首选CURL
在实际项目大概自己编写小工具(比如消息聚合,商品代价监控,比价)的过程中, 通常必要从第3方网站大概API接口获取数据, 在必要处理1个URL队列时, 为了提高性能, 可以采用cURL提供的
  1. curl_multi_*
复制代码
族函数实现简单的并发.
  1. <?php
  2. include 'curl.class.php';
  3. function callback($response, $info, $error, $request)
  4. {
  5. echo 'response:<br>';
  6. print_r($response);
  7. echo '<br>' . date("Y-m-d H:i:s") . '&nbsp;&nbsp;&nbsp;<br>';
  8. echo '<br>' . str_repeat("-", 100) . '<br>';
  9. }
  10. $USER_COOKIE = (!empty($_REQUEST['cookie'])) ? $_REQUEST['cookie'] : file_get_contents("cookie.txt");
  11. $curl = new Curl ("callback");
  12. $data = array(
  13. array(
  14.   'url' => 'http://dyactive2.vip.xunlei.com/com_sign/?game=qmr&type=rec_gametime&referfrom=&rt=0.42521539455332336', //秦美人
  15.   'method' => 'POST',
  16.   'post_data' => '',
  17.   'header' => null,
  18.   'options' => array(
  19.    CURLOPT_REFERER => "http://niu.xunlei.com/entergame/?gameNo=qmr&fenQuNum=3",
  20.    CURLOPT_COOKIE => $USER_COOKIE,
  21.   )
  22. ),
  23. array(
  24.   'url' => 'http://dyactive2.vip.xunlei.com/com_sign/?game=sq&type=rec_gametime&referfrom=&rt=0.42521539455332336', //神曲
  25.   'method' => 'POST',
  26.   'post_data' => '',
  27.   'header' => null,
  28.   'options' => array(
  29.    CURLOPT_REFERER => "http://niu.xunlei.com/entergame/?gameNo=sq&fenQuNum=41",
  30.    CURLOPT_COOKIE => $USER_COOKIE,
  31.   )
  32. ),
  33. array(
  34.   'url' => 'http://dyactive2.vip.xunlei.com/com_sign/?game=frxz&type=rec_gametime&referfrom=&rt=0.42521539455332336', //凡人修真
  35.   'method' => 'POST',
  36.   'post_data' => '',
  37.   'header' => null,
  38.   'options' => array(
  39.    CURLOPT_REFERER => "http://niu.xunlei.com/entergame/?gameNo=frxz&fenQuNum=3",
  40.    CURLOPT_COOKIE => $USER_COOKIE,
  41.   )
  42. ),
  43. array(
  44.   'url' => 'http://dyactive2.vip.xunlei.com/com_sign/?game=smxj&type=rec_gametime&referfrom=&rt=0.42521539455332336', //神魔仙界
  45.   'method' => 'POST',
  46.   'post_data' => '',
  47.   'header' => null,
  48.   'options' => array(
  49.    CURLOPT_REFERER => "http://niu.xunlei.com/entergame/?gameNo=smxj&fenQuNum=2",
  50.    CURLOPT_COOKIE => $USER_COOKIE,
  51.   )
  52. ),
  53. array(
  54.   'url' => 'http://dyactive2.vip.xunlei.com/com_sign/?game=qsqy&type=rec_gametime&referfrom=&rt=0.42521539455332336', //倾世情缘
  55.   'method' => 'POST',
  56.   'post_data' => '',
  57.   'header' => null,
  58.   'options' => array(
  59.    CURLOPT_REFERER => "http://niu.xunlei.com/entergame/?gameNo=qsqy&fenQuNum=11",
  60.    CURLOPT_COOKIE => $USER_COOKIE,
  61.   )
  62. ),
  63. );
  64. foreach ($data as $val) {
  65. $request = new Curl_request ($val ['url'], $val ['method'], $val ['post_data'], $val ['header'], $val ['options']);
  66. $curl->add($request);
  67. }
  68. $curl->execute();
  69. 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. */
  44. class Curl {
  45. /**
  46.   * 请求url个数
  47.   * @var int
  48.   */
  49. private $size    = 5;
  50. /**
  51.   * 等待所有cURL批处理中的活动连接等待响应时间
  52.   * @var int
  53.   */
  54. private $timeout   = 5;
  55. /**
  56.   * 完成请求回调函数
  57.   * @var string
  58.   */
  59. private $callback   = null;
  60. /**
  61.   * cRUL配置
  62.   * @var array
  63.   */
  64. private $options   = array (CURLOPT_SSL_VERIFYPEER => 0,CURLOPT_RETURNTRANSFER => 1,CURLOPT_CONNECTTIMEOUT => 30 );
  65. /**
  66.   * 请求头
  67.   * @var array
  68.   */
  69. private $headers   = array ();
  70. /**
  71.   * 请求列队
  72.   * @var array
  73.   */
  74. private $requests   = array ();
  75. /**
  76.   * 请求列队索引
  77.   * @var array
  78.   */
  79. private $request_map  = array ();
  80. /**
  81.   * 错误
  82.   * @var array
  83.   */
  84. private $errors   = array ();
  85. /**
  86.   * @access public
  87.   * @param string $callback 回调函数
  88.   * 该函数有4个参数($response,$info,$error,$request)
  89.   * $response url返回的body
  90.   * $info  cURL连接资源句柄的信息
  91.   * $error  错误
  92.   * $request  请求对象
  93.   */
  94. public function __construct($callback = null) {
  95.   $this->callback = $callback;
  96. }
  97. /**
  98.   * 添加一个请求对象到列队
  99.   * @access public
  100.   * @param object $request
  101.   * @return boolean
  102.   */
  103. public function add($request) {
  104.   $this->requests [] = $request;
  105.   return TRUE;
  106. }
  107. /**
  108.   * 创建一个请求对象并添加到列队
  109.   * @access public
  110.   * @param string $url
  111.   * @param string $method
  112.   * @param string $post_data
  113.   * @param string $headers
  114.   * @param array $options
  115.   * @return boolean
  116.   */
  117. public function request($url, $method = 'GET', $post_data = null, $headers = null, $options = null) {
  118.   $this->requests [] = new Curl_request ( $url, $method, $post_data, $headers, $options );
  119.   return TRUE;
  120. }
  121. /**
  122.   * 创建GET请求对象
  123.   * @access public
  124.   * @param string $url
  125.   * @param string $headers
  126.   * @param array $options
  127.   * @return boolean
  128.   */
  129. public function get($url, $headers = null, $options = null) {
  130.   return $this->request ( $url, "GET", null, $headers, $options );
  131. }
  132. /**
  133.   * 创建一个POST请求对象
  134.   * @access public
  135.   * @param string $url
  136.   * @param string $post_data
  137.   * @param string $headers
  138.   * @param array $options
  139.   * @return boolean
  140.   */
  141. public function post($url, $post_data = null, $headers = null, $options = null) {
  142.   return $this->request ( $url, "POST", $post_data, $headers, $options );
  143. }
  144. /**
  145.   * 执行cURL
  146.   * @access public
  147.   * @param int $size 最大连接数
  148.   * @return Ambigous <boolean, mixed>|boolean
  149.   */
  150. public function execute($size = null) {
  151.   if (sizeof ( $this->requests ) == 1) {
  152.    return $this->single_curl ();
  153.   } else {
  154.    return $this->rolling_curl ( $size );
  155.   }
  156. }
  157. /**
  158.   * 单个url请求
  159.   * @access private
  160.   * @return mixed|boolean
  161.   */
  162. private function single_curl() {
  163.   $ch = curl_init ();
  164.   $request = array_shift ( $this->requests );
  165.   $options = $this->get_options ( $request );
  166.   curl_setopt_array ( $ch, $options );
  167.   $output = curl_exec ( $ch );
  168.   $info = curl_getinfo ( $ch );
  169.   // it's not neccesary to set a callback for one-off requests
  170.   if ($this->callback) {
  171.    $callback = $this->callback;
  172.    if (is_callable ( $this->callback )) {
  173.     call_user_func ( $callback, $output, $info, $request );
  174.    }
  175.   } else
  176.    return $output;
  177.   return true;
  178. }
  179. /**
  180.   * 多个url请求
  181.   * @access private
  182.   * @param int $size 最大连接数
  183.   * @return boolean
  184.   */
  185. private function rolling_curl($size = null) {
  186.   if ($size)
  187.    $this->size = $size;
  188.   else
  189.    $this->size = count($this->requests);
  190.   if (sizeof ( $this->requests ) < $this->size)
  191.    $this->size = sizeof ( $this->requests );
  192.   if ($this->size < 2)
  193.    $this->set_error ( 'size must be greater than 1' );
  194.   $master = curl_multi_init ();
  195.   //添加cURL连接资源句柄到map索引
  196.   for($i = 0; $i < $this->size; $i ++) {
  197.    $ch = curl_init ();
  198.    $options = $this->get_options ( $this->requests [$i] );
  199.    curl_setopt_array ( $ch, $options );
  200.    curl_multi_add_handle ( $master, $ch );
  201.    $key = ( string ) $ch;
  202.    $this->request_map [$key] = $i;
  203.   }
  204.   $active = $done = null;
  205.   do {
  206.    while ( ($execrun = curl_multi_exec ( $master, $active )) == CURLM_CALL_MULTI_PERFORM )
  207.     ;
  208.    if ($execrun != CURLM_OK)
  209.     break;
  210.    //有一个请求完成则回调
  211.    while ( $done = curl_multi_info_read ( $master ) ) {
  212.     //$done 完成的请求句柄
  213.     $info = curl_getinfo ( $done ['handle'] );//
  214.     $output = curl_multi_getcontent ( $done ['handle'] );//
  215.     $error = curl_error ( $done ['handle'] );//
  216.     $this->set_error ( $error );
  217.     //调用回调函数,如果存在的话
  218.     $callback = $this->callback;
  219.     if (is_callable ( $callback )) {
  220.      $key = ( string ) $done ['handle'];
  221.      $request = $this->requests [$this->request_map [$key]];
  222.      unset ( $this->request_map [$key] );
  223.      call_user_func ( $callback, $output, $info, $error, $request );
  224.     }
  225.     curl_close ( $done ['handle'] );
  226.     //从列队中移除已经完成的request
  227.     curl_multi_remove_handle ( $master, $done ['handle'] );
  228.    }
  229.    //等待所有cURL批处理中的活动连接
  230.    if ($active)
  231.     curl_multi_select ( $master, $this->timeout );
  232.   } while ( $active );
  233.   //完成关闭
  234.   curl_multi_close ( $master );
  235.   return true;
  236. }
  237. /**
  238.   * 获取没得请求对象的cURL配置
  239.   * @access private
  240.   * @param object $request
  241.   * @return array
  242.   */
  243. private function get_options($request) {
  244.   $options = $this->__get ( 'options' );
  245.   if (ini_get ( 'safe_mode' ) == 'Off' || ! ini_get ( 'safe_mode' )) {
  246.    $options [CURLOPT_FOLLOWLOCATION] = 1;
  247.    $options [CURLOPT_MAXREDIRS] = 5;
  248.   }
  249.   $headers = $this->__get ( 'headers' );
  250.   if ($request->options) {
  251.    $options = $request->options + $options;
  252.   }
  253.   $options [CURLOPT_URL] = $request->url;
  254.   if ($request->post_data && strtolower($request->method) == 'post' ) {
  255.    $options [CURLOPT_POST] = 1;
  256.    $options [CURLOPT_POSTFIELDS] = $request->post_data;
  257.   }
  258.   if ($headers) {
  259.    $options [CURLOPT_HEADER] = 0;
  260.    $options [CURLOPT_HTTPHEADER] = $headers;
  261.   }
  262.   return $options;
  263. }
  264. /**
  265.   * 设置错误信息
  266.   * @access public
  267.   * @param string $msg
  268.   */
  269. public function set_error($msg) {
  270.   if (! empty ( $msg ))
  271.    $this->errors [] = $msg;
  272. }
  273. /**
  274.   * 获取错误信息
  275.   * @access public
  276.   * @param string $open
  277.   * @param string $close
  278.   * @return string
  279.   */
  280. public function display_errors($open = '<p>', $close = '</p>') {
  281.   $str = '';
  282.   foreach ( $this->errors as $val ) {
  283.    $str .= $open . $val . $close;
  284.   }
  285.   return $str;
  286. }
  287. /**
  288.   * @access public
  289.   * @param string $name
  290.   * @param string $value
  291.   * @return boolean
  292.   */
  293. public function __set($name, $value) {
  294.   if ($name == 'options' || $name == 'headers') {
  295.    $this->{$name} = $value + $this->{$name};
  296.   } else {
  297.    $this->{$name} = $value;
  298.   }
  299.   return TRUE;
  300. }
  301. /**
  302.   *
  303.   * @param string $name
  304.   * @return mixed
  305.   * @access public
  306.   */
  307. public function __get($name) {
  308.   return (isset ( $this->{$name} )) ? $this->{$name} : null;
  309. }
  310. /**
  311.   * @return void
  312.   * @access public
  313.   */
  314. public function __destruct() {
  315.   unset ( $this->size, $this->timeout, $this->callback, $this->options, $this->headers, $this->requests, $this->request_map, $this->errors );
  316. }
  317. }
  318. // END Curl Class
  319. /* End of file curl.class.php */
复制代码
更多关于PHP相干内容感爱好的读者可查看本站专题:《php curl用法总结》、《PHP网络编程本领总结》、《PHP数组(Array)操作本领大全》、《php字符串(string)用法总结》、《PHP数据结构与算法教程》、《php步调计划算法总结》、《PHP运算与运算符用法总结》及《php常见数据库操作本领汇总》
盼望本文所述对各人PHP步调计划有所帮助。

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作