跳到主要内容
IM智引科技

研究 / 外贸与 B2B 增长

AI Skill:Cannibalization 诊断——同站竞争页面识别

注册表审计查的是规划层面的冲突,Cannibalization 诊断查的是已发布内容的实际竞争。这个 Skill 用 GSC 数据找出同一查询下多个页面轮流排名的证据,再用页面正文比对确认原因,最后给出合并、差异化或降权的处置决策。

BLKTECH 编辑部2026年8月4日13 分钟难度 实战免费Node.jsGoogle Search ConsoleAI Agent

Cannibalization 的确凿证据来自 GSC:同一 query 下有两个以上 page 有曝光,且排名互相波动。脚本从 GSC 导出数据聚合出候选组,模型比对页面正文找出重叠原因,输出三种处置决策:合并(301)、差异化(改 PKW/NKW)、降权(加 noindex 或调整内链)。

AI Skill:Cannibalization 诊断——同站竞争页面识别

与注册表审计的区别

Skill 检查对象 数据来源 发现的问题
注册表审计(第45篇) 规划层面 registry.json 计划中的冲突(还没发生)
Cannibalization 诊断(本篇) 已发布内容 GSC 实际数据 正在发生的竞争

注册表审计是预防,Cannibalization 诊断是治疗。已经上线的页面即使注册表配置正确,也可能因为内容写偏而产生实际竞争。


确凿证据:GSC 的 query × page 交叉数据

判断 Cannibalization 不能靠猜。唯一可靠的证据是 GSC 的查询-页面对应关系。

Cannibalization 的三个信号(需同时满足)

  1. 同一 query 下有 ≥2 个 page 产生曝光
  2. 这些页面的平均排名都在 5–30 之间(都没排到最前,也都不是完全没戏)
  3. 排名在时间序列上互相波动(这周 A 页排 8,下周 B 页排 12 而 A 掉到 20)

只满足第1条不是问题——大站正常情况下一个词也会有多个页面有零星曝光。三条同时满足才是真的自相残杀。

从 GSC 导出数据

GSC → Performance → Search results → 导出

需要的维度组合:Query + Page,时间范围至少3个月。

导出的 CSV 结构:

Query,Page,Clicks,Impressions,CTR,Position
centrifugal pump manufacturer,/products/centrifugal-pumps/,45,1200,3.75%,8.2
centrifugal pump manufacturer,/about/,3,340,0.88%,14.6

Skill 说明书

# Skill:Cannibalization 诊断

## 何时使用
- 某个重要关键词排名长期停滞在第2–3页
- 定期(每季度)全站诊断
- 发现 GSC 里同一 query 有多个页面曝光

## 输入
- GSC 导出的 Query + Page CSV(必需,至少3个月数据)
- 可选:站点页面正文(用于分析重叠原因)
- 可选:registry.json(用于验证是否与规划一致)

## 执行步骤

### Step 1:运行确定性脚本
执行 `scripts/cannibalization-detect.mjs`,获得候选冲突组。
脚本只做聚合和阈值筛选,不做判断。

### Step 2:逐组分析(你来判断)

对每个候选组,按以下顺序判断:

**判断 A:是否真的是 Cannibalization**
排除以下假阳性:
- 主页面排名稳定在 Top 3,另一页面只有零星曝光 → 不是问题
- 两个页面的意图确实不同(一个 commercial 一个 informational),
  Google 只是暂时分辨不清 → 观察,不急处理
- 其中一个页面是分页(/page/2/)或筛选页 → 技术问题,不是内容竞争

**判断 B:确认竞争原因(需读页面正文)**
读两个页面的 H1、H2 和前 500 字,找出重叠:
- 两个页面的 H1 是否含同一核心词
- 弱势页面是否在正文大量使用了强势页面的 PKW
- 弱势页面的 NKW 是否遗漏了强势页面的 PKW

**判断 C:给出处置决策(三选一)**

| 决策 | 适用条件 | 具体动作 |
|------|----------|----------|
| 合并 | 两页内容高度重叠,业务上没必要都存在 | 弱势页 301 → 强势页,合并有价值的内容段落 |
| 差异化 | 两页都有存在价值,只是意图写偏 | 修改弱势页的 PKW 和 H1,NKW 加入强势页 PKW,重写偏离的段落 |
| 降权 | 弱势页必须存在(如 About 页)但不该排这个词 | NKW 加入该词,从正文移除该词的高频出现,减少指向它的内链锚文本 |

### Step 3:输出报告

## 输出格式

Cannibalization 诊断报告

数据区间:[YYYY-MM-DD] 至 [YYYY-MM-DD] 检出候选组:[N] 确认冲突:[N] 假阳性排除:[N]

确认冲突(按业务影响排序)

C1. query: centrifugal pump manufacturer

月曝光合计:1,540 当前最佳排名:8.2

页面 曝光 点击 平均排名 排名波动
/products/centrifugal-pumps/ 1,200 45 8.2 6–14
/about/ 340 3 14.6 11–22

