IP地址街道级查询接口接入实践:从街道定位到风险评分的多数据源方案
在风控反欺诈、用户归属地展示、就近接入调度、内容合规分发和日志分析等业务里,"把一个 IP 解析成可读的地理位置"是一个高频需求。
普通的 IP 库往往只能给到省市级别,遇到风控场景还需要额外判断代理、机房、真人占比等信息,工程上经常要拼接多个数据源。本文基于接口页面资料,对一个支持街道级定位 + ISP + 风险评分的 IP 查询接口进行接入整理:包括能力边界、请求方式、参数确认、返回字段处理、降级逻辑和上线检查。
接口资料明确说明:该接口精确到街道级,采用多数据源自动切换——主源提供街道、ISP 与风险评分,主源不可用时自动降级到备用源(城市级 + ISP),并通过响应里的 data.source 字段标识本次数据档位。
接口地址:
GET https://v1.apizero.cn/api/ip-pro
一、接口适用场景
该接口适合用于以下业务场景:
- 用户归属地展示(登录地、评论 IP 属地、订单来源地)
- 风控反欺诈(识别代理、机房 IP、异常登录地)
- 就近接入与调度(按地理位置分配节点)
- 日志与流量分析(按地域统计访问来源)
- 内容合规与分区分发(按地区差异化展示)
- 营销活动地域限制(按省市区维度做规则)
核心目标是把一个 IPv4 / IPv6 地址,解析成"大洲—国家—省—市—区县—街道"的层级位置,并附带运营商和风险信息。
二、页面资料可确认的能力边界
根据接口页面资料,可以确认以下能力:
| 街道级定位 | 主数据源可定位到街道 / 乡镇 |
| 多数据源切换 | 主源不可用时自动降级到备用源 |
| 数据档位标识 | 通过 data.source 标识 primary / backup |
| IPv4 支持 | 支持查询 IPv4 地址 |
| IPv6 支持 | 支持查询 IPv6 地址 |
| 自动取调用方 IP | 不传 ip 时自动使用调用方自身 IP |
| ISP 识别 | 返回运营商信息 |
| 风险评分 | 返回包含 level/score/is_proxy 等的风险对象 |
| 候选街道 | 同一 IP 可返回多个候选街道 |
| 经纬度与海拔 | 返回经纬度,主源含海拔 |
| 行政与邮政信息 | 返回行政区划代码、邮编、城市电话区号 |
| 时区 | 返回时区,如 Asia/Shanghai |
| 匿名调用 | 默认开放匿名调用(受每日免费额度限制) |
三、请求方式与认证
页面资料明确给出了请求方式和认证说明,这一点比很多接口都清晰,可以直接按文档接入。
1. 请求方式
| 请求方法 | GET |
| 接口地址 | https://v1.apizero.cn/api/ip-pro |
2. 认证说明
页面资料说明:本接口默认开放匿名调用(受每日免费额度限制)。需要更高配额或商业使用时,携带 Authorization 头。
| Authorization | string | 可选 | Bearer Token。匿名调用时可省略;超过免费额度或付费方案时必需,格式 Bearer sk_live_xxxxxxxx |
工程建议:即使当前用匿名调用,也建议在配置层预留 Token 字段,方便后续切换到带 Key 调用,不用改代码。
四、请求参数
接口请求参数非常简单,只有一个可选参数。
| ip | string | 可选 | 要查询的 IP 地址(IPv4 或 IPv6)。不传时自动使用调用方自身 IP,适用于"查我自己"。示例:110.87.41.14 |
两种典型用法:
- 查指定 IP:传 ip 参数,例如解析日志里采集到的访问者 IP。
- 查调用方自身 IP:不传 ip,接口自动识别请求来源 IP,适合"显示我的归属地"这类前端场景(注意此时应由服务端转发,见第十一节)。
五、返回字段说明
页面资料给出了完整的返回字段。这里按"基础定位、地理坐标、行政信息、运营商与风险、数据档位"分组整理,便于在业务侧建模。
1. 基础定位字段
| ip | string | 查询的 IP(IPv4 / IPv6) |
| continent | string | 所属大洲(中文) |
| country | string | 国家 |
| country_code | string | 国家二字母代码 |
| province | string | 省 / 一级行政区 |
| city | string | 市 / 二级行政区 |
| district | string | 区县(仅主数据源提供) |
| street | string | 街道 / 乡镇(仅主数据源提供) |
| street_alternatives | array | 同一 IP 多个候选街道(仅主数据源提供) |
2. 地理坐标字段
| latitude | number | 纬度 |
| longitude | number | 经度 |
| elevation | number | 海拔(米,备用数据源时为 null) |
| time_zone | string | 时区,如 Asia/Shanghai |
3. 行政与邮政字段
| area_code | string | 行政区划代码 |
| zip_code | string | 邮编 |
| city_code | string | 城市电话区号 |
4. 运营商与风险字段
| isp | string | ISP / 运营商 |
| risk | object | 风险评分对象,含 level/score/is_proxy/proxy_probability 等 |
5. 数据档位字段
| source | string | 数据档位:primary(街道级 + 风险评分)或 backup(城市级基础信息) |
source 字段是这个接口很关键的设计:它告诉你这次拿到的是高精度主源数据还是降级后的备用源数据,业务侧可以据此决定是否展示街道、是否使用风险评分。
六、返回示例
页面资料提供了完整的返回示例(主数据源 primary 档位):
{
"code": 0,
"msg": "成功",
"data": {
"ip": "117.25.49.203",
"continent": "亚洲",
"country": "中国",
"country_code": "CN",
"province": "福建",
"city": "福州",
"district": "永泰",
"street": "城峰镇",
"street_alternatives": [
"福建福州永泰城峰镇",
"福建福州永泰大洋镇"
],
"area_code": "350125",
"zip_code": "350000",
"city_code": "0591",
"latitude": 25.855039,
"longitude": 118.94202,
"elevation": 29,
"time_zone": "Asia/Shanghai",
"isp": "电信",
"risk": {
"level": "无风险",
"score": 0,
"is_proxy": false,
"proxy_probability": 0,
"real_rate": 6,
"mobile_rate": 4.69
},
"source": "primary"
},
"request_id": "abc123"
}
从示例可以确认外层结构:
| code | 业务状态码,0 表示成功 |
| msg | 文案信息 |
| data | 业务数据对象(即上面的字段表) |
| request_id | 请求 ID,便于排查问题时定位 |
七、调用示例
下面给出常见语言的调用模板。请求方式、地址、参数均来自页面资料,可直接套用;Token 部分按需携带。
1. cURL 请求
查询指定 IP:
curl -G "https://v1.apizero.cn/api/ip-pro" \\
–data-urlencode "ip=110.87.41.14" \\
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxx"
查询调用方自身 IP(不传 ip,匿名调用可省略 Authorization):
curl "https://v1.apizero.cn/api/ip-pro"
2. Python 调用
import requests
def query_ip(ip: str | None = None, token: str | None = None) –> dict:
url = "https://v1.apizero.cn/api/ip-pro"
params = {}
if ip:
params["ip"] = ip
headers = {}
if token:
headers["Authorization"] = f"Bearer {token}"
resp = requests.get(url, params=params, headers=headers, timeout=10)
resp.raise_for_status()
result = resp.json()
if result.get("code") != 0:
raise RuntimeError(f"IP 查询失败:{result.get('msg')}")
return result["data"]
if __name__ == "__main__":
data = query_ip("110.87.41.14")
print(data["province"], data["city"], data.get("district"), data.get("street"))
print("数据档位:", data["source"])
3. JavaScript(浏览器 / fetch)
注意:浏览器端直接调用会暴露 Token,正式环境建议由服务端代理(见第十一节)。下面示例用于本地调试或匿名调用。
async function queryIp(ip) {
const url = new URL("https://v1.apizero.cn/api/ip-pro");
if (ip) {
url.searchParams.set("ip", ip);
}
const response = await fetch(url, { method: "GET" });
if (!response.ok) {
throw new Error(`IP 查询请求失败,HTTP 状态码:${response.status}`);
}
const result = await response.json();
if (result.code !== 0) {
throw new Error(`IP 查询失败:${result.msg}`);
}
return result.data;
}
4. Node.js 服务端封装
class IpLocationService {
constructor(options = {}) {
this.endpoint = options.endpoint || "https://v1.apizero.cn/api/ip-pro";
this.token = options.token || "";
}
async query(ip) {
const url = new URL(this.endpoint);
if (ip) {
url.searchParams.set("ip", ip);
}
const headers = {};
if (this.token) {
headers["Authorization"] = `Bearer ${this.token}`;
}
const response = await fetch(url, { method: "GET", headers });
const result = await response.json();
if (!response.ok || result.code !== 0) {
throw new Error(`IP 定位失败:${result.msg || response.status}`);
}
return result.data;
}
}
const service = new IpLocationService({
token: process.env.IP_LOCATION_TOKEN
});
八、返回结果适配建议
不同业务对字段的关注点不同,建议在业务系统里建立一个适配层,把接口返回标准化成自己的内部模型。
function normalizeIpResult(data) {
return {
ip: data.ip,
// 拼接可读地址,主源到街道,备用源到市
address: [data.province, data.city, data.district, data.street]
.filter(Boolean)
.join(""),
province: data.province,
city: data.city,
district: data.district || "",
street: data.street || "",
isp: data.isp || "",
location: {
latitude: data.latitude,
longitude: data.longitude
},
timeZone: data.time_zone || "",
risk: data.risk || null,
// 关键:记录数据档位,决定是否展示街道与风险
source: data.source,
isStreetLevel: data.source === "primary",
raw: data
};
}
建议在落库时保留原始返回(raw),方便接口字段升级后重新解析。
九、数据档位(source)处理
这是接入这个接口时最值得单独处理的一点。由于存在主源(primary)与备用源(backup)两档,业务展示逻辑应当根据 source 做差异化处理,避免在降级时展示空字段或误用风险评分。
function buildDisplay(data) {
if (data.source === "primary") {
return {
level: "street",
text: [data.province, data.city, data.district, data.street]
.filter(Boolean)
.join(""),
showRisk: !!data.risk
};
}
// backup:城市级 + ISP,无街道、无风险评分,elevation 可能为 null
return {
level: "city",
text: [data.province, data.city].filter(Boolean).join(""),
showRisk: false
};
}
处理原则:
- primary:可展示到街道,可使用风险评分。
- backup:只展示到城市,不要展示街道/区县占位,不要使用风险评分。
- 字段如 district、street、street_alternatives、elevation 在备用源时可能为空或 null,前端需要做空值兜底。
十、风险字段(risk)使用建议
risk 是一个对象,页面资料说明包含 level/score/is_proxy/proxy_probability 等字段,返回示例中还出现了 real_rate、mobile_rate。
风控场景下的常见用法:
function evaluateRisk(data) {
const risk = data.risk;
if (!risk) {
// 备用源或无风险数据时,建议走默认策略
return { decision: "unknown", reason: "缺少风险数据" };
}
if (risk.is_proxy || risk.proxy_probability >= 0.8) {
return { decision: "block", reason: "疑似代理/机房 IP" };
}
if (typeof risk.score === "number" && risk.score >= 60) {
return { decision: "review", reason: `风险分较高:${risk.score}` };
}
return { decision: "pass", reason: risk.level || "正常" };
}
建议:
- 风险分阈值(如示例中的 60)应结合自身业务调参,不要照搬。
- is_proxy 与 proxy_probability 适合用于登录、下单、领券等关键动作的拦截判断。
- 当 source 为 backup 时,risk 可能缺失,风控策略要有"无风险数据"的兜底分支。
十一、安全与合规建议
IP 定位涉及来源识别和风险判断,工程落地时建议注意:
- 不要在前端代码里硬编码 Token,统一由服务端代理调用。
- "查我自己"场景:前端拿到的是前端到接口的链路 IP,正确做法是后端读取真实客户端 IP(如 X-Forwarded-For 链路首个可信 IP)后再传给接口,避免拿到代理/网关 IP。
- 对外展示 IP 属地时,注意只展示到合适粒度(如省市),街道级信息更适合内部风控使用。
- 记录 request_id,便于出现异常时向平台反馈定位。
- 遵守平台服务条款与隐私政策,不要将接口用于违法、违规或侵犯他人权益的场景。
推荐链路:
客户端请求
↓
业务服务端解析真实客户端 IP(可信 X-Forwarded-For)
↓
服务端携带 Token 调用 IP 查询接口
↓
按 source 档位做展示/风控适配
↓
结果缓存与落库
不推荐:
前端直接携带 Token 调用接口,并展示街道级位置给所有人
十二、性能与缓存建议
IP 与地理位置的对应关系在短期内相对稳定,适合做缓存来降低调用量、提升响应速度。
import time
_cache = {}
_TTL = 60 * 60 # 1 小时
def query_ip_cached(ip, fetcher):
now = time.time()
hit = _cache.get(ip)
if hit and now – hit["ts"] < _TTL:
return hit["data"]
data = fetcher(ip)
_cache[ip] = {"data": data, "ts": now}
return data
建议:
- 对高频访问的 IP 做本地或 Redis 缓存,设置合理 TTL。
- 注意接口存在每日免费额度与 QPS 限制,批量场景应控制并发并做好缓存与限速。
- 缓存 key 建议带上"是否带 Token"维度,避免不同档位结果互相污染。
十三、上线前测试清单
输入测试
- 正常 IPv4
- 正常 IPv6
- 不传 ip(查调用方自身 IP)
- 非法 IP 字符串
- 内网 / 保留地址 IP
- 海外 IP
返回与档位测试
- 命中主源(source = primary,含街道与风险)
- 命中备用源(source = backup,仅城市级)
- district / street 为空时的兜底展示
- elevation 为 null 时的处理
- risk 缺失时风控分支是否正常
工程测试
- 匿名调用是否正常
- 携带 Token 调用是否正常
- 超时与重试逻辑
- 缓存命中与失效
- code != 0 时的错误处理
十四、总结
IP 地址查询(街道级)接口通过 GET https://v1.apizero.cn/api/ip-pro 提供服务,只需一个可选的 ip 参数即可使用,默认支持匿名调用,需要更高配额时携带 Authorization Bearer Token。
接口最大的特点是多数据源自动切换 + 街道级精度 + 风险评分:主源(primary)返回街道、ISP 与风险对象,主源不可用时自动降级到备用源(backup)的城市级基础信息,并通过 data.source 字段明确标识本次数据档位。
工程接入时,重点是围绕 source 字段做展示与风控的差异化适配,对 district、street、elevation、risk 等"仅主源提供"的字段做好空值兜底;同时按服务端代理、缓存、限速、真实客户端 IP 解析等工程实践落地,既能拿到高精度定位,又能稳定、安全地用于归属地展示与风控场景。

