SearXNG 的工作原理:从一次搜索请求到结果聚合(技术向)
SearXNG 是一个 元搜索(metasearch)聚合器:它不像 Google/Bing 那样自己维护一个覆盖全网的倒排索引库,而是把你的查询同时发给多个搜索引擎/数据源,然后把返回结果进行 标准化、去重、重排,再统一展示。
这篇文章从工程视角拆开讲:一次搜索请求在 SearXNG 里到底经历了什么、每一层在解决什么问题,以及为什么“自建元搜索”会遇到验证码/封禁、以及如何权衡。
1. 典型架构:SearXNG 站在你和搜索引擎之间
把它看成三层会更清晰:
- Web/UI 层:接收用户请求,输出 HTML/JSON
- 引擎适配层(engines):把 query 翻译成每家引擎的请求,并解析返回
- 聚合层(aggregation):合并、去重、评分、排序
数据流大致如下:
浏览器/客户端
│ (q=... & category=...)
▼
SearXNG
│ 并发请求
├────────────► Engine A (HTML/JSON)
├────────────► Engine B (HTML/JSON)
├────────────► Engine C (HTML/JSON)
▼
标准化结果列表
▼
去重/融合/评分
▼
输出 HTML/JSON
隐私点:对外部引擎来说,请求来源是 SearXNG 服务器的出口 IP,而不是用户的真实 IP。
2. 一次搜索请求的生命周期(request lifecycle)
当你在 SearXNG 输入关键词并点击搜索,大体会经历:
2.1 参数解析与规范化
SearXNG 会把请求参数归一化成内部统一模型,例如:
- query 文本
- 语言/地区(
language/locale) - 搜索类别(
general / images / news / videos等) - 时间范围(过去一天/一周/一月)
- 安全搜索等级
- 页码、每页数量
它的意义是:不同引擎的参数体系不一致,先把“用户意图”抽象出来。
2.2 选择引擎集合(engine selection)
你配置里启用的引擎,会按 category 过滤。例如:
- 你搜“图片”,只会调图片引擎
- 你搜“新闻”,只会调新闻引擎
同时还会考虑:
- 引擎是否健康(最近是否大量失败)
- 引擎是否需要 key
- 引擎是否被限制(限速/并发)
2.3 并发调度与超时控制
核心点:同一查询会被拆成多个独立的 engine task 并行执行。
工程上通常会有:
- 单引擎请求超时(避免被慢引擎拖死)
- 全局超时(前端体验不能无限等)
- 失败隔离(某个引擎挂了不影响整体)
所以你常看到:
- 某些引擎 0 results 或报错
- 但整体仍能返回结果
3. 引擎(engine)适配:最“脆弱”也最核心的部分
每个引擎模块基本都包含:
3.1 请求构造(build request)
要解决的问题:
- A 引擎用
q=,B 引擎用query= - 语言参数格式不一样(
hl=zh-CN/lr=lang_zh-CN/setlang=...) - 时间筛选方式不一样
- 有的走 HTML 页面,有的走 JSON API
以及请求指纹:
- User-Agent
- Accept-Language
- Referer
- Cookie(通常尽量不用,保持“无状态”)
3.2 结果解析(parse response)
这是最容易坏的一环:
- 引擎页面结构经常变(CSS selector 改、DOM 改)
- 反爬策略变化会导致返回验证码页/挑战页
解析输出会统一成类似结构:
titleurlcontent/snippetengine(来源)publishedDate(若可得)thumbnail(若可得)
理解重点:SearXNG 不负责“检索”,它负责“把别人检索的结果稳定转成统一格式”。
4. 聚合层:去重、融合、排序怎么做
把多个引擎结果拉回来以后,SearXNG 会做“结果融合”。这部分通常包含:
4.1 URL 规范化(canonicalization)
为了去重,需要把 URL 做标准化,例如:
- 去掉常见跟踪参数:
utm_*、ref、fbclid等 - http/https 统一
- 去掉末尾
/
否则同一页面会因为参数不同被当成多条结果。
4.2 去重(dedup)
常见策略是:
- URL 相同 → 合并
- URL 不同但高度相似(同域名同路径差一点)→ 可能合并(依实现)
合并后通常会保留:
- “被哪些引擎返回过”
- “出现次数/投票数”
4.3 评分与重排(scoring / rerank)
SearXNG 不会重建 PageRank,但会做轻量排序:
- 同一条结果被多个引擎返回 → 通常加分(类似投票)
- 引擎权重(engine weight)→ 你更信任谁就给谁更大权重
- 时间过滤(新闻/博客)→ 新鲜度可影响
这也是为什么:
- 多引擎聚合能减少“单引擎偏差”
- 但也可能放大“同质化来源”的排名
5. 隐私机制:为什么它能“保护用户”
SearXNG 的隐私优势主要来自:
- 搜索引擎看不到用户真实 IP:它只看到你的 SearXNG 出口 IP
- 可配置不记录用户行为:不做画像、不做广告 ID
- 可自定义请求头/参数清理:减少可识别信息
- 可配出口代理:让 SearXNG 自己通过代理访问引擎(进一步隔离)
但这也带来代价:
- 如果你的出口 IP 被引擎判定为“机器人/异常流量”,更容易触发验证码
6. 为什么自建会遇到验证码/封禁(反爬视角)
对引擎来说,SearXNG 的访问模式往往“像机器人”:
- 同一 IP 在短时间内访问大量 query
- 请求头/指纹较固定
- 缺少真实用户的浏览器行为信号
因此常见现象:
- 返回 challenge 页面(而不是结果)
- 返回空结果或 429/403
- 解析器失效(因为拿到的不是搜索结果 DOM)
工程应对一般是:
- 限速与并发控制(最重要)
- 选择更稳定/更友好的引擎
- 出口代理池(成本更高)
- 在可行时使用官方 API(更稳定但可能要钱/要 key)
7. 缓存与性能:为什么很多实例需要缓存
一条 query 如果被多个用户重复搜索(比如热点关键词),可以缓存:
- 降低对外部引擎的请求压力
- 减少触发反爬
- 提升响应速度
但缓存也有 trade-off:
- 时效性下降
- 对“个性化/地区化结果”可能不适用
8. 实用建议:如何把 SearXNG 调到“更稳、更快、更少验证码”
如果是自建(尤其公开给多人用),我通常建议:
- 减少引擎数量:挑 3~6 个稳定引擎即可,不要 20 个全开
- 控制并发与速率:宁可慢一点也不要被封
- 优先选择 API 型引擎(可选):稳定但可能需要 key
- 把实例放在“出口质量好”的网络:出口 IP 风险小很多
- 加反向代理与基础防护:避免被人当成“开放代理”滥用
如果你把你当前 settings.yml 的两段配置贴出来:
engines:(启用了哪些引擎、权重)outgoing:(是否走代理、超时并发)
我可以按你实际配置做一次“针对性调参建议”(哪些引擎该关、权重怎么配、并发怎么设)。