用 AI 做站点 QA:checklist 驱动的小毛病排查流程

用真实 checklist 抓站点小毛病:可粘贴的 AI prompt、shell 验证脚本、CI 闸门让关键问题挂构建。

站点 bug 大多不刺激——缺 alt、内链断了、200 字的页面根本不该发出去。给 AI 一个真实 checklist 并交叉验证,它在这件事上极强。下面是 prompt 和验证脚本。

问题背景

站点 QA 没人愿意做,所以总被跳过。让 AI Agent 按既定 checklist 读你的构建产物,10 分钟能扫完 200 页,比人工 review 抓得还全。关键是 checklist 要具体:“找出 400 字以下的页面”是好任务,“帮我审站点”不是。

判断标准

  • 60+ 天没做过完整站点检查。
  • 最近改过路由、重命名了 slug、迁移过内容。
  • Search Console 报告 coverage 问题增多。
  • 最近加了一批新页面,怀疑有些带 bug 上线了。

快速结论

build、指 AI 看 dist/、问六个窄问题、shell 抽查、分批修。

开始前准备

  • 本地 dist/ 已 build。
  • Codex / Claude Code 能读文件。
  • greplinkinatorxmllintjq 装好。

实操步骤

  1. 本地 build:
npm run build
ls dist/   # 确认页面在
  1. 死链 QA。Prompt:
[CONTEXT] 构建产物在 dist/(Astro 静态)。内部链接形如 /en/articles/<slug>/ 或 /zh/articles/<slug>/。
[TASK] 列出 dist/**/*.html 里所有 href 指向 dist/ 中没有对应 index.html 的内部链接。
输出:file, broken_href

shell 验证(真理来源):

# 活 URL 集合
find dist -name 'index.html' | sed 's|dist||;s|/index.html|/|' | sort > /tmp/live-urls.txt
# 每页用到的内链
grep -RhoE 'href="(/[a-z]+/articles/[a-z0-9-]+/)"' dist | sed 's/href="//;s/"//' \
  | sort -u > /tmp/used-urls.txt
# 用到的 - 活的 = 死链
comm -23 /tmp/used-urls.txt /tmp/live-urls.txt | head
  1. 缺 alt。Prompt:
[TASK] dist/**/*.html 里列出无 alt 或 alt="" 的 <img>。
输出:file, line_excerpt

验证:

grep -RHn '<img[^>]*>' dist | grep -v 'alt="[^"]\+"' | head
  1. 薄页。Prompt:
[TASK] dist/**/index.html 每页提取可见正文(剥掉 nav/header/footer/scripts)并计数字数。
列出正文字数 < 400 的页面。
输出:file, word_count
  1. 孤儿检测。Prompt:
[TASK] dist/ 里每篇文章页,统计其它页面中指向它的内链数量。
列出 0 入链的页面(孤儿)。
输出:file, incoming_count

验证:

# 从未被链作目标的页面
for url in $(cat /tmp/live-urls.txt); do
  count=$(grep -RlE "href=\"$url\"" dist | grep -v "dist$url" | wc -l)
  [ "$count" -eq 0 ] && echo "ORPHAN: $url"
done | head
  1. title sanity。Prompt:
[TASK] dist/**/*.html 列出 <title>:
  - 缺失或空
  - > 65 字符
  - 跨页面重复
输出:file, issue, title_text
  1. 源文件 frontmatter 一致性。 10 行脚本:
// scripts/frontmatter-consistency.mjs
import { readdirSync, readFileSync } from 'node:fs';
import matter from 'gray-matter';
const REQUIRED = ['title', 'description', 'urlSlug', 'category', 'tags',
                  'publishedAt', 'lang', 'translationKey'];
for (const lang of ['en', 'zh']) {
  for (const cat of readdirSync(`src/content/articles/${lang}`)) {
    for (const f of readdirSync(`src/content/articles/${lang}/${cat}`)) {
      if (!f.endsWith('.mdx')) continue;
      const { data } = matter(readFileSync(`src/content/articles/${lang}/${cat}/${f}`, 'utf8'));
      const missing = REQUIRED.filter((k) => data[k] === undefined || data[k] === '');
      if (missing.length) console.log(`${lang}/${cat}/${f}: 缺 ${missing.join(',')}`);
    }
  }
}
  1. 按类别开 issue。 把关键项接到 CI 闸门:
# .github/workflows/qa.yml(节选)
- name: QA gates
  run: |
    node scripts/frontmatter-consistency.mjs    # 永远跑
    npx linkinator dist --skip 'http' --silent  # 内链闸门
    node scripts/audit-pillars.mjs              # 孤儿闸门

执行检查清单

  • AI prompt 都指向 dist/,每个一类问题。
  • 6 类里至少 3 类有 shell 验证。
  • frontmatter 一致性接 CI。
  • 内链闸门:新出现的死链直接挂构建。
  • issue 按类别开,不按文件。

上线后验证

  • 修完后重跑每个 prompt 返回 0(或近 0)。
  • 4-8 周后 Search Console coverage 问题下降。
  • 抽样 Lighthouse SEO + Accessibility 都 100。

容易踩的坑

  • 让 AI 看源码而不是构建产物。很多 bug 渲染后才出现:null frontmatter 导致 meta 为空、:key 插值断了等等。
  • 相信 AI 一句”看起来没问题”。一定让它出明确列表,没列表就没法验证。
  • 改完不记账。一个月后会重犯。
  • 跳过孤儿检测。重构后特别容易出孤儿,悄悄拖排名。
  • 只看字数判质量。200 字能答清问题的页面也行,字数标记是起点不是结论。

FAQ

  • 能放进 CI 自动化吗: 可以。写脚本输出列表,关键类别(内部死链、缺 canonical)直接 fail build。AI 适合第一遍,定型之后就用代码固化。
  • 外链失效呢: 用专门的工具(如 lychee、linkinator),AI 在这上面又慢又费。
  • 多久做一次完整 QA: 活跃站每月一次,否则每季度。每次大改后必做。
  • 缺 alt 真的影响排名吗: 间接影响——无障碍和图片搜索受损。要修但不必慌。
  • AI 数到 23 条死链、我的验证脚本数到 18 条,信谁?: 永远信脚本。AI 列表用于探索,脚本用于闸门。

相关阅读

标签: #独立开发 #AI 辅助建站 #工作流 #Technical SEO