竞争原因: /about/ 页面正文出现 “centrifugal pump manufacturer” 5 次, H2 使用了 “Leading Centrifugal Pump Manufacturer Since 2003”, 且注册表中 /about/ 的 NKW 未包含该词。

处置决策:降权 具体动作:

  1. /about/ 的 H2 改为 “Our Company History Since 2003”
  2. 正文中该词的出现从 5 次减到 1 次(仅在必要处保留)
  3. 注册表 /about/ 行的 NKW 加入 centrifugal pump manufacturer, centrifugal pump supplier
  4. 检查全站指向 /about/ 的内链锚文本, 把含该词的锚文本改为 “about us” 或 “our company”

预期效果:/products/centrifugal-pumps/ 排名从 8.2 提升到 5 以内

假阳性排除([N] 项)

F1. query: industrial pump specifications

  • /products/cp-100/(排名 4.1,曝光 800)
  • /products/cp-200/(排名 18.3,曝光 45)
  • 排除原因:CP-100 排名稳定 Top 5,CP-200 曝光量极低(5%), 属于正常的品牌内多型号覆盖,非竞争

## 禁止行为
- 不要在没有 GSC 数据的情况下"推测"Cannibalization
- 不要对假阳性给处置动作
- 不要建议直接删除页面(用 301 或 noindex,保留权重)

确定性脚本

// scripts/cannibalization-detect.mjs
import fs from 'fs/promises';
import { parse } from 'csv-parse/sync';

const csv = await fs.readFile('gsc-query-page.csv', 'utf8');
const rows = parse(csv, { columns: true, skip_empty_lines: true });

// 按 query 聚合
const byQuery = new Map();
for (const row of rows) {
  const query = row.Query;
  if (!byQuery.has(query)) byQuery.set(query, []);
  byQuery.get(query).push({
    page: row.Page,
    clicks: Number(row.Clicks),
    impressions: Number(row.Impressions),
    position: Number(row.Position),
  });
}

// 筛选候选冲突组
const THRESHOLD = {
  minPages: 2,           // 至少2个页面
  minImpressions: 100,   // query 总曝光至少 100(过滤长尾噪音)
  minPagePct: 0.10,      // 次要页面曝光占比至少 10%(过滤零星曝光)
  positionRange: [3, 35],// 排名在 3–35 之间(都没排到最前)
};

const candidates = [];

for (const [query, pages] of byQuery) {
  if (pages.length < THRESHOLD.minPages) continue;

  const totalImpressions = pages.reduce((s, p) => s + p.impressions, 0);
  if (totalImpressions < THRESHOLD.minImpressions) continue;

  // 按曝光排序
  pages.sort((a, b) => b.impressions - a.impressions);

  // 次要页面的曝光占比
  const secondary = pages[1];
  const secondaryPct = secondary.impressions / totalImpressions;
  if (secondaryPct < THRESHOLD.minPagePct) continue;

  // 所有页面排名都在指定区间内
  const inRange = pages.every(p =>
    p.position >= THRESHOLD.positionRange[0] &&
    p.position <= THRESHOLD.positionRange[1]
  );
  if (!inRange) continue;

  candidates.push({
    query,
    totalImpressions,
    totalClicks: pages.reduce((s, p) => s + p.clicks, 0),
    bestPosition: Math.min(...pages.map(p => p.position)),
    pages: pages.map(p => ({
      ...p,
      impressionShare: (p.impressions / totalImpressions * 100).toFixed(1) + '%',
    })),
  });
}

// 按业务影响排序(总曝光量)
candidates.sort((a, b) => b.totalImpressions - a.totalImpressions);

console.log(JSON.stringify({
  summary: {
    totalQueries: byQuery.size,
    candidateGroups: candidates.length,
    thresholds: THRESHOLD,
  },
  candidates,
}, null, 2));

阈值调整说明

脚本里的阈值是起点,需要按站点规模调整:

参数 小站(<100页) 中站(100–1000页) 说明
minImpressions 50 200 曝光门槛,过滤噪音
minPagePct 15% 10% 次要页面占比门槛
positionRange [3, 30] [3, 40] 大站长尾词排名分布更广

调整原则:先用宽松阈值跑一遍,看候选组数量。如果超过20组,说明阈值太松(人工处理不完),收紧;如果少于3组,可能太严,放宽。


处置后的验证

修复不是终点,要验证效果:

修复后的验证节奏:
- 第 1 周:确认技术改动生效(301 是否正确、noindex 是否生效)
- 第 2–4 周:GSC 观察 query 下的页面数是否减少
- 第 4–8 周:观察主页面排名是否提升
- 8 周后仍无改善 → 原因可能不是 Cannibalization,重新诊断

→ AI Skill:Pillar-Cluster 内链流审计——权重流动是否形成闭环

NEXT ACTION / 下一步

继续系列:AI 外贸站建设全系列

把读到的方法变成一个小行动,完成后再回来迭代。

继续

RELATED / 相关推荐

接着读这些

按同一分类、系列与标签为你挑选。