KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA
05 · 站点信息架构:URL、内链与分页 — keel 龙骨
本章目标:把站点的"物理结构"设计成搜索引擎能理解、能分配权重、能穷尽抓取的形状。 验收标准:无孤儿页、内链模型清晰、分页可抓取、sitemap 分层且可扩展。
本章目标:把站点的"物理结构"设计成搜索引擎能理解、能分配权重、能穷尽抓取的形状。
验收标准:无孤儿页、内链模型清晰、分页可抓取、sitemap 分层且可扩展。
为什么架构是工程问题:内容再多,如果架构扁平混乱、重要页面深埋、分页不可达,发现与抓取就都失效。信息架构(IA)是唯一一处你能完全掌控、且收益最持久的杠杆。
一、URL 设计
| 原则 | 正例 | 反例 |
|---|---|---|
| 可读 | /learning/courses/tools/lessons/1/ |
/p?id=87 |
| 稳定 | 发布后不变 | 频繁改路径 |
| 有层级 | /courses/<course>/lessons/<n>/ |
全平铺 /a1 |
| 单一大写策略 | 全小写 | 混用大小写 |
| 尾斜杠唯一 | 统一带 / |
两种并存 |
| 不含无意义参数 | 干净路径 | ?sessionid= |
三条硬规则:
- 一页一 URL,其余形式 301 到规范形式。
- 深度 ≤ 4 跳——从首页到任意重要页面。
- 层级最多 3 层语义分割,过深会稀释权重。
# 检查站内 URL 是否混用尾斜杠
curl -s https://www.xxxxxx.cn/learning/ | grep -oE 'href="[^"]+"' \
| grep -vE '\.(css|js|png|svg)' | sort -u | head -20
二、面包屑:可抓取的层级表达
面包屑同时服务用户体验与结构表达,且是内链的一种(向上指)。
<nav aria-label="Breadcrumb">
<ol>
<li><a href="/learning/">首页</a></li>
<li><a href="/learning/courses/tools/">工具课</a></li>
<li>第 1 课</li>
</ol>
</nav>
配套 BreadcrumbList 结构化数据(第 04 章)。规则:面包屑的每一级都应是真实可访问的页面,且与 URL 层级一致。
三、内链模型:Hub / Spoke
内链不是"随便加几个链接",而是有权重分配意图的图结构。
Homepage
/ | \
Hub A Hub B Hub C ← 栏目/hub 页(聚合主题)
/ | \ / | \ / | \
S S S S S S S S S ← spoke 内容页(具体文章)
\ | / \ | / \ | /
Hub A Hub B Hub C ← 相关内容回链 hub
| 角色 | 作用 | 设计要点 |
|---|---|---|
| Hub(栏目页) | 聚合主题、分配权重 | 链向全部 spoke,且被首页链向 |
| Spoke(内容页) | 承载具体主题 | 链回 hub,并交叉链向相关 spoke |
| 交叉链 | 强化主题簇 | 只在相关时连,避免为连而连 |
判据:
- 无孤儿页:每个页面至少有一条入链。
- 无死胡同:每个页面至少有一条出链(回 hub 或相关页)。
- hub 被首页直接链向,否则整个簇的权重都低。
# 生成站内链接图(简版):列出每页的出链数
for u in $(curl -s https://www.xxxxxx.cn/learning/sitemap.xml | grep -oE '<loc>[^<]+' | sed 's/<loc>//'); do
n=$(curl -s "$u" | grep -c '<a ')
echo "$n $u"
done | sort -rn | head -20
锚文本:内链的"半句话推荐"
锚文本是链接里可见的文字,它告诉引擎"目标页讲的是什么"。规范做法:
| 做法 | 评价 |
|---|---|
| 描述性锚文本("抓取预算的量化方法") | 推荐 |
| 裸 URL 或"点击这里" | 浪费信号,避免 |
| 同一目标页全站用完全相同锚文本 | 过于机械,适度变化 |
| 无关锚文本堆砌 | 可能被判定操纵 |
规则:锚文本应描述目标页主题,且与之相关;对同一目标页,用语义相近但措辞多样的锚文本,比全站复制一句话更自然。
四、分页与无限滚动的可抓取化
4.1 分页
| 做法 | 可抓取性 | 评价 |
|---|---|---|
?page=N + <a href> |
好 | 可用,配 canonical 自引用 |
| JS 点击加载下一页 | 差 | 深层不可达 |
| 无限滚动无 URL | 最差 | 只有第一页被索引 |
推荐:分页用真实 <a href>,每页自引用 canonical,不做跨页 canonical 合并(避免把第 2 页并入第 1 页导致不收录)。
4.2 无限滚动
无限滚动的正确工程化做法是**"滚动 + 真实分页 URL 双轨"**:
<!-- 滚动加载的同时,提供可抓取的"下一页"链接 -->
<a href="/learning/courses/tools/lessons/page/2/" rel="next">下一页</a>
| 要求 | 说明 |
|---|---|
| 每个滚动区块有独立 URL | 如 /page/2/ |
有 <a href> 直达 |
不用 onclick |
| 首屏内容直出 | 不依赖滚动触发 |
| sitemap 收录各分页 | 让引擎发现深层 |
五、站点地图分层
当 URL 数量增长,单个 sitemap 会超限(5 万条/50MB)。用 sitemap index 拆分层级:
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap><loc>https://www.xxxxxx.cn/sitemap-pages.xml</loc></sitemap>
<sitemap><loc>https://www.xxxxxx.cn/sitemap-lessons.xml</loc></sitemap>
<sitemap><loc>https://www.xxxxxx.cn/sitemap-images.xml</loc></sitemap>
</sitemapindex>
| 分层 | 内容 | 提交优先级 |
|---|---|---|
| pages | 首页、栏目、核心页 | 高 |
| lessons | 内容页 | 高 |
| tags | 标签/归档 | 低 |
| images | 图片 | 中 |
规则:
- 每个子 sitemap 只含同类 URL,便于独立监控。
lastmod必须真实,否则失去"是否重抓"的信号价值。- 大站可再按
lastmod分段,提高增量抓取效率。
六、故障速查
| 现象 | 架构层原因 | 处理 |
|---|---|---|
| 部分页面从不被抓 | 孤儿页 | 补内链 |
| 重要页排名低 | 深埋、无 hub 链接 | 缩短深度、加 hub |
| 分页第 2 页起不收录 | JS 加载 | 改真实 URL + <a href> |
| 收录数低于页面数 | sitemap 未覆盖 | 补全 + 分层提交 |
| 权重被稀释 | 内链到处乱指 | 收敛到 hub/spoke 模型 |
| 重复 URL 多 | 尾斜杠/参数混用 | 统一 + 301 |
七、本章验收
- 全站 URL 单一大写与尾斜杠策略,无参数污染
- 任意重要页面从首页 ≤4 跳可达,无孤儿页、无死胡同
- 每个主题簇有 hub,且 hub 被首页直链
- 分页/无限滚动有真实
<a href>与独立 URL - sitemap 已分层(或已明确分层计划),lastmod 真实
# 架构自检:sitemap 条数与首页出链
curl -s https://www.xxxxxx.cn/learning/sitemap.xml | grep -c '<loc>'
curl -s https://www.xxxxxx.cn/learning/ | grep -c '<a '
结构就绪后,如果要面向多种语言/地区,就进入下一章的国际化。