西瓜视频研究 API 教程
搭一套西瓜视频研究工作流:搜关键词、读视频详情、拉评论——一个 SandBase 密钥,无需西瓜视频登录、无需 SDK。

在西瓜视频上做视频研究,归根到底是三个动作:搜一个话题、打开一条重要的视频、读大家对它的评论。这篇教程用 SandBase 西瓜视频 API 把这些动作串成一套工作流——搜关键词、读视频详情、拉它的评论。一个 SandBase 密钥,不需要登录西瓜视频,也不需要 SDK。
完整的端点全景见 西瓜视频公开数据 API 总览。这一篇是落地的研究工作流。
关于 API 面的说明:SandBase 目录里可能把这些能力列成 GET /apis/v1/xigua/... 路径,但本教程使用每个端点 API 参考上标注的 SandBase Model API POST /v1/api/xigua/... 路由。方法、URL 和请求 body 以参考为准。参考只保证响应信封;下面的业务字段(err_code、results、offset 等)是我抓取里观测到的、仅供观测——并非文档保证——请以真实响应为准核对。
先说结论
- 三步:
search-video(发现)→one-video-v2(详情)→video-comment-list(互动)。- 每次都是
POST /v1/api/xigua/<path>,一个SANDBASE_API_KEY;completed 运行带outputs,failed/timeout 运行带error。- 在我的抓取里,上游负载报告了一个
err_code(0 表示成功)——这是一个参考并不保证的业务字段;搜索接keyword,视频读取接item_id。- 仅公开、只读数据;你这边不用登录西瓜视频,但仍需要一个 SandBase API 密钥。
工作流全貌
| 步骤 | 端点 | 输入 | 你拿到 |
|---|---|---|---|
| 1. 发现 | xigua/app-v2/search-video | keyword | 排名结果 + offset/has_more |
| 2. 详情 | xigua/app-v2/one-video-v2 | item_id | 单条视频的详情 |
| 3. 互动 | xigua/app-v2/video-comment-list | item_id | 一条视频的评论 |
端点 API 参考是每个参数名和响应路径的事实来源。
第 1 步 —— 搜一个关键词
先写一个判 status 并检查上游 err_code 的辅助函数,再跑一次搜索:
import os
import requests
BASE = "https://api.sandbase.ai/v1/api/xigua"
HEADERS = {
"Authorization": f"Bearer {os.environ['SANDBASE_API_KEY']}",
"Content-Type": "application/json",
}
def call(path: str, payload: dict) -> dict:
resp = requests.post(f"{BASE}/{path}", headers=HEADERS, json=payload, timeout=90)
resp.raise_for_status()
body = resp.json()
if body.get("status") != "completed":
raise RuntimeError(body.get("error", {}).get("message", "请求未完成"))
data = body["outputs"][0]["data"]
# 在我的抓取里,负载报告了一个上游 err_code;参考并不保证它,
# 所以防御式检查,并以真实响应核对路径。
if isinstance(data, dict) and data.get("err_code") not in (0, None):
raise RuntimeError("上游错误")
return data if isinstance(data, dict) else {}
search = call("app-v2/search-video", {"keyword": "科技"})
print(search.get("count"), "条结果,offset:", search.get("offset"), "more:", search.get("has_more"))
results = search.get("results", [])
下面的块是示意性的、并非文档保证:它是我那次调用的一次抓取(搜索 run id 07f62735-11c0-4394-997e-27da674651b9,测试于 2026-09-27,UTC)。在那次抓取里,搜索在 results 旁边给出 count、offset 和 has_more,而每个结果项嵌套它自己的结构化负载。参考的业务负载示例是刻意留空的,所以对每个字段都用 .get() 读取、把这些名字当作仅供观测,并检查一份真实响应弄清 item_id 和 user_id 在哪:
{
"id": "07f62735-11c0-4394-997e-27da674651b9",
"status": "completed",
"model": "xigua/app-v2/search-video",
"outputs": [
{
"data": {
"err_code": 0,
"count": 10,
"offset": 10,
"has_more": true,
"results": [ { "id": "…", "data": {} } ]
}
}
]
}
因为每个结果项嵌套它自己的负载(一个渲染卡结构),迭代之前先检查一份真实响应,弄清到 item_id 和 user_id 的确切路径。
search-video 返回结果加 offset/has_more;从真实响应里对准 item_id 和 user_id。
第 2 步 —— 读一条视频的详情
对你从搜索里浮现出的 item_id,读视频详情。one-video-v2 接一个 item_id:
def video_detail(item_id: str) -> dict:
return call("app-v2/one-video-v2", {"item_id": item_id})
# item_id 来自搜索结果——在一份真实响应里确认它的确切路径
detail = video_detail("<来自搜索的 item_id>")
防御式读取返回的字段,并以一份真实响应核对字段名,因为详情负载由上游决定、可能变化。
第 3 步 —— 拉评论
读一条视频的评论串,拿互动和情感输入。video-comment-list 同样接一个 item_id:
def comments(item_id: str) -> dict:
return call("app-v2/video-comment-list", {"item_id": item_id})
thread = comments("<来自搜索的 item_id>")
评论负载由上游决定;防御式读取,并从一份真实响应里对准列表路径,再依赖它。
video-comment-list 按 item_id 读取一条视频的评论。
把它串起来
一次最小的研究过程长这样——搜索,然后对每条视频读详情和评论:
search = call("app-v2/search-video", {"keyword": "科技"})
report = []
for entry in search.get("results", []):
# 按一份真实响应从结果的嵌套负载里对准 item_id
item_id = extract_item_id(entry) # 你为结果结构写的解析器
if not item_id:
continue
detail = call("app-v2/one-video-v2", {"item_id": item_id})
thread = call("app-v2/video-comment-list", {"item_id": item_id})
report.append({"item_id": item_id, "detail": detail, "comments": thread})
# 要给搜索翻页,下一次 search-video 调用把返回的 offset 传回去
因为每次调用共用同一个信封和同一个 call 辅助函数(带它的 err_code 检查),加重试或速率退避是一处改动的事。当你需要的不止这些读取时——某个创作者的资料或帖子列表——用一个 user_id 调 xigua/app-v2/user-info 或 user-post-list,并先对照参考确认参数。
为什么在 API 层做这件事
你当然可以用无头浏览器指向西瓜视频、解析 App 的负载,但这条路很脆:App 会变,token 会轮换,你维护的是采集器而不是在做产品。通过一层统一 API 来读,意味着每次调用都返回相同的 { id, status, model, outputs } 信封、带一个内层 err_code,于是你的循环就几行、错误处理是一个辅助函数。搜索给你候选,item_id 带进详情和评论,整个过程落进一张你可以随时间做趋势的表。
这种一致性让工作流可组合。把关键词换成任意话题,对一条视频背后的创作者加一次 user-info 读取,它就用同一个辅助函数、同一个 err_code 检查接进来。你的时间花在”这些视频和评论对你的研究意味着什么”上,而不是花在维持一个采集器上。
局限与边界
- 仅公开、只读数据。 不发帖、不关注、不涉及私有或仅账号可见的数据。
- 上游 err_code(观测到的)。 在我的抓取里负载报告了一个
err_code(0 表示成功)——这是一个参考并不保证的业务字段;读更多字段前先防御式检查它。 - 结果项嵌套自己的负载。 迭代前先从一份真实响应里对准
item_id/user_id路径。 - 参数随上游面而定。
search-video接keyword;one-video-v2和video-comment-list接item_id;user-info/user-post-list接user_id。分页是每端点各自的——查阅每个端点的结构确定确切参数。 - 速率与量级。 把响应当作尽力而为的读取;遇到 HTTP 429 等瞬时错误时按退避策略重试,并控制请求节奏。
- 以线上参考核对。 可用性和字段可能变化;在依赖某个具体端点前先确认。
常见问题
我需要西瓜视频开发者应用或登录吗?
不需要。你用自己的 SANDBASE_API_KEY 向 SandBase 鉴权。这套工作流读的是公开视频数据,不需要你这边有西瓜视频账号或 OAuth。
什么标识一条视频、什么标识一个创作者?
item_id 标识一条视频(供 one-video-v2 和 video-comment-list 用);user_id 标识一个创作者(供 user-info 和 user-post-list 用)。两者都能从搜索结果里浮现——从一份真实响应里对准它们的确切路径。
我怎么给搜索翻页?
在我的抓取里 search-video 返回了一个 offset 和一个 has_more 标记;在 has_more 为真时,下一次调用把 offset 传回去。确切分页参数请对照端点参考核对。
我能读私有或仅账号可见的数据吗? 不能。这套工作流只是公开数据。私有和账号授权内容不在范围内。
动手搭
创建一个 SandBase API 密钥,搜一个关键词,读一条视频的详情和评论。准备好后: