Google Haritalar Platformu web hizmetleri, harita hizmetleriniz için coğrafi veriler sağlayan Google hizmetlerine yönelik bir HTTP arayüz 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. Directions API ile ilgili tüm belgeler için geliştirici kılavuzuna bakın.
Web hizmeti nedir?
Google Haritalar Platformu web hizmetleri, harici hizmetlerden Haritalar 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ı'na uygun şekilde haritayla birlikte kullanılmak üzere tasarlanmıştır.
Haritalar API'leri web hizmetleri, belirli URL'lere yapılan HTTP(S) isteklerini kullanarak URL parametrelerini ve/veya JSON biçiminde POST verilerini hizmetlerin bağımsız değişkenleri olarak iletir. Genellikle bu hizmetler, uygulamanız tarafından ayrıştırılması ve/veya işlenmesi için yanıt gövdesindeki verileri JSON veya XML olarak döndürür.
Tipik bir Directions API isteği genellikle aşağıdaki biçimdedir:
https://maps.googleapis.com/maps/api/directions/output?parameters
Burada output
, yanıt biçimini (genellikle json
veya xml
) belirtir.
Not: Tüm Directions API uygulamaları kimlik doğrulama gerektirir. Kimlik doğrulama bilgileri hakkında daha fazla bilgi edinin.
SSL/TLS Erişimi
API anahtarları kullanan veya kullanıcı verileri içeren tüm Google Haritalar Platformu istekleri için HTTPS gereklidir. HTTP üzerinden hassas veriler içeren istekler reddedilebilir.
Geçerli bir URL oluşturma
"Geçerli" bir URL'nin çok bariz olduğunu düşünebilirsiniz, ancak bu doğru değildir. Örneğin, tarayıcıdaki bir 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ı şekilde, UTF-8 girişi oluşturan veya kabul eden tüm kodlar, UTF-8 karakterlerinin bulunduğu URL'leri "geçerli" olarak değerlendirebilir. Ancak bu karakterleri web sunucusuna göndermeden önce çevirmeleri gerekir.
Bu işleme
URL kodlaması veya yüzde kodlaması denir.
Özel karakterler
Tüm URL'lerin Tek Tip Kaynak Tanımlayıcısı (URI) spesifikasyonunda belirtilen söz dizimine uyması gerektiğinden özel karakterleri çevirmemiz gerekir. Yani, URL'ler yalnızca ASCII karakterlerin özel bir alt kümesini içermelidir: Bildiğiniz alfanümerik simgeler ve URL'lerde kontrol karakterleri olarak kullanılacak bazı ayrılmış karakterler. Bu tabloda şu karakterler özetlenmektedir:
Ayarla | karakter | URL kullanımı |
---|---|---|
Alfanümerik | CANNOT TRANSLATE | 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 Geçerli URL Karakterlerinin Özeti tablosunda gösterilen karakterleri içerdiğinden emin olmalısınız. Bir URL'nin bu karakter kümesini kullanacak şekilde biçimlendirilmesi, genellikle iki soruna neden olur: Biri eksik, diğeri ikame:
- Ele almak istediğiniz karakterler yukarıdaki grubun dışında
bulunur. Örneğin,
上海+中國
gibi yabancı dillerdeki karakterlerin yukarıdaki karakterler kullanılarak kodlanması gerekir. Popüler kurallara göre boşluklar (URL'lerde izin verilmez) genellikle'+'
karakteriyle de gösterilir. - Yukarıdaki karakterler ayrılmış karakterler olarak ayarlanır, ancak kelimenin tam olarak kullanılması gerekir.
Örneğin,
?
, sorgu dizesinin başlangıcını belirtmek için URL'lerde kullanılır. "? ve Mysterions" dizesini kullanmak isterseniz'?'
karakterini kodlamanız gerekir.
URL olarak kodlanmış tüm karakterler, bir '%'
karakteri ve UTF-8 karakterlerine karşılık gelen iki karakterli bir onaltılık 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.
Kodlama gerektiren 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 zordur. Örneğin, bir kullanıcı "5. Ana Cadde" şeklinde bir adres girebilir. Genel olarak, tüm kullanıcı girişlerini tam karakter olarak kabul ederek URL'nizi bölümlerinden oluşturmanız gerekir.
Buna ek olarak URL'ler, tüm Google Haritalar Platformu web hizmetleri ve statik web API'leri için 8.192 karakterle sınırlıdır. Çoğu hizmette bu karakter sınırına nadiren ulaşılır. Ancak belirli hizmetlerin uzun URL'lere neden olabilecek birkaç parametresi olduğunu unutmayın.
Google API'lerinin Sonradan Kullanımı
Kötü tasarlanmış API istemcileri hem internet hem de Google sunucuları için gerekenden daha fazla yük oluşturabilir. Bu bölümde, API'lerin müşterileri için bazı en iyi uygulamalar yer almaktadır. Bu en iyi uygulamaları izleyerek uygulamanızın API'lerin yanlışlıkla kötüye kullanımı nedeniyle engellenmesini önleyebilirsiniz.
Üstel Geri Alma
Nadiren de olsa isteğiniz yerine bir şeylerle ilgili sorun yaşanabilir. 4XX veya 5XX HTTP yanıt kodu alabilirsiniz. TCP bağlantısı istemciniz ile Google'ın sunucusu arasındaki bir noktada da başarısız olabilir. Orijinal istek başarısız olduğunda takip isteği başarılı olabileceğinden, genellikle isteği yeniden denemeniz önerilir. Bununla birlikte, Google sunucularına sürekli olarak istekte bulunan tek bir döngü oluşturmak yeterli değildir. Bu döngü davranışı, müşteriniz ile Google arasındaki ağın aşırı yüklenmesine neden olabilir ve birçok taraf için soruna neden olabilir.
Denemeler arasında gecikmeleri artırarak yeniden denemek daha iyi bir yaklaşımdır. Genellikle gecikme, her denemede Çarpımsal Geri Alma olarak bilinen bir çarpma faktörüyle artırılır.
Örneğin, Time Zone API'ye istekte bulunmak isteyen bir uygulamayı ele alalım:
https://maps.googleapis.com/maps/api/timezone/json?location=39.6034810,-119.6822510×tamp=1331161200&key=YOUR_API_KEY
Aş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, başvuru arama zincirinde daha yüksek kodlarla tekrar tekrar deneme yapılmasına neden olmayan kodların tekrar tekrar denenmesine dikkat edin.
Senkronize İstekler
Google'ın API'lerine senkronize edilen çok sayıda istek, Google'ın altyapısına Dağıtılmış Hizmet Reddi (DDoS) saldırısı olarak değerlendirilebilir ve buna göre ele alınabilir. Bunu önlemek için API isteklerinin istemciler arasında senkronize edilmediğinden emin olmanız gerekir.
Örneğin, geçerli saat diliminde saati görüntüleyen bir uygulamayı ele alalım. Bu uygulama muhtemelen istemci işletim sisteminde dakika başına uyanıp görüntülenen saati güncelleyebilmek için bir alarm kurar. Uygulama, bu alarmla ilişkili işlemler kapsamında API çağrıları 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ılmak yerine dakikanın başlangıcıyla, farklı cihazlar arasında bile senkronize edilmesine neden olduğundan kötüdür. Bunu kötü tasarlanmış bir uygulama, her dakikanın başında normal seviyelerde altmış kat trafik artışı sağlar.
Bunun yerine, ikinci bir alarm rastgele seçilen bir saate ayarlanabilir. Bu ikinci alarm tetiklendiğinde uygulama, ihtiyacı olan tüm API'leri çağırır ve sonuçları depolar. Uygulama, görünümünü dakikanın başında 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 bir şekilde yayılır. Ayrıca API çağrıları, ekran güncellenirken oluşturma işlemini geciktirmez.
Dakikanın başlangıcının dışında, hedeflemeniz gereken diğer yaygın senkronizasyon zamanlarıbir saatin başında, her günün başlangıcında ise gece yarısıdır..
Yanıtlar İşleniyor
Bu bölümde, web hizmeti yanıtlarından bu değerlerin dinamik olarak nasıl ayıklanacağı açıklanmaktadır.
Google Haritalar web hizmetleri, anlaşılması kolay ancak tam olarak kullanıcı dostu olmayan yanıtlar sağlar. Sorgu gerçekleştirirken bir veri kümesini görüntülemek yerine birkaç belirli değeri çıkarmak isteyebilirsiniz. Genellikle, web hizmetinden gelen yanıtları ayrıştırıp yalnızca sizi ilgilendiren değerleri çıkarmak istersiniz.
Kullandığınız ayrıştırma şeması, XML veya JSON'da çıkış döndürüp döndürmediğinize bağlıdır. JavaScript nesneleri biçiminde olan JSON yanıtları, istemcide JavaScript içinde işlenebilir. XML yanıtları, XML biçimi içindeki öğeleri ele almak için XML işlemci ve XML sorgu dili kullanılarak işlenmelidir. XPath, XML işleme kitaplıklarında yaygın olarak desteklendiğinden aşağıdaki örneklerde kullanılmıştır.
XPath ile XML işleniyor
XML, veri değişimi için kullanılan, nispeten eski bir yapılandırılmış bilgi biçimidir. JSON kadar hafif olmasa da XML, daha fazla dil desteği ve daha güçlü 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şaretlemesindeki 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 bir şekilde tanımlamak için kullanılan bir dil söz dizimidir. XPath ifadeleri, XML yanıt dokümanındaki belirli içeriği tanımlamanızı sağlar.
XPath İfadeleri
XPath'e aşina olmak, güçlü bir ayrıştırma şeması geliştirme konusunda önemli bir yol katetmenizi sağlar. Bu bölümde, bir XML dokümanındaki öğelerin XPath ile nasıl ele alındığına odaklanılmıştır. Böylece birden fazla öğe ele alınabilir ve karmaşık sorgular oluşturulabilir.
XPath, XML dosyasındaki öğeleri seçmek için dizin yollarında kullanılana benzer bir söz dizimi kullanarak ifadeleri kullanır. Bu ifadeler, bir DOM'unkine benzer bir hiyerarşik ağaç olan XML dokümanı ağacındaki öğeleri tanımlar. Genellikle XPath ifadeleri, belirtilen ölçütlerle eşleşen tüm düğümlerle eşleştiklerini gösterir.
Ö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çer. Kök düğüm, dokümanın tamamını kapsar. Bu düğümü "/
" özel ifadesini kullanarak seçersiniz. Kök düğüm, XML dokümanınızın en üst düzey düğümü değildir. Bu düğüm, bu üst düzey öğenin bir seviye üzerindedir ve bu düğümü de içerir.
Öğe düğümleri, XML doküman ağacındaki çeşitli öğeleri temsil eder. Örneğin, bir <WebServiceResponse>
öğesi, yukarıdaki örnek hizmetimizde döndürülen üst düzey öğeyi temsil eder. Düğümleri mutlak veya göreli yollar aracılığıyla ve öncülük eden "/
" karakterinin var olmadığını ya da yokluğunu seçerek 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 ikisinin de "/
" kök düğümünden geldiğini unutmayın.) - Geçerli bağlamdaki göreli yol: "
result
" ifadesi, geçerli bağlamdaki tüm<result>
öğeleriyle eşleşir. Genellikle web hizmeti sonuçlarını tek bir ifade ile işlediğiniz için bağlam hakkında endişelenmenize gerek yoktur.
Bu ifadelerden biri, çift eğik çizgi ("//
") ile belirtilen bir joker karakter yolu eklenerek artırılabilir.
Bu joker karakter, müdahaleye dahil edilen yolda sıfır veya daha fazla öğenin eşleşebileceğini gösterir. Örneğin "//formatted_address
" XPath ifadesi, mevcut dokümandaki ilgili adın tüm düğümleriyle eşleşir.
//viewport//lat
ifadesi, <viewport>
olarak üst öğe olarak izlenebilen 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 koşul 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 öğ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 "sample" olan bir result öğesinin name . |
XPath İfadesi: "
/WebServiceResponse/result[type/text()='sample']/name "Seçim:
Sample XML |
Öğeleri seçerken yalnızca bu nesnelerdeki metni değil, düğümleri de seçtiğinizi unutmayın. Genellikle eşleşen tüm 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 öğeleri özellik olmadan yayınlar. Bu nedenle, özelliklerin eşleştirilmesi gerekmez.
İfadelerde Metin Seçimi
Bir XML dokümanındaki metin, XPath ifadelerinde bir metin düğüm operatörü aracılığıyla belirtilir. Bu "text()
" operatörü, belirtilen düğümden metin çıkarmayı 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ğerlendirebilir, bir dizi düğüm döndürebilir ve daha sonra bu "düğüm grubunu" tekrarlayarak her bir düğümdeki metni alabilirsiniz. Bu yaklaşımı aşağıdaki örnekte kullanıyoruz.
XPath hakkında daha fazla bilgi için XPath W3C Spesifikasyonu'na bakın.
Java'da XPath değerlendirme
Java, XML'yi ayrıştırma ve javax.xml.xpath.*
paketinde XPath ifadelerini kullanma konusunda kapsamlı destek sunar.
Bu nedenle, bu bölümdeki örnek kodda XML'nin 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ılır.
XPath'i Java kodunuzda kullanmak için önce bir XPathFactory
örneğini örneklendirmeniz ve söz konusu fabrikada XPath
nesnesi oluşturmak için newXPath()
yöntemini çağırmanız gerekir. Bu nesne, evaluate()
yöntemini kullanarak, aktarılan XML ve XPath ifadelerini işleyebilir.
XPath ifadelerini değerlendirirken, döndürülebilecek olası "düğüm kümelerini" yinelemeye dikkat edin. Bu sonuçlar Java kodunda DOM düğümleri olarak döndürüldüğünden bu tür birden çok değeri bir NodeList
nesnesi içinde yakalamanız ve bu düğümlerdeki metinleri veya değerleri ayıklamak için söz konusu nesnenin üzerine yinelemeniz gerekir.
Aşağıdaki kod, bir XPath
nesnesinin nasıl oluşturulacağını, XML ve XPath ifadesi atayıp ilgili içeriği yazdırmak için ifadeyi nasıl değerlendireceğini göstermektedir.
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"); } } }