小红书短链(如xhslink.com/abc123)是302跳转,最终指向含笔记ID等参数的完整URL;PHP需用cURL开启CURLOPT_FOLLOWLOCATION并获取CURLINFO_EFFECTIVE_URL才能正确还原。

小红书短链接结构是怎样的?
小红书分享文案里的短链(如 https://xhslink.com/abc123)本质是 302 跳转,最终指向带完整参数的笔记页 URL。直接访问短链会触发重定向,但 PHP 中默认的 file_get_contents() 或 curl_exec() 不会自动跟随跳转,所以拿不到最终 URL —— 这是还原失败最常见的原因。
关键参数藏在跳转后的 URL query string 里,典型结构类似:https://www.xiaohongshu.com/explore/xxxxxx?xhsshare=xxx&app_platform=android&app_version=8.93.0&share_from_user_hidden=true&xhss=xxx
其中 explore/xxxxxx 后面那段 ID 就是笔记唯一标识符(俗称“笔记ID”),其余如 app_platform、share_from_user_hidden 是渠道或埋点参数,通常可忽略。
用 cURL 获取重定向最终 URL(推荐)
PHP 最可靠的方式是配置 cURL 请求头并启用跳转跟踪,同时只获取响应头(不下载页面内容),提升速度和稳定性。
立即学习“PHP免费学习笔记(深入)”;
- 必须设置
CURLOPT_FOLLOWLOCATION为true,否则卡在第一次 302 - 禁用
CURLOPT_RETURNTRANSFER或配合CURLOPT_HEADER+CURLOPT_NOBODY,避免拉取整页 HTML - 加上
User-Agent,部分短链服务会拦截无 UA 的请求 - 注意:某些短链可能跳转多次(例如 xhslink → xiaohongshu.com → 带参数的 explore 页面),
CURLOPT_MAXREDIRS建议设为5
function getRealXHSUrl($shortUrl) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $shortUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); // 不要 body
curl_setopt($ch, CURLOPT_HEADER, true); // 只要 header
curl_setopt($ch, CURLOPT_NOBODY, true); // 不取 body
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
ob_start();
curl_exec($ch);
$headers = ob_get_clean();
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$finalUrl = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
curl_close($ch);
if ($httpCode >= 300 && $httpCode < 400 || $httpCode === 200) {
return $finalUrl;
}
return null;
}
// 示例调用
$real = getRealXHSUrl('https://xhslink.com/ABcDeF');
echo $real; // 输出类似 https://www.xiaohongshu.com/explore/65a1b2c3d4e5f67890123456?xhsshare=...
从最终 URL 提取笔记 ID 和关键参数
得到 https://www.xiaohongshu.com/explore/65a1b2c3d4e5f67890123456?xhsshare=... 后,笔记 ID 就是 explore/ 后面那一串 24 位十六进制字符串(MongoDB ObjectId 格式)。其他参数如 xhsshare、share_from_user_hidden 可用 parse_url() + parse_str() 拆解。
- 笔记 ID 正则建议用:
/\/explore\/([0-9a-f]{24})/i,注意大小写不敏感 - 不要依赖
parse_url($url, PHP_URL_PATH)后再 explode,因为路径可能含中文或特殊字符(极少数情况) - 如果最终 URL 是
https://www.xiaohongshu.com/discovery/item/...(新版发现页),ID 位置不同,需额外判断
$url = 'https://www.xiaohongshu.com/explore/65a1b2c3d4e5f67890123456?xhsshare=abc123&app_platform=ios';
$matches = [];
if (preg_match('/\/explore\/([0-9a-f]{24})/i', $url, $matches)) {
$noteId = $matches[1]; // "65a1b2c3d4e5f67890123456"
$parsed = parse_url($url);
parse_str($parsed['query'], $params);
$xhsshare = $params['xhsshare'] ?? null; // "abc123"
$platform = $params['app_platform'] ?? null; // "ios"
}
绕过跳转的替代方案(不推荐但有时有效)
部分小红书短链支持 HEAD 请求直接返回 Location 头,不用走完整 GET 流程。但 xhslink.com 近期已限制 HEAD,多数情况下返回 405 或空 Location —— 所以不能作为主力方案,仅作 fallback。
- 若 cURL 被墙或超时,可尝试加代理(
CURLOPT_PROXY),但需注意代理稳定性 - 批量处理时务必加延迟(
usleep(300000)),高频请求会被封 IP 或返回 429 - 别用
get_headers():它底层不保证跟随跳转,PHP 版本差异大,行为不可控
真正稳定还原的关键,不是“怎么快”,而是“怎么让服务端把跳转链完整吐出来”。cURL 的 CURLINFO_EFFECTIVE_URL 是目前最接近“真实终点”的 PHP 原生能力。











