Blog/开发者工具/

知乎公开数据 API | SandBase

用一个 REST API 读取知乎公开的问题、回答、文章、热榜和用户资料。无需知乎登录,无需 SDK,一把 SandBase key,为 agent 而建。

深色电影质感画面:知乎问题、回答和资料数据经由单一 API 通道汇入 agent 核心

知乎是中国最大的问答和知识社区——长篇回答、专家专栏、一个追踪全国在讨论什么的热榜,还有充满领域信号的用户资料。这直接对应到知识挖掘、趋势调研和专家发现。但想用程序拿到这些数据,通常得逆向网站、管理 cookie,还要在标记每次变动时重建爬虫。

SandBase 的知乎公开数据 API 把这层搭建成本去掉了。它通过普通 REST 端点读取知乎公开的问题、回答、文章、热榜、搜索和用户资料——一把 SandBase API key,不用知乎登录,也不用 SDK。端点参考保证的是响应信封(id、status、model,以及 outputs[0].data);下面出现的业务字段是示例结构,不是保证的 schema,请以一份真实响应为准核对。

这不是知乎的官方开放平台。 如果你需要已认证的成员操作或一份授权的数据协议,请用知乎官方渠道;当你的流程需要的是公开、只读的数据(调研、监测)时,用 SandBase。想直接试?领取 SandBase API key,再浏览知乎端点。

先说结论

  • 一个 API 读取知乎公开的问题、回答、文章、热榜、搜索和资料。
  • 本文的 Model API 端点用 POST /v1/api/zhihu/<path> 调用——只传该端点的参数,不用 SDK,一把 SANDBASE_API_KEY。
  • 端点以自然标识为入参:内容用 question_id/answer_id/article_id,人用 user_url_token,搜索用 keyword。
  • 它只返回公开、只读数据。不能发帖、你这边不用登录、也拿不到私密数据;鉴权用 SandBase API key。

你到底需要哪个知乎 API?

你的需求选择原因
发帖、以成员身份操作,或用账号授权数据知乎官方渠道成员和账号操作走知乎官方。
读取公开的问题、回答、文章或资料SandBase 知乎公开数据 API普通 REST、一把 SandBase key、面向只读流程的结构化 JSON。
私密或仅账号可见的数据都不适用于公开流程这类数据不在本篇公开数据的范围内。

从知乎 API 能拿到什么

整个目录建立在一个 web 面上。按用途归类:

  • 热榜与发现 —— 热榜、热门推荐,以及搜索联想。
  • 搜索 —— 按关键词搜文章、问题、视频、专栏和用户。
  • 问答 —— 问题详情、它的回答,以及回答详情。
  • 文章与专栏 —— 专栏文章详情、某专栏的文章,以及评论。
  • 用户 —— 按 user_url_token 读公开资料、回答、文章和想法。

动手前请查每个端点的在线 API 参考确认参数;可用性因端点而异。

SandBase 知乎 API 页面:描述、能力标签和端点列表 SandBase 上的知乎 API 页面——带标签的概览,加上端点列表,每个端点标有路径。

知乎提供的 vs. SandBase 补上的

公开数据来自知乎。SandBase 并不拥有或运营知乎,它只是为符合条件的公开数据流程提供一个统一的 API 层。每一项能力变成一个稳定端点,鉴权收敛成一把 key,响应都是可预期的 JSON——于是 agent 可以沿着同一套约定串起”读热榜 → 打开一个问题 → 给回答者建档”,而不用再维护一个爬虫。

快速上手:第一次调用

SandBase 有不止一个 API 面。目录里可能会展示 /apis/v1/... 下的 GET 路径;本文用的是每个端点 API 参考里带厂商前缀的 Model API 路径。不要替换 HTTP 方法或 URL——按你所选端点的参考文档来。

读取热榜:

import os
import requests

