如何获取含JS重定向在内的多种重定向后的最终URL?
问题
我需要从罗马尼亚比价网站Pricy.ro获取商品的最终跳转URL。示例页面URL为https://www.pricy.ro/extensionhtml?url=https://www.emag.ro/telefon-mobil-apple-iphone-12-128gb-5g-black-mgja3rm-a/pd/DZDJ27MBM/,已经从页面HTML中解析出各店铺的跳转URL数组:
$shops = [ ['shop' => 'emag', 'url' => 'https://www.pricy.ro/red/r/?shopProductId=60e6d3aec716012740f624a6&source=AlternativeProducts'], ['shop' => 'altex', 'url' => 'https://www.pricy.ro/red/r/?shopProductId=60ca3252c0486fc28847794b&source=AlternativeProducts'], ['shop' => 'mediagalaxy', 'url' => 'https://www.pricy.ro/red/r/?shopProductId=60cb38efc0486fc2884ba1a1&source=AlternativeProducts'], ['shop' => 'flanco', 'url' => 'https://www.pricy.ro/red/r/?shopProductId=60c9ca58c0486fc288336be3&source=AlternativeProducts'], ['shop' => 'evomag', 'url' => 'https://www.pricy.ro/red/r/?shopProductId=60a8f6e0a771b2fb18843424&source=AlternativeProducts'], ['shop' => 'pcgarage', 'url' => 'https://www.pricy.ro/red/r/?shopProductId=60a8f6e0a771b2fb18843424&source=AlternativeProducts'], ];
我用PHP的curl编写了获取最终URL的函数,但只有一个店铺的URL能成功解析,其余都返回https://www.pricy.ro/。显然curl无法处理该网站的JavaScript重定向,想找不需要curl、正则的方案,比如无头浏览器?另外我的场景里200状态码不代表已经到达最终目标URL。
解决方案
用无头浏览器模拟真实环境
curl只能处理HTTP响应头里的重定向,而Pricy.ro的跳转大概率依赖前端JavaScript计算跳转逻辑(比如延迟跳转、动态生成目标URL),这种情况下必须用无头浏览器模拟真实用户的浏览器行为,才能正确追踪到最终跳转URL。
推荐使用PHP生态里的chrome-php/chrome库,它可以直接调用Chrome/Chromium无头模式来处理页面加载和跳转。
步骤1:安装依赖
通过Composer安装库:
composer require chrome-php/chrome
步骤2:编写获取最终URL的函数
use HeadlessChromium\BrowserFactory; function getFinalRedirectUrl(string $startUrl, int $timeout = 15): string { $browserFactory = new BrowserFactory(); // 启动无头浏览器 $browser = $browserFactory->createBrowser([ 'headless' => true, 'timeout' => $timeout * 1000, // 毫秒 'userAgent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36' ]); try { $page = $browser->createPage(); // 导航到起始URL,等待页面加载完成(包括JS执行) $page->navigate($startUrl)->waitForNavigation([ 'waitUntil' => 'networkIdle0', // 等待网络请求全部完成 'timeout' => $timeout * 1000 ]); // 检查当前URL,如果还是Pricy的域名,可能需要等待JS跳转 $currentUrl = $page->getCurrentUrl(); $maxWaitAttempts = 5; $attempt = 0; while (str_contains($currentUrl, 'pricy.ro') && $attempt < $maxWaitAttempts) { usleep(1000000); // 等待1秒 $currentUrl = $page->getCurrentUrl(); $attempt++; } return $currentUrl; } finally { // 关闭浏览器 $browser->close(); } } // 遍历店铺数组获取最终URL foreach ($shops as $shop) { echo "Shop: {$shop['shop']} URL: " . getFinalRedirectUrl($shop['url']) . "<br/>"; }
关键说明
networkIdle0等待策略:确保页面所有网络请求都完成,JS执行完毕,避免提前获取未跳转的URL。- 循环等待逻辑:针对可能的延迟JS跳转,最多等待5次(共5秒),确保追踪到最终目标URL。
- 真实User-Agent:模拟主流浏览器请求,避免被网站反爬机制拦截。
内容的提问来源于stack exchange,提问作者m3tsys
相关产品推荐
相关产品推荐

