Community寫作與編輯github.com

Sakurakilove/local-search

完全在使用者機器上執行的網頁搜尋技能 — 無需 Z.AI 或雲端 SDK 依賴。直接解析 DuckDuckGo / Bing / Google 的 HTML,並具備自動引擎備援功能。

local-search 是什麼?

這個技能(名為 `local-search`)讓 AI 代理程式(例如 Claude Code、Coder 或 Codex)能夠直接在本地機器上執行網頁搜尋,而不需仰賴任何雲端 API 或 SDK。它透過直接解析 DuckDuckGo、Bing 和 Google 的 HTML 來運作,並內建自動引擎備援機制:若某個引擎發生速率限制,系統會無縫地切換至下一個引擎,從而提高各種網路環境(包括資料中心 IP)下的成功率和穩健性。每個搜尋結果皆遵循標準化的 `SearchFunctionResultItem` 結構,包含 URL、名稱、摘要等常見欄位,以及原始引擎來源和分數等擴展欄位,確保與其他採用相同結構的網頁搜尋技能相容。此技能主要支援基於 TypeScript 的 Node.js 環境(Node 18+),可透過 CLI(使用 `tsx` 或 `bun`)執行一次性查詢,也可作為 SDK 整合至應用程式中,僅需一個執行時期相依套件(`cheerio`)和 Node 內建的 `fetch` 函式。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add Sakurakilove/local-search

Installed? Explore more 寫作與編輯 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

預覽

來自技能 README

ClawHub
Version
License: MIT
Node

說明文件

Local Search 技能

具備自動引擎備援的本地網頁搜尋。 直接解析 DuckDuckGo / Bing / Google 的 HTML · 對抗速率限制 · 標準化結果結構。

ClawHub Version License: MIT Node

這個技能會直接從您的機器呼叫公開搜尋引擎。無需 API 金鑰、無需 SDK、無需經過網路跳轉。 如果某個引擎對您進行速率限制,協調器會默默切換至下一個引擎,因此呼叫通常能在第一次就成功,即使在 Google 被封鎖的資料中心 IP 上也是如此。

每個結果都是一個 SearchFunctionResultItem,包含標準的 7 個欄位(url、name、snippet、host_name、rank、date、favicon)以及三個選用的擴展欄位:source_engine、raw_html、score。針對任何其他採用類似結構的網頁搜尋技能所編寫的消費端程式碼,在此處無需修改即可運作。

✨ 重點特色

  • 零雲端 SDK 依賴 — 僅需 cheerio(HTML 解析器)和 Node 內建的 fetch。
  • 三個引擎,自動備援 — 當 engine: "auto"(預設值)時,依序嘗試 DuckDuckGo → Bing → Google。
  • 支援地區語言 — --locale en-US / zh-CN / ja-JP 或任何 BCP-47 標籤。對於非美國 IP 來說至關重要,因為 Bing 即使在英文查詢下也會提供本地化結果。
  • 時間過濾器 — --recency-days 7 限制為過去一週的結果。DDG 支援精確的 N 天;Bing/Google 使用日/週/月區間。
  • 標準化結果結構 — url / name / snippet / host_name / rank / date / favicon 欄位,與 ClawHub 註冊表中其他網頁搜尋技能的形式完全相同。
  • CLI + SDK — 使用 tsx bin/web-search.ts <query> 進行一次性查詢,或在程式碼中使用 import { search } from "local-search"。
  • 純 TypeScript ESM — 可在 Node 18+ 上透過 tsx 執行,或透過 bun 零配置執行。

🚀 快速開始

# 1. 安裝(一個執行時期相依套件:cheerio)
cd skills/local-search && npm install

# 2. 搜尋(自動備援:DDG → Bing → Google)
tsx bin/web-search.ts "artificial intelligence"

# 3. 指定特定引擎和地區語言
tsx bin/web-search.ts "machine learning" --engine bing --locale en-US --num 5

# 4. 以 JSON 格式輸出近期新聞
tsx bin/web-search.ts "AI breakthroughs" --recency-days 7 --json -o ai_news.json

程式化使用範例:

import { search } from "local-search";

