15. May 2019
Azure MapsWe need to admit: No one is using Bing, am I right? No, seriously: Microsoft definitely missed the cloud computing and mapping developments in the past. Personally, I don’t know anyone using Bing Maps / Azure Maps at all. Yet, the recent changes in the pricing scheme for Google Maps Services might reshape the market a bit. So how do we use Azure Maps for, let’s say, geocoding.
The API SubscriptionTo use the geocoding service from Azure Maps you first need to create an Azure Maps account after you created an Microsoft Azure account. And yes, you will need a credit card already. And no, you can’t use the same payment details for two different subscriptions ;-).
For simple geocoding you will be fine with a S0 subscription which will give cost you €0.422 per 1,000 transactions (/geocodes). This price is well above the included transactions of a Freemium subscription at HERE. Once you have registered for the API you can use you subscription-key:
The Python CodeI don’t want to go too far with processing and plugins but want to share the simple code for requesting the API, getting the found address as well as some quality indicator and the latitude/longitude of course:
import requests, json from qgis.core import QgsField, QgsFeature from PyQt5.QtCore import QVariant query = r'Mörikestraße 2, 06862 Dessau-Roßlau' key = "put you fancy Primary Key here" r = requests.get('https://atlas.microsoft.com/search/fuzzy/json?api-version=1.0&subscription-key=' + key + '&query=' + query)Now, as the query is set and send, we will deal with the response. But first, let’s create a layer for the result:
layer = QgsVectorLayer( "Point?crs=EPSG:4326", "AddressLayer", "memory" ) layer.dataProvider().addAttributes([ QgsField("id",QVariant.Int), QgsField("oldAddress",QVariant.String), QgsField("newAddress",QVariant.String), QgsField("score",QVariant.Double), QgsField("lat",QVariant.Double), QgsField("lon",QVariant.Double) ]) layer.updateFields()Our result will have some more “hits” as well as additional attributes but we will only use the one with the largest score and most important attributes:
fet = QgsFeature() fet.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(r.json()["results"]["position"]["lon"],r.json()["results"]["position"]["lat"]))) fet.setAttributes([ 0, query, r.json()["results"]["address"]["freeformAddress"], r.json()["results"]["score"], r.json()["results"]["position"]["lat"], r.json()["results"]["position"]["lon"] ]) pr = layer.dataProvider() pr.addFeatures([fet]) QgsProject.instance().addMapLayer(layer)As you can see, we got some results here: In this example we used the “fuzzy search” approach. if you have a defined address structure, you might also want to try out the structured search or only “address search”. Fortunately, especially the address search uses a similar result schema, so you could easily change the above script and use:
r = requests.get('https://atlas.microsoft.com/search/address/json?api-version=1.0&subscription-key=' + key + '&query=' + query)Happy geocoding, everyone!