Tuesday, November 20, 2012

Weather information from openweathermap.org JSON API by Python

The openweathermap.org offers JSON API to query weather information around the world. It is not difficult to use python to call the API, parse the JSON and gather the information.

Since all the request are from web, it'd better to prepare a simple function to fetch the HTML/JSON from the site:

import urllib2, json

def fetchHTML(url):
    req = urllib2.Request(url)
    return response.read()

Remember it is just for a quick and dirty approach. In real case we should handle exceptions (such as URL unreachable, network not found, etc)

Now we are ready to call the API. First of all we need to know the "id" of a City. http://openweathermap.org/data/2.1/find/name?q=<CITY>

>>> output=fetchHTML("http://openweathermap.org/data/2.1/find/name?q=hongkong")>>> print output
'{"message":"","cod":"200","type":"geonames-cash","calctime":0.0205,"units":"internal","count":1,"list":[{"id":1819729,"coord":{"lat":22.285521,"lon":114.157692},"name":"Hong Kong","main":{"temp":295.93,"humidity":73,"pressure":1017,"temp_min":294.97,"temp_max":295.93},"dt":1353375271,"date":"2012-11-20 01:34:31","wind":{"speed":8.22,"deg":100},"rain":{"3h":0.2},"clouds":{"all":100},"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10d"}],"sys":{"country":"HK","population":7012738},"url":"http:\\/\\/openweathermap.org\\/city\\/1819729"}]}'

Please note that it is a strings. To convert it as JSON format:

Now it's much better for us to retrieve the data. What we need is the ID, which is within the first item of 'list'->'id'
>>> json_out['list'][0]['id']

Now we get the ID, let's try to get temperature of Hong Kong:
output=fetchHTML("http://openweathermap.org/data/2.1/weather/city/%s" % 1819729)
{u'clouds': {u'all': 100}, u'name': u'Hong Kong', u'url': u'http://openweathermap.org/city/1819729', u'coord': {u'lat': 22.285521, u'lon': 114.157692}, u'sys': {u'country': u'HK', u'id': 37808}, u'weather': [{u'main': u'Rain', u'id': 500, u'icon': u'10d', u'description': u'light rain'}], u'rain': {u'3h': 0.2}, u'date': u'2012-11-20 01:44:32', u'dt': 1353375872, u'main': {u'pressure': 1017, u'temp_min': 294.97, u'temp_max': 295.93, u'temp': 295.93, u'humidity': 73}, u'id': 1819729, u'wind': {u'speed': 8.22, u'deg': 90}, u'cod': 200}
>>> json.loads(output)['main']
{u'pressure': 1017, u'temp_min': 294.97, u'temp_max': 295.93, u'temp': 295.93, u'humidity': 73}
>>> json.loads(output)['main']['temp']

Note that the temperature is measured in degree Kelvin unit. We can convert it back to degress Celsius easily:
>>> temp_c = round(json.loads(output)['main']['temp'] - 273.15)

Another good API call is the forecast:
>>> output=fetchHTML("http://openweathermap.org/data/2.1/forecast/city/%s" % 1819729)>>> json.loads(output)['list'][0]
{u'clouds': {u'high': 10, u'middle': 0, u'all': 100, u'low': 100}, u'rain': {u'3h': 0.6}, u'dt_txt': u'2012-11-19 23:00:00', u'weather': [{u'main': u'Clouds', u'id': 804, u'icon': u'04n', u'description': u'overcast clouds'}], u'dt': 1353366000, u'main': {u'temp_kf': 1.3, u'temp': 295.93, u'temp_max': 295.93, u'humidity': 81.1, u'pressure': 1013.25, u'temp_min': 294.65}, u'wind': {u'gust': 7.4, u'speed': 5.18, u'deg': 80}}
>>> json.loads(output)['list'][1]
{u'clouds': {u'high': 0, u'middle': 0, u'all': 84, u'low': 84}, u'rain': {u'3h': 0.1}, u'dt_txt': u'2012-11-20 02:00:00', u'weather': [{u'main': u'Clouds', u'id': 803, u'icon': u'04d', u'description': u'broken clouds'}], u'dt': 1353376800, u'main': {u'temp_kf': 1.24, u'temp': 296.98, u'temp_max': 296.98, u'humidity': 73.3, u'pressure': 1013.25, u'temp_min': 294.64}, u'wind': {u'gust': 7.3, u'speed': 5.73, u'deg': 73}}
>>> json.loads(output)['list'][1]['main']['temp']

Within the 'list' there are weather information of each time interval, we can get the weather for the coming days.

Apart from temperature, we can also get pressure, humidity, wind speed, and even city population. It'd better leave to you to explore :)

Ref: http://openweathermap.org/wiki/API/JSON_API

No comments: