全球IP地址查询:错误处理与 ret_code 排查
# 全球IP地址查询:错误处理与 ret_code 排查
> 元信息:接口 全球IP地址查询(apiCode=20)· 免费 · 适用人群 开发者/运维 · 阅读时间 5 分钟
## TL;DR 快速概览
- 两层返回:外层系统级 `showapi_res_code`(0 成功),内层业务级 `showapi_res_body.ret_code`(0 成功,其他失败)。
- 文档**未枚举**业务错误码,只说明 `ret_code` "0 为成功,其他为失败";排查以实际返回的 `ret_code` 值为准,不臆造 -2/-3 等。
- 网络层要加重试与超时(默认 10s),并对 `showapi_res_code != 0` 做系统级兜底。
## Why:为什么错误处理要分两层
很多初学者只判断 HTTP 200 就直接取 `city`,结果遇到系统级限流或业务查不到时程序崩溃、前端显示异常。区分"请求本身成没成"和"归属地查没查到"两层,才能稳定兜住异常。
## What:两层返回与状态码
| 层级 | 字段 | 含义 |
|------|------|------|
| 系统级 | `showapi_res_code` | 0 成功;非 0 表示平台/系统级错误(如鉴权、限流) |
| 系统级 | `showapi_res_error` | 系统级错误描述 |
| 业务级 | `showapi_res_body.ret_code` | 0 成功;**其他为失败**(文档未给具体枚举) |
> 说明:文档仅在返回体标注 `ret_code` "0为成功,其他为失败",未列出完整业务错误码表。因此排查时以接口实际返回的 `ret_code` 值为准,不要套用其他接口的 -2/-3 等数字。
## How:健壮的调用骨架
```python
import requests
from requests.exceptions import Timeout, RequestException
def safe_query(ip, appkey="YOUR_APPKEY", retries=2):
for attempt in range(retries + 1):
try:
resp = requests.get(
"https://route.showapi.com/20-1",
params={"appKey": appkey, "ip": ip},
timeout=10,
)
data = resp.json()
except (Timeout, RequestException) as e:
if attempt == retries:
return None, f"网络异常: {e}"
continue # 指数退避前先简单重试
if data.get("showapi_res_code") != 0:
return None, f"系统错误 {data.get('showapi_res_code')}: {data.get('showapi_res_error')}"
body = data["showapi_res_body"]
if body.get("ret_code") != "0":
return None, f"业务失败 ret_code={body.get('ret_code')}"
return body, None
return None, "重试后仍失败"
body, err = safe_query("203.0.113.220")
print(err or f"{body.get('country')}{body.get('region')}{body.get('city')}")
```
## 返回示例与解析
成功:
```json
{ "showapi_res_code": 0, "showapi_res_error": "", "showapi_res_body": { "ret_code": "0", "country": "中国", "city": "东莞" } }
```
系统级异常(示例形态,具体以接口返回为准):
```json
{ "showapi_res_code": -1, "showapi_res_error": "appKey 无效或权限不足", "showapi_res_body": {} }
```
## 进阶 / 边界
- **重试要有上限与退避**:网络抖动可重试 1~2 次并加短暂退避,但 `appKey` 无效、参数非法这类确定性错误不要重试,直接报错。
- **业务失败不重试**:`ret_code != "0"` 属业务结果,重试通常无变化,按失败处理即可。
- **免费档位限流**:高频触发限流时属系统级异常,应降速 + 本地缓存(见[免费档位指南](https://www.showapi.com/guides/ip-geo-free-tier-20))。
## FAQ
**Q1:ret_code 非 0 时有哪些具体错误码?**
A:文档只说明 `ret_code` "0 为成功,其他为失败",未给出完整枚举。排查以接口实际返回的 `ret_code` 值为准;不要套用其他接口的编码。
**Q2:showapi_res_code 和 ret_code 有什么区别?**
A:`showapi_res_code` 是系统级(请求/鉴权/平台),`ret_code` 在 `showapi_res_body` 内是业务级(这条 IP 查到没)。两层都要判断:先系统级 0,再业务级 0。
**Q3:请求超时设多少?**
A:文档未指定,示例按通用默认 10s 设置;如你的网络环境更严,可下调并在超时后重试。
**Q4:appKey 写错会怎样?**
A:通常表现为系统级 `showapi_res_code != 0` 并带错误描述;检查 AppKey 是否完整、是否在[控制台](https://www.showapi.com/console#/myApp)有效。
## 相关能力 / 下一步阅读
- [5 分钟接入全球IP地址查询](https://www.showapi.com/guides/ip-geo-quickstart-20) — 基础调用
- [全球IP地址查询:免费档位与积分兑换](https://www.showapi.com/guides/ip-geo-free-tier-20) — 限流与缓存
- [全球IP地址查询:返回字段全解](https://www.showapi.com/guides/ip-geo-response-fields-20) — 字段含义
- **本系列共 10 篇**:查看[全球IP地址查询指南总目录](https://www.showapi.com/guides/ip-geo-guides-20)