做外链分析的时候经常遇到一个问题:导出来的外链数据里混杂了大量短链接和跳转链接,t.cn、dwz.cn、bit.ly、suo.im、还有各种二级域名的301跳转,根本不知道最终落地页是什么。不还原吧,没法判断外链质量;一条条手动点开吧,200条链接就能点到你怀疑人生。
这篇文章整理了从在线工具到自写脚本的几套方案,重点解决一个核心需求:怎么把一堆短链接批量、准确、高效地还原成真实目标URL,而且能处理多重跳转和跳转路径中的异常。
一、链接还原到底在还原什么
很多人以为链接还原就是把短链接展开,但其实场景比这个复杂得多:
五种场景里,前四种用HTTP层面的工具就能解决,第五种JS跳转需要能解析页面内容的工具。大部分情况下,前四种已经覆盖了90%以上的需求。
二、四种方案的实测对比
同一批500条链接(含短链接、301跳转、嵌套短链接),用四种方案跑了一遍,结果如下:
在线工具漏掉的23%,主要来自两类链接:需要特定User-Agent才返回跳转的链接(部分短链接服务会检查请求头),和嵌套超过1层的短链接(在线工具一般只还原第一层就停了)。
三、curl一行命令解决80%的需求
如果你只需要批量还原一批链接,不需要复杂的统计分析,curl的-L参数就是最直接的方案。

# 单条链接还原,追踪所有跳转,输出最终URLcurl -Ls -o /dev/null -w "%{url_effective}" https://t.cn/xxxxx# 批量还原:把链接列表放urls.txt,一行一个while read url; doecho "$url → $(curl -Ls -o /dev/null -w '%{url_effective}' "$url")"done < urls.txt# 加上User-Agent和超时,避免被短链接服务拒绝curl -Ls -o /dev/null -w "%{url_effective}\n" \-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \--connect-timeout 5 --max-time 10 \https://t.cn/xxxxx
curl -L的原理是让curl自动跟随HTTP重定向(301/302/303/307/308),最终输出的是跳转链终点URL。它能自动追踪多层跳转,不需要自己写递归逻辑。但有三个限制:
无法检测JS跳转
如果页面通过JavaScript(location.href或meta refresh)跳转,curl看不到,因为curl不执行JS。
串行处理慢
while read循环是串行的,1000条链接大约需要3-5分钟。数量大的时候建议换并发方案。
被反爬拦截
部分短链接服务(尤其是国内平台)会检查Referer和Cookie,curl不加这些头可能返回验证页面。
四、Python并发脚本:500条5秒,多层嵌套自动剥到底
当链接数量超过200条,或者需要处理嵌套短链接时,curl的串行方案就不够用了。下面是一个完整的Python脚本,核心思路是并发请求 + 递归追踪跳转 + 自动剥离追踪参数:
import asyncioimport aiohttpfrom urllib.parse import urlparse, urlunparseimport csv# 需要剥离的追踪参数TRACKING_PARAMS = {'utm_source', 'utm_medium', 'utm_campaign','utm_term', 'utm_content', 'spm', 'clickid','gclid', 'fbclid', 'msclkid', 'ref'}def strip_tracking(url):"""剥离追踪参数,保留核心URL"""parsed = urlparse(url)if not parsed.query:return urlparams = [p for p in parsed.query.split('&')if p.split('=')[0].lower() not in TRACKING_PARAMS]new_query = '&'.join(params)return urlunparse((parsed.scheme, parsed.netloc,parsed.path, parsed.params, new_query, parsed.fragment))async def resolve_url(session, url, max_redirects=10, visited=None):"""递归追踪跳转,最多追max_redirects层,防止死循环"""if visited is None:visited = set()if url in visited or max_redirects <= 0:return url, len(visited)visited.add(url)headers = {'User-Agent': 'Mozilla/5.0 (compatible; LinkResolver/1.0)'}try:async with session.get(url, headers=headers,allow_redirects=False,timeout=aiohttp.ClientTimeout(total=8)) as resp:if resp.status in (301, 302, 303, 307, 308):location = resp.headers.get('Location', '')if location:return await resolve_url(session, location,max_redirects - 1, visited)return str(resp.url), len(visited)except Exception as e:return f'ERROR: {e}', len(visited)async def batch_resolve(urls, concurrency=50):"""批量并发还原链接"""connector = aiohttp.TCPConnector(limit=concurrency)async with aiohttp.ClientSession(connector=connector) as session:tasks = [resolve_url(session, url) for url in urls]results = await asyncio.gather(*tasks)return results# 使用示例urls = ['https://t.cn/xxxxx', 'https://bit.ly/yyyyy', ...]results = asyncio.run(batch_resolve(urls))for original, (final, depth) in zip(urls, results):clean = strip_tracking(final)print(f'{original} → {clean} (跳了{depth}层)')
✅ 这个脚本解决了curl做不到的四件事
- 并发50线程:500条链接约5秒跑完,curl串行需要3-5分钟
- 手动控制跳转:设置allow_redirects=False,每层跳转自己判断,防止被中间劫持链接带偏
- 递归追踪嵌套短链接:t.cn → dwz.cn → 最终页,自动一层层剥开
- 自动剥离追踪参数:utm_source、gclid、fbclid等自动清理,方便去重分析
五、跳转路径中的劫持检测
还原链接不只是拿到最终URL就完事了。中间跳转路径里有没有被插入广告联盟跳转、有没有经过可疑域名——这些问题在线工具和简单脚本都检测不到。
🔴 三种需要警惕的跳转路径异常
原始路径:短链接 → 目标页
异常路径:短链接 → 广告联盟跳转(如go.xxx.com/ad?url=...)→ 目标页
广告联盟在中间截了一道流量,用户的每次点击都被计入广告展示。
短链接过期后被回收重新绑定到了仿冒网站。还原出来是钓鱼站或色情站,但原链接看起来还是正常的短链接域名。常见于免费短链接服务的老链接。
短链接A → 短链接B → 目标页,如果短链接B的服务挂了或链接过期了,整个链条中断。还原工具需要标记哪一层出了问题和具体错误码。
上文的Python脚本只要稍加修改,在递归追踪时记录每一跳的URL和HTTP状态码,就能生成完整的跳转链路图。如果你发现中间经过了不明广告域名(如go.xxx.com、track.xxx.com、redirect.xxx.com),就可以判断跳转路径被污染了。
六、不同数量级的工具选型建议
在线工具 + 浏览器插件
用浏览器插件Link Redirect Trace逐条查看完整跳转链,能看到每一跳的HTTP状态码和响应头,比在线工具详细得多。20条以内手动操作完全可接受。
推荐工具

