php多线程抓取网页(php手册中语焉不详的curl_multi一族的函数头疼不已)
优采云 发布时间: 2021-12-21 00:26php多线程抓取网页(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系列函数而头疼。他们的文件较少,而且他们提供...