🚀 Search Stack
Search Stack 是 AI Agent 專用的 Web 搜索與抓取中間層,為 OpenClaw、Claude Code、Dify 等 AI 智能體提供統一的 Web 訪問 API。它具備多引擎搜索自動 fallback、無頭 Chrome 反爬渲染、Cookie 注入登錄態、正文精準提取等功能,一次部署,所有 Agent 均可共用。
🚀 快速開始
Search Stack 為 AI 智能體提供了強大的 Web 搜索與抓取能力。以下是快速部署和使用的步驟:
前置要求
- Docker + Docker Compose
- (可選)Tavily API Key — 免費 1000 次/月
- (可選)Serper API Key — 免費 2500 次
不配 Tavily / Serper 也能用,會自動 fallback 到 SearXNG(完全免費)。
1. 克隆項目
git clone https://github.com/pinkpills/search-stack.git
cd search-stack
2. 配置環境變量
cp .env.example .env
編輯 .env:
TAVILY_API_KEY=your_tavily_key
SERPER_API_KEY=your_serper_key
SEARXNG_SECRET=
PROXY_API_KEY=
BROWSERLESS_TOKEN=
REDIS_PASSWORD=
一鍵生成隨機密鑰:
python3 -c "
import secrets
for name in ['SEARXNG_SECRET', 'PROXY_API_KEY', 'BROWSERLESS_TOKEN', 'REDIS_PASSWORD']:
print(f'{name}={secrets.token_hex(16)}')
" >> .env
3. 配置 SearXNG
必做! 不做這步 SearXNG 的 JSON API 會返回 403。
cp searxng/settings.yml.example searxng/settings.yml
編輯 searxng/settings.yml,確保包含:
search:
formats:
- html
- json
如果你之前已經啟動過 SearXNG(它會自動生成 settings.yml),需要手動加上 formats 配置後重啟容器。
4. 啟動服務
docker compose -f search-stack.yml up -d
等待所有容器健康(約 30 秒):
docker compose -f search-stack.yml ps
全部顯示 healthy 即完成。
5. 驗證
curl -s -H "X-API-Key: YOUR_PROXY_API_KEY" http://127.0.0.1:17080/health | python3 -m json.tool
curl -s -X POST http://127.0.0.1:17080/search \
-H "X-API-Key: YOUR_PROXY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "hello world", "count": 3}' | python3 -m json.tool
curl -s -X POST http://127.0.0.1:17080/search \
-H "X-API-Key: YOUR_PROXY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "hello world", "count": 3, "provider": "searxng"}' | python3 -m json.tool
curl -s -X POST http://127.0.0.1:17080/fetch \
-H "X-API-Key: YOUR_PROXY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "render": false}' | python3 -m json.tool
提示: 如果 SearXNG 返回 502 或空結果,大概率是缺少 formats: [html, json] 配置,參見步驟 3。
✨ 主要特性
- 多引擎 Fallback — Tavily → Serper → SearXNG 按優先級自動切換,單引擎掛不影響服務。
- 搜索 + 抓取一體 —
/search 搜索,/fetch 抓取正文,enrich=true 搜索後自動抓取全文。
- 抗反爬 — Browserless Stealth 模式,繞過 Cloudflare / JS Challenge。
- 正文提取 — trafilatura + BeautifulSoup + readability 三引擎,精準提取正文。
- Cookie 管理 — API 動態增刪 Cookie,自動注入 Chrome 渲染,支持直接粘貼瀏覽器 Cookie。
- 登錄/反爬檢測 — 多維度啟發式檢測:HTTP 狀態碼(401/403)、文本關鍵詞(中英日)、頁面標題、HTML 結構(密碼框、CAPTCHA 嵌入、meta refresh 重定向)、SPA 登錄牆,返回
needs_login 標記引導 Cookie 更新。
- Cookie Catcher — 瀏覽器內遠程登錄:通過 WebSocket + CDP Screencast 在 Web UI 中操控遠程 Chrome 完成登錄,一鍵保存 Cookie。
- SSRF 防護 — 拒絕訪問私網 IP(127/10/172.16/192.168/169.254)。
- URL 去重 — 自動去除追蹤參數(utm_*、fbclid 等),同域名結果限制。
- Redis 緩存 — 15 分鐘 TTL,重複查詢即時返回。
- API Key 鑑權 + 限流 — 滑動窗口限流。
- MCP Server — stdio 模式 MCP Server(
mcp-server.ts),可通過 mcporter 註冊供 OpenClaw 等 Agent 使用。
- TikHub 社交媒體 API — 可選集成,代理 TikHub 803 個社交平臺工具(抖音、TikTok、微博等),內置自動回退。
- HTTP 代理 — 支持 HTTP / SOCKS5 代理,用於反爬固定 IP 或翻牆訪問被牆網站(YouTube 等)。
- 全異步 — async Redis + 共享 httpx 連接池,高併發低延遲。
📦 安裝指南
前置要求
- Docker + Docker Compose
- (可選)Tavily API Key — 免費 1000 次/月
- (可選)Serper API Key — 免費 2500 次
克隆項目
git clone https://github.com/pinkpills/search-stack.git
cd search-stack
配置環境變量
cp .env.example .env
編輯 .env 並可一鍵生成隨機密鑰:
python3 -c "
import secrets
for name in ['SEARXNG_SECRET', 'PROXY_API_KEY', 'BROWSERLESS_TOKEN', 'REDIS_PASSWORD']:
print(f'{name}={secrets.token_hex(16)}')
" >> .env
配置 SearXNG
cp searxng/settings.yml.example searxng/settings.yml
編輯 searxng/settings.yml 確保包含 formats: [html, json],若之前啟動過需手動添加並重啟容器。
啟動服務
docker compose -f search-stack.yml up -d
等待容器健康:
docker compose -f search-stack.yml ps
驗證
curl -s -H "X-API-Key: YOUR_PROXY_API_KEY" http://127.0.0.1:17080/health | python3 -m json.tool
curl -s -X POST http://127.0.0.1:17080/search \
-H "X-API-Key: YOUR_PROXY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "hello world", "count": 3}' | python3 -m json.tool
curl -s -X POST http://127.0.0.1:17080/search \
-H "X-API-Key: YOUR_PROXY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "hello world", "count": 3, "provider": "searxng"}' | python3 -m json.tool
curl -s -X POST http://127.0.0.1:17080/fetch \
-H "X-API-Key: YOUR_PROXY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "render": false}' | python3 -m json.tool
💻 使用示例
基礎用法
curl -s -X POST http://127.0.0.1:17080/search \
-H "X-API-Key: KEY" -H "Content-Type: application/json" \
-d '{"query": "Docker best practices", "count": 5}'
curl -s -X POST http://127.0.0.1:17080/search \
-H "X-API-Key: KEY" -H "Content-Type: application/json" \
-d '{"query": "Python asyncio", "count": 3, "enrich": true}'
curl -s -X POST http://127.0.0.1:17080/search \
-H "X-API-Key: KEY" -H "Content-Type: application/json" \
-d '{"query": "AI news", "count": 5, "provider": "searxng"}'
高級用法
curl -s -X POST http://127.0.0.1:17080/fetch \
-H "X-API-Key: KEY" -H "Content-Type: application/json" \
-d '{"url": "https://example.com", "render": false}'
📚 詳細文檔
與 Brave Search 對比
| 維度 |
Search Stack |
Brave Search(OpenClaw 內置) |
| 搜索速度 |
0.8 - 1.5s(Tavily/Serper) |
~1 - 2s |
| 緩存命中 |
13ms(Redis 緩存 15 分鐘) |
無緩存,每次重新請求 |
| 中文搜索 |
結果豐富(掘金、知乎、什麼值得買等) |
中文結果偏少,偏英文源 |
| 英文搜索 |
優秀 |
優秀 |
| 高可用 |
三引擎自動 fallback |
單點,掛了就沒了 |
| 全文抓取 |
enrich=true 搜索+正文一步到位 |
只返回摘要,需額外抓取 |
| 反爬站點 |
Browserless Chrome 渲染 |
無法抓取 |
| 需登錄站點 |
Cookie 注入 + 自動檢測引導 |
不支持 |
| 免費額度 |
SearXNG 無限量兜底 |
免費 Key 有嚴格限制 |
結論:搜索速度持平,中文質量更好,功能遠超 Brave。
架構
+-----------+
AI Agent ──────────>| search- |──> Tavily API
(OpenClaw / Claude) | proxy |──> Serper API (Google)
POST /search | (FastAPI) |──> SearXNG (self-hosted)
POST /fetch +-----+-----+
|
+-------------+-------------+
| |
+-----+-----+ +--------+--------+
| Redis | | Browserless |
| (cache + | | (headless Chrome |
| rate-limit)| | anti-bot render)|
+------------+ +-----------------+
四個容器,一鍵啟動:
| 服務 |
作用 |
| search-proxy |
FastAPI 核心代理,統一搜索/抓取接口 |
| Redis |
結果緩存(15 分鐘 TTL)+ API 限流計數 |
| SearXNG |
自託管元搜索引擎(聚合 Google、DuckDuckGo、Brave 等,免費無限量) |
| Browserless |
無頭 Chrome,渲染 JS 頁面,Stealth 模式繞過反爬 |
集成 OpenClaw
方式一:原生插件(推薦)
openclaw plugins install --link /opt/search-stack/plugin/
- 步驟 2:配置
編輯
~/.openclaw/openclaw.json,在 plugins.entries 中添加:
{
"plugins": {
"entries": {
"search-stack": {
"enabled": true,
"config": {
"apiUrl": "http://127.0.0.1:17080",
"apiKey": "your_proxy_api_key",
"tikhubApiKey": "your_tikhub_key"
}
}
}
}
}
apiKey 的值就是 .env 中的 PROXY_API_KEY。
tikhubApiKey 可選,填入 TikHub API Key 可啟用社交媒體 API。
注意: 配置必須放在 config 嵌套對象內,不能直接放在 search-stack 下。
- 步驟 3:禁用內置 Brave 搜索
編輯
~/.openclaw/openclaw.json:
{
"tools": {
"web": {
"search": {
"enabled": false
}
}
}
}
mkdir -p ~/.openclaw/workspace/skills/web-search/
cp /opt/search-stack/skill-template/SKILL.md ~/.openclaw/workspace/skills/web-search/SKILL.md
sudo systemctl restart openclaw
openclaw plugins list
重要: 如果 AI 仍在使用舊方式,需要歸檔舊 session。OpenClaw 的會話上下文會緩存之前的工具模式,即使配置已更新,舊 session 仍會沿用舊行為。詳見下方「常見問題 → AI 不使用 search-stack」。
方式二:MCP + mcporter(備選)
curl -fsSL https://bun.sh/install | bash
bun add -g @modelcontextprotocol/sdk zod
- 步驟 2:註冊到 mcporter
編輯
~/.mcporter/mcporter.json,添加 search-stack:
{
"mcpServers": {
"search-stack": {
"command": "/home/your_user/.bun/bin/bun",
"args": ["run", "/opt/search-stack/proxy/mcp-server.ts"],
"keepAlive": true,
"env": {
"SEARCH_STACK_URL": "http://127.0.0.1:17080",
"SEARCH_STACK_API_KEY": "your_proxy_api_key",
"TIKHUB_API_KEY": "your_tikhub_key"
}
}
}
}
驗證註冊:
mcporter daemon restart
mcporter list
- 步驟 3:創建 Skill 並重啟
創建
~/.openclaw/workspace/skills/web-search/SKILL.md(使用 mcporter exec 調用格式),禁用 Brave 搜索,重啟 OpenClaw。
注意: MCP+mcporter 方式中,AI 通過 exec 工具執行 mcporter call search-stack.* 命令。超時時 SIGKILL 會導致零輸出,AI 可能認為"搜索引擎掛了"。推薦使用原生插件方式避免此問題。
異地部署(OpenClaw 和 Search Stack 在不同機器)
- 步驟 1:服務器 A — 配置反向代理(HTTPS)
location /search-stack/ {
proxy_pass http://127.0.0.1:17080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
安全提醒: API Key 會在請求頭中明文傳輸,必須使用 HTTPS。建議用 Certbot 自動申請 Let's Encrypt 證書。
git clone https://github.com/pinkpills/search-stack.git /opt/search-stack
cd /opt/search-stack/plugin && npm install
mkdir -p /opt/search-stack && cd /opt/search-stack
git clone --depth 1 --filter=blob:none --sparse \
https://github.com/pinkpills/search-stack.git .
git sparse-checkout set plugin skill-template
cd plugin && npm install
- 步驟 3:服務器 B — 安裝插件到 OpenClaw
openclaw plugins install --link /opt/search-stack/plugin/
- 步驟 4:服務器 B — 配置遠程 API 地址
編輯
~/.openclaw/openclaw.json:
{
"plugins": {
"entries": {
"search-stack": {
"enabled": true,
"config": {
"apiUrl": "https://search.example.com/search-stack",
"apiKey": "your_proxy_api_key",
"publicUrl": "https://search.example.com/search-stack",
"tikhubApiKey": "your_tikhub_key"
}
}
}
},
"tools": {
"web": {
"search": {
"enabled": false
}
}
}
}
配置說明:
| 字段 |
說明 |
apiUrl |
服務器 A 的 Search Stack API 地址(通過 Nginx 代理後的 HTTPS URL) |
apiKey |
服務器 A .env 中的 PROXY_API_KEY |
publicUrl |
Cookie Catcher 鏈接中使用的公網 URL(用戶瀏覽器需要能訪問),通常與 apiUrl 相同 |
tikhubApiKey |
(可選)TikHub API Key |
- 步驟 5:服務器 B — 創建 Skill 並重啟
mkdir -p ~/.openclaw/workspace/skills/web-search/
cp /opt/search-stack/skill-template/SKILL.md ~/.openclaw/workspace/skills/web-search/SKILL.md
sudo systemctl restart openclaw
驗證
在 OpenClaw 中對話測試:
用戶: "搜索一下 Claude Opus 4.6 評測"
AI: 調用 web_search → 返回結果(來自遠程 Search Stack)
用戶: "打開第一條鏈接看看全文"
AI: 調用 page_fetch → 返回全文(遠程 Browserless 渲染)
如果工具調用失敗,檢查:
- 服務器 B 能否訪問
apiUrl:curl -H "X-API-Key: KEY" https://search.example.com/search-stack/health
- 插件是否加載:
openclaw plugins list
- 舊 session 緩存:歸檔舊 session 後重啟(詳見「常見問題 → AI 不使用 search-stack」)
多機併發與資源控制
| 客戶端數 |
MAX_CONCURRENT_SESSIONS |
memory |
服務器內存建議 |
| 1 - 2 臺 |
5 |
2g |
4GB+ |
| 3 - 5 臺 |
10 |
4g |
8GB+ |
| 5 - 10 臺 |
20 |
8g |
16GB+ |
超出併發上限時,Browserless 會將請求排隊等待;隊列也滿時返回 429,page_fetch 會報錯但不影響搜索功能(web_search 不依賴 Chrome)。Cookie Catcher 另有 2 會話硬限制,多人同時登錄需排隊。
工具列表
| 工具 |
說明 |
web_search |
多引擎搜索,支持 enrich 全文抓取 |
page_fetch |
抓取網頁正文,支持 Cookie 注入 + Chrome 渲染 + 登錄檢測 |
cookies_list |
列出已配置 Cookie 的域名 |
cookies_update |
添加/更新域名 Cookie(支持 raw 字符串粘貼) |
cookies_delete |
刪除域名 Cookie |
cookie_catcher_link |
生成遠程瀏覽器登錄鏈接(Cookie Catcher) |
tikhub_call |
調用 TikHub 社交媒體 API(需配置 Key,按需使用) |
注意: 抓取工具名為 page_fetch 而非 web_fetch。這是為了避免與 OpenClaw 內置的 web_fetch 工具名衝突。內置 web_fetch 不支持 Cookie 注入和 Chrome 渲染,使用同名會導致 AI 調用錯誤的工具。
Cookie 工作流實戰
方式一:手動複製粘貼(適用於桌面端)
用戶: "幫我看看這個網頁 https://zhuanlan.zhihu.com/p/xxxx"
AI: 調用 page_fetch → 正文不完整(只有標題/摘要)
AI: "這個網站的反爬比較嚴格,正文沒有完整抓到。
如果你需要完整內容,可以提供該網站的 Cookie:
1. 在瀏覽器中打開該網址並登錄
2. 按 F12 → Network 標籤 → 刷新頁面
3. 找到請求頭中的 Cookie: 一行
4. 複製整個值發給我"
用戶: "z_c0=xxx; _xsrf=yyy; d_c0=zzz ..."
AI: 自動提取域名 zhihu.com → cookies_update → 保存成功
AI: 用 bypass_cache:true 重新抓取 → 拿到完整文章內容
方式二:Cookie Catcher 遠程登錄(適用於複雜登錄流程)
1. 瀏覽器打開:http://YOUR_HOST:17080/cookie-catcher?key=API_KEY&url=https://threads.net
2. 在遠程 Chrome 畫面中完成登錄(支持鼠標/鍵盤/觸屏操作)
3. 點擊 "Save Cookies" → 自動保存到 cookies.json
4. 後續 /fetch 請求自動注入 Cookie
適合需要 OAuth 跳轉、二維碼掃碼、手機驗證碼等複雜登錄場景。
🔧 技術細節
API 文檔
所有請求需攜帶 X-API-Key 頭部。
GET /health
健康檢查。
{
"ok": true,
"redis": true,
"order": ["tavily", "serper", "searxng"],
"browserless_configured": true,
"dedupe": { "enabled": true, "max_per_host": 2 }
}
POST /search
Web 搜索。
| 參數 |
類型 |
默認值 |
說明 |
query |
string |
必填 |
搜索關鍵詞 |
count |
int |
5 |
返回結果數(1 - 10) |
provider |
string |
自動 |
強制指定:tavily / serper / searxng |
enrich |
bool |
false |
抓取每條結果的網頁全文 |
max_chars |
int |
8000 |
enrich 時每頁最大字符數 |
render |
bool |
true |
用無頭瀏覽器渲染 |
concurrency |
int |
3 |
enrich 併發抓取數 |
POST /fetch
抓取網頁正文。
| 參數 |
類型 |
默認值 |
說明 |
url |
string |
必填 |
目標 URL |
render |
bool |
true |
用無頭瀏覽器渲染 |
max_chars |
int |
20000 |
最大提取字符數 |
timeout |
float |
25 |
超時秒數 |
headers |
object |
null |
自定義請求頭 |
bypass_cache |
bool |
false |
跳過緩存(更新 Cookie 後用) |
當頁面需要登錄或被反爬攔截時,返回 needs_login: true:
{
"needs_login": true,
"has_cookies": false
}
has_cookies: true 時表示已有 Cookie 但已過期,需要重新導出。
檢測規則覆蓋以下信號(按優先級排列):
| 信號 |
條件 |
示例 |
| HTTP 401 |
直接判定 |
API 端點未認證 |
| HTTP 403 + 短內容 |
text < 2000 字符 |
訪問被拒絕頁面 |
| 文本登錄關鍵詞 |
1 hit + < 500 字符,或 2+ hits |
"請登錄"、"sign in to continue"、"verify you are human" |
| 頁面標題含登錄詞 |
+ text < 2000 字符 |
<title>Sign In - Example</title> |
| HTML 密碼輸入框 |
+ text < 3000 字符 |
<input type="password"> |
| Meta refresh → 登錄 URL |
直接判定 |
<meta http-equiv="refresh" content="0;url=/login"> |
| CAPTCHA 嵌入 |
+ text < 1000 字符 |
reCAPTCHA、hCaptcha、Cloudflare Turnstile |
| 空殼備案頁 |
2+ hits + < 800 字符 |
僅含 ICP 備案號的頁面(小紅書等) |
支持中文、英文、日文登錄關鍵詞,以及 OAuth 提示("continue with Google")、付費牆("subscribe to continue")、Cloudflare 驗證("checking your browser")等。
Cookie 管理
GET /cookies
PUT /cookies/zhihu.com
{"raw": "z_c0=xxx; _xsrf=yyy; d_c0=zzz"}
PUT /cookies/zhihu.com
{"cookies": [{"name":"z_c0","value":"xxx"}, {"name":"_xsrf","value":"yyy"}]}
DELETE /cookies/zhihu.com
POST /cookies/reload
Cookie Catcher(遠程瀏覽器登錄)
瀏覽器訪問:GET /cookie-catcher?key=YOUR_API_KEY[&url=https://target-site.com]
工作流程:
- 瀏覽器打開
/cookie-catcher?key=API_KEY,建立 WebSocket 連接
- 在地址欄輸入目標網站 URL,點擊 Go