Sprawdzone metody korzystania z usług internetowych interfejsu Geocoding API

Usługi internetowe Google Maps Platform to zbiór interfejsów HTTP Google usługi udostępniające dane geograficzne na potrzeby aplikacji z mapami.

W tym przewodniku opisujemy kilka typowych sposobów konfigurowania usługa sieciowa żądań i przetwarzania odpowiedzi usługi. Zapoznaj się z przewodnikiem dla programistów. .

Co to jest usługa sieciowa?

Usługi internetowe Google Maps Platform to interfejs do żądania danych interfejsu API Map Google z usług zewnętrznych i wykorzystywanie danych w aplikacjach Mapy. Te usługi są przeznaczone do używania w połączeniu z mapą, zgodnie z Ograniczenia licencji w Warunkach korzystania z Google Maps Platform.

Usługi internetowe interfejsów API Map Google używają żądań HTTP(S) kierowanych do konkretnych adresów URL, przekazują parametry adresów URL lub Dane POST w formacie JSON jako argumenty dla usług. Usługi te zwracają dane w treść odpowiedzi w formacie JSON lub XML do analizy. lub przetwarzania przez aplikację.

Typowe żądanie do interfejsu Geocoding API jest zwykle ten formularz:

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

gdzie output oznacza format odpowiedzi (zwykle json lub xml).

Uwaga: wszystkie aplikacje interfejsu Geocoding API wymagają uwierzytelniania. Dowiedz się więcej o danych uwierzytelniających.

Dostęp SSL/TLS

Protokół HTTPS jest wymagany w przypadku wszystkich żądań Google Maps Platform, które używają kluczy interfejsu API lub zawierają użytkownika i skalowalnych danych. Żądania przesyłane za pomocą protokołu HTTP, które zawierają dane wrażliwe, mogą zostać odrzucone.

Tworzenie prawidłowego adresu URL

Może Ci się wydawać, że „prawidłowy”, Adres URL jest oczywisty, ale To nie do końca tak. Adres URL wpisany na pasku adresu w przeglądarka może na przykład zawierać znaki specjalne (np. "上海+中國"); przeglądarka musi wykonać wewnętrzne tłumaczenie zmień kodowanie tych znaków przed przesłaniem. Przy użyciu tego samego tokena każdy kod, który generuje lub akceptuje dane wejściowe UTF-8, może traktować adresy URL ze znakami UTF-8 jako „prawidłowe”, ale wymagają tego również przetłumaczyć te znaki przed wysłaniem ich na serwer WWW. Ten proces nazywa się Kodowanie adresów URL lub kodowanie procentowe.

Znaki specjalne

Znaki specjalne trzeba przetłumaczyć, Wszystkie adresy URL muszą spełniać składnię określoną w tagu Strój Specyfikacja identyfikatora zasobu (URI). Oznacza to, że adresy URL może zawierać tylko specjalny podzbiór znaków ASCII: znany symbole alfanumeryczne i niektóre znaki zarezerwowane do użytku jako elementy sterujące znaków w adresach URL. Tabela zawiera podsumowanie tych znaków:

Podsumowanie prawidłowych znaków adresu URL
UstawznakówUżycie adresu URL
Alfanumeryczne a b c d e f g h i j k l m n o p q r s t u v x y z A 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 0 1 2 3 4 5 6 7 8 9 Ciągi tekstowe, wykorzystanie schematu (http), port (8080) itp.
Niezarezerwowane - _ . ~ Ciągi tekstowe
Zarezerwowane ! * ( ) ; : @ & = + $ , / ? % # [ ] Znaki kontrolne lub ciągi tekstowe

Tworząc prawidłowy adres URL, należy się upewnić, że zawiera on tylko znaki podane tabeli. Zgodność adresu URL w celu ogólnego korzystania z tego zestawu znaków prowadzi do dwóch problemów: pierwszego pominięcia i zastąpienia:

  • Znaki, którymi chcesz się zajmować, znajdują się poza powyżej zestawu. Na przykład znaki w obcych językach takie jak 上海+中國, muszą być zakodowane za pomocą funkcji powyżej znaków. Zgodnie z powszechną konwencją pokoje (czyli niedozwolonych w adresach URL) są często przedstawiane za pomocą znaku plusa '+' znak.
  • Znaki w powyższym zestawie są dostępne jako znaki zarezerwowane. ale muszą być używane dosłownie. Na przykład ? jest używany w adresach URL do oznaczania początku ciągu zapytania, jeśli chcesz użyć „? i Tajemnice” musisz zakodować '?' znak.

