跳到主要内容
BLKBLKTECH

指南 / ai

AI Skills 实战:内链结构审计 Skill——没有一条链接是坏的,但结构可能是坏的

用点击深度、入链分布、连通性和锚文本四个图指标审计站内结构,剔除全局导航干扰,识别内容孤岛与权重错配,并让模型判断分布是否匹配内容战略。

作者 BLKTECH 编辑部更新 2026年8月1日18 分钟难度 实战免费Node.jsBunAI Agent图算法

内链结构审计要先剔除全局导航链接,否则链接图退化成完全图、所有指标失效。剔除后用 BFS 算点击深度、统计横向入链分布、找连通分量、检查锚文本描述性。图指标本身没有对错,必须由模型结合内容战略解读,因此这类检查不应阻断构建。

先说结论

前四篇查的都是错误:链接断了(①)、字段缺了(②)、标记错了(③)、信号矛盾了(④)。每一条都能指着说「这里错了」。

这一篇不一样。一个站可以做到:零死链、Meta 全合格、结构化数据全绿、sitemap 零矛盾——同时内链结构一塌糊涂

因为结构问题不在任何单条链接上:

没有一条链接是坏的,但它们组成的形状可能是坏的。

比如你最想推的那篇文章,全站只有 1 个内链指向它;比如有 7 篇文章互相链来链去,和站点主体几乎不通;比如某个页面要点 5 次才能从首页到达。逐条检查这些链接,每一条都完全正常。

要看见形状,得把内链当成来算。


一、开始之前:必须先剔除全局导航

这是本篇最重要的一条,做错了后面全部白算。

大多数站点的 header 和 footer 里有一套全局导航,出现在每一个页面上。如果你把页面上所有 <a> 都算进链接图:

  • 每个页面都链向导航里的那 10 个页面
  • 于是那 10 个页面各自获得 N 个入链(N = 全站页面数)
  • 每个页面到它们的距离都是 1 跳

图退化成了近似完全图,所有指标同时失去意义。 点击深度全是 1,入链分布被导航项垄断,连通分量只剩一个。你会得到一份「一切正常」的报告,而它什么也没测出来。

正确做法是只统计正文区域的链接:

// 只取 <main> 内的链接,排除 header / footer / 侧边栏
const body = html.split('<main')[1]?.split('</main>')[0] ?? html;

差别有多大?本站实测:

统计范围 最大点击深度 入链中位数 可达页面
全部 <a> 1 跳 被导航项垄断 全部
<main> 2 跳 9 64 / 66

只有第二行的数据能拿来做判断。

这条同样适用于面包屑、相关文章推荐、分页控件等模板化链接。 判断标准很简单:这个链接是「因为这篇内容需要」而存在,还是「因为模板长这样」而存在?只有前者反映真实的内容关系。


二、四个可测指标

指标 算法 回答什么问题
点击深度 从首页 BFS 这页要点几次才能到?
入链分布 入度统计 站内认为哪些页面重要?
连通性 连通分量 有没有和主体断开的内容团?
锚文本 文本聚合 链接告诉了搜索引擎什么?

四个指标有个共同特点,也是本篇 Skill 设计的关键:

图指标本身没有对错,全靠解读。

「这页入链是 2」既不是好也不是坏——取决于它是一篇你想推的核心文章,还是一个归档页。这决定了模型在这个 Skill 里承担的比例是五篇里最高的。


三、点击深度

从首页出发的最短路径长度。经验共识是超过 3 跳的页面权重明显衰减,抓取频率也会下降。

BFS 就够了,不需要复杂算法:

const depth = new Map([['/', 0]]);
const queue = ['/'];
while (queue.length) {
  const cur = queue.shift();
  for (const next of graph.get(cur) ?? []) {
    if (graph.has(next) && !depth.has(next)) {
      depth.set(next, depth.get(cur) + 1);
      queue.push(next);
    }
  }
}
const unreachable = [...graph.keys()].filter((p) => !depth.has(p));

本站实测结果:

0 跳:   1 页    (首页)
1 跳:  28 页
2 跳:  35 页
3 跳+:  0 页
不可达: 2 页    /about/  /newsletter/

深度分布很健康——全站最深 2 跳,因为首页和栏目索引页承担了枢纽作用。

值得注意的是最后一行的 2 个不可达页面/about//newsletter/ 从首页出发、只走正文链接是到不了的,它们完全依赖 header 里的全局导航存活。

这不一定是问题(导航链接搜索引擎同样会爬),但它揭示了一件事:这两个页面没有任何一篇内容认为有必要提到它们。如果 /newsletter/ 是个转化目标,那这就是实打实的机会损失——正文里一次都没被提及的订阅页,转化率不会好。


四、入链分布:它反映的是组织方式,不是质量

统计每个页面被多少个其他页面的正文链接。本站实测的 Top 5:

65 入链  /                        (首页)
56 入链  /resources/              (栏目索引)
44 入链  /guides/                 (栏目索引)
27 入链  /ai/                     (栏目索引)
15 入链  /guides/展示型独立站进阶优化/  ← 第一个内容页

