Parcourir la source

IP解析获取经纬度

zhangdongming il y a 2 mois
Parent
commit
ea387d42cf
2 fichiers modifiés avec 87 ajouts et 5 suppressions
  1. 5 5
      Controller/ShadowController.py
  2. 82 0
      Object/IPWeatherObject.py

+ 5 - 5
Controller/ShadowController.py

@@ -8,7 +8,7 @@ from Model.models import Device_Info, UidSetModel, UID_Preview, VoicePromptModel
     AiService, CountryModel, CityInformation, IPAddr, LogModel
 from Object.ETkObject import ETkObject
 from Service.CommonService import CommonService
-from Object.IPWeatherObject import IPQuery, GeoIP2
+from Object.IPWeatherObject import IPQuery, GeoIP2, Findip
 
 
 # 更新设备影子
@@ -187,8 +187,8 @@ def save_ip_info(ip, qs_dict):
     else:
         ip_addr_qs = IPAddr.objects.filter(ip=ip, is_geoip2=True)
         if not ip_addr_qs.exists():
-            GeoIP2(ip)
-
+            # GeoIP2(ip)
+            Findip(ip)
 
 def update_ip_info(ip, uid):
     """
@@ -213,8 +213,8 @@ def update_ip_info(ip, uid):
     else:
         ip_addr_qs = IPAddr.objects.filter(ip=ip, is_geoip2=True)
         if not ip_addr_qs.exists():
-            GeoIP2(ip)
-
+            # GeoIP2(ip)
+            Findip(ip)
 
 def get_district(ip):
     ip_addr_qs = IPAddr.objects.filter(ip=ip, is_geoip2=False).values('district', 'city')

+ 82 - 0
Object/IPWeatherObject.py

@@ -2,6 +2,7 @@
 # @File      : IPWeatherObject.py
 # @Time      : 2023/8/16 8:56
 import datetime
+import json
 
 import geoip2.webservice
 import requests
@@ -235,3 +236,84 @@ class OpenWeatherMap:
         temp = str(int(res_data['main']['temp']))
         humidity = str(int(res_data['main']['humidity']))
         return temp, humidity
+
+
+class Findip:
+    """
+    findip 查询国外ip
+    同时保存ip信息
+    https://www.findip.net/Main/Index
+    """
+
+    def __init__(self, ip):
+        self.token = 'bb51156441ec401caec0476864ec2b93'
+        self.ip = ip
+        self.lat = 0.0
+        self.lon = 0.0
+        self.city = ''
+        self.region = ''
+        self.country_code = ''
+
+        try:
+            # 调用findip API获取IP信息
+            self._get_ip_info()
+
+            # 保存ip信息
+            ip_addr_data = {
+                'ip': self.ip,
+                'lat': self.lat,
+                'lon': self.lon,
+                'city': self.city,
+                'region': self.region,
+                'country_code': self.country_code,
+                'is_geoip2': True  # 是否为GeoIP2解析
+            }
+            IPAddr.objects.create(**ip_addr_data)
+
+        except Exception as e:
+            LOGGER.error('FindIP解析ip异常:error_line:{}, error_msg:{}'.format(
+                e.__traceback__.tb_lineno, repr(e)
+            ))
+
+    def _get_ip_info(self):
+        """调用findip API并解析返回结果"""
+        try:
+            # 构建API请求URL
+            url = f"https://api.findip.net/{self.ip}/?token={self.token}"
+            response = requests.get(url, timeout=10)
+
+            # 检查请求是否成功
+            if response.status_code == 200:
+                data = response.json()
+                self._parse_response(data)
+            else:
+                raise Exception(f"API请求失败,状态码: {response.status_code}")
+
+        except requests.RequestException as re:
+            raise Exception(f"请求异常: {str(re)}")
+        except json.JSONDecodeError as jde:
+            raise Exception(f"JSON解析异常: {str(jde)}")
+
+    def _parse_response(self, data):
+        """解析API返回的JSON数据并提取所需字段"""
+        # 提取经纬度并保留两位小数
+        if 'location' in data and data['location']:
+            self.lat = round(data['location'].get('latitude', 0.0), 2)
+            self.lon = round(data['location'].get('longitude', 0.0), 2)
+
+        # 提取国家代码
+        if 'country' in data and data['country'] and 'iso_code' in data['country']:
+            self.country_code = data['country']['iso_code']
+
+        # 提取城市名称(优先中文,其次英文)
+        if 'city' in data and data['city'] and 'names' in data['city']:
+            names = data['city']['names']
+            self.city = names.get('zh-CN', names.get('en', ''))
+
+        # 提取地区名称(优先中文,其次英文)
+        if 'subdivisions' in data and data['subdivisions']:
+            # 取第一个细分区域(通常是省/州级别)
+            first_subdivision = data['subdivisions'][0]
+            if 'names' in first_subdivision:
+                names = first_subdivision['names']
+                self.region = names.get('zh-CN', names.get('en', ''))