Địa chỉ mã hóa địa lý để sử dụng trong KML

Mano Marks, Nhóm Google Geo
Tác giả: Tháng 12 năm 2007
Cập nhật: Tháng 12 năm 2013

Mục tiêu

Hướng dẫn này dành cho các nhà phát triển quen thuộc với ngôn ngữ viết tập lệnh và muốn tìm hiểu cách sử dụng API mã hoá địa lý của Google để mã hoá địa chỉ và tích hợp các địa chỉ này vào tệp KML. Mặc dù mã mẫu được trình bày bằng Python, nhưng các mẫu đó có thể được điều chỉnh khá dễ dàng cho hầu hết các ngôn ngữ lập trình khác.

Mã hóa địa lý là quá trình chuyển đổi một địa chỉ thành một tọa độ có vĩ độ/kinh độ, giúp bạn có thể chỉ định các địa chỉ trên bản đồ. Bạn có thể muốn mã hoá địa lý các địa chỉ và đặt chúng trực tiếp vào tệp KML. Vấn đề này thường xảy ra, chẳng hạn như khi dữ liệu được nhập vào biểu mẫu và bạn đang tạo tệp KML để phản hồi các yêu cầu. Những tệp KML này có thể được lưu trữ trong cơ sở dữ liệu, trong hệ thống tệp hoặc được trả về một NetworkLink kết nối với tệp của bạn. Xin lưu ý rằng khi sử dụng kỹ thuật này, bạn phải tuân thủ Điều khoản dịch vụ đối với API mã hoá địa lý vì có một số giới hạn về thời gian lưu trữ kết quả, cũng như số lượng phần tử mà bạn có thể mã hoá địa lý mỗi ngày.

Phần hướng dẫn này sẽ hướng dẫn bạn cách sử dụng Python để lấy chuỗi "1600 Amphitheatre Pkwy, Mountain View, CA 94043" và biến chuỗi đó thành như sau:

<?xml version='1.0' encoding='UTF-8'?> 
<kml xmlns='http://earth.google.com/kml/2.2'>
<Document>
<Placemark>
<description>1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA</description>
<Point>
<coordinates>-122.081783,37.423111,0</coordinates>
</Point>
</Placemark>
</Document>
</kml>

Tạo tài liệu KML

KML là một ngôn ngữ đánh dấu XML, vì vậy chúng ta có thể sử dụng các hàm xml.dom.minidom tích hợp sẵn của Python để tạo tài liệu KML. Sự đơn giản của Python là một hoạt động triển khai DOM và DOM được hỗ trợ ở hầu hết các ngôn ngữ lập trình, vì vậy quá trình này sẽ dễ dàng chuyển sang một ngôn ngữ lập trình khác. Sau đây là các bước:

  1. Tạo tài liệu bằng cách sử dụng xml.dom.minidom.Document() của Python.
  2. Tạo phần tử <kml> gốc bằng cách sử dụng createElementNS.
  3. Thêm vào tài liệu bằng cách sử dụng appendChild.
  4. Tạo phần tử Tài liệu bằng createElement.
  5. Thêm nó vào phần tử <kml> bằng cách sử dụng appendChild.
  6. Đối với mỗi địa chỉ, hãy tạo một phần tử <Placemark> bằng cách sử dụng createElement và thêm phần tử đó vào phần tử Document. Sau đó, hãy tạo một phần tử <description>, chỉ định giá trị của địa chỉ và thêm phần tử đó vào phần tử <Placemark>.
  7. Tạo một phần tử <Point>, thêm một phần tử con <coordinates> và thêm phần tử đó vào phần tử <Placemark>.
  8. Gửi địa chỉ đến Bộ mã hóa địa lý API Maps để gửi phản hồi trong JSON hoặc XML. Sử dụng urllib.urlopen() để truy xuất tệp và đọc thành một chuỗi.
  9. Phân tích cú pháp phản hồi và trích xuất kinh độ và phần tử vĩ độ.
  10. Tạo một nút văn bản trong phần tử <coordinates> và gán chuỗi kinh độ/vĩ độ làm giá trị.
  11. Ghi tài liệu KML vào tệp văn bản.

Mã Python mẫu

Xin lưu ý rằng mã mẫu bên dưới sử dụng một biến mapKey giả mạo — bạn cần thay thế khóa này bằng khoá riêng của mình.

Mã mẫu để mã hoá địa lý bằng đầu ra Python 2.7 và JSON được trình bày dưới đây:

import urllib
import xml.dom.minidom
import json 

def geocode(address, sensor=False):
 # This function queries the Google Maps API geocoder with an
 # address. It gets back a csv file, which it then parses and
 # returns a string with the longitude and latitude of the address.

 # This isn't an actual maps key, you'll have to get one yourself.
 # Sign up for one here: https://code.google.com/apis/console/
  mapsKey = 'abcdefgh'
  mapsUrl = 'https://maps.googleapis.com/maps/api/geocode/json?address='
     
 # This joins the parts of the URL together into one string.
  url = ''.join([mapsUrl,urllib.quote(address),'&sensor=',str(sensor).lower()])
#'&key=',mapsKey])
  jsonOutput = str(urllib.urlopen(url).read ()) # get the response 
  # fix the output so that the json.loads function will handle it correctly
  jsonOutput=jsonOutput.replace ("\\n", "")
  result = json.loads(jsonOutput) # converts jsonOutput into a dictionary 
  # check status is ok i.e. we have results (don't want to get exceptions)
  if result['status'] != "OK": 
    return ""
  coordinates=result['results'][0]['geometry']['location'] # extract the geometry 
  return str(coordinates['lat'])+','+str(coordinates['lng'])

def createKML(address, fileName):
 # This function creates an XML document and adds the necessary
 # KML elements.

  kmlDoc = xml.dom.minidom.Document()
  
  kmlElement = kmlDoc.createElementNS('http://earth.google.com/kml/2.2','kml')

  kmlElement = kmlDoc.appendChild(kmlElement)

  documentElement = kmlDoc.createElement('Document')
  documentElement = kmlElement.appendChild(documentElement)

  placemarkElement = kmlDoc.createElement('Placemark')
  
  descriptionElement = kmlDoc.createElement('description')
  descriptionText = kmlDoc.createTextNode(address)
  descriptionElement.appendChild(descriptionText)
  placemarkElement.appendChild(descriptionElement)
  pointElement = kmlDoc.createElement('Point')
  placemarkElement.appendChild(pointElement)
  coorElement = kmlDoc.createElement('coordinates')

  # This geocodes the address and adds it to a  element.
  coordinates = geocode(address)
  coorElement.appendChild(kmlDoc.createTextNode(coordinates))
  pointElement.appendChild(coorElement)

  documentElement.appendChild(placemarkElement)

  # This writes the KML Document to a file.
  kmlFile = open(fileName, 'w')
  kmlFile.write(kmlDoc.toprettyxml(' '))  
  kmlFile.close()

if __name__ == '__main__':
  createKML('1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA', 'google.kml')

Những việc khác cần cân nhắc

Đặt thời gian cho yêu cầu mã địa lý

Các yêu cầu mã hóa địa lý sẽ phải tuân theo giới hạn tỷ lệ truy vấn tối đa hàng ngày của bộ mã hóa. Vui lòng tham khảo tài liệu API mã hoá địa lý của Google để biết thêm thông tin về các giới hạn này. Để đảm bảo bạn không gửi truy vấn quá nhanh đến bộ mã hoá địa lý, bạn có thể chỉ định độ trễ giữa mỗi yêu cầu mã hoá địa lý. Bạn có thể tăng độ trễ này mỗi khi nhận được trạng thái OVER_QUERY_LIMIT và sử dụng vòng lặp while để đảm bảo bạn đã mã hóa thành công một địa chỉ trước khi lặp lại đến địa chỉ tiếp theo.

Thay đổi quốc gia cơ sở

Bộ mã hoá địa lý được lập trình để thiên vị kết quả tuỳ thuộc vào miền gốc. Ví dụ: việc nhập "syracuse" vào hộp tìm kiếm trên maps.google.com sẽ mã hoá địa lý thành phố "Syracuse, NY", trong khi nhập cùng một truy vấn trên maps.google.it (miền của Ý) sẽ tìm thấy thành phố "Siracusa" ở Sicily. Bạn sẽ nhận được kết quả tương tự bằng cách gửi truy vấn đó qua mã hóa địa lý HTTP đến maps.google.it thay vì maps.google.com. Bạn có thể thực hiện việc này bằng cách sửa đổi biến mapsUrl trong mã mẫu ở trên. Hãy tham khảo tài liệu về API mã hoá địa lý để biết thêm thông tin về Xu hướng khu vực.

Lưu ý: Bạn không thể gửi yêu cầu đến máy chủ map.google.* không tồn tại, vì vậy, hãy đảm bảo rằng miền quốc gia tồn tại trước khi chuyển hướng các truy vấn mã hóa địa lý tới miền đó. Để được hỗ trợ về mã hoá địa lý theo quốc gia, hãy đọc bài đăng này.

Kết luận

Khi sử dụng mã ở trên, giờ đây, bạn có thể mã hoá địa chỉ một địa chỉ bằng Python, tạo một KML <Placemark> từ địa chỉ đó và lưu vào ổ đĩa. Nếu bạn thấy rằng bạn cần mã hóa nhiều địa chỉ hơn mỗi ngày so với giới hạn cho phép hoặc bộ mã hóa địa lý của Google không bao gồm các khu vực bạn quan tâm, thì hãy cân nhắc sử dụng các dịch vụ web mã hóa địa lý bổ sung.

Giờ đây, khi bạn đã biết cách mã hoá địa lý các địa chỉ của mình, hãy xem các bài viết vềSử dụng KML trong Google Mashup EditorSử dụng PHP và MySQL để tạo KML. Nếu bạn gặp bất kỳ vấn đề hoặc câu hỏi nào về hướng dẫn này, vui lòng đăng lên diễn đàn Stack Overflow.