Video Editing Tool Free
提供从赛道选择到交付的完整变现执行框架,助力个人创作者快速启动。
基于真实用户需求构建博客选题库,拒绝凭空猜测,用可验证的搜索数据驱动内容创作。
openclaw skills install @automatelab/blog-topic-research命令、参数、文件名以原文为准
为博客生成具备真实用户需求依据的话题候选。该技能旨在对抗虚构的 SEO 想法:每个提出的话题都必须指向一个可验证的 URL,证明确实有人在询问这个问题。
research <N> topics [for cluster <C>] [--append-to <path>]N - 返回的话题数量(默认 50;上限 100)cluster - 如果博客采用聚类分类体系,可限定在用户指定的某一聚类中--append-to <path> - 在展示结果后,询问用户是否将已接受的话题以 JSON 格式追加到指定路径(如待办文件、CSV 等博客使用的格式)该技能仅关注内容生成:不自行进行网页抓取。它调用代理的 WebFetch 和 WebSearch 工具获取来源,并(可选)调用 Python 相似度脚本执行重复话题检测。
对于技能输出的每一个话题,需记录以下字段:
| 字段 | 说明 |
|---|---|
topic | 以长尾查询形式呈现的完整标题 |
cluster | 用户定义的博客话题分类桶(例如 n8n、databases、react-hooks) |
format | 以下之一:how-to-fix、how-to-connect、how-to-automate、x-vs-y、what-is、use-case、listicle、migration、release-recap |
demand_signals[] | 一个或多个信号,每个包含 type、url、evidence(原文片段)、strength(1-3 分) |
signal_score | 所有信号 strength 值之和;话题仅当 >=3 时被接受 |
primary_sources[] | 至少包含 1 个官方文档 / GitHub Issue / 官方发布日志链接 |
keywords[] | 从源文本中提取的主要关键词 + 3-5 个相关词(LSI 变体) |
commentary | 1-2 句话说明该话题的独特性(无冗余表达) |
problem_summary | 从最高互动信号正文提炼出的症状与触发条件,用客观写作风格描述(非营销语言)。帮助作者跳过重新检索,直接理解问题本质 |
confirmed_fixes[] | 每项包含 {kernel, source}:简短修复方案(一句话,如 "set N8N_PAYLOAD_SIZE_MAX=16000000" 或 "downgrade crewai to 0.113")及该修复被提及的来源 URL。若尚未有文档修复,则列表为空(仍开放的问题也算);作者需将内核扩展为完整段落并再次核实 |
version_context | 版本上下文字符串,如 "n8n 1.65+"、"Cursor 0.42 only"、"introduced in CrewAI 0.114",或 null(无版本限制) |
question_variants[] | 2-4 个真实用户实际提问的改写版本(来自 PAA、自动补全深度 2、同类论坛标题)。直接用于文章 FAQ 段落和 LSI 关键词覆盖。不得虚构——每个变体必须源自已捕获的信号或自动补全结果 |
evidence 字段必须逐字复制自原始来源(PAA 问题文本、GitHub Issue 标题、Reddit 帖子标题、论坛线程标题)。X to Y、特定边缘场景)。拒绝模糊标题如“n8n 教程”或“什么是自动化”。problem_summary、confirmed_fixes[]、version_context、question_variants[] 必须基于实际抓取内容推导,绝不允许编造。若原文未提修复方案,confirmed_fixes[] 保持空;若未提及版本,version_context 为 null。作者应视其为可信框架,但仍需至少重新获取一个主源以确认时效性。N 个有效话题,返回已有的数量,并报告缺口。只有当信号类型属于以下类别,且链接页面包含原文证据时,才视为有效:
| 类型 | 认可的内容 |
|---|---|
paa | Google SERP 上的“人们还问”问题。URL = 主查询的 SERP 页面。证据 = PAA 问题原文 |
autocomplete | 输入部分关键词时触发的 Google 自动补全建议。证据 = 补全结果文本 |
reddit | 在相关 subreddit 上发布的、提出相同问题或近似变体的 Reddit 帖子。证据 = 帖子标题 |
stackoverflow | 与意图一致的 Stack Overflow 问题。证据 = 问题标题 |
github_issue | 工具仓库中描述该问题的 GitHub Issue(无论开放或关闭)。证据 = Issue 标题 |
forum | 第三方或厂商社区论坛中的讨论帖。证据 = 线程标题 |
vendor_doc | 因用户频繁提问而存在的厂商文档页面。证据 = 页面标题 |
trends | Google Trends 中上升趋势的查询。证据 = 查询词 + Trends 显示的上升百分比 |
signal_score)| 类型 | 1(存在) | 2(活跃) | 3(高参与度) |
|---|---|---|---|
paa | 出现一次 | 在 ≥2 个父级 SERP 中出现 | “更多问题”扩展显示 ≥4 个同意图的后续问题 |
autocomplete | 直接建议 | 建议词长度 ≥4 个词 | 建议词长度 ≥6 个词 |
reddit | 帖子存在 | ≥10 条评论 或 ≥20 个点赞 | ≥50 条评论 或 ≥100 个点赞 |
stackoverflow | 问题存在 | 得分 ≥3 或 浏览量 ≥500 | 得分 ≥10 或 浏览量 ≥2000 |
github_issue | 问题存在 | ≥3 个反应 或 ≥5 条评论 | ≥10 个反应 或 ≥20 条评论 或 被变更日志引用 |
forum | 线程存在 | ≥5 条回复 | ≥20 条回复 或 置顶 / 标记为解决方案 |
vendor_doc | 页面存在 | 页面位于主导航中 | 有专用 FAQ 条目或“常见错误”部分 |
trends | 查询量上升 | 上升 ≥100% | 上升 ≥500% 或 标记为“爆发性” |
参与度统计值在抓取时从源页面读取。将该数值记录在信号条目中,以便用户审计(例如:[strength=3, 14 reactions])。
不计入的情况:
用户需提供博客覆盖的来源列表(或请求技能推荐)。按集群类型提供的通用来源模板:
针对博客涵盖的每个工具,进行如下挖掘:
r/<language> 和 r/<framework> 版块。ecommerce、customer-support、marketing-ops)r/ecommerce、r/customerservice 等)。若用户已有明确的集群列表,请先索取其来源 URL;若无,则建议一份列表并允许用户编辑。
若用户已有现有文章清单文件(如 backlog.json、posts.csv、已发布文章的 RSS 源等),请提供路径及标题枚举方式。内容重复检测步骤需要基于这些已有标题构建嵌入缓存。
若具备 Python 嵌入脚本,用户可生成缓存(一个 JSON 文件,将每个已有标题映射到其 OpenAI text-embedding-3-small 向量),并指向该缓存文件。典型成本约为每百万 token $0.02。
若无 Python 环境或缓存,退而使用仅 Jaccard 的重复检测(成本低,准确率较低;可识别完全相同的标题,但无法发现同义重复)。
同时为每个已有标题构建一个词元集合(小写、仅字母数字、去除停用词),用于步骤 4 中的 Jaccard 预过滤。
若用户提供集群权重(如“30% n8n,20% AI 编码,...”),则应用权重:减去当前文章清单中各集群的数量,再按比例分配剩余 N 个目标。
若指定了 cluster <C>,则将全部 N 分配给该集群。
若完全没有集群分类体系,将整个博客视为单一集群,并优先考虑格式多样性(参见步骤 3 的格式矩阵)。
对每个集群,遍历其来源列表。对每个来源 URL:
WebFetch(或对 SERP 衍生信号使用 WebSearch)获取内容。 - 错误字符串(如 Error:、TypeError:、Traceback、异常类名、堆栈帧头)。
- 三重反引号包裹的代码块(常包含实际出错的代码片段,揭示真实边缘情况)。
- 版本限定短语(如“升级至 1.65 后”、“在 Cursor 0.42 上”、“v3 版本发布后”)。
每个提取出的字符串本身即成为一个候选种子。长尾故障排查类查询通常是原始错误信息,这类信息通常不会出现在帖子标题中。
谷歌侧种子:使用 WebSearch 以以下模式运行,并解析自动补全和 PAA 结果。对每个集群运行完整集,不仅限于故障排查类——长尾多样性是防止语料库陷入全“如何修复”的关键。
| 模式 | 格式目标 |
|---|---|
<工具> <错误信息>, <工具> 无法使用, <工具> 卡住, <工具> 失败 | how-to-fix |
<工具> 如何 <动词>, <工具> 连接 <其他工具> | how-to-connect / how-to-automate |
<工具> 对比 <竞品>, <工具> 或 <竞品> | x-vs-y |
什么是 <功能>, <功能> 解释, <功能> 如何工作 | what-is |
用 <工具> 构建 <结果>, <工具> 用于 <垂直领域>(如“用于电商”、“用于 SaaS”、“用于营销”、“用于客户支持”),<工具> 代理完成 <任务> | use-case |
最佳 <工具类别>, 前 N 个 <工具类别>, 免费 <工具>, <工具> 替代方案, <工具> 模板用于 <垂直领域> | listicle |
从 <工具 A> 迁移到 <工具 B>, 从 <工具 A> 切换到 <工具 B>, <工具 A> 到 <工具 B> 的迁移 | migration |
<工具> 新功能, <工具> 更新日志, <工具> <最近版本> 特性, <工具> 发布说明 | release-recap |
每个工具 / 框架 / 垂直领域集群内重复此矩阵。
每种格式的来源指引(除集群内源列表外):
use-case - 供应商模板库是最高信号来源。每个库条目都是经过验证的用户需求信号(人们搜索特定结果)。Reddit 上类似 *"如何用 [工具] 实现 [结果]"* 的帖子,且评论较多,也具有参考价值。若某个种子仅来自现有 SEO 博客的列表,则应剔除——这是竞争对手信号,而非真实用户需求信号。listicle - 在 best <类别> 和 top <N> <类别> 上进行 Google 自动补全深度挖掘;分析竞争对手的汇总类 SERP(观察前 3 个结果列出的内容)。Reddit 上提问 *"Y 场景下最好的 X 是什么"* 且评论多的帖子得分较高。migration - 标题以 moving from / switching from 开头的 Reddit 帖子;Stack Overflow 上关于在两个工具间导出并重新导入的问题;供应商的迁移文档(文档存在是因为用户有相关需求)。release-recap - 已存在于源列表中的供应商更新日志,但需重点挖掘 过去 90 天内发布的具体版本。只有当满足以下条件时,撰写 <工具> <版本> 的发布回顾才有价值:(a) 该版本为当前版本或仅落后一个次要版本,且 (b) 更新日志中至少包含一条面向用户的变更,而非仅内部重构。过时的回顾会迅速失效。每个提取出的查询都成为候选内容。其来源即为首个需求信号。
对每个通过步骤 3 的候选内容,附加一个额外限定词并重新查询 Google 建议。保留任何返回新变体的深层补全结果。这能帮你获取真正的长尾关键词而非中尾关键词——一次自动补全可发现 "如何修复 n8n webhook 错误",第二次则可能发现 "如何修复 n8n webhook 错误 404 在重启后出现"。
常见可尝试的限定词(尝试多个,保留实际返回结果的):
error、not working、after update、stuck、slow、timeout、free、limit、vs <已知竞品>、<当前年份>、self-hosted、cloud、docker
最多进行 两次递归遍历 以控制运行时间。每个新补全继承父级的第一个信号来源,并仍需独立通过步骤 4。
对每个通过步骤 3b 的候选内容,通过重新阅读 最高互动量的需求信号(在强度表中得分为 2 或 3 的内容——通常是高响应度的 GitHub 问题、置顶论坛帖或热门 Stack Overflow 问答)构建写作者可用的框架。若已在步骤 3.4 中获取过内容,可复用;否则现在立即获取。
提取四个字段:
problem_summary** - 用 1-2 句话以写作者口吻描述症状 + 触发条件。客观陈述,不含营销语言。示例:*"n8n 的 HTTP Request 节点在 OAuth2 凭据的访问令牌过期且刷新令牌授予缺少 offline_access 范围时返回 401 错误。"* 从正文提取动词和名词;不要改写标题。confirmed_fixes[]** - 列出 {kernel, source} 条目。每个 kernel 是一个简短短语,捕捉具体操作动作(设置环境变量、降级版本、切换开关、代码修改)。source 为该修复方法的来源链接(论坛回复、厂商文档、GitHub 提交、更新日志条目)。浏览回复、已接受答案块、厂商“常见问题”页面。忽略噪音:跳过“你试过重启吗?”这类建议,或与后续回复矛盾的修复方案。如果问题确实未解决且无有效修复方案,保持 confirmed_fixes[] 为空——写作者将围绕“目前已知情况”展开,而非虚构解决方案。version_context** - 从正文或线程中提取任何版本限定短语,用于界定问题范围(如 "升级到 n8n 1.65 后"、"Cursor 0.42 仅限"、"CrewAI 0.114 引入"、"Power Automate desktop V2")。若提及多个版本,选择与故障最紧密相关的那个。若正文为版本无关,设为 null。question_variants[] - 2-4 个与主题近似但表达不同的问题变体,来源于 PAA 框、自动补全深度补全、同类论坛帖标题或 SO 相关问题。每个变体必须是来自真实来源的字符串 —— 不得自行编造**。这些内容将用于写作者的 FAQ 模块和 LSI 关键词扩展。若任一字段无法从正文真实填充,保持默认空值(""、[]、null)而非虚构。信息稀疏的框架比虚构的更实用——写作者可重新调研,但无法信任被污染的数据。
- 从 X 迁移到 Y / 从 X 切换到 Y / 从 X 移动到 Y → migration
- X 版本中的新功能 / X 更新日志 / X 发布说明 / X v<N> 特性 → release-recap
- Y 的最佳 X / 前 N 个 X / 免费 X / X 替代方案 / 最受欢迎的 X → listicle
- X 对比 Y / X 或 Y → x-vs-y
- <错误信息> / 无法工作 / 修复 / 失败 / 损坏 → how-to-fix
- 将 X 与 Y 连接 / 集成 / 将 X 与 Y 集成 → how-to-connect
- 使用 X 构建 <结果> / <结果> 使用 X / X 用于 <垂直领域/使用场景> → use-case
- 自动化 X / <工具> 的 Y 工作流 → how-to-automate
- 什么是 X / X 解释 / X 如何工作 → what-is
模糊规则:当标题提及具体产物时(如“每日 Slack 摘要”、“发票提取代理”),优先选择 use-case;对于通用流程(如“自动化邮件分类”),优先选择 how-to-automate。当选项数量 ≥3 时选择 listicle,恰好 2 个时选择 x-vs-y。
- Jaccard 预过滤:候选标题与已有标题的词元集合重叠度 ≥0.6 时丢弃(快速剔除明显重复项)。
- 语义 + 词元重复检查(仅在已构建嵌入缓存时启用):
- 与任一已有标题的余弦相似度 ≥0.85 → 丢弃,记录为 cannibalization-semantic。
- 词元重复:候选标题与缓存中任意标题共享独特数值/错误码且共享工具关键词(无论余弦相似度如何)→ 丢弃。(捕捉表面表达不同但实质重复的内容。例如:“让 AI 代理设置 40 秒超时” vs “让 HTTP 模块出现 40 秒超时错误”——余弦值 0.51,但共享 [40秒, 设置] 被标记。)
- 余弦相似度在 0.75–0.85 之间且无词元重复 → REVIEW(保留但标记)。用户在追加时自行判断。
- 余弦相似度 <0.75 且无词元重复 → 接受。
- 若未构建嵌入缓存,则仅运行 Jaccard 预过滤,并在摘要尾部添加一行 cannibalization: jaccard-only,提示用户检查已简化。
signal_score < 3,则获取额外一次 SERP 结果,查找更多信号(PAA、第二个论坛帖、Stack Overflow 问题、厂商文档)。若仍低于 3 分,标记为 low-signal-score 并丢弃。- 字数 ≥7 个;
- 包含具体限定词(版本号、错误代码/字符串、命名集成对、特定边缘情况)。
若不满足,尝试从原始文本中提取限定词重写标题;若无法实现,则标记为 low-specificity 并丢弃。
每条通过审核的主题输出一个固定格式的区块,便于用户扫描或管道处理:
[01/50] cluster=<cluster> format=how-to-fix priority=2
TOPIC: How to fix the n8n "Cannot read properties of undefined" error in Code node
slug: n8n-cannot-read-properties-undefined-code-node
keywords: n8n Code node error, undefined property, JavaScript error, item access, $json
commentary: Specific to mistakes when accessing $json on the wrong item; vendor docs do not show the failure mode.
problem: The n8n Code node throws "Cannot read properties of undefined" when the script accesses $json on an item index that doesn't exist (typically the second iteration of a for-loop reading $items[1].json with only one input item).
fixes:
- guard with $items[i]?.json before accessing (https://github.com/n8n-io/n8n/issues/<id>#issuecomment-<n>)
- use $input.item.json instead of $items[i] when iterating (https://docs.n8n.io/code/builtin/data/)
version_context: n/a
question_variants:
- "n8n Code node Cannot read properties of undefined reading 'json'"
- "n8n JavaScript error TypeError undefined json"
- "Code node loop fails when item missing"
demand: (signal_score=4)
- github_issue: https://github.com/n8n-io/n8n/issues/<id> ("Code node throws Cannot read properties of undefined") [strength=3, 14 reactions]
- reddit: https://www.reddit.com/r/n8n/comments/<id> ("Help: Code node error when looping over items") [strength=1]
sources:
- https://docs.n8n.io/code/builtin/data/ (n8n docs - Built-in data variables)若 confirmed_fixes 为空(即问题开放但尚未有有效修复方案),则输出 fixes: (none documented yet - frame as 'what's known so far') 而非空列表。若 version_context 为 null,输出 version_context: n/a。若 question_variants 为空,整行省略(罕见但合法)。
若该主题处于重复检测的 REVIEW 区间,需附加一条 dedup_review 行,供用户知情决策:
dedup_review: cosine=0.81 vs "n8n Code node returns undefined when reading $json" (backlog-queued)随后输出摘要尾部:
Requested: 50
Validated: <X>
Dropped: <Y> (cannibalization-jaccard: <a1>, cannibalization-semantic: <a2>, cannibalization-token-dupe: <a3>, low-signal-score: <b>, no primary source: <c>, off-cluster: <d>, low-specificity: <e>)
Cluster mix: <cluster1>=__ <cluster2>=__ ...
Format mix: how-to-fix=__ how-to-connect=__ how-to-automate=__ x-vs-y=__ what-is=__ use-case=__ listicle=__ migration=__ release-recap=__技能:博客主题调研
版本:1.0.0
分块:5/5
如果传入了 --append-to <path> 参数:输出差异(数量 + 聚类混合变化),并提示 将 <X> 个主题追加到 <path>?[y/N]。当用户选择 y 时,将每个主题以 JSON 格式写入目标路径,格式如下:
{
"id": "<slug>",
"topic": "<标题>",
"cluster": "<聚类>",
"format": "<格式>",
"priority": 100,
"status": "queued",
"tags": ["<格式标签>", "<工具标签>"],
"notes": "<评论>",
"added_at": "<YYYY-MM-DD>",
"research_proof": {
"demand_signals": [...],
"primary_sources": [...],
"keywords": [...],
"problem_summary": "<来自最高互动信号正文的 1-2 句事实性描述>",
"confirmed_fixes": [
{"kernel": "<简短修复语句>", "source": "<url>"},
{"kernel": "<简短修复语句>", "source": "<url>"}
],
"version_context": "<版本限定词或 null>",
"question_variants": ["<变体 1>", "<变体 2>", "<变体 3>"]
},
"published_slug": null,
"published_at": null
}research_proof 数据块在状态为 queued 时保留在待办列表中,供下游写稿技能后续读取(避免重复调研)。当主题正式发布后,移除该数据块,防止待办文件随规模增长而膨胀;已发布的文章保留引用信息。
evidence 字符串按字节原样复制,不进行改写或转述。长度限制 120 字符,超长则用 ... 截断。low-signal-score。评分层级表是唯一权威标准——不得自行定义评分规则。low-specificity。长尾特征由标题本身内容决定,而非主观声称“这是具体的”。5400 / 月 数值。--append-to <path> 时,仅将主题加入待办队列,状态为 queued;由用户决定下一个写作主题。research <N> topics [for cluster <C>] [--append-to <path>]problem_summary、confirmed_fixes[]、version_context、question_variants[]。空默认值可接受;绝不虚构内容。signal_score ≥ 3、具体性下限、至少一个主来源、真实关键词。--append-to <path>,提示用户确认后,将结果写入待办文件,并保留 research_proof 数据块。已收录 1 个 Skill