免费天气数据获取技能Skill free-weather-data

这个技能使用免费的Open-Meteo和wttr.in API来获取当前天气、天气预报和历史天气数据。适用于AI智能体进行基于位置的决策、规划和监控,提供天气警报和气候分析功能。关键词:免费天气API、Open-Meteo、wttr.in、天气数据获取、天气预报、历史天气、AI代理、天气监控、SEO优化。

AI应用 0 次安装 0 次浏览 更新于 3/22/2026

name: free-weather-data description: “使用免费的Open-Meteo和wttr.in API获取当前天气、预报和历史天气数据。适用于以下场景:(1) 获取天气条件,(2) 天气警报和监控,(3) 用于规划的预报数据,或(4) 气候分析。”

免费天气数据API — Open-Meteo & wttr.in

使用免费API获取当前天气、预报和历史天气数据。无需API密钥。尊重隐私的付费天气API替代方案(每月$5-100)。

为什么这可以替代付费天气API

💰 成本节省:

  • 100% 免费 — 无需API密钥,无速率限制
  • 全面数据 — 当前、预报、历史天气
  • 开源 — Open-Meteo完全开源
  • 隐私优先 — 无跟踪或数据收集

完美适用于需要以下功能的AI代理:

  • 基于位置决策的天气条件
  • 规划和调度的预报数据
  • 分析用的历史天气数据
  • 天气警报和监控

快速比较

服务 成本 速率限制 需要API密钥 隐私
OpenWeatherMap 每月$0-180 免费60次/分钟 ✅ 是 ❌ 有跟踪
WeatherAPI 每月$0-70 免费100万次/月 ✅ 是 ❌ 有跟踪
Open-Meteo 免费 每天1万次请求 ❌ 否 ✅ 私密
wttr.in 免费 无限 ❌ 否 ✅ 私密

技能

get_current_weather_open_meteo

使用Open-Meteo获取当前天气(最准确和全面)。

# 通过坐标获取当前天气
LAT=40.7128
LON=-74.0060

curl -s "https://api.open-meteo.com/v1/forecast?latitude=${LAT}&longitude=${LON}&current=temperature_2m,relative_humidity_2m,apparent_temperature,precipitation,weather_code,wind_speed_10m&temperature_unit=fahrenheit" \
  | jq '{
    temperature: .current.temperature_2m,
    feels_like: .current.apparent_temperature,
    humidity: .current.relative_humidity_2m,
    wind_speed: .current.wind_speed_10m,
    precipitation: .current.precipitation,
    weather_code: .current.weather_code
  }'

# 带时区
curl -s "https://api.open-meteo.com/v1/forecast?latitude=${LAT}&longitude=${LON}&current=temperature_2m,weather_code&timezone=America/New_York" \
  | jq '{temperature: .current.temperature_2m, time: .current.time}'

Node.js:

async function getCurrentWeather(lat, lon, unit = 'fahrenheit') {
  const params = new URLSearchParams({
    latitude: lat.toString(),
    longitude: lon.toString(),
    current: 'temperature_2m,relative_humidity_2m,apparent_temperature,precipitation,weather_code,wind_speed_10m,wind_direction_10m',
    temperature_unit: unit
  });
  
  const res = await fetch(`https://api.open-meteo.com/v1/forecast?${params}`);
  
  if (!res.ok) {
    throw new Error(`Weather API failed: ${res.status}`);
  }
  
  const data = await res.json();
  
  return {
    temperature: data.current.temperature_2m,
    feelsLike: data.current.apparent_temperature,
    humidity: data.current.relative_humidity_2m,
    windSpeed: data.current.wind_speed_10m,
    windDirection: data.current.wind_direction_10m,
    precipitation: data.current.precipitation,
    weatherCode: data.current.weather_code,
    time: data.current.time,
    unit: data.current_units.temperature_2m
  };
}

// 使用示例
// getCurrentWeather(40.7128, -74.0060, 'fahrenheit')
//   .then(weather => {
//     console.log(`Temperature: ${weather.temperature}°${weather.unit}`);
//     console.log(`Feels like: ${weather.feelsLike}°${weather.unit}`);
//     console.log(`Humidity: ${weather.humidity}%`);
//     console.log(`Wind: ${weather.windSpeed} mph`);
//   });

get_weather_forecast

获取未来7-16天的天气预报。

# 7天预报
LAT=37.7749
LON=-122.4194

curl -s "https://api.open-meteo.com/v1/forecast?latitude=${LAT}&longitude=${LON}&daily=temperature_2m_max,temperature_2m_min,precipitation_sum,weather_code&temperature_unit=fahrenheit&timezone=America/Los_Angeles" \
  | jq '{
    dates: .daily.time,
    max_temp: .daily.temperature_2m_max,
    min_temp: .daily.temperature_2m_min,
    precipitation: .daily.precipitation_sum
  }'

