内容站快速扩量时怎么避免内容重复:在 Google 之前先发现自己的重复页

站点过几百篇之后,内容重复会悄悄把收录拖死。用脚本化流程在 Google 发现之前先把重复页揪出来——附真实的 embedding 成本和 Search Console 信号。

内容站的”重复”很少是两篇一模一样的文章。几乎都是两篇文章在打同一个意图:标题不同、措辞不同,但底层 query 一样。Google 挑一篇当 canonical,把另一篇降权。在快速扩量的站点上——尤其是用 AI 辅助批量出稿的站——只要没有一套能赶在 Googlebot 之前发现问题的脚本化流程,这种事每个月都会发生。

一句话结论

  • 重复分三种:完全相同、近重复、重复意图。最后一种人眼看不出来,伤害也最大。
  • 给每篇文章打上 primaryKeyword,两篇撞同一个关键词时直接让 prebuild 失败。
  • 近重复用 301 重定向合并(按 Google 的说法,这是强 canonical 信号),不要只靠 canonical 标签。
  • 用 embedding + cosine 相似度在发布前抓近重复。text-embedding-3-small 的价格是 每 100 万 token 0.02 美元(2026 年 6 月),扫 2000 篇也就几美分。
  • canonical 改动通常要 2 到 6 周 Google 才会认,所以清理不是立竿见影的。

三种重复,三种修法

类型是什么常见程度修法
完全相同同一篇发在两个 URL 上少见把弱的那个 301 掉
近重复同一篇被改写过AI 出稿下很常见把独特内容搬过去,再 301
重复意图不同文章打同一个 query最坏的——人眼看不出重新定角度(拆分)或把弱的那篇 noindex

过了大约 200 篇之后,这些都没法手工做。每种类型都有自己的检测信号和修法,所以必须自动化。

怎么判断自己有重复问题

  • 两篇文章在 Search Console 上对同一 query 反复抢位置。
  • Pages 报告里 Indexed 数明显低于 Submitted——干净站点上差距超过 5% 就值得查一下。
  • “Why pages aren’t indexed” 里出现 “Duplicate without user-selected canonical” 或 “Duplicate, Google chose different canonical”。前者表示 Google 发现了重复而你没指定偏好;后者表示 Google 推翻了你设的 canonical。
  • 两篇文章的 H1 去掉修饰语后讲的是同一件事。
  • sitemap 里的条数超过你独立主关键词的数量。

开始前准备

  • 这是一次 content-ops 清理,不是上线。预留 1 到 2 小时专注时间。
  • 先备份内容库。跑任何合并或重定向脚本之前,git status 必须干净。
  • 确认托管层支持 301 重定向:Astro 静态用 _redirects、Firebase Hosting 在 firebase.json 里写 redirects、或 Vercel 的 vercel.json

实操步骤

1. 给每篇文章加 primaryKeyword 字段

这是一个字符串,说明这篇文章到底服务什么。后面所有重复检查都以它为锚点。

---
title: "How to Submit a Sitemap to Search Console"
urlSlug: "submit-sitemap-search-console"
primaryKeyword: "submit sitemap search console"
category: "indie-dev"
---

2. 跑一份”重复关键词报告”

约 30 行的 Node 脚本扫一遍内容库,打出任何被两篇文章共享的 keyword:

