php多线程抓取网页(php手册中语焉不详的curl_multi一族的函数头疼不已)

优采云 发布时间: 2021-12-21 00:26

  php多线程抓取网页(php手册中语焉不详的curl_multi一族的函数头疼不已)

  让我向您介绍 Curl 多线程示例和原理。请指教

  相信很多人都为php手册中含糊不清的curl_multi系列函数而头疼。它们的文档较少,并且给出的示例很容易让您学习。我也搜索了很多网页,都没有看到一个完整的应用实例。

  curl_multi_add_handle

  curl_multi_close

  curl_multi_exec

  curl_multi_getcontent

  curl_multi_info_read

  curl_multi_init

  curl_multi_remove_handle

  curl_multi_select

  一般来说,在考虑使用这些函数时,目的显然应该是同时请求多个URL,而不是一个一个,否则最好在循环中调整curl_exec。

  步骤总结如下:

  第一步:调用 curl_multi_init

  第二步:循环调用 curl_multi_add_handle

  这一步需要注意的是curl_multi_add_handle的第二个参数是curl_init的子句柄。

  第三步:继续调用curl_multi_exec

  第四步:根据需要调用 curl_multi_getcontent 循环获取结果

  第五步:调用curl_multi_remove_handle,对每个字句柄调用curl_close

  第 6 步:调用 curl_multi_close

  这是 PHP 手册中的一个示例:

  复制代码代码如下:

  整个使用过程差不多就是这样,但是这段简单的代码有个致命的弱点,就是在do循环部分,在整个URL请求过程中都是无限循环,容易造成CPU占用100%。

  现在让我们改进它。这里我们需要使用一个几乎没有文档的函数 curl_multi_select。虽然C的curl库有select的说明,但是PHP中的界面和用法确实和C中的有所不同。

  将上面的段落更改为以下内容:

  复制代码代码如下:

  做 {

  $mrc = curl_multi_exec($mh,$active);

  } while ($mrc == CURLM_CALL_MULTI_PERFORM);

  而($active 和 $mrc == CURLM_OK){

  如果 (curl_multi_select($mh) != -1) {

  做 {

  $mrc = curl_multi_exec($mh, $active);

  } while ($mrc == CURLM_CALL_MULTI_PERFORM);

  }

  }

  因为$active要等到所有url数据都被接受后才会变为false,所以这里用curl_multi_exec的返回值来判断是否有数据。有数据时,会不断调用 curl_multi_exec。如果没有数据,则进入选择阶段。新数据可以唤醒继续执行。这里的优点是没有不必要的 CPU 消耗。

  另外:还有一些细节有时可能会遇到:

  要控制每个请求的超时时间,请在 curl_multi_add_handle 之前通过 curl_setopt 进行:

  curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);

  判断是否超时或其他错误,使用 curl_error($conn[$i]); 在 curl_multi_getcontent 之前;

  该类别的特点:

  运行非常稳定。

  设置并发将始终使用此并发数,即使通过回调函数添加任务也是如此。

  CPU占用率极低,大部分CPU消耗在用户的回调函数中。

  内存利用率高,任务量大(15W任务会占用256M以上内存)。可以使用回调函数添加任务,任务数量可以自定义。

  可以最大限度地占用带宽。

  链式任务,例如需要多个不同地址采集的数据的任务,可以通过回调一次完成。

  能够对CURL错误进行多次尝试,次数自行决定(大并发初期容易产生CURL错误,网络条件或者对方服务器的稳定性也可能导致CURL错误)。

  回调函数相当灵活,可以同时执行多种类型的任务(比如下载文件、抓取网页、分析404可以在一个PHP进程中同时执行)。

  自定义任务类型非常容易,比如检查404,获取重定向的最后一个URL等。

  您可以设置缓存来挑战产品纪律。

  不足的:

  不能充分利用多核CPU(可以开多个进程解决,需要自己处理任务划分等逻辑)。

  最大并发数为 500(或 512?)。经过测试,是CURL的内部限制。如果超过最大并发,总是返回失败。

  目前没有可恢复的传递函数。

  目前任务是原子的,一个大文件不能分成几个部分开线程下载。

  trueTechArticle 向您介绍了 Curl 多线程示例和原理。有什么问题,请指教。相信很多人都为php手册中含糊不清的curl_multi系列函数而头疼。他们的文件较少,而且他们提供...

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线