As a data scientist I often have to extract data from RESTful API’s this was something I’m admittedly not very good at.
So I decided to look at the MetOffice Datapoint API which provides weather information in the United Kingdom. You can visit that website to get your own API key if you wish.
Being from near Newry in Northern Ireland I decided to write a simple API call to extract data from that API.
The aim of this short gist is just to illustrate how you’d write a short OOP friendly snippet in Python.
In the future, I’ll write up something on how to mock out this API since that’s a big interest for me. Pytest looks like one of the best ways to do that.
These kinds of API’s are of interest if your model depends on weather information – which a lot of models do.
Thanks to Maciej Kula for providing some much needed code review.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import urllib.request | |
import json | |
URL = ('http://datapoint.metoffice.gov.uk/public/data/val/wxfcs/all/json/352817' | |
+ '?res=3hourly&key=*api_key*') | |
class Manager(object): | |
def __init__(self, api_key=""): | |
self.api_key = api_key | |
def _call_api(self, path): | |
""" | |
Private method | |
:param path: This is our URL string | |
:return: returns a decoded response from the URL | |
""" | |
response = urllib.request.urlopen(path) | |
try: | |
data = response.read() | |
except ValueError: | |
raise Exception("DataPoint has not returned any data" + | |
"this could be due to an incorrect API key") | |
datadecoded = data.decode('utf-8') | |
return datadecoded | |
def _convert_to_dictionary(self): | |
""" | |
Converts JSON data to a dictionary object | |
:param self: | |
:return: python dictionary | |
""" | |
json_from_api = self._call_api(path=URL) | |
data_dict = json.loads(json_from_api) | |
if not isinstance(data_dict, dict): | |
raise ValueError("Not successfully converted into a dictionary, check API key") | |
return data_dict | |
def _extraction_from_json(self): | |
""" | |
A function for extracting from the JSON of the Datapoint api | |
This is a heavily nested JSON API | |
:return: (date, day, time, temperature, location) | |
""" | |
data_dic = self._convert_to_dictionary() | |
date = data_dic['SiteRep']['DV']['dataDate'] | |
period = data_dic['SiteRep']['DV']['Location']['Period'][0] | |
day = period['value'] | |
time = period['Rep'][0]['$'] | |
temperature = int((period['Rep'][0]['T'])) | |
location = (data_dic['SiteRep']['DV']['Location']['name']) | |
return (date, day, time, temperature, location) | |
def extract_from_api(self): | |
""" | |
Calls all private functions | |
:return: | |
""" | |
convert_to_dict = self._convert_to_dictionary() | |
json_extract = self._extraction_from_json | |
return json_extract | |
if __name__ == "__main__": | |
print("Current Weather in Newry", Manager().extract_from_api()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import urllib.request | |
import json | |
URL = ('http://datapoint.metoffice.gov.uk/public/data/val/wxfcs/all/json/352817' | |
+ '?res=3hourly&key=*api_key*') | |
class Manager(object): | |
def __init__(self, api_key=""): | |
self.api_key = api_key | |
def _call_api(self, path): | |
""" | |
Private method | |
:param path: This is our URL string | |
:return: returns a decoded response from the URL | |
""" | |
response = urllib.request.urlopen(path) | |
try: | |
data = response.read() | |
except ValueError: | |
raise Exception("DataPoint has not returned any data" + | |
"this could be due to an incorrect API key") | |
datadecoded = data.decode('utf-8') | |
return datadecoded | |
def _convert_to_dictionary(self): | |
""" | |
Converts JSON data to a dictionary object | |
:param self: | |
:return: python dictionary | |
""" | |
json_from_api = self._call_api(path=URL) | |
data_dict = json.loads(json_from_api) | |
if not isinstance(data_dict, dict): | |
raise ValueError("Not successfully converted into a dictionary, check API key") | |
return data_dict | |
def _extraction_from_json(self): | |
""" | |
A function for extracting from the JSON of the Datapoint api | |
This is a heavily nested JSON API | |
:return: (date, day, time, temperature, location) | |
""" | |
data_dic = self._convert_to_dictionary() | |
date = data_dic['SiteRep']['DV']['dataDate'] | |
period = data_dic['SiteRep']['DV']['Location']['Period'][0] | |
day = period['value'] | |
time = period['Rep'][0]['$'] | |
temperature = int((period['Rep'][0]['T'])) | |
location = (data_dic['SiteRep']['DV']['Location']['name']) | |
return (date, day, time, temperature, location) | |
def extract_from_api(self): | |
""" | |
Calls all private functions | |
:return: | |
""" | |
convert_to_dict = self._convert_to_dictionary() | |
json_extract = self._extraction_from_json | |
return json_extract | |
if __name__ == "__main__": | |
print("Current Weather in Newry", Manager().extract_from_api()) |