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
相关产品推荐
相关产品推荐

