关于 domain-expired-opportunity-finder
Expired Domain Opportunity Finder 是用于按目标细分领域评估过期域名的技能,并生成供人工审核的可解释候选名单。它结合历史、主题、注册和风险信号,也可使用 LLM 增强相关性评分。
主要功能
- 01评估主题契合度、活跃度、内容质量和历史
- 02检查 Wayback 快照与历史页面内容
- 03通过 RDAP 查询注册状态
- 04应用风险标记和候选筛选条件
- 05说明入选理由及潜在风险
适用场景
- 01筛选符合指定细分领域的过期域名
- 02比较用于重建网站或重定向的候选域名
- 03在人工决策前审查域名风险
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ varnan-tech/ opendirectory --skill domain-expired-opportunity-finder安装后在 Claude Code 中输入/domain-expired-opportunity-finder确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
.env.exampleREADME.mdevals/evals.jsonreferences/guardrails.mdoutput-format.mdrisk-flags.mdscoring-model.md详细介绍
过期域名机会筛选器
针对特定细分领域评估过期域名候选项。根据主题契合度、历史活跃度、历史记录的干净程度和重定向适用性为其评分。输出一份保守且理由充分的候选名单,供人工审核。
关键规则: 每条推荐都必须同时包含正面理由
(why_selected)和风险提示理由(why_risky)。绝不能只输出分数而不作解释。
默认采用保守策略: 信号不完整或相互矛盾时,降低置信度。不要将含糊不明的候选项列为绝佳机会。缺失数据只会降低置信度,绝不会提高置信度。
反滥用规则: 绝不鼓励无关重定向、构建 PBN,或将历史主题与目标细分领域不匹配的域名改作他用。完整的反滥用政策请阅读 references/guardrails.md。
第 1 步:环境检查
在进行任何操作之前,先检查环境。
确认 curl 和 python3(或 python)可用:
curl --version > /dev/null 2>&1 && echo "curl: available" || echo "curl: MISSING"
python3 --version 2>/dev/null || python --version 2>/dev/null || echo "python: MISSING"
检查是否设置了可选的 LLM API 密钥,以增强细分领域相关性评分:
echo "LLM_API_KEY: ${LLM_API_KEY:+set}"
如果缺少 curl 或 python:
停止。告知用户:“此技能需要 curl 和 Python 3.10+。请安装后重试。”
如果未设置 LLM_API_KEY:
继续。此技能将仅使用基于规则的评分(域名字符串匹配、Wayback 标题分析、关键词重合度)。告知用户:“当前仅以基于规则的模式运行。设置 LLM_API_KEY 可增强细分领域相关性评分。”
如果已设置 LLM_API_KEY:
此技能将使用 LLM 增强评分来分析主题相关性,从而更深入地评估与细分领域的契合度。
QA:说明评分模式(llm-enhanced 或 rule-based-only),并确认所需工具可用。
第 2 步:收集输入
向用户收集必需和可选的输入。
必需:
target_niche(字符串):用于评估的核心细分领域。示例:“开发者工具”“AI SaaS”“网络安全”“金融科技”。
可选(仅在未提供时询问):
seed_keywords(数组):用于优化主题匹配的关键词。如果未提供,则从细分领域名称中自动提取 3–5 个关键词。candidate_domains(数组):要评估的特定域名。如果未提供,则提示用户输入。discovery_source(字符串):候选项的来源——manual、expireddomains-net、external-feed。min_snapshots(整数):历史快照数量下限。默认值:10。max_risk_level(字符串):low、medium或high。控制筛选高风险候选项的严格程度。默认值:medium。intended_use(字符串):rebuild、redirect或either。默认值:either。
如果未提供 candidate_domains:
询问:“请提供要评估的过期域名候选项列表。你可以:
- 粘贴域名(每行一个或以逗号分隔)
- 提供一个文本文件的路径,文件中每行一个域名
- 输入 ‘example’,使用内置示例集运行‘开发者工具’细分领域的评估”
如果用户输入 ‘example’: 使用以下示例集:
devtoolsweekly.com
codeshipnews.io
stackforgeapp.com
quickseorank.net
bestcheaphosting247.com
cloudbuildpro.dev
reactwidgetlib.com
megadealsshop.xyz
收集完所有输入后,确认: “目标细分领域:[niche]。正在评估 [N] 个候选域名。评分模式:[mode]。预期用途:[use]。”
第 3 步:规范化候选项
评分前,清理并验证候选项列表。
python3 -c "
import sys, re
domains = '''CANDIDATE_LIST_HERE'''.strip().split('\n')
seen = set()
valid = []
invalid = []
for d in domains:
d = d.strip().lower()
# Strip protocols and paths
d = re.sub(r'^https?://', '', d)
d = d.split('/')[0]
d = d.strip('.')
if not d:
continue
# Basic TLD validation
if '.' not in d or len(d) < 4:
invalid.append(d)
continue
# Deduplicate
if d in seen:
continue
seen.add(d)
valid.append(d)
print(f'Valid candidates: {len(valid)}')
print(f'Removed (invalid/duplicate): {len(invalid)}')
for v in valid:
print(f' ✓ {v}')
for i in invalid:
print(f' ✗ {i} (invalid format)')
"
将 CANDIDATE_LIST_HERE 替换为第 2 步中的实际域名列表。
说明:“规范化后有 [N] 个有效候选项。已移除 [M] 个(无效/重复)。”
如果有效候选项数量为 0,则停止并告知用户:“未找到有效的域名候选项。请按 ‘example.com’ 格式提供域名。”
第 4 步:收集信号
针对每个有效候选项,从免费的公开来源收集信号。 按域名依次运行以下检查。
4a:Wayback CDX API — 历史快照
查询 Wayback Machine 中的所有历史快照。我们使用 limit=100000,并有意省略显式的 from/to 参数,这样 CDX 就会返回该域名整个生命周期内的快照。结果按时间戳升序排列(最早的在前),以确保 first_capture 和 last_capture 准确无误:
curl -s "https://web.archive.org/cdx/search/cdx?url=DOMAIN_HERE&output=json&fl=timestamp,statuscode&collapse=timestamp:6&limit=100000" \
| python3 -c "
import sys, json
try:
data = json.load(sys.stdin)
if len(data) <= 1:
print(json.dumps({'domain': 'DOMAIN_HERE', 'snapshots': 0, 'first_capture': None, 'last_capture': None, 'status_codes': {}, 'years_active': 0}))
else:
rows = data[1:] # skip header row
timestamps = [r[0] for r in rows] # already ascending (oldest first)
statuses = [r[1] for r in rows]
status_counts = {}
for s in statuses:
status_counts[s] = status_counts.get(s, 0) + 1
first_year = int(timestamps[0][:4])
last_year = int(timestamps[-1][:4])
print(json.dumps({
'domain': 'DOMAIN_HERE',
'snapshots': len(rows),
'first_capture': timestamps[0],
'last_capture': timestamps[-1],
'status_codes': status_counts,
'years_active': last_year - first_year + 1
}))
except:
print(json.dumps({'domain': 'DOMAIN_HERE', 'snapshots': 0, 'error': 'wayback_api_failed'}))
"
速率限制: 两次 Wayback API 调用之间等待 2 秒,以免给服务造成负担。
4b:Wayback 内容抽样 — 历史页面标题
对于快照数 > 0 的候选域名,获取最新快照以提取页面标题(用于主题相关性评分):
curl -s -L "https://web.archive.org/web/LATEST_TIMESTAMP/http://DOMAIN_HERE" \
| python3 -c "
import sys, re
html = sys.stdin.read()[:50000]
title_match = re.search(r'<title[^>]*>(.*?)</title>', html, re.IGNORECASE | re.DOTALL)
title = title_match.group(1).strip() if title_match else 'no title found'
# Extract meta description too
meta_match = re.search(r'<meta[^>]*name=[\"']description[\"'][^>]*content=[\"'](.*?)[\"']', html, re.IGNORECASE)
desc = meta_match.group(1).strip() if meta_match else 'no description found'
print(f'Title: {title}')
print(f'Description: {desc}')
"
将 LATEST_TIMESTAMP 替换为步骤 4a 中的最新时间戳。
4c:RDAP 查询 — 注册状态
使用跨平台、基于 HTTP 的 RDAP 标准(取代依赖操作系统的 WHOIS)。 RDAP 返回 HTTP 404 表示该域名尚未注册(即确实可用或未被追踪),这与网络故障不同。请明确处理这两种情况:
python3 -c "
import urllib.request, urllib.error, json
domain = 'DOMAIN_HERE'
try:
req = urllib.request.Request(
f'https://rdap.org/domain/{domain}',
headers={'User-Agent': 'Mozilla/5.0'}
)
with urllib.request.urlopen(req, timeout=10) as response:
data = json.loads(response.read().decode())
registrar = 'unknown'
created = 'unknown'
for entity in data.get('entities', []):
if 'registrar' in entity.get('roles', []):
try:
registrar = entity.get('vcardArray', [[]])[1][0][3]
except Exception:
pass
for event in data.get('events', []):
if event.get('eventAction') == 'registration':
created = event.get('eventDate', 'unknown')
print(json.dumps({
'domain': domain,
'status': 'registered',
'registrar': registrar,
'created': created
}))
except urllib.error.HTTPError as e:
if e.code == 404:
# Domain has no RDAP object — likely unregistered or not in RDAP coverage
print(json.dumps({'domain': domain, 'status': 'unregistered_or_no_rdap_object'}))
else:
print(json.dumps({'domain': domain, 'error': f'rdap_http_error_{e.code}'}))
except Exception:
print(json.dumps({'domain': domain, 'error': 'rdap_lookup_failed'}))
"
4d:域名字符串分析 — 关键词匹配
对域名与目标细分领域/种子关键词之间的关键词重叠进行评分:
python3 -c "
import re, json
domain = 'DOMAIN_HERE'
niche = 'NICHE_HERE'
seeds = SEEDS_JSON_HERE # e.g., ['devops', 'ci/cd', 'code editor']
# Extract words from domain
domain_base = domain.rsplit('.', 1)[0] # remove TLD
domain_words = re.split(r'[-_.]', domain_base.lower())
# Check niche words
niche_words = niche.lower().split()
all_keywords = set(niche_words + [s.lower() for s in seeds])
matches = [w for w in domain_words if any(kw in w or w in kw for kw in all_keywords)]
match_ratio = len(matches) / max(len(domain_words), 1)
print(json.dumps({
'domain': domain,
'domain_words': domain_words,
'keyword_matches': matches,
'match_ratio': round(match_ratio, 2)
}))
"
4e:Gemini 大模型细分领域相关性评估(如果已设置 LLM_API_KEY)
如果已配置大模型 API 密钥,则将所有候选域名及其收集到的信号批量发送,并请求进行上下文相关的细分领域相关性评估。
注意: 以下请求/响应格式使用 Gemini API(generateContent 格式)。未经修改,与 OpenAI 风格的端点不兼容。如果使用其他提供商,必须调整 JSON 请求正文和响应解析。
cat > /tmp/domain-relevance-request.json << 'ENDJSON'
{
"system_instruction": {
"parts": [{
"text": "You are an SEO research analyst. For each expired domain candidate provided, assess its topical relevance to the specified target niche. Consider the domain name, historical page title, and meta description. For each domain, output a JSON object with: domain (string), relevance_score (integer 1-10), relevance_rationale (one sentence explaining the score), redirect_plausibility (integer 1-10), redirect_rationale (one sentence). Output only a JSON array. No commentary before or after."
}]
},
"contents": [{
"parts": [{
"text": "DOMAIN_SIGNALS_AND_NICHE_CONTEXT_HERE"
}]
}],
"generationConfig": {
"temperature": 0.2,
"maxOutputTokens": 2048
}
}
ENDJSON
将 DOMAIN_SIGNALS_AND_NICHE_CONTEXT_HERE 替换为:
- 目标细分领域和种子关键词
- 每个候选域名的信息:域名、历史标题、描述、关键词匹配数据
向 Gemini API 发送请求:
curl -s -X POST \
"${LLM_API_ENDPOINT:-https://generativelanguage.googleapis.com/v1beta}/models/${LLM_MODEL:-gemini-2.0-flash}:generateContent?key=$LLM_API_KEY" \
-H "Content-Type: application/json" \
-d @/tmp/domain-relevance-request.json \
| python3 -c "
import sys, json
try:
d = json.load(sys.stdin)
text = d['candidates'][0]['content']['parts'][0]['text']
print(text)
except (KeyError, IndexError, json.JSONDecodeError) as e:
print(json.dumps({'error': 'llm_response_parse_failed', 'detail': str(e)}))
"
如果大模型调用或响应解析失败,请记录错误,并继续仅使用基于规则的评分。不要停止工作流。
收集完所有信号后,输出: “已完成 [N] 个候选域名的信号收集。[M] 个 Wayback 命中,成功完成 [K] 次 RDAP 查询。”
步骤 5:评分与分类
阅读 references/scoring-model.md,了解完整的评分框架。
针对每个候选域名,计算以下 6 个维度的分数:
-
主题相关性(0–30): 综合域名关键词匹配率、历史标题/描述分析结果,以及大模型相关性分数(如果可用)。未使用大模型时:使用关键词匹配率 × 15 + 标题关键词重叠度 × 15。使用大模型时:使用 LLM relevance_score × 3。
-
历史活跃度(0–25): 根据 Wayback 快照的多样性和频率评分。跨多年持续捕获到更多快照,意味着活跃度持续较高,且推测可信度较高。
-
历史内容质量(0–15): 根据历史页面标题和元描述分析得出,检查措辞是否自然,还是存在关键词堆砌。未使用大模型时:基础分为 8/15,并根据精确匹配密度调整。
-
历史记录清晰度(0–15): 根据 Wayback 快照数量、活跃年数、状态代码一致性,以及是否存在停放页面迹象进行评分。
-
重定向适用性(0–10): 根据历史内容与目标细分领域之间的主题连续性评分。如果可用,则使用大模型的 redirect_plausibility 分数;否则使用关键词重叠率。
-
信号完整度(0–5): 统计返回了可用数据的数据源数量(Wayback、RDAP、域名分析;如已配置,还包括大模型)。
计算:
opportunity_score= 所有维度分数之和(0–100)confidence= 根据具有强数据支持的维度数量计算(参见 scoring-model.md)recommended_action= 根据分数、置信度和风险标记确定(参见步骤 6)
第 6 步:风险标记与筛选
阅读 references/risk-flags.md,查看完整的标记定义。
为每个候选项应用风险标记:
| 检查项 | 应用的标记 |
|---|---|
| 与目标细分领域的历史主题重合度 < 30% | topic_mismatch |
| 域名在到期前活跃时间 < 1 年 | short_history |
| Wayback 快照少于 3 个,或全部为停放页面 | unclear_history |
| 活跃多年后,Wayback 快照数量突然下降 | possible_deindex |
快照数量低于 min_snapshots | weak_historical_activity |
| 重定向适用性 < 4/10 | redirect_mismatch |
应用推荐逻辑:
| 评分 + 标记 | 推荐操作 |
|---|---|
评分 ≥ 75 且置信度为 high,并且没有高严重性标记 | high-priority-review |
评分 ≥ 55 且置信度 ≥ medium | review |
| 评分 ≥ 55,但重定向适用性 < 4/10 | rebuild-only-review |
| 评分 < 55,或存在任何关键高严重性标记 | reject |
应用 max_risk_level 筛选条件:
- 如果
max_risk_level=low:排除带有中或高风险标记的所有候选项 - 如果
max_risk_level=medium:仅排除带有高风险标记的候选项 - 如果
max_risk_level=high:包含所有候选项(不筛选)
第 7 步:输出与保存
阅读 references/output-format.md,查看准确的 JSON 架构。
阅读 references/guardrails.md,查看必需的免责声明文本。
默认:候选清单模式。 仅显示 recommended_action 为
high-priority-review、review 或 rebuild-only-review 的候选项。
如果用户要求使用审计模式,则显示所有候选项,并提供完整的维度细分 和拒绝原因。
呈现输出:
## Expired Domain Opportunity Finder — [YYYY-MM-DD]
**Target niche:** [niche]
**Seed keywords:** [keywords]
**Intended use:** [rebuild/redirect/either]
**Candidates evaluated:** [N]
**Shortlisted:** [M]
**Rejected:** [K]
**Scoring mode:** [llm-enhanced / rule-based-only]
---
### 1. [domain.com] — Score: [N]/100 | Confidence: [level] | Action: [recommendation]
**Topical fit:** [summary]
**Activity level:** [summary]
**Content quality:** [summary]
**History:** [summary]
**Redirect suitability:** [level]
**Risk flags:** [flags or "none"]
**Why selected:** [rationale]
**Why risky:** [rationale]
---
[repeat for each shortlisted domain, ranked by opportunity_score descending]
---
**Disclaimer:** These results are research recommendations, not guarantees
of SEO value. Redirect analysis should only be considered when strong
topic continuity exists between the expired domain and your target site.
Search engine algorithms change frequently. Always perform manual due
diligence — including checking current index status, reviewing the full
backlink profile with a commercial tool, and verifying domain history —
before making any acquisition decision. This skill does not endorse or
facilitate manipulative SEO practices.
保存结构化 JSON 输出:
mkdir -p docs/expired-domain-intel
OUTFILE="docs/expired-domain-intel/$(date +%Y-%m-%d).json"
cat > "$OUTFILE" << 'EOF'
JSON_OUTPUT_HERE
EOF
echo "Saved to $OUTFILE"
如果通过候选清单筛选的候选项为 0: “在当前风险容忍度下,没有候选项符合「[niche]」细分领域的候选清单标准。这是正常结果——意味着经过评估的域名匹配度不够高。请尝试:
- 提供不同的候选域名
- 扩大种子关键词范围
- 将 max_risk_level 设为 'high',以查看边缘候选项
- 使用审计模式运行,查看候选项被拒绝的原因”
自查清单
呈现输出前,逐项检查:
- 每个入选候选清单的域名都有
why_selected和why_risky - 没有带高严重性风险标记的入选域名被标记为
high-priority-review - 带有
redirect_mismatch的域名标记为rebuild-only-review(而不是review) - 输出末尾包含防护措施免责声明
- 不使用夸大宣传措辞:不得出现“保证”“轻松取胜”“重定向很安全”“SEO 技巧”
-
scoring_mode正确反映是否使用了 LLM - 候选项按
opportunity_score降序排列 - JSON 输出已保存到
docs/expired-domain-intel/YYYY-MM-DD.json - 所有 Wayback API 调用都遵守了速率限制(每次调用间隔 2 秒)
呈现前修复任何违规项。
优质输出的特点
- 每个域名都有评分、置信度、操作建议和风险评估
- 每项摘要为 1–2 句话,具体描述对应候选项(而非泛泛而谈)
- 包含风险标记,并在
why_risky中说明 - 候选清单数量较少(重质量而非数量)——通常每批 10–20 个域名中选出 2–5 个
- 保守处理:如有疑问,则拒绝或降低置信度
- 用户可以清楚了解每个域名被选中或拒绝的具体原因
劣质输出的特点
- 只给出评分,没有说明
- 使用“这个域名的指标不错”等泛泛摘要(必须具体)
- 为带有严重风险标记的域名给出高优先级建议
- 为主题不匹配的域名提出重定向建议
- 末尾没有免责声明
- 使用夸大宣传措辞,承诺 SEO 成效
- 入选候选清单的域名过多(此技能应有所筛选,而非一味放宽)