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

PHP中使用curl_multi_exec跟随跳转时能否获取源URL?

解决curl_multi_exec跟随跳转时获取原始URL的问题

嘿,我之前做批量链接有效性检测脚本的时候,刚好碰到过一模一样的问题——开启自动跳转后,很容易搞混哪个检测结果对应最初的原始URL。给你分享两个实用的解决方案:

方案1:给每个CURL Handle绑定原始URL(最推荐)

因为curl_multi是基于多个独立的easy handle并行执行的,我们可以直接把原始URL绑定到对应的handle上,这样不管URL跳转多少次,都能轻松把结果关联回最初的目标链接。

以PHP为例(其他语言逻辑完全相通):

// 初始化multi句柄
$mh = curl_multi_init();
$handles = [];

// 待检测的原始链接列表
$originalUrls = [
    'https://example.com/old-redirect-link', // 会触发3xx跳转的URL
    'https://example.com/valid-direct-link'
];

foreach ($originalUrls as $url) {
    $ch = curl_init($url);
    // 开启自动跟随跳转
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    // 设置最大跳转次数,避免循环跳转卡死脚本
    curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
    // 只获取状态码,不下载响应内容,提升效率
    curl_setopt($ch, CURLOPT_NOBODY, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
    // 关键操作:把原始URL绑定到当前handle的私有字段
    curl_setopt($ch, CURLOPT_PRIVATE, $url);
    
    curl_multi_add_handle($mh, $ch);
    $handles[] = $ch;
}

// 执行异步请求
$running = null;
do {
    curl_multi_exec($mh, $running);
    curl_multi_select($mh);
} while ($running > 0);

// 处理检测结果
foreach ($handles as $ch) {
    // 取出绑定的原始URL
    $originalUrl = curl_getinfo($ch, CURLINFO_PRIVATE);
    // 获取最终跳转后的HTTP状态码
    $finalStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    // 获取最终跳转后的目标URL(可选)
    $finalUrl = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
    
    echo "原始URL: {$originalUrl} | 最终状态码: {$finalStatusCode} | 最终跳转URL: {$finalUrl}\n";
    
    curl_multi_remove_handle($mh, $ch);
    curl_close($ch);
}

curl_multi_close($mh);

方案2:自定义Header函数记录完整跳转轨迹

如果需要追踪每一步的跳转细节(比如中间经过的所有URL和对应的状态码),可以通过CURLOPT_HEADERFUNCTION捕获每个跳转的响应头,再结合绑定的原始URL做关联:

foreach ($originalUrls as $url) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
    curl_setopt($ch, CURLOPT_NOBODY, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_PRIVATE, $url);
    
    // 自定义Header回调函数,捕获每一次跳转的Location头
    $redirectSteps = [];
    curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($ch, $header) use (&$redirectSteps) {
        if (preg_match('/^Location:\s*(.*)$/i', $header, $matches)) {
            $redirectSteps[] = trim($matches[1]);
        }
        return strlen($header);
    });
    
    curl_multi_add_handle($mh, $ch);
    // 把跳转轨迹和handle关联,方便后续读取
    $handleMeta[spl_object_hash($ch)] = [
        'original' => $url,
        'redirects' => &$redirectSteps
    ];
}

// 执行完成后,就能拿到每个原始URL的完整跳转路径

关键注意事项

  • 务必设置CURLOPT_MAXREDIRS,防止遇到循环跳转导致脚本无限挂起
  • 如果检测HTTPS链接,根据场景调整CURLOPT_SSL_VERIFYPEER和CURLOPT_SSL_VERIFYHOST(比如测试环境可以临时关闭证书验证)
  • 异步执行时,确保每个handle的关联数据(私有字段或外部数组)对应准确,不要搞混顺序

内容的提问来源于stack exchange,提问作者Frank M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:36:00