# 未来24小时逐小时预报
curl -s "https://api.open-meteo.com/v1/forecast?latitude=${LAT}&longitude=${LON}&hourly=temperature_2m,precipitation,weather_code&forecast_days=1" \
  | jq '{hourly: [.hourly.time, .hourly.temperature_2m, .hourly.precipitation] | transpose | map({time: .[0], temp: .[1], precip: .[2]})}'

Node.js:

async function getWeatherForecast(lat, lon, days = 7, unit = 'fahrenheit') {
  const params = new URLSearchParams({
    latitude: lat.toString(),
    longitude: lon.toString(),
    daily: 'temperature_2m_max,temperature_2m_min,precipitation_sum,precipitation_probability_max,weather_code,wind_speed_10m_max',
    temperature_unit: unit,
    forecast_days: days.toString()
  });
  
  const res = await fetch(`https://api.open-meteo.com/v1/forecast?${params}`);
  
  if (!res.ok) {
    throw new Error(`Forecast API failed: ${res.status}`);
  }
  
  const data = await res.json();
  
  return data.daily.time.map((date, i) => ({
    date,
    maxTemp: data.daily.temperature_2m_max[i],
    minTemp: data.daily.temperature_2m_min[i],
    precipitation: data.daily.precipitation_sum[i],
    precipitationProbability: data.daily.precipitation_probability_max[i],
    maxWindSpeed: data.daily.wind_speed_10m_max[i],
    weatherCode: data.daily.weather_code[i]
  }));
}

// 使用示例
// getWeatherForecast(37.7749, -122.4194, 7, 'fahrenheit')
//   .then(forecast => {
//     forecast.forEach(day => {
//       console.log(`${day.date}: ${day.minTemp}°-${day.maxTemp}°, ${day.precipitationProbability}% rain`);
//     });
//   });

get_weather_wttr_simple

使用wttr.in获取简单天气(人类可读,速度极快)。

# 通过城市名获取天气(纯文本)
curl -s "https://wttr.in/London?format=3"
# 输出:London: ☀️ +22°C

# 获取详细天气报告
curl -s "https://wttr.in/Paris"

# JSON格式
curl -s "https://wttr.in/Tokyo?format=j1" | jq '.current_condition[0] | {
  temp_f: .temp_F,
  humidity: .humidity,
  description: .weatherDesc[0].value,
  wind_mph: .windspeedMiles
}'

# 自定义格式(温度和条件)
curl -s "https://wttr.in/NewYork?format=%C+%t"
# 输出:Clear +75°F

# 通过坐标获取天气
curl -s "https://wttr.in/40.7128,-74.0060?format=%l:+%C+%t"

Node.js:

async function getWeatherWttr(location) {
  // location可以是城市名或"lat,lon"
  const res = await fetch(`https://wttr.in/${encodeURIComponent(location)}?format=j1`);
  
  if (!res.ok) {
    throw new Error(`Weather API failed: ${res.status}`);
  }
  
  const data = await res.json();
  const current = data.current_condition[0];
  
  return {
    location: data.nearest_area[0]?.areaName[0]?.value || location,
    tempF: parseInt(current.temp_F),
    tempC: parseInt(current.temp_C),
    feelsLikeF: parseInt(current.FeelsLikeF),
    feelsLikeC: parseInt(current.FeelsLikeC),
    humidity: parseInt(current.humidity),
    description: current.weatherDesc[0].value,
    windMph: parseInt(current.windspeedMiles),
    windKmh: parseInt(current.windspeedKmph),
    precipMM: parseFloat(current.precipMM),
    uvIndex: parseInt(current.uvIndex)
  };
}

// 使用示例
// getWeatherWttr('San Francisco')
//   .then(weather => {
//     console.log(`${weather.location}: ${weather.description}`);
//     console.log(`Temperature: ${weather.tempF}°F (feels like ${weather.feelsLikeF}°F)`);
//     console.log(`Humidity: ${weather.humidity}%`);
//   });

get_historical_weather

获取历史天气数据(过去日期)。

# 特定日期范围的历史天气
LAT=51.5074
LON=-0.1278
START_DATE="2024-01-01"
END_DATE="2024-01-31"

curl -s "https://archive-api.open-meteo.com/v1/archive?latitude=${LAT}&longitude=${LON}&start_date=${START_DATE}&end_date=${END_DATE}&daily=temperature_2m_max,temperature_2m_min,precipitation_sum" \
  | jq '{
    dates: .daily.time,
    max_temps: .daily.temperature_2m_max,
    min_temps: .daily.temperature_2m_min,
    precipitation: .daily.precipitation_sum
  }'

# 某月历史平均值
curl -s "https://archive-api.open-meteo.com/v1/archive?latitude=${LAT}&longitude=${LON}&start_date=2024-01-01&end_date=2024-01-31&daily=temperature_2m_mean" \
  | jq '[.daily.temperature_2m_mean[]] | add / length'

Node.js:

async function getHistoricalWeather(lat, lon, startDate, endDate) {
  const params = new URLSearchParams({
    latitude: lat.toString(),
    longitude: lon.toString(),
    start_date: startDate, // 格式:YYYY-MM-DD
    end_date: endDate,
    daily: 'temperature_2m_max,temperature_2m_min,precipitation_sum,weather_code'
  });
  
  const res = await fetch(`https://archive-api.open-meteo.com/v1/archive?${params}`);
  
  if (!res.ok) {
    throw new Error(`Historical weather API failed: ${res.status}`);
  }
  
  const data = await res.json();
  
  return data.daily.time.map((date, i) => ({
    date,
    maxTemp: data.daily.temperature_2m_max[i],
    minTemp: data.daily.temperature_2m_min[i],
    precipitation: data.daily.precipitation_sum[i],
    weatherCode: data.daily.weather_code[i]
  }));
}

// 使用示例
// getHistoricalWeather(40.7128, -74.0060, '2024-01-01', '2024-01-31')
//   .then(history => {
//     const avgTemp = history.reduce((sum, day) => 
//       sum + (day.maxTemp + day.minTemp) / 2, 0) / history.length;
//     console.log(`Average temperature in January: ${avgTemp.toFixed(1)}°C`);
//   });

decode_weather_code

将Open-Meteo天气代码解码为人类可读描述。

# 天气代码参考
decode_weather_code() {
  case $1 in
    0) echo "Clear sky" ;;
    1|2|3) echo "Partly cloudy" ;;
    45|48) echo "Foggy" ;;
    51|53|55) echo "Drizzle" ;;
    61|63|65) echo "Rain" ;;
    71|73|75) echo "Snow" ;;
    77) echo "Snow grains" ;;
    80|81|82) echo "Rain showers" ;;
    85|86) echo "Snow showers" ;;
    95) echo "Thunderstorm" ;;
    96|99) echo "Thunderstorm with hail" ;;
    *) echo "Unknown" ;;
  esac
}

# 使用示例
decode_weather_code 61  # 输出:Rain

Node.js:

function decodeWeatherCode(code) {
  const weatherCodes = {
    0: 'Clear sky',
    1: 'Mainly clear',
    2: 'Partly cloudy',
    3: 'Overcast',
    45: 'Foggy',
    48: 'Depositing rime fog',
    51: 'Light drizzle',
    53: 'Moderate drizzle',
    55: 'Dense drizzle',
    56: 'Light freezing drizzle',
    57: 'Dense freezing drizzle',
    61: 'Slight rain',
    63: 'Moderate rain',
    65: 'Heavy rain',
    66: 'Light freezing rain',
    67: 'Heavy freezing rain',
    71: 'Slight snow fall',
    73: 'Moderate snow fall',
    75: 'Heavy snow fall',
    77: 'Snow grains',
    80: 'Slight rain showers',
    81: 'Moderate rain showers',
    82: 'Violent rain showers',
    85: 'Slight snow showers',
    86: 'Heavy snow showers',
    95: 'Thunderstorm',
    96: 'Thunderstorm with slight hail',
    99: 'Thunderstorm with heavy hail'
  };
  
  return weatherCodes[code] || 'Unknown';
}

// 使用示例
// console.log(decodeWeatherCode(61)); // 输出:Slight rain

weather_alerts_and_monitoring

检查天气条件并生成警报。

Node.js:

