健康气象预警系统

🌡️ 科学计算体感温度

一、项目简介

这是一个基于NOAA算法的体感温度计算系统,能够:

  • 实时获取天气数据(温度/湿度/风速/紫外线)
  • 计算精确的体感温度(包含热指数和风寒指数)
  • 提供5级健康风险预警(从极端危险到安全)
  • 支持中英文双语输出

应用场景
✅ 户外活动安全评估
✅ 气象健康研究
✅ 智能家居环境控制
✅ 公共卫生预警


二、环境配置与安装

# 基础环境(Python 3.8+)
pip install requests

# 可选扩展
pip install matplotlib  # 数据可视化
pip install pandas     # 数据分析

三、代码实现

#!/usr/bin/python
# -*- coding: utf-8 -*-
# @Users: LiMu
# @Files:somatosensory.py
# @Times: 2025/7/17
# @Software:PyCharm

import requests
from datetime import datetime


class WeatherCalculator:
    def __init__(self):
        self.base_url = "https://api.open-meteo.com/v1/forecast"  # 使用实时预报接口

    def get_historical_weather(self, city_name, date):
        """获取天气数据(包含紫外线强度假设)"""
        try:
            city_coords = {
                "北京": (39.9042, 116.4074),
                "上海": (31.2304, 121.4737),
                "广州": (23.1291, 113.2644),
                "深圳": (22.5431, 114.0579),
                "成都": (30.5728, 104.0668)
            }
            lat, lon = city_coords.get(city_name, (None, None))
            if not lat or not lon:
                raise ValueError(f"不支持的城市: {city_name}")

            params = {
                "latitude": lat,
                "longitude": lon,
                "hourly": "temperature_2m,relative_humidity_2m,wind_speed_10m",
                "timezone": "auto",
                "forecast_days": 1
            }

            response = requests.get(self.base_url, params=params, timeout=10)
            data = response.json()

            hourly_data = data.get("hourly", {})
            if not hourly_data:
                raise ValueError("无有效天气数据")

            current_hour = datetime.now().hour
            return {
                'city': city_name,
                'date': date.strftime('%Y-%m-%d'),
                'temp': hourly_data["temperature_2m"][current_hour],
                'humidity': hourly_data["relative_humidity_2m"][current_hour],
                'wind_speed': hourly_data["wind_speed_10m"][current_hour] * 3.6,
                'uv_index': 10  # 假设强烈紫外线(实际API可添加uv_index参数)
            }

        except Exception as e:
            print(f"天气数据获取失败: {e}")
            return None

    @staticmethod
    def calculate_feels_like(temp_c, humidity, wind_kmh, uv_index=0):
        """改进版体感温度计算(NOAA热指数 + 风寒指数 + 紫外线修正)"""
        # 高温高湿环境使用NOAA热指数
        if temp_c >= 27 and humidity >= 40:
            temp_f = temp_c * 9 / 5 + 32
            hi_f = (
                    -42.379 + 2.04901523 * temp_f + 10.14333127 * humidity
                    - 0.22475541 * temp_f * humidity - 6.83783e-3 * temp_f ** 2
                    - 5.481717e-2 * humidity ** 2 + 1.22874e-3 * temp_f ** 2 * humidity
                    + 8.5282e-4 * temp_f * humidity ** 2 - 1.99e-6 * temp_f ** 2 * humidity ** 2
            )
            feels_like = (hi_f - 32) * 5 / 9

            # 强风修正(高温时低风速增加闷热感)
            if wind_kmh < 5:
                feels_like += 2
            feels_like = min(feels_like, temp_c + 15)  # 限制最大偏差

        # 低温环境使用风寒指数
        elif temp_c <= 10 and wind_kmh >= 4.8:
            wc = 13.12 + 0.6215 * temp_c - 11.37 * (wind_kmh ** 0.16) + 0.3965 * temp_c * (wind_kmh ** 0.16)
            feels_like = min(wc, temp_c)

        else:
            feels_like = temp_c

        # 紫外线修正(假设uv_index 0-15)
        if uv_index >= 8:  # 强阳光
            feels_like += max(1, 0.3 * uv_index)  # 每级紫外线增加0.3℃

        return round(feels_like, 1)

    @staticmethod
    def get_health_impact(feels_like):
        """健康风险等级(根据中国气象局标准优化)"""
        if feels_like >= 45:
            return "🔥 极端危险", "中暑风险极高,立即避暑!"
        elif feels_like >= 39:
            return "⚠️ 危险", "易引发热射病,避免外出!"
        elif feels_like >= 32:
            return "☀️ 高风险", "可能热衰竭,减少户外活动。"
        elif feels_like >= 27:
            return "🌞 注意", "部分人群可能不适。"
        elif feels_like <= -20:
            return "❄️ 极端危险", "30分钟可冻伤致命!"
        elif feels_like <= -10:
            return "⚠️ 危险", "低温症风险高。"
        elif feels_like <= 0:
            return "☃️ 高风险", "需保暖防寒。"
        else:
            return "✅ 安全", "适宜活动。"


