China Weather

👤 Bingo 📦 v1.0.3 ⭐ 4.3 ⬇️ 798 下載
🏠 生活服務 免費

📖 技能介紹


name: china-weather description: 中國天氣查詢工具。Use when user wants to check weather for Chinese cities. Supports current weather, forecast, air quality, life index with rich data and beautiful formatting. Free APIs with fallback strategy. 天氣查詢、天氣預報、空氣質量。 version: 1.0.3 license: MIT-0 metadata: {"openclaw": {"emoji": "🌤️", "requires": {"bins": ["curl", "python3"], "env": []}}}


China Weather

中國天氣查詢工具,支援即時天氣、天氣預報、空氣質量、生活指數,提供豐富的資料和精美的排版輸出。

Features

  • 🌤️ 即時天氣: 當前天氣狀況、溫度、溼度、風向
  • 📅 天氣預報: 7天/15天天氣預報
  • 🌫️ 空氣質量: AQI指數、PM2.5、PM10
  • 🧥 生活指數: 穿衣、紫外線、運動、洗車指數
  • 🔄 API降級: 多個免費API自動切換
  • 🎨 精美排版: 專業格式輸出
  • 🌍 多語言: 中英文支援

Trigger Conditions

7w4.net小蔥技能。

  • "查天氣" / "Check weather"
  • "明天天氣怎麼樣" / "What's the weather tomorrow"
  • "北京天氣" / "Beijing weather"
  • "空氣質量" / "Air quality"
  • "天氣預報" / "Weather forecast"
  • "china-weather"

API Strategy (介面策略)

認證方式說明

API 認證方式 免費額度 配置要求
wttr.in 無需認證 無限制 ❌ 無需任何配置
和風天氣 API Host + Key 1000次/天 ✅ 需要API_HOST + API_KEY
OpenWeatherMap API Key 1000次/天 ✅ 需要API_KEY + 繫結信用卡
心知天氣 API Key 無限制 ✅ 需要API_KEY

推薦:優先使用wttr.in(無需任何配置,免費無限制)

降級策略

# 優先順序:無需配置 → 需要配置
API_CHAIN = [
    {"name": "wttr", "requires_key": False},      # 無需任何配置
    {"name": "qweather", "requires_key": True},    # 需要API Host + Key
    {"name": "openweathermap", "requires_key": True} # 需要Key + 信用卡
]

和風天氣配置說明(重要)

和風天氣從2026年起不再支援公共API地址,必須使用專屬API Host:

# 環境變數配置
export QWEATHER_API_HOST="你的API_HOST"  # 如:abc1234xyz.def.qweatherapi.com
export QWEATHER_API_KEY="你的API_KEY"

# 正確的API呼叫
curl "https://${QWEATHER_API_HOST}/v7/weather/now?location=101010100&key=${QWEATHER_API_KEY}"

注意:響應使用gzip壓縮,需要新增--compressed引數或在程式碼中處理

降級策略

API_CHAIN = [
    {"name": "qweather", "priority": 1, "fallback": True},
    {"name": "seniverse", "priority": 2, "fallback": True},
    {"name": "openweathermap", "priority": 3, "fallback": True},
    {"name": "wttr", "priority": 4, "fallback": False}
]

def get_weather_with_fallback(city):
    """Try APIs in priority order, fallback on failure"""
    for api in API_CHAIN:
        try:
            result = call_api(api["name"], city)
            if result:
                return result
        except Exception as e:
            if api["fallback"]:
                continue
            else:
                raise
    return None

Step 1: Install Dependencies

pip install requests

Step 2: Weather Query Script

python3 << 'PYEOF'
import os
import requests
import json
from datetime import datetime

