You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

关于使用cURL获取TikTok帖子最终URL及追踪重定向路径的技术求助

如何用cURL追踪TikTok短链接的完整跳转链,获取浏览器显示的最终用户主页链接?

我想用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

火山引擎 最新活动