Probieren Sie die nächste Generation von Directions-Funktionen mit der Routes API aus.

Best Practices für die Verwendung der Directions API-Webdienste

Die Google Maps Platform-Webdienste sind eine Sammlung von HTTP-Schnittstellen zu Google-Diensten, die geografische Daten für Ihre Kartenanwendungen bereitstellen.

In diesem Leitfaden werden einige gängige Vorgehensweisen zum Einrichten deiner Webdienstanfragen und der Verarbeitung von Dienstantworten beschrieben. Im Entwicklerhandbuch finden Sie die vollständige Dokumentation für die Directions API.

Was ist ein Webdienst?

Die Google Maps Platform-Webdienste sind eine Schnittstelle, über die Sie Maps API-Daten von externen Diensten anfordern und die Daten in Ihren Maps-Anwendungen nutzen können. Diese Dienste sind für die Verwendung in Kombination mit einer Karte konzipiert, wie in den Lizenzbeschränkungen der Nutzungsbedingungen für die Google Maps Platform beschrieben.

Die Google Maps APIs-Webdienste verwenden HTTP(S)-Anfragen an bestimmte URLs und übergeben URL-Parameter und/oder POST-Daten im JSON-Format als Argumente an die Dienste. Im Allgemeinen geben diese Dienste im Antworttext entweder JSON oder XML zum Parsen und/oder Verarbeiten durch Ihre Anwendung zurück.

Eine typische Directions API-Anfrage hat normalerweise die folgende Form:

https://maps.googleapis.com/maps/api/directions/output?parameters

Dabei gibt output das Antwortformat an (in der Regel json oder xml).

Hinweis: Für alle Directions API-Anwendungen ist eine Authentifizierung erforderlich. Weitere Informationen zu Anmeldedaten für die Authentifizierung

SSL-/TLS-Zugriff

HTTPS ist für alle Google Maps Platform-Anfragen erforderlich, die API-Schlüssel verwenden oder Nutzerdaten enthalten. Anfragen über HTTP, die vertrauliche Daten enthalten, werden möglicherweise abgelehnt.

Gültige URL erstellen

Es mag den Anschein haben, dass „gültige“ URLs eine Selbstverständlichkeit sind. Das ist jedoch nicht der Fall. So kann beispielsweise eine URL, die in die Adresszeile eines Browsers eingegeben wird, Sonderzeichen wie "上海+中國" enthalten; der Browser muss diese Zeichen vor der Übertragung intern in eine andere Codierung umwandeln. Ebenso ist es möglich, dass Code, der UTF-8-Eingaben erzeugt oder akzeptiert, URLs mit UTF-8-Zeichen als „gültig“ behandelt; diese Zeichen müssten jedoch vor dem Senden an einen Webbrowser ebenfalls umgewandelt werden. Dieser Vorgang wird als URL-Codierung oder Prozentcodierung bezeichnet.

Sonderzeichen

Sonderzeichen müssen umgewandelt werden, da alle URLs der Syntax entsprechen müssen, die in der Spezifikation Uniform Resource Identifier (URI) angegeben ist. Das bedeutet, dass URLs nur einen Teil der ASCII-Zeichen enthalten dürfen: die bekannten alphanumerischen Symbole und einige reservierte Zeichen, die in den URLs als Steuerzeichen dienen. Hier eine Übersicht:

Gültige URL-Zeichen
ZeichensatzcharactersVerwendung in der URL
Alphanumerisch b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N N P P R R S T U V W X Y Z 0 1 2 3 4 5 6 5 6 Textstrings, Schemas (http), Portangaben (8080) usw.
Nicht reserviert - _ . ~ Text
Reserviert ! * ' ( ) ; : @ & = + $ , / ? % # [ ] Steuerzeichen und/oder Text