Wszystkie znaki do kodowania URL są zakodowane używając znaku '%' i dwuznakowego kodu szesnastkowego odpowiadającą jej znakowi UTF-8. Przykład: Kod 上海+中國 w UTF-8 byłby zakodowany jako URL %E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B ciąg ? and the Mysterians byłby zakodowany w adresie URL jako %3F+and+the+Mysterians lub %3F%20and%20the%20Mysterians.

Typowe znaki, które wymagają kodowania

Oto kilka typowych znaków, które muszą być zakodowane:

Niebezpieczna postać Zakodowana wartość
Spacja %20
%22
< %3C
> %3E
# %23
% %25
| %7C

Konwersja adresu URL otrzymanego z danych wejściowych użytkownika jest czasami podchwytliwe. Użytkownik może na przykład wprowadzić adres „ul. Główna 5" Ogólnie URL trzeba utworzyć z jego części, traktując wpisywanych przez użytkownika jako literów.

Oprócz tego adresy URL we wszystkich usługach internetowych Google Maps Platform mogą mieć maksymalnie 16 384 znaki i statycznych sieciowych interfejsów API. W większości usług limit znaków będzie rzadko osiągany. Pamiętaj jednak: pamiętaj, że niektóre usługi mają kilka parametrów, które mogą powodować generowanie długich adresów URL.

Kontrolowane korzystanie z interfejsów API Google

Źle zaprojektowane klienty interfejsu API mogą powodować większe obciążenie zarówno w internecie, jak i w internecie Serwery Google. Ta sekcja zawiera kilka sprawdzonych metod dla klientów korzystających z interfejsów API. Obserwujesz te sprawdzone metody pomogą Ci uniknąć zablokowania aplikacji z powodu przypadkowego naruszenia dla interfejsów API.

Zarządzanie błędami i ponownymi próbami

Informacje o kodach odpowiedzi UNKNOWN_ERROR i OVER_QUERY_LIMIT z Geocoding API – dowiedz się więcej o zarządzaniu błędami i ponownymi próbami.

Exponential Backoff

W rzadkich przypadkach może coś pójść nie tak podczas wyświetlania żądania. możesz otrzymać kod HTTP 4XX lub 5XX kodu odpowiedzi lub połączenie TCP może po prostu ulec awarii gdzieś pomiędzy klientem a serwera. Często warto ponawiać próbę, ponieważ dodatkowe żądanie może się udać, jeśli pierwotne żądanie nie zostało przetworzone. Ważne jest jednak, aby nie po prostu wielokrotnego wysyłania żądań do serwerów Google. Takie zapętlenie może spowodować przeciążenie między klientem a Google, co powoduje problemy u wielu stron.

Lepszym sposobem jest ponowienie próby z coraz większymi opóźnieniami. Zwykle jest zwiększane przez mnożnik przy każdej próbie. Ta metoda nazywa się Wykładniczy czas ponowienia.

Weźmy na przykład aplikację, która chce wysłać to żądanie do Time Zone API:

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

Poniższy przykładowy Python pokazuje, jak wysłać żądanie ze wzrastającym czasem do ponowienia:

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}")

Zwróć też uwagę, aby w wywołaniu aplikacji nie było kodu ponowienia próby łańcuch, który prowadzi do powtarzania żądań w krótkich odstępach czasu.

Zsynchronizowane żądania

Duża liczba zsynchronizowanych żądań do interfejsów API Google może wyglądać jak rozproszone Atak typu Denial of Service (DDoS) na infrastrukturę Google i odpowiednio traktowany. Do tego uniknąć, upewnij się, że żądania do interfejsu API nie są synchronizowane między klientami.

Weźmy na przykład aplikację, która wyświetla godzinę w bieżącej strefie czasowej. Ta aplikacja prawdopodobnie ustawi alarm w systemie operacyjnym klienta, który go wybudzi początku minuty, aby można było zaktualizować wyświetlany czas. Aplikacja powinna nie może wykonywać żadnych wywołań interfejsu API w ramach przetwarzania związanego z tym alarmem.

Wykonywanie wywołań interfejsu API w odpowiedzi na naprawiony alarm jest niewłaściwe, ponieważ powoduje jest zsynchronizowany z początkiem minuty, nawet między różnymi urządzeniami, a nie równomiernie rozłożony w czasie. Źle zaprojektowana aplikacja w tym trybie spowoduje wzrost wartości na początku każdej minuty natężenie ruchu przekracza 60-krotność normalnego poziomu.

Dobrym rozwiązaniem jest ustawienie drugiego alarmu na losowo wybraną godzinę. Gdy ten drugi alarm uruchomi się, aplikacja wywoła wszelkie potrzebne interfejsy API i zapisze wyników. Gdy aplikacja chce zaktualizować wyświetlacz na początku minuty, używa funkcji zapisane wcześniej wyniki, zamiast ponownie wywoływać interfejs API. Przy tej metodzie wywołania interfejsu API są równomiernie rozłożone na przestrzeni czasu. Co więcej, wywołania interfejsu API nie opóźniają renderowania, gdy wyświetlacz jest są aktualizowane.

