Places API Web Hizmetlerini Kullanmayla İlgili En İyi Uygulamalar

Google Haritalar Platformu web hizmetleri, harita uygulamalarınız için coğrafi veriler sağlayan Google hizmetlerine yönelik HTTP arayüzleri koleksiyonudur.

Bu kılavuzda, web hizmeti isteklerinizi ayarlamak ve hizmet yanıtlarını işlemek için yararlanabileceğiniz bazı yaygın uygulamalar açıklanmaktadır. Places API ile ilgili tüm dokümanlar için geliştirici kılavuzuna bakın.

Web hizmeti nedir?

Google Haritalar Platformu web hizmetleri, harici hizmetlerden Maps API verileri istemek ve Haritalar uygulamalarınızdaki verileri kullanmak için bir arayüzdür. Bu hizmetler, Google Haritalar Platformu Hizmet Şartları'ndaki Lisans Kısıtlamaları uyarınca bir haritayla birlikte kullanılacak şekilde tasarlanmıştır.

Maps API'leri web hizmetleri, belirli URL'lere gönderilen HTTP(S) isteklerini kullanarak URL parametrelerini ve/veya JSON biçimli POST verilerini hizmetlere bağımsız değişken olarak iletir. Genellikle bu hizmetler, uygulamanız tarafından ayrıştırmak ve/veya işlemek için yanıt gövdesinde verileri JSON veya XML olarak döndürür.

Tipik bir Places API isteği genellikle aşağıdaki biçimdedir:

https://places.googleapis.com/v1/places/PLACE_ID?parameters

Not: Tüm Places API uygulamaları kimlik doğrulama gerektirir. Kimlik doğrulama kimlik bilgileri hakkında daha fazla bilgi edinin.

SSL/TLS Erişimi

HTTPS, API anahtarları kullanan veya kullanıcı verileri içeren tüm Google Haritalar Platformu istekleri için gereklidir. HTTP üzerinden yapılan ve hassas veriler içeren istekler reddedilebilir.

Geçerli bir URL oluşturma

"Geçerli" bir URL'nin kendiliğinden açıkça ortaya çıktığını düşünebilirsiniz, ancak bu doğru değildir. Örneğin, bir tarayıcıda adres çubuğuna girilen bir URL özel karakterler (ör."上海+中國") içerebilir. Tarayıcının bu karakterleri iletilmeden önce dahili olarak farklı bir kodlamaya çevirmesi gerekir. Aynı jetonla, UTF-8 girişi oluşturan veya kabul eden tüm kodlar UTF-8 karakterlerine sahip URL'leri "geçerli" olarak değerlendirebilir ancak bu karakterleri bir web sunucusuna göndermeden önce çevirmesi de gerekir. Bu sürece URL kodlaması veya yüzde kodlaması adı verilir.

Özel karakterler

Tüm URL'lerin Tek Tip Kaynak Tanımlayıcı (URI) spesifikasyonunda belirtilen söz dizimine uygun olması gerektiğinden özel karakterleri çevirmemiz gerekir. Bu, aslında URL'lerin ASCII karakterlerin yalnızca özel bir alt kümesini içermesi gerektiği anlamına gelir: bilinen alfasayısal simgeler ve URL'lerde kontrol karakterleri olarak kullanılmak üzere ayrılmış bazı karakterler. Bu tabloda şu karakterler özetlenmektedir:

Geçerli URL Karakterlerinin Özeti
AyarlakarakterlerURL kullanımı
Alfanümerik a b c d e f g h i j k l m n o p q r s t u v g 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 Metin dizeleri, şema kullanımı (http), bağlantı noktası (8080) vb.
Ayrılmamış - _ . ~ Metin dizeleri
Rezervasyon yapıldı ! * ' ( ) ; : @ & = + TL , / ? % # [ ] Kontrol karakterleri ve/veya Metin Dizeleri