Beachte bei der Generierung einer URL, dass sie nur die in der Tabelle aufgeführten Zeichen enthalten darf. Die Anpassung der URL an diesen Zeichensatz führt in der Regel zu zwei Problemen, nämlich dass Zeichen weggelassen oder ersetzt werden müssen:

  • Die Zeichen, die du verarbeiten möchtest, sind nicht im obigen Zeichensatz enthalten. So müssen beispielsweise Zeichen ausländischer Sprachen, wie 上海+中國, mithilfe der oben angegebenen Zeichen codiert werden. Auch werden Leerzeichen, die innerhalb von URLs nicht zulässig sind, entsprechend den geltenden Konventionen oftmals durch das Zeichen '+' dargestellt.
  • Die Zeichen sind im obigen Zeichensatz als reservierte Zeichen enthalten, müssen aber im ursprünglichen Sinn des Zeichens verwendet werden. So wird beispielsweise ? in URLs für den Beginn eines Abfragestrings verwendet. Möchtest du es stattdessen für den Text „? and the Mysterions“ verwenden, musst du das Zeichen '?' codieren.

Alle Zeichen, die als URL codiert werden sollen, werden mithilfe des Zeichens '%' und eines Hexadezimalwerts aus zwei Zeichen codiert, der ihrem UTF-8-Zeichen entspricht. So würde zum Beispiel der UTF-8-String 上海+中國 durch die URL-Codierung in %E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B umgewandelt. Und aus ? and the Mysterians würde %3F+and+the+Mysterians oder %3F%20and%20the%20Mysterians werden.

Allgemeine Zeichen, die codiert werden müssen

Folgende häufig vorkommende Zeichen müssen codiert werden:

Unsicheres Zeichen Codierter Wert
Leertaste %20
" %22
< %3C
> %3E
# %23
% %25
| %7C

Die Konvertierung von URLs, die aus Nutzereingaben empfangen werden, kann manchmal Probleme mit sich bringen. Beispielsweise kann ein Nutzer eine Adresse als „5th&Main St.“ eingeben. Im Allgemeinen solltest du die URL aus ihren Teilen erstellen und jede Nutzereingabe wortwörtlich betrachten.

Außerdem sind URLs für alle Google Maps Platform-Webdienste und statischen Web APIs auf 8.192 Zeichen beschränkt. Bei den meisten Diensten wird diese Begrenzung selten erreicht. Beachte jedoch, dass bestimmte Dienste einige Parameter haben, die zu langen URLs führen können.

Respektvolle Nutzung der Google APIs

Schlecht konzipierte API-Clients können sowohl im Internet als auch auf den Google-Servern mehr Last als nötig platzieren. Dieser Abschnitt enthält einige bewährte Methoden für Kunden der APIs. Mithilfe dieser Best Practices können Sie verhindern, dass Ihre Anwendung aufgrund von unbeabsichtigtem Missbrauch der APIs blockiert wird.

Exponentieller Backoff

In seltenen Fällen kann bei der Verarbeitung Ihrer Anfrage ein Fehler auftreten. Möglicherweise erhalten Sie einen 4XX- oder 5XX-HTTP-Antwortcode oder die TCP-Verbindung zwischen Ihrem Client und dem Google-Server schlägt fehl. Es lohnt sich oft, die Anfrage noch einmal zu wiederholen, da die nachfolgende Anfrage erfolgreich sein kann, wenn die ursprüngliche Anfrage fehlgeschlagen ist. Es ist jedoch wichtig, nicht wiederholt Anfragen an die Google-Server zu senden. Durch diese Schleife kann das Netzwerk zwischen Ihrem Client und Google überlastet werden, was für viele Parteien zu Problemen führen kann.

Ein besserer Ansatz ist es, wiederholte Versuche in immer größeren Abständen durchzuführen. In der Regel erhöht sich die Verzögerung bei jedem Versuch um einen multiplikativen Faktor. Dieser Ansatz wird als exponentieller Backoff bezeichnet.

Beispiel: Eine Anwendung möchte diese Anfrage an die Time Zone API senden:

https://maps.googleapis.com/maps/api/timezone/json?location=39.6034810,-119.6822510&timestamp=1331161200&key=YOUR_API_KEY

Im folgenden Beispiel mit Python wird gezeigt, wie die Anforderung mit exponentiellem Backoff durchgeführt wird:

