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 yararlı olan bazı yaygın uygulamalar açıklanmaktadır. Geocoding API ile ilgili tüm belgeler için geliştirici kılavuzuna bakın.
Web hizmeti nedir?
Google Haritalar Platformu web hizmetleri, harici hizmetlerden Maps API verileri istemek ve bu verileri Haritalar uygulamalarınızda 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 HTTP(S) istekleri göndererek 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ırılmak ve/veya işlenmek üzere yanıt gövdesinde JSON ya da XML olarak veri döndürür.
Tipik bir Geocoding API isteği genellikle aşağıdaki biçimdedir:
https://maps.googleapis.com/maps/api/geocode/output?parameters
Burada output, yanıt biçimini (genellikle json veya xml) gösterir.
Not: Tüm Geocoding API uygulamaları için kimlik doğrulama gerekir. Kimlik doğrulama bilgileri hakkında daha fazla bilgi edinin.
SSL/TLS Erişimi
API anahtarlarını kullanan veya kullanıcı verileri içeren tüm Google Haritalar Platformu istekleri için HTTPS gereklidir. HTTP üzerinden yapılan ve hassas veriler içeren istekler reddedilebilir.
Geçerli bir URL oluşturma
"Geçerli" bir URL'nin ne olduğu açık gibi görünse de aslında durum tam olarak öyle değildir. Örneğin, bir tarayıcının adres çubuğuna girilen URL özel karakterler (ör. "上海+中國") içerebilir. Tarayıcının, iletimden önce bu karakterleri dahili olarak farklı bir kodlamaya çevirmesi gerekir.
Aynı şekilde, UTF-8 girişi oluşturan veya kabul eden tüm kodlar, UTF-8 karakterleri içeren URL'leri "geçerli" olarak kabul edebilir ancak bu karakterleri bir web sunucusuna göndermeden önce çevirmesi de gerekir.
Bu işleme
URL kodlaması veya yüzde kodlaması denir.
Özel karakterler
Tüm URL'lerin Tekdüzen Kaynak Tanımlayıcısı (URI) spesifikasyonunda belirtilen söz dizimine uyması gerektiğinden özel karakterleri çevirmemiz gerekir. Bu, URL'lerin yalnızca ASCII karakterlerinin özel bir alt kümesini içermesi gerektiği anlamına gelir: tanıdık alfanümerik simgeler ve URL'lerde kontrol karakterleri olarak kullanılacak bazı ayrılmış karakterler. Bu tabloda bu karakterler özetlenmektedir:
| Ayarlandı | karakterler | URL kullanımı |
|---|---|---|
| Alfasayısal | 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 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 | Metin dizeleri, şema kullanımı (http), bağlantı noktası (8080) vb. |
| Ayrılmamış | - _ . ~ | Metin dizeleri |
| Rezervasyon yapıldı | ! * ' ( ) ; : @ & = + $ , / ? % # [ ] | Kontrol karakterleri ve/veya metin dizeleri |
Geçerli bir URL oluştururken yalnızca tabloda gösterilen karakterleri içerdiğinden emin olmanız gerekir. Bir URL'yi bu karakter grubunu kullanacak şekilde uyarlamak genellikle iki soruna yol açar: karakterlerin atlanması ve karakterlerin değiştirilmesi:
- İşlemek istediğiniz karakterler yukarıdaki kümenin dışında yer alıyor. Örneğin, yabancı dillerdeki karakterlerin (ör.
上海+中國) yukarıdaki karakterler kullanılarak kodlanması gerekir. Yaygın bir kural olarak, boşluklar (URL'lerde izin verilmez) genellikle artı'+'karakteri kullanılarak da temsil edilir. - Karakterler, yukarıdaki grupta ayrılmış karakterler olarak bulunur ancak tam anlamıyla kullanılmaları gerekir.
Örneğin, URL'lerde sorgu dizesinin başlangıcını belirtmek için
?kullanılır. "? ve Gizemliler" dizesini kullanmak istiyorsanız'?'karakterini kodlamanız gerekir.
URL kodlaması yapılacak tüm karakterler, '%' karakteri ve UTF-8 karakterlerine karşılık gelen iki karakterli onaltılık değer kullanılarak kodlanır. Örneğin, UTF-8'deki 上海+中國, URL kodlamasıyla %E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B olur. ? and the Mysterians dizesi, URL kodlamalı olarak %3F+and+the+Mysterians veya %3F%20and%20the%20Mysterians şeklinde olur.
Kodlanması gereken yaygın karakterler
Kodlanması gereken bazı yaygın karakterler şunlardır:
| Güvenli olmayan karakter | Kodlanmış değer |
|---|---|
| Boşluk | %20 |
| " | %22 |
| < | %3C |
| > | %3E |
| # | %23 |
| % | %25 |
| | | %7C |
Kullanıcı girişinden aldığınız bir URL'yi dönüştürmek bazen zor olabilir. Örneğin, bir kullanıcı adresi "5th&Main St." olarak girebilir. Genellikle URL'nizi parçalarından oluşturmanız ve tüm kullanıcı girişlerini değişmez karakterler olarak ele almanı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ırlamasına nadiren yaklaşılır. Ancak bazı hizmetlerin, uzun URL'lere neden olabilecek çeşitli parametreleri olduğunu unutmayın.
Google API'lerinin Ölçülü Kullanımı
Kötü tasarlanmış API istemcileri, hem internete hem de Google'ın sunucularına gereğinden fazla yük bindirebilir. Bu bölümde, API'lerin istemcileri için bazı en iyi uygulamalar yer almaktadır. Bu en iyi uygulamaları takip etmek, API'lerin yanlışlıkla kötüye kullanılması nedeniyle uygulamanızın engellenmesini önlemenize yardımcı olabilir.
Hataları ve yeniden denemeleri yönetme
Geocoding API'den gelen UNKNOWN_ERROR veya OVER_QUERY_LIMIT yanıt kodları hakkında bilgi edinmek için hataları ve yeniden denemeleri yönetme başlıklı makaleyi okuyun.
Eksponansiyel Geri Yükleme
Nadir durumlarda isteğiniz yerine getirilirken bir sorun oluşabilir. 4XX veya 5XX HTTP yanıt kodu alabilirsiniz ya da istemciniz ile Google'ın sunucusu arasındaki TCP bağlantısı başarısız olabilir. İlk istek başarısız olduğunda takip isteği başarılı olabileceğinden, isteği yeniden denemek genellikle faydalı olur. Ancak Google'ın sunucularına tekrar tekrar istek gönderen bir döngü oluşturmamak önemlidir. Bu döngü davranışı, istemciniz ile Google arasındaki ağda aşırı yüklenmeye neden olarak birçok taraf için sorunlara yol açabilir.
Daha iyi bir yaklaşım, denemeler arasındaki gecikmeleri artırarak yeniden denemektir. Genellikle gecikme, her denemede çarpımsal bir faktörle artırılır. Bu yaklaşım, eksponansiyel geri yükleme olarak bilinir.
Örneğin, Saat Dilimi API'ye şu isteği göndermek isteyen bir uygulama düşünün:
https://maps.googleapis.com/maps/api/timezone/json?location=39.6034810,-119.6822510×tamp=1331161200&key=YOUR_API_KEYAşağıdaki Python örneğinde, isteğin eksponansiyel geri yükleme ile nasıl yapılacağı 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ı zincirinin üst kısımlarında, hızlı bir şekilde art arda istek gönderilmesine neden olan yeniden deneme kodu bulunmadığından emin olmanız gerekir.
Senkronize İstekler
Google'ın API'lerine gönderilen çok sayıda senkronize istek, Google'ın altyapısına yönelik Dağıtılmış Hizmet Reddi (DDoS) saldırısı olarak algılanabilir ve buna göre işlem yapılabilir. Bunu önlemek için API isteklerinin istemciler arasında senkronize edilmediğinden emin olmanız gerekir.
Örneğin, geçerli saat dilimindeki saati gösteren bir uygulama düşünün. Bu uygulama, istemci işletim sisteminde bir alarm ayarlayarak gösterilen saatin güncellenebilmesi için dakikanın başında sistemi uyandırabilir. Uygulama, bu alarm ile ilişkili işlem kapsamında API çağrısı yapmamalıdır.
Sabit bir alarma yanıt olarak API çağrıları yapmak, API çağrılarının zaman içinde eşit olarak dağıtılması yerine farklı cihazlar arasında bile dakikanın başına senkronize edilmesine neden olduğu için iyi bir yöntem değildir. Kötü tasarlanmış bir uygulama bunu yaptığında her dakikanın başında normal seviyenin altmış katı trafik artışı yaşanır.
Bunun yerine, rastgele seçilen bir zamana ayarlanmış ikinci bir alarm kullanmak iyi bir tasarım olabilir. Bu ikinci alarm tetiklendiğinde uygulama, ihtiyaç duyduğu tüm API'leri çağırır ve sonuçları depolar. Uygulama, dakikanın 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 dağıtılır. Ayrıca API çağrıları, ekran güncellenirken oluşturmayı geciktirmez.
Dakikanın başlangıcının yanı sıra, hedeflememeye dikkat etmeniz gereken diğer yaygın senkronizasyon zamanları, saatin başlangıcı ve her günün gece yarısı başlangıcıdır.
Yanıtlar işleniyor
Bu bölümde, bu değerlerin web hizmeti yanıtlarından dinamik olarak nasıl ayıklanacağı açıklanmaktadır.
Google Haritalar web hizmetleri, kolay anlaşılır ancak tam olarak kullanıcı dostu olmayan yanıtlar sağlar. Sorgu yaparken bir veri kümesini görüntülemek yerine birkaç belirli değeri ayıklamak isteyebilirsiniz. Genellikle web hizmetinden gelen yanıtları ayrıştırmak ve yalnızca sizi ilgilendiren değerleri ayıklamak istersiniz.
Kullanacağınız ayrıştırma şeması, çıkışı XML veya JSON olarak döndürmenize bağlıdır. JSON yanıtları, zaten JavaScript nesneleri biçiminde olduğundan istemcide JavaScript'in kendisi 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 kullanıyoruz.
XPath ile XML işleme
XML, veri alışverişi için kullanılan, nispeten olgun bir yapılandırılmış bilgi biçimidir. JSON kadar basit olmasa da XML daha fazla dil desteği ve daha güçlü araçlar sunar. Ö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çinde mutlak konumlarda bulunduğunu varsaymak yerine XML dokümanındaki düğümleri seçmek için uygun bir sorgu dili kullanmanız gerekir. XPath, XML dokümanındaki düğümleri ve öğeleri benzersiz şekilde tanımlayan bir dil söz dizimidir. XPath ifadeleri, XML yanıt dokümanındaki belirli içerikleri tanımlamanıza olanak tanır.
XPath İfadeleri
XPath hakkında biraz bilgi sahibi olmak, sağlam bir ayrıştırma şeması geliştirmek için çok faydalıdır. Bu bölümde, bir XML belgesindeki öğelerin XPath ile nasıl ele alındığına odaklanılacaktır. Bu sayede birden fazla öğeyi ele alabilir ve karmaşık sorgular oluşturabilirsiniz.
XPath, bir XML dokümanındaki öğeleri seçmek için dizin yollarında kullanılana benzer bir söz dizimi kullanan ifadelerden yararlanır. Bu ifadeler, DOM'a benzer hiyerarşik bir ağaç olan XML belge ağacındaki öğeleri tanımlar. Genellikle XPath ifadeleri, sağlanan ölçütlerle eşleşen tüm düğümlerle eşleşeceklerini belirten açgözlü ifadelerdir.
Örneklerimizi göstermek 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çer. Kök düğüm,
belgenin tamamını kapsar. Bu düğümü "/" özel ifadesini kullanarak seçersiniz. Kök düğümün, XML dokümanınızın üst düzey düğümü olmadığını unutmayın. Aslında bu üst düzey öğenin bir düzey üstünde bulunur 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 tek tek seçmek için mutlak veya göreli yolları kullanabilirsiniz. Mutlak yolların başında "/" karakteri bulunur, göreli yolların başında ise bu karakter yoktur.
- Mutlak yol: "
/WebServiceResponse/result" ifadesi,<WebServiceResponse>düğümünün alt öğesi olan tüm<result>düğümlerini seçer. (Bu öğelerin her ikisinin de "/" kök düğümünden geldiğini unutmayın.) - Mevcut bağlamdan göreli yol: "
result" ifadesi, mevcut bağlamdaki tüm<result>öğeleriyle eşleşir. Genellikle web hizmeti sonuçlarını tek bir ifadeyle işlediğiniz için bağlam konusunda endişelenmeniz gerekmez.
Bu ifadelerden herhangi biri, çift eğik çizgi ("//") ile gösterilen bir joker karakter yolu eklenerek genişletilebilir. Bu joker karakter, aradaki yolda sıfır veya daha fazla öğenin eşleşebileceğini gösterir. Örneğin, "//formatted_address" XPath ifadesi, mevcut dokümandaki bu ada sahip 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çine alınmış bir yüklem 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>
|
| Yüklem içeren yol | XPath İfadesi: "
/WebServiceResponse/result[2]/message"Seçim:
<message>The secret message</message>
|
İlk result öğesinin tüm doğrudan alt öğeleri |
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 "örnek" olan bir result öğesinin name. |
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 seçtiğinizi unutmayın. Genellikle, eşleşen tüm düğümler üzerinde iterasyon yapmak 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. Ancak tüm Google Haritalar web hizmetleri, özellikleri olmayan öğeler sunduğundan özelliklerin eşleştirilmesi gerekmez.
İfadelerde metin seçimi
XML dokümanındaki metin, XPath ifadelerinde metin düğümü operatörü aracılığıyla belirtilir. Bu operatör "text()", belirtilen düğümden metin çıkarıldığını gösterir. Örneğin, "//formatted_address/text()" XPath ifadesi, <formatted_address> öğelerindeki tüm metni döndürür.
| İfade Türü | |
|---|---|
| Tüm metin düğümleri (boşluklar 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 ardından bu "düğüm grubu" üzerinde iterasyon yaparak her düğümden metni ayıklayabilirsiniz. Aşağıdaki örnekte bu yaklaşımı kullanıyoruz.
XPath hakkında daha fazla bilgi için XPath W3C Spesifikasyonu'na bakın.
Java'da XPath'i değerlendirme
Java, javax.xml.xpath.* paketinde XML ayrıştırma ve XPath ifadelerini kullanma konusunda geniş bir desteğe sahiptir.
Bu nedenle, bu bölümdeki örnek kodda XML'in nasıl işleneceğini ve XML hizmet yanıtlarından verilerin nasıl ayrıştırılacağını göstermek için Java kullanılmıştır.
Java kodunuzda XPath kullanmak için önce bir XPathFactory örneği oluşturmanız ve bu fabrikada newXPath() yöntemini çağırarak bir XPath
nesnesi oluşturmanız gerekir. Bu nesne daha sonra evaluate() yöntemini kullanarak iletilen XML ve XPath ifadelerini işleyebilir.
XPath ifadelerini değerlendirirken döndürülebilecek tüm olası "düğüm kümeleri" üzerinde yineleme yaptığınızdan emin olun. Bu sonuçlar Java kodunda DOM düğümleri olarak döndürüldüğünden, bu tür birden fazla değeri bir NodeList nesnesi içinde yakalamanız ve bu düğümlerden herhangi bir metni veya değeri ayıklamak için bu nesne üzerinde yineleme yapmanız gerekir.
Aşağıdaki kodda, bir XPath nesnesinin nasıl oluşturulacağı, bu nesneye XML ve XPath ifadesinin nasıl atanacağı ve ilgili içeriği yazdırmak için ifadenin nasıl değerlendirileceği gösterilmektedir.
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"); } } }