欢迎访问 AI Skills Video ! 海量优质视频教程,助你提升技能。

DeepSeek 推出 Search API:接口替代多套联网检索服务

老张 2026年10月19日 2 次阅读
DeepSeek 2026/10/18 推出Search/Fetch API 两个接口给 Agent 提供实时网页内容:Search 返回带重排分与权威度的结构化结果,Fetch 把网页转成 Markdown。本文给出请求字段、搜索语法、限流与计费口径,并用一份 Python 脚本跑通。

上周给一期视频脚本核实「DeepSeek 搜索接口怎么计费」时,模型凭记忆只能给出一个含糊区间——这类问题,正是联网检索要解决的。

DeepSeek 在 2026 年 10 月 17 日上线的 Search / Fetch 两个接口,把联网 RAG 里的「检索」和「正文抽取」两段收进了同一套 Bearer 鉴权:Search 按 query 返回带 rerank_score 与 authority 的结构化结果,Fetch 把任意 http/https 页面转成 Markdown。 也就是说,你不必再分别维护搜索服务、正文解析器、重排接口三套 SDK 与三套错误码。

下面覆盖:Search 与 Fetch 的请求字段、搜索语法、返回结构、错误码与计费口径,四步 Python 实现,以及它覆盖不到的场景——全部基于 DeepSeek 官方 Search & Fetch 指南 与 2026-10-17 的 API 变更日志,价格与限速以官方文档为准。这是我们 AI-Skills.video 做选题调研时最先接进来的外部能力。

先划边界:它只管「公开网页」这一路,私有文档、登录态页面、付费墙内容都不在其中,这部分仍要自建索引或走知识库方案。

一、这套接口省了什么:联网 RAG 从「五段自建」变成「两段调用」

结论先说:传统 RAG 与联网检索的差别不在模型,而在索引由谁维护。

离线 RAG 里,你要自己把文档灌进向量库、调 embedding、跑 TopK、再挂一个 rerank;联网检索里,索引和重排都在服务端。对照如下:

环节 自建离线 RAG DeepSeek Search / Fetch
索引来源 你自己灌入的文档与切块 自研搜索引擎的网页索引
召回方式 向量相似度 + TopK query 语法 + 服务端重排评分
重排 rerank 自建 cross-encoder 或调第三方 直接返回 rerank_score(0~3)
正文清洗 自写解析器、去样板、去导航 Fetch 直接返回 Markdown
数据新鲜度 看你何时重灌 实时网页

据官方变更日志,这套检索由 DeepSeek 自研搜索引擎承担,日志称其每天处理全球数亿次搜索请求、索引数千亿网页,并针对 SEO 垃圾与低质 AIGC 做了过滤。对使用者的实际意义是:你拿到的每条结果都自带重排分和权威度,不必再从零搭一套清洗 + 打分流水线。

省掉的「多套 API」具体是三样东西:

  1. 鉴权与配额:同一把 Key、同一个 Base URL(api.deepseek.com),与模型调用共用。
  2. 计费口径:搜索与抓取都是每 1000 次成功请求 5 元,不按 token、不按条数。
  3. 错误格式:OpenAI 兼容错误体,param 恒为 null,重试逻辑可以复用。

据作者观察,多供应商方案真正贵的不是接入代码,而是四套口径漂移后的排障——同一个 429 在不同厂商代表「超频」「余额不足」「被目标站拦截」三种事。

这套接口和 Agent 侧的工具调用是同一条线上的事,配套的编排方式可以对照 AI Agent 工具调用与工作流 一起看。

二、动手前的三个前提:Key、计费口径、限流

两个接口不单独开通,和模型 API 共用一把 Key 与一个 Base URL。 前提只有三条。

Key 与鉴权:在 platform.deepseek.com 申请后,请求头带 Authorization: Bearer <Key> 与 Content-Type: application/json 即可。

计费:按请求次数计费,每 1,000 次成功请求 5 元(英文文档标注 $0.75)。关键口径是——只有 HTTP 200 且产生结果才计费:Search 的 results 必须非空,Fetch 必须返回正文;失败、空结果、超时都不计费;count 只影响返回条数,不影响单价。

项目 口径(以官方文档为准)
Search 每 1,000 次成功请求 5 元
Fetch 每 1,000 次成功请求 5 元
计费触发 200 且返回结果/正文
结果条数 不影响价格