import json
import time
import urllib.error
import urllib.parse
import urllib.request

# The maps_key defined below isn't a valid Google Maps API key.
# You need to get your own API key.
# See https://developers.google.com/maps/documentation/timezone/get-api-key
API_KEY = "YOUR_KEY_HERE"
TIMEZONE_BASE_URL = "https://maps.googleapis.com/maps/api/timezone/json"


def timezone(lat, lng, timestamp):

    # Join the parts of the URL together into one string.
    params = urllib.parse.urlencode(
        {"location": f"{lat},{lng}", "timestamp": timestamp, "key": API_KEY,}
    )
    url = f"{TIMEZONE_BASE_URL}?{params}"

    current_delay = 0.1  # Set the initial retry delay to 100ms.
    max_delay = 5  # Set the maximum retry delay to 5 seconds.

    while True:
        try:
            # Get the API response.
            response = urllib.request.urlopen(url)
        except urllib.error.URLError:
            pass  # Fall through to the retry loop.
        else:
            # If we didn't get an IOError then parse the result.
            result = json.load(response)

            if result["status"] == "OK":
                return result["timeZoneId"]
            elif result["status"] != "UNKNOWN_ERROR":
                # Many API errors cannot be fixed by a retry, e.g. INVALID_REQUEST or
                # ZERO_RESULTS. There is no point retrying these requests.
                raise Exception(result["error_message"])

        if current_delay > max_delay:
            raise Exception("Too many retry attempts.")

        print("Waiting", current_delay, "seconds before retrying.")

        time.sleep(current_delay)
        current_delay *= 2  # Increase the delay each time we retry.


if __name__ == "__main__":
    tz = timezone(39.6034810, -119.6822510, 1331161200)
    print(f"Timezone: {tz}")

Sie sollten außerdem darauf achten, dass der Code in der Anwendungsaufrufkette nicht wiederholt wird, was zu wiederholten Anfragen in kurzer Abfolge führt.

Synchronisierte Anforderungen

Eine große Anzahl synchronisierter Anfragen an die APIs von Google kann wie ein Distributed-Denial-of-Service-Angriff (DDoS) auf der Infrastruktur von Google aussehen und entsprechend behandelt werden. Achten Sie deshalb darauf, dass API-Anfragen zwischen Clients nicht synchronisiert werden.

Angenommen, eine Anwendung zeigt die Zeit in der aktuellen Zeitzone an. Diese Anwendung setzt wahrscheinlich einen Wecker im Betriebssystem des Clients, der zu Beginn der Minute aktiviert, damit die angezeigte Zeit aktualisiert werden kann. Die Anwendung darf im Rahmen der Verarbeitung dieses Alarms keine API-Aufrufe ausführen.

API-Aufrufe als Reaktion auf einen festen Alarm sind schlecht, weil die API-Aufrufe dadurch zu Beginn der Minute synchronisiert werden – auch zwischen verschiedenen Geräten – und nicht zeitlich gleichmäßig verteilt. Eine schlecht konzipierte Anwendung, die dies tut, erzeugt zu Beginn jeder Minute einen 60-fachen Anstieg des Traffics.

Stattdessen wird bei einer guten Lösung ein zweiter Alarm für eine zufällig gewählte Zeit festgelegt. Wenn diese zweite Auslösung ausgelöst wird, ruft die Anwendung alle benötigten APIs auf und speichert die Ergebnisse. Wenn die Anwendung zu Beginn der Minute ihre Anzeige aktualisieren möchte, verwendet sie zuvor gespeicherte Ergebnisse, anstatt die API noch einmal aufzurufen. Bei diesem Ansatz werden API-Aufrufe gleichmäßig über einen längeren Zeitraum verteilt. Außerdem verzögern die API-Aufrufe das Rendering nicht, wenn die Anzeige aktualisiert wird.

Abgesehen von den Startzeiten der Minute sollten Sie auch andere gängige Synchronisierungszeiten nicht auf den Beginn einer Stunde und jeden Tag um Mitternacht festlegen.

