22# -*- coding: utf-8 -*-
33import httpx
44
5- from asgiref .sync import sync_to_async
65from fastapi import Request
76from ip2loc import XdbSearcher
87from user_agents import parse
98
109from backend .common .dataclasses import IpInfo , UserAgentInfo
1110from backend .common .log import log
1211from backend .core .conf import settings
13- from backend .core .path_conf import IP2REGION_XDB
12+ from backend .core .path_conf import STATIC_DIR
1413from backend .database .redis import redis_client
1514
1615
@@ -55,7 +54,10 @@ async def get_location_online(ip: str, user_agent: str) -> dict | None:
5554 return None
5655
5756
58- @sync_to_async
57+ # 离线 IP 搜索器单例(数据将缓存到内存,缓存大小取决于 IP 数据文件大小)
58+ __xdb_searcher = XdbSearcher (contentBuff = XdbSearcher .loadContentFromFile (dbfile = STATIC_DIR / 'ip2region_v4.xdb' ))
59+
60+
5961def get_location_offline (ip : str ) -> dict | None :
6062 """
6163 离线获取 IP 地址属地,无法保证准确率,100% 可用
@@ -64,15 +66,12 @@ def get_location_offline(ip: str) -> dict | None:
6466 :return:
6567 """
6668 try :
67- cb = XdbSearcher .loadContentFromFile (dbfile = IP2REGION_XDB )
68- searcher = XdbSearcher (contentBuff = cb )
69- data = searcher .search (ip )
70- searcher .close ()
69+ data = __xdb_searcher .search (ip )
7170 data = data .split ('|' )
7271 return {
7372 'country' : data [0 ] if data [0 ] != '0' else None ,
74- 'regionName' : data [2 ] if data [2 ] != '0' else None ,
75- 'city' : data [3 ] if data [3 ] != '0' else None ,
73+ 'regionName' : data [1 ] if data [1 ] != '0' else None ,
74+ 'city' : data [2 ] if data [2 ] != '0' else None ,
7675 }
7776 except Exception as e :
7877 log .error (f'离线获取 IP 地址属地失败,错误信息:{ e } ' )
@@ -97,7 +96,7 @@ async def parse_ip_info(request: Request) -> IpInfo:
9796 if settings .IP_LOCATION_PARSE == 'online' :
9897 location_info = await get_location_online (ip , request .headers .get ('User-Agent' ))
9998 elif settings .IP_LOCATION_PARSE == 'offline' :
100- location_info = await get_location_offline (ip )
99+ location_info = get_location_offline (ip )
101100
102101 if location_info :
103102 country = location_info .get ('country' )
0 commit comments