mirror of
https://github.com/hanzoskill/swissweather.git
synced 2026-10-30 21:03:00 +00:00
121 lines
3.9 KiB
Python
121 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Get weather forecast for Swiss locations by postal code.
|
|
Data source: MeteoSwiss API (official Swiss government weather service)
|
|
|
|
Note: The MeteoSwiss API endpoint may change or require updates.
|
|
If this script fails, check references/api_info.md for alternative methods.
|
|
"""
|
|
import argparse
|
|
import json
|
|
import sys
|
|
|
|
try:
|
|
import requests
|
|
except ImportError:
|
|
print("Error: requests library not found. Install with: pip3 install requests", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
FORECAST_URL = "https://app-prod-ws.meteoswiss-app.ch/v1/plzDetail?plz={plz:06d}"
|
|
USER_AGENT = "android-31 ch.admin.meteoswiss-2160000"
|
|
|
|
# Weather condition mapping (from MeteoSwiss icon codes)
|
|
CONDITIONS = {
|
|
1: "☀️ Sunny",
|
|
2: "🌤️ Partly cloudy",
|
|
3: "🌤️ Partly cloudy",
|
|
4: "🌤️ Partly cloudy",
|
|
5: "☁️ Cloudy",
|
|
6: "🌧️ Rainy",
|
|
7: "🌧️ Rainy/Snowy",
|
|
8: "❄️ Snowy",
|
|
9: "🌧️ Light rain",
|
|
10: "🌨️ Rain/Snow mix",
|
|
11: "❄️ Light snow",
|
|
12: "⛈️ Thunderstorm",
|
|
13: "⛈️ Thunderstorm with rain",
|
|
101: "🌙 Clear night",
|
|
102: "🌙 Partly cloudy night",
|
|
}
|
|
|
|
|
|
def fetch_forecast(plz):
|
|
"""Fetch forecast data from MeteoSwiss API."""
|
|
try:
|
|
url = FORECAST_URL.format(plz=int(plz))
|
|
headers = {"User-Agent": USER_AGENT}
|
|
response = requests.get(url, headers=headers, timeout=10)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
except requests.RequestException as e:
|
|
print(f"Error fetching forecast: {e}", file=sys.stderr)
|
|
print("\nNote: The MeteoSwiss API may have changed.", file=sys.stderr)
|
|
print("Check references/api_info.md for alternative methods.", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
|
|
def format_forecast(data, days=3):
|
|
"""Format forecast data for display."""
|
|
if 'forecast' not in data:
|
|
print("Error: Unexpected API response format", file=sys.stderr)
|
|
return
|
|
|
|
forecast = data['forecast']
|
|
if 'dayForecast' in forecast:
|
|
daily = forecast['dayForecast'][:days]
|
|
|
|
print(f"\n{'='*60}")
|
|
print(f"Weather Forecast - {data.get('currentWeather', {}).get('location', 'Unknown')}")
|
|
print(f"{'='*60}\n")
|
|
|
|
for day in daily:
|
|
date = day.get('date', 'Unknown')
|
|
icon = day.get('icon', 0)
|
|
condition = CONDITIONS.get(icon, f"Code {icon}")
|
|
temp_max = day.get('temperatureMax', 'N/A')
|
|
temp_min = day.get('temperatureMin', 'N/A')
|
|
precip = day.get('precipitation', 'N/A')
|
|
|
|
print(f"{date}")
|
|
print(f" {condition}")
|
|
print(f" Temperature: {temp_min}°C - {temp_max}°C")
|
|
print(f" Precipitation: {precip} mm")
|
|
print()
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description='Get weather forecast for Swiss locations by postal code',
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
epilog='''
|
|
Examples:
|
|
%(prog)s 8640 # Rapperswil-Jona
|
|
%(prog)s 8001 # Zurich
|
|
%(prog)s 3000 # Bern
|
|
%(prog)s 1200 --days 7 # Geneva, 7-day forecast
|
|
%(prog)s 8640 --json # Raw JSON output
|
|
|
|
Common postal codes:
|
|
8001 - Zurich, 3000 - Bern, 1200 - Geneva, 4000 - Basel,
|
|
6900 - Lugano, 8640 - Rapperswil-Jona, 9000 - St. Gallen
|
|
'''
|
|
)
|
|
|
|
parser.add_argument('plz', type=int, help='Swiss postal code (4 or 5 digits)')
|
|
parser.add_argument('--days', '-d', type=int, default=3, help='Number of days to show (default: 3)')
|
|
parser.add_argument('--json', '-j', action='store_true', help='Output raw JSON')
|
|
|
|
args = parser.parse_args()
|
|
|
|
# Fetch forecast
|
|
data = fetch_forecast(args.plz)
|
|
|
|
if args.json:
|
|
print(json.dumps(data, indent=2))
|
|
else:
|
|
format_forecast(data, args.days)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|