thzxx 6cedba9042 fix: 文档解析链路修复 —— 缺失导入 + 静默吞错
- fetch.py: 补全 subprocess/zipfile/xml.etree.ElementTree/io 导入
  (PDF/DOCX/XLSX 解析此前直接 NameError)
- fetch.py main(): 检查 FetchResult.error_code, 文档解析失败不再
  静默输出空内容 + exit 0, 改为明确报错并 exit 1
- search.py fetch_page(): 同样检查 error_code, 修复 --fetch 抓取
  PDF 失败被误报 status=ok 的问题
- _parse_document_content: image/audio/video/* 类型统一返回
  E_UNSUPPORTED_MEDIA (此前退化为乱码文本)
2026-08-03 17:51:05 +08:00

SearXNG CLI 技能包

Python 3.8+ License: MIT

一个面向 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 如何使用

搜索网络

python scripts/search.py -q "搜索词" -i https://your-searxng-instance

AI 调用后,stdout 输出 JSON 格式搜索结果,AI 可解析并使用:

{
  "query": "搜索词",
  "results": [
    {"title": "...", "url": "https://...", "content": "摘要...", "engine": "google", "score": 1.0}
  ],
  "suggestions": ["相关建议词"],
  "answers": ["直接答案(如有)"]
}

抓取网页

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_id8 位 hex,每次运行自动生成);--pages N 时新增 page_ok/page_fail 事件。

--dump-schema:输出当前版本的 JSON Schema 到 stdout 并退出,AI 可程序化发现字段名与类型,无需解析文档。

# 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(自建或受信任的实例)

安装

git clone https://git.metona.cn/MetonaTeam/searxng-use-cli.git

无需安装依赖。search.py 仅使用 Python 标准库,开箱即用。

可选安装:

# 提升 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.tomlWindows
# 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 — 网络搜索

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 批量查询文件(每行一个查询)
--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 — 网页抓取

python scripts/fetch.py -u https://example.com \
  --extract text|html|markdown \
  [--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(必填)
-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.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/.xlsxstdlib 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.pySSOT
  • 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_topicresearch_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/.xlsxstdlib 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.pySSOT),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.1report_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_detectedbool)、waf_typestr|null)、fallback_usedstr|null)、error_codestr|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_failJSON Lines 到 stderr
  • batch 模式统一 schemastatus 字段区分成功/失败)
  • 544 个单元+集成测试

跨 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,跨平台可移植

测试

pip install pytest
pytest -q

539 个测试覆盖:缓存操作、认证解析、域名过滤、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)。

项目结构

├── 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

S
Description
面向 AI Agent 的 SearXNG 搜索与网页抓取 CLI 技能包——隐私友好的元搜索 + 可读文本提取,零 API Key,多实例故障转移 + 反爬 + 重试 + 缓存
Readme MIT
533 KiB
Languages
Python 100%