2026-10-10 · 原文发布日
输入软件名自动汇总全网替代品清单
自托管n8n专用的调研模板:在表单里输入一个软件产品名,工作流用DuckDuckGo搜出前十二条结果页并读取正文,代码节点只保留真正列举替代品的页面、排除产品官网、每站取一页。然后让聊天模型(默认OpenRouter的Gemini 3.8 Flash,可换任意模型节点)列出各页面提到的替代工具并引用原文句子,代码再校验引句确实存在于页面上,按独立站点数给每个工具计票,最后在表单里展示表格、读过的站点和被排除页面及原因。DuckDuckGo部分不需要API key。模板免费。
原文要点
这是n8n.io上的免费模板(作者Sam),仅支持自托管n8n,因为需要安装社区节点n8n-nodes-duckduckgo-search(Settings→Community nodes),n8n Cloud装不了社区节点。流程:表单输入软件名(可选填品类),一次DuckDuckGo搜索取前12条结果页并读正文(不需要任何API key或账号);Code节点只保留列举替代品的页面、按域名排除产品官网、每站只取一页;聊天模型默认OpenRouter的Gemini 3.8 Flash,可换成任意chat-model节点,要求模型列出各页提到的替代工具并引用原文句子;Code节点校验引句确实出现在页面上才计票,按独立站点数给每个工具计票(某站给自家产品的投票不计),引句补全到句尾。表单最后展示表格、读过的站点、被排除页面及原因。Code节点最多用8个来源、最多展示15个工具。表格只代表站点计数,不代表质量排名。作者给出的源码说明在github.com/samnodehi/n8n-nodes-duckduckgo。
这次做成什么
在自己的自托管n8n上搭一个“输入任意软件名→自动读多个评测/盘点页→输出按站点计数的替代品清单+原文引句”的调研小工具,并用一个常见软件名演练。
准备什么
- 一台自托管n8n(版本支持社区节点)且能访问外网
- 管理员权限,用于在Settings→Community nodes安装n8n-nodes-duckduckgo-search
- 一个OpenRouter API key(默认走Gemini 3.8 Flash)或任何n8n chat-model节点的凭据
- 一个用于练习的知名软件名,例如Notion或Slack
- 明白表单会抓取搜索结果页,需保持在n8n登录保护后使用
具体怎么做
装社区节点和模型凭据
Settings→Community nodes里安装n8n-nodes-duckduckgo-search并重启生效;Credentials里新建OpenRouter凭据填入key;确认实例能访问duckduckgo.com。
搭表单触发
用n8n Form Trigger,添加两个字段:productName(必填,文本)、category(可选,文本,如‘笔记软件’)。保持表单在n8n登录保护之下——原作者明确提醒这一点,因为节点会去抓搜索返回的任意页面。
搜索并读页
接DuckDuckGo搜索节点,查询词拼成 {{$json.productName}} alternatives({{$json.category}}有值时追加),Region保持us-en或改成你关心的国家;Max Results设12,Max Results for Page Content控制实际读正文的页数。
筛选来源
Code节点做三件事:丢弃正文里没有‘列举多个替代品’特征的页面(可用是否出现多个工具名+列表结构粗判);从productName提取域名,排除该域名页面;按域名去重,每站只留一页。输出保留的sources数组和excluded数组(含排除原因)。
模型抽取+引句校验
chat-model节点对每个保留页面用材料A的提示词,要求返回JSON数组[{tool, quote}]。接Code节点(参考材料B):strip空白后检查quote是否是页面正文的子串,不是就丢弃;同一站点对自家产品的提名不计票;按工具聚合独立站点数,按票数降序,最多取15个。
表单展示结果
用Form Ending节点渲染三张表:替代品清单(工具名/站点数/一条引句)、已读站点列表、被排除页面及原因,并在页面上注明‘站点数不等于质量排名’。
可直接复制的材料
材料A:替代品抽取提示词
本站独立编写的示例提示词;{{productName}}和{{pageText}}需替换为n8n表达式。
你在分析一个网页,任务是找出页面中作为“{{productName}}替代品”被推荐的工具。
只输出一个JSON数组,不要markdown、不要解释。每个元素格式:
{"tool": "工具名", "quote": "从页面正文逐字复制的、明确把该工具列为替代品或竞品的完整句子"}
规则:
1. quote必须是页面原文里逐字存在的句子,不得改写、拼接或翻译。
2. 只收录被当作{{productName}}的替代/竞品提到的工具,页面顺带提及但无关的不算。
3. 如果页面没有列出任何替代品,输出空数组[]。
页面正文:
{{pageText}}材料B:引句校验与计票的Code节点参考实现
本站独立编写的示意代码,未在原模板实测;原模板另有‘把引句补全到句尾’的处理,可在norm比对后用原文截取到下一个句点。
// n8n Code节点(Run Once for All Items),本站独立编写的参考实现
const pages = $input.all(); // 每项含 {url, domain, text, modelOutput}
const votes = new Map(); // tool -> Set(domain)
const quoteOf = new Map(); // tool -> 第一条校验通过的引句
const norm = s => s.replace(/\s+/g, ' ').trim();
for (const item of pages) {
const { domain, text } = item.json;
let list;
try { list = JSON.parse(item.json.modelOutput); } catch { continue; }
if (!Array.isArray(list)) continue;
for (const { tool, quote } of list) {
if (!tool || !quote) continue;
if (!norm(text).includes(norm(quote))) continue; // 引句必须逐字存在于页面
const key = tool.trim();
if (key.toLowerCase().includes(domain.split('.')[0])) continue; // 本站给自家产品投票不计
if (!votes.has(key)) { votes.set(key, new Set()); quoteOf.set(key, quote); }
votes.get(key).add(domain); // 每域名一票
}
}
const table = [...votes.entries()]
.map(([tool, set]) => ({ tool, sites: set.size, quote: quoteOf.get(tool) }))
.sort((a, b) => b.sites - a.sites)
.slice(0, 15);
return [{ json: { table } }];材料C:来源筛选的判定字段约定
本站设计的字段方案,方便你在排除页展示‘为什么被排除’。
Code节点输入项约定(每项一个页面):
url: 页面完整URL
domain: 从URL提取的主域名,如 g2.com
text: 页面正文纯文本(HTML已剥离)
modelOutput: 模型对该页的原始字符串输出
排除原因枚举(写入excluded数组):
own_site: 域名与productName匹配,判定为官网
no_list: 正文未呈现替代品列表结构
duplicate_domain: 同站已有页面入选
fetch_failed: 页面读取失败输入与输出示例
本站虚构演示,引句为编写示例、计票数字与输入假设对应,非真实搜索结果。
输入
productName = Notion,category = 笔记软件(本站虚构演练:假设12条结果中notion.so官网2条、抓取失败1条,其余9条可读;9条中有3条因域名重复被去重,最终剩6个独立站点)对应输出
表单展示表格前3行:Obsidian | 5 | “If you want a local-first alternative to Notion, Obsidian keeps your notes as plain Markdown files.”;Logseq | 4 | “Logseq is an open-source outliner often recommended as a Notion alternative.”;Anytype | 3 | “Anytype positions itself as a privacy-focused Notion alternative.”;已读站点6个,被排除页6条:notion.so×2(own_site)、同域重复页×3(duplicate_domain)、某论坛页×1(fetch_failed)做完检查这些
- 输入一个软件名后,表单页出现三张表:替代品清单、已读站点、被排除页面及原因
- 清单中每个工具的引句能在对应来源页面正文中逐字找到(norm后子串匹配)
- 同一域名的多个页面只贡献一票,官网域名页面全部出现在排除列表
- 把productName换成小众软件、结果不足12条时,流程不报错,表格按实际站点数展示
容易卡住的地方
- 仅自托管n8n可用,n8n Cloud无法安装社区节点,这是硬前提
- 搜索节点会抓取任意结果页,务必保持表单在登录保护后,别公开暴露
- 模型可能编造引句,所以引句校验这步不能省,否则计票失真
- DuckDuckGo无需key但有频控,连续调试太密会被限流,间隔几分钟再试
- 原作者说明计数最多8个来源、展示最多15个工具,别期待全网穷尽
本站借助AI整理来源事实,独立编写中文操作指南与示例。示例不代表实际运行结果;来源效果尚未由本站独立复现。付费模板与模型、服务费用分别计算。
- 原文标题
- Find software alternatives with DuckDuckGo and OpenRouter Gemini
- 原作者
- Sam
- 原始发布日期
- 2026-10-10T13:33:04.452Z
- 来源
- https://n8n.io/workflows/20738