resp = requests.post(
    "https://api.sandbase.ai/v1/api/zhihu/web/hot-list",
    headers={
        "Authorization": f"Bearer {os.environ['SANDBASE_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={},
)
resp.raise_for_status()
body = resp.json()
if body.get("status") != "completed":
    error = body.get("error", {})
    raise RuntimeError(error.get("message", "Zhihu request did not complete"))

# 只有信封(id/status/model/outputs[0].data)是保证的;下面嵌套的
# 业务字段是示例结构,所以用 .get() 做防御式读取。
outputs = body.get("outputs") or [{}]
data = outputs[0].get("data", {})
for item in data.get("data", [])[:5]:
    target = item.get("target", {})
    print(target.get("title"), item.get("detail_text"))
curl -X POST https://api.sandbase.ai/v1/api/zhihu/web/hot-list \
  -H "Authorization: Bearer $SANDBASE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

每个响应都用同一个信封:一个 id、一个 status、model 名称,以及一个 outputs 数组,其中唯一一项在 data 下携带载荷。这个信封正是端点参考所保证的部分。读 outputs[0].data 之前先判 status,并查每个端点的参考了解它的运行模式。知乎的列表端点常把条目嵌在一个 data 数组里,而每条热榜项把问题包在一个 target 对象下。下面是一段示例响应结构——其中嵌套的业务字段是示例结构、不是保证的 schema,请把字段名和数值当作示例,以一份真实响应为准核对(载荷会变、数值也会随时间变):

{
  "id": "0437c98c-2fc0-4b23-9e40-c986f4512883",
  "status": "completed",
  "model": "zhihu/web/hot-list",
  "outputs": [
    {
      "data": {
        "data": [
          {
            "detail_text": "…",
            "target": { "title": "…", "answer_count": 560, "follower_count": 1701 }
          }
        ]
      }
    }
  ]
}

failed 或 timeout 的请求会带上 error 而没有 outputs。不同端点的响应结构不一样——先看一份真实响应,再按端点逐一对准字段路径。

SandBase 上某个知乎端点的 API 参考,展示带厂商前缀的 URL 和响应 schema 端点的 API 参考是每个参数名和响应路径的权威来源。

能力地图

能力簇代表端点典型用途
热榜zhihu/web/hot-list热门问题监测
文章搜索zhihu/web/article-search-v3关键词内容发现
问题详情zhihu/web/question-detail按 question_id 读问题
问题回答zhihu/web/question-answers拉取某问题下的回答
用户资料zhihu/web/user-info按 user_url_token 的公开专家信号

分页方式因端点而异——若干端点接受一个偏移或数量类的请求参数。具体看每个端点的 schema。

SandBase 知乎端点列表,展示热榜、搜索、问题和用户端点及其路径 知乎端点列表的一部分,在 web 面上。

在 agent 工作流里串联调用

因为每个端点共用同一套鉴权和同一个响应信封,agent 可以从一个热门问题走到它的专家回答者,而不用为每个页面单独写特例。一个常见的知识调研模式是这样:

  1. 读热榜。 调 zhihu/web/hot-list 拿热门问题,每一项带一个标题和一个热度数字。
  2. 打开问题。 用 question_id 调 zhihu/web/question-detail,再调 zhihu/web/question-answers 拉回答。
  3. 给专家建档。 用 user_url_token 调 zhihu/web/user-info,附上像昵称、粉丝数和回答数这样的账号上下文。

每一步都返回同样的 { id, status, model, outputs } 结构,所以你的 agent 只需判一次 status,读 JSON 的那段代码在每一步都能复用。

常见用例

用知乎热榜 API 做趋势监测

按计划定时轮询 zhihu/web/hot-list 追踪热门问题——每一项带一个问题标题和一个热度数字。输入:无。输出:排名的热门问题列表。端点:hot-list。完整工作流看如何挖掘知乎问答。

用知乎搜索 API 做内容发现

用一个关键词调 zhihu/web/article-search-v3,围绕某话题摸清文章。输入:关键词。输出:匹配文章。端点:article-search-v3。

用知乎资料 API 做专家发现

用 zhihu/web/user-info 读取公开资料,拿到像昵称、粉丝数和回答数这样的字段。输入:user_url_token。输出:结构化的资料记录。端点:user-info。完整工作流看如何做知乎专家发现。

为什么在 API 层做这件事

你当然可以让无头浏览器去抓知乎、解析 HTML,但那条路很脆:标记会变,你维护的是一堆选择器而不是在做功能。通过一个统一 API 读取,意味着你的代码依赖命名的 JSON 字段和一个统一的响应信封,而不是页面布局。鉴权是一把 key 而不是轮换 cookie;而且因为每个端点都返回同样的 { id, status, model, outputs } 结构,重试、日志和错误处理都集中在一个你写一次、到处复用的帮助函数里。

这种一致性正是让工作流对 agent 可组合的原因。把一个热榜问题换成另一个、把一个 user_url_token 换成另一个,代码路径完全一样。再加第四次读取——比如某条回答的详情——它就接在同一个判状态的帮助函数后面。实际的回报是:你把时间花在数据对你的调研意味着什么上,而不是花在跟一个不断变化的目标较劲、维持爬虫存活上。当你需要的不止单次读取时,查线上列表找到合适的端点,接入前先确认它的参数。

边界与限制

  • 只读、公开数据。 不能发帖、关注,也拿不到私密/仅账号可见的数据。
  • 速率与量级。 把响应当作尽力而为的读取;作为客户端韧性措施,遇到 HTTP 429 这类瞬时错误时用退避重试。
  • 参数与结构随上游而定。 标识各异(question_id/answer_id/article_id、user_url_token、keyword);列表载荷常嵌在一个 data 数组下;分页是各端点自己的请求参数。先看真实响应、读 schema。
  • 对照在线参考确认端点。 可用性和字段可能变化;在依赖某个具体端点之前先确认。
  • 这不是知乎官方合作。 SandBase 只是提供对公开数据的统一访问;请遵守知乎的条款以及你使用场景下适用的规则。

常见问题

我需要知乎开发者应用或登录吗? 不需要。你用 SANDBASE_API_KEY 向 SandBase 鉴权。这些读取端点不需要知乎账号或你这边的 OAuth。

用什么来标识问题、回答或用户? 用自然标识:内容用 question_id、answer_id 或 article_id,人用 user_url_token。搜索用 keyword。

分页怎么做? 取决于端点——若干端点接受一个偏移或数量请求参数。具体看每个端点的 schema。

能读私密或仅账号可见的数据吗? 不能。这个 API 只返回公开数据。私密和账号授权的内容都不在范围内。

从热榜开始

创建一把 SandBase API key,调 hot-list,先看清返回的 schema,再扩展到搜索、问题或资料。准备好之后: