fix: MMDB中文路径解决方案 + 聚类优先使用最新GeoIP数据

- geoip.py: maxminddb C库不支持Windows中文路径,复制MMDB到ASCII临时目录
- views.py: _cluster_network 优先用 geoip_lookup()(MMDB) 而非上传时缓存(text)
- 效果: IP地理坐标从 ~55城市粗定位 → 全球百万级精确城市定位

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
TianXuan Developer
2026-07-23 23:59:27 +08:00
parent 2e93bcad2e
commit 8ba99292b7
2 changed files with 19 additions and 4 deletions
+16 -2
View File
@@ -12,6 +12,7 @@ import bisect
import gzip
import logging
import shutil
import tempfile
from pathlib import Path
from typing import Optional
@@ -107,11 +108,24 @@ def _load_mmdb() -> None:
try:
import maxminddb
_mmdb_city = maxminddb.open_database(city_path)
# maxminddb C extension cannot handle non-ASCII Windows paths.
# Workaround: copy MMDB files to a temp dir with ASCII-only path.
_tmp_dir = Path(tempfile.gettempdir()) / 'tianxuan_geoip'
_tmp_dir.mkdir(parents=True, exist_ok=True)
_tmp_city = _tmp_dir / 'GeoLite2-City.mmdb'
if not _tmp_city.exists() or _tmp_city.stat().st_size != city_path.stat().st_size:
logger.info('[GEOIP] copying MMDB to ASCII-safe temp dir …')
shutil.copy2(city_path, _tmp_city)
_mmdb_city = maxminddb.open_database(str(_tmp_city))
logger.info('[GEOIP] loaded GeoLite2-City.mmdb (MMDB format)')
if asn_path.exists():
_mmdb_asn = maxminddb.open_database(asn_path)
_tmp_asn = _tmp_dir / 'GeoLite2-ASN.mmdb'
if not _tmp_asn.exists() or _tmp_asn.stat().st_size != asn_path.stat().st_size:
shutil.copy2(asn_path, _tmp_asn)
_mmdb_asn = maxminddb.open_database(str(_tmp_asn))
logger.info('[GEOIP] loaded GeoLite2-ASN.mmdb (ISP/ORG)')
except Exception as e:
logger.warning('[GEOIP] failed to open MMDB: %s', e)
+3 -2
View File
@@ -792,11 +792,12 @@ def _cluster_network(entry: dict, df: pl.DataFrame, meta: dict,
logger.info('Network clustering: %d unique IPs from %d records', n_nodes, len(df))
# ── 2. GeoIP 解析所有 IP ───────────────────────────────────────────
# MMDB优先(高精度),upload时的geo_cache兜底(低精度文本回退)
node_geo = {} # ip → {lat, lon, city, country, isp, org}
for ip in unique_ips:
info = geo_cache.get(ip)
info = geoip_lookup(ip) # 优先用当前加载的MMDB数据库
if not info:
info = geoip_lookup(ip)
info = geo_cache.get(ip) # 回退到上传时的缓存
if info:
node_geo[ip] = info