Accessing xServer internet from Python

This section explains how to request xLocateServer with python inside QGIS. The result of the request will be displayed as a layer on the map.

Add Python HTTP Requests to QGIS

The xServer python script uses the requests extension to call xServer internet. You can get it from the GitHub repository https://github.com/kennethreitz/requests

Just download it and add the folder requests to the QGIS Python folder, e.g. C:\Program Files\QGIS Brighton\apps\Python27

Add the script to the processing toolbox

You can start a script within QGIS by adding a .py file to the processing toolbox.

  • Paste the script code below to a file named xlocate_findaddress.py
  • Copy the file to the folder <User Folder>\.qgis2\processing\scripts
  • Open the processing toolbox under Processing->Toolbox
  • Now you can start the script by double-clicking on the item Scripts->[PTV scripts]->xlocate_findaddress in the tree.

Run the script and validate the result

Enter your token into the dialog, set the address and press Run. A new layer output_geoc is added to the map. The layer displays the result locations of the geocoding. You can also open the result as a table by right-clicking on the layer and opening the attribute table.

The script

#a simple geocoding request that displays the result as a QGIS layer
##[PTV scripts]=group
##cluster=string eu-n-test
##token=string enter your token here
##country=string 
##address=string Neustadt
##output_geoc=output vector

import fileinput
import sys, os, json, requests
from PyQt4.QtCore import *
from qgis.core import *
from qgis.utils import *
from requests.auth import HTTPBasicAuth

# our geocoding function
def findAddressByText(url, token, country, address):
        
        header = {'content-type': 'application/json'}
        request = { "address": address,
			"country": country,
			"options": [],
			"sorting": [],
			"additionalFields": [],
			"callerContext": {
				"properties": [{"key": "CoordFormat","value": "OG_GEODECIMAL"},{"key": "Profile","value": "default"},{"key": "ResponseGeometry", "value": "WKT"}
			]}
		}
		
        jsondata = json.dumps(request)
        jsonresp = requests.post(url = url, data = jsondata, headers = header, auth = HTTPBasicAuth('xtok', token))
            				
        if jsonresp.status_code == 200:            
            pyresp = json.loads(jsonresp.text)
            jsonresponse = pyresp["resultList"]
		
            return jsonresponse
        else:
			raise Exception("Web error " + str(jsonresp.status_code))

# build url 			        
url = "https://xlocate-" + cluster + ".cloud.ptvgroup.com/xlocate/rs/XLocate/findAddressByText"

# invoke the geocoding
jsonresponse = findAddressByText(url, token, country, address)

# build the fields collection
fields = QgsFields()                                  # 2: Integer 6: Float  10: String
fields.append(QgsField("id", 2,"Integer"))
fields.append(QgsField("country", 10, "String", 32))
fields.append(QgsField("state", 10,"String", 128))
fields.append(QgsField("postcode", 10,"String", 12))
fields.append(QgsField("city", 10,"String", 128))
fields.append(QgsField("city2", 10,"String", 128))
fields.append(QgsField("street", 10,"String", 128))
fields.append(QgsField("houseNumber", 10,"String", 32))
fields.append(QgsField("adminRegion", 10,"String", 128))
fields.append(QgsField("totalScore", 2,"Integer"))
        
# create the output layer
outputLayer = QgsVectorFileWriter(output_geoc, None, fields, QGis.WKBPoint,QgsCoordinateReferenceSystem(4326))

# fill the layer data
count=0
for resultList in jsonresponse:
    count+=1
    country=resultList["country"]
    state=resultList["state"]
    postcode=resultList["postCode"]
    city=resultList["city"]
    city2=resultList["city2"]
    street=resultList["street"]
    housenumber=resultList["houseNumber"]
    score=resultList["totalScore"]
    adminRegion=resultList["adminRegion"]
    geomwkt=resultList["coordinates"]["wkt"]
  
    outFeat = QgsFeature()    
    outFeat.setGeometry(QgsGeometry.fromWkt(geomwkt))
    outFeat.setAttributes([count, country, state, postcode, city, city2, street, housenumber, adminRegion, score])
	
    outputLayer.addFeature(outFeat)
    
progress.setText("Geocoding matches: " + str(count))
progress.setText("---------------------------------------")
del outputLayer