限流与免费期:QPS 按账号粒度限制,Search 与 Fetch 独立计数,互不占用额度;Fetch 另有针对目标域名的 QPS 限制,超限一律返回 429。另外,通过 DeepSeek Harness / Claude Code / Codex 使用 DeepSeek API 时,服务端工具调用已经会打到这两个接口,这部分目前不计费,自北京时间 2026 年 11 月 1 日 00:00 起按次收费——免费期结束前对一下自己的调用量比较稳妥。

三种接入形态,按需要选一种

形态 适合谁 你要做的事
服务端工具(Harness / Claude Code / Codex) 在 IDE、CLI 里让 Agent 自己搜 无需配置,走 DeepSeek API 即生效
原始 HTTP(本文主线) 自建服务、自动化脚本 两个 POST + Bearer
社区 MCP 封装(非官方) 任意支持 MCP 的客户端 配 mcpServers 与环境变量 Key

三、Search:5 个请求字段、8 个操作符、10 个返回字段

Search 是 POST https://api.deepseek.com/v1/tools/search,全部信息都在这 5 个请求字段里。

字段 类型 必填 口径(以官方文档为准)
query string 是 1~128 字符,不能全空白,支持操作符
count integer 否 1~50,默认 10
ori_question string 否 用户原始问题,1~128 字符,助意图理解
localization string 否 IP 地址,优先返回本地化结果
need_content boolean 否 默认 false,false 时 content 为空串

搜索语法原样透传给搜索服务,8 个操作符可在一个 query 里组合:

操作符 示例 作用
site: site:github.com 限定站点,多个用 OR 连接
-site: -site:example.com 排除指定站点
- -广告 排除含该词的页面
-"" -"release notes" 排除含该短语的页面
"" "精确短语" 精确匹配短语
lang: lang:zh,en 限定语言,逗号分隔
after: after:2025-01-01 限定发布日期之后
before: before:2026-06-01 限定发布日期之前

返回是一个 results 数组(无匹配时为空数组),每条结果 10 个字段:

字段 说明
rerank_score 0~3,≥1.5 为优质结果
title / url 标题与链接
snippet 100~200 字符,适合前端展示
summary 600~800 字符,适合给模型读
content 正文,need_content=false 时为空串
site_name / site_icon 站点名与图标,缺失为 null
date UTC RFC 3339,未知为 null
authority 0~4,≥3 为极权威,-1 表未知

一条结果的形态大致是这样(简化示意,字段取值来自官方文档示例):

{
  "results": [
    {
      "rerank_score": 2.4,
      "title": "DeepSeek V4 model released",
      "url": "https://example.com/deepseek-v4",
      "snippet": "DeepSeek V4 is now available...",
      "summary": "DeepSeek has released the V4 model...",
      "content": "",
      "site_name": "Example News",
      "site_icon": "https://example.com/favicon.ico",
      "date": "2026-06-01T00:00:00+00:00",
      "authority": 3
    }
  ]
}

一个能省一半调用的取舍:summary 已是 600~800 字符的长摘要,概览型问答只靠它就够;只有当你要引用原文细节、核对具体数字与版本号时,才值得再对精选链接调一次 Fetch。字段全貌可查 Search API Reference。

四、Fetch:1 个字段、2 个返回项,和三类抓不到的情况

Fetch 是 POST https://api.deepseek.com/v1/tools/fetch,请求体只有一个 url。 要求是 HTTP/HTTPS、含 host、不带用户名密码、长度不超过 8192 字符;返回两项——title 与 content(Markdown 正文)。

它的价值在于把「网页 → 干净文本」这一段黑箱化:不用自己写正文抽取、不用处理导航与广告样板、不用关心页面里是 <article> 还是 <div>。

但它有三类情况会抓不到,都属于正常返回而非接口故障:

  1. 站点侧拒绝或页面不存在:URL 不可用、被站点策略拦截、目标站点返回错误,归入 403/404 一类。
  2. 内容类型不受支持或无正文可提取:返回 404,content 自然也没有。
  3. 按域名 QPS 超限:返回 429,等一会儿重试。

因此正确用法是「少量精选 + 兜底」:先搜再抓,每轮只抓 2~3 篇最相关的结果,抓不到就退回该条的 summary,不要让抓取成为链路的单点。抓下来的 Markdown 想直接塞进客户端工具,可以照着 把网页抓取封装成 MCP 工具 的思路包一层。

