关于使用cURL获取TikTok帖子最终URL及追踪重定向路径的技术求助
我想用cURL请求TikTok的帖子短链接,追踪跳转过程中所有经过的地址,但测试示例链接 https://vm.tiktok.com/ZMeh1yKUQ/ 时,当前代码只返回了 https://m.tiktok.com/v/6841927751578946822.html,而不是浏览器里显示的最终目标 https://www.tiktok.com/@ibruno_maciel/video/6841927751578946822。希望能得到解决这个问题的建议。
当前使用的PHP代码
function getWebPage($url, $redirectcallback = null){ $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_NOBODY, false); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1) Gecko/20061024 BonEcho/2.0"); $html = curl_exec($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($http_code == 301 || $http_code == 302) { list($httpheader) = explode("\r\n\r\n", $html, 2); $matches = array(); preg_match('/(Location:|URI:)(.*?)\n/', $httpheader, $matches); $nurl = trim(array_pop($matches)); $url_parsed = parse_url($nurl); if (isset($url_parsed)) { if($redirectcallback){ // callback $redirectcallback($nurl, $url); } $html = getWebPage($nurl, $redirectcallback); } } return $html; } function trackAllLocations($newUrl, $currentUrl){ echo $currentUrl.' ---> '.$newUrl."\r\n"; } getWebPage('https://vm.tiktok.com/ZMeh1yKUQ/', 'trackAllLocations');
解决方案建议
TikTok的短链接跳转逻辑混合了HTTP 3xx重定向和JavaScript客户端跳转,你的当前代码只处理了HTTP层面的重定向,所以没拿到最终的用户主页链接。这里有几个调整方向:
1. 升级User-Agent,模拟现代浏览器
你当前使用的User-Agent是非常老旧的Firefox版本,TikTok会根据UA返回不同的内容(比如给旧UA返回m端页面,而给现代UA返回完整的web端页面)。替换成最新的Chrome或Firefox UA:
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36");
2. 处理JavaScript跳转
当你拿到https://m.tiktok.com/v/6841927751578946822.html这个页面时,它的HTML里会包含JS跳转代码,比如window.location.href = 'https://www.tiktok.com/@ibruno_maciel/video/6841927751578946822'。你需要解析这段内容提取目标URL:
// 在getWebPage函数中,当没有HTTP重定向时,检查页面中的JS跳转 if ($http_code == 200) { // 提取JS中的跳转URL preg_match('/window\.location\.href\s*=\s*[\'"](.*?)[\'"]/', $html, $js_matches); if (!empty($js_matches[1])) { $js_redirect_url = trim($js_matches[1]); if($redirectcallback){ $redirectcallback($js_redirect_url, $url); } $html = getWebPage($js_redirect_url, $redirectcallback); } }
3. 使用cURL内置的重定向追踪(更可靠)
手动解析Header中的Location字段容易出错,cURL提供了CURLINFO_REDIRECT_URL来直接获取重定向地址,同时可以开启CURLOPT_FOLLOWLOCATION并设置最大跳转次数:
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_MAXREDIRS, 5); // 设置最大跳转次数,避免死循环 // 获取所有跳转历史(需要PHP 7.1+) $redirect_chain = curl_getinfo($ch, CURLINFO_REDIRECT_CHAIN); if ($redirect_chain) { foreach ($redirect_chain as $step) { echo "跳转: " . $step . "\n"; } }
不过注意,开启FOLLOWLOCATION后,cURL会自动跳转,你需要结合CURLINFO_REDIRECT_CHAIN来获取完整的跳转链。
4. 处理相对URL的拼接
有时候跳转的URL是相对路径,需要结合当前页面的域名拼接成完整URL。可以添加一个辅助函数:
function resolve_full_url($base_url, $relative_url) { if (parse_url($relative_url, PHP_URL_SCHEME)) { return $relative_url; // 已经是完整URL } $base_parsed = parse_url($base_url); $scheme = $base_parsed['scheme']; $host = $base_parsed['host']; if ($relative_url[0] == '/') { return "$scheme://$host$relative_url"; } // 处理相对路径 $base_path = dirname($base_parsed['path']); return "$scheme://$host$base_path/$relative_url"; }
5. 考虑使用无头浏览器(终极方案)
如果TikTok的跳转逻辑非常复杂(比如需要Cookie验证、JS渲染),纯cURL可能无法完全模拟。可以用PHP的无头浏览器库(比如spatie/browsershot或直接调用Puppeteer),完整模拟浏览器加载过程,获取最终的URL:
// 示例:使用spatie/browsershot use Spatie\Browsershot\Browsershot; $final_url = Browsershot::url('https://vm.tiktok.com/ZMeh1yKUQ/') ->setUserAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36') ->waitUntilNetworkIdle() ->getCurrentUrl(); echo "最终URL: " . $final_url;
内容的提问来源于stack exchange,提问作者Bruno Maciel