首页和栏目页占据前四位是正常的枢纽结构。真正要看的是文章之间的横向链接——把栏目页排除后,只统计「文章 → 文章」:

文章页共 53 篇
横向入链为 0 的:1 篇

最少:
  0 入链  /practice/first-week-content-ops/
  1 入链  /resources/learning-paths/
  2 入链  /guides/docker-basics-for-solo-devs/

最多:
 11 入链  /guides/展示型独立站进阶优化/
 10 入链  /resources/hyperframes-video-workflow-template/
 10 入链  /guides/hyperframes-skills-first-video/

这组数据里藏着一个容易被误读的规律:

入链最多的全部是系列文章,入链最少的全部是单篇文章。

原因很朴素——系列文章末尾有导航节,天然互相链接;单篇文章再好也没人链它。所以:

内链分布反映的是内容的组织方式,不是内容的质量。

这个结论直接影响该怎么修:看到「某篇文章入链只有 2」,正确的反应不是「这篇文章不重要」,而是「这篇文章没有被组织进任何结构里」。修法是给它找到归属——并入某个系列、或从相关文章里主动引用,而不是机械地到处塞链接。

判断「这个分布合不合理」需要知道你的内容战略是什么,脚本给不出答案。这是模型在这个 Skill 里最主要的工作。


五、连通性与内容孤岛

把链接图看作无向图求连通分量,能找出和主体断开的内容团。

比①的孤儿页检测更进一步的是:孤岛可以由多个页面组成,每个页面都有入链,但整团和主体不通。逐页检查永远发现不了——每一页看起来都好好的。

// 无向连通分量
const undirected = new Map();
for (const [from, tos] of graph) {
  for (const to of tos) {
    if (!graph.has(to)) continue;
    (undirected.get(from) ?? undirected.set(from, new Set()).get(from)).add(to);
    (undirected.get(to) ?? undirected.set(to, new Set()).get(to)).add(from);
  }
}
const seen = new Set(); const components = [];
for (const node of graph.keys()) {
  if (seen.has(node)) continue;
  const comp = []; const stack = [node];
  while (stack.length) {
    const cur = stack.pop();
    if (seen.has(cur)) continue;
    seen.add(cur); comp.push(cur);
    for (const n of undirected.get(cur) ?? []) if (!seen.has(n)) stack.push(n);
  }
  components.push(comp);
}

理想结果是一个大分量 + 零星孤立点。出现两个以上规模相当的分量,说明站点内容实际上分成了互不往来的两块——常见于「后来加了个新主题,但从没和老内容互相引用」。


六、锚文本

链接的文字告诉搜索引擎目标页是关于什么的。三类问题:

问题 例子 影响
无信息锚文本 「点击这里」「阅读更多」「详情」 浪费了一次描述机会
过度一致 全站 20 条链接锚文本一字不差 有过度优化嫌疑
完全无关 锚文本和目标页主题对不上 信号混乱

本站实测无信息锚文本 0 处——这类问题在手写 Markdown 的站上很少见,在用可视化编辑器或从模板生成的站上则很普遍。

第二、三类都需要模型判断:「20 条锚文本都叫『Astro 教程』」到底是自然的(确实都在指同一篇教程)还是过度优化,得看上下文。脚本只能把锚文本按目标页聚合起来,判断交给模型。


七、Skill 设计:模型占比最高的一篇

任务 归属
剔除全局导航、构建链接图 脚本
BFS 算点击深度 脚本
入度统计、连通分量 脚本
锚文本按目标页聚合 脚本
判断深度分布是否合理 模型
判断入链分布是否匹配内容战略 模型
判断孤岛该合并还是该断开 模型
判断锚文本是自然还是过度优化 模型
给出补哪条内链的具体建议 模型

脚本在这一篇只负责把图算出来,所有「这算好还是不好」的问题全归模型。

最后一项特别值得说。发现「文章 X 只有 2 个入链」之后,真正有用的输出不是这句话本身,而是:

「从《A》第 3 节讲到部署时,可以链到 X;从《B》的相关阅读里也该有 X。」

这需要同时理解 X 讲什么、A 和 B 讲什么、在哪个位置插入是自然的。这是整个系列里模型价值最高的一处——脚本连边都摸不到。


八、报告样例

本站真实扫描结果:

# 内链结构审计报告

统计范围:<main> 内链接(已剔除全局导航)
页面 66 / 文章 53 / 最大深度 2 跳

## ✅ 点击深度

0 跳 1 页 · 1 跳 28 页 · 2 跳 35 页 · 3 跳+ 0 页

结构扁平,首页与栏目索引承担枢纽作用,无深层页面。

## 🟡 正文不可达(2 页)

| 页面 | 说明 |
|---|---|
| /about/ | 仅存在于 header 导航,无任何正文引用 |
| /newsletter/ | 同上 |

**判定**:/about/ 可接受(工具型页面)。
/newsletter/ 若为转化目标则是机会损失——53 篇文章无一提及订阅入口。
**建议**:在系列文章末尾的「相关阅读」中加入订阅引导。

