Skip to content

IP 归属地解析

说明

src/common/utils/ip2region.py 基于 ip2region 离线数据库,提供 IP 地址到省市区的归属地查询能力,无需网络请求。src/common/utils/helpers.py 中的 detect_osdetect_browser 提供 User-Agent 解析。

核心接口

get_ip_location — 获取归属地文本

python
from common.utils.ip2region import get_ip_location

location = get_ip_location("114.114.114.114")
# 返回: "中国 江苏省 南京市"

location = get_ip_location("8.8.8.8")
# 返回: "United States California"

location = get_ip_location("10.0.0.1")
# 返回: "内网IP"

get_ip_region — 获取完整区域信息

python
from common.utils.ip2region import get_ip_region

info = get_ip_region("114.114.114.114")
# 返回: {"country": "中国", "province": "江苏省", "city": "南京市", "isp": "南京信风", "country_code": "CN"}

UA 解析

位于 src/common/utils/helpers.py

python
from common.utils.helpers import detect_os, detect_browser

# 解析操作系统
os_name = detect_os("Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...")
# 返回: "Windows 10.0"

# 解析浏览器
browser_name = detect_browser("Mozilla/5.0 ... Chrome/120.0.0.0 ...")
# 返回: "Chrome 120.0"

应用场景

操作日志记录

python
# src/common/middleware/operation_log.py
ip = get_ip_location(handler.request.remote_ip)
os_name = detect_os(ua)
browser_name = detect_browser(ua)

登录日志记录

python
# src/common/middleware/login_log.py
ip = get_ip_location(handler.request.remote_ip)
os_name = detect_os(ua)
browser_name = detect_browser(ua)

预热机制

ip2region.xdb 文件约 10MB,首次查询时加载。应用启动时预热避免首次请求延迟:

python
# src/bootstrap.py
from common.utils.ip2region import preload
preload()  # 预加载 xdb 文件到内存

降级策略

异常场景降级行为
xdb 文件不存在返回 "未知"
xdb 加载失败返回 "未知"
畸形 IP 地址返回 "未知"
内网/保留地址返回 "内网IP"

所有查询接口均采用 fail-open 降级策略,查询失败绝不向上抛异常,保证日志落库不受影响。

xdb 数据库更新

ip2region.xdb 离线数据库需要定期更新以覆盖新增的 IP 段:

bash
# 1. 下载最新 xdb 文件
# GitHub: https://github.com/lionsoul2014/ip2region/tree/master/data
# 将 ip2region.xdb 放到 static/ 目录下

# 2. 重启应用即可生效(启动时自动加载)
poetry run python app.py --port=8041

数据库格式

xdb 是 ip2region 的二进制索引格式,约 10MB,支持微秒级查询。文件路径在 src/common/utils/ip2region.py 中配置。

完整日志记录示例

操作日志和登录日志中记录完整的客户端信息:

python
from common.utils.ip2region import get_ip_location
from common.utils.helpers import detect_os, detect_browser

# 获取客户端信息
ip = handler.request.remote_ip
ua = handler.request.headers.get("User-Agent", "")
location = get_ip_location(ip)
os_name = detect_os(ua)
browser_name = detect_browser(ua)

# 记录到日志
log_data = {
    "ip": ip,                    # "114.114.114.114"
    "ip_location": location,     # "中国 江苏省 南京市"
    "os": os_name,               # "Windows 10.0"
    "browser": browser_name,     # "Chrome 120.0"
}

总结

IP 归属地解析基于 ip2region 离线数据库,零网络依赖。提供 get_ip_location(文本)和 get_ip_region(结构化)两个查询接口,配合 detect_os / detect_browser 为操作日志和登录日志提供完整的客户端身份信息。xdb 文件需定期更新以覆盖新增 IP 段。

小蚂蚁云团队 · 提供技术支持