From 569852a1dc96835d1425e5a509dec82a31fac928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=9F=E5=85=89-k?= <36470587+kxgx@users.noreply.github.com> Date: Sat, 8 Feb 2025 01:17:52 +0000 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20weather.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/weather.py | 127 ++++++++++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 59 deletions(-) diff --git a/bin/weather.py b/bin/weather.py index a082de6..e698d6f 100644 --- a/bin/weather.py +++ b/bin/weather.py @@ -7,83 +7,92 @@ import logging import requests from threading import Timer -white = 255 # 颜色 -black = 0 -logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s') # 设置日志级别 +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(message)s', + datefmt='%Y-%m-%d %H:%M:%S' +) def get_area_id(city_name): """从city.js中检索AREAID,无限重试直到成功""" url = "https://j.i8tq.com/weather2020/search/city.js" while True: try: - response = requests.get(url) - response.raise_for_status() # 检查请求是否成功 - city_data_text = response.text.strip().split('var city_data = ')[-1].rstrip(';') - if city_data_text: - city_data = json.loads(city_data_text) - for province, cities in city_data.items(): - for city, districts in cities.items(): - for district, info in districts.items(): - if info['NAMECN'] == city_name: - return info['AREAID'] - logging.error("城市名称 '%s' 在城市数据中未找到", city_name) - else: - logging.error("从city.js接收到的数据为空") - except (requests.RequestException, json.JSONDecodeError) as e: - logging.error("检索或解析城市数据时发生错误: %s", e) - time.sleep(180) # 重试前等待 + resp = requests.get(url, timeout=10) + resp.encoding = 'utf-8' # 显式设置编码 + city_data = json.loads(resp.text.split('=', 1)[1].rstrip(';')) + for province in city_data.values(): + for city in province.values(): + for district, info in city.items(): + if info['NAMECN'] == city_name: + return info['AREAID'] + logging.error("未找到城市: %s", city_name) + except Exception as e: + logging.error("获取城市ID失败: %s", str(e)) + time.sleep(180) def get_current_city(): - """获取当前城市名称,无限重试直到成功""" + """获取当前定位城市并去除'市'后缀""" url = "http://ip-api.com/json/?lang=zh-CN" while True: try: - response = requests.get(url) - response.raise_for_status() # 检查请求是否成功 - data = response.json() + resp = requests.get(url, timeout=10) + resp.encoding = 'utf-8' # 显式设置编码 + data = resp.json() if data['status'] == 'success': - return data['city'] - else: - logging.error("获取当前城市失败: %s", data['message']) - except (requests.RequestException, json.JSONDecodeError) as e: - logging.error("检索或解析当前城市时出现错误: %s", e) - time.sleep(180) # 重试前等待 + return data['city'].rstrip('市') + logging.error("定位失败: %s", data.get('message')) + except Exception as e: + logging.error("定位异常: %s", str(e)) + time.sleep(180) def schedule_getWeath(): - """调度 getWeath 函数每3分钟执行一次""" - getWeath() - Timer(180, schedule_getWeath).start() # 重新设置定时器 + """定时任务调度""" + try: + getWeath() + finally: + Timer(180, schedule_getWeath).start() -def getWeath(city='101060101'): +def getWeath(default_city='101060101'): + """获取天气数据核心函数""" + city_name = get_current_city() + area_id = default_city # 设置默认值 + + if city_name: + try: + area_id = get_area_id(city_name) or default_city + except Exception as e: + logging.error("获取区域ID失败: %s", str(e)) + headers = { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', 'Referer': 'https://www.weather.com.cn/' } - current_city = get_current_city() - if current_city: - area_id = get_area_id(current_city) - if area_id: - city = area_id + try: - response = requests.get(f'https://d1.weather.com.cn/sk_2d/{city}.html', headers=headers) - response.raise_for_status() # 检查请求是否成功 - response.encoding = 'utf-8' - weather_data = response.text[11:] - with open('/root/2.13-Ink-screen-clock/bin/weather.json', 'w') as fileHandle: - fileHandle.write(weather_data) - print("天气文件更新") - except requests.RequestException as e: - logging.error("获取天气数据时出现网络错误: %s", e) + resp = requests.get( + f'https://d1.weather.com.cn/sk_2d/{area_id}.html', + headers=headers, + timeout=15 + ) + resp.encoding = 'utf-8' # 关键修改:强制设置响应编码 + resp.raise_for_status() + + # 直接处理原始字节数据 + weather_data = resp.content[11:].decode('utf-8') + + # 使用utf-8编码写入文件 + with open('/root/2.13-Ink-screen-clock/bin/weather.json', 'w', encoding='utf-8') as f: + f.write(weather_data) + + logging.info("天气数据更新成功") except Exception as e: - logging.error("发生了意外错误: %s", e) + logging.error("天气更新失败: %s", str(e)) -try: - schedule_getWeath() # 开始调度天气获取函数 -except KeyboardInterrupt: - logging.info("检测到键盘中断,正在退出") -except Exception as e: - logging.error("发生了意外错误: %s", e) - exit() - -# 脚本正常结束后的清理操作 -exit() +if __name__ == "__main__": + try: + schedule_getWeath() + while True: + time.sleep(1) # 保持主线程存活 + except KeyboardInterrupt: + logging.info("程序已终止") \ No newline at end of file