秘塔API响应需按三步安全解析:先捕获JSONDecodeError确认是否为合法JSON;再检查code字段判断错误响应;最后验证data是否为列表。成功响应中data恒为列表,错误响应无data字段,流式响应需剥离data:前缀后再解析。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜

你在秘塔AI搜索API返回的JSON里反复遇到KeyError、JSONDecodeError或data字段为空,不是代码写错了,而是没看清响应结构就硬解析——秘塔的API响应不是扁平字典,它有固定三层嵌套,且错误响应和成功响应结构完全不同。
先确认返回的是不是合法JSON
用requests调用后,不要直接response.json()。先检查response.status_code是否为200,再用response.text[:200]打印前200个字符,看开头是不是{。如果返回的是HTML(比如403页面)、纯文本“Unauthorized”或空字符串,JSON.parse必然失败。
这一步不能跳过。很多开发者卡在第一步,却去改解析逻辑,浪费两小时。
识别秘塔API的标准响应结构
秘塔v1接口所有成功响应都遵循同一结构:
【data字段是列表,不是字典】 即使只返回一个结果,data也是[{"id":"xxx","title":"xxx",...}]这样的数组。直接response.json()["data"]["title"]会报TypeError: list indices must be integers。
错误响应则走另一条路径:{"code":401,"message":"Invalid API Key","error":"invalid_api_key"}——此时根本没有data字段,也没有result或items等别名。
安全解析三步法
第一步:用try/except包裹json.loads,捕获JSONDecodeError。若抛出,说明返回根本不是JSON,立刻终止解析流程,打印response.text并检查网络或鉴权。
第二步:检查顶层键是否存在code字段。存在且code≠0,说明是错误响应,直接取message字段,不要碰data。
第三步:code==0时,确认data字段类型。用isinstance(response_json.get("data"), list)判断,不是list就报结构异常,中止后续处理。
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
这三步缺一不可。漏掉第二步,你会在错误响应里强行遍历data;漏掉第三步,你把空值或字符串当列表循环,触发IndexError。
提取搜索结果内容的两种写法
方法一:基础索引(适合单结果)
if response_json.get("code") == 0 and response_json.get("data"):
first_result = response_json["data"][0]
title = first_result.get("title", "")
url = first_result.get("url", "")
方法二:防御性遍历(推荐用于生产)
results = response_json.get("data", [])
for item in results:
if not isinstance(item, dict): continue
title = item.get("title") or item.get("snippet", "")[:50]
print(f"标题:{title}")
注意:snippet字段在部分知识库查询中才存在,title在网页搜索中稳定返回,但企业版私有知识库可能返回content字段代替title——【不要假设字段必存在,一律用.get()带默认值】。
处理流式响应的特殊逻辑
如果你启用了stream=true参数,响应不再是完整JSON,而是SSE格式:data: {"id":"abc","title":"xxx"}\n\n。必须先按行分割,过滤掉以data:开头的行,再对每行去掉data:前缀,最后逐行json.loads。
漏掉剥离data:前缀,JSONDecodeError会持续报Unexpected token 'd'——这是最常被忽略的协议层污染。

















