技术博客
百度搜索 API 报错怎么查:query 为空、appKey err、ret_code 各是什么

百度搜索 API 报错怎么查:query 为空、appKey err、ret_code 各是什么

作者: 万维易源
2026-09-15
百度搜索错误排查错误码排错指南
# 百度搜索 API 报错怎么查:query 为空、appKey err、ret_code 各是什么 > 接口:百度搜索(apiCode=3351,接入点 3351-1)· 官方自营 · 按次计费 > 请求方式:POST / GET · 适用人群:已接入、正在排查问题的开发者 · 阅读时间:约 6 分钟 > **最后实测核对:2026-09-15(含三种错误的真实响应原文)** 调用百度搜索 API 没拿到数据,先看 `showapi_res_code`。它是 0 之外的值时,`showapi_res_body` 基本是空的,你也不用往下看 `references` 了——问题出在网关层,跟检索没关系。 这篇把三类错误的真实响应贴出来对照,并说明为什么"返回 200"不代表调用成功。 ## 错误分层:先看哪一层 百度搜索 API(apiCode=3351)的响应有三层状态信息,排查顺序从上往下: | 层级 | 字段 | 位置 | 含义 | |------|------|------|------| | 网关层 | `showapi_res_code` | 响应最外层 | 0 表示请求被受理;非 0 表示参数/鉴权/额度问题 | | 网关层描述 | `showapi_res_error` | 响应最外层 | 机器可读的英文错误描述,如 `appKey err` | | 业务层 | `showapi_res_body.ret_code` | body 内 | 0 成功 / -1 失败(文档定义) | | 业务层描述 | `showapi_res_body.remark` | body 内 | 返回描述,实测成功时为空字符串 | | 扣费 | `showapi_fee_num` | 响应最外层 | 本次扣了几次,**失败时为 0** | 关键点:`showapi_res_code` 非 0 时,`showapi_res_body` 会是空对象 `{}`,或者这个键**整个不存在**。两种情况的差别在下面实测表里。 ## 实测错误对照表 2026-09-15 实测三种场景,其中两种是失败、一种是成功对照(请求体固定): | 场景 | HTTP | `showapi_res_code` | `showapi_res_error` | `showapi_res_body` | `showapi_fee_num` | |------|------|-------------------|---------------------|--------------------|-------------------| | `query` 未传或为空 | 200 | `-1` | `must input query field` | `{}`(空对象) | `0` | | AppKey 错误 | 200 | `-1004` | `appKey err` | **该键不存在** | `0` | | 正常调用 | 200 | `0` | `""` | 完整业务数据 | `1` | 三条结论: 1. **HTTP 状态码永远是 200。** 出错也是 200,所以判断成功只能靠 `showapi_res_code`,不能靠 `resp.status_code`。 2. **失败不扣费。** 两种错误场景下 `showapi_fee_num` 都是 0。参数写错不会白白消耗次数,你可以放心调试。 3. **错误响应的 body 结构不统一。** `query` 为空时 `showapi_res_body` 是 `{}`;AppKey 错误时这个键直接不存在。解析代码必须两种情况都能扛住。 第 3 点是文档没写的,也是实际最容易让程序崩的地方——直接写 `result["showapi_res_body"]["references"]` 会抛 `KeyError`。 ## 真实响应长什么样 `query` 未传时的完整响应(原文照录,仅去掉缩进): ```json { "showapi_res_error": "must input query field", "showapi_res_id": "6aa89f3afb638c2f69c82001", "showapi_res_code": -1, "showapi_fee_num": 0, "showapi_res_body": {} } ``` AppKey 错误时的完整响应: ```json { "showapi_res_error": "appKey err", "showapi_res_id": "6aa89f55fb638c2f69cf03d7", "showapi_res_code": -1004, "showapi_fee_num": 0 } ``` 注意第二段里没有 `showapi_res_body`。`showapi_res_id` 两种情况都有,出了问题拿这个 id 去找客服,比描述现象快得多。 ## 排查路径 **第一步,确认 `showapi_res_code`。** 不是 0 就对照上表定位,别继续往下查。 **第二步,如果是 `must input query field`。** `query` 是唯一必填参数,且不能为空字符串。检查三件事:参数名是否拼成 `query`(不是 `q` 或 `keyword`);内容是否真的传进去了;是不是被空值覆盖了。实测中 `query=` 这种空值提交就会触发这个错误。 **第三步,如果是 `appKey err`。** 检查 AppKey 是否放在 URL 参数 `appKey` 上、有没有多余空格或换行、是否误复制了其他接口的 key。这个错误码是 `-1004`。 **第四步,如果 `showapi_res_code` 是 0 但结果不对。** 这属于"调用成功但结果不符合预期",常见原因是 `query` 的编码出了问题,见下一节。 ## 看起来成功、其实错了的情况 这是排查里最费时间的一类:`showapi_res_code = 0`、`ret_code = 0`、`references` 也有 10 条,但内容跟查询毫无关系。 2026-09-15 实测复现过一次。在 Windows 的 Git Bash 里执行: ```bash curl -X POST "https://route.showapi.com/3351-1?appKey=YOUR_APPKEY" \ -d "query=昆明天气" ``` 返回的前几条是酷狗音乐的歌曲页和金山词霸的单词页,`url` 里出现 `w=??????` 这样的内容。根因不在接口,在于命令行把中文按 GBK 送了出去,真正被检索的是一串乱码。 正确写法: ```bash # 方式一:让 curl 自己编码 curl -X POST "https://route.showapi.com/3351-1?appKey=YOUR_APPKEY" \ --data-urlencode "query=昆明天气" # 方式二:参数写入 UTF-8 文件后提交(Windows 下更可靠) curl -X POST "https://route.showapi.com/3351-1?appKey=YOUR_APPKEY" \ -H "content-type: application/x-www-form-urlencoded" \ --data-binary @params.txt ``` Python 和 Node.js 用 `requests` / `URLSearchParams` 传中文不会踩这个坑,它们默认 UTF-8。 **自检方法**:看返回的 `url` 和 `title` 里中文是否正常。中文正常说明编码没问题;出现 `????` 或乱码字符,先改编码,不要再调参数。 ## 稳一点的解析代码 把三层判断和键存在性一起处理,这段可以照抄: ```python import requests def search(query: str, appkey: str, timeout: int = 10) -> list: resp = requests.post( "https://route.showapi.com/3351-1", params={"appKey": appkey}, data={"query": query}, timeout=timeout, ) resp.raise_for_status() result = resp.json() code = result.get("showapi_res_code") if code != 0: # 网关层失败:showapi_res_body 可能为空对象,也可能不存在 raise RuntimeError( f"调用失败 code={code} error={result.get('showapi_res_error')} " f"res_id={result.get('showapi_res_id')}" ) body = result.get("showapi_res_body") or {} if body.get("ret_code") != 0: raise RuntimeError( f"检索失败 ret_code={body.get('ret_code')} remark={body.get('remark')}" ) refs = body.get("references") if not isinstance(refs, list): return [] # 正常返回但没结果,别让它抛异常 return refs ``` 三个细节:`showapi_res_body` 用 `or {}` 兜底;`references` 判断是不是列表;错误信息里带上 `showapi_res_id`。 ## 进阶与边界 **`ret_code = -1` 本次没测到。** 文档写的是"成功标志 0:成功 -1:失败",但 2026-09-15 的 18 次成功调用里,参数错误和鉴权错误都在网关层就被拦下了,`showapi_res_body` 是空的,业务层的 -1 没有复现。所以这条我标在这里:文档定义存在,触发条件未实测,不要凭猜测在代码里处理它——按上面对照表的实际行为写就够了。 **没有官方错误码全集。** 文档只给了 `ret_code` 的 0 / -1,网关层错误码(如 `-1004`)没有在接口文档里列出。实测遇到的就是上面两个值,其余情况以实际返回的 `showapi_res_error` 文本为准,代码里做字符串兜底比硬编码码表靠谱。 ## FAQ **Q1:接口返回 HTTP 200,是不是就成功了?** 不是。实测三种场景(正常、`query` 为空、AppKey 错误)HTTP 状态码都是 200,区别全在响应体的 `showapi_res_code` 上。 **Q2:参数写错会不会扣次数?** 不会。实测 `query` 为空和 AppKey 错误时 `showapi_fee_num` 都是 0。 **Q3:为什么我的代码报 `KeyError: 'showapi_res_body'`?** AppKey 错误时这个键不存在。先判断 `showapi_res_code == 0` 再取 body,或者用 `result.get("showapi_res_body") or {}` 兜底。 **Q4:返回了结果但内容和查询无关,是接口坏了吗?** 大概率是 `query` 编码问题。检查返回的 `url` 里中文是否正常,出现乱码就改用 `--data-urlencode` 或 UTF-8 参数文件。 **Q5:拿不到结果时怎么找客服?** 带上响应里的 `showapi_res_id`。这个字段成功和失败时都会返回,用它定位比复述现象有效。 ## 下一步阅读 - [百度搜索 API:用 Python 跑通第一次实时检索](https://www.showapi.com/guides/baidu-search-api-quickstart-3351) —— 三种语言的正确请求写法 - [百度搜索 API 返回字段:references 里 13 个字段逐个说清](https://www.showapi.com/guides/baidu-search-api-response-fields-3351) —— 分清成功响应里每个字段 - [百度搜索 API 域名过滤只需两个参数](https://www.showapi.com/guides/baidu-search-api-domain-filter-3351) —— 返回条数比预期少时的正常原因 --- - **本系列共 8 篇**:查看[百度搜索 API 指南总目录](https://www.showapi.com/guides/baidu-search-guides-3351)