IPWeatherObject.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. # @Author : Rocky
  2. # @File : IPWeatherObject.py
  3. # @Time : 2023/8/16 8:56
  4. import datetime
  5. import geoip2.webservice
  6. import requests
  7. from Model.models import IPAddr
  8. from Object.RedisObject import RedisObject
  9. from Service.CommonService import CommonService
  10. class IPQuery:
  11. """
  12. 阿里云IP地址查询
  13. https://market.aliyun.com/products/57002003/cmapi021970.html?spm=5176.2020520132.recommend-card.dbottom-suggestion.33e17218GYjWDt#sku=yuncode15970000020
  14. """
  15. def __init__(self, ip):
  16. self.appcode = 'd7d63b34b1d54214be446608a57ff0a2'
  17. self.host = 'https://c2ba.api.huachen.cn'
  18. self.path = '/ip'
  19. self.district = '' # 区
  20. self.city = '' # 市
  21. self.region = '' # 省/州
  22. self.country_id = ''
  23. param = 'ip=' + ip
  24. url = self.host + self.path + '?' + param
  25. # 获取ip的区级和城市信息
  26. headers = {'Authorization': 'APPCODE ' + self.appcode}
  27. res = requests.get(url=url, headers=headers)
  28. if res.status_code == 200:
  29. # 反序列化响应数据
  30. res_data = eval(res.content.decode('utf-8'))
  31. if res_data['ret'] == 200:
  32. district = res_data['data']['district']
  33. city = res_data['data']['city']
  34. region = res_data['data']['region']
  35. country_id = res_data['data']['country_id']
  36. # 国内城市数据不为空字符,拼上'市'字
  37. if country_id == 'CN' and city != '':
  38. city += '市'
  39. # ip地址信息存表或更新
  40. ip_addr_qs = IPAddr.objects.filter(ip=ip, is_geoip2=False)
  41. if ip_addr_qs.exists():
  42. ip_addr_qs.update(district=district, city=city, region=region, country_code=country_id)
  43. else:
  44. IPAddr.objects.create(ip=ip, district=district, city=city, region=region, country_code=country_id)
  45. # 确定天气城市
  46. if district != '':
  47. self.district = district
  48. elif city != '':
  49. self.district = city
  50. self.country_id = country_id
  51. class WeatherInfo:
  52. """
  53. 阿里云墨迹天气服务
  54. https://market.aliyun.com/products/57096001/cmapi013828.html?spm=5176.2020520132.101.19.2b8f7218NuiGPd#sku=yuncode782800000
  55. """
  56. def __init__(self, city_id):
  57. self.appcode = 'd7d63b34b1d54214be446608a57ff0a2'
  58. self.headers = {'Authorization': 'APPCODE ' + self.appcode,
  59. 'Content-Type': 'application/x-www-form-urlencoded'}
  60. self.city_id = city_id
  61. def get_city_weather(self):
  62. url = "https://aliv18.data.moji.com/whapi/json/alicityweather/condition" # 获取实时天气
  63. data = {'cityId': self.city_id}
  64. response = requests.post(url, headers=self.headers, data=data, verify=False)
  65. if response.status_code == 200:
  66. result = response.json()
  67. if result['code'] == 0:
  68. # 返回温湿度
  69. return result['data']['condition']['temp'], result['data']['condition']['humidity']
  70. return None, None
  71. def get_city_24_weather(self):
  72. url = 'https://aliv18.data.moji.com/whapi/json/alicityweather/forecast24hours' # 获取城市24小时天气
  73. data = {'cityId': self.city_id}
  74. response = requests.post(url, headers=self.headers, data=data, verify=False)
  75. if response.status_code == 200:
  76. result = response.json()
  77. if result['code'] == 0:
  78. # 返回天气列表
  79. return result['data']['hourly']
  80. return None
  81. class GeoIP2:
  82. """
  83. MaxMind GeoIP2查询国外ip
  84. 同时保存ip信息
  85. https://www.maxmind.com/
  86. """
  87. def __init__(self, ip):
  88. self.account_id = 938644
  89. self.license_key = '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'
  90. self.license_key_sandbox = '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'
  91. try:
  92. with geoip2.webservice.Client(self.account_id, self.license_key) as client:
  93. # You can also use `client.city` or `client.insights`
  94. # `client.insights` is not available to GeoLite2 users
  95. response = client.city(ip)
  96. # 经纬度精确到小数点两位
  97. lat = round(response.location.latitude, 2)
  98. lon = round(response.location.longitude, 2)
  99. city = response.city.names['zh-CN']
  100. region = response.subdivisions[0].names['zh-CN']
  101. country_code = response.country.iso_code
  102. # 保存ip信息
  103. ip_addr_data = {
  104. 'ip': ip,
  105. 'lat': lat,
  106. 'lon': lon,
  107. 'city': city,
  108. 'region': region,
  109. 'country_code': country_code,
  110. 'is_geoip2': True
  111. }
  112. IPAddr.objects.create(**ip_addr_data)
  113. except Exception as e:
  114. print('error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  115. class OpenWeatherMap:
  116. """
  117. OpenWeatherMap查询国外天气服务
  118. https://openweathermap.org/
  119. """
  120. def __init__(self, lat, lon):
  121. self.appid = '7a6cd7dfeb034ededa451ed575788857'
  122. self.lat = lat # 纬度
  123. self.lon = lon # 经度
  124. def get_weather(self):
  125. """
  126. 从缓存查询天气数据
  127. 或者查询当前天气,并缓存数据
  128. @return: temp, humidity
  129. """
  130. # 查询缓存数据
  131. today = datetime.datetime.today()
  132. now_time = datetime.datetime(today.year, today.month, today.day, today.hour)
  133. time_stamp = CommonService.str_to_timestamp(now_time.strftime('%Y-%m-%d %H:%M:%S'))
  134. key = 'weather:lat:{}_lon:{}_time_stamp:{}'.format(self.lat, self.lon, time_stamp)
  135. redis_obj = RedisObject()
  136. weather = redis_obj.get_data(key)
  137. if weather:
  138. temp, humidity = weather.split('/')
  139. else:
  140. temp, humidity = self.get_current_weather()
  141. if temp is not None and humidity is not None:
  142. key = 'weather:lat:{}_lon:{}_time_stamp:{}'.format(self.lat, self.lon, time_stamp)
  143. redis_obj.set_ex_data(key, '{}/{}'.format(temp, humidity), 3600)
  144. return temp, humidity
  145. def get_current_weather(self):
  146. """
  147. 根据经纬度获取当前天气
  148. @return: temp, humidity
  149. """
  150. url = 'https://api.openweathermap.org/data/2.5/weather'
  151. params = {
  152. 'lat': self.lat,
  153. 'lon': self.lon,
  154. 'appid': self.appid,
  155. 'units': 'metric' # 公制单位,温度单位:摄氏度
  156. }
  157. res = requests.get(url=url, params=params, timeout=10)
  158. if res.status_code != 200:
  159. return None, None
  160. res_data = eval(res.text)
  161. if res_data['cod'] != 200:
  162. return None, None
  163. temp = res_data['main']['temp']
  164. humidity = res_data['main']['humidity']
  165. return temp, humidity