class WeatherService:
    def __init__(self):
        self.apis = {
            'qweather': QWeatherAPI(),
            'seniverse': SeniverseAPI(),
            'openweathermap': OpenWeatherMapAPI(),
            'wttr': WttrAPI()
        }

    def get_weather(self, city, days=7):
        """Get weather with fallback strategy"""
        for name, api in self.apis.items():
            try:
                result = api.get_weather(city, days)
                if result:
                    result['source'] = name
                    return result
            except Exception as e:
                print(f"⚠️ {name} failed: {e}")
                continue
        return None

    def format_weather(self, data, lang='zh'):
        """Format weather data beautifully"""
        if lang == 'zh':
            return self._format_chinese(data)
        else:
            return self._format_english(data)

    def _format_chinese(self, data):
        """Chinese format output"""
        output = []
        output.append(f"┌{'─'*50}┐")
        output.append(f"│  🌤️ {data['city']}天氣預報")
        output.append(f"└{'─'*50}┘")
        output.append("")

        # 當前天氣
        output.append(f"📍 當前天氣")
        output.append(f"├─ 🌡️ 溫度: {data['current']['temp']}°C (體感 {data['current']['feels_like']}°C)")
        output.append(f"├─ 🌤️ 天氣: {data['current']['weather']}")
        output.append(f"├─ 💧 溼度: {data['current']['humidity']}%")
        output.append(f"├─ 🌬️ 風向: {data['current']['wind_dir']} {data['current']['wind_speed']}km/h")
        output.append(f"└─ 👁️ 能見度: {data['current']['visibility']}km")
        output.append("")

        # 空氣質量
        if 'aqi' in data:
            output.append(f"🌫️ 空氣質量")
            aqi = data['aqi']
            aqi_level = self._get_aqi_level(aqi['value'])
            output.append(f"├─ AQI: {aqi['value']} ({aqi_level})")
            output.append(f"├─ PM2.5: {aqi.get('pm25', 'N/A')}μg/m³")
            output.append(f"├─ PM10: {aqi.get('pm10', 'N/A')}μg/m³")
            output.append(f"└─ 首要汙染物: {aqi.get('primary', 'N/A')}")
            output.append("")

        # 未來預報
        output.append(f"📅 未來預報")
        for day in data.get('forecast', [])[:7]:
            output.append(f"├─ {day['date']}: {day['weather']} {day['temp_min']}~{day['temp_max']}°C")
        output.append("")

        # 生活指數
        if 'indices' in data:
            output.append(f"🧥 生活指數")
            for idx in data['indices'][:4]:
                output.append(f"├─ {idx['name']}: {idx['level']}")

        return '\n'.join(output)

    def _format_english(self, data):
        """English format output"""
        output = []
        output.append(f"┌{'─'*50}┐")
        output.append(f"│  🌤️ {data['city']} Weather Forecast")
        output.append(f"└{'─'*50}┘")
        output.append("")

        # Current weather
        output.append(f"📍 Current Weather")
        output.append(f"├─ 🌡️ Temperature: {data['current']['temp']}°C (Feels like {data['current']['feels_like']}°C)")
        output.append(f"├─ 🌤️ Weather: {data['current']['weather']}")
        output.append(f"├─ 💧 Humidity: {data['current']['humidity']}%")
        output.append(f"├─ 🌬️ Wind: {data['current']['wind_dir']} {data['current']['wind_speed']}km/h")
        output.append(f"└─ 👁️ Visibility: {data['current']['visibility']}km")
        output.append("")

        # Air quality
        if 'aqi' in data:
            output.append(f"🌫️ Air Quality")
            aqi = data['aqi']
            aqi_level = self._get_aqi_level(aqi['value'])
            output.append(f"├─ AQI: {aqi['value']} ({aqi_level})")
            output.append(f"├─ PM2.5: {aqi.get('pm25', 'N/A')}μg/m³")
            output.append(f"├─ PM10: {aqi.get('pm10', 'N/A')}μg/m³")
            output.append(f"└─ Primary: {aqi.get('primary', 'N/A')}")
            output.append("")

        # Forecast
        output.append(f"📅 Forecast")
        for day in data.get('forecast', [])[:7]:
            output.append(f"├─ {day['date']}: {day['weather']} {day['temp_min']}~{day['temp_max']}°C")
        output.append("")

        return '\n'.join(output)

    def _get_aqi_level(self, aqi):
        """Get AQI level description"""
        if aqi <= 50:
            return "優 🟢"
        elif aqi <= 100:
            return "良 🟡"
        elif aqi <= 150:
            return "輕度汙染 🟠"
        elif aqi <= 200:
            return "中度汙染 🔴"
        elif aqi <= 300:
            return "重度汙染 🟣"
        else:
            return "嚴重汙染 🟤"

class WttrAPI:
    """wttr.in - Free, no API key required"""

    def get_weather(self, city, days=7):
        url = f"https://wttr.in/{city}?format=j1"
        response = requests.get(url, timeout=10)
        data = response.json()

        current = data['current_condition'][0]

        result = {
            'city': city,
            'current': {
                'temp': current['temp_C'],
                'feels_like': current['FeelsLikeC'],
                'weather': current['lang_zh'][0]['value'] if 'lang_zh' in current else current['weatherDesc'][0]['value'],
                'humidity': current['humidity'],
                'wind_dir': current['winddir16Point'],
                'wind_speed': current['windspeedKmph'],
                'visibility': current['visibility']
            },
            'forecast': []
        }

        for day in data['weather'][:days]:
            result['forecast'].append({
                'date': day['date'],
                'weather': day['hourly'][4]['weatherDesc'][0]['value'],
                'temp_min': day['mintempC'],
                'temp_max': day['maxtempC']
            })

        return result

