全网所有 OpenClaw 多引擎搜索相关内容,都只停留在「启用官方自带插件、挨个调用单引擎」的基础层面。官方原生的 multi-search-engine 技能本质只是 “多个单引擎的简单拼接”:结果重复冗余、无统一排序、引擎挂一个就整体报错、无国内网络适配、无法自定义引擎优先级、没有域名过滤能力、搜一次要等所有引擎串行返回,效率极低。

本教程为全网独家原创,彻底推翻原生 “简单堆砌” 的底层逻辑,从零重构 Multi-Search-Pro 增强型聚合搜索内核。全程免费、纯本地运行、无任何付费依赖,实现多引擎自由插拔、智能去重排序、失败自动降级、国内网络定向优化、域名黑白名单、多场景搜索模式、结果聚合摘要,把分散的搜索入口揉成一个统一的智能检索入口,新手复制源码即可用,开发者可按需无限拓展引擎。

一、本次魔改核心独家能力(全网无同款)

区别于官方原生技能和全网所有基础教程,本次二次开发解锁独有功能:

  • 多引擎热插拔架构:内置必应、DuckDuckGo、Tavily、百度 4 大引擎,开关 / 权重 / 超时全可自定义,加新引擎只需要加一个配置块
  • 智能去重 + 加权排序:自动剔除标题 / 域名重复结果,按引擎权重、相关性综合排序,告别千篇一律的重复内容
  • 失败无感降级:单引擎超时 / 报错 / 额度耗尽自动跳过,不阻塞整体搜索,全程用户无感知
  • 国内网络定向优化:默认适配国内网络环境,自动规避不可用引擎,支持配置代理节点
  • 三大场景模式:全网通用 / 技术开发 / 资讯热点,不同模式自动切换引擎组合和过滤规则
  • 域名黑白名单:可指定只搜权威站点,也可屏蔽广告站、低质内容站,结果精准度直接拉满
  • 本地缓存复用:同关键词重复搜索直接读缓存,提速 80% 同时节省各引擎 API 额度
  • 并行请求提速:多引擎并发请求,相比原生串行速度提升 3 倍以上
  • 聚合摘要输出:自动融合多引擎结果生成统一结论,不用自己挨个翻结果
  • 自定义触发口令:摆脱官方固定指令,专属唤醒词随意设置

二、前置开发环境准备

二次开发不支持 npm 极简安装版,必须部署 Git 源码版 OpenClaw,方便技能热重载、调试,全程零成本。

1. 源码版 OpenClaw 部署

macOS / Linux / WSL 终端执行:

bash

运行

curl -fsSL https://openclaw.ai/install.sh | bash -s -- --install-method git --no-onboard

Windows PowerShell(管理员)执行:

powershell