Oprócz początku minuty warto też zachować ostrożność. nie są ustawione na początek godziny i początek każdego dnia o północy.

Przetwarzanie odpowiedzi

W tej sekcji omówiono sposób dynamicznego wyodrębniania tych wartości z odpowiedzi usługi sieciowej.

Usługi internetowe Map Google udzielają odpowiedzi, które są łatwe do ale też nie są łatwe w użyciu. Podczas wykonywania zapytania nie warto niż wyświetlanie zbioru danych, lepiej będzie wyodrębnić kilka konkretnych . Odpowiedzi z internetu powinny być analizowane i wyodrębnij tylko te wartości, które Cię interesują.

Schemat analizy zależy od tego, czy zwracasz dane wyjściowe w formacie XML lub JSON. Odpowiedzi JSON, które mają już postać obiekty JavaScriptu, mogą być przetwarzane w obrębie samego JavaScriptu. na klienta. Odpowiedzi XML powinny być przetwarzane przy użyciu procesora XML oraz język zapytań XML do obsługi elementów w formacie XML. Używamy XPath w poniższych przykładów, ponieważ jest to powszechnie obsługiwane przy przetwarzaniu XML. biblioteki.

Przetwarzanie pliku XML z użyciem XPath

XML to stosunkowo dopracowany format uporządkowanych informacji używany do wymiany danych. Chociaż nie jest to tak proste, jak JSON, XML ale zapewnia większą obsługę języków i bardziej zaawansowane narzędzia. Kod dla na przykład przetwarzanie XML w Javie jest wbudowana javax.xml pakietu.

Przy przetwarzaniu odpowiedzi XML używaj odpowiedniego języka zapytań na potrzeby wyboru węzłów w dokumencie XML, a nie niż zakładamy, że elementy znajdują się w bezwzględnych położeniach w Znaczniki XML. XPath to składnia języka służąca do jednoznacznego opisywania węzłów i elementów w dokumencie XML. Wyrażenia XPath umożliwiają identyfikowanie określonych treści w dokumencie z odpowiedziami XML.

Wyrażenia XPath

Częściowa znajomość XPath wskazuje drogę rozbudowany schemat analizy. W tej sekcji skupimy się na sposobie, w jaki w dokumencie XML są adresowane za pomocą XPath, co pozwala uwzględnianie wielu elementów i konstruowanie złożonych zapytań.

XPath korzysta z wyrażeń do wybierania elementów w kodzie XML. przy użyciu składni podobnej do używanej dla ścieżek do katalogów. Te wyrażenia identyfikują elementy w dokumencie XML drzewa, które jest hierarchicznym drzewem podobnym do DOM. Wyrażenia XPath są zachłanne, co oznacza, że pasuje do wszystkich węzłów zgodnych z podanymi kryteriami.

Użyjemy poniższego abstrakcyjnego kodu XML, aby zilustrować Przykłady:

<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>

Wybór węzła w wyrażeniach

Wybory XPath wybierają węzły. Węzeł główny obejmuje cały dokument. Wybierasz ten węzeł za pomocą wyrażenie specjalne „/”. Zwróć uwagę, że pierwiastek węzeł nie jest węzłem najwyższego poziomu w dokumencie XML; że znajduje się o jeden poziom wyżej niż ten element najwyższego poziomu i zawiera .

Węzły elementów reprezentują różne elementy w obrębie pliku XML drzewo dokumentu. element <WebServiceResponse>, na przykład reprezentuje element najwyższego poziomu zwracany w funkcji przykładowej usługi powyżej. Poszczególne węzły można wybrać za pomocą ścieżek bezwzględnych lub względnych, co wskazuje obecność lub brak początkowego „/” znaku.

  • Ścieżka bezwzględna: „/WebServiceResponse/result” wybiera wszystkie <result> węzły, które to dzieci grupy <WebServiceResponse> do węzła. (Pamiętaj, że oba te elementy pochodzą z poziomu głównego węzła „/”).
  • Ścieżka względna z bieżącego kontekstu: wyrażenie „result” będzie pasować do dowolnego <result> elementów w bieżącym kontekście. Zasadniczo nie należy martwić się o kontekst, bo zwykle przetwarzasz treści w internecie, wyników usługi za pomocą pojedynczego wyrażenia.

