手机归属地查询返回字段全解:prov/city/type/postCode 一文读懂
# 手机归属地查询返回字段全解:prov/city/type/postCode 一文读懂
> **接口**:手机归属地查询 `6-1` | **是否免费**:是(有使用档次限制)| **请求方式**:POST / GET | **返回格式**:JSON | **适用人群**:已初步调用、需要精确理解返回结构的开发者 | **阅读时间**:约 8 分钟
## TL;DR
- 业务数据**全部封装在 `showapi_res_body` 里**,外层 `showapi_res_code` 等是系统级字段,别读错层。
- 共 **10 个业务字段**:`prov` `city` `name` `num` `provCode` `cityCode` `areaCode` `postCode` `type` `ret_code`;其中 `type` 和 `ret_code` 是枚举/状态码,其余为字符串或数字标量。
- 两个容易踩的坑:① `num` 返回的是**号段(前 7 位)**不是完整手机号;② 接口**不返回经纬度**,地图需求需外部地理编码。
## Why:为什么要把字段啃透?
很多开发者第一次拿到返回,只打印了 `prov` 和 `city` 就完事,结果上线后接连踩坑:把 `num`(号段)当成用户原号存进数据库、用 `type` 的数字去拼运营商中文名拼错、想做地图却发现没有坐标……
把字段彻底讲清,目的就一个——**让你在写解析代码前,先知道每个字段"是什么、不是什么、能拿来干什么"**。这一篇是系列的"字段速查母页",后面《type 字段全解》《错误码排查》两篇都从这里延伸,所有文章也都会链回这里。
## What:接口与返回结构速览
| 项目 | 内容 |
|------|------|
| 接入点 | `6-1`(同步请求-响应,仅 1 个接入点) |
| 接口地址 | `https://route.showapi.com/6-1?appKey={your_appKey}` |
| 必填参数 | `num`(手机号) |
| 返回格式 | JSON |
| 数据结构 | 外层系统字段 + 内层 `showapi_res_body`(业务数据) |
### 返回封装结构(务必先剥这一层)
```
HTTP 响应 JSON
├── showapi_res_code 系统级:0 成功(注意与 body 内 ret_code 区分)
├── showapi_res_error 系统级:错误信息
├── showapi_res_id 系统级:本次请求唯一 ID
└── showapi_res_body ★ 业务数据全部在这里 ★
├── prov / city / name / num
├── provCode / cityCode / areaCode / postCode
├── type
└── ret_code
```
> ⚠️ 最常见的解析错误:直接读 `data.prov`。正确做法是先取 `showapi_res_body`,再读里面的字段(见 [快速开始](https://www.showapi.com/guides/phone-attribution-quickstart-6) 的代码)。
## 返回字段完整一览表
下表覆盖 `showapi_res_body` 内的全部 10 个字段。示例值取自官方返回示例(手机号 `18908711111`)。
| 字段 | 类型 | 含义 | 示例值 | 备注 |
|------|------|------|--------|------|
| `prov` | String | 省 | 云南 | 行政区划省级名称 |
| `city` | String | 市 | 昆明 | 文档定义为"市",粒度以返回为准 |
| `name` | String | 运营商名称 | 电信 | 与 `type` 对应(中文名) |
| `num` | Number | 号段(前 7 位) | 1890871 | **不是完整手机号**,是号段 |
| `provCode` | Number | 省别编码 | 530000 | 本省身份证的前几位编码 |
| `cityCode` | String | 城市编码 | 530100 | 本城市身份证的前几位编码 |
| `areaCode` | String | 城市区号 | 0871 | 座机号码前几位(参数表曾误写 0810,以示例 0871 为准) |
| `postCode` | String | 邮政编码 | 650000 | 见下方"来源说明" |
| `type` | Number | 运营商枚举 | 2 | 1移动/2电信/3联通/4广电/-1未知 |
| `ret_code` | String | 业务状态码 | 0 | 0 成功,其他失败(失败不扣点数) |
### 关于 `postCode` 的来源说明(如实标注)
`postCode`(邮政编码)出现在官方**返回示例**与产品说明("省、市、邮编、区号")中,但未被列入"返回体参数"表——属文档待补录项。本文按真实返回示例将其列为有效返回字段;若你实测某次返回未带该字段,以实际响应为准。
### `provCode` / `cityCode` 的隐藏用途(文档原文)
文档对这两个字段的注释是"本省/本城市**身份证的前几位编码**"。即:`provCode=530000` 与云南身份证前 6 位一致,`cityCode=530100` 与昆明身份证前 6 位一致。这是官方给出的既定事实——可用于"手机号归属地与身份证归属地是否同源"的粗略比对场景,但**不要**据此做身份证校验(这是另一个接口的能力,本文不展开)。
## 字段深挖 1:`type` 运营商枚举
`type` 用数字表示运营商,和 `name`(中文名)一一对应:
| `type` 值 | 运营商 | 说明 |
|-----------|--------|------|
| `1` | 移动 | 含 134-139、150-152、157-159、182-184、187-188、198 等号段 |
| `2` | 电信 | 含 133、153、180-181、189、199 等号段 |
| `3` | 联通 | 含 130-132、155-156、185-186、166 等号段 |
| `4` | 广电 | 192 号段(较新运营商) |
| `-1` | 未知 | 无法识别运营商时返回 |
> 注意:`type` 与 `name` 是**同一事实的两种表达**(数字 + 中文名),不要两者各存一套再比对,取一个即可,另一个作为展示用。`type=-1` 表示未知,业务上应作"无法归类"处理,而不是默认当成某家。运营商与号段的精确映射以接口返回为准,上表号段仅作直觉参考。
## 字段深挖 2:`ret_code` 业务状态码
`ret_code` 位于 `showapi_res_body` 内,与外层 `showapi_res_code` 是两回事:
- `ret_code = 0`:**成功**,此时其余字段有效。
- `ret_code < 0`:**失败,且不扣点数**。完整枚举:
| `ret_code` | 含义 |
|-----------|------|
| `-2` | 手机号输入的不是 11 位 |
| `-3` | 手机号中有非数字字符 |
| `-4` | 手机号格式错误 |
| `-5` / `-6` | 找不到归属地 |
> 实战建议:客户端先做"11 位纯数字"正则校验,再发请求,可大幅减少无效调用(免费档位下更省心)。详细排查路径见 [《错误码排查》](https://www.showapi.com/guides/phone-attribution-error-codes-6)。
## 字段使用示例(解析代码片段)
```python
import requests
APP_KEY = "YOUR_APPKEY"
PHONE = "18908711111"
r = requests.get(
"https://route.showapi.com/6-1",
params={"appKey": APP_KEY, "num": PHONE},
timeout=10,
)
body = r.json().get("showapi_res_body", {})
if body.get("ret_code") != 0:
print("失败,错误码", body.get("ret_code"))
else:
# 用 type 做展示分支
carrier_map = {1: "移动", 2: "电信", 3: "联通", 4: "广电", -1: "未知"}
carrier = carrier_map.get(body.get("type"), "未知")
print(f"{body['prov']} {body['city']} | {carrier} | 区号 {body['areaCode']} | 邮编 {body.get('postCode')}")
# 注意 num 是号段,不是完整手机号
print("号段(前7位):", body["num"])
```
## 进阶 / 边界(如实写)
- **`num` 是号段不是原号**:返回 `1890871` 这类 7 位号段,不含完整手机号,别误存。
- **不返回经纬度**:只有省/市文字,没有坐标。地图标点需把 `city` 交给外部地理编码服务(如高德/腾讯地图 API)转坐标,本接口不提供。
- **不支持携号转网**:号码转网后归属地仍按原号段返回,不会变化。
- **`city` 粒度**:文档定义为"市",不保证到区/县,别假设更细。
- **字段缺失可能性**:如 `postCode` 当前未在参数表登记,个别返回可能不带某字段,解析时一律用 `.get()` 兜底,避免 KeyError。
## FAQ
**Q1:`showapi_res_code` 和 `ret_code` 有什么区别?**
外层 `showapi_res_code` 是系统级(网络/网关层),`ret_code` 是 `showapi_res_body` 内的业务状态码。判断业务成败看 `ret_code`。
**Q2:为什么我读不到 `prov`?**
因为你读在了外层。必须先取 `showapi_res_body`,再读 `prov`。这是最常见的解析错误。
**Q3:`num` 返回的是用户输入的完整手机号吗?**
不是,是号段(前 7 位),如 `1890871`。完整号码不会回传。
**Q4:`type` 和 `name` 用哪个好?**
展示用 `name`(中文),逻辑分支用 `type`(数字)更稳妥。两者同源,不必重复存储比对。
**Q5:返回里没有 `postCode` 怎么办?**
`postCode` 来源于返回示例,参数表未登记。个别响应可能不带,解析用 `.get("postCode")` 兜底,缺失时不强制依赖。
**Q6:能拿 `provCode`/`cityCode` 做身份证校验吗?**
不能。文档仅说明它们是"身份证前几位编码",可用于归属地同源粗略比对;身份证校验是另一接口职责,本文不覆盖。
## 相关能力 / 下一步阅读
- [《5 分钟接入手机归属地查询:从注册到第一条返回》](https://www.showapi.com/guides/phone-attribution-quickstart-6) —— 还没跑通?从这篇开始
- [《type 字段全解:1移动/2电信/3联通/4广电/-1未知怎么用》](https://www.showapi.com/guides/phone-attribution-type-field-6) —— 运营商枚举的业务落地
- [《错误码排查:-2 非11位 / -3 非数字 / -4 格式 / -5-6 找不到》](https://www.showapi.com/guides/phone-attribution-error-codes-6) —— 4 类失败对照表
- **本系列共 12 篇**:查看[手机归属地查询 · 官方指南总目录](https://www.showapi.com/guides/phone-attribution-guides-6)