API Month Day 11 - Movies

API.png

API purpose Interfacing and searching IMDB database

Signup not needed

Documentation http://www.omdbapi.com/

Github Click here for link

Comment Surprisingly fun game

So I went to a games night last night to decide who got what teams for the upcoming Euros 2016. I do live an exciting life. Anywho we play a game sometimes where you pick a number in days, hours and minutes and have to name 3 boxsets of popular TV that would get you there.

We found some inconsistencies (and were running out of games) so I had a quick look at the omdbapi (open movie database API) to see how the data was being gathered. I found a quick call that would return the IMDB ratings of movies so I whipped up a quick script to calculate the sum of an arbitrary number of movies.

See attached link in the header for the source. It’s very short and is a pretty standard requests format if you’ve seen any of my other posts. The one style change I made was to use raw_input() instead of a sys.argv() to pass arguments to the script. It’s a lot neater and more flexible for the sort of scripts I’ve been writing so I think I’ll change to using it in the future.

I also won that round …;

API Month Day 10 - Oasis or Blur

oasisorblur

API purpose Interfacing and searching twitter

Signup https://dev.twitter.com/apps/new

Documentation https://dev.twitter.com/rest/public

Github Click here for link

Comment So much that could be done with this

Today is so easy. After reading into the Twitter API it became obvious that people had written so much on this subject. So to get started you do the following.

After running

1
easy_install twitter

Just look at this resource: https://github.com/ideoforms/python-twitter-examples

It’s so good, gives examples for searching by hashtag (both as a sample or from the streaming service), searching by area, posting to your feed and doing a bunch of general analytics.

Make sure you have installed twitter tools (via the above command) and not python-twitter which is a separate set of tools. This lead to a bit of confusion on my part. I wrote a simple app that searches hashtags for Oasis and Blur to answer the age old question once and for all. Enjoy!

Apparently it’s Blur!

Day10

API Month Day 9 - Petrol Stations

API purpose Interfacing and searching google maps

Signup Via your google account

Documentation Click here for link

Comment So much that could be done with this

Today I wanted to play with the google places API. Its very cool, it lets you search within a distance of your current location for various services. Pretty cool to see from this what’s around you. You can even pull out reviews from the locations!

So I wrote a script that takes in an address and checks for nearby petrol stations. Nice little function that could easily be extended to take in any service in your area from user input.

Nothing too tricky today, but it turns out there are not very many petrol stations in my area. I did change the argv input to a raw_input prompt from the user, its a little bit nicer and means you can be dynamically prompted for inputs during the programs operation without having to build a GUI. This can be used later to build simple command line menus etc…

Here is an example output from the script:

Day9Output

API Month Day 8 - SPACE

API purpose Finding information about the International Space Station

Signup No signup necessary

Documentation http://open-notify.org/Open-Notify-API/

Github Click here for link

Comment Really fun dataset to play with

I did promise some time manipulation stuff today but it was super boringso I got interested in space instead. Fellow bedlabber (that’s a word) vykta sent on a link to Urethcast, a service which provides pictures from the International Space Station (ISS). He’s promised to write up a post on it this month so stay tuned for that. It did get me thinking about what other sources of open data are available from the ISS.

I did some googling and found open-notify, a wrapper API for some of the data Nasa puts out. Turns out space agencies have a good understanding of where the ISS is at any given time, who would have thought? Open-notify provides information on where the ISS is, when it will be visible over a given GPS coordinates and who is on board. All cool stuff 🙂

It did give me the opportunity to implement a few things:

  • Epoch converter, epoch time (or unix time) is time quoted in seconds since 00:00:00 UTC on Thursday, 1 January 1970. Its useful for comparing times on servers but is not very human readable.

  • Reverse geocoding, for if I got a set of GPS coordinates and want a real address, I’ve made a function for that now

Its a nice little script, returns a little table of data like so:

Day8 Output

I also realised I’ve been consistently spelling longitude incorrectly all week for my variables. Oh well. Check out the code, again its all commented so hopefully is understandable. Any questions pop them in the comments.

All the code is on the github. I’ve realised that its not exactly readable without the indents now that my programs are more complex. I’ll have a read on the wordpress nexus to see how its done and maybe only copy the interesting bits from now on.

API Month Day 7 - Where is my air?

API purpose: Finding local air quality from address

Signup: air quality has no signup google, as always, does.

Documentation: https://developers.google.com/maps/web-services/client-library

Github: https://github.com/gregario/API-Month/tree/master/Day7%20AQ%20Project

Comment: Wrapping up the first week into a useful script

So today was a culmination of all the learnings I achieved this week…. A bit of background on this one. I decided to do something a bit more abitious today. Since I now have the basic building blocks of data for getting and manipulating JSON API data I thought I would put it to the test for something more than one localised test. So today I’m going to build something chunkier. Using the work I’ve done all week from data manipulation, geocaching and the air quality API, I want to build an app that if you put in a post code in London it finds the nearest AQ monitor from the list and returns its air quality data.

This is more challenging than it sounds, the basic work flow would be.

Take input address and convert to GPS. Pull down list of all London Air Quality monitors and extract their locations. Do a diff between the two to find the closest distance from that new list. Then from that new list pull down a list of sensors associated with that sensor. Then from this pull down their data and average it for the day.

What I can then use this to do is to give Air quality information as an extension to map or location searches. An interesting wrapper library for future work. I’m going to try some more complex error handling in this too, as I’ve been pretty lax with this up until now.

As I’ve moved onto commenting inline the code should be self explanatory, it produces some nice pretty outputs too!

Screenshot

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#coding: utf-8
# Day seven of the month of API
# Today finds your nearest Air Quality monitor and returns its data
# Greg Jackson @gr3gario on twitter and gregario on github
import requests
import json
import sys
import googlemaps
from APIKEY import googlekey
import math
## Workflow
#Pull down list of all London Air Quality monitors and extract their locations.
#Do a diff between the two to find the closest distance from that new list.
#Then from that monitor pull out its air quality monitor.
# This function takes in a command line post code (or address), performs a google maps call to check its GPS data and returns as a list
def addtoGPS():
attempts = 0
latlng = []
while attempts < 3:
try:
gmaps = googlemaps.Client(key=googlekey) # Get key from your google developer portal.
# Geocoding an address
geocode_result = gmaps.geocode(sys.argv[1]) # passes address given on command line to google maps geocoding api
for key in geocode_result: # the returned object is a list with nested JSON objects inside each list. So you need to iterate through the list and do operations on each object separately
latlng.append(float(key['geometry']['bounds']['northeast']['lat'])) # pulls out nested latitude figure from call
latlng.append(float(key['geometry']['bounds']['northeast']['lng'])) # pulls out nested longditude figure from call
break
except:
attempts += 1
print "Error getting data from Google maps API"
return latlng
# This function calls the London Air Quality API and returns a list of all the sites with their GPS Coordinates
def LAQNList():
url = "http://api.erg.kcl.ac.uk/AirQuality/Information/MonitoringSites/GroupName=All/JSON" # Gives all units in London for AQ
siteDetails=[]
siteDetail={}
attempts=0
distance = 0.0
while attempts < 3:
try:
r = requests.get(url).json() # Make a request to the TFL API for data
q = r['Sites']['Site'] # This extracts the list from the JSON object
for key in q:
# This is quite elegant. There are closed air quality units on the system which we want to ignore. So we check the dateclosed field. If its emply we include the unit.
dateclosed = key ['@DateClosed']
if not dateclosed:
sitecode = key['@SiteCode']
latitude = float(key['@Latitude'])
longditude = float(key['@Longitude'])
siteDetail={'sitecode': sitecode, 'latitude': latitude, 'longditude': longditude, 'distance':distance}
siteDetails.append(siteDetail)
break
except:
attempts += 1
#print "Error getting Location data from LAQN API"
return siteDetails
# This function takes input values and calculates distance for every point and calculates the closest site code
def distance():
latlngin = addtoGPS()
siteDetails=LAQNList()
distance = []
for key in siteDetails:
lat = float(key ['latitude'])
lng = float(key ['longditude'])
output = math.sqrt((latlngin[0] - lat)**2 + (latlngin[1] - lng)**2)
key['distance'] = output
distance.append(output)
mindistance = min(distance)
for key in siteDetails:
check = key['distance']
if check == mindistance:
finalsite = key['sitecode']
return finalsite
## I now have my closest Air Quality Monitor, need to call this and see what sensors it has
## back to the API documentation
def whatSensor():
siteCode = distance()
speciesCode = []
attempts = 0
while attempts < 3:
try:
url= "http://api.erg.kcl.ac.uk/AirQuality/Daily/MonitoringIndex/Latest/SiteCode=" +siteCode+ "/json"
r = requests.get(url).json() # Make a request to the TFL API for data
q = r['DailyAirQualityIndex']['LocalAuthority']['Site']['Species'] # This extracts the list from the JSON object
for key in q:
specie = key['@SpeciesCode']
species={'SpeciesCode': specie}
speciesCode.append(species)
break
except:
attempts += 1
print "error finding speciesCode of sensors"
return speciesCode
# Finally once we have the sensors associated with the closest air quality sensor we can do a check of the last day and return an average of the readings
# I realise here it would be nice to check the current time and return it as a variable for input, will work on that on day 8
def sensorReadings():
siteCode = distance()
speciesCode = whatSensor()
attempts = 0
averageOut = []
for key in speciesCode:
speciesUrl = key['SpeciesCode']
url = "http://api.erg.kcl.ac.uk/AirQuality/Data/SiteSpecies/SiteCode="+siteCode+"/SpeciesCode="+speciesUrl+"/StartDate=05-12-15/EndDate=06-12-15/Json" # Gives data in closest AQ monitor
r = requests.get(url).json() # Make a request to the LAQN API for data
rLoop = r['RawAQData']['Data']
AQugm3 = []
for key in rLoop:
AQugm3temp = key['@Value']
try:
AQugm3temp = float(AQugm3temp)
AQugm3.append(AQugm3temp) # Adds output to AQugm3 variable
# Catches exceptions
except:
print 'error in parsing, oops'
pass
# Really simple averages. Sums all elements in the list and divides by the length of the list
average = sum(AQugm3) / float(len(AQugm3))
average = round(average,2)
average={'SpeciesCode': speciesUrl, 'average':average}
averageOut.append(average)
return averageOut
print sensorReadings()

