| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 | # @Author    : Rocky# @File      : IPWeatherObject.py# @Time      : 2023/8/16 8:56import datetimeimport geoip2.webserviceimport requestsfrom Model.models import IPAddr, OpenWeatherMapCallCountfrom Object.RedisObject import RedisObjectfrom Service.CommonService import CommonServicefrom Ansjer.config import LOGGERclass IPQuery:    """    阿里云IP地址查询    https://market.aliyun.com/products/57002003/cmapi021970.html?spm=5176.2020520132.recommend-card.dbottom-suggestion.33e17218GYjWDt#sku=yuncode15970000020    """    def __init__(self, ip):        self.appcode = 'd7d63b34b1d54214be446608a57ff0a2'        self.host = 'https://c2ba.api.huachen.cn'        self.path = '/ip'        self.district = ''  # 区        self.city = ''  # 市        self.region = ''  # 省/州        self.country_id = ''        param = 'ip=' + ip        url = self.host + self.path + '?' + param        # 获取ip的区级和城市信息        headers = {'Authorization': 'APPCODE ' + self.appcode}        res = requests.get(url=url, headers=headers)        if res.status_code == 200:            # 反序列化响应数据            res_data = eval(res.content.decode('utf-8'))            if res_data['ret'] == 200:                district = res_data['data']['district']                city = res_data['data']['city']                region = res_data['data']['region']                country_id = res_data['data']['country_id']                # 国内城市数据不为空字符,拼上'市'字                if country_id == 'CN' and city != '':                    city += '市'                # ip地址信息存表或更新                ip_addr_qs = IPAddr.objects.filter(ip=ip, is_geoip2=False)                if ip_addr_qs.exists():                    ip_addr_qs.update(district=district, city=city, region=region, country_code=country_id)                else:                    IPAddr.objects.create(ip=ip, district=district, city=city, region=region, country_code=country_id)                # 确定天气城市                if district != '':                    self.district = district                elif city != '':                    self.district = city                self.country_id = country_idclass WeatherInfo:    """    阿里云墨迹天气服务    https://market.aliyun.com/products/57096001/cmapi013828.html?spm=5176.2020520132.101.19.2b8f7218NuiGPd#sku=yuncode782800000    """    def __init__(self, city_id):        self.appcode = 'd7d63b34b1d54214be446608a57ff0a2'        self.headers = {'Authorization': 'APPCODE ' + self.appcode,                        'Content-Type': 'application/x-www-form-urlencoded'}        self.city_id = city_id    def get_city_weather(self):        url = "https://aliv18.data.moji.com/whapi/json/alicityweather/condition"  # 获取实时天气        data = {'cityId': self.city_id}        response = requests.post(url, headers=self.headers, data=data, verify=False)        if response.status_code == 200:            result = response.json()            if result['code'] == 0:                # 返回温湿度                return result['data']['condition']['temp'], result['data']['condition']['humidity']        return None, None    def get_city_24_weather(self):        url = 'https://aliv18.data.moji.com/whapi/json/alicityweather/forecast24hours'  # 获取城市24小时天气        data = {'cityId': self.city_id}        response = requests.post(url, headers=self.headers, data=data, verify=False)        if response.status_code == 200:            result = response.json()            if result['code'] == 0:                # 返回天气列表                return result['data']['hourly']        return Noneclass GeoIP2:    """    MaxMind GeoIP2查询国外ip    同时保存ip信息    https://www.maxmind.com/    """    def __init__(self, ip):        self.account_id = 938644        self.license_key = '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'        self.license_key_sandbox = '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'        try:            with geoip2.webservice.Client(self.account_id, self.license_key) as client:                # You can also use `client.city` or `client.insights`                # `client.insights` is not available to GeoLite2 users                response = client.city(ip)                # 经纬度精确到小数点两位                lat = round(response.location.latitude, 2)                lon = round(response.location.longitude, 2)                # 获取中文或英文城市名,省/州                city = ''                city_names = response.city.names                city_cn = city_names.get('zh-CN')                if city_cn:                    city = city_cn                elif city_names.get('en'):                    city = city_names['en']                region = ''                subdivisions_names = response.subdivisions[0].names                region_cn = subdivisions_names.get('zh-CN')                if region_cn:                    region = region_cn                elif subdivisions_names.get('en'):                    region = subdivisions_names['en']                country_code = response.country.iso_code                # 保存ip信息                ip_addr_data = {                    'ip': ip,                    'lat': lat,                    'lon': lon,                    'city': city,                    'region': region,                    'country_code': country_code,                    'is_geoip2': True                }                IPAddr.objects.create(**ip_addr_data)        except Exception as e:            LOGGER.info('GeoIP2解析ip异常:error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))class OpenWeatherMap:    """    OpenWeatherMap查询国外天气服务    https://openweathermap.org/    """    def __init__(self, lat, lon):        self.appid = '7a6cd7dfeb034ededa451ed575788857'        self.lat = lat  # 纬度        self.lon = lon  # 经度    def get_weather(self):        """        从缓存查询天气数据        或者查询当前天气,并缓存数据        @return: temp, humidity        """        # 查询缓存数据        today = datetime.datetime.today()        now_time = datetime.datetime(today.year, today.month, today.day, today.hour)        str_time = now_time.strftime('%Y-%m-%d %H:%M:%S')        time_stamp = CommonService.str_to_timestamp(str_time)        key = 'weather:lat:{}_lon:{}_time_stamp:{}'.format(self.lat, self.lon, time_stamp)        redis_obj = RedisObject()        weather = redis_obj.get_data(key)        if weather:            temp, humidity = weather.split('/')        else:            temp, humidity = self.get_current_weather(str_time[:7])            if temp is not None and humidity is not None:                key = 'weather:lat:{}_lon:{}_time_stamp:{}'.format(self.lat, self.lon, time_stamp)                redis_obj.set_ex_data(key, '{}/{}'.format(temp, humidity), 3600)        return temp, humidity    def get_current_weather(self, month):        """        根据经纬度获取当前天气        @param month: 年月份        @return: temp, humidity        """        url = 'https://api.openweathermap.org/data/2.5/weather'        params = {            'lat': self.lat,            'lon': self.lon,            'appid': self.appid,            'units': 'metric'   # 公制单位,温度单位:摄氏度        }        res = requests.get(url=url, params=params, timeout=10)        # 记录调用次数        open_weather_map_call_count_qs = OpenWeatherMapCallCount.objects.filter(month=month).values('count')        if not open_weather_map_call_count_qs.exists():            OpenWeatherMapCallCount.objects.create(month=month)        else:            count = open_weather_map_call_count_qs[0]['count'] + 1            open_weather_map_call_count_qs.update(count=count)        if res.status_code != 200:            return None, None        res_data = eval(res.text)        if res_data['cod'] != 200:            return None, None        temp = int(res_data['main']['temp'])        humidity = int(res_data['main']['humidity'])        return temp, humidity
 |