// scripts/find-duplicate-keywords.mjs
import { readdirSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
import matter from 'gray-matter';

const ROOT = 'src/content/articles/zh';
const byKw = new Map();

for (const cat of readdirSync(ROOT)) {
  for (const file of readdirSync(join(ROOT, cat))) {
    if (!file.endsWith('.mdx')) continue;
    const { data } = matter(readFileSync(join(ROOT, cat, file), 'utf8'));
    const kw = (data.primaryKeyword || '').toLowerCase().trim();
    if (!kw) continue;
    if (!byKw.has(kw)) byKw.set(kw, []);
    byKw.get(kw).push(`${cat}/${file}`);
  }
}

for (const [kw, files] of byKw) {
  if (files.length > 1) console.log(`DUP "${kw}":\n  ${files.join('\n  ')}`);
}

挂到 npm run audit:content 里,让重复关键词直接卡 prebuild,而不是溜进生产环境。

3. 近重复用 301 合并

选权重高的那篇(Search Console 里看 impressions),把另一篇的独特段落搬过去,再加重定向。按 Google 的 canonicalization 文档,重定向是 canonical 信号——比 rel="canonical" 标签强,更比 sitemap 收录强得多。Firebase Hosting 写法:

{
  "hosting": {
    "redirects": [
      { "source": "/articles/scale-ai-content-safely",
        "destination": "/articles/scale-content-with-ai-safely",
        "type": 301 }
    ]
  }
}

Astro 静态 + Netlify 风格 _redirects 文件:

/articles/scale-ai-content-safely  /articles/scale-content-with-ai-safely  301

4. 重复意图:重新定角度或 noindex

要么拆角度——一篇写新手、一篇写进阶,改 H1 和 primaryKeyword,让两篇真正打不同的 query;要么把弱的那篇标 draft: true,meta 加 noindex。文章布局里写:

{frontmatter.noindex && <meta name="robots" content="noindex,follow" />}

noindex,follow(不是 noindex,nofollow),让这个页面留在索引之外的同时仍然传递链接信号。

5. 全站默认设 self-canonical

所有页面先自指 canonical,只在你确定目标更强时才跨页指向。Astro 布局里:

<link rel="canonical" href={`${Astro.site}${Astro.url.pathname}`} />

千万别用 robots.txt 或 URL 移除工具来”修”重复——Google 文档明确反对这两种做法。被 robots 屏蔽的 URL 仍可能在没有内容的情况下被收录,而移除工具会把一个 URL 的所有版本都从 Search 里藏掉。

6. AI 批量出稿前过一遍相似度检查

title + 首段跑一遍 cosine 相似度(用 OpenAI embedding),能在发布前抓出大部分近重复。截至 2026 年 6 月,text-embedding-3-small每 100 万输入 token 0.02 美元(用 Batch API 是 0.01),1536 维,8192 token 上下文窗口。扫一个 2000 篇的内容库也就几美分,没理由手工做。

// scripts/similarity-check.mjs(节选)
import OpenAI from 'openai';
const client = new OpenAI();

async function embed(text) {
  const r = await client.embeddings.create({
    model: 'text-embedding-3-small',
    input: text,
  });
  return r.data[0].embedding;
}

function cosine(a, b) {
  let dot = 0, na = 0, nb = 0;
  for (let i = 0; i < a.length; i++) {
    dot += a[i] * b[i];
    na += a[i] * a[i];
    nb += b[i] * b[i];
  }
  return dot / (Math.sqrt(na) * Math.sqrt(nb));
}

// cosine > 0.85 的对,标记为人工复核。

如果想让相近主题之间的区分更锐利,更大的模型成本更高,但对这个场景几乎不会改变判断:

模型(2026 年 6 月)价格 / 100 万 token维度备注
text-embedding-3-small$0.021,536默认;最便宜,去重够用
text-embedding-3-large$0.133,072更细腻,但贵 6.5 倍
gemini-embedding-001$0.15最高 3,072支持 Matryoshka 截断;官方推荐 768 维为甜点

做去重,3-small 基本永远是对的选择:阈值比模型重要得多。

7. 清理上线后,让 Google 重新校验

用 URL Inspection 检查被合并的 URL,确认它返回 301,再对存活的那个 URL 点 “Request indexing”。批量重定向后重新提交 sitemap。预期大约 2 到 6 周 Google 才会认这个 canonical 改动,具体取决于你的站被抓取的频率。

执行检查清单

  • 每篇文章都有 primaryKeyword;audit 脚本在 prebuild 阶段标记重复。
  • 301 重定向写在 firebase.json / vercel.json / _redirects,不是只在文章正文里说说。
  • 默认全站 self-canonical;跨页 canonical 是 per-article 显式开启。
  • 相似度检查接进 AI 内容流水线里,不是手动跑。

上线后验证

  • 用 Search Console URL Inspection 重抓被合并的 URL,确认返回码是 301、目标是主 canonical URL。
  • 2 到 4 周后再看 Pages 报告:“Duplicate” 类原因数应该下降。
  • 确认 sitemap 里不再列被合并掉的 URL(grep 一下 build 输出)。

容易踩的坑

  • 相信”标题不同 = 文章不同”。 意图比措辞重要得多。征兆是两篇文章在 Search Console 里对同一 query 互抢曝光。
  • 用 canonical 标签”掩盖”重复但不真正解决。 Google 不认同你的 canonical 时会推翻它——这正是 Pages 报告里的 “Google chose different canonical” 状态。301 更强,因为它直接把重复页消掉了。
  • 生成”10 best X for [职业]“这种各版本 90% 相似的页面。 这种模式会被读成规模化的低价值内容,可能把整个 cluster 一起拖下去。
  • 把去重当一次性清理。 每批稿子都会新长出重复——把检查接进 prebuild。
  • 301 到一个本身也 301 的 URL。 链式重定向会损耗信号;永远只跳一次,直接跳到最终 canonical。
  • 合并后忘了从 sitemap 移除老 URL。 Google 会一直抓、一直再次标记它。

FAQ

  • 同一篇文章的中英文版本算重复吗?: 不算,前提是用 hreflang 配对。EN 和 ZH 是两个 URL,服务两类受众。两边都要用 <link rel="alternate" hreflang> 标签互指。
  • Google 会因为重复扣分吗?: 大多数情况下不会有 manual action,但弱的那篇会被压制,重复比例一高,站级质量信号也会受影响。
  • 直接 noindex 重复页不行吗?: 可以,但浪费了写作精力。301 合并能保留链接权重;只在没东西可合的时候才用 noindex,follow
  • 怎么大规模检测近重复?: embedding + 对 title + 首段跑 cosine 相似度,效果很好。text-embedding-3-small 每 100 万 token 0.02 美元,全库扫一遍便宜到可以忽略。
  • 相似度脚本阈值设多少?: 人工复核线设 0.85,CI 自动阻断线设 0.92。如果总在相近但确实不同的题上误报,就把复核线往下调。
  • Google 多久才会认 canonical 改动?: 通常 2 到 6 周,取决于抓取频率和站点规模。重新提交 sitemap 加请求索引能加速,但不保证当周就重抓。

相关阅读

外部参考:Google Search Central — Consolidate duplicate URLsOpenAI embeddings 定价

标签: #独立开发 #内容运营 #SEO #建站策划 #Canonical #Technical SEO