initial commit

This commit is contained in:
Mark Kors
2025-11-13 08:42:21 +01:00
commit 7435759eea
17 changed files with 512998 additions and 0 deletions

364
jaar_weerdata.py Normal file
View File

@@ -0,0 +1,364 @@
"""
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()