KML에서 사용할 주소 지오코딩

Mano Marks, Google Geo Team
작성: 2007년 12월
업데이트: 2013년 12월

목표

이 튜토리얼은 스크립트 언어에 익숙하고 Google Geocoding API를 사용하여 주소를 지오코딩하고 KML 파일에 통합하는 방법을 배우려는 개발자를 대상으로 합니다. 코드 샘플은 Python으로 제공되지만 대부분의 다른 프로그래밍 언어로 비교적 쉽게 조정할 수 있습니다.

지오코딩은 주소를 위도/경도 좌표 집합으로 변환하여 지도에 주소를 표시할 수 있도록 하는 과정입니다. 주소를 지오코딩하여 KML 파일에 직접 넣을 수도 있습니다. 이는 예를 들어 양식에 데이터를 입력하고 요청에 따라 KML 파일을 생성하는 경우에 흔히 발생합니다. 이러한 KML 파일은 데이터베이스나 파일 시스템에 저장되거나 파일에 연결된 NetworkLink로 반환될 수 있습니다. 이 기법을 사용할 때는 결과를 저장할 수 있는 시간과 매일 지오코딩할 수 있는 요소의 수에 제한이 있으므로 Geocoding 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 문서를 만들 수 있습니다. Python의 minidom은 DOM 구현이며 DOM은 대부분의 프로그래밍 언어에서 지원되므로 이 프로세스를 다른 프로그래밍 언어로 쉽게 포팅할 수 있습니다. 다음 단계를 따르세요.

  1. Python의 xml.dom.minidom.Document()을 사용하여 문서를 만듭니다.
  2. createElementNS.을 사용하여 루트 <kml> 요소 만들기
  3. appendChild을 사용하여 문서에 추가합니다.
  4. createElement을 사용하여 문서 요소를 만듭니다.
  5. appendChild를 사용하여 <kml> 요소에 추가합니다.
  6. 각 주소에 대해 createElement를 사용하여 <Placemark> 요소를 만들고 Document 요소에 추가합니다. 그런 다음 <description> 요소를 만들고 주소 값을 할당하고 <Placemark> 요소에 추가합니다.
  7. <Point> 요소를 만들고 하위 <coordinates> 요소를 추가한 후 <Placemark> 요소에 추가합니다.
  8. 주소를 Maps API Geocoder로 전송합니다. 그러면 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 루프를 사용하여 다음 주소로 반복하기 전에 주소를 성공적으로 지오코딩했는지 확인할 수 있습니다.

기본 국가 변경

지오코더는 원래 도메인에 따라 결과를 편향되도록 프로그래밍되어 있습니다. 예를 들어 maps.google.com의 검색창에 'syracuse'를 입력하면 'Syracuse, NY' 도시가 지오코딩되지만 maps.google.it (이탈리아 도메인)에 동일한 검색어를 입력하면 시칠리아의 'Siracusa' 도시가 검색됩니다. 위 샘플 코드에서 mapsUrl 변수를 수정하여 maps.google.com이 아닌 maps.google.it에 HTTP 지오코딩을 통해 쿼리를 전송해도 동일한 결과를 얻을 수 있습니다. 지역 편향에 관한 자세한 내용은 Geocoding API 문서를 참고하세요.

참고: 존재하지 않는 maps.google.* 서버에 요청을 보낼 수 없으므로 지오코딩 쿼리를 리디렉션하기 전에 국가 도메인이 있는지 확인하세요. 국가별 지오코드 지원은 이 게시물을 참고하세요.

결론

위의 코드를 사용하여 이제 Python으로 주소를 지오코딩하고, 이를 기반으로 KML <Placemark>를 만들어 디스크에 저장할 수 있습니다. 일일 지오코딩 주소 수가 한도를 초과하거나 Google 지오코더가 관심 있는 지역을 지원하지 않는 경우 추가 지오코딩 웹 서비스를 사용하는 것이 좋습니다.

주소를 지오코딩하는 방법을 알았으니 Google 매시업 편집기에서 KML 사용PHP 및 MySQL을 사용하여 KML 만들기에 관한 도움말을 확인하세요. 이 튜토리얼에 문제가 있거나 궁금한 점이 있으면 Stack Overflow 포럼에 게시해 주세요.