On the code, apologies but the white spaces were not preserved when I copied it over, have a look at the github to get a more human readable version of the code.

Running

1
python AQProject.py SW72bx

Gives

1
[{"SpeciesCode": "NO2";, "average": 43.0}, {"SpeciesCode: 'PM10", 'average': 21.68}, {'SpeciesCode': "PM25", 'average': 8.66}]

Turns out the air quality around work is pretty good, for NO2 43ug/m3 average is right at the 40ug/m3 target for a yearly average. Yay 🙂

One thing I’ve noticed from this work is I need to have a play with times and dates to do it neatly. Tomorrow I’m going to play with NTP servers and the date module in python. Its a slight divergence from the API calling but will be a useful function to plug into other functions in the future.

Day 6 API Month - GPS Distance

API purpose: GPS Distance

Signup: Using the google developer portal

Documentation: https://developers.google.com/maps/web-services/client-library

Github: https://github.com/gregario/API-Month/tree/master/Day6%20GPS%20Distance

Comment: Continuation of day 4, interesting problem.

Quick one today after yesterday drove me mad. Wanted to do a quick function that takes in two sets of GPS data and works out the distance between them. I did some reading on calculating distances between two points on a map. Apparently its a real issue in the mapping community with many implementations of map hashing being discussed.

My first thoughts would be to take the two latitudes from each other, take the absolute of that. Then do the same with longditude and then add those two numbers together. In math-y terms it would be:

distance = abs(lat2 - lat1) + abs(long2 - long2)

But then I had a flashback to my school maths and it would be more appropriate to do a pythagoras job on it. Basically take the two points as a hypotenuse of a right angled triangle. Then I had the fun of programming it in python, I got:

math.sqrt((p0[0] - p1[0])**2 + (p0[1] - p1[1])**2)

A small aside but another thing I did for today was to make an API key file that I can use with all my programs. So commiting your API keys to Git is generally a bad thing. People have scripts running to search for API key, particularly for anything to do with AWS, and start hammering them once they’re found. It can end up costing a bunch of money. So I have a separate file I do not commit to any Git repository and I add to my files by importing it like any other module in python. It also is a nice system for configuration files if you want to make your python scripts more abstract.

