Artikel getaggt mit ‘ArcGIS Server’

Januar 12th, 2011

ArcGIS Server REST-Schnittstelle mit Python auslesen

Wenn mit ESRI ArcGIS Server Dienste veröffentlicht werden, kann für jeden Dienst die REST-Schnittstelle abgerufen werden.
Diese offenbart einige Informationen über den angebotenen Dienst. Sie kann ganz simpel mit dem Browser angesteuert werden wie die Dokumentation von ESRI verrät:

The ArcGIS Server REST API, short for Representational State Transfer, provides a simple, open Web interface to services hosted by ArcGIS Server. All resources and operations exposed by the REST API are accessible through a hierarchy of endpoints or Uniform Resource Locators (URLs) for each GIS service published with ArcGIS Server.

When using the REST API, you typically start from a well-known endpoint, which represents the server catalog. The table of contents for this Help system mimics the hierarchy of resources in the REST API. The default start URL for an ArcGIS Server installation is:

  • Java:

http://<host>:8399/argis/rest

  • .NET:

http://<host>/arcgis/rest

Ein Beispiel für einen Aufruf der REST-Schnittstelle wäre demnach:

http://server.arcgisonline.com/arcgis/rest/services

Das Ergebnis im Browser entspricht dem Wurzelverzeichnis eines ArcGIS Servers. In dieser hierachischen Struktur kann man sich nun manuell durchklicken um zu Informationen über die angebotenen Dienste und ihrer Layer zu bekommen.

Dabei werden die Elementbezeichnung wie Folder oder Layernamen bei jedem Klick in die angezeigte URL übernommen – nach dem Schema:

http://<host>/arcgis/rest/services/<folder>/<service>/MapServer/

Ein beispielhafter Aufruf zu einem Layer im Dienst USA_1990-2000_Population_Change wäre damit:

http://server.arcgisonline.com/ArcGIS/rest/services/Demographics/USA_1990-2000_Population_Change/MapServer/

Hängt man an den Aufruf eine Formatanweisung hinzu, kann die Information nicht nur hübsch aufbereitet als HTML-Seite bezogen werden, sondern auch als JSON-Objekt.
Der Schlüssel dazu lautet: ?f=pjson und die gesamte URL nun:

http://server.arcgisonline.com/ArcGIS/rest/services/Demographics/USA_1990-2000_Population_Change/MapServer/?f=pjson

Ein Ausschnitt des Ergebnisses diesen Aufrufs sieht folgendermaßen aus:

{
  "currentVersion" : 10.01,
  "serviceDescription" : "This thematic map indicates the annual compound rate of total population change in the United States from 1990 to 2000. Total Population is the total number of residents in an area.  Residence refers to the “usual place” where a person lives.  Total Population for 2000 is from the U.S. Census 2000.  Total Population for 1990 is from the 1990 U.S. Census adjusted to 2000 boundaries.  The geography depicts states at greater than 25m scale, counties at 1m to 25m scale, Census Tracts at 250k to 1m scale, and Census Block Groups at less than 250k scale. The map has been designed to be displayed with semi-transparency of about 50% for overlay on other base maps, which is reflected in the legend for the map.  For more information on this map, visit us \u003ca href=\"http://goto.arcgisonline.com/maps/Demographics/USA_1990-2000_Population_Change \" target=\"_new\"\u003eonline\u003c/a\u003e.",
  "mapName" : "Layers",
  "description" : "This thematic map indicates the annual compound rate of total population change in the United States from 1990 to 2000. Total Population is the total number of residents in an area. Residence refers to the “usual place” where a person lives. Total Population for 2000 is from the U.S. Census 2000. Total Population for 1990 is from the 1990 U.S. Census adjusted to 2000 boundaries. The geography depicts states at greater than 25m scale, counties at 1m to 25m scale, Census Tracts at 250k to 1m scale, and Census Block Groups at less than 250k scale. The map has been designed to be displayed with semi-transparency of about 50% for overlay on other base maps, which is reflected in the legend for the map.  For more information on this map, visit us online at http://goto.arcgisonline.com/maps/Demographics/USA_1990-2000_Population_Change",
  "copyrightText" : "Copyright:© 2010 ESRI",
  "layers" : [
    {
      "id" : 0,
      "name" : "USA 1990-2000 Population Change",
      "parentLayerId" : -1,
      "defaultVisibility" : true,
      "subLayerIds" : [1, 2, 3, 4],
      "minScale" : 0,
      "maxScale" : 0
    },
    {
      "id" : 1,
      "name" : "Block Groups",
      "parentLayerId" : 0,
      "defaultVisibility" : true,
      "subLayerIds" : null,
      "minScale" : 150000,
      "maxScale" : 0
     }

Dieses JSON-Objekt kann man nun in eigenem Code, der die URL ausliest, wunderbar weiterverarbeiten. Wunderbar deswegen, weil eine HTML-Ausgabe auszulesen dagegen ein ziemliches Gefrickel ist.

Ich wollte das Ganze mit Python anzapfen um Layerinformationen aus dem ArcGIS Server Dienst zu extrahieren. Dazu braucht es neben der urllib2 von Python noch das Modul simplejson, um die Informationen, die im JSON-Objekt gekapselt sind, auf einfache Weise in Python zugänglich zu machen.

Nach der Installation von simplejson kann es losgehen. Wir importieren simplejson und das Standardmodul urllib2, das die Verbindung zum Server übernimmt.

import simplejson as json
import urllib2
URL = "http://server.arcgisonline.com/ArcGIS/rest/services/Demographics/"

Anschließend definiere ich eine Funktion, die jeweils die Layer-ID und den Layernamen aus dem angegebenen Dienst anzeigen soll. Die Funktion benötigt nur eine URL zu einem ArcGIS Server und den Servicenamen, der abgefragt werden soll.  Selbstverständlich könnte man auch ganz oben in der Hierachie beginnen und aus dem Wurzelverzeichnis alle Diensteverzeichnisse auflisten lassen und dann weiter in die jeweiligen Dienste schauen. An dieser Stelle möchte ich jedoch nur einen einfachen Fall beschreiben.

def getLayerInfoFromREST(url, _serviceName):
    ''' Liest die Layer-IDs des ArcGIS REST Dienstes aus
        der angegebenen URL und liefert eine Liste mit den
        Layer-IDs (Strings) und den Layernamen zurück.
        Benötigtes Format der URL:
        http://<host>/ArcGIS/rest/services/<folder>/'''

    serviceName = _serviceName
    url = url + serviceName + '/MapServer/?f=pjson'

    response = urllib2.urlopen(url).read()
    jsonObj = json.loads(response)

Wir haben also die URL mit dem Servicenamen angereichert, eine Antwort des Servers auf unseren Request in das Objekt response gespeichert und zu guter Letzt die response als JSON-Objekt geladen. Denn auf unsere Anfrage in der URL mit der Endung ?f=pjson bekommen wir auf jeden Fall ein JSON-Objekt zurück. Jetzt initialisieren wir das Dictionary resultDict, das unser Ergebnis der Abfrage speichern wird. Auch das Element jsonObj ist ein Dictionary.
Den Inhalt des JSON-Objekts durchlaufen wir mit einer for-Schleife und der Funktion iterkeys(). Genauer gesagt durchlaufen wir nur die Keys des Dictionarys. Wenn der Key bzw. anschaulicher der Knoten „layers“ gefunden wurde, steigen wir mit der zweiten for-Schleife in diesen Knoten ein und iterieren über die untergeordneten Elemente. Auf dieser Ebene können nun die Layerinformationen abgerufen werden, z.B. die ID und der Name, welche mit der Funktion get() und dem entsprechendem Key abfragbar sind.
Nun wird das Ergebnis in das Dictionary resultDict gesichert.

    resultDict = {}
    for key in jsonObj.iterkeys():
        # layers entspricht dem Data Frame Namen des zugrunde-
        # liegenden ArcMap-Dokument und muss evtl. angepasst
        # werden
        if key == 'layers':
            root = jsonObj.get(key)

            for layerInfo in root:
                nameString = layerInfo.get('name')
                id = int(layerInfo.get('id'))

                resultDict[id] = nameString

    return resultDict

Jede Funktion muss auch aufgerufen werden, und genau das machen wir im folgenden. Die Parameter sind wie o.g. URL und ein Servicename.

# Funktionsaufruf
resultDict = getLayerInfoFromREST(URL, "USA_1990-2000_Population_Change")

for item in resultDict.iteritems():
    print item

In der Ausgabe des Skripts sehen wir nun die Layer-IDs und die Namen der Layer aus dem ArcGIS Server Dienst.

>>>
(0, 'USA 1990-2000 Population Change')
(1, 'Block Groups')
(2, 'Tracts')
(3, 'Counties')
(4, 'States')
>>>

Das Beispielsskript „jsonRESTSample.py“ kann hier gedownloaded werden.

5 Leute mögen diesen Artikel.