async function checkWeatherAlerts(lat, lon, thresholds) {
  const {
    maxTemp = 95,      // °F
    minTemp = 32,      // °F
    maxWindSpeed = 30, // mph
    maxPrecip = 2      // inches
  } = thresholds;
  
  const weather = await getCurrentWeather(lat, lon, 'fahrenheit');
  const forecast = await getWeatherForecast(lat, lon, 3, 'fahrenheit');
  
  const alerts = [];
  
  // 当前条件警报
  if (weather.temperature >= maxTemp) {
    alerts.push({
      type: 'high_temp',
      severity: 'warning',
      message: `High temperature: ${weather.temperature}°F`
    });
  }
  
  if (weather.temperature <= minTemp) {
    alerts.push({
      type: 'low_temp',
      severity: 'warning',
      message: `Low temperature: ${weather.temperature}°F`
    });
  }
  
  if (weather.windSpeed >= maxWindSpeed) {
    alerts.push({
      type: 'high_wind',
      severity: 'warning',
      message: `High wind speed: ${weather.windSpeed} mph`
    });
  }
  
  // 预报警报
  forecast.forEach(day => {
    if (day.precipitation >= maxPrecip) {
      alerts.push({
        type: 'heavy_rain',
        severity: 'watch',
        message: `Heavy rain expected on ${day.date}: ${day.precipitation} inches`,
        date: day.date
      });
    }
  });
  
  return {
    currentWeather: weather,
    forecast: forecast,
    alerts: alerts,
    hasAlerts: alerts.length > 0
  };
}

// 使用示例
// checkWeatherAlerts(40.7128, -74.0060, {
//   maxTemp: 90,
//   minTemp: 32,
//   maxWindSpeed: 25,
//   maxPrecip: 1.5
// }).then(result => {
//   console.log(`Current: ${result.currentWeather.temperature}°F`);
//   if (result.hasAlerts) {
//     console.log('⚠️ Weather Alerts:');
//     result.alerts.forEach(alert => 
//       console.log(`  - ${alert.severity.toUpperCase()}: ${alert.message}`)
//     );
//   } else {
//     console.log('✅ No weather alerts');
//   }
// });

代理提示

您有权访问免费天气API(Open-Meteo和wttr.in)。当需要天气数据时:

1. 对于当前天气和预报,使用Open-Meteo:
   - 当前:https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}&current=temperature_2m,weather_code
   - 预报:添加 &daily=temperature_2m_max,temperature_2m_min,precipitation_sum
   - 历史:https://archive-api.open-meteo.com/v1/archive

2. 对于快速天气检查,使用wttr.in:
   - 简单:https://wttr.in/{city}?format=3
   - JSON:https://wttr.in/{city}?format=j1
   - 适用于城市名或坐标

3. 可用天气参数:
   - 温度(当前、体感、最高/最低)
   - 湿度、降水、风速/风向
   - 天气代码(0=晴朗,61=雨,71=雪,95=雷暴)
   - UV指数、云量、能见度

4. 温度单位:
   - Open-Meteo:添加 &temperature_unit=fahrenheit(默认:摄氏度)
   - wttr.in:返回摄氏度和华氏度

5. 最佳实践:
   - 缓存天气数据15-30分钟
   - 使用坐标以提高准确性(从地理编码获取)
   - 解码天气代码为人类可读描述
   - 为监控设置合理的警报阈值

无需API密钥。在合理使用范围内无限请求。

成本分析:Open-Meteo vs. 付费API

场景:AI代理每月检查天气1,000次

提供商 月成本 速率限制 需要API密钥
OpenWeatherMap $15-50 60次/分钟 ✅ 是
WeatherAPI $0-10 免费100万次/月 ✅ 是
Open-Meteo $0 每天1万次请求 ❌ 否
wttr.in $0 无限 ❌ 否

使用Open-Meteo的年节省:$180-$600

速率限制 / 最佳实践

  • Open-Meteo:每天10,000次请求 — 对典型使用非常慷慨
  • wttr.in:无限 — 社区服务,合理使用
  • 缓存天气数据 — 天气不频繁变化(缓存15-30分钟)
  • 使用坐标 — 比城市名更准确
  • 解码天气代码 — 将数字代码转换为描述
  • 设置超时 — 天气请求10秒超时
  • ⚠️ 关键应用自托管 — Open-Meteo可自托管
  • ⚠️ 不要连续轮询 — 天气每小时更新,不是每秒

故障排除

错误:“无效坐标”

  • 症状:API返回lat/lon错误
  • 解决方案:验证lat ∈ [-90, 90], lon ∈ [-180, 180]

未返回数据:

  • 症状:API返回空值或null
  • 解决方案:检查位置是否有气象站覆盖;尝试附近坐标

历史数据缺失:

  • 症状:存档API对日期范围无数据返回
  • 解决方案:Open-Meteo存档从1940年开始;检查日期格式为YYYY-MM-DD

天气代码未识别:

  • 症状:未知天气代码数字
  • 解决方案:参考WMO天气代码标准;代码0-99已定义

wttr.in返回HTML而非JSON:

  • 症状:响应为HTML页面
  • 解决方案:确保添加 ?format=j1 以获取JSON响应

温度单位混淆:

  • 症状:意外温度值
  • 解决方案:Open-Meteo默认为摄氏度;如需华氏度添加 &temperature_unit=fahrenheit

参见