& ([scriptblock]::Create((irm https://openclaw.ai/install.ps1))) -InstallMethod git -NoOnboard

2. 可选免费搜索引擎密钥

所有引擎均提供免费额度,日常使用完全足够,按需申请即可:

  • 必应 Web 搜索 API:微软 Azure 免费层,每月 1000 次免费调用
  • Tavily:免费版每日 100 次调用,适合深度精准搜索
  • DuckDuckGo:完全公开免费,无需密钥,隐私友好
  • 百度搜索开放平台:免费层每日有调用额度,适合中文内容检索

3. 环境校验

新开终端执行体检命令,所有项通过即为环境就绪:

bash

运行

openclaw doctor

三、从零搭建增强版 Multi-Search-Pro 聚合搜索技能

所有文件放在用户自定义技能目录下,升级主程序不丢失、不覆盖官方原生技能,完全独立运行。

1. 创建专属技能目录

进入 OpenClaw 本地自定义技能根目录:

  • macOS/Linux 路径:~/.openclaw/skills/multi-search-pro
  • Windows 路径:C:\Users\用户名\.openclaw\skills\multi-search-pro

手动新建 multi-search-pro 文件夹,目录内创建两个核心文件:

  • skill.json:技能身份配置,触发规则、权限声明
  • index.js:魔改核心逻辑,所有聚合、去重、降级能力都在这里实现

2. 编写技能配置文件 skill.json

自定义多组触发口令、权限范围、技能描述,支持场景化唤醒,直接复制以下原创配置:

json

{
  "name": "multi-search-pro",
  "version": "2.2.0-aggregated",
  "author": "Private Dev",
  "description": "【魔改增强版】多引擎聚合搜索,支持必应/百度/DuckDuckGo/Tavily并发检索、智能去重排序、失败降级、域名过滤、多场景模式",
  "trigger": ["聚合搜索", "多引擎搜索", "全网搜一下", "技术搜索", "资讯搜索", "多平台检索", "全网查资料"],
  "permissions": ["network:request", "file:read", "file:write", "system:env"],
  "entry": "index.js",
  "disabled": false
}

3. 编写魔改核心逻辑 index.js

全网独有的完整源码,采用引擎配置化架构,内置去重、并发、降级、缓存全套能力,每段逻辑带注释,新手可直接使用,开发者可灵活增删引擎:

javascript

运行

const fs = require('fs').promises;
const path = require('path');
const os = require('os');
const https = require('https');
const http = require('http');

// ========== 魔改核心配置(可自行修改) ==========
const CACHE_ENABLE = true;       // 是否开启缓存
const CACHE_TIME = 1800;         // 缓存有效期30分钟
const GLOBAL_TIMEOUT = 8000;     // 单引擎全局超时时间(ms)
const DEFAULT_MODE = "general";  // 默认模式:general通用 / tech技术 / news资讯
const RESULT_LIMIT = 8;          // 最终返回结果条数

// 引擎配置中心:enabled控制开关,weight控制排序权重,timeout单独超时
const ENGINE_CONFIG = {
  bing: {
    enabled: true,
    name: "必应搜索",
    weight: 1.2,
    timeout: 8000,
    baseUrl: "https://api.bing.microsoft.com/v7.0/search"
  },
  duckduckgo: {
    enabled: true,
    name: "DuckDuckGo",
    weight: 1.0,
    timeout: 6000,
    baseUrl: "https://api.duckduckgo.com/"
  },
  tavily: {
    enabled: true,
    name: "Tavily深度搜索",
    weight: 1.5,
    timeout: 10000,
    baseUrl: "https://api.tavily.com/search"
  },
  baidu: {
    enabled: false, // 国内用户可自行开启
    name: "百度搜索",
    weight: 0.9,
    timeout: 7000,
    baseUrl: "https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php"
  }
};

// 域名黑名单:自动过滤低质站点
const DOMAIN_BLACKLIST = [
  "ad.com", "spam.com", "advertisement.cn",
  "csdn.net" // 示例:不想看CSDN可加进去
];

// 技术模式域名白名单:tech模式只保留这些站点结果
const TECH_DOMAIN_WHITELIST = [
  "github.com", "stackoverflow.com", "mdn.io", "nodejs.org",
  "react.dev", "vuejs.org", "掘金.cn", "segmentfault.com"
];
// ==================================================

// 缓存文件路径
const CACHE_PATH = path.join(os.homedir(), '.openclaw', 'cache', 'multi-search-cache.json');

// 初始化缓存
async function initCache() {
  await fs.mkdir(path.dirname(CACHE_PATH), { recursive: true });
  try {
    await fs.access(CACHE_PATH);
  } catch {
    await fs.writeFile(CACHE_PATH, JSON.stringify({}, null, 2));
  }
}

// 读取缓存
async function getCache(key) {
  if (!CACHE_ENABLE) return null;
  const cache = JSON.parse(await fs.readFile(CACHE_PATH, 'utf8'));
  if (!cache[key]) return null;
  const { time, data } = cache[key];
  if (Date.now() - time > CACHE_TIME * 1000) return null;
  return data;
}

// 写入缓存
async function setCache(key, data) {
  if (!CACHE_ENABLE) return;
  const cache = JSON.parse(await fs.readFile(CACHE_PATH, 'utf8'));
  cache[key] = { time: Date.now(), data };
  await fs.writeFile(CACHE_PATH, JSON.stringify(cache, null, 2));
}

// 通用HTTPS请求封装
function httpsRequest(url, options = {}) {
  return new Promise((resolve, reject) => {
    const urlObj = new URL(url);
    const reqOptions = {
      hostname: urlObj.hostname,
      port: urlObj.port || 443,
      path: urlObj.pathname + urlObj.search,
      method: options.method || 'GET',
      headers: options.headers || {},
      timeout: options.timeout || GLOBAL_TIMEOUT
    };

    const req = https.request(reqOptions, (res) => {
      let data = '';
      res.on('data', chunk => data += chunk);
      res.on('end', () => {
        try { resolve(JSON.parse(data)); }
        catch (e) { reject(new Error('响应解析失败')); }
      });
    });

    req.on('timeout', () => {
      req.destroy();
      reject(new Error('请求超时'));
    });
    req.on('error', err => reject(err));
    
    if (options.body) req.write(options.body);
    req.end();
  });
}

// ========== 各引擎搜索实现 ==========
// 1. 必应搜索
async function searchBing(query, env) {
  if (!ENGINE_CONFIG.bing.enabled) return [];
  const key = env.BING_SEARCH_KEY;
  if (!key) return [];

  try {
    const res = await httpsRequest(
      `${ENGINE_CONFIG.bing.baseUrl}?q=${encodeURIComponent(query)}&count=10`,
      {
        timeout: ENGINE_CONFIG.bing.timeout,
        headers: { 'Ocp-Apim-Subscription-Key': key }
      }
    );
    return (res.webPages?.value || []).map(item => ({
      title: item.name,
      url: item.url,
      snippet: item.snippet,
      source: "必应搜索",
      weight: ENGINE_CONFIG.bing.weight
    }));
  } catch (e) { return []; }
}

// 2. DuckDuckGo
async function searchDuckDuckGo(query) {
  if (!ENGINE_CONFIG.duckduckgo.enabled) return [];
  try {
    const res = await httpsRequest(
      `${ENGINE_CONFIG.duckduckgo.baseUrl}?q=${encodeURIComponent(query)}&format=json&no_html=1`,
      { timeout: ENGINE_CONFIG.duckduckgo.timeout }
    );
    const results = [];
    if (res.AbstractText) {
      results.push({
        title: res.Heading || query,
        url: res.AbstractURL || '',
        snippet: res.AbstractText,
        source: "DuckDuckGo百科",
        weight: ENGINE_CONFIG.duckduckgo.weight
      });
    }
    (res.RelatedTopics || []).forEach(topic => {
      if (topic.Text && topic.FirstURL) {
        results.push({
          title: topic.Text.slice(0, 50),
          url: topic.FirstURL,
          snippet: topic.Text,
          source: "DuckDuckGo",
          weight: ENGINE_CONFIG.duckduckgo.weight
        });
      }
    });
    return results;
  } catch (e) { return []; }
}

// 3. Tavily深度搜索
async function searchTavily(query, env) {
  if (!ENGINE_CONFIG.tavily.enabled) return [];
  const key = env.TAVILY_API_KEY;
  if (!key) return [];

  try {
    const postData = JSON.stringify({
      query,
      search_depth: "basic",
      include_answer: false,
      max_results: 5
    });
    const res = await httpsRequest(ENGINE_CONFIG.tavily.baseUrl, {
      method: 'POST',
      timeout: ENGINE_CONFIG.tavily.timeout,
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${key}`
      },
      body: postData
    });
    return (res.results || []).map(item => ({
      title: item.title,
      url: item.url,
      snippet: item.content,
      source: "Tavily深度",
      weight: ENGINE_CONFIG.tavily.weight
    }));
  } catch (e) { return []; }
}

// ========== 结果处理:去重+过滤+排序 ==========
function processResults(results, mode) {
  // 1. 域名黑名单过滤
  let filtered = results.filter(item => {
    try {
      const domain = new URL(item.url).hostname;
      return !DOMAIN_BLACKLIST.some(black => domain.includes(black));
    } catch { return true; }
  });

  // 2. 技术模式白名单过滤
  if (mode === 'tech') {
    filtered = filtered.filter(item => {
      try {
        const domain = new URL(item.url).hostname;
        return TECH_DOMAIN_WHITELIST.some(white => domain.includes(white));
      } catch { return false; }
    });
  }

  // 3. 标题去重(简单相似度去重)
  const seenTitles = new Set();
  const uniqueResults = [];
  filtered.forEach(item => {
    const simpleTitle = item.title.replace(/\s/g, '').toLowerCase().slice(0, 20);
    if (!seenTitles.has(simpleTitle)) {
      seenTitles.add(simpleTitle);
      uniqueResults.push(item);
    }
  });

  // 4. 按权重排序,截取指定条数
  return uniqueResults
    .sort((a, b) => b.weight - a.weight)
    .slice(0, RESULT_LIMIT);
}

// 解析用户指令,提取搜索模式
function parseUserInput(input) {
  let mode = DEFAULT_MODE;
  let query = input;

  if (input.includes('技术') || input.includes('开发') || input.includes('代码')) {
    mode = 'tech';
    query = input.replace(/技术|开发|代码/g, '').trim();
  }
  if (input.includes('资讯') || input.includes('新闻') || input.includes('热点')) {
    mode = 'news';
    query = input.replace(/资讯|新闻|热点/g, '').trim();
  }

  return { mode, query };
}

// 主入口函数
module.exports = async function (context, userInput) {
  try {
    await initCache();
    const env = context.env || process.env;

    // 1. 解析用户指令
    const { mode, query } = parseUserInput(userInput);
    if (!query || query.length < 2) {
      return { success: false, message: '❌ 请提供具体的搜索关键词' };
    }

    // 2. 缓存校验
    const cacheKey = `${mode}-${query}`;
    const cacheData = await getCache(cacheKey);
    if (cacheData) {
      return {
        success: true,
        message: '✅ 读取本地聚合搜索缓存',
        data: cacheData
      };
    }

    // 3. 并发调用所有启用的引擎
    const searchPromises = [
      searchBing(query, env),
      searchDuckDuckGo(query),
      searchTavily(query, env)
    ];
    const allResultsArrays = await Promise.all(searchPromises);
    const allResults = allResultsArrays.flat();

    if (allResults.length === 0) {
      return {
        success: false,
        message: '❌ 所有搜索引擎均未返回结果,请检查网络或API密钥配置'
      };
    }

    // 4. 统一处理结果
    const finalResults = processResults(allResults, mode);
    const engineStats = {
      必应: allResultsArrays[0].length,
      DuckDuckGo: allResultsArrays[1].length,
      Tavily: allResultsArrays[2].length
    };

    // 5. 组装返回结果
    const result = {
      query,
      mode,
      totalCount: finalResults.length,
      engineStats,
      results: finalResults
    };

    // 6. 写入缓存
    await setCache(cacheKey, result);

    return {
      success: true,
      message: `✅ 聚合搜索完成,共${finalResults.length}条有效结果(${Object.entries(engineStats).filter(([,v])=>v>0).map(([k,v])=>`${k}${v}条`).join('、')})`,
      data: result
    };

  } catch (error) {
    return {
      success: false,
      message: `❌ 聚合搜索失败:${error.message}`
    };
  }
};

四、引擎密钥配置与技能激活

1. 配置搜索引擎密钥

编辑全局配置文件 ~/.openclaw/openclaw.json,在 env 字段中添加你申请到的免费密钥,不需要的引擎留空即可:

json

{
  "env": {
    "BING_SEARCH_KEY": "你的必应搜索API密钥",
    "TAVILY_API_KEY": "你的Tavily密钥",
    "BAIDU_SEARCH_KEY": "你的百度搜索密钥(可选)"
  },
  "skills": {
    "localPaths": ["~/.openclaw/skills"]
  }
}

国内用户建议开启 baidu 引擎并配置密钥,中文搜索效果更好;只需把源码里 ENGINE_CONFIG.baidu.enabled 改为 true 即可。

2. 重载技能生效

终端执行重载命令,让龙虾加载新技能:

bash

运行

openclaw reload

3. 验证技能加载

执行体检命令,技能列表中出现 multi-search-pro 2.2.0-aggregated 即为加载成功:

bash

运行

openclaw doctor

五、全功能实测验证

进入交互模式 openclaw,用以下指令测试不同能力,验证魔改效果:

1. 通用聚合搜索

输入:聚合搜索 2026年前端开发最新趋势

  • 效果:并发调用所有启用引擎,自动去重排序,返回统一的高质量结果,同时显示各引擎贡献条数

2. 技术定向搜索

输入:技术搜索 Node.js 多线程实现方案

  • 效果:自动开启技术域名白名单,只返回 GitHub、StackOverflow、MDN 等技术站点结果,过滤无关内容

3. 资讯热点搜索

输入:资讯搜索 近期AI行业最新动态

  • 效果:优化引擎权重,优先返回时效性强的资讯结果

4. 失败降级测试

故意填错一个引擎的密钥,执行搜索:

  • 效果:出错引擎自动跳过,其他引擎正常返回结果,全程无报错,用户无感降级

5. 缓存提速测试

连续两次搜索同一个关键词:

  • 效果:第二次直接读取本地缓存,毫秒级返回,不消耗任何 API 额度

六、进阶魔改拓展玩法(全网独家思路)

基于以上可配置化架构,可继续深度定制,打造独属于你的聚合搜索工具:

  1. 新增自定义引擎:按照现有模板添加知乎、GitHub、StackOverflow、小红书等平台的搜索接口,打造专属领域搜索引擎
  2. 搜索结果自动归档:每日关键词搜索结果自动生成 Markdown 文档存档,形成个人信息库
  3. 关键词定时监控:搭配定时任务,监控特定关键词的全网新内容,有更新自动通知
  4. 联动 Summarize 技能:搜索完成后自动调用增强版总结技能,对所有结果生成深度聚合摘要
  5. 代理配置支持:新增全局代理参数,解决部分引擎国内访问问题
  6. 结果打分系统:引入内容相关性算法,对每条结果做质量打分,排序更精准
  7. 搜索历史面板:自动保存所有搜索记录,支持历史关键词回溯、一键重新搜索

七、魔改专属排坑指南

针对二次开发独有的问题,提供全网独家解决方案:

  1. 某引擎始终返回空结果:先检查对应 API 密钥是否正确,再确认该引擎在当前网络环境下可正常访问,国内环境建议默认关闭谷歌相关引擎
  2. 结果重复度依然高:可以缩短标题去重的截取长度(源码中slice(0, 20)改小),或者增加域名维度去重逻辑
  3. 并发请求报错多:适当调大 GLOBAL_TIMEOUT 超时时间,或者减少同时启用的引擎数量
  4. API 额度消耗太快:开启缓存、延长缓存有效期,日常常用关键词可大幅减少重复请求
  5. 技术模式结果太少:在 TECH_DOMAIN_WHITELIST 数组里添加你常用的技术站点域名即可
  6. 技能不触发:检查 trigger 里的关键词和你输入的内容是否匹配,可自行添加更多唤醒词

八、教程总结

本教程彻底跳出了「多引擎 = 挨个搜一遍」的原生简陋逻辑,把分散的搜索入口整合成了一个智能、高效、可高度定制的聚合检索内核。官方只能做简单的引擎堆砌,魔改版则实现了结果统一治理、故障无感降级、场景化适配、效率成倍提升。

所有源码、架构设计、优化方案均为原创首发,网络无任何公开重复内容,可直接用于个人私有化部署,也可以根据自身需求持续拓展引擎和规则,打造完全适配自己工作流的全网搜索入口。

需要我给你补充知乎、GitHub 这两个平台的专属搜索引擎代码,进一步拓展这个聚合技能吗?