dsh 联网搜索:web_search 提供方与自建 SearXNG
dsh 的 web_search 默认走 deepseek-official,每次搜索都另算一次 API 费用。讲清提供方怎样选择、为何报错,以及如何改用 Exa 或同机自建、免密钥的 SearXNG。
dsh 联网搜索的默认路径
dsh(DeepSeek Harness)的联网搜索由两个面向模型的工具完成:web_search 负责搜索,web_fetch 负责抓取网页。默认的搜索提供方是 deepseek-official,它每次搜索都会另外向 DeepSeek API 发一次请求,单独消耗 token。想换后端,就改 web 这一行配置里的 searchProvider。想要免密钥、不产生额外的 DeepSeek 请求,可以在同一台 VPS 上跑 SearXNG,再用插件或 MCP 接进来。
下文以 npm 上 @deepseek-ai/dsh 的 latest 版本为准。截至 2026 年 10 月 15 日,latest 是 0.2.0-rc.2,对应 Git 标签 dsh-v0.2.0-rc.2,源码仓库是 deepseek-ai/deepseek-harness。文中的配置键、提供方 id 和错误码都出自这个标签。版本变了,键名也可能跟着变,所以第一步是固定版本。
先固定版本,再看实际生效的配置
这个版本的 dsh 要求 Node ^22.19.0 || >=24.0.0。Node 版本不够,后面的命令都跑不起来,所以先检查:
node --version
alias dsh='npx -y @deepseek-ai/dsh@0.2.0-rc.2'
dsh web --dump-config > composed.yml
grep -n -A4 'id: web$' composed.ymlnode --version 应输出 v22.19.0 或更高的 22.x,或者 v24 及以上。alias 把命令固定在这个版本,避免 npx 悄悄拉取新版本。--dump-config 打印组合后的完整配置树然后退出,不会启动服务。输出里的注释写明每一行来自哪个文件,以及哪些覆盖层改过它。
在 0.2.0-rc.2 的基础 bundle(packages/bundle/base/cordis.patch.yml)里,web 这一行是这样写的:
- id: web
name: '@deepseek-ai/dsh-web'
config:
searchProvider: deepseek-official
fetchProvider: http也就是说,默认配置并不是自动挑一个提供方。它写死了 deepseek-official 负责搜索,http 负责抓取。后面所有的改动,本质上都是在改这一行。
在 VPS 上通过 SSH 运行 dsh web 时,它只打印地址,不会替你打开浏览器。Web 界面默认监听 http://127.0.0.1:3080。从自己的电脑访问它的方法,见 在 VPS 上访问 dsh Web 界面。
web_search 背后的结构:ctx.web 和提供方
联网在 dsh 里是一项可选能力。官方中文文档 docs/subsystems/web.zh.md 的原话是:“Web 是一项可选能力,不属于 agent loop(智能体循环)主干”。这项能力由几个包拼成:
dsh-web:服务本身,挂在ctx.web上,只有搜索(search)和抓取(fetch)两种操作。dsh-web-search-deepseek:默认搜索提供方,id 是deepseek-official。dsh-web-search-exa和dsh-web-search-perplexity:另外两个搜索提供方,id 分别是exa和perplexity。dsh-web-fetch-http:默认抓取提供方,id 是http。dsh-tool-web:把这项能力变成模型能调用的web_search和web_fetch工具。
ctx.web 对插件暴露四个方法:registerSearchProvider、registerFetchProvider、search 和 fetch。两个注册方法都返回一个函数,调用它就撤销注册。同一个搜索 id 注册两次,会抛出 WEB_DUPLICATE_PROVIDER。每个提供方还要实现 available()。文档要求它只做本地检查,比如凭据在不在、配置能否解析,不能发网络请求。所以 available() 返回 true,只说明配置看起来齐全,不说明远端服务真的能用。
tool-web 有一条容易误会的规则:工具是否注册,取决于产品开关,而不是后端是否可用。README 原文是 “Tool registration follows product enablement, not backend availability.” 结果是:提供方缺失或没配好时,模型照样能看到 web_search,只有真正调用时才返回一个结构化的 WebError。看到模型说搜索失败,先读工具返回里的错误码,不要先怀疑工具没加载。
web_search 接收一个 queries 数组,每次 1 到 searchMaxQueries 条,默认上限是 4。web_fetch 只接收一个 url。一次搜索返回的条数上限 searchMaxResults 默认是 8。超时由 searchTimeoutMs 和 fetchTimeoutMs 控制,tool-web 自己的默认值都是 30000 毫秒。基础 bundle 把 searchTimeoutMs 改成了 60000,给默认的 DeepSeek 搜索留出更多时间。
还有一点要注意。在 dsh web 里,web-app bundle 把宿主层的 tool-web 行设成了 disabled: true。基础配置的注释说明,Web 应用会按智能体预设(preset)分别组合这些工具。所以在 Web 界面里,web_search 是否出现,要看你选的预设,不能只看 tool-web 那一行。
为什么 dsh 不会随便挑一个提供方
选择规则只看两个字段:searchProvider 和 fetchProvider。在 dsh-web 包里,两者默认都不设置。环境变量 DSH_WEB_SEARCH_PROVIDER 和 DSH_WEB_FETCH_PROVIDER 填的是同一组字段,不是另一条优先级链。字段不设置时,只有恰好一个提供方可用,才会自动选中它。
这套规则的重点是失败要明确。注册顺序、配置顺序和热重载顺序,都不决定选哪个。可能的错误有四个:
WEB_PROVIDER_CONFIGURED_MISSING:配置了 id,但没有任何包注册这个 id。通常是包没装,或者 id 拼错。WEB_PROVIDER_CONFIGURED_UNAVAILABLE:id 已注册,但它的available()返回 false,多半是缺密钥。WEB_PROVIDER_UNAVAILABLE:没有配置 id,也没有任何可用的提供方。WEB_PROVIDER_AMBIGUOUS:没有配置 id,但有多个提供方可用。文档原话:“如果存在多个可用提供方却未配置 id,则抛出WEB_PROVIDER_AMBIGUOUS,而不会选用最先注册的提供方。”
这样设计,是为了避免一种很难排查的情况:你多装了一个提供方,搜索就悄悄换了后端,账单也换了地方。
基础 bundle 的 web 行已经写死了 searchProvider: deepseek-official。只设置环境变量 DSH_WEB_SEARCH_PROVIDER 能不能盖过这个写死的值,文档没有说明,这里也没有测试。稳妥的做法是直接用补丁改这一行,再用 --dump-config 确认结果。
默认的 deepseek-official 花的是哪份钱
deepseek-official 不是在你的对话里顺便搜一下。每次搜索,它都另外向 DeepSeek 的 Anthropic 兼容接口发一次 Messages 请求,请求里带着服务端工具 web_search(类型是 web_search_20250305)。它的 README 写明:“Separate provider input and output tokens are incurred for each search”,即每次搜索都单独产生输入和输出 token。
这个提供方的默认配置如下:
model:deepseek-v4-flashmaxUses:5,即一次请求里服务端web_search最多使用 5 次apiKeyEnv:DEEPSEEK_API_KEYbaseURL:https://api.deepseek.com/anthropic/v1
这里的 baseURL 是这个辅助请求自己的设置,和聊天适配器使用的 $DEEPSEEK_BASE_URL 无关。
DeepSeek 中文价格页(2026 年 10 月 17 日查看)把 deepseek-v4-flash 列为旧名称:仍可调用,请求由 DeepSeek-V4.1-Flash 处理,按 Flash 的价格计费。价格页上 Flash 当前的模型名是 deepseek-flash。Flash 的价格按每百万 tokens 计,单位是元:
- 输入(缓存未命中):空闲时段 1 元,高峰时段 2 元
- 输入(缓存命中):空闲时段 0.02 元,高峰时段 0.04 元
- 输出:空闲时段 4 元,高峰时段 8 元
高峰时段是北京时间周一至周五(不含中国法定节假日)9:00 至 12:00 和 14:00 至 18:00。空闲时段的价格是高峰时段的一半。价格页另有“网页搜索与抓取价格”一节:Search 和 Fetch 是独立的 API,按请求次数计费,各为每 1,000 次成功请求 5 元。这一节直接点名了 DeepSeek Harness:在 DeepSeek Harness、Claude Code 或 Codex 中使用 DeepSeek API 时,会通过服务端工具调用访问 Search/Fetch 接口,原话是“这部分 Search/Fetch 接口调用目前未计费,并将于北京时间 2026 年 11 月 1 日 00:00 起按次收取调用费用”。也就是说,deepseek-official 发起的服务端搜索,现在只算 token,从北京时间 2026 年 11 月 1 日 00:00 起,还要按次另付 Search 的请求费用。一次 dsh 搜索里,服务端搜索最多可以用到 maxUses 设定的 5 次,实际计了多少次,以控制台记录为准。一次搜索消耗多少 token,取决于查询内容和返回的网页,所以这里不给估算值。想知道真实成本,就在 DeepSeek 控制台看用量,对比开启搜索前后的变化。另外,搜索结果会作为工具结果回到你的对话里,在主模型那边还要再算一次输入 token。
凭据方面,deepseek-official 只认两样东西:DeepSeek 账号登录,或者 DEEPSEEK_API_KEY。两者都有时,登录令牌优先,并且只通过 x-dsh-auth-token 请求头发送。两者都没有时,搜索失败,错误码是 WEB_PROVIDER_CREDENTIAL_MISSING。基础配置的注释说,搜索使用的是 Models 页面为聊天管理的同一个密钥,每次搜索时才去解析。这意味着:如果你把聊天模型换成了别家的服务,又没有留下 DeepSeek 的密钥,搜索就会因为缺凭据而失败。密钥和模型的配置方法,见 dsh 的 API 密钥与模型配置。
换成 Exa 或 Perplexity:要自己挂载
dsh-web-search-exa 和 dsh-web-search-perplexity 都作为独立的 npm 包发布。但是 0.2.0-rc.2 里的六个 bundle(base、web-app、headless、sdk-app、acp-app、sdk-minimal)都没有挂载它们。要用它们,得自己装包,再在补丁里插入一行,并把 searchProvider 指过去。
以 Exa 为例。先把包装进 web 这个 profile,版本和 dsh 保持一致:
dsh plugin --profile web add @deepseek-ai/dsh-web-search-exa@0.2.0-rc.2
export EXA_API_KEY='你的 Exa 密钥'dsh plugin 会把后面的参数原样交给 pnpm,在该 profile 的目录里执行。Exa 提供方在配置里没有 apiKey 时,会读取 $EXA_API_KEY。密钥为空或不存在,它就被视为不可用。
然后写一个补丁文件 web-search.yml:
- id: web
config:
searchProvider: exa
fetchProvider: http
- insert:
- id: web-search-exa
name: '@deepseek-ai/dsh-web-search-exa'注意第一段里的 fetchProvider: http。你只想改搜索,为什么还要写抓取?因为按 id 定位的补丁会整体替换这一行的 config,不做逐键合并。CLI 参考文档的原话是:“a patch replaces the targeted row's complete config value rather than deep-merging keys”。如果只写 searchProvider: exa,fetchProvider 就从这一行消失,回到未设置的状态,抓取改按自动选择的规则运行。
同样的问题在 tool-web 行更容易踩到。假设你只想把结果条数改小,补丁里只写了 searchMaxResults: 5。那么基础配置里的 searchTimeoutMs: 60000 也被丢掉,搜索超时退回 tool-web 默认的 30000 毫秒。改哪一行,就把那一行的全部键重写一遍。
先看组合结果,确认无误再启动:
dsh web --patch ./web-search.yml --dump-config | grep -n -A4 'id: web$'
dsh web --patch ./web-search.yml第一条命令应显示 searchProvider: exa 和 fetchProvider: http,旁边的注释指向 web-search.yml。启动后,如果搜索返回 WEB_PROVIDER_CONFIGURED_MISSING,说明 exa 没有注册成功,先查包有没有装进 web profile。如果返回 WEB_PROVIDER_CONFIGURED_UNAVAILABLE,说明包已加载,但 dsh 进程里的 EXA_API_KEY 是空的。
Perplexity 的做法相同。它的提供方 id 是 perplexity,密钥回退到 $PERPLEXITY_API_KEY,默认接口是 https://api.perplexity.ai,默认模型是 sonar。
--patch 适合做试验。想长期生效,就把同样的内容写进 profile 自己的 $DSH_HOME/profiles/web/cordis.patch.yml,或者主目录级的 $DSH_HOME/cordis.patch.yml。没有设置 $DSH_HOME 时,它一般是 ~/.dsh,以 --dump-config 注释里显示的路径为准。合并顺序是:先是各个 bundle 补丁,然后是 profile 补丁,再是主目录补丁,最后是命令行上的每个 --patch。同一行以后面的层为准。
免密钥方案:在同一台 VPS 上运行 SearXNG
SearXNG 是开源的元搜索引擎。它把查询转发给多个上游搜索引擎,再把结果合并返回。它不需要 API 密钥,跑在你自己的 VPS 上,搜索这一步也不再产生 DeepSeek 的辅助请求。完整的部署说明见 自建 SearXNG 搜索引擎。这里只做 dsh 需要的部分:只监听 127.0.0.1,并打开 JSON 输出。
JSON 输出必须手动打开。SearXNG 默认只开 HTML 格式,请求一个没有开启的格式,会得到 403 Forbidden。先写好配置,再启动容器:
mkdir -p ~/searxng/config ~/searxng/data
cd ~/searxng
cat > config/settings.yml <<EOF
use_default_settings: true
server:
secret_key: "$(openssl rand -hex 32)"
search:
formats:
- html
- json
EOFuse_default_settings: true 表示其余设置沿用 SearXNG 的内置默认值,你只写需要改的部分。secret_key 必须换成随机值,openssl rand -hex 32 会在写文件时生成它。
启动容器,端口只绑定到本机回环地址:
docker run --name searxng -d --restart unless-stopped -p 127.0.0.1:8888:8080 -v "./config/:/etc/searxng/" -v "./data/:/var/cache/searxng/" docker.io/searxng/searxng:latestSearXNG 官方文档的示例写的是 -p 8888:8080。那样 Docker 会在所有网卡上监听,任何人都能拿你的 VPS 去搜索。加上 127.0.0.1: 前缀后,只有 Docker 所在的这台主机能连上。这一点有版本前提:Docker 文档提醒,28.0.0 之前的版本里,同一二层网段上的其他主机(比如接在同一台交换机上的机器)仍能访问发布到 localhost 的端口。先运行 docker version 看 Server 的版本号,低于 28.0.0 就先升级 Docker。官方文档也建议,要对公网开放,就放在反向代理后面。真有这个需要,先读 公开 SearXNG 实例的加固方法。
检查监听地址和 JSON 接口:
ss -ltn | grep 8888
curl -s -o /dev/null -w '%{http_code}\n' 'http://127.0.0.1:8888/search?q=deepseek&format=json'
curl -s 'http://127.0.0.1:8888/search?q=deepseek&format=json' | jq '.results | length'ss 应只显示 127.0.0.1:8888,不能出现 0.0.0.0:8888。第二条命令应输出 200。输出 403,说明 json 没有写进 search.formats,或者容器没有读到这份配置。改完配置要执行 docker restart searxng。容器刚启动的几秒内,curl 可能连不上,稍等再试。第三条命令输出结果条数。输出 0,说明接口是通的,但上游引擎没有返回结果。系统里没有 jq,先执行 sudo apt install -y jq。
JSON 接口还支持 categories、language、time_range(可选 day、month、year)和 pageno(默认是 1)。SearXNG JSON API 接入 Open WebUI 用的是同一个接口,可以对照着看。
哪些引擎在你的 VPS 上能出结果
这个问题没有通用答案,必须自己测。同一份配置,放在中国大陆的 VPS 上和放在境外的 VPS 上,能正常返回结果的上游引擎可能差别很大。有的引擎连不上,有的会返回验证码页面。这里不给结论。可行的做法是:挑几个你常用的查询,分别跑上面的 jq 命令看结果条数,然后看容器日志:
docker logs --tail 50 searxng日志里反复出现超时或被拒绝的引擎,就在 SearXNG 的设置里停用它,免得每次搜索都要等它超时。遇到验证码类的错误,参考 SearXNG 引擎验证码错误的处理方法。
接入方式一:社区插件 A3Boy/dsh-web-tools
SearXNG 不是 dsh 内置的提供方。要让 web_search 走 SearXNG,需要一个插件把它注册成 ctx.web 的搜索提供方。A3Boy/dsh-web-tools 就是这样一个插件,仓库描述是 “Multi-provider Web Search & Fetch for DeepSeek Harness”。截至 2026 年 10 月 15 日,它采用 MIT 许可证,有 35 个 star,main 分支最新的提交是 a3a2ffe7433a883e6cd0f72e632b1330fd15f396(2026 年 10 月 5 日),版本号是 0.3.5。它支持的后端包括 Exa、Tavily、Firecrawl、Parallel、Brave Search、You.com、Jina 和 SearXNG。
安装插件,等于让别人的代码带着你的智能体的权限运行。先按 dsh 插件的工作原理与审查方法 读代码,再决定装不装。装的时候,要固定到你读过的那个提交:
git clone https://github.com/A3Boy/dsh-web-tools.git
cd dsh-web-tools
git checkout a3a2ffe7433a883e6cd0f72e632b1330fd15f396
cat package.json cordis.patch.yml
ls lib src读的时候,重点看这几处:
package.json的scripts。在这个提交里,没有preinstall、install、postinstall或prepare,只有prepack,所以安装时不会自动执行脚本。- 依赖项:
defuddle、linkedom、undici和ws。 lib/目录。仓库里提交了构建好的lib/,实际运行的是它,不是src/。只读src/不够。要么直接读lib/,要么自己重新构建,再和lib/对比。cordis.patch.yml,也就是插件对配置的改动,下面单独说。
插件的补丁把 web 行的 searchProvider 改成 dsh-web-tools,同时把 fetchProvider 改成 dsh-web-tools-fetch。这意味着,web_fetch 从此不再走内置的 http 提供方。后面威胁模型一节提到的 SSRF 检查,属于内置的抓取路径。换成插件以后,抓取时会不会拦截内网地址,要看插件自己的代码。补丁还把宿主层的 tool-web 行设为 disabled: false,并完整重写了这一行的全部配置,原因正是前面说的整体替换规则。
插件里还有驱动本机浏览器、抓取特定社交平台的代码。这里不讲这部分,但审查时它在你要读的范围之内。插件仓库还合并过一个与 SearXNG 基本认证相关的改动,README 里没有写用法。你的 SearXNG 如果设了 HTTP 基本认证,要先读代码确认怎么配置。
插件 README 给的安装命令是 dsh plugin --profile web add github:A3Boy/dsh-web-tools,它装的是 main 分支在那一刻的代码,不是你读过的那个版本。dsh plugin 把参数交给 pnpm,而 pnpm 支持在 GitHub 简写后面加 #提交哈希:
dsh plugin --profile web add A3Boy/dsh-web-tools#a3a2ffe7433a883e6cd0f72e632b1330fd15f396装好后,重启 dsh web,打开 Settings 里的 Web Search。新安装的插件默认使用 Exa,要手动切换到 SearXNG。API Key 留空。Base URL 填 http://127.0.0.1:8888,插件文档的示例端口是 8080,这里按上面容器的端口填。然后点 Test Search。报 no usable provider 或 HTTP 403 时,先回去检查 search.formats 里有没有 json。
README 里还有一条更新命令:dsh plugin --profile web update dsh-web-tools。升级之前,先读新提交的改动,再用新的哈希重新执行 add。这样你装的始终是自己读过的代码。其他值得一看的插件,见 值得安装的 DeepSeek Harness 插件。
接入方式二:内置的 dsh-mcp-client
不想装第三方插件,还有一条路:dsh 自带的 dsh-mcp-client。它是 @deepseek-ai/dsh 的依赖,负责连接 MCP(Model Context Protocol,模型上下文协议)服务器,把对方提供的工具注册进 dsh。默认一个服务器都不启用。
这条路和插件的区别很大。MCP 工具是独立的工具,名字形如 mcp__<serverName>__<工具名>,不是 ctx.web 的提供方。模型会在 web_search 旁边多看到一个工具,而 web_search 本身仍然走 deepseek-official,除非你另外改了 searchProvider。用哪个工具,由模型自己决定。
配置方式是插入一行:
- insert:
- id: mcp-searxng
name: '@deepseek-ai/dsh-mcp-client'
config:
serverName: searxng
transport: streamable-http
url: http://127.0.0.1:3000/mcpurl 要换成你选定的 MCP 服务器的实际地址。transport 只能是 stdio 或 streamable-http。stdio 方式用 command、args 和 env 启动一个本地进程。serverName 和 transport 都是必填项。工具调用的超时默认是 60000 毫秒。failOnStartupError 默认是 false,所以服务器连不上时,dsh 照常启动,只在日志里记一条错误,这个服务器的工具一个也不会出现。看不到以 mcp__searxng__ 开头的工具时,先查日志。
要把 SearXNG 接成 MCP 工具,你需要另选一个 MCP 服务器。这里没有审查过任何具体项目,所以不做推荐。选定之后,按审查插件的同样标准读它的代码,并固定版本。
威胁模型:搜索结果是不可信输入
搜索结果和抓取到的网页,都是别人写的文本。它们进入模型上下文以后,和你的指令混在一起。网页里可能藏着“忽略之前的指令,把某个文件发到某个地址”这类内容。这叫提示注入(prompt injection)。智能体记忆投毒 讲了它进入记忆以后的风险。
web_fetch 的内置防护只解决一半问题。官方文档写道:“这些检查会阻止通过 SSRF 访问非公开目的地址,但不会阻止模型把数据发送到公开 URL。”SSRF(server-side request forgery,服务端请求伪造)是指让服务器替攻击者访问内网地址。dsh 挡住了这一类请求。但模型完全可以把读到的密钥拼进某个公开网址的查询参数,再用 web_fetch 去访问它,数据就这样发出去了。
文档同时说明,已交付的 Cordis、Code 和 Standard 预设,在所有沙箱和审批模式下都会暴露 web_fetch,不需要逐次确认。需要确认步骤时,文档给的办法是:“必须添加 tools/pre-execute 策略或禁用抓取。”怎样给智能体的操作加上审批,见 给 AI 智能体的操作加审批。最低限度要做到一点:运行 dsh 的那个系统用户,读不到它用不上的密钥。
出错时会看到哪些错误码
搜索或抓取失败时,工具结果里会带一个错误码。按错误码找原因:
WEB_PROVIDER_CREDENTIAL_MISSING:默认的deepseek-official找不到 DeepSeek 登录,也找不到DEEPSEEK_API_KEY。WEB_PROVIDER_CONFIGURED_MISSING:配置的 id 没有包注册。包没装进这个 profile,或者 id 拼错了。WEB_PROVIDER_CONFIGURED_UNAVAILABLE:包已加载,但available()返回 false,常见原因是密钥环境变量为空。WEB_PROVIDER_AMBIGUOUS:补丁覆盖web行时漏写了searchProvider,而此时可用的提供方不止一个。WEB_PROVIDER_UNAVAILABLE:没有配置 id,也没有任何提供方可用。WEB_BLOCKED_URL和WEB_REDIRECT_BLOCKED:内置抓取拒绝了非公开地址,或拦截了一次跳转。使用内置http抓取时,让web_fetch去访问127.0.0.1:8888上的 SearXNG 会被拒绝,这是预期行为。WEB_FETCH_TIMEOUT、WEB_FETCH_TOO_LARGE和WEB_UNSUPPORTED_CONTENT_TYPE:抓取超时、内容超过上限,或者内容类型不受支持。
FAQ
dsh 的 web_search 每次搜索要花多少钱?
token 部分没有固定数字。默认的 deepseek-official 每次搜索都另外发一次 DeepSeek 请求,默认模型是 deepseek-v4-flash,按 DeepSeek-V4.1-Flash 的价格计费。2026 年 10 月 17 日的 DeepSeek 中文价格页上,缓存未命中的输入是每百万 tokens 空闲时段 1 元、高峰时段 2 元,输出是空闲时段 4 元、高峰时段 8 元。价格页还单独列出了 Search API 的按次价格:每 1,000 次成功请求 5 元。价格页写明,DeepSeek Harness 里经服务端工具调用访问的 Search/Fetch 目前未计费,从北京时间 2026 年 11 月 1 日 00:00 起按次收费。一次搜索用多少 token 也随查询变化,所以要在 DeepSeek 控制台看实际用量。
聊天模型不用 DeepSeek,为什么搜索还报 WEB_PROVIDER_CREDENTIAL_MISSING?
因为默认的搜索提供方 deepseek-official 和聊天模型是分开的。它需要 DeepSeek 账号登录或 DEEPSEEK_API_KEY,两者都没有就报这个错。解决办法有两个:补上 DeepSeek 密钥,或者用补丁把 web 行的 searchProvider 改成别的提供方,同时在同一行里保留 fetchProvider: http。
只想改 searchProvider,为什么网页抓取的设置也变了?
按 id 修改某一行的补丁,会整体替换这一行的 config,不会逐键合并。补丁里只写了 searchProvider,原来的 fetchProvider: http 就没有了。改哪一行,就把那一行的所有键都写全,然后运行 dsh web --dump-config 确认组合后的结果。
自建的 SearXNG 返回 403,dsh 搜不到结果,怎么办?
SearXNG 默认只开 HTML 输出,实例没有开启 JSON 时,请求 format=json 就会返回 403 Forbidden。在 settings.yml 的 search.formats 下加上 json,执行 docker restart searxng,再运行 curl -s -o /dev/null -w '%{http_code}\n' 'http://127.0.0.1:8888/search?q=test&format=json' 检查,正常应输出 200。