Generating statics maps with Google Maps and Python

Posted by in Python

Today’s entrance is dedicated to solve a problem that I received from on of the readers of this blog, and I would like to share with you the solution: a small Python script using Google Maps for creating images of static maps to show locations. The main goal is to use this static maps as part of informs, and by using thi script my reader could accelerate and automatize this process. The alternative was doing it using ArcGIS, doing several steps.

The problem

There is alist of named points with its lon-lat, and the goal is to generate a map of each location. One cool alternative is to use static maps of Google Maps. The solution showed here is onle for one point, introduced manually, but once you know the structure of data, the rest is easy: load the collection of named points, create the structure data designed and apply the function to save the map as a file.

The main benefit of this exercise is to explain how easy you can create this types of maps that you neeed in your documents. If you only have one point, you work with URL and you got it, but if you need to do it several times, there is nothiing better than a small Python script.

The solution to the problem will be divided in three parts: URL preparation, URL download, and save image to file.

1.- URL preparation

Maybe, this is the hard part of the problem, because you need to accomplish Google Maps rules, available in the documentation. Read it carefully and you can notice that you even don’t need Javascript.

For preparing the URL, there are a few thing you must know for the configuration:

  • center, with lon-lat to represent
  • zoom, is the zoom level you need, from 1 (general) to 20 (more concrete and close).
  • size, is the size of the image to be generated. For example, 400×400, but you can select what you need.
  • maptype, is the type of map you need, and you have several options: hybrid, sensor, satellite, …
  • format, is another optional parameter to specify the format of the image to receive. By default is png, but you can change it to jpg.
  • markers, is optional too,  and it’s what you need in order to show a marker in your map. The sintax is: color, label and position.

Although I haven’t used for the solution, here you have a function (the original function is here) for creating urls:


def get_static_google_map(filename_wo_extension, center=None, zoom=None, imgsize="500x500", imgformat="jpeg",
maptype="roadmap", markers=None ):
"""retrieve a map (image) from the static google maps server

See: http://code.google.com/apis/maps/documentation/staticmaps/

Creates a url2 string with a URL like this:
http://maps.google.com/maps/api/staticmap?center=Brooklyn+Bridge,New+York,NY&zoom=14&size=512x512&maptype=roadmap
&markers=color:blue|label:S|40.702147,-74.015794&sensor=false"""

# assemble the URL
url2  =  "http://maps.google.com/maps/api/staticmap?" # base URL, append query params, separated by &

# if center and zoom  are not given, the map will show all marker locations
if center != None:
url2 += "center=%s&" % center
#url2 += "center=%s&" % "40.714728, -73.998672"   # latitude and longitude (up to 6-digits)
#url2 += "center=%s&" % "50011" # could also be a zipcode,
#url2 += "center=%s&" % "Brooklyn+Bridge,New+York,NY"  # or a search term
if center != None:
url2 += "zoom=%i&" % zoom  # zoom 0 (all of the world scale ) to 22 (single buildings scale)

url2 += "size=%ix%i&" % (imgsize)  # tuple of ints, up to 640 by 640
url2 += "format=%s&" % imgformat
url2 += "maptype=%s&" % maptype  # roadmap, satellite, hybrid, terrain

# add markers (location and style)
if markers != None:
for marker in markers:
url2 += "%s&" % marker

#url2 += "mobile=false&"  # optional: mobile=true will assume the image is shown on a small screen (mobile device)
url2 += "sensor=false&"   # must be given, deals with getting loction from mobile device
return url2

For example, let’s create an URL to link to my city, where I live.

Mapa estático desde Google Maps

The URL is: http://maps.google.com/maps/api/staticmap?center=37.8654938,-4.7791247&zoom=14&size=512×512&maptype=roadmap&markers=color:blue|label:M|37.8654938,-4.7791247&sensor=false.

But for my solution I have used a function for processing the data when generating the URL:


tmp_url = "https://maps.googleapis.com/maps/api/staticmap?center={lat},{lon}&zoom=17&size=400x400&maptype=satellite&markers=color:green|label:|{lat},{lon}"

def crea_url(datos):
return tmp_url.format(**datos)

Dato structure

For this exercise, data to be processed should be a dictionary with the fields: lon, lat y nombre.

2.- URL download

This second part is more easy, because you already read how to download HTML code using Python (and alsoC#). Here I will use request, library, very easy to use instead of urllib2. Also, I have configured in case you need to use a proxy server.


import requests

proxy = "127.0.0.1:8080"
proxies = {"http": proxy, "https": proxy}
sesion = requests.Session()
sesion.proxies = proxies

If you don’t need a proxy, then proxies = { }. Now, everything is ready for downloading URLs.

3.- Save the image to a file

The last step is to retrieve the data and save it to a image file.


def save_imagen(datos):
url = crea_url(datos)
r = sesion.get(url)
f=open('%s.png' % datos["nombre"],'wb')
f.write(r.content)
f.close()

You have the full code available on GitHub, ready for you to use or modify.


# coding:utf-8
from __future__ import print_function
from __future__ import division

__UPDATED__ = '2015.06.22'
__WEBSITE__ = 'http://www.manejandodatos.es'
__VERSION__ = "1.0.0"

import requests

# URLs antiguas
# url = "https://maps.googleapis.com/maps/api/staticmap?center=-38.25466,-4.971062&zoom=13&size=600x300&maptype=roadmap&markers=color:blue|label:S|40.702147,-74.015794&markers=color:green|label:G|40.711614,-74.012318&markers=color:red|label:C|40.718217,-73.998284"
tmp_url = "https://maps.googleapis.com/maps/api/staticmap?center={lat},{lon}&zoom=17&size=400x400&maptype=satellite&markers=color:green|label:|{lat},{lon}"

def crea_url(datos):
return tmp_url.format(**datos)

def save_imagen(datos):
url = crea_url(datos)
r = sesion.get(url)
f=open('%s.png' % datos["nombre"],'wb')
f.write(r.content)
f.close()

proxy = ""  # In case you need a proxy
proxies = {"http": proxy, "https": proxy}
sesion = requests.Session()
sesion.proxies = proxies

# Aqui se modifican los datos
datos = {"lat": 37.8654938, "lon": -4.7791247, "nombre": "gm2img"}

save_imagen(datos)

When you run the code, the image will be stored in the same dir where the script is.

Fichero imagen creado

Fichero imagen creado

My reader is delighted with the solution, so I hope this entrance should be of your interest, too!

Happy coding.