## 🟡 横向入链偏低(3 篇)

| 文章 | 横向入链 |
|---|---|
| /practice/first-week-content-ops/ | 0 |
| /resources/learning-paths/ | 1 |
| /guides/docker-basics-for-solo-devs/ | 2 |

**根因**:三篇均为独立单篇,未归入任何系列。入链最多的
11 篇全部来自「展示型独立站」与「HyperFrames」两个系列
——系列末尾的导航节带来了天然互链。

**建议**:不要机械补链。first-week-content-ops 与
content-publishing-automation 主题相邻,可在后者正文中
自然引用;或将两者组织为内容运营小系列。

## ✅ 锚文本

无信息锚文本 0 处。

报告里真正有价值的是每一条判定后面的那句解释:为什么 /about/ 不可达可以接受而 /newsletter/ 不行,为什么入链低的都是单篇文章。数字是脚本给的,判断是模型给的,而人只会读判断。


九、修复策略

问题 动作 注意
深度 > 3 跳 从栏目页或相关文章增加入口 别靠加导航项解决
正文不可达 判断是否为工具型页面;是转化目标就必须补 导航链接不能替代正文引用
横向入链为 0 先找归属,再补链 归入系列比零散加链有效
内容孤岛 从主体内容主动引用,建立双向连接 单向链接不足以打通
无信息锚文本 换成描述目标页内容的短语
锚文本过度一致 自然变化即可,不必刻意改写 别为了「多样性」写得不通顺

一条贯穿的原则:

内链要因为内容需要而存在,不是因为 SEO 需要而存在。

为了提升某页入链数,在 20 篇不相关的文章里硬塞链接——这既帮不了排名,也损害阅读体验。内链分布应该是内容组织的自然结果,如果某篇文章实在找不到自然的引用位置,那要解决的是它在内容体系里的定位问题,不是链接数量问题。


十、CI 策略:这一篇完全不阻断

系列前四篇的阻断线各不相同,这一篇的答案最干脆:全部不阻断,只出报告。

理由回到那条一以贯之的判据——这件事有没有唯一正确答案

检查 有标准答案吗
内链指向 404 ✅ 有
title 跨页重复 ✅ 有
sitemap ∩ noindex ✅ 有
某页入链只有 2 ❌ 没有
深度 3 跳 ❌ 没有
锚文本重复 8 次 ❌ 没有

给结构指标设阈值(「每篇文章至少 3 个入链」)会立刻产生副作用:为了达标而互相塞链接,制造出一堆对读者无意义的链接。指标一旦成为目标,就不再是好指标。

所以这个 Skill 的正确用法是周期性人工触发,而不是每次 push 都跑:

name: link-structure
on:
  schedule:
    - cron: '0 4 1 * *'   # 每月一次
  workflow_dispatch:       # 需要时手动触发

月度跑一次,把报告当作内容规划的输入——看看这个月新发的文章有没有被组织进结构里,比在 CI 里卡构建有用得多。

至此五篇的 CI 策略全景:

系列 阻断 放行 频率
① 死链 内链 404 外链失效 每次构建 / 每周
② Meta 缺失、跨页重复 长度、措辞 每次构建
③ 结构化数据 L1+L2+客观 L3 语义一致性 每次构建
④ Sitemap 信号矛盾 漏收录、孤儿页 每次构建
⑤ 内链结构 全部 每月

从「必须阻断」到「完全不阻断」,判据始终只有一条。


十一、系列导航

「SEO Skills 工具箱」五类检查至此讲完:

  1. 死链与断链审计
  2. Meta 审计:title、description、H1
  3. 结构化数据与 JSON-LD 校验
  4. Sitemap 差异审计与孤儿页发现
  5. 当前:内链结构审计
  6. 内置 seo:audit 与 Skill 封装——把五类检查合并成一条命令
  7. 配套资源:说明书、规则注册表与检查清单

六条原则:

  • 确定性交给脚本,判断交给模型(①)
  • 能量化的写成阈值表,不能量化的给判断依据(②)
  • CI 的阻断线画在「有唯一正确答案」的地方(②③④⑤)
  • 报告要给根因,不是给症状列表(③)
  • 集合运算前先做归一化——脚本不会报错,只会安静地全错(④)
  • 算图指标前先剔除模板化链接,否则测的是模板不是内容(⑤)

五类检查下来会发现,真正区分「能用的 Skill」和「玩具」的,从来不是模型多聪明,而是判定规则写得够不够细、边界划得够不够清。这些规则可以慢慢积累——每次发现一个误报就往参考资料里加一条,用得越久越准。这正是把它做成 Skill 而不是一次性脚本的意义。

下一篇把这五类检查合并成项目内置的一条 validate 命令,并给出 Skill 层该怎么只做解释、不做检测。

相关阅读:

NEXT ACTION / 下一步

回看系列第四篇:Sitemap 差异审计

把读到的方法变成一个小行动,完成后再回来迭代。

继续

RELATED / 相关推荐

接着读这些

按同一栏目、标签与技术栈为你挑选。