Antworten verarbeiten

In diesem Abschnitt wird gezeigt, wie diese Werte dynamisch aus Webdienstanforderungen extrahiert werden können.

Die Google Maps-Webdienste stellen Antworten bereit, die leicht verständlich, aber nicht besonders nutzerfreundlich sind. Wenn Sie eine Abfrage ausführen, anstatt einen Datensatz anzuzeigen, sollten Sie wahrscheinlich einige bestimmte Werte extrahieren. Im Allgemeinen möchten Sie wahrscheinlich Antworten aus dem Webdienst parsen und nur die für Sie relevanten Werte extrahieren.

Das verwendete Parsing-Schema hängt davon ab, ob Sie eine Ausgabe im XML- oder JSON-Format zurückgeben. JSON-Antworten, die bereits in Form von JavaScript-Objekten vorliegen, können in JavaScript selbst auf dem Client verarbeitet werden. XML-Antworten sollten mit einem XML-Prozessor und einer XML-Abfragesprache verarbeitet werden, um Elemente im XML-Format anzusprechen. In den folgenden Beispielen verwenden wir XPath, da es in XML-Verarbeitungsbibliotheken häufig unterstützt wird.

XML mit XPath verarbeiten

XML ist ein relativ ausgereiftes Format für strukturierte Informationen, das für den Datenaustausch verwendet wird. XML ist zwar nicht so schwer wie JSON, bietet jedoch mehr Sprachunterstützung und robustere Tools. Code zum Verarbeiten von XML in Java ist beispielsweise in die javax.xml-Pakete integriert.

Bei der Verarbeitung von XML-Antworten sollten Sie eine geeignete Abfragesprache zum Auswählen von Knoten im XML-Dokument verwenden, anstatt davon auszugehen, dass sich die Elemente an absoluten Positionen im XML-Markup befinden. XPath ist eine Sprachsyntax zur eindeutigen Beschreibung von Knoten und Elementen in einem XML-Dokument. Mit XPath-Ausdrücken können Sie bestimmte Inhalte im XML-Antwortdokument identifizieren.

XPath-Ausdrücke

Die Vertrautheit mit XPath ist ein langer Weg, um ein robustes Parsing-Schema zu entwickeln. In diesem Abschnitt geht es darum, wie Elemente in einem XML-Dokument mit XPath behandelt werden. So können Sie mehrere Elemente adressieren und komplexe Abfragen erstellen.

XPath nutzt Ausdrücke, um Elemente in einem XML-Dokument auszuwählen. Dabei wird eine Syntax verwendet, die der für Verzeichnispfade ähnelt. Mit diesen Ausdrücken werden Elemente in einer XML-Dokumentstruktur identifiziert, eine hierarchische Baumstruktur, die der eines DOM ähnelt. XPath-Ausdrücke sind grundsätzlich gierig. Das bedeutet, dass sie mit allen Knoten übereinstimmen, die den angegebenen Kriterien entsprechen.

Zur Veranschaulichung verwenden wir den folgenden abstrakten XML-Code:

<WebServiceResponse>
 <status>OK</status>
 <result>
  <type>sample</type>
  <name>Sample XML</name>
  <location>
   <lat>37.4217550</lat>
   <lng>-122.0846330</lng>
  </location>
 </result>
 <result>
  <message>The secret message</message>
 </result>
</WebServiceResponse>

Auswahl von Knoten in Ausdrücken

In der XPath-Auswahl werden Knoten ausgewählt. Der Stammknoten umfasst das gesamte Dokument. Sie wählen diesen Knoten mit dem Spezialausdruck "/" aus. Beachten Sie, dass der Stammknoten nicht der übergeordnete Knoten Ihres XML-Dokuments ist. Er befindet sich eine Ebene über diesem übergeordneten Element und schließt ihn ein.

