Files
searxng-use-cli/README.md
T
thzxx f983a9377e feat(v1.7.0): AI 友好度增强 + 测试补全 (155→309)
核心新增(面向 AI Agent 程序化使用):
- 结构化错误码体系:E_CONFIG/E_AUTH/E_NETWORK/E_RATE_LIMIT/E_PARSE/E_EMPTY/E_INPUT/E_INTERNAL
  classify_error() 自动分类异常,JSON 错误输出含 error_code 字段
- JSON Lines 流式输出 (--stream):每条结果独立一行,AI 可增量处理
- 进度事件 (--progress):JSON Lines 事件流到 stderr(start/cache_hit/fetch_ok/done 等)

测试补全(+154 例,覆盖全部高风险盲区):
- HTML 回退搜索路径 (19)
- --fetch 自动抓取 (21)
- --verify 健康检查 (15)
- 输出格式化 (15)
- 实例解析链 (20)
- 并行多实例搜索 (10)
- CLI 入口与端到端 (17)
- 错误码分类 (27)
- 流式输出与进度事件 (10)

源码改进:
- search.py: h3 内 a 标签 href 作为 url fallback,提升 SearXNG 主题兼容性
- common.py: 新增 classify_error/emit_progress/set_progress_enabled

文档同步:SKILL.md 新增 AI Agent Integration Guide 章节,README.md 更新参数与错误码表
2026-08-01 17:40:14 +08:00

