#!/usr/bin/env python3 """ Get energyprices from Entsoe """ 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 = common.env("el_entsoe_token") # https://transparency.entsoe.eu/content/static_content/Static%20content/web%20api/Guide.html apiUrl = "https://web-api.tp.entsoe.eu/api" 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") # 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") # Create a session object for making requests session = requests.Session() # Get the data values = [] for area in areas: try: url = ( f"{apiUrl}" f"?securityToken={apiKey}" f"&documentType=A44" f"&in_Domain={area['code']}" f"&out_Domain={area['code']}" f"&periodStart={startTime}0000" f"&periodEnd={endTime}0000" ) print("Getting data for " + area["code"]) # Use the session object to make the request response = session.get(url, timeout=10) # Handle any exceptions or non-200 status code response.raise_for_status() except requests.exceptions.RequestException as e: print(f"Error: {e}") sys.exit(1) 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(f"Got {items} records") # SQL sql = """ INSERT INTO entsoe VALUES(%s, %s, %s) ON CONFLICT (starttime, zone) DO NOTHING""" common.dbi(sql, values, verbose=True)