Геокодирование адресов для использования в KML

Мано Маркс, команда Google Geo
Автор: декабрь 2007 г.
Обновлено: декабрь 2013 г.

Цель

Это руководство предназначено для разработчиков, знакомых со скриптовыми языками и желающих научиться использовать API геокодирования Google для геокодирования адресов и их включения в KML-файл. Хотя примеры кода представлены на Python, их можно легко адаптировать к большинству других языков программирования.

Геокодирование — это процесс преобразования адреса в набор координат широты и долготы, что позволяет отображать адреса на карте. Вы можете геокодировать адреса и сохранять их непосредственно в KML-файл. Это часто встречается, например, при вводе данных в форму и создании KML-файлов в ответ на запросы. Эти KML-файлы могут храниться в базе данных, файловой системе или возвращаться по NetworkLink, подключающемуся к вашему файлу. Обратите внимание, что при использовании этого метода необходимо соблюдать Условия использования API геокодирования, поскольку существуют ограничения на срок хранения результатов и количество геокодируемых элементов в день.

В этом уроке показано, как использовать Python, чтобы взять строку « 1600 Amphitheatre Pkwy, Mountain View, CA 94043 » и преобразовать ее в следующее:

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

Создать KML-документ

KML — это язык разметки XML, поэтому мы можем использовать встроенные функции Python xml.dom.minidom для создания KML-документа. Minidom в Python — это реализация DOM , которая поддерживается большинством языков программирования, поэтому этот процесс должен быть легко перенесен на другой язык программирования. Вот шаги:

  1. Создайте документ с помощью xml.dom.minidom.Document() Python.
  2. Создайте корневой элемент <kml> с помощью createElementNS.
  3. Добавьте его к документу с помощью appendChild .
  4. Создайте элемент Document с помощью createElement .
  5. Добавьте его к элементу <kml> с помощью appendChild .
  6. Для каждого адреса создайте элемент <Placemark> с помощью createElement и добавьте его к элементу Document . Затем создайте элемент <description> , присвойте ему значение адреса и добавьте его к элементу <Placemark> .
  7. Создайте элемент <Point> , добавьте дочерний элемент <coordinates> и присоедините его к элементу <Placemark> .
  8. Отправьте адрес геокодеру Maps API, который отправит ответ в формате JSON или XML. Используйте urllib.urlopen() для извлечения файла и преобразования его в строку.
  9. Проанализируйте ответ и извлеките элементы долготы и широты.
  10. Создайте текстовый узел в элементе <coordinates> и присвойте ему строку долготы/широты в качестве значения.
  11. Запишите KML-документ в текстовый файл.

Пример кода Python

Обратите внимание, что в примере кода ниже используется фиктивная переменная mapsKey — вам нужно заменить этот ключ своим собственным ключом .

Пример кода для геокодирования с использованием Python 2.7 и вывода JSON показан ниже:

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

Другие вещи, которые следует учитывать

Расчет времени запросов на геокодирование

Запросы на геокодирование будут ограничены максимальной суточной частотой запросов геокодера. Подробнее об этих ограничениях см. в документации Google Geocoding API. Чтобы не отправлять запросы геокодеру слишком часто, можно указать задержку между каждым запросом. Эту задержку можно увеличивать каждый раз, когда вы получаете статус OVER_QUERY_LIMIT , и использовать цикл while , чтобы убедиться в успешном геокодировании адреса перед переходом к следующему.

Изменение базовой страны

Геокодер запрограммирован на смещение результатов в зависимости от исходного домена. Например, ввод «syracuse» в поле поиска на maps.google.com геокодирует город «Syracuse, NY», а ввод того же запроса на maps.google.it (домен Италии) найдёт город «Siracusa» на Сицилии. Вы получите те же результаты, отправив этот запрос через HTTP-геокодирование на maps.google.it вместо maps.google.com , изменив переменную mapsUrl в примере кода выше. Подробнее о смещении региона см. в документации по Geocoding API.

Примечание: Вы не можете отправить запрос на несуществующий сервер maps.google.*, поэтому убедитесь, что домен страны существует, прежде чем перенаправлять на него запросы геокодирования. Подробнее о поддержке геокодирования по странам см. в этой публикации .

Заключение

Используя приведённый выше код, вы теперь можете геокодировать адрес с помощью Python, создать на его основе KML-файл <Placemark> и сохранить его на диск. Если вы обнаружите, что вам нужно геокодировать больше адресов в день, чем позволяет лимит, или что геокодер Google не охватывает интересующие вас регионы, рассмотрите возможность использования дополнительных веб-сервисов геокодирования.

Теперь, когда вы знаете, как геокодировать адреса, ознакомьтесь со статьями «Использование KML в Google Mashup Editor» и «Использование PHP и MySQL для создания KML» . Если у вас возникнут какие-либо проблемы или вопросы по этому руководству, пожалуйста, оставьте сообщение на форуме Stack Overflow .