294 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SearXNG CLI 技能包
[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
一个面向 AI Agent 的网络搜索与网页抓取技能包。AI 通过终端调用 CLI 脚本即可获得"搜索网络"和"抓取网页"两项核心能力,无需 API Key,路由通过用户自建的 SearXNG 实例完成。
**这不是给人用的工具,而是给 AI 用的技能。** 任何能执行终端命令的 AI AgentHermes、Claude Code、Codex、OpenCode、Cursor、Trae 等)均可直接调用。
## 为什么需要这个技能
AI Agent 在以下场景中需要实时网络信息:
- 查询最新新闻、文档、技术资料
- 验证事实、获取实时数据
- 抓取网页内容进行阅读和分析
传统方案依赖付费搜索 API(Google、Bing)或专有爬虫服务。本技能通过用户自建的 SearXNG 实例(隐私元搜索引擎,聚合 70+ 搜索服务)实现零成本、零 API Key、隐私可控的网络搜索能力。
## AI 如何使用
### 搜索网络
```bash
python scripts/search.py -q "搜索词" -i https://your-searxng-instance
```
AI 调用后,stdout 输出 JSON 格式搜索结果,AI 可解析并使用:
```json
{
"query": "搜索词",
"results": [
{"title": "...", "url": "https://...", "content": "摘要...", "engine": "google", "score": 1.0}
],
"suggestions": ["相关建议词"],
"answers": ["直接答案(如有)"]
}
```
### 抓取网页
```bash
python scripts/fetch.py -u "https://example.com" --extract markdown
```
AI 调用后,stdout 输出网页正文(text/html/markdown 三种格式),AI 可直接阅读分析。
### 输入输出约定(AI 必读)
| 通道 | 内容 | 说明 |
|------|------|------|
| stdout | 数据 | JSON/CSV/文本,AI 解析的唯一来源 |
| stderr | 日志 | 进度、警告、错误,AI 可忽略或用于调试 |
| exit 0 | 成功 | 有结果 |
| exit 1 | 失败 | 致命错误(所有实例不可用、参数错误等) |
| exit 2 | 空结果 | 搜索成功但无结果 |
**错误处理**`--format json` 模式下,错误以 JSON 输出到 stdout(非 stderr),格式为 `{"error": "...", "error_code": "E_NETWORK", "exit_code": 1, "query": "..."}`AI 可程序化捕获。
**错误码体系**`error_code` 字段):
| 错误码 | 含义 | AI 恢复策略 |
|--------|------|-------------|
| `E_CONFIG` | 配置错误(无实例) | 提示用户设置 `-i` / `SEARXNG_INSTANCE` |
| `E_AUTH` | 认证失败(401/403 | 检查 token/凭证 |
| `E_NETWORK` | 网络错误(连接失败、5xx) | 重试或切换实例/代理 |
| `E_RATE_LIMIT` | 限流(429) | 等待后重试 |
| `E_PARSE` | 解析错误 | 检查实例 JSON 支持 |
| `E_INPUT` | 输入错误(参数/文件) | 修正参数 |
| `E_INTERNAL` | 内部错误 | 报告 bug |
### 流式输出与进度事件(AI 高级用法)
**`--stream`**JSON Lines 流式输出,每条结果一行 JSON,AI 可增量处理:
```
{"type": "result", "result": {"title": "...", "url": "..."}}
{"type": "done", "count": 10, "query": "..."}
```
**`--progress`**:进度事件流(JSON Lines 到 stderr),AI 可实时跟踪执行:
```
{"event": "start", "query": "...", "instances": 2}
{"event": "cache_hit", "query": "...", "ttl": 30}
{"event": "fetch_ok", "url": "...", "chars": 12345}
{"event": "done", "results": 10, "query": "..."}
```
```bash
# AI 推荐用法:流式输出 + 进度事件
python scripts/search.py -q "research" -i https://your-instance --stream --progress
```
## 部署
### 前置条件
- Python 3.8+
- 一个 SearXNG 实例 URL(自建或受信任的实例)
### 安装
```bash
git clone https://git.metona.cn/MetonaTeam/searxng-use-cli.git
```
无需安装依赖。`search.py` 仅使用 Python 标准库,开箱即用。
可选安装(提升 `fetch.py` 抓取质量):
```bash
pip install requests beautifulsoup4
```
### 配置实例
AI Agent 无需每次传入实例 URL,支持三种配置方式(优先级从高到低):
1. **CLI 参数**`-i https://your-instance`
2. **环境变量**`export SEARXNG_INSTANCE="https://your-instance"`
3. **配置文件**`./searxng.toml``~/.config/searxng-cli/searxng.toml`
```toml
# searxng.toml
[searxng]
instance = "https://your-searxng.example.com"
```
## 参数参考
### search.py — 网络搜索
```bash
python scripts/search.py -q "查询词" -i https://your-instance \
[--format json|brief|urls|csv] \
[--engines google,bing,brave] \
[--time-range day|month|year|none] \
[--language zh-CN] \
[--sort-by score|date|engine|none] \
[--no-dedup] \
[--max-results 10] \
[--fetch 3] \
[--cache-ttl 30] \
[--queries-file queries.txt] \
[--include-domain example.com] \
[--exclude-domain spam.com] \
[--proxy http://corp:8080] \
[--auth-bearer-file ~/.token] \
[--verify] \
[--stream] \
[--progress] \
[--verbose|-v] [--quiet]
```
| 参数 | 说明 | 默认值 |
|------|------|--------|
| `-q / --query` | 搜索词(必填,除非用 `--verify`/`--queries-file`/`--clear-cache`/`--cache-stats` | — |
| `-i / --instance` | SearXNG 实例 URL,逗号分隔实现故障转移 | — |
| `-f / --format` | 输出格式:json/brief/urls/csv | json |
| `--engines` | 搜索引擎列表 | google,bing,brave,duckduckgo,startpage,wikipedia,wikidata |
| `-t / --time-range` | 时间范围:day/month/year/none | year |
| `-s / --safesearch` | 安全搜索:0/1/2 | 0(关闭) |
| `-l / --language` | 语言代码 | — |
| `-p / --pageno` | 页码 | 1 |
| `--sort-by` | 排序:score/date/engine/none | score(降序) |
| `--no-dedup` | 禁用跨引擎去重 | 默认开启去重 |
| `--max-results` | 限制结果数(去重+排序后截取) | 不限 |
| `--fetch N` | 自动抓取前 N 个结果的网页正文 | 0(不抓取) |
| `--cache-ttl` | 缓存分钟数 | 0(不缓存) |
| `--queries-file` | 批量查询文件(每行一个查询) | — |
| `--include-domain` | 域名白名单 | — |
| `--exclude-domain` | 域名黑名单 | — |
| `--proxy` | 代理 URL | — |
| `--auth-bearer-file` | Bearer Token 文件 | — |
| `--auth-basic-file` | Basic Auth 文件 | — |
| `--verify` | 实例健康检查模式 | — |
| `--config` | 指定配置文件 | 自动发现 |
| `--stream` | JSON Lines 流式输出(每条结果一行) | 关闭 |
| `--progress` | 进度事件(JSON Lines 到 stderr | 关闭 |
| `-v / --verbose` | 调试日志 | — |
| `--quiet` | 仅输出警告和错误 | — |
### fetch.py — 网页抓取
```bash
python scripts/fetch.py -u https://example.com \
--extract text|html|markdown \
[--encoding gbk] \
[--max-size 5242880] \
[--timeout 15] \
[--retries 3] \
[--no-redirect] \
[--proxy http://corp:8080] \
[--auth-bearer-file ~/.token]
```
| 参数 | 说明 | 默认值 |
|------|------|--------|
| `-u / --url` | 目标 URL(必填) | — |
| `-e / --extract` | 提取模式:text/html/markdown | text |
| `--encoding` | 强制字符编码 | 自动检测 |
| `--max-size` | 最大字节数 | 不限 |
| `--timeout` | 超时秒数 | 15 |
| `--retries` | 重试次数 | 3 |
| `--no-redirect` | 不跟随重定向 | 跟随 |
| `--proxy` | 代理 URL | — |
| `--auth-bearer-file` | Bearer Token 文件 | — |
| `--auth-basic-file` | Basic Auth 文件 | — |
## 能力清单
**搜索**
- 多实例故障转移 + 并行探测
- 指数退避重试(429/5xx/连接错误)
- 跨引擎去重(忽略 utm_*/gclid 等跟踪参数)
- 结果排序(score/date/engine
- 域名白名单/黑名单
- 批量查询(`--queries-file`
- 实例健康检查(`--verify`
**输出**
- JSON(默认,含完整元数据)
- brief(标题+URL+摘要)
- urls(纯 URL 列表)
- CSV(表格导出)
- 结构化 JSON 错误输出
**网页抓取**
- text:提取纯文本
- html:原始 HTML
- markdown:增强 Markdown 转换(GFM 表格、代码块、引用块、嵌套列表、定义列表)
**缓存**
- SQLite 缓存(`--cache-ttl`),相同查询在 TTL 内跳过网络
- `--clear-cache` / `--cache-stats` 管理缓存
**网络**
- 代理支持(`--proxy`
- 认证(Bearer/Basic,支持文件和环境变量,避免 shell 历史泄露)
- 凭证文件权限警告(POSIX
**工程**
- 共享 `common.py`(统一重试/字符集/认证/日志)
- 结构化日志(`--verbose` / `--quiet`
- 结构化错误码(`E_NETWORK` / `E_AUTH` / `E_RATE_LIMIT` 等)
- JSON Lines 流式输出(`--stream`
- 进度事件(`--progress`JSON Lines 到 stderr
- 309 个单元+集成测试
## 跨 Agent 兼容性
本技能与 Agent 无关——任何能执行终端命令的 AI 均可使用:
| Agent | 调用方式 |
|-------|---------|
| Hermes | `python scripts/search.py -q "..." -i https://your-instance` |
| Claude Code | 同上,通过终端工具调用 |
| Codex (OpenAI) | 同上 |
| OpenCode | 同上 |
| Cursor | 同上 |
| Trae | 同上 |
设计要点:
- 零外部依赖(`search.py` 仅标准库)
- 脚本自注入目录到 `sys.path`,可从任意工作目录运行
- stdout 纯数据,stderr 纯日志
- 无 Agent 专属 API 调用,纯 CLI,跨平台可移植
## 测试
```bash
pip install pytest
pytest -q
```
309 个测试覆盖:缓存操作、认证解析、域名过滤、Markdown 转换、搜索逻辑、集成流程、日志配置、HTML 回退、自动抓取、健康检查、输出格式化、实例解析、并行搜索、CLI 端到端、错误码分类、流式输出、进度事件。
## 项目结构
```
├── scripts/
│ ├── search.py # 搜索(多实例故障转移/缓存/批量/域名过滤)
│ ├── fetch.py # 网页抓取(text/markdown 提取)
│ ├── common.py # 共享工具(认证/重试/字符集/日志)
│ ├── cache.py # SQLite 结果缓存
│ └── _config.py # 版本号 + User-Agent
├── tests/ # pytest 单元+集成测试
├── SKILL.md # 完整技能文档(Agent 技能描述)
├── pytest.ini # 测试配置
└── README.md
```
## 许可证
MIT