init: Search Hub - 统一多搜索引擎聚合服务

This commit is contained in:
2026-05-09 18:46:05 +08:00
commit 81d726179c
27 changed files with 3179 additions and 0 deletions

72
search.py Normal file
View File

@@ -0,0 +1,72 @@
#!/usr/bin/env python3
"""Unified search via local search-hub API (port 8650).
Supports baidu, tavily, searxng, duckduckgo sources.
Usage:
python3 search.py "<query>" [--source auto] [--limit 5]
"""
import json
import sys
import urllib.request
import urllib.error
SEARCH_API = "http://192.168.5.14:8650"
def search(query: str, source: str = "auto", max_results: int = 5) -> dict:
payload = json.dumps({
"query": query,
"source": source,
"max_results": max_results,
}).encode("utf-8")
req = urllib.request.Request(
f"{SEARCH_API}/api/search",
data=payload,
headers={"Content-Type": "application/json"},
method="POST",
)
try:
with urllib.request.urlopen(req, timeout=30) as resp:
return json.loads(resp.read().decode("utf-8"))
except urllib.error.HTTPError as e:
return {"error": f"HTTP {e.code}: {e.reason}", "results": []}
except urllib.error.URLError as e:
return {"error": f"Connection failed: {e.reason}", "results": []}
except Exception as e:
return {"error": str(e), "results": []}
if __name__ == "__main__":
args = sys.argv[1:]
if not args:
print(json.dumps({"error": "No query provided"}, ensure_ascii=False))
sys.exit(1)
query = args[0]
source = "auto"
limit = 5
for i, a in enumerate(args[1:]):
if a == "--source" and i + 1 < len(args[1:]):
source = args[1:][i + 1]
elif a == "--limit" and i + 1 < len(args[1:]):
limit = int(args[1:][i + 1])
result = search(query, source, limit)
# Clean up for agent consumption
output = {
"query": result.get("query", query),
"source": result.get("source", source),
"elapsed": result.get("elapsed", 0),
"total": result.get("total", len(result.get("results", []))),
"results": [
{
"title": r.get("title", ""),
"url": r.get("url", ""),
"content": r.get("content", ""),
"source": r.get("source", ""),
}
for r in result.get("results", [])[:limit]
],
}
if "error" in result:
output["error"] = result["error"]
print(json.dumps(output, ensure_ascii=False, indent=2))