Link Redirect Trace(Chrome插件)
curl -L 批量脚本
一行bash脚本就够,加上User-Agent头。如果遇到需要Cookie的链接,先从浏览器复制Cookie到curl的-b参数。
核心命令
curl -Ls -o /dev/null -w "%{url_effective}" -H "User-Agent: ..."
Python并发脚本
上文的Python脚本直接拿来用,改一下输入文件的路径就行。支持CSV输入输出、自动剥离追踪参数、记录跳转层数。
性能参考
1000条约10秒,5000条约50秒
七、还原后要做的三件事
链接还原本身不是目的,还原后的数据怎么用才是关键:
域名去重统计
还原后提取所有目标域名,做频次统计。外链分析时能快速看出哪些域名给了最多链接、哪些是垃圾域名。
死链接标记
还原失败的链接单独导出(404/超时/DNS解析失败),区分是短链接服务挂了还是目标页面挂了,处理方式不同。
跳转路径异常告警
跳转层数超过3层的、中间经过广告域名的、某层返回非200/301/302状态码的——这些单独标记出来人工核查。
🔗 站群外链分析场景:怎么把链接还原融入日常SEO工作流
做站群运营的时候,定期扫描外链中的短链接和跳转链接是一项需要持续做的事情。UC建站系统的外链监控模块支持自动抓取所有外链并批量还原真实目标URL,同时标记跳转路径中的异常(广告劫持、多层嵌套、死链),一个看板看到所有站的外链健康状态和跳转链路,不用手动跑脚本再贴回Excel。
批量还原目标URL
广告劫持/多层嵌套/死链
统一监控不遗漏
链接批量还原这件事,工具选择取决于两个变量:数量级和复杂度。100条以内,curl一行命令完全够用;超过500条且需要处理嵌套跳转和劫持检测,Python脚本是性价比最高的方案。在线工具只适合偶尔查一两条的场景,千万别拿它批量跑——效率差了几十倍不说,准确率也差了一截。
