You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PHP cURL multi执行过程中实时处理返回结果?

在PHP cURL Multi循环中实时处理请求结果

完全可以在下载循环中实时处理返回结果,这确实能更早释放cURL句柄、减少资源占用,还能让爬虫的并发效率更稳定——不用等所有请求都结束再批量处理。

你提到的curl_multi_select确实不会直接返回哪个请求完成,但可以配合curl_multi_info_read()来获取所有已完成的请求状态,从而实现实时处理。下面是修改后的核心代码,替换你原来的下载循环和结果收集部分:

<?php
$remainingTargets = ...;
$concurrency = 30;

$multiHandle = curl_multi_init();
$targets = [];
// 初始化第一批请求
while (count($targets) < $concurrency && count($remainingTargets) > 0) {
  $target = array_shift($remainingTargets);
  $alreadyChecked = ...;
  if ($alreadyChecked !== false) {
    continue;
  }
  $curl = curl_init($target);
  curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36');
  curl_setopt($curl, CURLOPT_FAILONERROR, true);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 4);
  curl_setopt($curl, CURLOPT_TIMEOUT, 5);
  curl_multi_add_handle($multiHandle, $curl);
  // 新增:用句柄作为键,方便反向查找目标
  $targets[(int)$curl] = $target;
}

// 改进后的下载循环:实时处理完成的请求
$running = null;
do {
  // 等待活动连接,避免空循环占用CPU
  curl_multi_select($multiHandle);
  // 执行当前的cURL批处理
  curl_multi_exec($multiHandle, $running);
  
  // 循环读取所有已完成的请求信息
  while ($info = curl_multi_info_read($multiHandle)) {
    $curl = $info['handle'];
    $target = $targets[(int)$curl];
    
    if ($info['result'] === CURLE_OK) {
      // 成功获取内容,实时处理
      $html = curl_multi_getcontent($curl);
      // 这里直接处理页面:解析链接、存储数据等
      // Process this page
    } else {
      // 处理请求失败的情况,比如记录错误日志
      $error = curl_error($curl);
      // Handle error
    }
    
    // 立即释放资源
    curl_multi_remove_handle($multiHandle, $curl);
    curl_close($curl);
    unset($targets[(int)$curl]);
    
    // 补充新的请求,维持并发数
    if (count($remainingTargets) > 0) {
      $newTarget = array_shift($remainingTargets);
      $alreadyChecked = ...;
      if ($alreadyChecked === false) {
        $newCurl = curl_init($newTarget);
        // 复用之前的curl配置
        curl_setopt($newCurl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36');
        curl_setopt($newCurl, CURLOPT_FAILONERROR, true);
        curl_setopt($newCurl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($newCurl, CURLOPT_CONNECTTIMEOUT, 4);
        curl_setopt($newCurl, CURLOPT_TIMEOUT, 5);
        curl_multi_add_handle($multiHandle, $newCurl);
        $targets[(int)$newCurl] = $newTarget;
      }
    }
  }
} while ($running > 0 || count($targets) > 0);

curl_multi_close($multiHandle);

关键改进点:

  • 用句柄作为$targets数组的键:方便根据返回的句柄快速找到对应的请求目标,避免遍历查找
  • curl_multi_select:等待cURL批处理中有活动状态变化,避免无意义的空循环,降低CPU占用
  • curl_multi_info_read:循环取出所有已完成的请求,不管是成功还是失败,都能实时处理
  • 即时释放资源:处理完一个请求就立即移除句柄并关闭,不用等到所有请求结束
  • 维持并发数:每释放一个句柄,就从剩余目标中补充新的请求,保持设定的并发量(30)

这样修改后,爬虫的资源利用率会更高,尤其是在处理大量请求时,能更快释放内存和连接资源,避免长时间占用过多句柄。

内容的提问来源于stack exchange,提问作者William Entriken

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 00:10:47