🌡️ 科学计算体感温度
一、项目简介
这是一个基于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