技术博客
手机归属地查询返回字段全解:prov/city/type/postCode 一文读懂

手机归属地查询返回字段全解:prov/city/type/postCode 一文读懂

作者: 万维易源
2026-08-27
手机归属地查询返回字段provcitytype
# 手机归属地查询返回字段全解: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)