++
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
---
|
||||
name: searxng_skills
|
||||
description: Search the live web via Jack's self-hosted SearXNG (https://searxng.erhe.top) using token-authenticated JSON output. Use when the agent needs current pricing/news/docs/product specs without invoking browser tools.
|
||||
---
|
||||
|
||||
# SearXNG Web Search (Jack's server)
|
||||
|
||||
Search the live web through Jack's self-hosted SearXNG. 129 engines enabled (bing / duckduckgo / startpage / brave / mojeek / qwant / wikipedia 系 / etc.). Google main engine is OFF; google scholar/images/videos/news/cse sub-APIs are enabled.
|
||||
|
||||
## Endpoint
|
||||
|
||||
- **URL**: `https://searxng.erhe.top` ⚠ `erhe.top`, **NOT** `ehre.top`
|
||||
- **Token**: `fGWEFWGrgasegtjt1jUJG` (passed as `?token=...` query param)
|
||||
- **Method**: GET works here. (Local docker 2026.7 default is `server.method=POST` — different; if porting code to a stock local SearXNG, flip to POST.)
|
||||
- **JSON 200**: This server has limiter/token auth configured, so `?format=json&token=...` returns 200. Stock local docker returns 403 unconditionally on JSON — different from this.
|
||||
|
||||
## Quick start
|
||||
|
||||
CLI (preferred; auto-renders results):
|
||||
|
||||
```bash
|
||||
python3 ~/.hermes/skills/searxng_skills/searxng_search.py "<query>" -m 5 -l en
|
||||
```
|
||||
|
||||
Direct API (works fine from any script):
|
||||
|
||||
```python
|
||||
import urllib.request, urllib.parse, json
|
||||
url = "https://searxng.erhe.top/search?" + urllib.parse.urlencode({
|
||||
"q": "<query>", "format": "json", "token": "fGWEFWGrgasegtjt1jUJG",
|
||||
})
|
||||
data = json.loads(urllib.request.urlopen(url, timeout=30).read())
|
||||
for r in data.get("results", [])[:5]:
|
||||
print(r["engine"], r["title"][:80], "→", r["url"])
|
||||
```
|
||||
|
||||
## Response shape
|
||||
|
||||
JSON: `{results: [...], unresponsive_engines: [...], suggestions: [...], query: ...}`
|
||||
Each result: `title, url, content, host, engine, score, type, publishedDate (optional)`.
|
||||
|
||||
Alternative formats:
|
||||
- `?format=csv` → CSV with columns `title,url,content,host,engine,score,type` (great for scripts)
|
||||
- `?format=rss` → RSS 2.0 feed
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- **Domain typo is the #1 way to silently break this skill**. `searxng.erhe.top` ≠ `searxng.erhe.top`. Jack's `docker-compose.yaml` says `ehre.top`; the live deployment is `erhe.top`. If `Could not resolve host` / DNS `NXDOMAIN`, double-check the spelling — almost certainly an `h`/`r` swap.
|
||||
- **JSON endpoint requires the token**. Without `?token=...`, returns 403. Token is rotated by changing `SEARXNG_API_KEY` env in docker-compose; no code redeploy needed.
|
||||
- **Google main engine is OFF**. `google.com` is blocked at upstream (Cloudflare anti-bot). Only `google_scholar` / `google_images` / `google_videos` / `google_news` / `google_cse` are enabled. If the user says "用 google 搜 XX", expect mostly bing/duckduckgo results — be honest about it rather than silently re-routing.
|
||||
- **LibreSSL/OpenSSL warning from urllib3 v2** is harmless on macOS Python 3.9. `urllib3 v2 only supports OpenSSL 1.1.1+, but the 'ssl' module is compiled with LibreSSL`. The search still runs to completion; ignore the warning, do not reinstall.
|
||||
- **SEO content farm pollution**. DuckDuckGo heavily surfaces AI-generated SEO blogs (llmmac / meshmac / neokvm / vulcloud / maccompute). For pricing/spec verification, filter by `host` to `apple.com`, `wikipedia.org`, `*.edu`, `github.com`, `arxiv.org`, `*.gov`. Don't blindly trust first-page blog links for actual prices.
|
||||
- **brave / mojeek / qwant commonly time out** (server logs show them in `unresponsive_engines`). Real workhorses: bing, duckduckgo, startpage, wikipedia 系, github 系.
|
||||
|
||||
## CLI flags (for `searxng_search.py`)
|
||||
|
||||
| Flag | Meaning |
|
||||
|---|---|
|
||||
| `-m N` / `--max-results N` | Result row limit (default 10) |
|
||||
| `-l LANG` | `auto` / `zh` / `en` / `ja` / `de` / `fr` |
|
||||
| `-c CAT` | `general` / `images` / `videos` / `news` / `music` |
|
||||
| `--time-range` | `day` / `week` / `month` / `year` |
|
||||
| `--safesearch` | `0` / `1` / `2` |
|
||||
| `--raw` | Print raw JSON |
|
||||
| `-v` / `--verbose` | Verbose per-result output |
|
||||
|
||||
## Companion docs in this folder
|
||||
|
||||
- `searxng_skills.md` — full API reference (more endpoints)
|
||||
- `searxng_README.md` — quickstart (Chinese)
|
||||
- `searxng_search.py` — the CLI entry; can also be imported as a module
|
||||
@@ -0,0 +1,194 @@
|
||||
# SearXNG API 使用指南
|
||||
|
||||
## 快速开始
|
||||
|
||||
### Python 脚本方式
|
||||
|
||||
```bash
|
||||
# 安装依赖 (如需要)
|
||||
pip3 install requests
|
||||
|
||||
# 搜索示例
|
||||
python3 /tmp/searxng_search.py "python教程"
|
||||
|
||||
# 指定分类
|
||||
python3 /tmp/searxng_search.py "猫咪图片" -c images
|
||||
|
||||
# 指定时间范围
|
||||
python3 /tmp/searxng_search.py "科技新闻" --time-range week
|
||||
|
||||
# 输出 JSON
|
||||
python3 /tmp/searxng_search.py "python" --raw
|
||||
```
|
||||
|
||||
### cURL 方式
|
||||
|
||||
```bash
|
||||
# 基础搜索
|
||||
curl "https://searxng.erhe.top/search?q=关键词&token=fGWEFWGrgasegtjt1jUJG"
|
||||
|
||||
# JSON 格式
|
||||
curl "https://searxng.erhe.top/search?q=关键词&format=json&token=fGWEFWGrgasegtjt1jUJG"
|
||||
```
|
||||
|
||||
### Python 代码方式
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
def search(query):
|
||||
response = requests.get(
|
||||
"https://searxng.erhe.top/search",
|
||||
params={
|
||||
"q": query,
|
||||
"format": "json",
|
||||
"token": "fGWEFWGrgasegtjt1jUJG"
|
||||
}
|
||||
)
|
||||
return response.json()
|
||||
|
||||
# 使用
|
||||
results = search("python教程")
|
||||
for r in results['results'][:5]:
|
||||
print(r['title'], r['url'])
|
||||
```
|
||||
|
||||
## 常用命令参考
|
||||
|
||||
| 用途 | 命令 |
|
||||
|------|------|
|
||||
| 基础搜索 | `python3 /tmp/searxng_search.py "关键词"` |
|
||||
| 图片搜索 | `python3 /tmp/searxng_search.py "关键词" -c images` |
|
||||
| 视频搜索 | `python3 /tmp/searxng_search.py "关键词" -c videos` |
|
||||
| 中文结果 | `python3 /tmp/searxng_search.py "关键词" -l zh` |
|
||||
| 最近一周 | `python3 /tmp/searxng_search.py "关键词" -t week` |
|
||||
| 限制结果数 | `python3 /tmp/searxng_search.py "关键词" -m 20` |
|
||||
| 原始 JSON | `python3 /tmp/searxng_search.py "关键词" --raw` |
|
||||
| 查看帮助 | `python3 /tmp/searxng_search.py --help` |
|
||||
|
||||
## Agent 集成示例
|
||||
|
||||
### Claude Code 工具定义
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "searxng_search",
|
||||
"description": "使用 SearXNG 隐私搜索引擎进行网络搜索",
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"query": {
|
||||
"type": "string",
|
||||
"description": "搜索关键词"
|
||||
},
|
||||
"category": {
|
||||
"type": "string",
|
||||
"enum": ["general", "images", "videos", "news", "music"],
|
||||
"description": "搜索分类"
|
||||
},
|
||||
"language": {
|
||||
"type": "string",
|
||||
"default": "auto",
|
||||
"description": "语言代码"
|
||||
},
|
||||
"max_results": {
|
||||
"type": "integer",
|
||||
"default": 10,
|
||||
"description": "最大结果数"
|
||||
}
|
||||
},
|
||||
"required": ["query"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Python 工具实现
|
||||
|
||||
```python
|
||||
def searxng_search_tool(query, category="general", language="auto", max_results=10):
|
||||
"""
|
||||
SearXNG 搜索工具
|
||||
"""
|
||||
try:
|
||||
response = requests.get(
|
||||
"https://searxng.erhe.top/search",
|
||||
params={
|
||||
"q": query,
|
||||
"format": "json",
|
||||
"token": "fGWEFWGrgasegtjt1jUJG",
|
||||
"language": language,
|
||||
"categories": category if category != "general" else None
|
||||
},
|
||||
timeout=15
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
results = []
|
||||
|
||||
for r in data.get('results', [])[:max_results]:
|
||||
results.append({
|
||||
"title": r.get('title', ''),
|
||||
"url": r.get('url', ''),
|
||||
"snippet": r.get('content', '')[:200],
|
||||
"source": r.get('engine', '')
|
||||
})
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"query": data.get('query', query),
|
||||
"count": len(results),
|
||||
"results": results
|
||||
}
|
||||
else:
|
||||
return {
|
||||
"success": False,
|
||||
"error": f"HTTP {response.status_code}"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
return {
|
||||
"success": False,
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
# 使用示例
|
||||
result = searxng_search_tool("如何安装Python", max_results=5)
|
||||
if result['success']:
|
||||
for r in result['results']:
|
||||
print(f"📄 {r['title']}\n {r['url']}\n")
|
||||
```
|
||||
|
||||
## 完整文档
|
||||
|
||||
查看详细文档: `cat /tmp/searxng_skills.md`
|
||||
|
||||
## 测试
|
||||
|
||||
```bash
|
||||
# 测试脚本
|
||||
python3 /tmp/searxng_search.py "test" -m 3
|
||||
|
||||
# 测试 cURL
|
||||
curl -s "https://searxng.erhe.top/search?q=test&format=json&token=fGWEFWGrgasegtjt1jUJG" | head -20
|
||||
```
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **Token 错误 403**
|
||||
- 确保请求中包含 `token=fGWEFWGrgasegtjt1jUJG`
|
||||
|
||||
2. **连接超时**
|
||||
- 检查网络连接
|
||||
- 尝试增加超时时间
|
||||
|
||||
3. **结果为空**
|
||||
- 尝试更换关键词
|
||||
- 检查语言设置
|
||||
|
||||
### 获取帮助
|
||||
|
||||
- 查看详细文档: `/tmp/searxng_skills.md`
|
||||
- 查看脚本帮助: `python3 /tmp/searxng_search.py --help`
|
||||
@@ -0,0 +1,184 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
SearXNG API 客户端 - 快速搜索工具
|
||||
"""
|
||||
|
||||
import requests
|
||||
import json
|
||||
import sys
|
||||
import argparse
|
||||
from urllib.parse import urlencode
|
||||
|
||||
# 配置
|
||||
SEARXNG_URL = "https://searxng.erhe.top"
|
||||
API_TOKEN = "fGWEFWGrgasegtjt1jUJG"
|
||||
|
||||
def search(query,
|
||||
format_type="json",
|
||||
categories=None,
|
||||
language="auto",
|
||||
safesearch=0,
|
||||
time_range=None,
|
||||
max_results=10):
|
||||
"""
|
||||
搜索函数
|
||||
|
||||
参数:
|
||||
query: 搜索关键词
|
||||
format_type: 返回格式 (json/html/csv/rss)
|
||||
categories: 分类 (images/videos/news/music/general)
|
||||
language: 语言代码 (auto/zh/en/ja/de/fr)
|
||||
safesearch: 安全搜索级别 (0=关闭, 1=适中, 2=严格)
|
||||
time_range: 时间范围 (day/week/month/year)
|
||||
max_results: 最大结果数
|
||||
|
||||
返回:
|
||||
dict: 搜索结果
|
||||
"""
|
||||
params = {
|
||||
"q": query,
|
||||
"format": format_type,
|
||||
"token": API_TOKEN,
|
||||
"language": language,
|
||||
"safesearch": safesearch
|
||||
}
|
||||
|
||||
if categories:
|
||||
params["categories"] = categories
|
||||
|
||||
if time_range:
|
||||
params["time_range"] = time_range
|
||||
|
||||
try:
|
||||
response = requests.get(
|
||||
f"{SEARXNG_URL}/search",
|
||||
params=params,
|
||||
timeout=15
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
if format_type == "json":
|
||||
return response.json()
|
||||
else:
|
||||
return {"html": response.text}
|
||||
elif response.status_code == 403:
|
||||
return {"error": "API token 无效或缺失"}
|
||||
else:
|
||||
return {"error": f"请求失败: {response.status_code}"}
|
||||
|
||||
except requests.exceptions.Timeout:
|
||||
return {"error": "请求超时"}
|
||||
except requests.exceptions.ConnectionError:
|
||||
return {"error": "连接失败,请检查网络"}
|
||||
except Exception as e:
|
||||
return {"error": str(e)}
|
||||
|
||||
def print_results(results, max_results=10, verbose=False):
|
||||
"""格式化输出结果"""
|
||||
if "error" in results:
|
||||
print(f"❌ 错误: {results['error']}")
|
||||
return
|
||||
|
||||
query = results.get('query', '未知')
|
||||
results_list = results.get('results', [])
|
||||
unresponsive = results.get('unresponsive_engines', [])
|
||||
|
||||
print(f"\n{'='*70}")
|
||||
print(f"🔍 查询: {query}")
|
||||
print(f"📊 找到 {len(results_list)} 个结果")
|
||||
if unresponsive:
|
||||
print(f"⚠️ 部分搜索引擎失败: {', '.join([u[0] for u in unresponsive[:3]])}")
|
||||
print(f"{'='*70}\n")
|
||||
|
||||
for i, result in enumerate(results_list[:max_results], 1):
|
||||
title = result.get('title', '无标题')
|
||||
url = result.get('url', '无链接')
|
||||
content = result.get('content', '')
|
||||
engine = result.get('engine', '未知')
|
||||
published = result.get('publishedDate', '')
|
||||
|
||||
print(f"{i:2d}. {title}")
|
||||
print(f" 🔗 {url}")
|
||||
|
||||
if content:
|
||||
# 截断内容
|
||||
if len(content) > 150:
|
||||
content = content[:150] + "..."
|
||||
print(f" 📝 {content}")
|
||||
|
||||
print(f" ⚙️ 来源: {engine}", end="")
|
||||
if published:
|
||||
print(f" | 📅 {published}", end="")
|
||||
print("\n")
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="SearXNG 搜索工具",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
示例:
|
||||
%(prog)s python 教程
|
||||
%(prog)s "machine learning" --category videos
|
||||
%(prog)s linux --language en --time-range week
|
||||
%(prog)s python --max-results 20 --verbose
|
||||
"""
|
||||
)
|
||||
|
||||
parser.add_argument('query', nargs='+', help='搜索关键词')
|
||||
parser.add_argument('-c', '--category',
|
||||
choices=['general', 'images', 'videos', 'news', 'music', 'files', 'it', 'science'],
|
||||
default='general',
|
||||
help='搜索分类 (默认: general)')
|
||||
parser.add_argument('-l', '--language',
|
||||
default='auto',
|
||||
help='语言代码 (默认: auto)')
|
||||
parser.add_argument('-s', '--safesearch',
|
||||
type=int, choices=[0, 1, 2], default=0,
|
||||
help='安全搜索: 0=关闭, 1=适中, 2=严格 (默认: 0)')
|
||||
parser.add_argument('-t', '--time-range',
|
||||
choices=['day', 'week', 'month', 'year'],
|
||||
help='时间范围')
|
||||
parser.add_argument('-m', '--max-results',
|
||||
type=int, default=10,
|
||||
help='最大结果数 (默认: 10)')
|
||||
parser.add_argument('-v', '--verbose',
|
||||
action='store_true',
|
||||
help='详细输出')
|
||||
parser.add_argument('--format',
|
||||
choices=['json', 'html', 'csv', 'rss'],
|
||||
default='json',
|
||||
help='返回格式 (默认: json)')
|
||||
parser.add_argument('--raw',
|
||||
action='store_true',
|
||||
help='输出原始 JSON')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# 组合查询词
|
||||
query = ' '.join(args.query)
|
||||
|
||||
# 执行搜索
|
||||
results = search(
|
||||
query,
|
||||
format_type=args.format,
|
||||
categories=args.category if args.category != 'general' else None,
|
||||
language=args.language,
|
||||
safesearch=args.safesearch,
|
||||
time_range=args.time_range,
|
||||
max_results=args.max_results
|
||||
)
|
||||
|
||||
# 输出结果
|
||||
if args.raw:
|
||||
print(json.dumps(results, indent=2, ensure_ascii=False))
|
||||
else:
|
||||
print_results(results, max_results=args.max_results, verbose=args.verbose)
|
||||
|
||||
# 如果有建议搜索词
|
||||
if 'suggestions' in results and results['suggestions']:
|
||||
print(f"💡 你可能想搜索:")
|
||||
for suggestion in results['suggestions']:
|
||||
print(f" - {suggestion}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,330 @@
|
||||
# SearXNG API Skills
|
||||
|
||||
## 基本信息
|
||||
|
||||
- **URL**: `https://searxng.erhe.top`
|
||||
- **API Token**: `fGWEFWGrgasegtjt1jUJG`
|
||||
- **端口**: 通过 Caddy 反向代理
|
||||
|
||||
## API 调用方法
|
||||
|
||||
### 1. 搜索 API
|
||||
|
||||
```bash
|
||||
# 基础搜索
|
||||
curl "https://searxng.erhe.top/search?q=关键词&token=fGWEFWGrgasegtjt1jUJG"
|
||||
|
||||
# JSON 格式返回(推荐)
|
||||
curl "https://searxng.erhe.top/search?q=关键词&format=json&token=fGWEFWGrgasegtjt1jUJG"
|
||||
```
|
||||
|
||||
### 2. Python 调用示例
|
||||
|
||||
```python
|
||||
import requests
|
||||
import json
|
||||
|
||||
def search_searxng(query, format_type="json"):
|
||||
"""
|
||||
使用 SearXNG 搜索
|
||||
|
||||
参数:
|
||||
query: 搜索关键词
|
||||
format_type: 返回格式 (json/html/csv/rss)
|
||||
|
||||
返回:
|
||||
dict: 搜索结果
|
||||
"""
|
||||
url = "https://searxng.erhe.top/search"
|
||||
params = {
|
||||
"q": query,
|
||||
"format": format_type,
|
||||
"token": "fGWEFWGrgasegtjt1jUJG"
|
||||
}
|
||||
|
||||
response = requests.get(url, params=params)
|
||||
|
||||
if format_type == "json":
|
||||
return response.json()
|
||||
else:
|
||||
return response.text
|
||||
|
||||
# 使用示例
|
||||
results = search_searxng("python 教程")
|
||||
print(f"找到 {len(results['results'])} 个结果")
|
||||
for result in results['results'][:5]:
|
||||
print(f"- {result['title']}: {result['url']}")
|
||||
```
|
||||
|
||||
### 3. Claude Code / Agent 调用示例
|
||||
|
||||
```python
|
||||
import urllib.request
|
||||
import urllib.parse
|
||||
import json
|
||||
|
||||
def search(query):
|
||||
"""搜索函数"""
|
||||
base_url = "https://searxng.erhe.top/search"
|
||||
params = urllib.parse.urlencode({
|
||||
"q": query,
|
||||
"format": "json",
|
||||
"token": "fGWEFWGrgasegtjt1jUJG"
|
||||
})
|
||||
|
||||
url = f"{base_url}?{params}"
|
||||
|
||||
with urllib.request.urlopen(url) as response:
|
||||
data = json.loads(response.read().decode())
|
||||
|
||||
return data
|
||||
|
||||
# Agent 中使用
|
||||
results = search("如何在 Linux 中查找文件")
|
||||
for r in results['results'][:3]:
|
||||
print(f"标题: {r['title']}")
|
||||
print(f"链接: {r['url']}\n")
|
||||
```
|
||||
|
||||
## 高级搜索
|
||||
|
||||
### 1. 指定语言
|
||||
|
||||
```bash
|
||||
curl "https://searxng.erhe.top/search?q=关键词&format=json&token=fGWEFWGrgasegtjt1jUJG&language=zh"
|
||||
```
|
||||
|
||||
语言代码:
|
||||
- `zh` - 中文
|
||||
- `en` - 英文
|
||||
- `ja` - 日文
|
||||
- `de` - 德文
|
||||
- `fr` - 法文
|
||||
|
||||
### 2. 指定分类
|
||||
|
||||
```bash
|
||||
# 图片搜索
|
||||
curl "https://searxng.erhe.top/search?q=猫&format=json&token=fGWEFWGrgasegtjt1jUJG&categories=images"
|
||||
|
||||
# 视频搜索
|
||||
curl "https://searxng.erhe.top/search?q=教程&format=json&token=fGWEFWGrgasegtjt1jUJG&categories=videos"
|
||||
|
||||
# 新闻搜索
|
||||
curl "https://searxng.erhe.top/search?q=科技&format=json&token=fGWEFWGrgasegtjt1jUJG&categories=news"
|
||||
```
|
||||
|
||||
分类列表:
|
||||
- `general` - 通用
|
||||
- `images` - 图片
|
||||
- `videos` - 视频
|
||||
- `news` - 新闻
|
||||
- `music` - 音乐
|
||||
- `files` - 文件
|
||||
- `it` - IT
|
||||
- `science` - 科学
|
||||
|
||||
### 3. 安全搜索
|
||||
|
||||
```bash
|
||||
# 关闭安全搜索 (0)
|
||||
curl "https://searxng.erhe.top/search?q=关键词&format=json&token=fGWEFWGrgasegtjt1jUJG&safesearch=0"
|
||||
|
||||
# 适中 (1)
|
||||
curl "https://searxng.erhe.top/search?q=关键词&format=json&token=fGWEFWGrgasegtjt1jUJG&safesearch=1"
|
||||
|
||||
# 严格 (2)
|
||||
curl "https://searxng.erhe.top/search?q=关键词&format=json&token=fGWEFWGrgasegtjt1jUJG&safesearch=2"
|
||||
```
|
||||
|
||||
### 4. 时间范围
|
||||
|
||||
```bash
|
||||
# 最近一天
|
||||
curl "https://searxng.erhe.top/search?q=关键词&format=json&token=fGWEFWGrgasegtjt1jUJG&time_range=day"
|
||||
|
||||
# 最近一周
|
||||
curl "https://searxng.erhe.top/search?q=关键词&format=json&token=fGWEFWGrgasegtjt1jUJG&time_range=week"
|
||||
|
||||
# 最近一月
|
||||
curl "https://searxng.erhe.top/search?q=关键词&format=json&token=fGWEFWGrgasegtjt1jUJG&time_range=month"
|
||||
|
||||
# 最近一年
|
||||
curl "https://searxng.erhe.top/search?q=关键词&format=json&token=fGWEFWGrgasegtjt1jUJG&time_range=year"
|
||||
```
|
||||
|
||||
## JSON 返回格式说明
|
||||
|
||||
```json
|
||||
{
|
||||
"query": "搜索关键词",
|
||||
"results": [
|
||||
{
|
||||
"title": "结果标题",
|
||||
"url": "https://example.com",
|
||||
"content": "结果摘要",
|
||||
"engine": "搜索引擎名称",
|
||||
"template": "模板类型",
|
||||
"publishedDate": "发布日期 (如果有)",
|
||||
"img_src": "图片URL (如果有)",
|
||||
"thumbnail": "缩略图URL (如果有)",
|
||||
"category": "分类"
|
||||
}
|
||||
],
|
||||
"answers": [],
|
||||
"corrections": [],
|
||||
"infoboxes": [],
|
||||
"suggestions": ["建议搜索词"],
|
||||
"unresponsive_engines": []
|
||||
}
|
||||
```
|
||||
|
||||
## 获取配置信息
|
||||
|
||||
```bash
|
||||
# 获取 SearXNG 配置
|
||||
curl "https://searxng.erhe.top/config&token=fGWEFWGrgasegtjt1jUJG"
|
||||
```
|
||||
|
||||
## 完整 Python 示例
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
SearXNG API 客户端示例
|
||||
"""
|
||||
|
||||
import requests
|
||||
import json
|
||||
import sys
|
||||
|
||||
SEARXNG_URL = "https://searxng.erhe.top"
|
||||
API_TOKEN = "fGWEFWGrgasegtjt1jUJG"
|
||||
|
||||
def search(query,
|
||||
format_type="json",
|
||||
categories=None,
|
||||
language="auto",
|
||||
safesearch=0,
|
||||
time_range=None):
|
||||
"""
|
||||
搜索函数
|
||||
|
||||
参数:
|
||||
query: 搜索关键词
|
||||
format_type: 返回格式 (json/html/csv/rss)
|
||||
categories: 分类列表 (images/videos/news/music)
|
||||
language: 语言代码 (auto/zh/en/ja/de/fr)
|
||||
safesearch: 安全搜索级别 (0/1/2)
|
||||
time_range: 时间范围 (day/week/month/year)
|
||||
|
||||
返回:
|
||||
dict: 搜索结果
|
||||
"""
|
||||
params = {
|
||||
"q": query,
|
||||
"format": format_type,
|
||||
"token": API_TOKEN,
|
||||
"language": language,
|
||||
"safesearch": safesearch
|
||||
}
|
||||
|
||||
if categories:
|
||||
params["categories"] = categories
|
||||
|
||||
if time_range:
|
||||
params["time_range"] = time_range
|
||||
|
||||
response = requests.get(f"{SEARXNG_URL}/search", params=params)
|
||||
|
||||
if format_type == "json":
|
||||
return response.json()
|
||||
else:
|
||||
return response.text
|
||||
|
||||
def format_results(results, max_results=10):
|
||||
"""格式化输出结果"""
|
||||
print(f"\n{'='*60}")
|
||||
print(f"查询: {results.get('query')}")
|
||||
print(f"找到 {len(results.get('results', []))} 个结果")
|
||||
print(f"{'='*60}\n")
|
||||
|
||||
for i, result in enumerate(results.get('results', [])[:max_results], 1):
|
||||
print(f"{i}. {result.get('title', '无标题')}")
|
||||
print(f" 链接: {result.get('url', '无链接')}")
|
||||
if result.get('content'):
|
||||
content = result.get('content', '')[:150]
|
||||
print(f" 摘要: {content}...")
|
||||
print(f" 来源: {result.get('engine', '未知')}")
|
||||
print()
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 示例搜索
|
||||
if len(sys.argv) > 1:
|
||||
query = " ".join(sys.argv[1:])
|
||||
else:
|
||||
query = "Python 编程"
|
||||
|
||||
try:
|
||||
results = search(query, categories="general")
|
||||
format_results(results)
|
||||
except Exception as e:
|
||||
print(f"搜索失败: {e}")
|
||||
```
|
||||
|
||||
## 错误处理
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
def safe_search(query):
|
||||
"""安全的搜索函数,包含错误处理"""
|
||||
try:
|
||||
response = requests.get(
|
||||
"https://searxng.erhe.top/search",
|
||||
params={
|
||||
"q": query,
|
||||
"format": "json",
|
||||
"token": "fGWEFWGrgasegtjt1jUJG"
|
||||
},
|
||||
timeout=10
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
elif response.status_code == 403:
|
||||
return {"error": "API token 无效或缺失"}
|
||||
else:
|
||||
return {"error": f"请求失败: {response.status_code}"}
|
||||
|
||||
except requests.exceptions.Timeout:
|
||||
return {"error": "请求超时"}
|
||||
except requests.exceptions.ConnectionError:
|
||||
return {"error": "连接失败,请检查网络"}
|
||||
except Exception as e:
|
||||
return {"error": str(e)}
|
||||
```
|
||||
|
||||
## 快速参考
|
||||
|
||||
| 功能 | 命令 |
|
||||
|------|------|
|
||||
| 基础搜索 | `curl "https://searxng.erhe.top/search?q=关键词&token=fGWEFWGrgasegtjt1jUJG"` |
|
||||
| JSON 返回 | 添加 `&format=json` |
|
||||
| 图片搜索 | 添加 `&categories=images` |
|
||||
| 中文结果 | 添加 `&language=zh` |
|
||||
| 最近一周 | 添加 `&time_range=week` |
|
||||
| 获取配置 | `curl "https://searxng.erhe.top/config&token=fGWEFWGrgasegtjt1jUJG"` |
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **Token 必须**: 所有 API 请求必须包含 `token` 参数
|
||||
2. **返回格式**: 推荐使用 `format=json` 获取结构化数据
|
||||
3. **超时处理**: 搜索可能需要几秒钟,建议设置超时
|
||||
4. **请求频率**: 避免过于频繁的请求,可能触发限制
|
||||
5. **结果数量**: 默认返回多个搜索引擎的结果
|
||||
|
||||
## 获取帮助
|
||||
|
||||
- SearXNG 主页: `https://searxng.erhe.top`
|
||||
- SearXNG 文档: `https://docs.searxng.org`
|
||||
Reference in New Issue
Block a user