# 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 Agent(Hermes、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_BLOCKED` | 抓取被站点反爬/WAF 拦截(403,v2.4.0) | 不是凭证问题——用 Wayback 兜底(默认开)、换镜像/其他 URL、或 `--exclude-domain` 排除该域名 | | `E_NETWORK` | 网络错误(连接失败、5xx) | 重试退避、切换实例、检查代理 | | `E_RATE_LIMIT` | 限流(429) | 等待重试、降低频率、分散负载 | | `E_PARSE` | 解析错误 | 切换实例、切换 `--method` | | `E_EMPTY` | 空结果(exit 2) | 调整查询词、扩大 `--time-range`/`--categories` | | `E_INPUT` | 输入错误(参数/文件) | 检查语法、标志组合、文件路径 | | `E_INTERNAL` | 内部错误 | 用 `--verbose` 重跑并报告 | | `E_BLOCKED` (v2.4.0) | 抓取被反爬/WAF 拦截(403) | 换 URL/镜像,或 `--exclude-domain`;Wayback 兜底默认开启 | | `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/json(json = 结构化 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.5.0 新功能与修复** - 修复核心反爬头 `Sec-Ch-Ua` 构造 bug:原实现产出 `""Not_A Brand";v="99""` 畸形头(双重引号),Chrome/Edge 两条路径都存在,严格校验的 WAF 会忽略;现改为品牌数组统一拼接,产出 `"Not_A Brand";v="99", "Chromium";v="140", "Google Chrome";v="140"` 合法格式(真实浏览器已验证) - `fetch.py --extract json`:结构化骨架输出 `{title, meta_description, headings[], links[], images[]}`——AI 只看骨架即可判断页面价值,无需拉全文(隐含 `--format json`;stdlib/bs4 双路径输出同构) - `fetch.py --max-chars N`:提取后语义级字符截断(区别于 `--max-size` 的原始字节截断),`truncated` 字段如实标记 - `search.py --fetch-total-chars N`:`--fetch` 全局字符预算,按结果顺序自上而下分配(剩余额度留给下一页),耗尽后剩余 URL 标记 `status="skipped"`(不发请求)——token 受限 agent 的上下文预算控制 - `--dedup-fetched-content`:抓取正文相似度去重(SimHash,复用 `--similarity-threshold`),镜像/转载页面标记 `status="duplicate"`(text 清空),避免 AI 重复阅读同一内容 - `--progress` 新增 research 角度级事件:`angle_start`/`angle_ok`/`angle_fail`(含 `index`/`total`);fetch 链路新增 `fetch_skip`/`fetch_duplicate` 事件 - `fetch.py` 补齐 `--log-format json` 与 `--dump-schema`(与 search.py 对齐,结构化 JSON 契约可程序化发现) - CSV 输出媒体列自适应:images/videos 类别结果自动追加 `img_src`/`thumbnail_src`/`resolution`/`iframe_src`/`source` 列(纯文本结果不变,向后兼容) - `--dry-run` 批量模式打印实际查询列表(`queries` 字段,读本地文件不发 HTTP) - search 连接复用:requests 可用时走模块级 Session(连接池 + TLS 会话恢复),`--pages`/批量/研究模式多请求场景显著降开销;stdlib 零依赖路径不变 - search 403 快速失败:实例级 403 不再退避重试(原 ~10.5s 空等),立即 failover;fetch 的 403 UA 轮换语义不受影响 - `AdaptiveThrottle` 修复 `--throttle-failure-threshold 0` 语义:现为真正的"禁用自适应退避"(原实现 0 导致首次失败即退避) - 新增 `scripts/release_check.py` 发布一致性检查:版本号(pyproject/_config/文档)与错误码表(common.py/README/SKILL)漂移检测 - 版本对齐:pyproject.toml 与 _config.py 同步为 2.5.0(此前 v2.4.0 发布时 pyproject 停在 2.3.0) **v2.4.0 新功能** - 新增 `E_BLOCKED` 错误码:fetch 场景的 403(WAF/反爬拦截)从 `E_AUTH` 细分出来——被封锁不是凭证问题,AI Agent 不再误判为"需要检查认证"。新增 `classify_fetch_error()` / `_extract_status_code()`(common.py),应用于 `fetch.py` 与 `search.py --fetch`;SearXNG 实例认证的 403 仍映射 `E_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 支持解析 PDF(pdftotext 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:`
`/`
` 缺失时,用文本密度算法选最可能正文的 `
`(v2.2.0:CJK 内容 100 字符阈值,其他 200 字符阈值) - v2.2.0 PDF/文档解析:支持解析 PDF(pdftotext 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/Linux;UA 池移至 `_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/`,默认启用,`--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|null,v2.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` 字段区分成功/失败) - 572 个单元+集成测试 ## 跨 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 ``` 572 个测试覆盖:缓存操作、认证解析、域名过滤、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 并发批量)、v2.4.0 E_BLOCKED 错误码(fetch 403 反爬拦截细分,classify_fetch_error)。 ## 项目结构 ``` ├── 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