Każde z tych wyrażeń można rozszerzyć przez dodanie ścieżki z symbolem wieloznacznym wskazywanej przez podwójny ukośnik („//”). Ten symbol wieloznaczny oznacza, że w ścieżki interwencji. Wyrażenie XPath „//formatted_address”, na przykład dopasuje wszystkie węzły o tej nazwie w bieżącym dokumencie. Wyrażenie //viewport//lat pasuje do wszystkich Elementy <lat>, które mogą śledzić wskaźnik <viewport> jako rodzic.

Domyślnie wyrażenia XPath pasują do wszystkich elementów. Możesz ograniczyć dopasowanie wyrażenia do określonego elementu za pomocą predykatu, w nawiasach kwadratowych ([]). XPath wyrażenie „/GeocodeResponse/result[2] zawsze zwraca dla drugiego wyniku.

Typ wyrażenia
Węzeł główny
Wyrażenie XPath:/
Wybór:
    <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>
    
Ścieżka bezwzględna
Wyrażenie XPath:/WebServiceResponse/result
Wybór:
    <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>
    
Ścieżka z symbolem wieloznacznym
Wyrażenie XPath:/WebServiceResponse//location
Wybór:
    <location>
     <lat>37.4217550</lat>
     <lng>-122.0846330</lng>
    </location>
    
Ścieżka z predykatem
Wyrażenie XPath:/WebServiceResponse/result[2]/message
Wybór:
    <message>The secret message</message>
    
Wszystkie bezpośrednie elementy podrzędne z pierwszego result roku
Wyrażenie XPath:/WebServiceResponse/result[1]/*
Wybór:
     <type>sample</type>
     <name>Sample XML</name>
     <location>
      <lat>37.4217550</lat>
      <lng>-122.0846330</lng>
     </location>
    
name result, w którym tekst type to „próbka”.
Wyrażenie XPath:/WebServiceResponse/result[type/text()='sample']/name
Wybór:
    Sample XML
    

Należy pamiętać, że przy wybieraniu elementów wybiera się węzły, a nie tylko tekst w tych obiektach. Zazwyczaj spróbuje iterować wszystkie pasujące węzły i wyodrębnić tekst. Ty może też bezpośrednio dopasowywać węzły tekstowe; patrz: Węzły tekstowe poniżej.

Pamiętaj, że XPath obsługuje również węzły atrybutów. jednak wszystkie usługi internetowe Map Google wyświetlają elementy bez atrybutów, więc dopasowania atrybutów nie jest konieczne.

Zaznaczanie tekstu w wyrażeniach

Tekst wewnątrz dokumentu XML jest określony w wyrażeniach XPath za pomocą operatora węzła tekstowego. Ten operator „text()” wskazuje wyodrębnianie tekstu ze wskazanego węzła. Przykład: wyrażenie XPath „//formatted_address/text()” będzie zwraca cały tekst z zakresu <formatted_address> .

Typ wyrażenia
Wszystkie węzły tekstowe (w tym odstępy)
Wyrażenie XPath://text()
Wybór:
    sample
    Sample XML

    37.4217550
    -122.0846330
    The secret message
    
Zaznaczenie tekstu
Wyrażenie XPath:/WebServiceRequest/result[2]/message/text()
Wybór:
    The secret message
    
Wybór zależny od kontekstu
Wyrażenie XPath:/WebServiceRequest/result[type/text() = 'sample']/name/text()
Wybór:
    Sample XML
    

Możesz też ocenić wyrażenie i zwrócić zbiór węzłów, a następnie iterować ten „zbiór węzłów”, wyodrębnianie tekstu z każdego węzła. Stosujemy tę metodę w przykładzie poniżej.

Więcej informacji na temat XPath znajdziesz Specyfikacja XPath W3C.

Ocena XPath w Javie

Java ma szeroki zakres obsługi analizy kodu XML i używania wyrażeń XPath w ramach pakietu javax.xml.xpath.*. Dlatego w przykładowym kodzie w tej sekcji jest używany język Java do Jak obsługiwać format XML i analizować dane z odpowiedzi usługi XML.

Aby użyć XPath w kodzie Java, musisz najpierw wystąpienie XPathFactory i wywołanie newXPath() w tej fabryce, aby utworzyć obiekt XPath . Ten obiekt może następnie przetworzyć przekazywane dane XML i XPath za pomocą metody evaluate().

Oceniając wyrażenia XPath, upewnij się, że powtarzają one nad wszelkimi możliwymi „zbiorami węzłów” które mogą zostać zwrócone. Ponieważ te w kodzie Java są zwracane jako węzły DOM, należy przechwytywać tak wiele wartości w obiekcie NodeList, iteracji danego obiektu, aby wyodrębnić z nich tekst lub wartości węzłów.

Poniższy kod ilustruje, jak utworzyć XPath należy przypisać mu kod XML i wyrażenie XPath, a następnie w celu wydrukowania odpowiedniej treści.

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");
    }
  }
}