Files
searxng-use-cli/README.md
T
thzxx 4df521dc9d feat(v2.3.0): fetch 结构化 JSON 契约 + 并发批量 + 真实并发门控
迭代 1 — 正确性修复:
- 修复 --pages N 多页聚合的 unresponsive-engine 警告误判: 原用循环末次
  cached 变量判断, 缓存命中时警告被错误跳过/误触发; 改用独立
  performed_live_query 标记
- UA 池单一来源: 删除 common.py 手工副本 _FALLBACK_UAS_BUILTIN,
  FALLBACK_UAS 直接引用 _config.UA_POOL, 消除双份漂移
- search_html 解码修复: 硬编码 utf-8 改为 detect_charset(header/meta
  自动检测), 新增 --encoding 强制覆盖, 贯穿 search_multi 全链
- AdaptiveThrottle 真实并发门控: acquire_slot()/release_slot() 槽位机制,
  退避降并发后新请求被快速拒绝(E_RATE_LIMIT), 实现持久降并发而非名义降并发

迭代 2 — fetch JSON 契约 + 批量并发:
- fetch.py --format json: 成功 {status,url,final_url,content_type,extract,
  truncated,text_length,user_agent}; 失败 {status,error,error_code,
  status_code,url}, 对齐 search.py 错误码体系
- fetch_page 采集 title + latency, 填充 --fetch-report json 空字段
- --queries-file --parallel-queries N (1-8): 并发批量, 输出保序, 受
  AdaptiveThrottle 门控; 并发模式禁用 --fetch(嵌套并行不安全)
- queries 文件编码自动检测 (UTF-8 → GBK 回退)

迭代 3 — 工程化:
- 新增 pyproject.toml (searxng-search/searxng-fetch 入口点)
- 收敛 20+ 处函数内冗余导入
- --dump-schema 扩展: fetched.items 补全 15 字段, 新增 defs.batch/research
- 新增 17 个测试 (tests/test_v230_features.py), 全量 561 测试通过
- 文档同步 (SKILL.md/README.md, 版本号 2.3.0)
2026-08-05 20:14:07 +08:00

