Mar 10

Quick and Dirty GeoIP Lookup Function in Python

A python function for calling Geo IP lookup service

I found a free GeoIP lookup service, that happens to have a simple API for getting the result in XML: http://api.hostip.info/?ip=65.34.176.69. The returned XML looks like this:


<?xml version="1.0" encoding="ISO-8859-1" ?>
<HostipLookupResultSet version="1.0.0" xmlns="http://www.hostip.info/api" xmlns:gml="http://www.opengis.net/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.hostip.info/api/hostip-1.0.0.xsd">
 <gml:description<This is the Hostip Lookup Service</gml:description>
 <gml:name>hostip</gml:name>
 <gml:boundedBy>
  <gml:Null>inapplicable</gml:Null>
 </gml:boundedBy>
 <gml:featureMember>

  <Hostip>
   <gml:name>Miami, FL</gml:name>
   <countryName>UNITED STATES</countryName>
   <countryAbbrev>US</countryAbbrev>
   <!-- Co-ordinates are available as lng,lat -->
   <ipLocation>
    <gml:PointProperty>

     <gml:Point srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
      <gml:coordinates>-80.2108,25.7757</gml:coordinates>
     </gml:Point>
    </gml:PointProperty>
   </ipLocation>
  </Hostip>
 </gml:featureMember>
</HostipLookupResultSet>

I had never done anything with XML in python so I figured I would write a function to wrap the API call. A few google searches led me to minidom and the rest was cake. The function takes in an IP address (string) and returns a dictionary with the geo information. I am a python noob and this code feels a little sketchy to me, so any feedback is more than welcome!


import urllib
from xml.dom import minidom

GEO_IP_LOOKUP_URL = 'http://api.hostip.info/?ip=%s'
GML_NS = 'http://www.opengis.net/gml'

def geo_ip_lookup(ip_address):
    """
    Look up the geo information based on the IP address passed in
    """
    dom = minidom.parse(urllib.urlopen(GEO_IP_LOOKUP_URL % ip_address))
    elem = dom.getElementsByTagName('Hostip')[0]
    location = elem.getElementsByTagNameNS(GML_NS, 'name')[0].firstChild.data.partition(',')

    try:
        latlong = elem.getElementsByTagNameNS(GML_NS, 'coordinates')[0].firstChild.data.partition(',')
    except:
        # lat/long isnt always returned
        latlong = None

    return {
            'country_code': elem.getElementsByTagName('countryAbbrev')[0].firstChild.data,
            'country_name': elem.getElementsByTagName('countryName')[0].firstChild.data,
            'locality': location[0].strip(),
            'region': location[2].strip(),
            'longitude': latlong[0].strip() if latlong else '',
            'latitude': latlong[2].strip() if latlong else ''
    }

Calling it from the interpreter:

>>> geo_ip_lookup('65.34.176.69')
{'locality': u'Miami', 'region': u'FL', 'longitude': u'-80.2108', 'latitude': u'25.7757', 'country_code': u'US', 'country_name': u'UNITED STATES'}
>>>

Tags:

Powered by my hackings on Django-Mingus a Django project, PostgreSQL, memcached, nginx, Apache + mod_wsgi, Ubuntu, Rackspace Cloud,...

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

html5 | top