#!/usr/bin/env python3 """ Get energyprices from Entsoe """ import os import sys from datetime import datetime, timedelta import common import requests import xmltodict from dateutil import tz from tzlocal import get_localzone # variables # Getting an api-key isn't very well documented. The documentation [1] points # to a pdf [2], which says the following: # > In order to request the access to the Restful API, please register on the # > Transparency Platform and send an email to transparency@entsoe.eu with # > “Restful API access” in the subject line. Indicate the email address you # > entered during registration in the email body. We will make our best to # > respond to your request. # 1: https://transparency.entsoe.eu/content/static_content/Static%20content/web%20api/Guide.html#_authentication_and_authorisation # 2: https://transparency.entsoe.eu/content/static_content/download?path=/Static%20content/API-Token-Management.pdf apiKey = os.environ["el_entsoe_token"] # https://transparency.entsoe.eu/content/static_content/Static%20content/web%20api/Guide.html apiUrl = "https://web-api.tp.entsoe.eu/api?securityToken=" + apiKey startTime = datetime.now(get_localzone()) - timedelta(days=7) startTime = startTime.strftime("%Y%m%d") # startTime = '20230523' # <- edit for manual starttime. Like when filling in missing info. endTime = datetime.now(get_localzone()) + timedelta(days=1) endTime = endTime.strftime("%Y%m%d") jobname = os.path.splitext(os.path.basename(__file__))[0] # https://transparency.entsoe.eu/content/static_content/Static%20content/web%20api/Guide.html#_areas areas = [ {"name": "NO-0", "code": "10YNO-0--------C"}, {"name": "NO-1", "code": "10YNO-1--------2"}, {"name": "NO-2", "code": "10YNO-2--------T"}, {"name": "NO-3", "code": "10YNO-3--------J"}, {"name": "NO-4", "code": "10YNO-4--------9"}, ] UTC = tz.gettz("UTC") CET = tz.gettz("Europe/Oslo") # Get the data values = [] for area in areas: try: url = ( apiUrl + "&documentType=A44&in_Domain=" + area["code"] + "&out_Domain=" + area["code"] + "&periodStart=" + startTime + "0000&periodEnd=" + endTime + "0000" ) print("Getting data for " + area["code"]) response = requests.get(url, timeout=10) if response.status_code != 200: print(response.status_code) print("Oh shit") response.raise_for_status() except requests.exceptions.RequestException as e: print("oh lol") sys.exit(e) data_dict = xmltodict.parse(response.content) items = 0 if "Publication_MarketDocument" in data_dict: for lista in data_dict["Publication_MarketDocument"]["TimeSeries"]: utctime = datetime.strptime( lista["Period"]["timeInterval"]["start"], "%Y-%m-%dT%H:%MZ" ) utctime = utctime.replace(tzinfo=UTC) cettime = utctime.astimezone(CET) items += len(lista["Period"]["Point"]) for item in lista["Period"]["Point"]: # the response contains timerange, but not timestamp for every price, so we must calculate it time = str(cettime + timedelta(hours=int(item["position"]) - 1)) # append values values.append((time, area["name"], item["price.amount"])) print("Got " + str(items) + " records") # SQL sql = """ INSERT INTO entsoe VALUES(%s, %s, %s) ON CONFLICT (starttime, zone) DO NOTHING""" common.dbi(sql, values, verbose=True)