防止批量页面同质化的三个手段:数据层差异化(每个场景的 challenges/standards 必须真实不同)、提示词层强制引用具体数据(禁止通用描述)、生成后跑重复度检测(shingle 算法,任意两页相似度需 < 40%)。超标的页面重新生成或合并。
AI Skill:pSEO 场景页批量生成 Prompt 模板
批量生成的真实风险
第 29 篇给了完整的批量生成脚本。但脚本能跑通不代表页面能被收录。
最常见的失败模式:50 个页面生成出来,内容结构一样、论述方式一样,只是把 “chemical transfer” 换成 “water treatment”。Google 的 Helpful Content 系统会把这批页面整体判为低价值,结果是大量 Crawled - currently not indexed。
这篇解决的就是:如何让批量生成的页面各自有实质差异。
一、三层差异化机制
差异化不能只靠提示词,要从数据层就开始。
层一:数据层差异化(最根本)
第 28 篇设计的 applications.yaml,每个场景必须有真实不同的技术细节。
反面例子(会导致同质化):
- id: chemical_transfer
challenges:
- "需要耐腐蚀"
- "需要可靠密封"
- "需要符合标准"
- id: water_treatment
challenges:
- "需要耐腐蚀"
- "需要可靠密封"
- "需要符合标准"
这两组 challenges 实质相同,AI 生成的内容必然雷同。
正面例子:
- id: chemical_transfer
challenges:
- "Corrosion resistance across pH 1–13 media range"
- "Zero-leakage requirement for hazardous chemical containment"
- "ATEX Zone 1/2 compliance for explosive atmosphere"
keySelectionCriteria:
- parameter: "Casing Material"
recommendation: "SS316 (pH 2–12) / Hastelloy C-276 (strong acids) / PVDF (H₂SO₄ >70%)"
industryStandards: ["API 685", "NACE MR0175", "ATEX 2014/34/EU"]
- id: water_treatment
challenges:
- "High flow rates (50–500 m³/h) at relatively low head"
- "Energy efficiency for 24/7 continuous operation"
- "Chloramine resistance in disinfected water systems"
keySelectionCriteria:
- parameter: "Motor Efficiency"
recommendation: "IE3 minimum; IE4/IE5 for >4000 annual operating hours"
industryStandards: ["NSF/ANSI 61", "ISO 9906", "EN 733"]
数据层不同,生成的内容自然不同。数据准备的投入决定批量生成的质量上限。
层二:提示词层强制引用具体数据
在提示词里明确禁止通用描述,强制引用数据文件里的具体值。
层三:生成后重复度检测
用脚本量化检测,超标的重新生成。
二、分层提示词模板
按内容段落分层给约束,而不是一个笼统的“写一篇文章”。
# pSEO 场景页生成提示词模板
## 第一部分:注册表规格(不可违反的硬约束)
URL: {page_slug}
页面类型: cluster-app
搜索意图: engineering
PKW(H1 和 Title 必须包含): {product_name} for {application_name}
SKW(至少 2 个 H2 自然包含):
- {product_slug} {application_slug} selection
- best {product_slug} for {application_slug}
NKW(严禁出现,含语义等同表达):
manufacturer, supplier, OEM, buy, price, quote,
what is {product_slug}, how does pump work,
{其他场景的核心词,避免横向抢词}
目标地区: {target_locale}
## 第二部分:可用数据(必须全部用到,不得编造额外数据)
产品信息:
- 名称:{product.name}
- 核心优势:{product.keyAdvantages}
- 不适用场景:{product.notSuitableFor}
场景信息:
- 场景全称:{app.nameFull}
- 所属行业:{app.industry}
- 技术挑战(必须逐条展开,不得概括):
{app.challenges}
- 选型参数(必须做成 HTML 表格,逐行呈现):
{app.keySelectionCriteria}
- 行业标准(必须至少引用 2 个,标注在相关段落):
{app.industryStandards}
## 第三部分:分段写作指令
### 段落 1:场景挑战(100–150 词)
要求:
- 逐条展开上方 challenges 中的每一项
- 每条必须给出**为什么**这是挑战(工程原理层面),
不要只重述现象
- 严禁使用以下通用句式:
❌ "This application requires reliable pumps"
❌ "Quality is important in this industry"
❌ "Selecting the right pump is crucial"
- 必须包含至少 1 个具体数值(来自 challenges 或 criteria)
### 段落 2:为什么选此泵型(100–150 词)
要求:
- 结合 product.keyAdvantages 说明适配性
- 必须提及 product.notSuitableFor 中与本场景相关的限制,
并给出替代方案建议(这一点最容易被跳过,但它是
专业性的体现)
- 引用至少 1 个具体参数支撑论述
### 段落 3:选型标准表(HTML table)
要求:
- 使用原生 <table>,包含 <caption>
- caption 格式:Key Selection Criteria: {PKW}
- 三列:Parameter / Recommended Specification / Engineering Rationale
- 第三列必须解释**为什么**,不能重复第二列内容
- 逐行对应 keySelectionCriteria,不增不减
### 段落 4:合规要求(80–120 词)
要求:
- 按地区分别说明(欧洲 / 北美 / 全球标准)
- 每个标准必须给出编号和适用条件
- 不要只列标准名,要说明"什么情况下强制要求"
### 段落 5:推荐型号(卡片形式)
要求:
- 2–3 个型号,每个给出针对本场景的核心参数(不是全部参数)
- 每个型号说明 1–2 条针对本场景的优势
- 内链锚文本使用型号名
- 使用提供的型号列表:{recommended_models}
### 段落 6:FAQ(3–5 条)
要求:
- 每条用 ### 标题,疑问句
- 答案首句给结论 + 具体数值,且包含主体名称
(不用 it / this / 该产品 指代)
- 至少 2 条引用行业标准
- 每条答案 80–150 词
- 问题必须针对本场景的**具体技术疑问**,
不要问通用问题(如 "How do I choose a pump?")
## 第四部分:全局格式要求
- 所有参数给双单位:公制 (英制)
- 语言:{locale} 英语(美式或英式,按 target_locale)
- 禁用词:world-class, leading, best, top-quality,
cutting-edge, one-stop, professional manufacturer
- 不要写 About Us 式的公司介绍段落
- 不要在正文写商业 CTA(CTA 由模板统一处理)
## 第五部分:输出格式
只输出 Markdown 正文,不包含 frontmatter。
从段落 1 开始,不要写引言或总结性开场白。
三、重复度检测脚本
生成后必须量化检测。用 shingle(词组切片)算法计算任意两个页面的相似度。
// scripts/pseo-similarity.mjs
import fs from 'fs/promises';
import path from 'path';
const DIR = 'src/content/applications';
const SHINGLE_SIZE = 5; // 5 词一组
const THRESHOLD = 0.40; // 相似度上限 40%
// 提取正文(去掉 frontmatter 和 HTML 标签)
function extractText(md) {
return md
.replace(/^---[\s\S]*?---/, '') // 去 frontmatter
.replace(/<[^>]+>/g, ' ') // 去 HTML 标签
.replace(/[#*`\[\](/zh/)]/g, ' ') // 去 Markdown 符号
.replace(/\s+/g, ' ')
.toLowerCase()
.trim();
}
// 生成 shingle 集合
function shingles(text, size = SHINGLE_SIZE) {
const words = text.split(' ').filter(Boolean);
const set = new Set();
for (let i = 0; i <= words.length - size; i++) {
set.add(words.slice(i, i + size).join(' '));
}
return set;
}
// Jaccard 相似度
function jaccard(a, b) {
let intersection = 0;
for (const s of a) if (b.has(s)) intersection++;
const union = a.size + b.size - intersection;
return union === 0 ? 0 : intersection / union;
}
// 读取所有生成的页面
const files = (await fs.readdir(DIR)).filter(f => f.endsWith('.md'));
const docs = [];
for (const file of files) {
const md = await fs.readFile(path.join(DIR, file), 'utf8');
const text = extractText(md);
docs.push({
file,
wordCount: text.split(' ').length,
shingles: shingles(text),
});
}
// 两两比对
const pairs = [];
for (let i = 0; i < docs.length; i++) {
for (let j = i + 1; j < docs.length; j++) {
const sim = jaccard(docs[i].shingles, docs[j].shingles);
if (sim >= THRESHOLD) {
pairs.push({
fileA: docs[i].file,
fileB: docs[j].file,
similarity: (sim * 100).toFixed(1) + '%',
raw: sim,
});
}
}
}
pairs.sort((a, b) => b.raw - a.raw);
// 找出"高相似度中心"——与多个页面都相似的页面(最需要重写)
const offenderCount = new Map();
for (const p of pairs) {
offenderCount.set(p.fileA, (offenderCount.get(p.fileA) ?? 0) + 1);
offenderCount.set(p.fileB, (offenderCount.get(p.fileB) ?? 0) + 1);
}
const topOffenders = [...offenderCount.entries()]
.sort((a, b) => b[1] - a[1])
.slice(0, 10)
.map(([file, count]) => ({ file, similarPairCount: count }));
// 字数异常检测
const wordCounts = docs.map(d => d.wordCount);
const avgWords = wordCounts.reduce((a, b) => a + b, 0) / wordCounts.length;
const tooShort = docs
.filter(d => d.wordCount < avgWords * 0.6)
.map(d => ({ file: d.file, wordCount: d.wordCount }));
console.log(JSON.stringify({
summary: {
totalPages: docs.length,
avgWordCount: Math.round(avgWords),
overThresholdPairs: pairs.length,
threshold: (THRESHOLD * 100) + '%',
verdict: pairs.length === 0 ? 'PASS' : 'NEEDS_REWRITE',
},
// 需要优先重写的页面
topOffenders,
// 具体的高相似对
similarPairs: pairs.slice(0, 30),
// 内容偏薄的页面
tooShort,
}, null, 2));
process.exit(pairs.length > 0 ? 1 : 0);
阈值说明
| 相似度 | 判定 | 处理 |
|---|---|---|
| < 30% | 正常 | 通过 |
| 30–40% | 偏高但可接受 | 观察,看 GSC 收录情况 |
| 40–60% | 超标 | 重写相似度最高的一方 |
| > 60% | 严重 | 考虑合并成一个页面 |
为什么用 40% 作为门槛:同结构页面必然有一定重复(表格表头、FAQ 问句模式),30% 以下几乎不可能达到。40% 是“结构重复但内容有实质差异”的合理区间。
四、Skill 说明书
# Skill:pSEO 场景页批量生成
## 何时使用
- 批量生成应用场景页 / 参数组合页
- 已有一批同结构页面需要检测同质化
## 前置条件(必须先确认)
1. `src/data/applications.yaml` 中每个场景的 challenges、
keySelectionCriteria、industryStandards 都是真实不同的内容
→ 如果多个场景的这些字段实质相同,先补全数据再生成
2. `combinations.yaml` 已过滤无意义组合
3. 注册表已为每个待生成页面添加对应行
## 执行步骤
### Step 1:数据层预检(必须,不可跳过)
执行 `scripts/pseo-data-check.mjs`
检查每个场景的 challenges 字段两两相似度。
如果两个场景的 challenges 相似度 > 50%,
说明数据准备不充分——**先补数据,不要开始生成**。
### Step 2:批量生成
执行第 29 篇的 `scripts/generate-pseo-pages.mjs`,
使用本篇的分层提示词模板。
建议分批:每批 10 个页面,跑完检测再跑下一批。
一次跑 50 个,如果提示词有问题,50 个都要重做。
### Step 3:重复度检测
执行 `scripts/pseo-similarity.mjs`
- verdict = PASS → 进入 Step 4
- verdict = NEEDS_REWRITE → 对 topOffenders 中的页面
重新生成,并在提示词里追加:
"以下段落与其他页面高度重复,重写时必须使用
{场景名} 特有的技术细节,禁止使用通用论述:[粘贴重复段落]"
### Step 4:人工抽查(10%)
随机抽 10% 的页面,检查:
□ challenges 展开是否有实质内容(不是重述现象)
□ notSuitableFor 的限制是否提到了
□ 选型表第三列是否解释了"为什么"
□ FAQ 是否针对本场景的具体疑问
□ 行业标准引用是否准确(这一项最容易出错,
AI 可能编造标准编号——必须核实)
### Step 5:NKW 校验
执行 `scripts/nkw-check.mjs`(第 45 篇的变体),
检查生成内容是否含 NKW。
## 输出格式
pSEO 批量生成报告
批次:[N] 个页面 数据层预检:[通过/不通过] 平均字数:[N] 重复度检测:[PASS/NEEDS_REWRITE]
数据层预检结果
场景数据相似度最高的组合:
- chemical_transfer × solvent_transfer:42%(可接受)
- water_treatment × wastewater:61%(⚠️ 需补充差异化数据)
重复度检测
超标页面对([N] 对):
| 页面 A | 页面 B | 相似度 |
|---|---|---|
| centrifugal-pump-water-treatment.md | centrifugal-pump-wastewater.md | 58.3% |
优先重写(与多页相似):
| 页面 | 相似对数 |
|---|---|
| centrifugal-pump-hvac.md | 4 |
人工抽查结果
抽查 [N] 篇,发现问题:
- centrifugal-pump-mining.md:引用了 “ISO 5199-3”, 实际不存在该分册 → 需修正
- centrifugal-pump-food.md:未提及 notSuitableFor 限制
待处理
□ 补充 wastewater 场景的差异化数据 □ 重写 4 篇高相似页面 □ 修正 1 处标准编号错误
## 禁止行为
- 数据层预检不通过时,不要开始生成
- 不要跳过标准引用的准确性核实(AI 会编造标准编号)
- 不要一次生成超过 10 个页面
- 重复度超标的页面不要靠"改几个词"应付,要重新生成
五、数据层预检脚本
// scripts/pseo-data-check.mjs
import fs from 'fs/promises';
import yaml from 'js-yaml';
const apps = yaml.load(
await fs.readFile('src/data/applications.yaml', 'utf8')
);
// 把场景的关键文本字段拼成一个字符串
function fingerprint(app) {
return [
...(app.challenges ?? []),
...(app.keySelectionCriteria ?? []).map(c =>
`${c.parameter} ${c.recommendation}`
),
...(app.industryStandards ?? []),
].join(' ').toLowerCase();
}
function tokenSet(text) {
return new Set(
text.replace(/[^a-z0-9\s]/g, ' ').split(/\s+/).filter(w => w.length > 3)
);
}
function jaccard(a, b) {
let inter = 0;
for (const t of a) if (b.has(t)) inter++;
return inter / (a.size + b.size - inter);
}
const prints = apps.map(a => ({
id: a.id,
name: a.name,
tokens: tokenSet(fingerprint(a)),
challengeCount: (a.challenges ?? []).length,
criteriaCount: (a.keySelectionCriteria ?? []).length,
standardCount: (a.industryStandards ?? []).length,
}));
// 数据完整性检查
const incomplete = prints.filter(p =>
p.challengeCount < 3 || p.criteriaCount < 3 || p.standardCount < 2
);
// 两两相似度
const pairs = [];
for (let i = 0; i < prints.length; i++) {
for (let j = i + 1; j < prints.length; j++) {
const sim = jaccard(prints[i].tokens, prints[j].tokens);
pairs.push({
a: prints[i].id,
b: prints[j].id,
similarity: (sim * 100).toFixed(1) + '%',
raw: sim,
needsWork: sim > 0.50,
});
}
}
pairs.sort((a, b) => b.raw - a.raw);
const problematic = pairs.filter(p => p.needsWork);
console.log(JSON.stringify({
summary: {
scenarioCount: apps.length,
incompleteData: incomplete.length,
highSimilarityPairs: problematic.length,
verdict: (incomplete.length === 0 && problematic.length === 0)
? 'READY_TO_GENERATE'
: 'NEEDS_DATA_WORK',
},
// 数据不完整的场景
incomplete: incomplete.map(p => ({
id: p.id,
challenges: p.challengeCount,
criteria: p.criteriaCount,
standards: p.standardCount,
required: 'challenges≥3, criteria≥3, standards≥2',
})),
// 相似度过高的场景对
problematicPairs: problematic,
// 全部相似度(供参考)
topSimilarities: pairs.slice(0, 10),
}, null, 2));
process.exit(
(incomplete.length > 0 || problematic.length > 0) ? 1 : 0
);
六、批次质量门槛
一批页面在发布前应同时满足:
□ 数据层预检 verdict = READY_TO_GENERATE
□ 重复度检测 verdict = PASS(无 >40% 的页面对)
□ 平均字数 ≥ 1000 词
□ 无页面字数低于平均值的 60%
□ NKW 检查全部通过
□ 10% 抽查中的标准引用全部核实无误
任一项不满足就不要发布这批页面。批量生成的风险是批量的——一批低质量页面上线,可能拖累整站的质量评分,修复成本远高于生成前多花两小时准备数据。
→ AI Skill:Author + Organization Schema 批量生成
RELATED / 相关推荐
接着读这些
按同一分类、系列与标签为你挑选。
GEO 审计升级:从「结构合规」到「有没有被引用」
之前那个 GEO 覆盖审计 Skill 只能查结构,查不了覆盖——因为它没有期望值可比。补上意图注册表之后,审计从一层变三层:结构、覆盖与一致性、引用实测。其中复述块与主答块的一致性检查是纯确定性的,脚本能百分之百判定,这是升级带来的最大收益。
AI Skill:Cannibalization 诊断——同站竞争页面识别
注册表审计查的是规划层面的冲突,Cannibalization 诊断查的是已发布内容的实际竞争。这个 Skill 用 GSC 数据找出同一查询下多个页面轮流排名的证据,再用页面正文比对确认原因,最后给出合并、差异化或降权的处置决策。
AI Skill:竞品关键词差距分析
竞品有排名而你没有的词,是最确定的增长机会——市场需求已经被验证。这个 Skill 用脚本做多竞品词库的集合运算,找出共同覆盖但你缺失的词(最高价值),模型负责按业务相关性过滤和排序,输出可直接进注册表的机会清单。