From 0c1ae937070909335b9cacefe79046c583349083 Mon Sep 17 00:00:00 2001 From: Clemens Berteld <clemens@berteld.com> Date: Sun, 8 Aug 2021 13:57:09 +0200 Subject: [PATCH] DB gets created if not existing DB gets filled with data --- dataacquisition/DwdAcquisition.py | 16 ++-- dataacquisition/ExportToDatabase.py | 69 +++++++++++++++++- dataacquisition/ExportToWorldShape.py | 5 +- .../pickle/stationList_germany.pickle | Bin 126687 -> 14530 bytes dataacquisition/test_ExportToDatabase.py | 2 + dataacquisition/test_feed_db.py | 66 +++++++++++++++++ 6 files changed, 148 insertions(+), 10 deletions(-) create mode 100644 dataacquisition/test_feed_db.py diff --git a/dataacquisition/DwdAcquisition.py b/dataacquisition/DwdAcquisition.py index c117712..48d1d76 100644 --- a/dataacquisition/DwdAcquisition.py +++ b/dataacquisition/DwdAcquisition.py @@ -97,6 +97,7 @@ def loadAndJoinDWDClimateFilenames(): # with open("stationList.pickle","wb") as pf: # pickle.dump(stationList, pf) + # here we have to try some interpolations for missing values def fillMissingData(annualData): months = ["Jan", "Feb", "Mrz","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"] @@ -145,6 +146,7 @@ def fillMissingData(annualData): return annualData + # load Temperatures from DWD gauges def loadTemperatureFromDWDGauges(): global climateCountry @@ -180,15 +182,16 @@ def loadTemperatureFromDWDGauges(): stationList.columns = stationList.columns.astype(str) stationList = stationList.sort_index(axis=1, ascending=False) - + + def start(): global stationList print("___ DWD Acquisition start___") loadDWDGauges() - stationList = stationList.loc[stationList['country']=="Germany"] - loadAndJoinDWDClimateFilenames() - loadTemperatureFromDWDGauges() + stationList = stationList.loc[stationList['country'] == "Germany"] + # loadAndJoinDWDClimateFilenames() + # loadTemperatureFromDWDGauges() with open("./pickle/stationList_germany.pickle", "wb") as pickleFile: pickle.dump(stationList, pickleFile) @@ -198,6 +201,7 @@ def start(): exportToDatabase.export(stationList) print("___DWD Acquisition finished___") - + + if __name__ == '__main__': - start() \ No newline at end of file + start() diff --git a/dataacquisition/ExportToDatabase.py b/dataacquisition/ExportToDatabase.py index 3bd6e1b..8b118fc 100644 --- a/dataacquisition/ExportToDatabase.py +++ b/dataacquisition/ExportToDatabase.py @@ -7,10 +7,73 @@ export the stationlist to database @author: geopeter """ +import psycopg2 +import psycopg2.extras +from psycopg2 import sql +from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT stationGPD = None + +# Connect to DB "postgres" to check for database "temperatures_berteld_morstein" +def check_for_db_existence(): + print("Checking for database existence") + with psycopg2.connect(database='postgres', user='postgres', password='postgres', host='localhost', port=5432) as connection: + with connection.cursor() as cursor: + cursor.execute("SELECT datname FROM pg_database WHERE datname LIKE 'temperatures_berteld_morstein';") + + try: + db_exists = cursor.fetchall()[0] + print('DB existing') + + except IndexError: # DB temperatures_berteld_morstein doesn't exist + print('DB not existing') + try: + create_db(connection, cursor) + create_table() + print('Successfully created database and table') + except (Exception, psycopg2.DatabaseError) as error: + print(error) + + +# Use existing connection to DB "postgres" to create DB "temperatures_berteld_morstein" +def create_db(connection, cursor): + connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) # Needs to be in AUTOCOMMIT mode for creating database + create_db_query = sql.SQL("CREATE DATABASE temperatures_berteld_morstein;") + print(create_db_query) + cursor.execute(create_db_query) + + +# Connect to DB "temperatures_berteld_morstein" to create table "temperatures" +def create_table(): + with psycopg2.connect(database='temperatures_berteld_morstein', user='postgres', password='postgres', host='localhost', port=5432) as connection: + with connection.cursor() as cursor: + query = sql.SQL("CREATE TABLE temperatures (id INTEGER, lon NUMERIC, lat NUMERIC, country TEXT);") + print(query) + cursor.execute(query) + + +def insert_data(stationList): + with psycopg2.connect(database='temperatures_berteld_morstein', user='postgres', password='postgres', host='localhost', port=5432) as connection: + with connection.cursor() as cursor: + + if len(stationList) > 0: + df_columns = list(stationList) + # create (col1,col2,...) + columns = ",".join(df_columns) + + # create VALUES('%s', '%s",...) one '%s' per column + values = "VALUES({})".format(",".join(["%s" for _ in df_columns])) + + # create INSERT INTO table (columns) VALUES('%s',...) + insert_stmt = "INSERT INTO {} ({}) {}".format('temperatures', columns, values) + + psycopg2.extras.execute_batch(cursor, insert_stmt, stationList.values) + + def export(stationList): - print("export the stationList to database") - - return stationList \ No newline at end of file + check_for_db_existence() + insert_data(stationList) + + # return stationList + diff --git a/dataacquisition/ExportToWorldShape.py b/dataacquisition/ExportToWorldShape.py index a3248a3..8d65bf4 100644 --- a/dataacquisition/ExportToWorldShape.py +++ b/dataacquisition/ExportToWorldShape.py @@ -10,6 +10,7 @@ Export the stationlist to the geopandas world shape file import numpy as np import geopandas as gpd + def buildAverageTimeseries(stationList, fromYear, toYear, name): meanAverage = [] for stationID, station in stationList.iterrows(): @@ -24,7 +25,8 @@ def buildAverageTimeseries(stationList, fromYear, toYear, name): meanAverage.append(np.NaN) stationList[name] = np.round(meanAverage,1) - + + def cleanAverageTimeseries(stationList): # determine gauges that includes both timeseries. If not delete them. @@ -35,6 +37,7 @@ def cleanAverageTimeseries(stationList): stationList.at[stationID, "m1961T1990"] = None stationList.at[stationID, "m1991T2018"] = None + def convertStationListToGPD(stationList): print("convert stationlist to GeoPandas") diff --git a/dataacquisition/pickle/stationList_germany.pickle b/dataacquisition/pickle/stationList_germany.pickle index e7c18a76be25b4cb9c2a0a9b9e4ece4695cc6e4b..cfe9b01de45901830483a9b5abc320c9e59529f1 100644 GIT binary patch literal 14530 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 BO(FmQ literal 126687 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%0Dat@=VM?#I5rymZgR_~gv^<g(0tY4efq z9y_sI|Mb#5M_>5%*S>jTS>_zd@A(goyzr9LJpUyj+R~P9{pO3$N&SiCr7cHa`o;?< zzp)_yy!*rp-}u_G<sU9Tz3J)APxl4dy(E2~|LdDKZF>H@;eY>W_}|}<|4IFqti`dH sP6#cRHa~ard*4}J`qbBtoIG;;#UtN3CjWl!TgOfw2?c`1OGn55KZY}R!2kdN diff --git a/dataacquisition/test_ExportToDatabase.py b/dataacquisition/test_ExportToDatabase.py index c31e116..3d1eec3 100644 --- a/dataacquisition/test_ExportToDatabase.py +++ b/dataacquisition/test_ExportToDatabase.py @@ -10,8 +10,10 @@ import unittest import pickle import ExportToDatabase as cut + class TestExportToDatabase(unittest.TestCase): stationList = None + def testExport(self): global stationList with open("./pickle/stationList_germany.pickle", "rb") as pickleFile: diff --git a/dataacquisition/test_feed_db.py b/dataacquisition/test_feed_db.py new file mode 100644 index 0000000..664b48c --- /dev/null +++ b/dataacquisition/test_feed_db.py @@ -0,0 +1,66 @@ +import urllib.request +import psycopg2 +from selenium import webdriver +from selenium.webdriver.firefox.firefox_profile import FirefoxProfile + + +def write_stations_to_db(): + url = "https://opendata.dwd.de/climate_environment/CDC/help/stations_list_CLIMAT_data.txt" + + for line in urllib.request.urlopen(url): + values = str(line.decode('latin1')).replace(' ', '').replace('\r', '').replace('\n', '').split(';') + if len(values) == 6: + station_id, name, lat, long, height, country = values + if country == 'Germany': + print(station_id, name, lat, long, height, country) + with psycopg2.connect(database=credentials['db_name'], user=credentials['user'], password=credentials['pw'], host=credentials['host'], port=credentials['port']) as connection: + with connection.cursor() as cursor: + sql = "INSERT INTO stations (station_id, name, lat, long, height, country) VALUES({}, '{}', {}, {}, {}, '{}')".format(station_id, name, lat, long, height, country) + print(sql) + cursor.execute(sql) + + +def get_stations_from_db(): + with psycopg2.connect(database=credentials['db_name'], user=credentials['user'], password=credentials['pw'], host=credentials['host'], port=credentials['port']) as connection: + with connection.cursor() as cursor: + sql = "SELECT station_id FROM stations_germany ORDER BY station_id ASC" + cursor.execute(sql) + results = cursor.fetchall() + for result in results: + station_id = result[0] + yield station_id + + +def create_driver(): + # Sets preference for direct download instead of download-menu + profile = FirefoxProfile() + profile.accept_untrusted_certs = True + profile.acceptSslCerts = True + profile.set_preference("browser.download.folderList", 2) + profile.set_preference("browser.download.manager.showWhenStarting", False) + profile.set_preference("browser.helperApps.neverAsk.saveToDisk", + "text/plain,text/x-csv,text/csv,application/vnd.ms-excel,application/csv,application/x-csv,text/csv,text/comma-separated-values,text/x-comma-separated-values,text/tab-separated-values,application/pdf") + + browser = webdriver.Firefox(firefox_profile=profile) + return browser + + +def get_weather_data_from_web(): + driver = create_driver() + driver.get('https://opendata.dwd.de/climate_environment/CDC/observations_global/CLIMAT/monthly/qc/air_temperature_mean/historical/') + links = driver.find_elements_by_tag_name('a') + for link in links: + linktext = link.get_attribute('innerHTML') + if '../' not in linktext: + + + +def write_weather_data_to_db(): + with psycopg2.connect(database=credentials['db_name'], user=credentials['user'], password=credentials['pw'], host=credentials['host'], port=credentials['port']) as connection: + with connection.cursor() as cursor: + station_id = next(get_stations_from_db()) + sql = "SELECT station_id FROM stations_germany ORDER BY station_id ASC" + cursor.execute(sql) + + +get_weather_data_from_web() \ No newline at end of file -- GitLab