416 lines
24 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", "recovery_hint": "...", "exit_code": 1, "query": "..."}`AI 可程序化捕获并按 `recovery_hint` 采取恢复行动。
**错误码体系**`error_code` + `recovery_hint` 字段):
| 错误码 | 含义 | recovery_hint(节选) |
|--------|------|----------------------|
| `E_CONFIG` | 配置错误(无实例) | 设置 `-i`/`SEARXNG_INSTANCE`/配置文件 |
| `E_AUTH` | 认证失败(401/403) | 检查凭证、token 过期与权限 |
| `E_NETWORK` | 网络错误(连接失败、5xx) | 重试退避、切换实例、检查代理 |
| `E_RATE_LIMIT` | 限流(429) | 等待重试、降低频率、分散负载 |
| `E_PARSE` | 解析错误 | 切换实例、切换 `--method` |
| `E_EMPTY` | 空结果(exit 2) | 调整查询词、扩大 `--time-range`/`--categories` |
| `E_INPUT` | 输入错误(参数/文件) | 检查语法、标志组合、文件路径 |
| `E_INTERNAL` | 内部错误 | 用 `--verbose` 重跑并报告 |
| `E_UNSUPPORTED_MEDIA` (v2.2.0) | 不支持的二进制媒体类型(PDF/docx/xlsx 解析失败) | 换 URL,或安装 `pdftotext` 用于 PDF 解析 |
### 流式输出与进度事件(AI 高级用法)
**`--stream`**JSON Lines 流式输出,每条结果一行 JSON,AI 可增量处理:
```
{"type": "result", "result": {"title": "...", "url": "..."}}
{"type": "done", "schema_version": "1.0", "count": 10, "query": "..."}
```
搜索失败时输出 error 事件(含 `recovery_hint`):
```
{"type": "error", "error": "...", "error_code": "E_AUTH", "recovery_hint": "Verify credentials...", "query": "..."}
```
注意:`--stream` 仅在单查询 + `--format json` 下有效;与 `--queries-file` 或非 json 格式同用会立即报 `E_INPUT`
**`--progress`**:进度事件流(JSON Lines 到 stderr),AI 可实时跟踪执行:
```
{"event": "start", "query": "...", "instances": 2, "request_id": "a1b2c3d4"}
{"event": "instance_try", "url": "https://inst1.example.com", "attempt": 1, "request_id": "a1b2c3d4"}
{"event": "instance_ok", "url": "https://inst1.example.com", "latency": 0.342, "results": 10, "request_id": "a1b2c3d4"}
{"event": "instance_fail", "url": "https://inst2.example.com", "error": "HTTP 503", "error_code": "E_NETWORK", "request_id": "a1b2c3d4"}
{"event": "cache_hit", "query": "...", "ttl": 30, "request_id": "a1b2c3d4"}
{"event": "page_ok", "pageno": 1, "results": 10, "request_id": "a1b2c3d4"}
{"event": "page_fail", "pageno": 2, "error": "HTTP 503", "request_id": "a1b2c3d4"}
{"event": "fetch_ok", "url": "...", "chars": 12345, "request_id": "a1b2c3d4"}
{"event": "done", "results": 10, "query": "...", "request_id": "a1b2c3d4"}
```
v2.2.0:每个事件含 `request_id`8 位 hex,每次运行自动生成);`--pages N` 时新增 `page_ok`/`page_fail` 事件。
**`--dump-schema`**:输出当前版本的 JSON Schema 到 stdout 并退出,AI 可程序化发现字段名与类型,无需解析文档。
```bash
# AI 推荐用法:流式输出 + 进度事件
python scripts/search.py -q "research" -i https://your-instance --stream --progress
```
## 部署
### 前置条件
- Python 3.8+3.11+ 开箱即用;3.8-3.10 使用 `searxng.toml` 配置需 `pip install tomli`
- 一个 SearXNG 实例 URL(自建或受信任的实例)
### 安装
```bash
git clone https://git.metona.cn/MetonaTeam/searxng-use-cli.git
```
无需安装依赖。`search.py` 仅使用 Python 标准库,开箱即用。
可选安装:
```bash
# 提升 fetch.py 抓取质量(HTTP 连接池 + HTML 解析)
pip install requests beautifulsoup4
# Python 3.8-3.10 使用 searxng.toml 配置文件时需要(3.11+ 内置 tomllib
pip install tomli
```
### 配置实例
AI Agent 无需每次传入实例 URL 和认证信息,支持通过配置文件一次性设置:
1. **CLI 参数**`-i https://your-instance`(最高优先级)
2. **环境变量**`export SEARXNG_INSTANCE="https://your-instance"`
3. **配置文件**`./searxng.toml``~/.config/searxng-cli/searxng.toml``%APPDATA%/searxng-cli/searxng.toml`Windows
```toml
# searxng.toml
[searxng]
instance = "https://your-searxng.example.com"
# 私有实例认证(可选,二选一):
auth_basic = "user:password" # Basic 认证
# auth_bearer = "sk-token-123" # Bearer Token(与 auth_basic 同时设置时 bearer 优先)
```
**认证优先级**(从高到低):`--auth-*` CLI 参数 > `--auth-*-file` 文件 > `searxng.toml` 配置 > 环境变量
> **安全提醒**:配置文件中的明文密码有泄露风险。生产环境推荐使用 `--auth-basic-file ~/.searxng_auth` 或环境变量。
## 参数参考
### search.py — 网络搜索
```bash
python scripts/search.py -q "查询词" -i https://your-instance \
[--format json|brief|urls|csv] \
[--engines google,bing,brave] \
[--time-range day|week|month|year|none] \
[--language zh-CN] \
[--sort-by score|date|engine|none] \
[--no-dedup] \
[--similarity-dedup] [--similarity-threshold 0.85] \
[--max-results 10] \
[--pages N] \
[--fetch 3] [--fetch-report [json]] \
[--no-fallback] \
[--referer URL] \
[--request-delay 0.3] \
[--cache-ttl 30] [--cache-max-size 100] \
[--queries-file queries.txt] \
[--research "研究主题"] [--research-angles "a,b,c"] \
[--include-domain example.com] \
[--exclude-domain spam.com] \
[--proxy http://corp:8080] \
[--auth-bearer-file ~/.token] \
[--throttle-failure-threshold 3] [--throttle-pause-seconds 30] [--throttle-max-delay 10] \
[--log-format text|json] \
[--dry-run] [--save-config FILE] \
[--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/week/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(不抓取) |
| `--fetch-report` | v2.0.0 抓取报告(stderr,含 WAF/兜底/限流统计) | 关闭 |
| `--no-fallback` | v2.0.0 禁用 Wayback Machine 兜底 | 默认启用兜底 |
| `--referer` | v2.0.0 设置 Referer 头 | 实例 URL |
| `--request-delay` | v2.0.0 抓取请求间隔秒数(自适应限流可能增大) | 0.3 |
| `--cache-ttl` | 缓存分钟数 | 0(不缓存) |
| `--queries-file` | 批量查询文件(每行一个查询) | — |
| `--parallel-queries` | v2.3.0 并发批量查询 worker 数(1-8,输出保序,受自适应限流门控;并发时禁用 --fetch) | 0(串行) |
| `--research` | v2.1.0 研究模式:给定主题自动扩展 5 个多角度查询 | — |
| `--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` | 仅输出警告和错误 | — |
| `--pages N` | v2.2.0 分页聚合:一次获取 N 页并跨页去重合并 | 1 |
| `--similarity-dedup` | v2.2.0 相似度去重(SimHash + Jaccard | 关闭 |
| `--similarity-threshold` | v2.2.0 相似度阈值 | 0.85 |
| `--log-format` | v2.2.0 日志格式:text/json | text |
| `--dry-run` | v2.2.0 预览模式(不发 HTTP 请求) | 关闭 |
| `--throttle-failure-threshold` | v2.2.0 限流失败阈值 | 3 |
| `--throttle-pause-seconds` | v2.2.0 429 全局暂停秒数 | 30 |
| `--throttle-max-delay` | v2.2.0 限流最大延迟秒数 | 10 |
| `--research-angles` | v2.2.0 自定义研究角度(逗号分隔) | 默认 5 角度 |
| `--save-config` | v2.2.0 保存当前参数为 searxng.toml 并退出 | — |
| `--cache-max-size` | v2.2.0 缓存大小上限(MB | 100 |
| `--fetch-report json` | v2.2.0 JSON 格式抓取报告 | text |
### fetch.py — 网页抓取
```bash
python scripts/fetch.py -u https://example.com \
--extract text|html|markdown \
--format text|json \ # v2.3.0: json = 结构化 JSON 契约
[--encoding gbk] \
[--max-size 5242880] \
[--timeout 15] \
[--retries 3] \
[--no-redirect] \
[--referer https://google.com/] \
[--proxy http://corp:8080] \
[--auth-bearer-file ~/.token]
```
| 参数 | 说明 | 默认值 |
|------|------|--------|
| `-u / --url` | 目标 URL(必填) | — |
| `-f / --format` | v2.3.0 输出格式:text/jsonjson = 结构化 JSON 契约,成功 `{status,url,final_url,content_type,extract,truncated,text_length,user_agent}`,失败 `{status,error,error_code,status_code,url}` | text |
| `-e / --extract` | 提取模式:text/html/markdown | text |
| `--encoding` | 强制字符编码 | 自动检测 |
| `--max-size` | 最大字节数 | 不限 |
| `--timeout` | 超时秒数(v2.0.0 内部拆分为 connect/read | 15 |
| `--retries` | 重试次数 | 3 |
| `--no-redirect` | 不跟随重定向 | 跟随 |
| `--no-fallback` | v2.1.0 禁用 Wayback Machine 兜底 | 默认启用兜底 |
| `--referer` | 设置 Referer 头(v2.0.0 反爬措施) | — |
| `--proxy` | 代理 URL | — |
| `--auth-bearer-file` | Bearer Token 文件 | — |
| `--auth-basic-file` | Basic Auth 文件 | — |
## 能力清单
**v2.3.0 新功能与修复**
- `fetch.py --format json`:结构化 JSON 输出契约。成功 `{status, url, final_url, content_type, extract, truncated, text_length, user_agent}`;失败 `{status, error, error_code, status_code, url}`(对齐 search.py 错误码体系,含 `E_UNSUPPORTED_MEDIA`)。AI Agent 可程序化解析抓取结果,无需再解析裸文本
- `--parallel-queries N`:批量模式并发执行(1-8 workers,输出保持文件顺序),受 AdaptiveThrottle 真实并发门控约束;并发模式下禁用 `--fetch`(嵌套并行抓取不安全)。queries 文件编码自动检测(UTF-8 → GBK 回退)
- 真实并发门控:`AdaptiveThrottle.acquire_slot()/release_slot()`——退避降并发后新请求被快速拒绝(返回 `E_RATE_LIMIT`),实现持久降并发(原实现仅名义降并发,线程池规模固定)
- `--fetch-report json` 字段补齐:`fetch_page` 采集 `title`(页面标题)与 `latency`(耗时秒数),此前恒为 None
- `--dump-schema` 扩展:`fetched.items` 字段补全(final_url/status/error_code/waf_type/fallback_used/title/latency 等),新增 `defs.batch`/`defs.research` 描述批量与研究模式输出 shape
- 修复多页聚合(`--pages N`)的 unresponsive-engine 警告误判:原实现用循环末次 `cached` 变量判断,缓存命中时警告被错误跳过/误触发;现用独立 `performed_live_query` 标记
- UA 池单一来源:删除 common.py 的手工副本 `_FALLBACK_UAS_BUILTIN``FALLBACK_UAS` 直接引用 `_config.UA_POOL`(消除双份漂移风险)
- search_html 解码修复:改用 `detect_charset`header/meta 自动检测),新增 `--encoding` 强制覆盖(非 UTF-8 SearXNG 实例不再乱码)
- 新增 `pyproject.toml`(可选打包,`searxng-search`/`searxng-fetch` 入口点);函数内冗余导入收敛
**v2.2.1 修复**
- Brotli 乱码修复:`build_browser_headers()` 智能声明 `Accept-Encoding`——仅当本机安装了 brotli/brotlicffi 包时才声明 `br`,避免服务器返回 Brotli 压缩字节而 requests 无法自动解压导致全页乱码
- `fetch.py` 双路径 br 解压:requests 路径和 stdlib urllib 路径都添加了 Brotli 手动解压逻辑(作为双保险,应对代理/CDN 强制返回 br 的边缘情况)
- 此前 bug 表现:Chrome/Edge UA 抓取 example.com 等返回 `Content-Encoding: br` 的站点时,输出 302 字符乱码(gzip 二进制被当作文本解码);修复后输出 127 字符正常文本
**v2.2.0 新功能**
- `--pages N` 分页聚合:一次获取 N 页结果并跨页去重合并,每页独立缓存(cache key 含 pageno),进度事件新增 `page_ok`/`page_fail`
- 缓存治理:缓存大小上限 + LRU 淘汰,新增 `--cache-max-size MB`(默认 100MB);`stats()` 新增 `total_bytes`/`max_size_bytes`/`evicted_count`/`utilization_pct` 字段;新增 `evict_expired()` 主动清理方法
- `--similarity-dedup` 相似度去重:基于标题 SimHash + Jaccard 相似度,默认关闭;`--similarity-threshold`(默认 0.85)控制严格程度;O(n²) 复杂度,结果数 > 500 时自动跳过
- PDF/文档解析:fetch 支持解析 PDFpdftotext subprocess)、`.docx`/`.xlsx`stdlib zipfile);不支持的二进制类型返回 `E_UNSUPPORTED_MEDIA`
- `--log-format json` 结构化日志:每行输出 JSON 对象 `{ts, level, logger, msg, request_id}`,便于 AI Agent 程序化解析
- request ID 贯穿:每次运行自动生成 8 位 hex request_id,贯穿所有日志和进度事件
- `--dry-run` 预览模式:不发 HTTP 请求,打印 `{action, url, params, headers_count}` JSON 到 stdout;支持 search/research/batch/verify 四种模式
- AdaptiveThrottle 参数可配置:新增 `--throttle-failure-threshold`(默认 3)、`--throttle-pause-seconds`(默认 30)、`--throttle-max-delay`(默认 10
- `--research-angles` 自定义研究角度:覆盖默认 5 角度,每个角度直接作为查询后缀
- `--save-config FILE`:将当前 CLI 参数保存为 searxng.toml 配置文件并退出
- `--fetch-report json`:输出完整 JSON 报告(含 items 数组 + summary 摘要);原 `--fetch-report`(无参数)保持 text 格式
- UA 池更新到 2026 年版本:Chrome 138-140 / Edge 138 / Firefox 140 / Safari 18,池移至 `_config.py`SSOT
- readability-lite 按语言调整:CJK 内容 100 字符阈值,其他 200 字符阈值
- classify_error 改用异常链(内部改进)、`_domain_ua_cache` 加锁(内部改进)
**搜索**
- 多实例故障转移 + 并行探测
- 指数退避重试(429/5xx/连接错误)
- 跨引擎去重(忽略 utm_*/gclid 等跟踪参数)
- 结果排序(score/date/engine
- 域名白名单/黑名单
- 批量查询(`--queries-file`
- v2.1.0 研究模式(`--research`):给定主题自动扩展 5 个多角度查询(overview/profile/background/works/review),输出含 `research_topic``research_queries` 元数据
- v2.1.1 增强:跨角度合并去重,输出 `merged_results` 字段;根据主题语言自动切换中英文后缀(中文主题用"简介/经历/作品/评价",英文主题用"profile/background/works/reviews"
- 实例健康检查(`--verify`
**输出**
- JSON(默认,含完整元数据)
- brief(标题+URL+摘要)
- urls(纯 URL 列表)
- CSV(表格导出)
- 结构化 JSON 错误输出
**网页抓取**
- text:提取纯文本
- html:原始 HTML
- markdown:增强 Markdown 转换(GFM 表格、代码块、引用块、嵌套列表、定义列表)
- v2.0.0 readability-lite`<article>`/`<main>` 缺失时,用文本密度算法选最可能正文的 `<div>`v2.2.0CJK 内容 100 字符阈值,其他 200 字符阈值)
- v2.2.0 PDF/文档解析:支持解析 PDFpdftotext subprocess)、`.docx`/`.xlsx`stdlib zipfile);不支持的二进制类型返回 `E_UNSUPPORTED_MEDIA`
**反爬与抓取稳定性(v2.0.0)**
- 浏览器指纹头:`build_browser_headers()` 发送完整 Sec-Ch-Ua / Sec-Fetch-* / Accept-Language,不仅靠 User-Agent
- 15 个 UA 池(v2.2.0 更新):Chrome 138-140 / Edge 138 / Firefox 140 / Safari 18 × Windows/macOS/LinuxUA 池移至 `_config.py`SSOT),common.py 通过导入引用
- 确定性 UA 轮换:`get_ua_for_domain()` 用 SHA-256 为每个域名固定一个 UA(会话内稳定,跨进程可复现)
- requests.Session 复用:连接池 + cookie 持久化 + TLS 会话恢复
- 超时分离:`(connect, read)` 元组,避免大页面下载中途超时浪费已建连接
- Retry-After 遵守:429/503 响应读取 Retry-After header(数字或 HTTP date)作为最小重试延迟
- 退避封顶 60s:原公式无上限,N=10 时达 1536s 会卡死进程
- WAF 指纹库:识别 Cloudflare / Imperva / PerimeterX / DataDome / Akamai / 通用反爬页,全文档扫描(非仅前 2000 字符)
- Wayback Machine 兜底:404/403/超时自动尝试 `https://web.archive.org/web/2/<url>`,默认启用,`--no-fallback` 关闭
- v2.1.0 fetch.py 独立调用也支持 Wayback 兜底(之前仅 search.py --fetch 路径有)
- v2.1.0 被墙站点智能回退:`is_hard_blocked_domain()` 识别百度搜索/百度百科/知乎/微博/微信公众号/豆瓣等强反爬站点,403 时自动优先 Wayback
- v2.1.1 精确化:`baidu.com` 从子域匹配改为精确子域列表(www/baike/zhidao/tieba/wenku),`pan.baidu.com`(网盘)/`cloud.baidu.com`(智能云)不再被误伤
- 自适应限流:`AdaptiveThrottle` 状态机,连续 3 次失败自动翻倍延迟 + 减半并发,429 触发全局暂停 30s
- v2.1.1`report_failure` 新增 `error_code` 参数,优先用结构化 `E_RATE_LIMIT` 检测 429(原字符串匹配"429"会漏判"Too Many Requests");`fetch_page` 返回结果新增 `error_code` 字段
- v2.2.0:原硬编码值现可通过 CLI 配置——`--throttle-failure-threshold`(默认 3)、`--throttle-pause-seconds`(默认 30)、`--throttle-max-delay`(默认 10
- `--fetch-report`:结构化抓取报告到 stderr(每 URL 状态/WAF 类型/兜底方式/字符数 + JSON 摘要);v2.2.0`--fetch-report json` 输出完整 JSON 报告(items 数组 + summary 摘要)
- `--referer` / `--request-delay`:精细控制 Referer 头和请求间隔
- fetch 结果新增字段:`anti_bot_detected`bool)、`waf_type`str|null)、`fallback_used`str|null)、`error_code`str|nullv2.1.1
**缓存**
- SQLite 缓存(`--cache-ttl`),相同查询在 TTL 内跳过网络
- `--clear-cache` / `--cache-stats` 管理缓存
- v2.2.0 缓存治理:`--cache-max-size MB`(默认 100MB)大小上限 + LRU 淘汰;`stats()` 新增 `total_bytes`/`max_size_bytes`/`evicted_count`/`utilization_pct` 字段;新增 `evict_expired()` 主动清理方法
**网络**
- 代理支持(`--proxy`
- 认证(Bearer/Basic,支持 CLI/文件/配置文件/环境变量四级优先级)
- `searxng.toml` 配置 `auth_basic` / `auth_bearer` 字段,AI Agent 一次配置即可
- 凭证文件权限警告(POSIX
**工程**
- 共享 `common.py`(统一重试/字符集/认证/日志/UA池/浏览器头/退避)
- 结构化日志(`--verbose` / `--quiet`
- UTF-8 stdout 强制(`force_utf8_stdout()`,修复 Windows GBK 崩溃)
- Windows 配置路径发现(`%APPDATA%/searxng-cli/`
- fetch.py 失败诊断增强(`status_code=` / `cause=` / `url=` 字段)
- 结构化错误码 + `recovery_hint` 恢复建议(`E_NETWORK` / `E_AUTH` / `E_RATE_LIMIT` 等)
- JSON 输出含 `schema_version` 字段,`--dump-schema` 输出 JSON Schema 文档
- JSON Lines 流式输出(`--stream`,含 `error` 事件类型)
- 进度事件(`--progress`,含 `instance_try`/`instance_ok`/`instance_fail`JSON Lines 到 stderr
- batch 模式统一 schema`status` 字段区分成功/失败)
- 561 个单元+集成测试
## 跨 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
```
561 个测试覆盖:缓存操作、认证解析、域名过滤、Markdown 转换、搜索逻辑、集成流程、日志配置、HTML 回退、自动抓取、健康检查、输出格式化、实例解析、并行搜索、CLI 端到端、错误码分类、流式输出、进度事件、配置文件认证、schema_version、recovery_hint、batch 统一 schema、--dump-schema、UTF-8 stdout 强制、Windows APPDATA 路径、v2.0.0 浏览器指纹头、WAF 反爬检测(v2.0.1 收窄误判 + title 精准检测)、Wayback Machine 兜底(v2.0.1 修复 HTTP 200 反爬页触发)、自适应限流(v2.1.1 结构化 error_code 检测 429)、v2.1.0 Wayback 共享逻辑(should_try_wayback/build_wayback_url)、被墙站点智能回退(v2.1.1 精确化 baidu 子域,pan/cloud 不再误伤)、--research 研究模式(v2.1.1 跨角度合并去重 + 中英文双语后缀)、--time-range week 支持(v2.1.1)、stdlib gzip/deflate 解压(v2.1.1)、实例引擎挂起检测(v2.1.1 _warn_unresponsive_engines)、v2.3.0 新功能(多页实时查询跟踪、GBK charset 检测与 --encoding、UA 单源、并发槽位门控、fetch JSON 契约、fetch_page title/latency、GBK queries 文件、--parallel-queries 并发批量)。
## 项目结构
```
├── 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