const outcome = await search("What is the capital of France?", { num: 5 });
if (outcome.success) {
  console.log(`由 ${outcome.engine} 回應,耗時 ${outcome.elapsedMs} 毫秒`);
  outcome.results.forEach(r => console.log(`- ${r.name}\n  ${r.url}`));
}

🎯 何時使用此技能

當使用者需要的資訊存在於公開網路上,且超出模型訓練資料的範圍時,請使用 local-search:

  • 即時資訊:最新新聞、股價、天氣、體育賽事比分
  • 最新文件:框架發行說明、API 變更、近期發表的論文
  • 事實查核:比對聲明與即時網路來源
  • 研究:收集關於某個主題的多個來源,比較觀點
  • 內容發現:尋找教學文章、部落格貼文、近期演講
  • 競爭/市場分析:競爭對手公告、產業趨勢
  • 學術查詢:尋找論文、引用、作者頁面

🔄 引擎比較

引擎端點API 金鑰住宅 IP資料中心 IP時間過濾器
DuckDuckGohtml.duckduckgo.com/html/ (GET)無✅ 高⚠️ 負載下會速率限制df=d<N> (精確天數)
Bingwww.bing.com/search無✅ 高✅ 高freshness=d1|w1|m1 (區間)
Googlewww.google.com/search無⚠️ 中等❌ 低 (enablejs 牆)tbs=qdr:d|w|m|y (區間)

engine: "auto" 會依序嘗試 DuckDuckGo → Bing → Google,並回傳第一個非空的結果集。從資料中心 IP 來看,有效的鏈結是 DDG → Bing(Google 通常被封鎖);從住宅 IP 來看,三個引擎均可使用。請編輯 src/engines/index.ts 中的 AUTO_ENGINE_ORDER 來變更優先順序。

📦 安裝路徑

建議位置:{project_path}/skills/local-search

將此技能套件解壓縮至專案中的上述路徑。

前置需求

  • Node.js >= 18(使用內建的全域 fetch)。
  • 一個 npm 相依套件:cheerio(HTML 解析器)。
  • 可用的網際網路連線 — 此技能會直接呼叫公開搜尋引擎。

在技能目錄中安裝一次:

cd {project_path}/skills/local-search
npm install            # 或:bun install / pnpm install

此技能是純 TypeScript ESM。您可以透過 tsx(推薦,開發者友善)或 bun(零配置)來執行。在 Node 22+ 上也可以使用 node --experimental-strip-types bin/web-search.ts 來執行(與執行時期無關)。

為什麼選擇本地端?

方面雲端搜尋技能此技能 (local-search)
搜尋後端雲端函式 / API直接 HTTP 連接 DuckDuckGo / Bing / Google
API 金鑰 / SDK需要無
網路路徑客戶端 → 雲端 → 搜尋引擎客戶端 → 搜尋引擎
失敗處理取決於 SDK自動備援至 3 個引擎
結果結構SearchFunctionResultItem (7 個欄位)相同 7 個欄位 + 3 個選用擴展欄位
CLI取決於 SDKtsx bin/web-search.ts

架構

local-search/
├── SKILL.md                 ← 您在這裡
├── LICENSE.txt
├── package.json             ← 宣告 `cheerio` 相依套件
├── tsconfig.json
├── bin/
│   └── web-search.ts        ← CLI 進入點
├── src/
│   ├── index.ts             ← 公開 SDK 匯出
│   ├── search.ts            ← 具備自動備援的協調器
│   ├── types.ts             ← SearchFunctionResultItem + 選項
│   └── engines/
│       ├── _shared.ts       ← fetch / parse 輔助函式
│       ├── duckduckgo.ts    ← POST https://html.duckduckgo.com/html/
│       ├── bing.ts          ← GET https://www.bing.com/search
│       ├── google.ts        ← GET https://www.google.com/search
│       └── index.ts         ← 引擎註冊表 + AUTO_ENGINE_ORDER
└── scripts/
    └── web_search.ts        ← 快速開始範例

唯一的執行時期相依套件是 cheerio(HTML 解析器),在 package.json 中宣告。Node 18+ 內建的 fetch 涵蓋了網路層 — 此套件中未匯入任何其他 SDK。

CLI 使用方式

CLI 位於 bin/web-search.ts。請透過 tsx、bun 或任何支援 TypeScript 的執行器來執行。

