网络搜索和读取网页的维护记录:Sonar Pro Search 和 DeepSeek Search、Fetch
这是网络搜索和读取网页背后的维护记录。用的时候不用看,出问题或者要改做法时再看。
2026-10-01 先接的是 DeepSeek 原生搜索。2026-10-02 用户指定 Perplexity 的 Sonar Pro Search 为默认,DeepSeek 改作备选。2026-10-18 DeepSeek 开放官方接口,备选换成官方 Search,另接 Fetch 读网页。
Sonar Pro Search
接口从哪来
- 模型是用户指定的,页面是 openrouter.ai/perplexity/sonar-pro-search3。它就是 OpenRouter 上的普通 chat 模型,用
/api/v1/chat/completions,没有特殊端点。 - 元数据从中转的
GET /api/v1/models/perplexity/sonar-pro-search/endpoints查:- 模型说明写的是「只在 OpenRouter API 上提供」的 Pro Search 模式,Perplexity 最强的 agentic 搜索。
- 上下文 200k,最多输出 8000 token。
- 输入每百万 token 3 美元,输出 15 美元,另有一项
web_search0.018。 - 支持
web_search_options、structured_outputs、reasoning。 - 上游延迟近 30 分钟 p50 是 8.1 秒,p90 是 19 秒,p99 是 29 秒。
- OpenRouter 上 Perplexity 还有
sonar、sonar-pro、sonar-reasoning-pro、sonar-deep-research,web_search一项都是 0.005。 - 返回格式和
search_context_size是经 Context7 查 OpenRouter 文档仓库(openrouterteam/docs)的 web search 指南看到的:来源以url_citation注解返回;web_search_options.search_context_size决定原生搜索模型取多少上下文。
实测
2026-10-02 经海外中转实测,查询词沿用 2026-10-01 测 DeepSeek 原生搜索时的两个,直接写在用户消息里,不加前缀:
| 请求 | 耗时 | 结果 |
|---|---|---|
| 「Caddy 2.11 release notes」 | 19.8 秒 | 200,693 个输出 token,0.0281 美元;15 条来源,回答分 2.11.1 的改动、安全修复、2.11.2 三节,带 CVE 编号 |
| 「2026 国庆 高速免费 时间」 | 6.0 秒 | 200,146 个输出 token,0.0200 美元;15 条来源,第一条是新华社;回答是 10 月 1 日到 7 日,还提到中秋不免费 |
| 中文那条再跑一次 | 4.9 秒 | 0.0205 美元,回答一样 |
中文那条加 search_context_size: "low" | 7.5 秒 | 0.0163 美元,回答一样 |
中文那条加 search_context_size: "high" | 4.9 秒 | 0.0249 美元,回答一样 |
OpenAI Python SDK 3.22.1,base_url 填 …/api/v1,英文那条 | 20.6 秒 | 15 条来源,message.annotations 直接能读 |
- 回答里的角标
[n]对应annotations里的第 n 条:核对了中文那次的[1]、[5]、[13],指向的文章都对得上。 url_citation只有url、title、start_index、end_index四个字段,两个 index 都是 0。OpenRouter 文档 Responses API 的例子里注解带content摘录,这里没有。- 两次都是 15 条来源。中文那次有好几条是同一篇新浪文章带不同的追踪参数。
- 响应里
reasoning是空的,reasoning_tokens是 0;顶层没有 Perplexity 官方 API 的citations、search_results字段。 - 输入 token 只算用户消息本身,8 个。扣掉输出 token 的钱,每次搜索的费用:
low约 0.014 美元,默认约 0.018,high约 0.022。 - 响应头里有
X-Generation-Id。
DeepSeek Search 和 Fetch
接口从哪来
DeepSeek 2026-10-17 开放了官方的 Search 和 Fetch 接口1,2026-10-18 接进来:Search 换掉网络搜索里原来的备选,Fetch 单开一篇读取网页。
- 原来的备选取自 DeepSeek Harness 的
web-search-deepseek插件2:往 Anthropic 兼容端点发一次挂web_search_20250305工具的 Messages 调用,每搜一次就是一次完整的模型调用,2026-10-01 实测 4.7 秒、输入 token 两千到八千多。官方接口不过模型,0.5 秒出结果 - 两个接口都是
/v1/tools/下的普通 JSON POST,鉴权跟模型接口一样用 Bearer。中转对所有路径原样转发,Caddy 没改 - 指南说
snippet通常 100 到 200 字符、summary600 到 800 字符,实测对不上,见下面的表 - 指南还提到 DeepSeek Harness、Claude Code、Codex 调 DeepSeek API 时,服务端工具调用会用到这两个接口,2026-11-01 起按次收费。原来那条挂
web_search工具的路应该就是这个,我们已经不走
计费、限速、错误码以下面存档的指南为准。只有拿到结果才收钱:
只有返回 HTTP 200 且产生结果的请求才会计费(Search 的
results必须非空,Fetch 必须返回网页正文)。请求失败、搜索无结果或超时不计费。
实测 Fetch 取不到的页面都返回 404,照这句不收钱;没去对账单。
DeepSeek《网页搜索与抓取》指南原文(2026-10-18 抓取,HTML 转成 Markdown,只把站内链接补成绝对地址)
# 网页搜索与抓取
Search 接口和 Fetch 接口为 Agent 与 RAG 应用提供实时网页内容:
* **Search 接口**按 query 搜索网页,返回结构化结果。该接口由 DeepSeek 自研搜索引擎提供支持。
* **Fetch 接口**抓取单个网页,以 Markdown 文本返回页面内容。
两者都是原始 JSON API,使用与 DeepSeek API 相同的 Bearer 鉴权。
Base URL 为 `https://api.deepseek.com`:
| API | Endpoint |
| --- | --- |
| Search | `POST https://api.deepseek.com/v1/tools/search` |
| Fetch | `POST https://api.deepseek.com/v1/tools/fetch` |
完整的请求与响应 Schema 请参考 [Search API Reference](https://api-docs.deepseek.com/zh-cn/api/search) 和 [Fetch API Reference](https://api-docs.deepseek.com/zh-cn/api/fetch)。
---
## 鉴权
在请求头中携带 API Key 和 JSON 内容类型:
| 请求头 | 必填 | 值 |
| --- | --- | --- |
| `Authorization` | 是 | `Bearer <DeepSeek API Key>` |
| `Content-Type` | 是 | `application/json` |
---
## Search 接口
### 请求
```bash
curl https://api.deepseek.com/v1/tools/search \
-H "Authorization: Bearer <DeepSeek API Key>" \
-H "Content-Type: application/json" \
-d '{
"query": "DeepSeek V4 模型 发布",
"count": 5,
"need_content": true
}'
```
```python
import requests
response = requests.post(
"https://api.deepseek.com/v1/tools/search",
headers={
"Authorization": "Bearer <DeepSeek API Key>",
},
json={
"query": "DeepSeek V4 模型 发布",
"count": 5,
"need_content": True,
},
)
response.raise_for_status()
for result in response.json()["results"]:
print(result["title"], result["url"])
print(result["summary"])
```
请求字段:
| 字段 | 类型 | 必填 | 默认值 | 说明 |
| --- | --- | --- | --- | --- |
| `query` | string | 是 | - | 搜索词,1~128 个 Unicode 字符,不能全为空白,支持下方列出的搜索语法。 |
| `count` | integer | 否 | `10` | 返回条数,1~50。 |
| `ori_question` | string | 否 | - | 触发搜索的用户原始问题,1~128 个字符,有助于更好地理解搜索意图,传 `null` 视为未提供。 |
| `localization` | string | 否 | `""` | 用于优先返回本地化搜索结果的 IP 地址。 |
| `need_content` | boolean | 否 | `false` | 是否在 `content` 中返回网页正文,为 `false` 时 `content` 恒为空字符串。 |
请求体中的未知字段会被忽略。
### 搜索语法
`query` 中的搜索语法会原样传递给搜索服务。下表中的示例将操作符与搜索词组合使用;你可以在一个 query 中组合多个操作符。
| 操作符 | 示例 | 说明 |
| --- | --- | --- |
| `site:` | `DeepSeek site:github.com` | 将结果限制在指定站点,指定多个时用空格分隔并通过 `OR` 连接,例如 `DeepSeek site:github.com OR site:huggingface.co`。 |
| `-site:` | `DeepSeek -site:example.com` | 排除指定站点,指定多个时用空格分隔。 |
| `-` | `DeepSeek -广告` | 排除包含指定关键词的网页,指定多个时用空格分隔。 |
| `-"..."` | `DeepSeek -"release notes"` | 排除包含指定短语的网页,短语内可以包含空格,指定多个时用空格分隔。 |
| `"..."` | `DeepSeek "精确短语"` | 精确匹配指定短语,指定多个时用空格分隔。 |
| `lang:` | `DeepSeek lang:zh,en` | 将结果限制在指定语言,多种语言用逗号分隔,例如 `lang:zh,en`。 |
| `after:` | `DeepSeek after:2025` 或 `DeepSeek after:2025-01-01` | 将结果限制在指定日期之后发布的网页。 |
| `before:` | `DeepSeek before:2026` 或 `DeepSeek before:2026-06-01` | 将结果限制在指定日期之前发布的网页。 |
例如:
```json
{
"query": "DeepSeek 模型 site:github.com OR site:huggingface.co lang:zh after:2025",
"count": 10
}
```
### 响应
请求成功时返回 HTTP 200 与 `results` 数组。搜索正常结束但没有匹配结果时,返回空数组。
```json
{
"results": [
{
"rerank_score": 2.4,
"title": "DeepSeek V4 模型发布",
"url": "https://example.com/deepseek-v4",
"snippet": "DeepSeek V4 已上线,支持工具调用与长上下文。",
"summary": "DeepSeek 发布了 V4 模型。此次发布改进了工具调用与长上下文能力,适合 Agent 工作流。",
"content": "DeepSeek V4 现已正式上线……",
"site_name": "Example News",
"site_icon": "https://example.com/favicon.ico",
"date": "2026-06-01T00:00:00+00:00",
"authority": 3
}
]
}
```
`results` 中每一项包含以下字段:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `rerank_score` | number | 排序分数,0~3 分,综合考虑相关性、权威性、时效性等维度,大于等于 1.5 分为优质结果。 |
| `title` | string | 标题。 |
| `url` | string | 结果链接。 |
| `snippet` | string | 短摘要,与 query 相关,通常为 100~200 字符,适用于前端展现。 |
| `summary` | string | 长摘要,与 query 相关,通常为 600~800 字符,适用于给模型阅读。 |
| `content` | string | 网页正文,`need_content` 为 `false` 或正文缺失时为空字符串。 |
| `site_name` | string 或 null | 站点名称,缺失时为 `null`。 |
| `site_icon` | string 或 null | 站点图标 URL,缺失时为 `null`。 |
| `date` | string 或 null | 发布时间,统一为 UTC 的 RFC 3339 格式,未知时为 `null`。 |
| `authority` | integer | 网页权威性,0~4(`-1` 表示未知),大于等于 3 为极权威结果。 |
---
## Fetch 接口
### 请求
```bash
curl https://api.deepseek.com/v1/tools/fetch \
-H "Authorization: Bearer <DeepSeek API Key>" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/article"
}'
```
```python
import requests
response = requests.post(
"https://api.deepseek.com/v1/tools/fetch",
headers={
"Authorization": "Bearer <DeepSeek API Key>",
},
json={"url": "https://example.com/article"},
)
response.raise_for_status()
page = response.json()
print(page["title"])
print(page["content"])
```
请求字段:
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `url` | string | 是 | 要抓取的网页地址,长度不超过 8192,必须为含 host 的 HTTP/HTTPS URL,且不能携带用户名或密码。 |
### 响应
```json
{
"title": "Example article",
"content": "# Example article\n\nArticle content."
}
```
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `title` | string | 页面标题,缺失时为空字符串。 |
| `content` | string | 抓取后的 Markdown 正文。 |
Fetch 的结果受目标站点的可用性和访问策略影响。
---
## 错误
错误响应使用 OpenAI 兼容的错误格式,`param` 字段恒为 `null`。
```json
{
"error": {
"message": "'count' must be between 1 and 50",
"type": "invalid_request_error",
"param": null,
"code": "invalid_request_error"
}
}
```
| HTTP 状态码 | 说明 |
| --- | --- |
| 400 | 请求头或请求体不合法,包括 JSON 格式错误或字段值无效。 |
| 401 | API Key 缺失或无效。 |
| 402 | 账号余额不足。 |
| 403 | Fetch 请求被安全策略拒绝。 |
| 404 | Fetch 未能获取可用的网页内容,例如 URL 不可用、被站点策略拦截、目标站点返回错误、内容类型不受支持或页面没有可提取的 Markdown 正文。 |
| 408 | 读取请求体超时。 |
| 413 | 请求体超过大小限制。 |
| 429 | 超过 Search 或 Fetch 的 QPS 限制。 |
| 500 | 服务器内部错误。 |
| 504 | 下游请求超时。 |
Search 和 Fetch 都是只读请求。遇到 HTTP 408、429 或 5xx 错误时,请等待后重试。遇到 HTTP 402 时,请先充值再重试。对于其它 4xx 错误,如不修改请求,请勿重试。
---
## 计费
Search 和 Fetch 按请求次数计费,不按 token 或返回结果条数计费:
| API | 计费单位 | 价格 |
| --- | --- | --- |
| Search | 每 1,000 次成功请求 | 5元 |
| Fetch | 每 1,000 次成功请求 | 5元 |
只有返回 HTTP 200 且产生结果的请求才会计费(Search 的 `results` 必须非空,Fetch 必须返回网页正文)。请求失败、搜索无结果或超时不计费。`count` 只控制返回的结果条数,不影响单次请求的价格。
请注意,当前用户在 DeepSeek Harness/Claude Code/Codex 中使用 DeepSeek API 时,已经会通过 Server 端工具调用访问到 Search/Fetch 接口,这部分 Search/Fetch 接口调用目前未计费,并将于北京时间 2026 年 11 月 1 日 00:00 起按次收取调用费用。
---
## 限速
对每个账号,Search 和 Fetch 分别独立限速,互不占用额度:
| API | QPS 限制 |
| --- | --- |
| Search | 5 |
| Fetch | 5 |
QPS(每秒请求数)限制按账号粒度计算,与使用哪个 API Key 无关,并与模型并发限制相互独立。超过账号级 QPS 限制的请求会收到 HTTP 429 错误码。除了账号级限制,Fetch 还针对目标域名有 QPS 限制,超过该限制也会收到 HTTP 429 错误码。
实测
2026-10-18 经国内中转实测,前两个查询沿用 Sonar 那次的:
| 请求 | 耗时 | 结果 |
|---|---|---|
| Search「Caddy 2.11 release notes」 | 0.70 秒 | 10 条,rerank_score 1.93 到 2.15,authority 都是 3;summary 1043 到 3813 字符,有一条 snippet 3137 字符 |
| Search「2026 国庆 高速免费 时间」 | 0.50 秒 | 10 条,前两条是光明网同一篇,一条 URL 带 #1;summary 96 到 714 字;第一条答案对:10 月 1 日 0 时到 7 日 24 时 |
中文那条加 count: 5、need_content: true | 0.50 秒 | content 406 到 2450 字 |
| Search「caddy release site:github.com after:2026-01-01」 | 0.54 秒 | 5 条全是 github.com,日期都在 2026 年 |
Search「高速免费」count: 3,加和不加 ori_question | 0.57 秒 | 两次返回的 3 条一模一样 |
| Search「国庆 高速免费 site:mp.weixin.qq.com」 | 0.39 秒 | 0 条;另一个查询要 20 条,也没有一条公众号 |
Search query 全是空格 | 0.22 秒 | 400,'query' must not be empty |
| Fetch 光明网新闻 | 6.3 秒 | 2049 字,正文全,末尾混进一行统计代码 |
| 同一个 URL 再取 | 0.25 秒 | 有缓存 |
| Fetch GitHub 的 release 页 | 10.9 秒 | 4131 字符,开头带「Skip to content」和导航菜单的标题 |
| Fetch uv 文档的 Running scripts | 8.1 秒 | 6329 字符,链接 0 个,代码块大多整块丢掉,行内代码前后的空格被吃掉 |
| Fetch DeepSeek 这篇指南 | 0.26 秒 | 6402 字,表格和代码块都压成了纯文本;这么快大概是别人取过 |
| Fetch 知乎问题页、arXiv 的 PDF | 0.2 到 0.3 秒 | 404,not_found_error |
| Fetch 不存在的页面 | 3.8 秒 | 404,not_found_error |
- Search 的 URL 片段不止
#1,还见过#2、#none、#comment#1。标题常常重复成「标题 - 标题」 date几乎都是T16:00:00+00:00,即北京时间零点,只有日期精度- Fetch 的
content标点全带反斜杠转义,去掉之后是普通 Markdown
没做的
- Sonar 和 DeepSeek Search 没拿同一批问题比过准确率。
- Sonar 的
web_search_options里只试了search_context_size,别的选项(比如限定域名、地区)没试。sonar、sonar-pro这些更便宜的 Perplexity 模型没试。 - 海外机的 SSH 公钥还没装回去,OpenRouter 的中转配置没同步进
assets/gateway/。 - DeepSeek Search 的
localization没试。 - Fetch 没拿真实的公众号文章试,也没试要跑 JS 才出内容的页面。
- 两个接口的 429 没撞到过,限速只照指南写。
-
DeepSeek 网页搜索与抓取指南,以及 Search、Fetch 的 API Reference,2026-10-18 读。 ↩
-
deepseek-harness
web-search-deepseek插件,钉639ed01(0.2.0-rc.2),2026-10-01 读。 ↩ -
openrouter.ai/perplexity/sonar-pro-search,2026-10-02 读。 ↩