五、实操:四步搭出 search → 筛选 → fetch → 回答

环境是 Python 3.9+,依赖只有 requests。下面四段代码按第一步到第四步的顺序拼进同一个 rag.py,在文件末尾加一行 print(answer("你的问题")[0]) 即可运行,不要单独执行某一段。

第一步:申请 Key 并跑通最小 Search 请求

这一段只做一件事:确认 Key 有效、能拿到 results 数组。

# rag.py 顶部 · 依赖 requests(pip install requests),Python 3.9+
import os
import requests
from urllib.parse import urlsplit

API_KEY = os.environ["DEEPSEEK_API_KEY"]   # 在 platform.deepseek.com 申请
BASE = "https://api.deepseek.com/v1/tools"
HEADERS = {"Authorization": f"Bearer {API_KEY}",
           "Content-Type": "application/json"}

def search(query, count=5):
    """返回 results 列表;无匹配时是空数组,不是异常。"""
    resp = requests.post(f"{BASE}/search", headers=HEADERS,
                         json={"query": query, "count": count}, timeout=20)
    resp.raise_for_status()      # 400/401/402/429 在这里抛出
    return resp.json()["results"]

# 试跑:print([(r["rerank_score"], r["title"]) for r in search("DeepSeek 搜索 API 计费", 3)])

第二步:用 rerank_score 与 authority 筛掉噪音

筛选口径直接对齐官方阈值:rerank_score ≥ 1.5 为优质,authority ≥ 3 为极权威。 顺手按站点去重,避免前三条全来自同一家转载站。

def pick(results, min_score=1.5, min_authority=2, limit=3):
    kept, seen = [], set()
    for r in sorted(results,
                    key=lambda x: (x["rerank_score"], x["authority"]),
                    reverse=True):
        if r["rerank_score"] < min_score or r["authority"] < min_authority:
            continue                      # authority 为 -1(未知)时自然被排除
        host = urlsplit(r["url"]).netloc  # 同一站点只留一条
        if host in seen:
            continue
        seen.add(host)
        kept.append(r)
        if len(kept) == limit:
            break
    return kept

第三步:对入选链接调 Fetch 拿 Markdown 正文

这一步要处理的就是 429 与超时:408/429/5xx 退避重试,其它 4xx 不改请求不重试。 同时按字符截断,控制后续上下文长度。

import time

def fetch_md(url, max_chars=12000, retries=3):
    """返回 dict;失败时 error 非空,由调用方决定是否用摘要兜底。"""
    for i in range(retries):
        resp = requests.post(f"{BASE}/fetch", headers=HEADERS,
                             json={"url": url}, timeout=30)
        if resp.status_code == 200:
            page = resp.json()
            return {"title": page["title"],
                    "content": page["content"][:max_chars],
                    "error": None}
        if resp.status_code in (408, 429) or resp.status_code >= 500:
            time.sleep(2 ** i)            # 1s → 2s → 4s
            continue
        return {"title": "", "content": "", "error": resp.status_code}
    return {"title": "", "content": "", "error": "retry_exhausted"}

第四步:把片段拼进 Prompt 并调模型回答

拼装时给每条资料编号,并用 system 指令要求「无法回答就说不知道」,否则模型很容易把相邻页面的信息混成一条。

def answer(question, top_k=3):
    hits = pick(search(question, count=10), limit=top_k)
    if not hits:                               # 幂等兜底:空结果不进模型
        return "没有检索到可用结果", []
    ctx, srcs = [], []
    for h in hits:
        page = fetch_md(h["url"])
        idx = len(srcs) + 1
        if page["error"]:                      # 抓不到就退回长摘要
            ctx.append(f"[{idx}] {h['title']}\n{h['summary']}")
        else:
            ctx.append(f"[{idx}] {page['title']}\n{page['content']}")
        srcs.append(h["url"])
    prompt = ("只依据下面的资料回答,无法回答就说不知道,"
              "并在句末用 [n] 标注来源。\n\n" + "\n\n".join(ctx))
    resp = requests.post("https://api.deepseek.com/chat/completions",
                         headers=HEADERS,
                         json={"model": "deepseek-flash",   # 模型名以官方文档为准
                               "messages": [{"role": "system", "content": prompt},
                                            {"role": "user", "content": question}]},
                         timeout=120)
    resp.raise_for_status()
    return resp.json()["choices"][0]["message"]["content"], srcs