if __name__ == "__main__":
    calculator = WeatherCalculator()
    weather_data = calculator.get_historical_weather("成都", datetime.now())

    if weather_data:
        feels_like = calculator.calculate_feels_like(
            temp_c=weather_data['temp'],
            humidity=weather_data['humidity'],
            wind_kmh=weather_data['wind_speed'],
            uv_index=weather_data.get('uv_index', 0)
        )
        risk_level, risk_tip = calculator.get_health_impact(feels_like)

        print("\n体感温度健康风险评估")
        print("=" * 50)
        print(f"城市: {weather_data['city']}")
        print(f"日期: {weather_data['date']}")
        print(f"- 实测气温: {weather_data['temp']}℃")
        print(f"- 相对湿度: {weather_data['humidity']}%")
        print(f"- 风速: {weather_data['wind_speed']:.1f}km/h")
        print(f"- 紫外线指数: {weather_data.get('uv_index', 'N/A')}")
        print("-" * 50)
        print(f"→ 计算体感温度: {feels_like}℃")
        print(f"→ 健康风险: {risk_level}")
        print(f"→ 风险提示: {risk_tip}")

    else:
        print("数据获取失败,请检查网络或API。")

    # 极端案例测试
    print("\n[极端案例测试]")
    test_cases = [
        (37, 80, 2, 12),  # 成都高温高湿+强紫外线
        (50, 90, 5, 10),  # 极端高温
        (-25, 30, 20, 0)  # 极端低温
    ]
    for temp, hum, wind, uv in test_cases:
        fl = calculator.calculate_feels_like(temp, hum, wind, uv)
        level, tip = calculator.get_health_impact(fl)
        print(f"{temp}℃/{hum}%/{wind}km/h/UV{uv} → 体感{fl}℃ → {level}: {tip}")

四、代码实现

4.1、基本语法

calculator = WeatherCalculator()
data = calculator.get_weather("上海")
if data:
    feels_like = calculator.calculate_feels_like(
        temp_c=data['temp'],
        humidity=data['humidity'],
        wind_kmh=data['wind_speed']
    )

4.2、典型输出

D:\Python38\python.exe E:\TestTools\somatosensory.py 

体感温度健康风险评估
==================================================
城市: 成都
日期: 2025-07-17
- 实测气温: 37.1℃
- 相对湿度: 47%
- 风速: 14.4km/h
- 紫外线指数: 10
--------------------------------------------------
→ 计算体感温度: 47.5℃
→ 健康风险: 🔥 极端危险
→ 风险提示: 中暑风险极高,立即避暑!

[极端案例测试]
37℃/80%/2km/h/UV12 → 体感55.6℃ → 🔥 极端危险: 中暑风险极高,立即避暑!
50℃/90%/5km/h/UV10 → 体感68.0℃ → 🔥 极端危险: 中暑风险极高,立即避暑!
-25℃/30%/20km/h/UV0 → 体感-36.8℃ → ❄️ 极端危险: 30分钟可冻伤致命!

进程已结束,退出代码为 0

五、扩展建议

5.1、数据可视化

import matplotlib.pyplot as plt
days = [1,2,3,4,5]
temps = [28,32,38,35,30]
plt.plot(days, temps)
plt.title('温度变化趋势')
plt.show()

5.2、微信预警机器人

import wechatwork
def send_alert(message):
    wechatwork.send(text=message)

六、注意事项

6.1、API限制:

  • ·Open-Meteo免费版限60次/分钟

  • ·商业项目建议购买紫外线API

6.2、精度说明:

  • ·湿度对体感温度影响±3℃

  • ·强阳光环境下建议手动+2~5℃

6.3、健康提示:

  • ·老年人/儿童建议按计算值+2℃预防

  • ·高温天气每小时补水500ml

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容