initial geocoder test

This commit is contained in:
Amy Bowersox 2020-08-14 17:02:47 -06:00
parent cda2195419
commit 70a33ff00d
4 changed files with 142 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
geoapi.ini
.idea/

9
distance-calc.iml Executable file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

12
geoapi.ini.template Executable file
View File

@ -0,0 +1,12 @@
[google]
apikey=<<API KEY HERE>>
[mapquest]
apikey=<<CONSUMER KEY HERE>>
secret=<<CONSUMER SECRET HERE>>
[geocodio]
apikey=<<API KEY HERE>>
[locationiq]
token=<<TOKEN HERE>>

119
src/gcoder.py Executable file
View File

@ -0,0 +1,119 @@
# GCoder.py: basic geocoding test
import sys
import argparse
import json
import configparser
import urllib.parse
import urllib.request
class GeocodingError(RuntimeError):
pass
def geocode_google(config, address):
apikey = config['google']['apikey']
if not apikey:
raise GeocodingError("Google API key not specified")
query = { 'key': apikey, 'address': address, 'region': 'us'}
url = 'https://maps.googleapis.com/maps/api/geocode/json?' + \
urllib.parse.urlencode(query, quote_via=urllib.parse.quote)
with urllib.request.urlopen(url) as response:
if response.status == 200:
apireturn = json.loads(response.read())
stat = apireturn['status']
if stat == 'OK':
results = apireturn['results']
if len(results) > 1:
raise GeocodingError(f"Google API returned ambiguous results (total count {len(results)})")
coords = results[0]['geometry']['location']
return coords['lat'], coords['lng']
else:
raise GeocodingError(f"Google API returns status of {stat}")
else:
raise GeocodingError(f"Google API returns {response.status} HTTP status code")
def geocode_mapquest(config, address):
apikey = config['mapquest']['apikey']
if not apikey:
raise GeocodingError("MapQuest API key not specified")
query = { 'key': apikey, 'inFormat': 'kvp', 'outFormat': 'json', 'location': address,
'thumbMaps': 'false', 'maxResults': 1}
url = 'https://www.mapquestapi.com/geocoding/v1/address?' + urllib.parse.urlencode(query)
with urllib.request.urlopen(url) as response:
if response.status == 200:
apireturn = json.loads(response.read())
stat = apireturn['info']['statuscode']
if stat == 0:
results = apireturn['results']
if len(results) > 1:
raise GeocodingError(f"MapQuest API returned ambiguous results (total count {len(results)})")
locations = results[0]['locations']
if len(locations) > 1:
raise GeocodingError(f"MapQuest API returned ambiguous locations (total count {len(locations)})")
coords = locations[0]['latLng']
return coords['lat'], coords['lng']
else:
raise GeocodingError(f"MapQuest API returns status of {stat}")
else:
raise GeocodingError(f"MapQuest API returns {response.status} HTTP status code")
def geocode_geocodio(config, address):
apikey = config['geocodio']['apikey']
if not apikey:
raise GeocodingError("Geocodio API key not specified")
query = {'q': address, 'api_key': apikey}
url = 'https://api.geocod.io/v1.6/geocode?' + urllib.parse.urlencode(query)
with urllib.request.urlopen(url) as response:
if response.status == 200:
apireturn = json.loads(response.read())
coords = apireturn['results'][0]['location']
return coords['lat'], coords['lng']
else:
raise GeocodingError(f"Geocodio API returns {response.status} HTTP status code")
def geocode_locationiq(config, address):
apikey = config['locationiq']['token']
if not apikey:
raise GeocodingError("LocationIQ API key not specified")
query = {'q': address, 'key': apikey, 'format': 'json', 'limit': 1}
url = 'https://us1.locationiq.com/v1/search.php?' + urllib.parse.urlencode(query, quote_via=urllib.parse.quote)
with urllib.request.urlopen(url) as response:
if response.status == 200:
apireturn = json.loads(response.read())
place = apireturn[0]
return place['lat'], place['lon']
else:
raise GeocodingError(f"LocationIQ API returns {response.status} HTTP status code")
geocoding_procs = {
'google': geocode_google,
'mapquest': geocode_mapquest,
'geocodio': geocode_geocodio,
'locationiq': geocode_locationiq
}
cmdline_parser = argparse.ArgumentParser()
cmdline_parser.add_argument('address', nargs='+', help='The address to be geocoded')
cmdline_parser.add_argument('-C', '--config', default='geoapi.ini', help='The geocoding API configuration file')
cmdline_parser.add_argument('-g', '--geocoder', default='google', choices=geocoding_procs.keys(),
help='Geocoding processor to use to get coordinates (default: google)')
def main(args):
opts = cmdline_parser.parse_args(args)
config = configparser.ConfigParser()
config.read(opts.config)
my_address = ' '.join(opts.address)
print(f"Address: '{my_address}'")
coords = geocoding_procs[opts.geocoder](config, my_address)
print(f"Coordinates: Latitude {coords[0]}, longitude {coords[1]}")
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))