基本搜尋

# 預設:自動引擎,10 個結果,人類可讀輸出
tsx bin/web-search.ts "artificial intelligence"

# 限制結果數量
tsx bin/web-search.ts "machine learning" --num 5
# (也支援短選項)
tsx bin/web-search.ts "machine learning" -n 5

指定特定引擎

# 僅強制使用 DuckDuckGo
tsx bin/web-search.ts "latest tech news" --engine duckduckgo
# 僅強制使用 Bing
tsx bin/web-search.ts "latest tech news" --engine bing
# 僅強制使用 Google(品質最高,但最可能被速率限制)
tsx bin/web-search.ts "latest tech news" --engine google
# 預設 — 嘗試 DDG → Bing → Google,回傳第一個非空結果
tsx bin/web-search.ts "latest tech news" --engine auto

時間過濾器

# 過去 7 天的結果
tsx bin/web-search.ts "cryptocurrency news" --num 10 --recency-days 7
# (短選項)
tsx bin/web-search.ts "cryptocurrency news" -r 7

將結果儲存為 JSON

# 將 JSON 寫入檔案(會抑制人類可讀的標題)
tsx bin/web-search.ts "climate change research" --num 5 --json -o search_results.json

# 或將 JSON 輸出至 stdout
tsx bin/web-search.ts "AI breakthroughs" --num 3 --recency-days 1 --json > ai_news.json

安靜模式(腳本 / 管道)

# 抑制「引擎 / 時間」標題 — 僅印出結果
tsx bin/web-search.ts "react hooks" --quiet

CLI 參數

旗標短選項說明
--num <N>-n結果數量(預設:10,最大值:50)
--engine <id>-educkduckgo | bing | google | auto(預設:auto)
--recency-days <N>-r限制為過去 N 天內的結果(預設:0 = 無過濾)
--timeout <ms>—每個引擎的超時時間,單位為毫秒(預設:8000)
--json—輸出 JSON 而非人類可讀格式
--output <path>-o將 JSON 寫入檔案而非 stdout
--pretty—美化 JSON 輸出(預設啟用;傳遞 --no-pretty 可停用 — 尚未支援,請改用 --json)
--quiet-q抑制引擎資訊標題
--help-h顯示說明

搜尋結果結構

每個結果項目都是一個 SearchFunctionResultItem:

interface SearchFunctionResultItem {
  // ----- 標準欄位(與 ClawHub 上的其他網頁搜尋技能共享的結構) -----
  url: string;          // 結果的完整 URL
  name: string;         // 頁面標題
  snippet: string;      // 預覽文字 / 說明
  host_name: string;    // 網域名稱(例如 "en.wikipedia.org")
  rank: number;         // 在該引擎結果集中的 1 起始排名
  date: string;         // 發布 / 更新日期;未知時為 "N/A"
  favicon: string;      // 網站圖示 URL(Google S2)

  // ----- 擴展欄位(local-search 新增) -----
  source_engine: "duckduckgo" | "bing" | "google";
  raw_html?: string;    // 摘要元素的原始 HTML(選用)
  score?: number;       // 啟發式相關性評分 [0, 100](選用)
}

SDK 使用方式

如果您正在編寫 TypeScript/JavaScript 程式碼(而非執行 CLI),請從 src/index.ts 匯入:

簡單搜尋

import { search } from "local-search";

const outcome = await search("What is the capital of France?", { num: 5 });

if (outcome.success) {
  console.log(`使用的引擎:${outcome.engine}`);
  console.log(`嘗試順序:${outcome.enginesTried.join(" → ")}`);
  console.log(`耗時:${outcome.elapsedMs} 毫秒`);
  for (const item of outcome.results) {
    console.log(`- ${item.name}  [${item.source_engine}]`);
    console.log(`  ${item.url}`);
    console.log(`  ${item.snippet}`);
  }
} else {
  console.error("搜尋失敗:", outcome.error);
  if (outcome.errors) {
    // 自動模式:查看嘗試了哪些引擎及其回報的錯誤
    for (const e of outcome.errors) {
      console.error(`  ${e.engine}:`, e.error);
    }
  }
}

失敗即拋出例外變體

import { searchOrThrow, AllEnginesFailedError } from "local-search";

try {
  const results = await searchOrThrow("JavaScript frameworks", { num: 10 });
  console.log(results);
} catch (err) {
  if (err instanceof AllEnginesFailedError) {
    console.error("所有引擎均失敗:", err.errors);
  } else {
    console.error("單一引擎錯誤:", err);
  }
}

指定特定引擎

import { search } from "local-search";

// 跳過備援鏈結 — 僅使用 DuckDuckGo。
const outcome = await search("quantum computing applications", {
  num: 8,
  engine: "duckduckgo",
});

時間過濾器

const outcome = await search("genomics research", {
  num: 5,
  recency_days: 30, // 過去 30 天
});

自訂 Fetch 實作(測試 / Edge 執行時期)

const outcome = await search("hello world", {
  fetchImpl: myMockFetch, // 任何符合 WhatWG-fetch 規範的函式
  userAgent: "my-bot/1.0",
  timeoutMs: 5000,
});

引擎後端

DuckDuckGo (duckduckgo)

  • 端點:https://html.duckduckgo.com/html/(POST 表單 q=...)
  • 無 API 金鑰。受到粗糙的速率限制 — 持續的大量請求會回傳空結果集。
  • 時間過濾器:df=d<N> 表單欄位。
  • 最佳使用時機:預設的第一個嘗試;很少被直接封鎖;尊重隱私。

Bing (bing)

  • 端點:https://www.bing.com/search?q=...&count=...
  • 無 API 金鑰。HTML 佈局穩定且易於解析。
  • 時間過濾器:freshness=d1 / w1 / m1 區間(Bing 沒有任意 N 天的 URL 過濾器)。
  • 最佳使用時機:第二個備援;良好的英文結果;偶爾有地區語言問題(可透過 ensearch=1 緩解)。

Google (google)

  • 端點:https://www.google.com/search?q=...&num=...
  • 無 API 金鑰,但 Google 對阻擋爬蟲最為積極。從 資料中心 / 雲端 IP 發出請求時,Google 通常會回傳一個「請啟用 JavaScript」的重新導向頁面(/httpservice/retry/enablejs),其中包含零個可解析的結果 — 引擎會將其視為軟失敗,自動鏈結會繼續往下嘗試。從 住宅 IP 發出請求時,Google HTML 解析通常可以正常運作。
  • 時間過濾器:tbs=qdr:d|w|m|y 區間。
  • 最佳使用時機:住宅 IP 上的最後備援;在雲端 IP 上通常會失敗(此時 DDG+Bing 已能滿足需求)。

自動備援策略

當 engine: "auto"(預設值)時,協調器會依下列順序嘗試引擎:

  1. DuckDuckGo — 最不積極的阻擋,最精細的日期過濾器
  2. Bing — 通常對任何 IP 都穩定,包括資料中心
  3. Google — 可連線時結果品質最佳;在資料中心 IP 上常被封鎖

它會回傳第一個產生 ≥ 1 個結果的引擎。如果所有三個引擎都失敗,結果會是 { success: false, errors: [...] },並附上每個引擎的錯誤 — 或者,在 searchOrThrow 模式下,會拋出 AllEnginesFailedError 例外。

實用可靠性表格(測試期間觀察到的情況):

呼叫者 IP 類型DDGBingGoogle有效的自動鏈結
住宅高高中等DDG → Bing → Google (3 個可用)
資料中心 / 雲端中等 (負載下會速率限制)高低 (enablejs 牆)實際為 DDG → Bing

順序定義在 src/engines/index.ts(AUTO_ENGINE_ORDER)中;如果您想要不同的優先順序,請編輯該陣列。

常見使用案例

  1. 即時資訊 — 取得模型訓練資料截止日期後的新聞、股價、天氣、體育賽事比分。
  2. 最新文件 — 擷取框架發行說明、API 變更、近期發表的論文。
  3. 事實查核 — 比對 AI 產生的聲明與即時網路來源。
  4. 研究 — 收集關於一個主題的多個來源,比較不同觀點。
  5. 內容發現 — 尋找特定主題的教學文章、部落格貼文、近期演講。
  6. 競爭 / 市場分析 — 監控競爭對手公告、產業趨勢。
  7. 學術查詢 — 尋找論文、引用、作者頁面。

相關技能