这条链路的完整流程,速查如下:

步骤 关键动作 关键字段与参数
1 POST /v1/tools/search query、count
2 按分数筛选去重 rerank_score≥1.5、authority≥2
3 POST /v1/tools/fetch url、正文截断 12000 字符
4 拼 Prompt 调模型 来源编号 + 拒答指令

脚本的完整版(含并发队列、429 退避与日志)我们整理成了 联网 RAG Agent 模板与脚本骨架,改 query 和截断长度就能接到自己的项目里。

六、坑与局限:429、404 和它真没覆盖的部分

这段是在 AI-Skills.video 的自动化选题流程里踩出来的,按坑的严重程度排。

同一个 QPS 数字,文档出现过两个版本

我们检索时,官方文档的中文页与英文页对 QPS 的记载并不一致:一处是 Search 与 Fetch 各 5 QPS,另一处是 Search 100 / Fetch 25。这说明限速在调整中,接入时不要把它写死进业务假设——按最保守的一档设计队列,遇到 429 就指数退避,并回读一次当前文档。账号级限速与模型并发限制相互独立,不要用模型侧的并发经验反推它。

404 不等于接口坏了

Fetch 的 404 涵盖「URL 不可用、被站点策略拦截、目标站点报错、内容类型不受支持、页面没有可提取正文」五种成因。所以别把 404 当异常监控的 P1 报警,它更接近「这条链接没价值」。真正要报警的是 401(Key 失效)、402(余额不足)与大面积 429。

计费只在「成功」时发生,但成功不等于「有用」

成功口径是「200 且检索出结果」,空结果不计费——这对手气不好时挺友好,但也意味着**「计费次数」不等于「有效资料数」**。做预算时按「成功请求数」算,做效果评估时按 rerank_score ≥1.5 的条数算,两个指标别混。

它不管的那部分:私有文档、登录态与非 HTML 内容

这套接口不做你私有文档的索引,也不处理需要登录态的页面;url 还明确禁止带用户名密码。换句话说,它替代的是「公开网页检索 + 正文抽取」,不是「企业知识库 RAG」。 需要私有资料时,仍要回到自建切块与召回的那条路。

抓取合规:两句话

Fetch 的结果受目标站点可用性与访问策略影响,抓取前先确认目标站的 robots 与授权条款;对受版权保护的正文,缓存范围与二次分发要自己收窄。

七、成本与选型:什么时候换、什么时候别换

先算一笔账(示例口径,非实测账单):一个内容团队每天 200 次 Search 做选题调研、100 次 Fetch 做正文核实,30 天共 9,000 次成功请求,按每 1,000 次 5 元估算约 45 元/月;把 count 从 5 调到 20,费用不变。实际扣费以账单为准。

场景 建议 理由
公开网页的实时事实核查 Search + Fetch 无需自建索引
纯概览型问答 只调 Search,need_content=false summary 已有 600~800 字符
私有文档问答 自建知识库 RAG 它检索不到你的文件
高频批量抓取 队列 + 退避,或降级多供应商 账号级 QPS 是硬约束
需要精细正文清洗 Fetch + 自建后处理 Markdown 仍需二次加工

判断标准可以压成一句:如果「资料在公开网页上、且你要的是实时性」,就值得换;如果「资料在你自己的库里、且你要的是稳定语料」,就别换。 需要私有知识库那条路时,切块与召回参数可以照 Dify 知识库 RAG 的切块与召回配置 调。

放到具体工作流里,我们用它的位置很固定:视频选题阶段用 Search 扫一轮行业动态与官方公告,写作前用 Fetch 抓 2~3 篇一手页面核对版本号与价格——这两件事以前要分别接一套搜索 API 和一套正文解析服务,现在是一条 Key 加两个 POST。

总结

  • 要实时公开网页 → 用 Search 的 summary 就够,先别急着抓正文。
  • 要引用原文细节 → 只对 rerank_score≥1.5 的 2~3 篇调 Fetch。
  • 要私有文档问答 → 这套接口帮不上,仍走自建知识库切块与召回。
  • 要控成本 → 每 1,000 次成功请求 5 元,空结果与失败不计费。
  • 要稳 → 按最保守的账号级 QPS 设计队列,429 指数退避,别写死限速。

它替代的不是 RAG,而是「检索 + 清洗」那两段最脏的维护工作。