Skip to content

Instantly share code, notes, and snippets.

@dannguyen
Last active November 15, 2017 21:06
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dannguyen/8c0e4c3c720d6da25f49 to your computer and use it in GitHub Desktop.
Save dannguyen/8c0e4c3c720d6da25f49 to your computer and use it in GitHub Desktop.
Quick command-line script in Python 3 to geocode a location using Google Maps Geocoding API
#!/usr/bin/env python3
#
# A Python 3.x script designed for command-line operation:
# Given a location string, passes it to Google's Geocoding API and prints to stdout: lat, lng,
# level of accuracy, and formatted address, as a single delimited line and, optionally, the raw JSON
# This is one in a series of mundane programming examples:
# - srccon.org/sessions/#proposal-106215
# - https://docs.google.com/spreadsheets/d/1oaUNiWOyuTmxr0hVgx32vr5XN8E4MEb_2FD56BE6mZA/edit?usp=drive_web
#
# Documentation of Google Maps API
# https://developers.google.com/maps/documentation/geocoding/
#
# Usage:
#
# $ script.py "100 Broadway New York, NY"
#
# Response:
#
# 40.70791579999999 -74.01107309999999 ROOFTOP 100 Broadway, New York, NY 10006, USA
#
#
# usage: script.py [-h] [--copy] [--delimiter DELIMITER] [--json] addr
# positional arguments:
# addr Enter an address, preferably quoted
# optional arguments:
# -h, --help show this help message and exit
# --copy, -c Copy JSON response to file at current directory
# --delimiter DELIMITER, -d DELIMITER
# Use specified delimiter between values; default is `\t`
# --json, -j Instead of the tab-delimited values, print the JSON
# response to stdout
########################################
import argparse
import csv
import requests
from io import StringIO
from urllib.parse import quote_plus
GOOGLE_MAPS_URL = "https://maps.googleapis.com/maps/api/geocode/json"
parser = argparse.ArgumentParser()
# Configure the parser
parser.add_argument("addr",
nargs = 1,
help = "Enter an address, preferably quoted")
parser.add_argument('--copy', '-c',
action = 'store_true',
help = 'Copy JSON response to file at current directory')
parser.add_argument('--delimiter', '-d',
default = "\t",
help = 'Use specified delimiter between values; default is `\\t`')
parser.add_argument('--json', '-j',
action = 'store_true',
help = 'Instead of the tab-delimited values, print the JSON response to stdout')
# Begin the command-line operation
args = parser.parse_args()
addr = args.addr[0]
resp = requests.get(GOOGLE_MAPS_URL, params = {'address': addr})
results = resp.json()['results']
if results:
if args.json:
# Print the raw JSON response
print(resp.text)
else:
# We use the csv library to deal with any edge cases involving delimiters and escape-sequences
outs = StringIO()
c = csv.writer(outs, delimiter = args.delimiter, quoting = csv.QUOTE_MINIMAL)
r = results[0]
c.writerow([
r['geometry']['location']['lat'],
r['geometry']['location']['lng'],
r['geometry']['location_type'],
r['formatted_address']
])
# csv.writerow() adds a newline character that needs to be stripped
print(outs.getvalue().strip())
# Save to file with --copy
# "100 Broadway New York, NY"
# is saved to:
# ./100+Broadway+New+York%2C+NY.json
if args.copy:
fpath = quote_plus(addr) + '.json'
with open(fpath, 'w') as f:
f.write(resp.text)
# For now, no error-handling...if results list is empty, nothing is printed
{
"results" : [
{
"address_components" : [
{
"long_name" : "100",
"short_name" : "100",
"types" : [ "street_number" ]
},
{
"long_name" : "Broadway",
"short_name" : "Broadway",
"types" : [ "route" ]
},
{
"long_name" : "Lower Manhattan",
"short_name" : "Lower Manhattan",
"types" : [ "neighborhood", "political" ]
},
{
"long_name" : "Manhattan",
"short_name" : "Manhattan",
"types" : [ "sublocality_level_1", "sublocality", "political" ]
},
{
"long_name" : "New York",
"short_name" : "NY",
"types" : [ "locality", "political" ]
},
{
"long_name" : "New York County",
"short_name" : "New York County",
"types" : [ "administrative_area_level_2", "political" ]
},
{
"long_name" : "New York",
"short_name" : "NY",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "United States",
"short_name" : "US",
"types" : [ "country", "political" ]
},
{
"long_name" : "10006",
"short_name" : "10006",
"types" : [ "postal_code" ]
}
],
"formatted_address" : "100 Broadway, New York, NY 10006, USA",
"geometry" : {
"location" : {
"lat" : 40.70791579999999,
"lng" : -74.01107309999999
},
"location_type" : "ROOFTOP",
"viewport" : {
"northeast" : {
"lat" : 40.70926478029149,
"lng" : -74.00972411970849
},
"southwest" : {
"lat" : 40.7065668197085,
"lng" : -74.0124220802915
}
}
},
"place_id" : "ChIJywL_PBdawokR4bOmKjJY3QE",
"types" : [ "street_address" ]
}
],
"status" : "OK"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment