Các dịch vụ web của Nền tảng Google Maps là một tập hợp các giao diện HTTP đối với Google các dịch vụ cung cấp dữ liệu địa lý cho các ứng dụng bản đồ của bạn.
Hướng dẫn này mô tả một số phương pháp phổ biến giúp bạn thiết lập dịch vụ web và xử lý phản hồi của dịch vụ. Tham khảo hướng dẫn dành cho nhà phát triển để xem tài liệu đầy đủ về Distance Matrix API (API Ma trận khoảng cách).
Dịch vụ web là gì?
Các dịch vụ web của Nền tảng Google Maps là một giao diện để yêu cầu dữ liệu API Maps từ các dịch vụ bên ngoài và sử dụng dữ liệu trong các ứng dụng Maps của bạn. Các dịch vụ này được thiết kế để sử dụng cùng với bản đồ, theo Quy định hạn chế về giấy phép trong Điều khoản dịch vụ của Nền tảng Google Maps.
Các dịch vụ web của API Maps sử dụng yêu cầu HTTP(S) cho các URL cụ thể, chuyển các tham số URL và/hoặc Dữ liệu POST ở định dạng JSON làm đối số cho các dịch vụ. Nói chung, các dịch vụ này trả về dữ liệu trong nội dung phản hồi dưới dạng JSON hoặc XML để phân tích cú pháp và/hoặc đang xử lý.
Một yêu cầu API ma trận khoảng cách điển hình thường là biểu mẫu sau:
https://maps.googleapis.com/maps/api/distancematrix/output?parameters
trong đó output
cho biết định dạng phản hồi (thường là
json
hoặc xml
).
Lưu ý: Tất cả ứng dụng Distance Matrix API (API Ma trận khoảng cách) đều yêu cầu xác thực. Xem thêm thông tin về thông tin xác thực.
Truy cập SSL/TLS
HTTPS là bắt buộc cho tất cả các yêu cầu trên Nền tảng Google Maps sử dụng khoá API hoặc chứa người dùng . Những yêu cầu được thực hiện qua HTTP chứa dữ liệu nhạy cảm có thể bị từ chối.
Tạo URL hợp lệ
Bạn có thể cho rằng trang web "hợp lệ" URL hiển thị rõ ràng, nhưng
không hẳn như vậy. URL được nhập trong thanh địa chỉ trong
trình duyệt, có thể chứa các ký tự đặc biệt (ví dụ:
"上海+中國"
); trình duyệt cần dịch nội bộ
các ký tự đó thành một chế độ mã hoá khác trước khi truyền.
Đồng thời, mọi mã tạo hoặc chấp nhận dữ liệu đầu vào UTF-8
có thể coi URL có ký tự UTF-8 là "hợp lệ", nhưng cũng phải
để dịch những ký tự đó trước khi gửi tới máy chủ web.
Quá trình này gọi là
Mã hoá URL hoặc mã hoá phần trăm.
Các ký tự đặc biệt
Chúng ta cần dịch các ký tự đặc biệt vì tất cả URL cần phải tuân theo cú pháp được chỉ định bởi Đồng phục Thông số kỹ thuật Giá trị nhận dạng tài nguyên (URI). Trên thực tế, điều này có nghĩa là URL chỉ được chứa một tập hợp con đặc biệt gồm các ký tự ASCII: ký hiệu chữ và số và một số ký tự dành riêng để sử dụng làm đối tượng kiểm soát ký tự trong URL. Bảng này tóm tắt những ký tự sau:
Đặt | ký tự | Sử dụng URL |
---|---|---|
Chữ và số | a b c d e f g h i j k l m n h o a o q u ả n g t ậ p A B C D E F G H I J K L M P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 | Chuỗi văn bản, cách sử dụng giao thức (http ), cổng (8080 ), v.v. |
Không dành riêng | — _ . ~ | Chuỗi văn bản |
Đã đặt trước | ! * ( ) ; : @ & = + $ , / ? % # [ ] | Ký tự điều khiển và/hoặc chuỗi văn bản |
Khi tạo một URL hợp lệ, bạn phải đảm bảo rằng URL đó chỉ chứa các ký tự đã hiển thị trong bảng. Tạo một URL để sử dụng bộ ký tự này thường dẫn đến hai vấn đề, một là không có và một là bị thay thế:
- Các ký tự bạn muốn xử lý tồn tại bên ngoài
đã chọn. Ví dụ: ký tự bằng tiếng nước ngoài
như
上海+中國
cần được mã hoá bằng ký tự phía trên. Theo quy ước phổ biến, không gian (là không được phép trong URL) thường được biểu thị bằng dấu cộng'+'
ký tự. - Các ký tự tồn tại trong tập hợp nêu trên dưới dạng ký tự dành riêng,
nhưng cần theo đúng nghĩa đen.
Ví dụ:
?
được sử dụng trong các URL để cho biết đầu chuỗi truy vấn; nếu bạn muốn sử dụng chuỗi "? và Bí ẩn," bạn sẽ cần mã hoá'?'
ký tự.
Tất cả các ký tự được mã hoá URL đều được mã hoá
sử dụng ký tự '%'
và hệ thập lục phân gồm hai ký tự
tương ứng với ký tự UTF-8 của chúng. Ví dụ:
上海+中國
trong UTF-8 sẽ được mã hoá URL thành
%E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B
. Chiến lược phát hành đĩa đơn
chuỗi ? and the Mysterians
sẽ được mã hoá URL thành
%3F+and+the+Mysterians
hoặc %3F%20and%20the%20Mysterians
.
Các ký tự phổ biến cần mã hoá
Một số ký tự phổ biến phải được mã hoá là:
Ký tự không an toàn | Giá trị được mã hoá |
---|---|
Không gian | %20 |
" | %22 |
< | %3C |
> | %3E |
# | %23 |
% | %25 |
| | %7C |
Đôi khi, việc chuyển đổi URL mà bạn nhận được từ hoạt động đầu vào của người dùng phức tạp. Ví dụ: người dùng có thể nhập địa chỉ là "5th&Main St." Thông thường, bạn nên xây dựng URL từ các phần của URL đó, xem xét bất kỳ hoạt động đầu vào nào của người dùng dưới dạng ký tự cố định.
Ngoài ra, URL chỉ được dài tối đa 16384 ký tự đối với tất cả các dịch vụ web trên Nền tảng Google Maps và API web tĩnh. Đối với hầu hết các dịch vụ, hiếm khi đạt đến giới hạn ký tự này. Tuy nhiên, Xin lưu ý rằng một số dịch vụ nhất định có một số tham số có thể dẫn đến URL dài.
Sử dụng lịch sự các API của Google
Các ứng dụng API được thiết kế kém có thể đặt tải nhiều hơn mức cần thiết trên cả Internet và của Google. Phần này trình bày một số phương pháp hay nhất dành cho các ứng dụng khách sử dụng API. Đang theo dõi Các phương pháp hay nhất này có thể giúp bạn tránh việc ứng dụng của mình bị chặn do vô tình sử dụng sai mục đích các API.
Thuật toán thời gian đợi luỹ thừa
Trong một số ít trường hợp, có thể xảy ra sự cố khi thực hiện yêu cầu của bạn; bạn có thể nhận được HTTP 4XX hoặc 5XX mã phản hồi hoặc kết nối TCP có thể chỉ bị lỗi ở đâu đó giữa ứng dụng của bạn và máy chủ. Thông thường, bạn nên thử yêu cầu lại yêu cầu theo dõi có thể thành công khi yêu cầu ban đầu không thành công. Tuy nhiên, điều quan trọng không chỉ là lặp lại nhiều lần để gửi yêu cầu đến máy chủ của Google. Hành vi lặp lại này có thể làm quá tải mạng giữa khách hàng của bạn và Google gây ra sự cố cho nhiều bên.
Cách tốt hơn là thử lại với độ trễ tăng dần giữa các lần thử. Thông thường, độ trễ sẽ tăng lên bằng một hệ số nhân với mỗi lần thử, một phương pháp được gọi là Thuật toán thời gian đợi luỹ thừa.
Ví dụ: hãy xem xét một đơn đăng ký muốn gửi yêu cầu này đến API Múi giờ:
https://maps.googleapis.com/maps/api/timezone/json?location=39.6034810,-119.6822510×tamp=1331161200&key=YOUR_API_KEY
Ví dụ sau đây trong Python cho thấy cách tạo yêu cầu bằng thuật toán thời gian đợi luỹ thừa:
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}")
Bạn cũng nên lưu ý rằng sẽ không có mã thử lại cao hơn trong lệnh gọi ứng dụng dẫn đến các yêu cầu lặp lại liên tiếp nhau.
Yêu cầu đã đồng bộ hoá
Một số lượng lớn các yêu cầu được đồng bộ hóa với các API của Google có thể trông giống như Cuộc tấn công Từ chối dịch vụ (DDoS) nhắm vào cơ sở hạ tầng của Google và được xử lý tương ứng. Người nhận để tránh tình trạng này, bạn nên đảm bảo rằng các yêu cầu API không được đồng bộ hoá giữa các ứng dụng.
Ví dụ: hãy xem xét một ứng dụng hiển thị thời gian theo múi giờ hiện tại. Ứng dụng này có thể sẽ đặt chuông báo trong hệ điều hành ứng dụng đánh thức thiết bị lúc thời gian bắt đầu của phút để có thể cập nhật thời gian hiển thị. Ứng dụng nên không thực hiện bất kỳ lệnh gọi API nào trong quá trình xử lý liên quan đến chuông báo đó.
Việc thực hiện lệnh gọi API để phản hồi một chuông báo đã khắc phục sẽ không tốt vì điều này dẫn đến việc các lệnh gọi API bị được đồng bộ hoá với thời điểm bắt đầu phút, ngay cả giữa các thiết bị khác nhau, thay vì được phân bổ đồng đều theo thời gian. Một ứng dụng được thiết kế không tốt làm việc này sẽ tạo ra ở mức 60 lần mức bình thường vào đầu mỗi phút.
Thay vào đó, bạn nên đặt chuông báo thứ hai theo thời gian được chọn ngẫu nhiên. Khi chuông báo thứ hai này kích hoạt, ứng dụng sẽ gọi bất kỳ API nào mà ứng dụng cần và lưu trữ kết quả. Khi muốn cập nhật màn hình vào đầu phút, ứng dụng sẽ sử dụng kết quả được lưu trữ trước đó thay vì gọi lại API. Với phương pháp này, lệnh gọi API được trải đều theo thời gian. Ngoài ra, các lệnh gọi API không trì hoãn việc kết xuất khi màn hình đang đang được cập nhật.
Ngoài phút bắt đầu, các thời gian đồng bộ hoá thông thường khác mà bạn nên cẩn thận không cần nhắm mục tiêu là thời điểm bắt đầu một giờ và bắt đầu mỗi ngày vào lúc nửa đêm.
Đang xử lý câu trả lời
Phần này thảo luận cách trích xuất các giá trị này một cách linh động từ phản hồi của dịch vụ web.
Dịch vụ web của Google Maps cung cấp câu trả lời dễ dàng hiểu, nhưng không hoàn toàn thân thiện với người dùng. Khi thực hiện truy vấn, thay vì ngoài việc hiển thị một tập dữ liệu cụ thể, bạn có thể muốn trích xuất một vài thông tin giá trị. Thông thường, bạn nên phân tích cú pháp phản hồi từ trang web và chỉ trích xuất những giá trị bạn quan tâm.
Giao thức phân tích cú pháp mà bạn sử dụng phụ thuộc vào việc bạn có quay lại hay không đầu ra ở định dạng XML hoặc JSON. Phản hồi JSON đang ở dạng Đối tượng JavaScript có thể được xử lý trong chính JavaScript trên máy khách. Phản hồi XML phải được xử lý bằng bộ xử lý XML và ngôn ngữ truy vấn XML để xử lý các phần tử trong định dạng XML. Chúng tôi sử dụng XPath trong phần các ví dụ sau đây, vì nó thường được hỗ trợ trong xử lý XML thư viện.
Xử lý XML bằng q
XML là một định dạng thông tin có cấu trúc tương đối hoàn thiện, được dùng cho
trao đổi dữ liệu. Mặc dù không nhẹ như JSON, nhưng XML
cung cấp nhiều hỗ trợ ngôn ngữ hơn và các công cụ mạnh mẽ hơn. Mã cho
xử lý XML trong Java, chẳng hạn, được tích hợp vào
javax.xml
gói.
Khi xử lý phản hồi XML, bạn nên sử dụng ngôn ngữ truy vấn để chọn các nút trong tài liệu XML, thay vì giả định các phần tử nằm ở vị trí tuyệt đối trong Mã đánh dấu XML. XPath là cú pháp ngôn ngữ để mô tả duy nhất các nút và phần tử trong tài liệu XML. Biểu thức Wi-Fi cho phép bạn xác định nội dung cụ thể trong tài liệu phản hồi XML.
Biểu thức Tên
Một chút quen thuộc với vai trò sẽ giúp bạn phát triển ứng dụng một giao thức phân tích cú pháp mạnh mẽ. Phần này sẽ tập trung vào cách các phần tử định địa chỉ trong tài liệu XML được ghi địa chỉ bằng Nhà quản lý đối tác xử lý nhiều phần tử và tạo các truy vấn phức tạp.
NETWORK sử dụng biểu thức để chọn các phần tử trong XML tài liệu, sử dụng cú pháp tương tự như cú pháp dùng cho đường dẫn thư mục. Những biểu thức này xác định các phần tử trong tài liệu XML là cây phân cấp tương tự như cây DOM. Nhìn chung, cách diễn đạt của ng là tham lam, thể hiện rằng sẽ khớp với tất cả các nút phù hợp với tiêu chí đã cung cấp.
Chúng tôi sẽ sử dụng XML trừu tượng sau để minh hoạ ví dụ:
<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>
Lựa chọn nút trong biểu thức
Chọn nút cho các mục lựa chọn Nhà quản lý đối tác. Nút gốc
bao gồm toàn bộ tài liệu. Bạn chọn nút này bằng cách sử dụng
biểu thức đặc biệt "/
". Lưu ý rằng thư mục gốc
nút không phải là nút cấp cao nhất của tài liệu XML; trên thực tế,
nó nằm trên phần tử cấp cao nhất một cấp và bao gồm
nó.
Các nút phần tử đại diện cho các phần tử khác nhau trong XML
cây tài liệu. Phần tử <WebServiceResponse>
,
đại diện cho phần tử cấp cao nhất được trả về trong
dịch vụ mẫu ở trên. Bạn chọn các nút riêng lẻ thông qua
đường dẫn tuyệt đối hoặc tương đối, được biểu thị bằng sự hiện diện hoặc
không có "/
" ở đầu .
- Đường dẫn tuyệt đối: "
/WebServiceResponse/result
" chọn tất cả các nút<result>
là con của<WebServiceResponse>
nút. (Lưu ý rằng cả hai phần tử này đều bắt nguồn từ gốc nút "/
".) - Đường dẫn tương đối trong ngữ cảnh hiện tại: biểu thức
"
result
" sẽ khớp với<result>
bất kỳ trong ngữ cảnh hiện tại. Thông thường, bạn không nên phải lo lắng về ngữ cảnh, vì bạn thường xử lý thông tin kết quả dịch vụ thông qua một biểu thức duy nhất.
Một trong hai biểu thức này có thể được tăng cường bằng cách thêm
của đường dẫn ký tự đại diện, biểu thị bằng dấu gạch chéo đôi ("//
").
Ký tự đại diện này cho biết rằng không có hoặc nhiều phần tử có thể khớp trong
đường dẫn xen kẽ. Biểu thức Wi-Fi "//formatted_address
"
ví dụ: sẽ khớp với tất cả các nút có tên đó trong tài liệu hiện tại.
Biểu thức //viewport//lat
sẽ khớp với tất cả
Các phần tử <lat>
có thể theo dõi <viewport>
cha mẹ.
Theo mặc định, biểu thức Wi-Fi khớp với tất cả các phần tử. Bạn có thể hạn chế
biểu thức để khớp với một phần tử nhất định bằng cách cung cấp một vị từ,
được đặt trong dấu ngoặc vuông ([]
). NETWORK
biểu thức "/GeocodeResponse/result[2]
luôn trả về
kết quả thứ hai.
Loại biểu cảm | |
---|---|
Root node | Biểu thức Nhà cung cấp dịch vụ Internet: "
/ "Lựa chọn:
<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> |
Đường dẫn tuyệt đối | Biểu thức Nhà cung cấp dịch vụ Internet: "
/WebServiceResponse/result "Lựa chọn:
<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> |
Đường dẫn có ký tự đại diện | Biểu thức Nhà cung cấp dịch vụ Internet: "
/WebServiceResponse//location "Lựa chọn:
<location> <lat>37.4217550</lat> <lng>-122.0846330</lng> </location> |
Đường dẫn có vị từ | Biểu thức Nhà cung cấp dịch vụ Internet: "
/WebServiceResponse/result[2]/message "Lựa chọn:
<message>The secret message</message> |
Tất cả phần tử con trực tiếp của result đầu tiên |
Biểu thức Nhà cung cấp dịch vụ Internet: "
/WebServiceResponse/result[1]/* "Lựa chọn:
<type>sample</type> <name>Sample XML</name> <location> <lat>37.4217550</lat> <lng>-122.0846330</lng> </location> |
name của
result có văn bản type là "mẫu". |
Biểu thức Nhà cung cấp dịch vụ Internet: "
/WebServiceResponse/result[type/text()='sample']/name "Lựa chọn:
Sample XML |
Điều quan trọng cần lưu ý là khi chọn phần tử, bạn phải chọn nút, chứ không chỉ văn bản trong các đối tượng đó. Nhìn chung, bạn sẽ muốn lặp lại tất cả các nút phù hợp và trích xuất văn bản. Bạn cũng có thể so khớp trực tiếp với các nút văn bản; xem Nút văn bản ở bên dưới.
Lưu ý rằng vai trò cũng hỗ trợ các nút thuộc tính; tuy nhiên, tất cả các dịch vụ web của Google Maps đều cung cấp các phần tử không có thuộc tính, vì vậy kết hợp các thuộc tính là không cần thiết.
Chọn văn bản trong biểu thức
Văn bản trong tài liệu XML được chỉ định trong biểu thức Tên
thông qua toán tử nút văn bản. Toán tử này "text()
"
biểu thị việc trích xuất văn bản từ nút được chỉ định. Ví dụ:
biểu thức Wi-Fi "//formatted_address/text()
" sẽ
trả về tất cả văn bản trong <formatted_address>
phần tử.
Loại biểu cảm | |
---|---|
Tất cả các nút văn bản (bao gồm cả khoảng trắng) | Biểu thức Nhà cung cấp dịch vụ Internet: "
//text() "Lựa chọn:
sample Sample XML 37.4217550 -122.0846330 The secret message |
Chọn văn bản | Biểu thức Nhà cung cấp dịch vụ Internet: "
/WebServiceRequest/result[2]/message/text() "Lựa chọn:
The secret message |
Lựa chọn nhạy cảm về bối cảnh | Biểu thức Nhà cung cấp dịch vụ Internet: "
/WebServiceRequest/result[type/text() = 'sample']/name/text() "Lựa chọn:
Sample XML |
Ngoài ra, bạn có thể đánh giá một biểu thức và trả về một tập hợp và sau đó lặp lại "tập hợp nút" đó, trích xuất văn bản từ mỗi nút. Chúng tôi sử dụng phương pháp này trong ví dụ bên dưới.
Để biết thêm thông tin về q, hãy tham khảo Thông số kỹ thuật W3C của ngỏ.
Đánh giá XPath trong Java
Java có hỗ trợ rộng rãi cho việc phân tích cú pháp XML và sử dụng biểu thức Tên
trong gói javax.xml.xpath.*
.
Vì lý do đó, mã mẫu trong phần này sử dụng Java để
minh hoạ cách xử lý XML và phân tích cú pháp dữ liệu trong phản hồi của dịch vụ XML.
Để sử dụng Wi-Fi trong mã Java, trước tiên bạn cần tạo thực thể
một thực thể của XPathFactory
và gọi
newXPath()
trên nhà máy đó để tạo đối tượng XPath
. Sau đó, đối tượng này có thể xử lý tệp XML đã truyền
và biểu thức quyết định sử dụng phương thức evaluate()
.
Khi đánh giá biểu thức Wi-Fi, hãy nhớ lặp lại
trên mọi "nhóm nút" có thể có Hàm này có thể được trả về. Bởi vì
kết quả được trả về dưới dạng các nút DOM trong mã Java, bạn nên chụp
nhiều giá trị như vậy trong đối tượng NodeList
và
lặp lại đối tượng đó để trích xuất mọi văn bản hoặc giá trị từ những đối tượng đó
nút.
Đoạn mã sau minh hoạ cách tạo XPath
, chỉ định đối tượng XML và biểu thức vai trò, đồng thời đánh giá
để in nội dung có liên quan.
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"); } } }