我最早做网站体检,是拿着一份三十多项的清单挨个勾。结果很尴尬:每次体检都能查出十几个"问题",按清单修完,流量一点没动。后来我才想明白,那些清单里的项目大多来自别人的站点结构和别人的业务模型,原样套到我的站上,修的是"清单要求",不是"我的站需要的"。
这篇写的是我自己改过五轮之后稳定下来的体检方法:不追求项目多,只保留六项能指向具体动作的检查,而且每一项都能在十分钟内做完、拿到一个可比较的数字。方法适用于自己写的 CMS、静态站、以及 WordPress/Typecho 这类常见程序。
先定一个原则:体检要产出动作,不产出评分
很多站长体检工具会给你一个 0~100 的分。分数很好看,但它是别人加权出来的,跟你站上真实存在的问题不一定相关。我自己的经验是:一个"体检项"如果不满足下面三条中的两条,就不该进清单。
- 它指向一个具体的修改动作(改哪一行、加哪个文件、动哪个配置)。
- 它有一个可复现的判断阈值(比如"内页 HTML 超过 120KB")。
- 它的结果能写进日志对比,下次体检可以看趋势。
按这个标准砍下来,剩下的六项是:抓取健康、收录覆盖、模板冗余、页面体积、内链结构、以及作弊式优化自查。最后一项听起来奇怪,但它是防止你为了短期排名埋雷的。
第一项:抓取健康——先确认爬虫看得见你的每一页
体检的起点不是 SEO 工具,是 Nginx 的 access log。搜索引擎的抓取行为在日志里是最真实的证据:谁来了、要了什么、拿到了什么状态码。
# 最近一天各爬虫的请求量与状态码分布
awk '$0 ~ /Googlebot|bingbot|Baiduspider/ {
match($0, /"(GET|HEAD|POST) [^"]+"/); req=substr($0,RSTART,RLENGTH);
split(req,a," "); url=a[2];
status=$9;
print status, url
}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -30要看的不是"来了多少次",而是三个比例:
非 200 比例。如果爬虫请求里 404/403/500 占到 10% 以上,说明站点里有大量坏链接在消耗抓取预算。403 尤其常见——很多站为了防采集,把 UA 里带 bot 的请求全拦了,顺手把搜索引擎也拦了。
重复请求比例。同一个 URL 一天被请求几十次,通常是站点没有做好规范化:带 ?from=、?ref= 的链接被到处引用,每个变体都被当成新页面抓。
深度分布。如果爬虫只抓首页和分类页,几乎不进内页,问题通常在内链——详情页只有 sitemap 里的入口,站内没有任何可点击的路径到达。
这一步做完,你应该能说出"我的站有多少页被爬虫访问过、其中多少是失败的"。这个数字是后面所有工作的基线。
第二项:收录覆盖——区分"没被发现"和"被发现但没收录"
收录是最容易被误读的指标。站长后台显示"已收录 320 页",你可能有一千篇文章,于是觉得是"收录率低"。但真正该拆开看的是三种状态:
| 状态 | 判断依据 | 动作方向 |
|---|---|---|
| 未发现 | 日志里爬虫从没请求过该 URL | 补内链、加 sitemap 入口 |
| 已发现未收录 | 爬虫来过,返回 200,但索引里没有 | 内容质量/重复度问题,不是技术问题 |
| 已收录未展现 | 索引中有,搜索该标题找不到 | 标题与意图不匹配,或竞争太强 |
这三种的修法完全不同,混在一起看只会得出"收录率 30%"这种没用的结论。我的做法是从日志里抽出最近 14 天爬虫访问过的 URL 集合,跟 sitemap 里的 URL 集合做差集:
grep -h 'Googlebot' /var/log/nginx/access.log* \
| grep -oE 'GET [^ ?]+' | awk '{print $2}' | sort -u > /tmp/crawled.txt
grep -oE '<loc>[^<]+' /var/www/site/sitemap.xml \
| sed 's#<loc>https\?://[^/]*##' | sort -u > /tmp/insitemap.txt
comm -23 /tmp/insitemap.txt /tmp/crawled.txt | head -40 # 在 sitemap 里但从未被抓
comm -13 /tmp/insitemap.txt /tmp/crawled.txt | head -40 # 被抓但不在 sitemap第一条输出就是"未发现"的候选清单。通常能一次找出一批老文章——它们只在首页分页里出现过一次,早就沉到底了。给它们补一条内链(相关推荐、归档页、标签页),比反复提交 sitemap 有用得多。
第三项:模板冗余——你的每一页都在重复同样的 40KB
这一项最容易被忽略,因为它在页面上看不出来。做法很简单:取一篇文章页,把正文抽掉,剩下的就是模板体积。
curl -s https://www.example.com/post/123.html -o /tmp/p.html
wc -c /tmp/p.html
# 正文大概占比多少?用 sed 去掉常见容器后对比
python3 - <<'EOF'
import re,io
s=io.open('/tmp/p.html',encoding='utf-8').read()
body=re.sub(r'(?s)<script.*?</script>','',s)
body=re.sub(r'(?s)<style.*?</style>','',s)
print('total',len(s),'no-js/css',len(body))
EOF如果一篇文章总 180KB,去掉 JS/CSS 还有 90KB,而正文只有 8KB,那 82KB 全是模板:导航、侧栏、热门文章列表、版权、各种 inline 样式。它对 SEO 的直接伤害有限,但对抓取效率和渲染速度的伤害很大,而且它会稀释正文的权重占比。
我当时的做法是三步:把侧栏"热门文章"从 20 条砍到 8 条;把每个页面都重复输出一遍的站内搜索框、分享按钮改成一次加载;把 inline 的 CSS 合并进一个文件并加缓存头。三步之后单页从 180KB 降到 62KB,服务器带宽账单也跟着降了。
第四项:页面体积与关键资源数
这一项跟性能重叠,但体检时我关心的是"数得清的数字",不是分数。取三页(首页、分类页、文章页)各跑一次:
for u in / /category/tech/ /post/123.html; do
echo "== $u"
curl -s -o /tmp/x.html -w 'html=%{size_download} ttfb=%{time_starttransfer}\n' \
"https://www.example.com$u?_=$(date +%s)"
grep -c '<script' /tmp/x.html
grep -c '<link rel="stylesheet"' /tmp/x.html
done我的自查阈值:HTML 本身不超过 100KB(压缩前),同步阻塞脚本为 0,外链样式表不超过 3 个,图片总数不超过 40 张。超了就要问一句"这一条真的必要吗"。
特别提醒的一点:广告位和统计代码是模板膨胀的最大来源。一个广告联盟的脚本很容易带进来 300KB 的依赖,而且经常是同步加载。上线前用 DevTools 的 Coverage 面板看一次未使用的代码比例,超过 60% 就该考虑换加载方式。
第五项:内链结构——不是"有没有链",是"链到哪"
内链体检我看两个指标,都能用一条 SQL 或一次脚本查出来。
孤岛页比例。站内没有任何页面链接指向它、只有 sitemap 提到的页面。比例超过 10% 就偏高。
入链集中度。如果首页拿走了 80% 的内链,其余页面各自只有一两条,那你的权重传递是严重偏斜的。健康的分布应该是分类页和内页之间形成若干簇。
-- 简易版:统计每篇文章被内链引用的次数(假设正文存 links 字段或另建表)
SELECT cid, title, inbound
FROM (
SELECT p.cid, p.title,
(SELECT COUNT(*) FROM post_links l WHERE l.target_cid = p.cid) AS inbound
FROM posts p
) t
ORDER BY inbound ASC
LIMIT 50;输出的前 50 条就是"最孤立的页面"。它们往往也是流量最差的页面——这两件事经常互为因果,但方向是内链不足导致收录差,而不是内容差。给它们加两三条来自强页面的上下文链接,比重写内容见效快。
第六项:自查作弊式优化,别给自己埋雷
这一项是我在吃过一次亏之后加进来的。所谓作弊式优化,包括但不限于:隐藏文字(白色文字铺关键词)、给爬虫和用户返回不同内容(cloaking)、关键词堆砌的 title、大量无意义的目录页、以及用 JS 把正文渲染出来而 HTML 里空空如也。
自查方式:用 curl 拿到的 HTML 和浏览器渲染后的 DOM 做对比。
curl -s "https://www.example.com/post/123.html" | sed 's/<[^>]*>//g' | wc -c
# 再在浏览器 Console 里执行
document.body.innerText.length如果 curl 拿到 800 字节、浏览器里是 12000 字节,说明正文完全靠 JS 渲染。对现代搜索引擎不算致命,但对中文站尤其是百度,抓取成功率会明显下降。同理,检查 CSS 里有没有 color:#fff 配合白色背景的文字段落——这类东西往往是从别人的模板里抄过来的。
还有一条容易被忽略:title 和 H1 是否一致。如果 H1 是"服务器运维教程",title 却是"服务器运维教程_运维教程_服务器_网站运维_技术分享",那就是典型堆砌,用户看一眼就关掉,点击率会低得离谱。
把这六项做成一张表,每季度跑一次
体检的价值在于对比。我做了一张固定格式的表,每次填完存档:
| 项目 | 指标 | 本期 | 上期 |
|---|---|---|---|
| 抓取健康 | 非 200 比例 | 4.2% | 11.6% |
| 收录覆盖 | sitemap 未抓取页数 | 37 | 142 |
| 模板冗余 | 单页 HTML 体积 | 62KB | 180KB |
| 资源 | 同步脚本数 | 0 | 4 |
| 内链 | 孤岛页比例 | 6% | 18% |
| 自查 | JS 渲染正文 | 否 | 是 |
看到这张表就明白了:真正带来变化的不是"修了 40 个问题",而是这四个数字。第一轮改造之后,抓取请求量涨了不到 20%,但有效抓取(200 状态)翻了一倍多,新文章的收录周期从三周降到了四五天。
体检时最容易做错的三件事
把别人的清单当标准。有人的站是电商,有人的站是内容站,体检项完全不同。内容站该关心的是"每一页有没有被至少三条内链指向",电商站该关心的是"筛选参数有没有造成重复页面"。抄清单之前先问:我这个站靠什么吃饭。
在没备案量的情况下追长尾。如果你只有五十篇文章,去追几千个长尾关键词,结果是每个页面都很薄。这个阶段该做的是把五十篇写到能打的水平,而不是铺一百个目录页。
改完不复查。这是最要命的一条。改了模板、换了内链、动了 sitemap,两周内必须复查一次抓取日志和收录数。没有复查的改动,等于没有做——你不知道它是有效、无效,还是反向。
体检记录怎么存:一个目录,四个文件
我早期把体检结果散落在笔记、截图、聊天记录里,半年后想问"上次改模板是哪天、改之前体积多少",翻了二十分钟没找到。后来改成固定结构:/root/site-audit/ 下按日期建目录,每次体检只允许产出四个文件——crawled.txt(爬虫访问过的 URL)、insitemap.txt(sitemap 里的 URL)、pagesize.csv(三页的体积与资源数)、notes.md(这次改了什么、下一步做什么)。
这样做的好处是下次体检可以直接 diff。比如想知道上个月做的改动有没有效果,diff -r audit/2026-06 audit/2026-09 一眼就能看到 crawled 集合多了哪些页面。比起凭记忆复盘,这个方式可靠得多,也更省时间。四个文件格式固定之后,还能写个小脚本把它们汇总成一张趋势表。
小结
体检这件事,做多了会发现它不是"技术检查",而是"自我纠偏"。站点做久了必然积累:过期的链接、膨胀的模板、只在某一页出现的功能、忘了删的测试文件。定期用同一套数字照一遍镜子,比任何工具评分都更能说明你的站在往哪个方向走。
我的建议是:这六项每季度跑一次,每次不超过两小时,填进同一张表。一年四次之后,你会对自己的站有完全不同的认识——不是"感觉还行",而是"我知道它在哪个环节漏气"。