""" Script voor het ophalen van een HEEL JAAR aan historische weerdata voor Amersfoort """ import requests import sqlite3 import pandas as pd from datetime import datetime import time # ===== CONFIGURATIE ===== LOCATIE = "Amersfoort" LATITUDE = 52.15 LONGITUDE = 5.39 # Kies je jaar(en) hier! START_JAAR = 2025 START_MAAND = 1 START_DAG = 1 EIND_JAAR = 2025 EIND_MAAND = 11 EIND_DAG = 11 DATABASE_NAAM = f"weer_amersfoort_{START_JAAR}.db" # Open-Meteo kan maximaal 1 jaar per request, dus we splitsen het op indien nodig # ======================== def setup_database(db_naam): """Maak database en tabellen aan""" conn = sqlite3.connect(db_naam) cursor = conn.cursor() cursor.execute(''' CREATE TABLE IF NOT EXISTS weer_dagelijks ( id INTEGER PRIMARY KEY AUTOINCREMENT, datum DATE UNIQUE NOT NULL, locatie TEXT NOT NULL, latitude REAL, longitude REAL, temp_max REAL, temp_min REAL, temp_gem REAL, neerslag REAL, wind_max REAL, wind_gem REAL, wind_richting REAL, luchtvochtigheid_gem REAL, bewolking_gem REAL, zonuren REAL, toegevoegd_op TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ''') cursor.execute(''' CREATE TABLE IF NOT EXISTS weer_uurlijks ( id INTEGER PRIMARY KEY AUTOINCREMENT, datum_tijd DATETIME UNIQUE NOT NULL, locatie TEXT NOT NULL, temperatuur REAL, gevoelstemperatuur REAL, neerslag REAL, wind_snelheid REAL, wind_richting REAL, luchtvochtigheid INTEGER, bewolking INTEGER, luchtdruk REAL, toegevoegd_op TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ''') conn.commit() return conn def haal_weerdata_op(start_date, end_date, ophaal_uurlijks=True): """ Haal weerdata op via Open-Meteo API Args: start_date: datetime object voor startdatum end_date: datetime object voor einddatum ophaal_uurlijks: Ook uurlijkse data ophalen (kan veel data zijn!) """ url = "https://archive-api.open-meteo.com/v1/archive" # Uitgebreide parameters voor een volledig beeld params = { "latitude": LATITUDE, "longitude": LONGITUDE, "start_date": start_date.strftime("%Y-%m-%d"), "end_date": end_date.strftime("%Y-%m-%d"), "daily": [ "temperature_2m_max", "temperature_2m_min", "temperature_2m_mean", "apparent_temperature_max", "apparent_temperature_min", "precipitation_sum", "rain_sum", "snowfall_sum", "precipitation_hours", "wind_speed_10m_max", "wind_speed_10m_mean", "wind_direction_10m_dominant", "sunshine_duration" ], "timezone": "Europe/Amsterdam" } if ophaal_uurlijks: params["hourly"] = [ "temperature_2m", "apparent_temperature", "precipitation", "rain", "snowfall", "wind_speed_10m", "wind_direction_10m", "relative_humidity_2m", "cloud_cover", "surface_pressure" ] print(f"\n📡 Data ophalen voor periode: {start_date.date()} tot {end_date.date()}") print(f" Aantal dagen: {(end_date - start_date).days + 1}") try: response = requests.get(url, params=params, timeout=60) response.raise_for_status() print(f"✅ Data succesvol opgehaald!") return response.json() except requests.exceptions.RequestException as e: print(f"❌ Fout bij ophalen data: {e}") return None def sla_dagelijkse_data_op(conn, data): """Sla dagelijkse data op in database""" if not data or 'daily' not in data: return 0 daily = data['daily'] cursor = conn.cursor() records_toegevoegd = 0 for i in range(len(daily['time'])): try: cursor.execute(''' INSERT OR REPLACE INTO weer_dagelijks (datum, locatie, latitude, longitude, temp_max, temp_min, temp_gem, neerslag, wind_max, wind_gem, wind_richting, zonuren) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ''', ( daily['time'][i], LOCATIE, LATITUDE, LONGITUDE, daily['temperature_2m_max'][i], daily['temperature_2m_min'][i], daily['temperature_2m_mean'][i], daily['precipitation_sum'][i], daily['wind_speed_10m_max'][i], daily['wind_speed_10m_mean'][i], daily['wind_direction_10m_dominant'][i], daily['sunshine_duration'][i] / 3600 if daily['sunshine_duration'][i] else None # Convert seconds to hours )) records_toegevoegd += 1 except sqlite3.IntegrityError: pass conn.commit() return records_toegevoegd def sla_uurlijkse_data_op(conn, data): """Sla uurlijkse data op in database""" if not data or 'hourly' not in data: return 0 hourly = data['hourly'] cursor = conn.cursor() records_toegevoegd = 0 print(f" Uurlijkse records verwerken: {len(hourly['time'])} uur...") # Batch insert voor betere performance batch = [] for i in range(len(hourly['time'])): batch.append(( hourly['time'][i], LOCATIE, hourly['temperature_2m'][i], hourly['apparent_temperature'][i], hourly['precipitation'][i], hourly['wind_speed_10m'][i], hourly['wind_direction_10m'][i], hourly['relative_humidity_2m'][i], hourly['cloud_cover'][i], hourly['surface_pressure'][i] )) cursor.executemany(''' INSERT OR REPLACE INTO weer_uurlijks (datum_tijd, locatie, temperatuur, gevoelstemperatuur, neerslag, wind_snelheid, wind_richting, luchtvochtigheid, bewolking, luchtdruk) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ''', batch) conn.commit() return len(batch) def toon_statistieken(conn): """Toon statistieken van de database""" cursor = conn.cursor() cursor.execute("SELECT COUNT(*) FROM weer_dagelijks") aantal_dagen = cursor.fetchone()[0] cursor.execute("SELECT COUNT(*) FROM weer_uurlijks") aantal_uren = cursor.fetchone()[0] print("\n" + "="*70) print("DATABASE STATISTIEKEN") print("="*70) print(f"📊 Dagelijkse records: {aantal_dagen} dagen") print(f"📊 Uurlijkse records: {aantal_uren} uur") if aantal_dagen > 0: cursor.execute(""" SELECT MIN(datum) as eerste_datum, MAX(datum) as laatste_datum, ROUND(AVG(temp_max), 1) as gem_max_temp, ROUND(MAX(temp_max), 1) as hoogste_temp, ROUND(MIN(temp_min), 1) as laagste_temp, ROUND(SUM(neerslag), 1) as totale_neerslag, ROUND(AVG(wind_max), 1) as gem_wind, ROUND(SUM(zonuren), 1) as totale_zonuren FROM weer_dagelijks """) stats = cursor.fetchone() print(f"\n📅 Periode: {stats[0]} tot {stats[1]}") print(f"\n🌡️ TEMPERATUUR:") print(f" Gemiddeld max: {stats[2]}°C") print(f" Hoogste: {stats[3]}°C") print(f" Laagste: {stats[4]}°C") print(f"\n💧 NEERSLAG:") print(f" Totaal: {stats[5]} mm") print(f"\n💨 WIND:") print(f" Gemiddeld max: {stats[6]} km/h") print(f"\n☀️ ZON:") print(f" Totale zonuren: {stats[7]} uur ({stats[7]/24:.1f} dagen)") # Maandstatistieken print(f"\n📊 PER MAAND:") cursor.execute(""" SELECT strftime('%Y-%m', datum) as maand, ROUND(AVG(temp_max), 1) as gem_max, ROUND(AVG(temp_min), 1) as gem_min, ROUND(SUM(neerslag), 1) as neerslag, COUNT(CASE WHEN neerslag > 0.1 THEN 1 END) as regendagen FROM weer_dagelijks GROUP BY maand ORDER BY maand """) print(f"\n {'Maand':<10} {'Max°C':<8} {'Min°C':<8} {'Neerslag':<12} {'Regendagen':<12}") print(f" {'-'*60}") for row in cursor.fetchall(): print(f" {row[0]:<10} {row[1]:<8} {row[2]:<8} {row[3]:<12} {row[4]:<12}") print("="*70) def exporteer_naar_csv(conn, output_prefix="weer_export"): """Exporteer data naar CSV bestanden""" # Dagelijkse data df_dagelijks = pd.read_sql_query( "SELECT * FROM weer_dagelijks ORDER BY datum", conn ) csv_dag = f"{output_prefix}_dagelijks.csv" df_dagelijks.to_csv(csv_dag, index=False) print(f"✅ Dagelijkse data: {csv_dag} ({len(df_dagelijks)} records)") # Uurlijkse data (alleen als niet te groot) cursor = conn.cursor() cursor.execute("SELECT COUNT(*) FROM weer_uurlijks") aantal_uur = cursor.fetchone()[0] if aantal_uur > 0 and aantal_uur < 10000: # Max ~1 jaar uurlijks df_uurlijks = pd.read_sql_query( "SELECT * FROM weer_uurlijks ORDER BY datum_tijd", conn ) csv_uur = f"{output_prefix}_uurlijks.csv" df_uurlijks.to_csv(csv_uur, index=False) print(f"✅ Uurlijkse data: {csv_uur} ({len(df_uurlijks)} records)") elif aantal_uur > 10000: print(f"⚠️ Uurlijkse data ({aantal_uur} records) niet geëxporteerd (te groot)") def main(): """Hoofdfunctie""" print("="*70) print(f"HISTORISCHE WEERDATA VOOR {LOCATIE}") print("="*70) # Datum objecten maken start_date = datetime(START_JAAR, START_MAAND, START_DAG) end_date = datetime(EIND_JAAR, EIND_MAAND, EIND_DAG) # Check of periode niet te groot is dagen = (end_date - start_date).days + 1 if dagen > 400: antwoord = input(f"\n⚠️ Je wilt {dagen} dagen ophalen. Dit kan even duren. Doorgaan? (j/n): ") if antwoord.lower() != 'j': print("Geannuleerd.") return # Uurlijkse data vraag if dagen > 180: print(f"\n💡 TIP: Voor {dagen} dagen is dat {dagen*24} uur aan data.") ophaal_uurlijks = input(" Wil je ook uurlijkse data? Dit maakt de database groter. (j/n): ") ophaal_uurlijks = ophaal_uurlijks.lower() == 'j' else: ophaal_uurlijks = True # Setup database print(f"\n📁 Database: {DATABASE_NAAM}") conn = setup_database(DATABASE_NAAM) # Haal data op data = haal_weerdata_op(start_date, end_date, ophaal_uurlijks) if data: print("\n💾 Data opslaan in database...") # Dagelijkse data dag_records = sla_dagelijkse_data_op(conn, data) print(f"✅ {dag_records} dagelijkse records opgeslagen") # Uurlijkse data if ophaal_uurlijks: uur_records = sla_uurlijkse_data_op(conn, data) print(f"✅ {uur_records} uurlijkse records opgeslagen") # Statistieken toon_statistieken(conn) # Exporteer print(f"\n📤 Data exporteren...") exporteer_naar_csv(conn, f"amersfoort_{START_JAAR}") conn.close() print(f"\n✅ Klaar! Database opgeslagen als: {DATABASE_NAAM}") if __name__ == "__main__": print("\n💡 Open-Meteo API - Gratis historische weerdata") print(" Data beschikbaar vanaf 1940") print(" Geen API key nodig!\n") main()