静态博客没有后端,但 SEO 的要求一样不少。这篇把渡劫博客的完整 SEO 流程摊开讲:软 404 治理、sitemap 纪律、RSS 规范、结构化数据、收录提交,以及我们刚踩过的一个真实大坑——把 GitHub Pages 的 URL 混进了主域 sitemap。

第一课:软 404 比 404 更伤站

所谓软 404,是服务器对不存在的路径返回 200 + text/html。我们之前的 CF Pages 站点没有根级 404.html,访问 /assets/avatar.png 这类错路径会拿到 200 状态的 index.html 内容。搜索引擎的判罚很直接:全站不同 URL 返回同一内容 = 重复页 + 低质量信号,收录会被系统性压制。

修复只需一步:在站点根目录放一个真正的 404.html。CF Pages 检测到根路径存在该文件后,对未命中路径返回它并带上 404 状态码:

curl -sI https://www.520691.xyz/assets/avatar.png
# HTTP/2 404   ← 修复后
curl -sI https://www.520691.xyz/404.html
# HTTP/2 200   ← 页面本身可访问

同时给 404 页加 <meta name="robots" content="noindex">,并提供返回首页与站内搜索入口,把迷路流量导回内容。

sitemap 的三条纪律

  • 只收主域:sitemap 是「这个文件描述这些 URL」的契约。把 gjsvip.github.io 的 URL 写进 www.520691.xyz 的 sitemap,搜索引擎要么忽略、要么判定跨域作弊。GitHub 端需要覆盖就单独出 sitemap-github.xml
  • lastmod 必须真实:全部写成同一天等于没写。文章的 lastmod 取 posts.json 里的 date,静态页用 git log -1 --format=%cs -- <文件> 取真实修改日期
  • URL 形态与 canonical 一致:CF Pages 支持无扩展名 URL(/posts/hello-world),canonical 与 sitemap 就都写无扩展名;GitHub Pages 不支持,所以它的 sitemap 用 .html 形态
<url>
  <loc>https://www.520691.xyz/posts/hello-world</loc>
  <lastmod>2024-12-26</lastmod>
  <changefreq>monthly</changefreq>
  <priority>0.8</priority>
</url>

priority 按页面类型分层:首页 1.0、文章 0.8、归档/标签 0.5、说说/友链/关于 0.4——它只是权重提示,但保持一致性本身就是质量信号。

robots.txt 与双向声明

robots.txt 放行全站,并用 Sitemap 指令声明两个入口(robots.txt 允许多条 Sitemap 行):

User-agent: *
Allow: /

Sitemap: https://www.520691.xyz/sitemap.xml
Sitemap: https://gjsvip.github.io/blog/sitemap-github.xml

RSS:把 pubDate 当契约

RSS 2.0 要求 pubDate 是 RFC-822 格式,写错的后果是聚合器直接丢弃整条 item。我们的生成规则:文章 date 加 08:00:00 +0800,星期几由程序计算,不手写:

<pubDate>Wed, 21 Oct 2026 08:00:00 +0800</pubDate>

channel 里保留 atom:link rel="self" 指向 RSS 自身,防止订阅源被镜像站抓走改成它们的地址。

结构化数据与 OG

每篇博客文章页嵌 BlogPosting JSON-LD,首页嵌 Blog,配合完整的 OG 标签。关键原则:og:url 与 canonical 保持同一个值,否则搜索引擎要在两个「官方地址」之间猜:

{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "headline": "静态博客 SEO 全流程",
  "datePublished": "2026-10-21",
  "author": { "@type": "Person", "name": "gjsvip" },
  "mainEntityOfPage": "https://www.520691.xyz/posts/static-blog-seo"
}

这些字段现在由 gen_posts.py 从 posts.json 自动生成,杜绝手写页面漏配——文章模板化的完整方案见工作台架构一文里的工程化思路。

收录提交

  • IndexNow:新文章发布后主动推送给接入的搜索引擎(key 文件托管各站根路径),当天可见收录——机制见三端同步架构记
  • Search Console:提交 sitemap,盯「网页编入索引」覆盖率,软 404 会在「已抓取 – 尚未编入索引」里现形
  • 内链:归档页、标签页、相关文章全部静态可达,保证爬虫三跳内到达任何文章

内容层面的 SEO

技术 SEO 之外,内容纪律同样影响收录。每篇只谈一个明确主题,标题含关键词但不堆砌;内链锚文本用描述性文字,不写「点击这里」。每篇文章的 description 是搜索结果里的免费广告位,把摘要写成「这篇解决什么问题」,而不是复述标题——标题党换来点击,换不回回访,搜索引擎的停留指标最终会惩罚它。归档页与标签页给每篇文章多个静态入口,配合文章间的相关链接,爬虫三跳内可以到达任何页面——对没有外链积累的新站,这是最廉价的抓取保障。

重复内容是静态博客的隐形杀手:www 与 apex、http 与 https 必须 301 归一。我们全部收拢到 https://www.520691.xyz,canonical、og:url、sitemap 三处口径一致,杜绝搜索引擎「精神分裂」。修订旧文章时,同步刷新它的 lastmod——搜索引擎对「声明更新但内容没动」的页面会逐渐失去信任。

结构化数据写完要用 Google Rich Results Test 验证:JSON-LD 有语法错误时是静默失效的,不测等于没写。收录本身以周计,个人站最需要的是耐心——把地基做对,然后继续写。

提交之后的观察

提交 sitemap 只是开始。每周看一次 Search Console 的覆盖率报告,三类信号各有含义:sitemap 报错是「文件坏了」,已抓取未索引是「质量存疑」,软 404 是「状态码错了」。我们的软 404 当初就是在这张表里现形的——根目录补上 404.html 后两周,「已抓取 – 尚未编入索引」的数量肉眼可见地下降。数据不会说谎,但它只会回答你真正在看的问题。

效果与复盘

这轮治理后:主域 sitemap 只含 12 篇文章 + 6 个静态页,每条 lastmod 可溯源;错路径统一 404;RSS 全部合法。SEO 没有黑魔法,把每个「诚实声明」做到位——状态码、日期、canonical——就是个人站点能做的最大的技术 SEO。