Geçerli bir URL oluştururken yalnızca tabloda gösterilen karakterleri içerdiğinden emin olmalısınız. Bu karakter grubunu kullanmak için bir URL oluşturmak, genellikle biri atlama, diğeri değiştirme olmak üzere iki soruna neden olur:

  • İşlemek istediğiniz karakterler yukarıdaki grubun dışında bulunuyor. Örneğin, yabancı dillerdeki 上海+中國 gibi karakterlerin yukarıdaki karakterler kullanılarak kodlanması gerekir. Popüler kurallara göre, boşluklar (URL'lerde izin verilmeyen alanlar) genellikle artı '+' karakteri kullanılarak gösterilir.
  • Yukarıdaki karakterler arasında ayrılmış karakterler olarak yer almaktadır ancak gerçek anlamda kullanılmaları gerekir. Örneğin, ?, URL'lerde sorgu dizesinin başlangıcını belirtmek için kullanılır. "? ve Gizemler" dizesini kullanmak isterseniz '?' karakterini kodlamanız gerekir.

URL olarak kodlanacak tüm karakterler, bir '%' karakteri ve UTF-8 karakterine karşılık gelen iki karakterlik onaltılık bir değer kullanılarak kodlanır. Örneğin, UTF-8'deki 上海+中國, %E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B olarak URL olarak kodlanır. ? and the Mysterians dizesi, %3F+and+the+Mysterians veya %3F%20and%20the%20Mysterians olarak URL olarak kodlanır.

Yaygın olarak kodlama gerektiren karakterler

Kodlanması gereken bazı yaygın karakterler şunlardır:

Güvenli olmayan karakter Kodlanmış değer
Alan %20
" %22
< %3C
> %3E
# %23
% %25
| %7C

Kullanıcı girişinden aldığınız bir URL'yi dönüştürmek bazen karmaşık bir iştir. Örneğin, bir kullanıcı "5th&Main Street" olarak bir adres girebilir. Genel olarak, tüm kullanıcı girişlerini sabit karakterler olarak ele alarak, URL'nizi kendi bölümlerinden oluşturmanız gerekir.

Ayrıca URL'ler, tüm Google Haritalar Platformu web hizmetleri ve statik web API'leri için 16.384 karakterle sınırlıdır. Çoğu hizmette bu karakter sınırına nadiren yaklaşılır. Ancak belirli hizmetlerde uzun URL'lere neden olabilecek çeşitli parametreler olduğunu unutmayın.

Google API'lerinin Sonradan Kullanımı

Kötü tasarlanmış API istemcileri hem internette hem de Google'ın sunucularında gerekenden daha fazla yük taşıyabilir. Bu bölümde, API istemcileri için bazı en iyi uygulamalar yer almaktadır. Bu en iyi uygulamalardan yararlanmanız, uygulamanızın API'lerin yanlışlıkla kötüye kullanımı nedeniyle engellenmesini önlemenize yardımcı olabilir.

Üstel Geri Alma

Nadir durumlarda, isteğinizin yerine getirilmesi sırasında bir şeyler ters gidebilir. 4XX veya 5XX HTTP yanıt kodu alabilirsiniz ya da TCP bağlantısı istemciniz ile Google sunucusu arasında bir yerde başarısız olabilir. Takip isteği, orijinal istek başarısız olduğunda başarılı olabileceğinden genellikle yeniden denemek faydalı olur. Ancak Google'ın sunucularına sürekli olarak istek göndermekle yetinmemek de önemlidir. Bu döngüsel davranış, istemciniz ile Google arasındaki ağda aşırı yüklenerek birçok taraf için soruna neden olabilir.

Daha iyi bir yaklaşım, denemeler arasındaki gecikmeleri artırarak tekrar denemektir. Genellikle gecikme her denemede çarpma faktörüyle artırılır. Bu yaklaşım Üstel Geri Alma olarak bilinir.

Örneğin, Time Zone API'ye bu isteği göndermek isteyen bir uygulamayı ele alalım:

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

Aşağıdaki Python örneğinde, isteğin eksponansiyel geri yüklemeyle nasıl gönderileceği gösterilmektedir:

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

Ayrıca, uygulama çağrı zincirinde, hızlı bir şekilde arka arkaya tekrarlanan isteklere yol açan daha yüksek bir yeniden deneme kodu olmadığından da emin olmalısınız.

Senkronize İstekler

Google'ın API'lerine yapılan çok sayıda senkronize edilmiş istek, Google altyapısına yönelik Dağıtılmış Hizmet Reddi (DDoS) saldırısı gibi görünebilir ve gerekli şekilde ele alınabilir. Bundan kaçınmak için API isteklerinin istemciler arasında senkronize edilmediğinden emin olmanız gerekir.

Örneğin, saati geçerli saat diliminde gösteren bir uygulamayı ele alalım. Bu uygulama muhtemelen istemci işletim sisteminde alarm kurarak dakikanın başında uyandırır. Böylece, görüntülenen süre güncellenebilir. Uygulama, söz konusu alarmla ilişkili işlemin bir parçası olarak API çağrısı yapmamalıdır.

Sabit bir alarma yanıt olarak API çağrıları yapmak kötüdür, çünkü API çağrıları zaman içinde eşit olarak dağıtmak yerine, farklı cihazlar arasında bile dakikanın başında senkronize edilir. Bunu yapan kötü tasarlanmış bir uygulama, her dakikanın başında normal düzeylerde altmış kat artışa neden olur.

Bunun yerine, rastgele seçilen bir zamana ayarlanmış ikinci bir alarm olması olası iyi bir tasarımdır. Bu ikinci alarm etkinleştiğinde uygulama, ihtiyacı olan API'leri çağırır ve sonuçları depolar. Uygulama dakika başında ekranını güncellemek istediğinde, API'yi tekrar çağırmak yerine önceden depolanan sonuçları kullanır. Bu yaklaşımda, API çağrıları zaman içinde eşit olarak yayılır. Ayrıca API çağrıları, ekran güncellenirken oluşturmayı geciktirmez.

Dakikanın başlangıcı dışında, diğer yaygın senkronizasyon zamanlarını hedeflememenize dikkat etmeniz gerekir.

Yanıtlar İşleniyor

Bu bölümde, bu değerlerin web hizmeti yanıtlarından dinamik olarak nasıl ayıklanacağı anlatılmaktadır.

Google Haritalar web hizmetleri kolay anlaşılır ancak tam olarak kullanıcı dostu yanıtlar verir. Bir sorgu gerçekleştirirken, bir veri kümesi görüntülemek yerine muhtemelen birkaç belirli değeri ayıklamak istersiniz. Genel olarak, web hizmetinden gelen yanıtları ayrıştırmak ve yalnızca sizi ilgilendiren değerleri ayıklamak istersiniz.

Kullandığınız ayrıştırma şeması, çıktıyı XML veya JSON biçiminde mi döndürdüğünüze bağlıdır. Zaten JavaScript nesneleri biçiminde olan JSON yanıtları, istemcide JavaScript'in kendi içinde işlenebilir. XML yanıtları, XML biçimindeki öğeleri ele almak için bir XML işlemcisi ve XML sorgu dili kullanılarak işlenmelidir. XML işleme kitaplıklarında yaygın olarak desteklendiği için aşağıdaki örneklerde XPath'i kullanıyoruz.

XPath ile XML işleme

XML, veri değişimi için kullanılan nispeten olgun bir yapılandırılmış bilgi biçimidir. JSON kadar hafif olmasa da XML, daha fazla dil desteği ve daha sağlam araçlar sağlar. Örneğin, Java'da XML işleme kodu javax.xml paketlerinde yerleşik olarak bulunur.

XML yanıtlarını işlerken, öğelerin XML işaretlemesi içindeki mutlak konumlarda bulunduğunu varsaymak yerine, XML belgesindeki düğümleri seçmek için uygun bir sorgu dili kullanmanız gerekir. XPath, bir XML belgesindeki düğümleri ve öğeleri benzersiz bir şekilde tanımlamak için kullanılan bir dil söz dizimidir. XPath ifadeleri, XML yanıt belgesindeki belirli içeriği tanımlamanızı sağlar.

XPath İfadeleri

XPath hakkında biraz bilgi sahibi olmak, güçlü bir ayrıştırma şeması geliştirmede oldukça faydalıdır. Bu bölümde, birden fazla öğeyi ele almanıza ve karmaşık sorgular oluşturmanıza olanak tanıyarak XML belgesindeki öğelerin XPath'de nasıl ele alındığına odaklanacağız.

XPath, dizin yolları için kullanılana benzer bir söz dizimi kullanarak XML belgesindeki öğeleri seçmek için ifadeleri kullanır. Bu ifadeler, DOM'ye benzer bir hiyerarşik ağaç olan XML belge ağacındaki öğeleri tanımlar. Genel olarak XPath ifadeleri, sağlanan ölçütlerle eşleşen tüm düğümlerle eşleşeceğini belirten girişsiz ifadelerdir.

Örneklerimizi açıklamak için aşağıdaki soyut XML'i kullanacağız:

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

İfadelerde Düğüm Seçimi

XPath seçimleri, düğümleri seçin. Kök düğüm, belgenin tamamını kapsar. Bu düğümü, "/" özel ifadesini kullanarak seçersiniz. Kök düğüm, XML belgenizin en üst düzey düğümü değildir. Aslında bu düğüm, bu üst düzey öğenin bir seviye üzerindedir ve onu içerir.

Öğe düğümleri, XML belge ağacındaki çeşitli öğeleri temsil eder. Örneğin <WebServiceResponse> öğesi, yukarıdaki örnek hizmetimizde döndürülen üst düzey öğeyi temsil eder. Düğümleri başında "/" karakteri olup olmamasıyla gösterilen mutlak veya göreli yollar aracılığıyla tek tek seçersiniz.

  • Mutlak yol: "/WebServiceResponse/result" ifadesi, <WebServiceResponse> düğümünün alt öğeleri olan tüm <result> düğümlerini seçer. (Bu öğelerin her ikisinin de "/" kök düğümünden geldiğine dikkat edin.)
  • Geçerli bağlamdaki göreli yol: "result" ifadesi, geçerli bağlamdaki herhangi bir <result> öğesiyle eşleşir. Web hizmeti sonuçlarını genellikle tek bir ifadeyle işlediğiniz için genel olarak içerik konusunda endişelenmenize gerek yoktur.

Bu ifadelerden her ikisi de, çift eğik çizgi ("//") ile belirtilen bir joker karakter yolu eklenerek genişletilebilir. Bu joker karakter, eşleşen yolda sıfır veya daha fazla öğenin eşleşebileceğini gösterir. Örneğin "//formatted_address" XPath ifadesi, mevcut belgede söz konusu ada sahip olan tüm düğümlerle eşleşir. //viewport//lat ifadesi, üst öğe olarak <viewport> öğesini izleyebilen tüm <lat> öğeleriyle eşleşir.

Varsayılan olarak, XPath ifadeleri tüm öğelerle eşleşir. Köşeli parantez ([]) içinde yer alan bir predicate sağlayarak ifadeyi belirli bir öğeyle eşleşecek şekilde kısıtlayabilirsiniz. Örneğin, "/GeocodeResponse/result[2] XPath ifadesi her zaman ikinci sonucu döndürür.

İfade Türü
Root düğüm
XPath İfadesi:  "/"
Seçim:
    <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>
    
Mutlak Yol
XPath İfadesi:  "/WebServiceResponse/result"
Seçim:
    <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>
    
Joker Karakterli Yol
XPath İfadesi:  "/WebServiceResponse//location"
Seçim:
    <location>
     <lat>37.4217550</lat>
     <lng>-122.0846330</lng>
    </location>
    
Koşullu Yol
XPath İfadesi:  "/WebServiceResponse/result[2]/message"
Seçim:
    <message>The secret message</message>
    
İlk result içindeki tüm doğrudan alt öğeler
XPath İfadesi:  "/WebServiceResponse/result[1]/*"
Seçim:
     <type>sample</type>
     <name>Sample XML</name>
     <location>
      <lat>37.4217550</lat>
      <lng>-122.0846330</lng>
     </location>
    
type metni "sample" olan bir result öğesinin name öğesi.
XPath İfadesi:  "/WebServiceResponse/result[type/text()='sample']/name"
Seçim:
    Sample XML
    

Öğeleri seçerken yalnızca bu nesnelerin içindeki metni değil, düğümleri de seçtiğinizi unutmayın. Genel olarak, tüm eşleşen düğümleri yinelemek ve metni ayıklamak istersiniz. Metin düğümlerini doğrudan da eşleştirebilirsiniz. Aşağıdaki Metin Düğümleri bölümüne bakın.

XPath'in özellik düğümlerini de desteklediğini unutmayın. Bununla birlikte, tüm Google Haritalar web hizmetleri, özellikleri olmayan öğeler sunduğundan özelliklerin eşleştirilmesi gerekmez.

İfadelerde Metin Seçimi

XML belgesindeki metin, XPath ifadelerinde bir metin düğümü operatörü aracılığıyla belirtilir. "text()" operatörü, belirtilen düğümden metin ayıklamayı belirtir. Örneğin, "//formatted_address/text()" XPath ifadesi, <formatted_address> öğeleri içindeki tüm metni döndürür.

İfade Türü
Tüm metin düğümleri (boşluk dahil)
XPath İfadesi:  "//text()"
Seçim:
    sample
    Sample XML

    37.4217550
    -122.0846330
    The secret message
    
Metin Seçimi
XPath İfadesi:  "/WebServiceRequest/result[2]/message/text()"
Seçim:
    The secret message
    
Bağlama Duyarlı Seçim
XPath İfadesi:  "/WebServiceRequest/result[type/text() = 'sample']/name/text()"
Seçim:
    Sample XML
    

Alternatif olarak bir ifadeyi değerlendirip bir düğüm grubu döndürebilir ve daha sonra bu "düğüm kümesi" üzerinde işlemi yineleyerek her bir düğümdeki metni ayıklayabilirsiniz. Bu yaklaşımı aşağıdaki örnekte kullanıyoruz.

XPath hakkında daha fazla bilgi için XPath W3C Spesifikasyonu'na bakın.

Java'daki XPath'i değerlendirme

Java, XML'i ayrıştırma ve javax.xml.xpath.* paketi içinde XPath ifadeleri kullanma için kapsamlı destek sunar. Bu nedenle, bu bölümdeki örnek kod XML'in nasıl işleneceğini ve XML hizmet yanıtlarından nasıl veri ayrıştırılacağını göstermek için Java'yı kullanır.

Java kodunuzda XPath kullanmak için önce bir XPathFactory örneğini örneklendirmeniz ve bu fabrikada newXPath() yöntemini çağırarak XPath nesnesini oluşturmanız gerekir. Daha sonra bu nesne, evaluate() yöntemini kullanarak geçirilen XML ve XPath ifadelerini işleyebilir.

XPath ifadelerini değerlendirirken, döndürülebilecek olası "düğüm kümelerini" yinelediğinizden emin olun. Bu sonuçlar Java kodunda DOM düğümleri olarak döndürüldüğünden, bir NodeList nesnesinde bu tür birden çok değeri yakalamanız ve bu düğümlerden herhangi bir metin veya değer çıkarmak için bu nesnenin üzerinde iterasyon yapmanız gerekir.

Aşağıdaki kod; XPath nesnesinin nasıl oluşturulacağını, bu nesneye bir XML ve XPath ifadesinin nasıl atanacağını ve ilgili içeriği yazdırmak için ifadeyi nasıl değerlendireceğini gösterir.

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