Elementknoten stellen die verschiedenen Elemente in der XML-Dokumentstruktur dar. Ein <WebServiceResponse>-Element ist beispielsweise das Element der obersten Ebene, das im obigen Beispieldienst zurückgegeben wird. Sie wählen einzelne Knoten entweder über absolute oder relative Pfade aus, die durch das Vorhandensein oder Fehlen eines führenden /-Zeichens angegeben werden.

  • Absoluter Pfad: Mit dem Ausdruck „/WebServiceResponse/result“ werden alle <result>-Knoten ausgewählt, die dem <WebServiceResponse>-Knoten untergeordnet sind. Beachten Sie, dass beide Elemente vom Stammknoten „/“ abstammen.
  • Der relative Pfad aus dem aktuellen Kontext: Der Ausdruck „result“ entspricht allen <result>-Elementen im aktuellen Kontext. Im Allgemeinen müssen Sie sich über den Kontext keine Gedanken machen, da Sie die Webdienstergebnisse normalerweise über einen einzelnen Ausdruck verarbeiten.

Jeder dieser Ausdrücke kann durch Hinzufügen eines Platzhalterpfads („//“) erweitert werden. Dieser Platzhalter weist darauf hin, dass null oder mehr Elemente im dazwischenliegenden Pfad übereinstimmen können. Der XPath-Ausdruck „//formatted_address“ sucht beispielsweise nach allen Knoten dieses Namens im aktuellen Dokument. Der Ausdruck //viewport//lat würde mit allen <lat>-Elementen übereinstimmen, die <viewport> als übergeordnetes Element verfolgen können.

Standardmäßig finden XPath-Ausdrücke alle übereinstimmenden Elemente. Sie können den Ausdruck so einschränken, dass er mit einem bestimmten Element übereinstimmt. Dazu geben Sie ein Prädikat an, das in eckige Klammern eingeschlossen ist ([]). Der XPath-Ausdruck „/GeocodeResponse/result[2]“ gibt beispielsweise immer das zweite Ergebnis zurück.

Ausdruckstyp
Stammknoten
XPath-Ausdruck:/
Auswahl:
    <WebServiceResponse>
     <status>OK</status>
     <result>
      <type>sample</type>
      <name>Sample XML</name>
      <location>
       <lat>37.4217550</lat>
       <lng>-122.0846330</lng>
      </location>
     </result>
     <result>
      <message>The secret message</message>
     </result>
    </WebServiceResponse>
    
Absoluter Pfad
XPath-Ausdruck:/WebServiceResponse/result
Auswahl:
    <result>
     <type>sample</type>
     <name>Sample XML</name>
     <location>
      <lat>37.4217550</lat>
      <lng>-122.0846330</lng>
     </location>
    </result>
    <result>
     <message>The secret message</message>
    </result>
    
Pfad mit Platzhalter
XPath-Ausdruck:/WebServiceResponse//location
Auswahl:
    <location>
     <lat>37.4217550</lat>
     <lng>-122.0846330</lng>
    </location>
    
Pfad mit Prädikat
XPath-Ausdruck:/WebServiceResponse/result[2]/message
Auswahl:
    <message>The secret message</message>
    
Alle direkten untergeordneten Elemente der ersten result
XPath-Ausdruck:/WebServiceResponse/result[1]/*
Auswahl:
     <type>sample</type>
     <name>Sample XML</name>
     <location>
      <lat>37.4217550</lat>
      <lng>-122.0846330</lng>
     </location>
    
Die name von result, deren type-Text „sample“ ist.
XPath-Ausdruck:/WebServiceResponse/result[type/text()='sample']/name
Auswahl:
    Sample XML
    

Beachten Sie, dass Sie beim Auswählen von Elementen nicht nur den Text in diesen Objekten, sondern Knoten auswählen. Im Allgemeinen sollten Sie alle übereinstimmenden Knoten iterieren und den Text extrahieren. Sie können auch direkt Textknoten zuordnen. Weitere Informationen finden Sie unten im Abschnitt Textknoten .

XPath unterstützt auch Attributknoten. Allerdings liefern alle Google Maps-Webdienste Elemente ohne Attribute, sodass kein Abgleich von Attributen erforderlich ist.

Auswahl von Text in Ausdrücken

Text in einem XML-Dokument wird in XPath-Ausdrücken über einen Textknoten-Operator angegeben. Dieser Operator „text()“ gibt an, dass Text aus dem angegebenen Knoten extrahiert wird. So gibt beispielsweise der XPath-Ausdruck „//formatted_address/text()“ den gesamten Text in <formatted_address>-Elementen zurück.

Ausdruckstyp
Alle Textknoten (einschl. Leerzeichen)
XPath-Ausdruck://text()
Auswahl:
    sample
    Sample XML

    37.4217550
    -122.0846330
    The secret message
    
Textauswahl
XPath-Ausdruck:/WebServiceRequest/result[2]/message/text()
Auswahl:
    The secret message
    
Kontextbezogene Auswahl
XPath-Ausdruck:/WebServiceRequest/result[type/text() = 'sample']/name/text()
Auswahl:
    Sample XML
    

Alternativ können Sie einen Ausdruck auswerten und eine Gruppe von Knoten zurückgeben. Anschließend iterieren Sie über diese Gruppe von Knoten und extrahieren den Text aus den einzelnen Knoten. Dieser Ansatz wird im folgenden Beispiel dargestellt:

Weitere Informationen zu XPath finden Sie in der XPath-W3C-Spezifikation.

XPath in Java auswerten

Java bietet umfassende Unterstützung für das Parsen von XML und die Verwendung von XPath-Ausdrücken innerhalb des javax.xml.xpath.*-Pakets. Aus diesem Grund wird im Beispielcode in diesem Abschnitt Java verwendet, um zu zeigen, wie XML verarbeitet und Daten aus XML-Dienstantworten geparst werden.

Um XPath in Ihrem Java-Code zu verwenden, müssen Sie zuerst eine Instanz eines XPathFactory instanziieren und newXPath() für diese Factory aufrufen, um ein XPath -Objekt zu erstellen. Dieses Objekt kann dann übergebene XML- und XPath-Ausdrücke mit der Methode evaluate() verarbeiten.

Achten Sie bei der Auswertung von XPath-Ausdrücken darauf, alle möglichen „Knotengruppen“ zu iterieren, die möglicherweise zurückgegeben werden. Da diese Ergebnisse als DOM-Knoten in Java-Code zurückgegeben werden, sollten Sie solche mehreren Werte in einem NodeList-Objekt erfassen und dieses Objekt iterieren, um Text oder Werte aus diesen Knoten zu extrahieren.

Im folgenden Code sehen Sie, wie ein XPath-Objekt erstellt, ihm ein XML-Code und ein XPath-Ausdruck zugewiesen wird. Anschließend wird der Ausdruck ausgewertet, um den relevanten Inhalt auszudrucken.

import org.xml.sax.InputSource;
import org.w3c.dom.*;
import javax.xml.xpath.*;
import java.io.*;

public class SimpleParser {

  public static void main(String[] args) throws IOException {

	XPathFactory factory = XPathFactory.newInstance();

    XPath xpath = factory.newXPath();

    try {
      System.out.print("Web Service Parser 1.0\n");

      // In practice, you'd retrieve your XML via an HTTP request.
      // Here we simply access an existing file.
      File xmlFile = new File("XML_FILE");

      // The xpath evaluator requires the XML be in the format of an InputSource
	  InputSource inputXml = new InputSource(new FileInputStream(xmlFile));

      // Because the evaluator may return multiple entries, we specify that the expression
      // return a NODESET and place the result in a NodeList.
      NodeList nodes = (NodeList) xpath.evaluate("XPATH_EXPRESSION", inputXml, XPathConstants.NODESET);

      // We can then iterate over the NodeList and extract the content via getTextContent().
      // NOTE: this will only return text for element nodes at the returned context.
      for (int i = 0, n = nodes.getLength(); i < n; i++) {
        String nodeString = nodes.item(i).getTextContent();
        System.out.print(nodeString);
        System.out.print("\n");
      }
    } catch (XPathExpressionException ex) {
	  System.out.print("XPath Error");
    } catch (FileNotFoundException ex) {
      System.out.print("File Error");
    }
  }
}