适用场景与接口能力IP 地址街道级查询在日志分析、风控、本地化服务中经常出现。例如用户登录后系统需要展示其大致位置城市、街道用于安全提醒。电商平台根据访客 IP 推荐附近门店。反欺诈系统结合 IP 风险评分判断是否存在代理或爬虫。本文介绍的接口ip-pro支持 IPv4 和 IPv6可直接返回街道、区县、城市、省份、经纬度、时区、邮编以及风险信息。核心特点是多数据源自动降级主源提供街道级 ISP 风险评分主源不可用时自动降级到备用源城市级 ISP响应中的data.source字段标识本次使用的数据档位primary或secondary。这对于保证服务可用性非常关键。接口 QPS 限制为 3 / s超出会返回限流错误。匿名调用有每日调用次数限制超过后需要在 Header 中传入Authorization: Bearer token。请求参数与鉴权Query 参数参数必填类型说明ip否string待查询的 IP 地址IPv4 或 IPv6。不传则自动获取调用方自身 IP。示例110.87.41.14Header 参数参数必填类型说明Authorization否stringBearer token。匿名调用可省略受每日调用次数限制限制超出调用次数限制或付费方案时必须携带。注意官方 curl 示例中使用的是X-API-Key头实际两者均可以最新文档为准。生产环境中推荐统一使用Authorization标准头部。curl 调试快速验证接口首先建议通过 curl 测试接口连通性。以下示例查询 IP110.87.41.14curl -sS \ -X GET \ -H Authorization: Bearer YOUR_API_KEY \ https://v1.apizero.cn/api/ip-pro?ip110.87.41.14如果使用匿名调用且未超出调用次数限制可省略Authorization头curl -sS \ -X GET \ https://v1.apizero.cn/api/ip-pro?ip110.87.41.14不传ip参数时接口会自动查询调用方自身 IPcurl -sS \ -X GET \ https://v1.apizero.cn/api/ip-pro成功返回示例已格式化{ code: 0, msg: 成功, request_id: abc123, data: { ip: 117.25.49.203, continent: 亚洲, country: 中国, country_code: CN, province: 福建, city: 福州, city_code: 0591, district: 永泰, street: 城峰镇, street_alternatives: [福建福州永泰城峰镇, 福建福州永泰大洋镇], area_code: 350125, zip_code: 350000, longitude: 118.94202, latitude: 25.855039, elevation: 29, time_zone: Asia/Shanghai, isp: 电信, risk: { score: 0, level: 无风险, is_proxy: false, proxy_probability: 0, mobile_rate: 4.69, real_rate: 6 }, source: primary } }注意source字段primary表示主源数据街道级secondary表示降级后的城市级数据。从 curl 到工程封装直接在命令行用 curl 调试很方便但集成到工程中需要处理超时、重试、错误码解析、鉴权管理等问题。下面给出 Python 和 Node.js 的封装示例。Python 封装requestsimport requests import time from typing import Optional, Dict, Any class IPQueryClient: def __init__(self, api_key: Optional[str] None, base_url: str https://v1.apizero.cn/api/ip-pro): self.api_key api_key self.base_url base_url self.session requests.Session() # 设置默认超时 self.session.timeout (3, 5) # connect, read timeout # 重试机制 from urllib3.util.retry import Retry from requests.adapters import HTTPAdapter retry_strategy Retry( total2, backoff_factor0.5, status_forcelist[429, 500, 502, 503, 504] ) adapter HTTPAdapter(max_retriesretry_strategy) self.session.mount(https://, adapter) self.session.mount(http://, adapter) def query(self, ip: Optional[str] None) - Dict[str, Any]: headers {} if self.api_key: headers[Authorization] fBearer {self.api_key} params {} if ip: params[ip] ip response self.session.get(self.base_url, paramsparams, headersheaders) if response.status_code 200: data response.json() if data.get(code) ! 0: raise RuntimeError(fAPI error: {data.get(msg, unknown)}) return data[data] elif response.status_code 429: raise RuntimeError(Rate limit exceeded (QPS: 3/s), wait and retry) else: raise RuntimeError(fHTTP {response.status_code}: {response.text}) # 使用示例 client IPQueryClient(api_keyNone) # 匿名调用 result client.query(110.87.41.14) print(result[street], result[district], result[risk][level])Node.js 封装axiosconst axios require(axios); class IPQueryClient { constructor(apiKey, baseURL https://v1.apizero.cn/api/ip-pro) { this.client axios.create({ baseURL, timeout: 5000, headers: apiKey ? { Authorization: Bearer ${apiKey} } : {} }); // 添加响应拦截器处理业务错误 this.client.interceptors.response.use( response { const data response.data; if (data.code ! 0) { return Promise.reject(new Error(data.msg || API error)); } return data.data; }, error { if (error.response error.response.status 429) { return Promise.reject(new Error(Rate limit exceeded)); } return Promise.reject(error); } ); } async query(ip) { const params ip ? { ip } : {}; return this.client.get(, { params }); } } // 使用示例 async function main() { const client new IPQueryClient(); try { const data await client.query(110.87.41.14); console.log(data.isp, data.street, data.risk.level); } catch (err) { console.error(err.message); } } main();返回值字段解读响应最外层的data对象包含全部信息需重点关注的字段字段类型说明ipstring查询的 IPcontinentstring大洲如“亚洲”countrystring国家名称country_codestring国家 ISO 代码provincestring省级行政区citystring地级市city_codestring电话区号districtstring区县streetstring街道/乡镇street_alternativesarray备选街道描述可能多个area_codestring行政区划代码6位数字zip_codestring邮政编码longitudenumber经度latitudenumber纬度elevationnumber海拔米time_zonestring时区标识ispstring运营商riskobject风险评分对象详见下方sourcestringprimary/secondary表示数据降级与否risk 对象字段字段类型说明scorenumber风险分数0-100越高越危险levelstring风险等级无风险 / 低风险 / 中风险 / 高风险is_proxyboolean是否代理 IPproxy_probabilitynumber代理概率0-100mobile_ratenumber移动网络概率百分比real_ratenumber真实用户概率百分比常见错误与处理错误场景HTTP 状态码code处理建议IP 格式非法40040001校验 IP 格式后再请求未携带 token 且超出调用次数限制40140101检查是否欠费添加 Authorization 头请求频率超限3 QPS42942901在客户端实现退避重试主备用源均不可用50350301等待一段时间后重试降级使用本地 IP 库缓存请求参数错误40040002参照文档确认参数名和类型工程化注意事项1. 缓存策略街道级数据的时效性较高通常 1-3 个月变化建议对同一 IP 的查询结果做短时间缓存如 1 小时减少 API 调用。可以使用 Redis 或内存缓存键为ip:{ip}。2. 降级处理接口本身有数据源降级但业务侧也应准备兜底策略。例如当 API 连续失败时可以回退到本地 IP 库如 GeoLite2获取城市级信息保证核心功能不中断。3. 异步与并发控制QPS 限制为 3/s若需要批量查询例如 100 个 IP应在客户端控制并发数使用信号量或队列限制每次并发请求不超过 3 个。import asyncio import aiohttp async def bounded_query(sem, ip): async with sem: async with aiohttp.ClientSession() as session: async with session.get(https://v1.apizero.cn/api/ip-pro, params{ip: ip}) as resp: return await resp.json() async def batch_query(ips): sem asyncio.Semaphore(3) # 最多3个并发 tasks [bounded_query(sem, ip) for ip in ips] return await asyncio.gather(*tasks)4. 监控与告警将接口响应时间、成功率、source为secondary的占比作为监控指标。若secondary比例突然升高说明主源可能出现问题应通知运维排查。参考文档官方文档页https://apizero.cn/aidocs/ip-pro原始接口文档https://apizero.cn/aidocs/ip-pro/raw.md
从curl到工程封装:IP地址街道级查询API实践
适用场景与接口能力IP 地址街道级查询在日志分析、风控、本地化服务中经常出现。例如用户登录后系统需要展示其大致位置城市、街道用于安全提醒。电商平台根据访客 IP 推荐附近门店。反欺诈系统结合 IP 风险评分判断是否存在代理或爬虫。本文介绍的接口ip-pro支持 IPv4 和 IPv6可直接返回街道、区县、城市、省份、经纬度、时区、邮编以及风险信息。核心特点是多数据源自动降级主源提供街道级 ISP 风险评分主源不可用时自动降级到备用源城市级 ISP响应中的data.source字段标识本次使用的数据档位primary或secondary。这对于保证服务可用性非常关键。接口 QPS 限制为 3 / s超出会返回限流错误。匿名调用有每日调用次数限制超过后需要在 Header 中传入Authorization: Bearer token。请求参数与鉴权Query 参数参数必填类型说明ip否string待查询的 IP 地址IPv4 或 IPv6。不传则自动获取调用方自身 IP。示例110.87.41.14Header 参数参数必填类型说明Authorization否stringBearer token。匿名调用可省略受每日调用次数限制限制超出调用次数限制或付费方案时必须携带。注意官方 curl 示例中使用的是X-API-Key头实际两者均可以最新文档为准。生产环境中推荐统一使用Authorization标准头部。curl 调试快速验证接口首先建议通过 curl 测试接口连通性。以下示例查询 IP110.87.41.14curl -sS \ -X GET \ -H Authorization: Bearer YOUR_API_KEY \ https://v1.apizero.cn/api/ip-pro?ip110.87.41.14如果使用匿名调用且未超出调用次数限制可省略Authorization头curl -sS \ -X GET \ https://v1.apizero.cn/api/ip-pro?ip110.87.41.14不传ip参数时接口会自动查询调用方自身 IPcurl -sS \ -X GET \ https://v1.apizero.cn/api/ip-pro成功返回示例已格式化{ code: 0, msg: 成功, request_id: abc123, data: { ip: 117.25.49.203, continent: 亚洲, country: 中国, country_code: CN, province: 福建, city: 福州, city_code: 0591, district: 永泰, street: 城峰镇, street_alternatives: [福建福州永泰城峰镇, 福建福州永泰大洋镇], area_code: 350125, zip_code: 350000, longitude: 118.94202, latitude: 25.855039, elevation: 29, time_zone: Asia/Shanghai, isp: 电信, risk: { score: 0, level: 无风险, is_proxy: false, proxy_probability: 0, mobile_rate: 4.69, real_rate: 6 }, source: primary } }注意source字段primary表示主源数据街道级secondary表示降级后的城市级数据。从 curl 到工程封装直接在命令行用 curl 调试很方便但集成到工程中需要处理超时、重试、错误码解析、鉴权管理等问题。下面给出 Python 和 Node.js 的封装示例。Python 封装requestsimport requests import time from typing import Optional, Dict, Any class IPQueryClient: def __init__(self, api_key: Optional[str] None, base_url: str https://v1.apizero.cn/api/ip-pro): self.api_key api_key self.base_url base_url self.session requests.Session() # 设置默认超时 self.session.timeout (3, 5) # connect, read timeout # 重试机制 from urllib3.util.retry import Retry from requests.adapters import HTTPAdapter retry_strategy Retry( total2, backoff_factor0.5, status_forcelist[429, 500, 502, 503, 504] ) adapter HTTPAdapter(max_retriesretry_strategy) self.session.mount(https://, adapter) self.session.mount(http://, adapter) def query(self, ip: Optional[str] None) - Dict[str, Any]: headers {} if self.api_key: headers[Authorization] fBearer {self.api_key} params {} if ip: params[ip] ip response self.session.get(self.base_url, paramsparams, headersheaders) if response.status_code 200: data response.json() if data.get(code) ! 0: raise RuntimeError(fAPI error: {data.get(msg, unknown)}) return data[data] elif response.status_code 429: raise RuntimeError(Rate limit exceeded (QPS: 3/s), wait and retry) else: raise RuntimeError(fHTTP {response.status_code}: {response.text}) # 使用示例 client IPQueryClient(api_keyNone) # 匿名调用 result client.query(110.87.41.14) print(result[street], result[district], result[risk][level])Node.js 封装axiosconst axios require(axios); class IPQueryClient { constructor(apiKey, baseURL https://v1.apizero.cn/api/ip-pro) { this.client axios.create({ baseURL, timeout: 5000, headers: apiKey ? { Authorization: Bearer ${apiKey} } : {} }); // 添加响应拦截器处理业务错误 this.client.interceptors.response.use( response { const data response.data; if (data.code ! 0) { return Promise.reject(new Error(data.msg || API error)); } return data.data; }, error { if (error.response error.response.status 429) { return Promise.reject(new Error(Rate limit exceeded)); } return Promise.reject(error); } ); } async query(ip) { const params ip ? { ip } : {}; return this.client.get(, { params }); } } // 使用示例 async function main() { const client new IPQueryClient(); try { const data await client.query(110.87.41.14); console.log(data.isp, data.street, data.risk.level); } catch (err) { console.error(err.message); } } main();返回值字段解读响应最外层的data对象包含全部信息需重点关注的字段字段类型说明ipstring查询的 IPcontinentstring大洲如“亚洲”countrystring国家名称country_codestring国家 ISO 代码provincestring省级行政区citystring地级市city_codestring电话区号districtstring区县streetstring街道/乡镇street_alternativesarray备选街道描述可能多个area_codestring行政区划代码6位数字zip_codestring邮政编码longitudenumber经度latitudenumber纬度elevationnumber海拔米time_zonestring时区标识ispstring运营商riskobject风险评分对象详见下方sourcestringprimary/secondary表示数据降级与否risk 对象字段字段类型说明scorenumber风险分数0-100越高越危险levelstring风险等级无风险 / 低风险 / 中风险 / 高风险is_proxyboolean是否代理 IPproxy_probabilitynumber代理概率0-100mobile_ratenumber移动网络概率百分比real_ratenumber真实用户概率百分比常见错误与处理错误场景HTTP 状态码code处理建议IP 格式非法40040001校验 IP 格式后再请求未携带 token 且超出调用次数限制40140101检查是否欠费添加 Authorization 头请求频率超限3 QPS42942901在客户端实现退避重试主备用源均不可用50350301等待一段时间后重试降级使用本地 IP 库缓存请求参数错误40040002参照文档确认参数名和类型工程化注意事项1. 缓存策略街道级数据的时效性较高通常 1-3 个月变化建议对同一 IP 的查询结果做短时间缓存如 1 小时减少 API 调用。可以使用 Redis 或内存缓存键为ip:{ip}。2. 降级处理接口本身有数据源降级但业务侧也应准备兜底策略。例如当 API 连续失败时可以回退到本地 IP 库如 GeoLite2获取城市级信息保证核心功能不中断。3. 异步与并发控制QPS 限制为 3/s若需要批量查询例如 100 个 IP应在客户端控制并发数使用信号量或队列限制每次并发请求不超过 3 个。import asyncio import aiohttp async def bounded_query(sem, ip): async with sem: async with aiohttp.ClientSession() as session: async with session.get(https://v1.apizero.cn/api/ip-pro, params{ip: ip}) as resp: return await resp.json() async def batch_query(ips): sem asyncio.Semaphore(3) # 最多3个并发 tasks [bounded_query(sem, ip) for ip in ips] return await asyncio.gather(*tasks)4. 监控与告警将接口响应时间、成功率、source为secondary的占比作为监控指标。若secondary比例突然升高说明主源可能出现问题应通知运维排查。参考文档官方文档页https://apizero.cn/aidocs/ip-pro原始接口文档https://apizero.cn/aidocs/ip-pro/raw.md