class QWeatherAPI:
    """和風天氣 - 需要API Host + Key"""

    def __init__(self):
        self.api_key = os.environ.get('QWEATHER_API_KEY', '')
        self.api_host = os.environ.get('QWEATHER_API_HOST', '')
        # 預設使用GeoAPI端點
        self.geo_url = f"https://{self.api_host}/geo/v2" if self.api_host else ''
        self.weather_url = f"https://{self.api_host}/v7" if self.api_host else ''

    def get_weather(self, city, days=7):
        if not self.api_key or not self.api_host:
            return None

        # Get city ID
        city_id = self._get_city_id(city)
        if not city_id:
            return None

        # Get current weather (with gzip support)
        url = f"{self.weather_url}/weather/now?location={city_id}&key={self.api_key}"
        response = requests.get(url, timeout=10, headers={'Accept-Encoding': 'gzip'})
        response.encoding = 'utf-8'

        try:
            current_data = response.json()
        except:
            return None

        if current_data.get('code') != '200':
            return None

        now = current_data['now']

        result = {
            'city': city,
            'current': {
                'temp': now['temp'],
                'feels_like': now['feelsLike'],
                'weather': now['text'],
                'humidity': now['humidity'],
                'wind_dir': now['windDir'],
                'wind_speed': now['windSpeed'],
                'visibility': now['vis']
            },
            'forecast': self._get_forecast(city_id, days)
        }

        # Get AQI
        aqi = self._get_aqi(city_id)
        if aqi:
            result['aqi'] = aqi

        return result

    def _get_city_id(self, city):
        """Get city ID from city name"""
        url = f"{self.geo_url}/city/lookup?location={city}&key={self.api_key}"
        response = requests.get(url, timeout=10, headers={'Accept-Encoding': 'gzip'})
        try:
            data = response.json()
            if data.get('code') == '200' and data.get('location'):
                return data['location'][0]['id']
        except:
            pass
        return None

    def _get_forecast(self, city_id, days):
        """Get weather forecast"""
        url = f"{self.base_url}/weather/7d?location={city_id}&key={self.api_key}"
        response = requests.get(url, timeout=10)
        data = response.json()

        forecast = []
        for day in data.get('daily', [])[:days]:
            forecast.append({
                'date': day['fxDate'],
                'weather': day['textDay'],
                'temp_min': day['tempMin'],
                'temp_max': day['tempMax']
            })
        return forecast

    def _get_aqi(self, city_id):
        """Get air quality index"""
        url = f"{self.base_url}/air/now?location={city_id}&key={self.api_key}"
        response = requests.get(url, timeout=10)
        data = response.json()

        if data.get('code') == '200':
            air = data['now']
            return {
                'value': int(air['aqi']),
                'pm25': air.get('pm2p5'),
                'pm10': air.get('pm10'),
                'primary': air.get('primary')
            }
        return None

# Example usage
service = WeatherService()

# Query weather
data = service.get_weather('Beijing')
if data:
    # Format output
    output = service.format_weather(data, lang='zh')
    print(output)
else:
    print("❌ 無法獲取天氣資料")
PYEOF

API Configuration (介面配置)

和風天氣 (推薦)

# 註冊: https://dev.qweather.com
# 免費額度: 1000次/天
export QWEATHER_API_KEY="your_key_here"

OpenWeatherMap

# 註冊: https://openweathermap.org/api
# 免費額度: 1000次/天
export OPENWEATHER_API_KEY="your_key_here"

心知天氣

# 註冊: https://www.seniverse.com
# 免費額度: 無限制(基礎資料)
export SENIVERSE_API_KEY="your_key_here"

wttr.in (無需API Key)

# 直接使用,無需註冊
curl "wttr.in/Beijing?format=j1"

Data Fields (資料欄位)

Current Weather (即時天氣)

欄位 說明 單位
temp 溫度 °C
feels_like 體感溫度 °C
weather 天氣狀況 文字
humidity 溼度 %
wind_dir 風向 方位
wind_speed 風速 km/h
visibility 能見度 km
pressure 氣壓 hPa

Air Quality (空氣質量)

欄位 說明 單位
aqi 空氣質量指數 0-500
pm25 PM2.5濃度 μg/m³
pm10 PM10濃度 μg/m³
so2 二氧化硫 μg/m³
no2 二氧化氮 μg/m³
co 一氧化碳 mg/m³
o3 臭氧 μg/m³

Life Index (生活指數)

指數 說明 等級
穿衣指數 建議穿著 寒冷/涼爽/舒適/炎熱
紫外線指數 UV強度 弱/中等/強/很強
運動指數 適合運動程度 適宜/較適宜/不宜
洗車指數 適合洗車程度 適宜/較適宜/不宜
感冒指數 感冒風險 低/中/高

Security Notes

  • ✅ No data uploaded to external servers (except API calls)
  • ✅ Open source dependencies
  • ✅ Multiple API fallback
  • ⚠️ API keys should be kept secure

Notes

  • wttr.in 免費無需API Key,功能較簡單
  • 和風天氣資料最豐富,需要註冊
  • 多API降級策略確保服務可用性
  • 支援中英文天氣描述

🤖 AI 評測

這是一款功能豐富的中文天氣查詢工具,支援即時天氣、預報、空氣質量和生活指數查詢。最大優點是操作簡單,無需配置即可查詢天氣,如果主服務不可用還會自動切換備用介面。介面排版清晰美觀,中英文都能用。但部分高階功能(如空氣質量、生活指數)需要註冊第三方賬號才能完全使用,整體文件和實際程式碼存在一些小不一致,對普通使用者來說可能造成困惑。總的來說基礎功能實用可靠,適合日常天氣查詢使用。

📊 多維度評分

適應性4.3
規範性4.1
有效性4.3
可靠性4.2
可信度5

📁 包含檔案 (3 個)

📄 LICENSE.txt 901 B
📄 SKILL.md 14.8 KB
📄 _meta.json 136 B