Virtual Earth Geocoding Services - Python Style
In this log, I will take you through using Python to utilize the Virtual Earth geocoding services on your PyS60 handset.
Background
Geocoding is the analysis technique of geo-demographic data such as ZIP codes, counties, regions, etc. These techniques include, among others, translating a postal address into a geographical coordinates. Web portals such as Google Maps and Virtual Earth allow the users to do this through their portals. What if you had power to do this from a handset, which might not be able to open these JavaScript heavy web portals?
Virtual Earth Services
Virtual Earth is a Microsoft product that provides web bases map services amongst other to the users. You can find a US postal address on the map, find directions between 2 points, locate yourself on the map (e.g. based on your IP address) and lot more. These services are consumed by the code-behind running on the website and are invisible to the user. But a simple network packet watcher shows the following:
Find Address:
http://local.live.com/search.ashx?b=[address]
Locate Me:
http://local.live.com/WiFiIPService/locate.ashx
Find Directions:
http://local.live.com/directions.ashx?start=[address1]&end=[address2]
The responses are in form of C# code. E.g. when searching for an address, you can expect:
/*1.3.0515*/
SetViewport(32.9500497939651,-117.086802489646,32.9307362060349,-117.117483510354);
VE_Scratchpad.AddLocation('12278 Scripps Summit Dr, San Diego, CA 92131-3697, United States', 32.940393, -117.102143, '');
Python Solution
Of course, you can use all the frameworks available to achieve what we are set out to do. Our solution is quite elegant as you will see in some time. We make use of the fact that C# syntax resembles that of Python when it comes to arrays. If we take out comments, function names, and class names, we have tuple of arrays of tuples (see the example above).
The solution looks as follows:
# If needed set the proxy address
import os
os.environ['http_proxy'] = 'http://[proxy_host]:[proxy_port]/'
# Definations for eval()
false = 0
true = 1
import urllib
# To remove the comments and non-py elements in the response buffer
import re
comment_pat = re.compile('(/\*.*?\*/)(".*?")', re.S)
def subfunc(match):
if match.group(2):
return match.group(2)
else:
return ''
nonpy_pat = re.compile('(new [\w\s,.]+)(".*?")', re.S)
def getAddress(address):
encaddress = urllib.urlencode({'b': address})
url = 'http://local.live.com/search.ashx?%s' % encaddress
sock = urllib.urlopen(url)
resp = comment_pat.sub(subfunc, sock.read())
sock.close()
lines = resp.split(';')
for instruction in lines:
if instruction.find('VE_Scratchpad.AddLocation') > -1:
break
locationstr = instruction.replace('VE_Scratchpad.AddLocation', '')
(infostr, lat, lon, pad) = eval(locationstr)
return (infostr, lat, lon)
def locateMe():
url = 'http://local.live.com/WiFiIPService/locate.ashx'
sock = urllib.urlopen(url)
resp = comment_pat.sub(subfunc, sock.read())
sock.close()
locationstr = resp.replace('SetAutoLocateViewport', '')[:-1]
(lat, lon, zoomradius, unknown, message) = eval(locationstr)
return (lat, lon, zoomradius)
if __name__ == "__main__":
result = getAddress('12278 scripps summit dr san diego ca')
print result
result = locateMe()
print result
Summary
This example shows how simply Python eval() allows parsing complex text. I have left few issues to be addressed, such as ambigous address, etc. Moreover, you can explore the directions as well. Hope you enjoy!
Background
Geocoding is the analysis technique of geo-demographic data such as ZIP codes, counties, regions, etc. These techniques include, among others, translating a postal address into a geographical coordinates. Web portals such as Google Maps and Virtual Earth allow the users to do this through their portals. What if you had power to do this from a handset, which might not be able to open these JavaScript heavy web portals?
Virtual Earth Services
Virtual Earth is a Microsoft product that provides web bases map services amongst other to the users. You can find a US postal address on the map, find directions between 2 points, locate yourself on the map (e.g. based on your IP address) and lot more. These services are consumed by the code-behind running on the website and are invisible to the user. But a simple network packet watcher shows the following:
Find Address:
http://local.live.com/search.ashx?b=[address]
Locate Me:
http://local.live.com/WiFiIPService/locate.ashx
Find Directions:
http://local.live.com/directions.ashx?start=[address1]&end=[address2]
The responses are in form of C# code. E.g. when searching for an address, you can expect:
/*1.3.0515*/
SetViewport(32.9500497939651,-117.086802489646,32.9307362060349,-117.117483510354);
VE_Scratchpad.AddLocation('12278 Scripps Summit Dr, San Diego, CA 92131-3697, United States', 32.940393, -117.102143, '');
Python Solution
Of course, you can use all the frameworks available to achieve what we are set out to do. Our solution is quite elegant as you will see in some time. We make use of the fact that C# syntax resembles that of Python when it comes to arrays. If we take out comments, function names, and class names, we have tuple of arrays of tuples (see the example above).
The solution looks as follows:
# If needed set the proxy address
import os
os.environ['http_proxy'] = 'http://[proxy_host]:[proxy_port]/'
# Definations for eval()
false = 0
true = 1
import urllib
# To remove the comments and non-py elements in the response buffer
import re
comment_pat = re.compile('(/\*.*?\*/)(".*?")', re.S)
def subfunc(match):
if match.group(2):
return match.group(2)
else:
return ''
nonpy_pat = re.compile('(new [\w\s,.]+)(".*?")', re.S)
def getAddress(address):
encaddress = urllib.urlencode({'b': address})
url = 'http://local.live.com/search.ashx?%s' % encaddress
sock = urllib.urlopen(url)
resp = comment_pat.sub(subfunc, sock.read())
sock.close()
lines = resp.split(';')
for instruction in lines:
if instruction.find('VE_Scratchpad.AddLocation') > -1:
break
locationstr = instruction.replace('VE_Scratchpad.AddLocation', '')
(infostr, lat, lon, pad) = eval(locationstr)
return (infostr, lat, lon)
def locateMe():
url = 'http://local.live.com/WiFiIPService/locate.ashx'
sock = urllib.urlopen(url)
resp = comment_pat.sub(subfunc, sock.read())
sock.close()
locationstr = resp.replace('SetAutoLocateViewport', '')[:-1]
(lat, lon, zoomradius, unknown, message) = eval(locationstr)
return (lat, lon, zoomradius)
if __name__ == "__main__":
result = getAddress('12278 scripps summit dr san diego ca')
print result
result = locateMe()
print result
Summary
This example shows how simply Python eval() allows parsing complex text. I have left few issues to be addressed, such as ambigous address, etc. Moreover, you can explore the directions as well. Hope you enjoy!


1 Comments:
Nice! thanks for the python example.
Post a Comment
Links to this post:
Create a Link
<< Home