So new code, here it it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# -*- coding: utf-8 -*-T
# Program to check the linear distance between two sets of GPS coordinates.
# Continuation of day 4 of API Month
# Greg Jackson 6th deb 2015
# Twitter @gr3gario or github gregario
# Day 6 of the Month of API
import googlemaps # install using pip install -U googlemaps
import sys # Used to take in input parameters from command line.
from APIKEY import googlekey
import math # Added to do sqrt
# Geocoding an address
geocode_result = gmaps.geocode(sys.argv[1]) # passes address given on command line to google maps geocoding api
gmaps = googlemaps.Client(key=[INSERT_KEY]googlekey) # Get key from your google developer portal.
latlng = []
latlngTB = [51.5054564,-0.0753565]
for key in geocode_result: # the returned object is a list with nested JSON objects inside each list. So you need to iterate through the list and do operations on each object separately
latlng.append(key['geometry']['bounds']['northeast']['lat']) # pulls out nested latitude figure from call
latlng.append(key['geometry']['bounds']['northeast']['lng']) # pulls out nested longditude figure from call
def distance(p0, p1):
return math.sqrt((p0[0] - p1[0])**2 + (p0[1] - p1[1])**2)
# Obsolete Method, simplier than other.
#distance = abs(latlngTB[0] - latlng[0]) + abs(latlng[1] - latlngTB[1])
distance = distance(latlng,latlngTB)
print "The distance to Tower Bridge is: " +str(distance)

Day 5 API Month - London Air Quality

API purpose: Getting London Air Quality Data

Signup: None, its open data

Documentation: http://api.erg.kcl.ac.uk/AirQuality/help

Github: https://github.com/gregario/API-Month/tree/master/Day5%20AirQuality

Comment: Really well made API, not real time though, about a day delay

So Kings College run an array of air quality monitors across London. Its a really interesting piece of data to work with that is so relevant to our day to day lives. Thought I would have a look at the API and try to pull the data from my nearest air quality monitor to my home.

The call from the API documentation requires the use of their site codes to work, which isn’t the most intuitive. A quick peruse of the maps at particulate matter. Cool so IS2 is my air quality roadside monitor. As a bonus there’s 15 years of data from the monitor.

So here is the link to the call we want. It actually leads to a pretty straightforward script. [Edit an hour later]. Getting strings converted to floats is apparently not straight forward. Anywho, here’s the completed script. As always I explain the crap out of the code in the code so I think it kind of explains itself!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#coding: utf-8
# Day 5 of month of API
# Looking at local air quality data and what the last 24 hours have been like in your local area
# Greg Jackson 05/12/15 gr3gario on twitter ang gregario on github
import requests
import json
url = "http://api.erg.kcl.ac.uk/AirQuality/Data/SiteSpecies/SiteCode=IS2/SpeciesCode=NO2/StartDate=04-12-15/EndDate=05-12-15/Json" # Gives data in closest AQ monitor
r = requests.get(url).json() # Make a request to the LAQN API for data
rLoop = r['RawAQData']['Data'] # You got to define this here as you can't nest it below. the for loop below only works for the list embedded in the JSON object
AQugm3 = [] # A list to store the readins
for key in rLoop:
AQugm3temp = key['@Value'] # This loops through each data packet in the list and pulls out our relevant datapoint
try: # A try catch is included here as there are blank datapoints returned from the LAQN API that would mess this up occasionally if there wasn't a catch in place
AQugm3temp = float(AQugm3temp) # Converts from a string to a float so we can perform operations on it
AQugm3.append(AQugm3temp) # Adds output to AQugm3 variable
# Catches exceptions
except:
print 'error in parsing, oops'
pass
# Really simple averages. Sums all elements in the list and divides by the length of the list
average = sum(AQugm3) / float(len(AQugm3))
average = round(average,2)
# This is an EU defined goal for NO2 in the city. I figure if our daily average is below this we're doing well. Its more to give context to the number.
goal = 40.0
# Simple check to give context to the number.
if average < goal:
print "Hurray! The air quality today is less than the yearly average target of 40 ug/m3 NO2 target in the UK and reads " +str(average)+ " ug/m3"
elif average > goal:
print "Unfortunately the air quality today is more than the yearly average target of 40 ug/m3 NO2 in the UK and reads " + str(average)+ " ug/m3"

So when I run python AQ.py.

Unfortunately the air quality today is more than the yearly average target of 40 ug/m3 NO2 in the UK and reads 69.71 ug/m3

Interesting stuff 🙂

So I had the thought of making a bigger project at the end of each week, not necessarily more work but wrapping up the work I’ve done into one bigger program. I have a good idea to wrap this weeks work up which I’ll explain on Monday but its missing one big element. I need to be able to easily calculate the distance between two sets of GPS coordinates. So tomorrow I’ll work on this. I’ll be pulling an address in the UK, converting to GPS data and checking its linear distance to tower bridge in London.

Day 4 API Month - Google Maps Geocoding

API purpose: Getting GPS data (amongst a bunch of other things)

Signup: Via your google account.

Documentation: https://developers.google.com/maps/web-services/client-library

Github: https://github.com/gregario/API-Month/tree/master/Day4%20GPS

Comment: Easy Peasy!

A super simple one today. Working through these location maps I’ve had to input GPS coordinates for a call and I thought it would be nice to be able to feed in a nice address and get a nice GPS coordinates. Turns out google provide this service and its super easy to use.

So I looked at a function for geocoding (taking an address and converting to GPS), this can be simply altered for reverse geocoding too (taking GPS and converting to an address). The latter is important too as some functions in API’s return a GPS and its not meaningful as an output (or nobody knows what the hell it means.

So the code today is super simple as a nice man made a python wrapper for all of this. So rock over to https://github.com/googlemaps/google-maps-services-python or just run:

sudo pip install -U googlemaps

You are basically good to go then. So I wrote two short scripts that are available on the github link above, the scripts are pretty easy and build on the python tricks I built up in the other tutorials.

JSON_Day4

Here’s the API call, very similar structure to the TFL structure!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# -*- coding: utf-8 -*-
# Program to check how long it will take me to get to work
# Greg Jackson 4th deb 2015
# Twitter @gr3gario or github gregario
# Day four of the Month of API
import googlemaps # install using pip install -U googlemaps
import sys # Used to take in input parameters from command line.
gmaps = googlemaps.Client(key='INSERT API KEY') # Get key from your google developer portal.
# Geocoding an address
geocode_result = gmaps.geocode(sys.argv[1]) # passes address given on command line to google maps geocoding api
latlng = []
for key in geocode_result: # the returned object is a list with nested JSON objects inside each list. So you need to iterate through the list and do operations on each object separately
latlng.append(key['geometry']['bounds']['northeast']['lat']) # pulls out nested latitude figure from call
latlng.append(key['geometry']['bounds']['northeast']['lng']) # pulls out nested longditude figure from call
# easy peasy printing
print "Your latitude is: " +latlng[0]
print "Your londitude is: " +latlng[1]

And it works! Go me.

day4 success

API Month Day 3 - TFL API

API purpose: Commuting Data

Signup: No Signup

Documentation: https://api-portal.tfl.gov.uk/docs

Github: https://github.com/gregario/API-Month/tree/master/Day3%20Maps Comment: surprisingly challenging

So as I said yesterday today I want to find the arrival time of my local train so I can plan my morning breakfast intake! It turned out to be quite challenging… Firstly a comment on the TFL (transport for london) API services. They’re all over the place. I found the following resources to extract data about journeys, stop locations and times:

https://api.tfl.gov.uk/#Journey

http://countdown.tfl.gov.uk/

and two sets of documentation at:

https://api-portal.tfl.gov.uk/docs

https://api.tfl.gov.uk/

So I eventually used the API portal to get access to arrival times, it wasn’t the most straightforward information set to work with however. Check out the photo!

JSON_TFL

The photo shows a typical API response from a station arrival time call. We want one variable from this giant list! This is a good time to work with a list like this as many API’s are complex like this one so it gives me an opportunity to go through the detail and figure out how to extract the data.

I got to play with some good stuff here such as operating on, iterating over and extracting conditional data from JSON objects. Also doing operations on time while pulling the current real time from the python datetime module.

The key for the code here is that the API is a list where each element in the list is a JSON object (that we manipulate as a python dict). Confused? I was… But its OK to work with in practice. What happens here is we write some code to loop through the list and for every JSON element in the list do a value search for arrival time. This gives us the arrival time of all trains into my station. However I only want certain trains heading in one direction. So I run an if with the loop checking for the relevant trains. If they are present pop the arrival time from that train into a new array. Then we have an array with all the relevant arrival times. Just sort that and you have the train that will arrive first. Pop that out and you have a variable to work with. YAY. Taking that from the current time gives you the number you are looking for.

I’ve explained the logic of what I want to do now let’s look at the code. If you are reading this (I do doubt anyone is) I am trying to improve the way in which I write these tutorials. Today I’m trying to explain how all the code works as comments. Hopefully one can understand how it works just from that.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# -*- coding: utf-8 -*-
# Program to check how long it will take me to get to work
# Greg Jackson 1st dev 2015
# Twitter @gr3gario or github gregario
# Day one of the Month of API
import requests
import json
import sys # needed to pass arguments from command line
import datetime
url = "https://api.tfl.gov.uk/StopPoint/910grctryrd/arrivals" # the stop number is returned from the TFL website from a manual search. This calls the data
r = requests.get(url).json() # Make a request to the TFL API for data
time = [] # List for my future train arrivals
for key in r: # the returned object is a list with nested JSON objects inside each list. So you need to iterate through the list and do operations on each object separately
if key['destinationName'] == ("Cheshunt Rail Station") or ("Enfield Town Rail Station"): # This filters out trains to different destinations. I can take either of these trains
time.append(key['expectedArrival']) # Adds expected arrival time from each train data structure to the time list
time_sorted = sorted(time) # sorts the time list so we get the train due to arrive first
time_train = time_sorted.pop(0) # pops out the first train to arrive and stores as a string
§
# this translates the time from a string in the list to a usable string, taking out the date.
# A note on how I deal with the date and time operations here.
# Its TERRIBLE. it works but I'm sure there's a much cleaner way of doing this.
time_train_temp = time_train.split('T',1)[-1]
time_train_parsed = time_train_temp.split('.',1)[0]
current_time = str(datetime.datetime.now())
current_time_temp = current_time.split(' ',1)[-1]
current_time_parsed = current_time_temp.split('.',1)[0]
#print k
# Converts the two hour:minute:second strings back into time variables.
timeA = datetime.datetime.strptime(time_train_parsed, '%H:%M:%S')
timeB = datetime.datetime.strptime(current_time_parsed, '%H:%M:%S')
# Takes the time of the next train away from the current time to give an estimated time until arrival of the next train I can take
time_delta = timeA-timeB
print ("The next train to work will arrive in " +str(time_delta))

And it works!

Output_day3

I’ve never been so happy to see some command line arguments! This was day three but I ran over time so I’m going to immediately do day 4 too 🙂 Stay tuned.

API Month Day 2 - Weather Underground

Highlights

API purpose: Weather Conditions

Signup: http://www.wunderground.com/weather/api/

Documentation: http://www.wunderground.com/weather/api/d/docs
Github: http://bit.ly/1OxwFrc

Comment: Feature rich and worldwide weather!

OK so day two of API month. Exciting, right? Yesterday it occured to me if I’m making a decision when debating my cycle vs tube debate it would also be good to see the near term forecast. So I did some reading and found weather underground. Its a system of weather stations around the world, with data provided by official and hobbyist sources. Their API is pretty good too!

Getting the Data

So I swung over and setup an account. Straight forward process. I want to pull relevant information from the API so I did a sample call for London to see what I would get.

http://api.wunderground.com/api/[INSERTKEY]/conditions/q/uk/London.json

Pretty straightforward. A slightly different system than citymapper but very usable. It returned this: ``

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
{
"response": {
"version":"0.1",
"termsofService":"http://www.wunderground.com/weather/api/d/terms.html",
"features": {
"conditions": 1
}
}
, "current_observation": {
"image": {
"url":"http://icons.wxug.com/graphics/wu2/logo_130x80.png",
"title":"Weather Underground",
"link":"http://www.wunderground.com"
},
"display_location": {
"full":"Dublin, Ireland",
"city":"Dublin",
"state":"",
"state_name":"Ireland",
"country":"IE",
"country_iso3166":"IE",
"zip":"00000",
"magic":"1",
"wmo":"03969",
"latitude":"53.43000031",
"longitude":"-6.25000000",
"elevation":"85.00000000"
},
"observation_location": {
"full":"Paulie - Swords West, Swords, DUBLIN",
"city":"Paulie - Swords West, Swords",
"state":"DUBLIN",
"country":"IRELAND",
"country_iso3166":"IE",
"latitude":"53.463554",
"longitude":"-6.249463",
"elevation":"138 ft"
},
"estimated": {
},
"station_id":"IDUBLINS3",
"observation_time":"Last Updated on December 2, 4:08 PM GMT",
"observation_time_rfc822":"Wed, 02 Dec 2015 16:08:49 +0000",
"observation_epoch":"1449072529",
"local_time_rfc822":"Wed, 02 Dec 2015 16:09:02 +0000",
"local_epoch":"1449072542",
"local_tz_short":"GMT",
"local_tz_long":"Europe/Dublin",
"local_tz_offset":"+0000",
"weather":"Mostly Cloudy",
"temperature_string":"51.1 F (10.6 C)",
"temp_f":51.1,
"temp_c":10.6,
"relative_humidity":"99%",
"wind_string":"Calm",
"wind_dir":"SW",
"wind_degrees":217,
"wind_mph":0.0,
"wind_gust_mph":0,
"wind_kph":0,
"wind_gust_kph":0,
"pressure_mb":"1017",
"pressure_in":"30.04",
"pressure_trend":"+",
"dewpoint_string":"51 F (11 C)",
"dewpoint_f":51,
"dewpoint_c":11,
"heat_index_string":"NA",
"heat_index_f":"NA",
"heat_index_c":"NA",
"windchill_string":"NA",
"windchill_f":"NA",
"windchill_c":"NA",
"feelslike_string":"51.1 F (10.6 C)",
"feelslike_f":"51.1",
"feelslike_c":"10.6",
"visibility_mi":"6.2",
"visibility_km":"10.0",
"solarradiation":"0",
"UV":"0.0","precip_1hr_string":"0.00 in ( 0 mm)",
"precip_1hr_in":"0.00",
"precip_1hr_metric":" 0",
"precip_today_string":"0.07 in (2 mm)",
"precip_today_in":"0.07",
"precip_today_metric":"2",
"icon":"mostlycloudy",
"icon_url":"http://icons.wxug.com/i/c/k/mostlycloudy.gif",
"forecast_url":"http://www.wunderground.com/global/stations/03969.html",
"history_url":"http://www.wunderground.com/weatherstation/WXDailyHistory.asp?ID=IDUBLINS3",
"ob_url":"http://www.wunderground.com/cgi-bin/findweather/getForecast?query=53.463554,-6.249463",
"nowcast":""
}
}

Wow… That is a lot more info than our last tutorial. This is great though, it gives me a chance to play with more information. Here’s what I wrote up.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# -*- coding: utf-8 -*-
# Program to check how long it will take me to get to work
# Greg Jackson 1st dev 2015
# Twitter @gr3gario or github gregario
# Day one of the Month of API
import requests
import json
import sys # needed to pass arguments from command line
country= str(sys.argv[1])
location = str(sys.argv[2])
url = "http://api.wunderground.com/api/[INSERTAPIKEY]/conditions/q/"+str(country)+"/"+str(location)+".json"
r = requests.get(url).json()
print("The current wind speed (mph) is: "+ str(r['current_observation']['wind_mph']))
print("The current temperature (C) is: " +str(r['current_observation']['temp_c']))
print("Sure what's the weather like? : "+ str(r['current_observation']['icon']))
print("The current relative RH is: "+str(r['current_observation']['relative_humidity']))
print("Will it rain soon? : "+str(r['current_observation']['precip_1hr_metric']))
# So I have a good indication of the weather from a current loation.
# I introduced two super simple things here.
# One is string concatonation in python. This lets us declare a location by variable instead of in line.
# this can be better than the payload option as it gives you more flexibility.
## Finally I thought I could declare from the command line the location to search.
## I've always wondered how this could be done so now I know!

Still pretty straightforward too!

Nested JSON

Yesterday our JSON was super easy. It was one series of machine tag pairs inside a JSON object. We asked for our machine tag (estimated_time) in that array and we were good to go with the value associated with that. However in JSON, each variable in an array can have an array of machine tags nested inside it. Its actually quite elegant if you work through the logic but we don’t care about this, we just want the data, right?!!! So let’s take wind speed from above. We wanted to get the current_observation array and inside that get the wind_mph tag and its associated value. To do this we used the following syntax.

1
2
print("The current wind speed (mph) is: "+ str(r\['current\_observation'\]\['wind\_mph'\]))

So What Next?

So that’s that for today. Another simple example with some useful tricks to get you going with weather APIs. So what shall I do tomorrow??? I like this work around my commute to work. I think I’m going to solve a final challenge tomorrow with a good one, I live a 4 minute walk from my local train to work. The train comes every 15 minutes. The arrival time of the next train dictates if I have breakfast each day. I check this every day on google maps so I want to write a script that checks the TFL API and displays the next train time for me so I can quickly glance and see how long I have!