2008년 3월
목표
이 튜토리얼에서는 Python을 사용하여 쉼표로 구분된 값 (CSV) 데이터에서 KML을 만드는 방법을 간략하게 설명합니다. CSV 데이터는 오늘날 가장 널리 사용되는 파일 형식 중 하나입니다. 대부분의 스프레드시트와 데이터베이스는 CSV 파일을 읽고 쓸 수 있습니다. 간단한 형식으로 텍스트 편집기에서 수정할 수 있습니다. Python과 같은 많은 프로그래밍 언어에는 CSV 파일을 읽고 쓰는 특수 라이브러리가 있습니다. 따라서 대량의 데이터를 교환하는 데 적합합니다.
이 튜토리얼의 코드 샘플은 Python으로 작성되었지만 대부분의 다른 프로그래밍 언어로도 적용할 수 있습니다. 이 튜토리얼에서는 KML에서 사용할 주소 지오코딩의 코드를 사용하여 주소를 경도/위도 좌표로 변환합니다. 또한 KML 2.2의 새로운 <ExtendedData>
요소를 사용하고 맞춤 데이터 추가에 설명된 풍선 템플릿을 활용합니다. 따라서 생성된 KML은 현재 Google 지도 또는 기타 KML 사용 애플리케이션에서 지원되지 않지만 코드를 조정하여 지도 호환 KML을 생성할 수 있습니다.
샘플 데이터
이 튜토리얼에서는 google-addresses.csv 파일을 샘플 CSV 파일로 사용합니다. 이 파일에는 다양한 미국 Google 사무실의 주소, 전화번호, 팩스 번호가 모두 포함되어 있습니다. 파일의 텍스트는 다음과 같습니다.
Office,Address1,Address2,Address3,City,State,Zip,Phone,Fax Headquarters,1600 Amphitheatre Parkway,,,Mountain View,CA,94043,650-253-0000,650-253-0001 New York Sales & Engineering Office,76 Ninth Avenue,,,New York,NY,10011,212-565-0000,212-565-0001 Ann Arbor Sales Office,201 South Division Street,,,Ann Arbor,MI,48104,734-332-6500,734-332-6501 Atlanta Sales & Engineering Office,10 10th Street NE,,,Atlanta,GA,30309,404-487-9000,404-487-9001 Boulder Sales & Engineering Office,2590 Pearl St.,,,Boulder,CO,80302,303-245-0086,303-535-5592 Cambridge Sales & Engineering Office,5 Cambridge Center,,,Cambridge,MA,02142,617-682-3635,617-249-0199 Chicago Sales & Engineering Office,20 West Kinzie St.,,,Chicago,IL,60610,312-840-4100,312-840-4101 Coppell Sales Office,701 Canyon Drive,,,Coppell,TX,75019,214-451-4000,214-451-4001 Detroit Sales Office,114 Willits Street,,,Birmingham,MI,48009,248-351-6220,248-351-6227 Irvine Sales & Engineering Office,19540 Jamboree Road,,,Irvine,CA,92612,949-794-1600,949-794-1601 Pittsburgh Engineering Office,4720 Forbes Avenue,,,Pittsburgh,PA,15213,, Santa Monica Sales & Engineering Office,604 Arizona Avenue,,,Santa Monica,CA,90401,310-460-4000,310-309-6840 Seattle Engineering Office,720 4th Avenue,,,Kirkland,WA,98033,425-739-5600,425-739-5601 Seattle Sales Office,501 N. 34th Street,,,Seattle,WA,98103,206-876-1500,206-876-1501 Washington D.C. Public Policy Office,1001 Pennsylvania Avenue NW,,,Washington,DC,20004,202-742-6520,
각 줄은 쉼표로 구분된 일련의 텍스트 문자열입니다.
각 쉼표는 필드를 구분하며 각 줄에는 동일한 수의 쉼표가 있습니다.
첫 번째 줄에는 필드 이름이 순서대로 포함됩니다. 예를 들어 각 행의 첫 번째 텍스트 블록은 'Office' 필드이고 두 번째는 'Address1'입니다. Python은 이를 DictReader
라는 dicts
모음으로 변환하여 각 행을 단계별로 살펴볼 수 있습니다. 이 코드 샘플은 데이터의 구조를 미리 알고 있다고 가정하지만 필드 구조를 동적으로 전달하는 기본 핸들러를 추가할 수 있습니다.
CSV 파일 파싱
Python의 xml.dom.minidom
모듈은 XML 문서를 만들기 위한 유용한 도구를 제공하며 KML은 XML이므로 이 튜토리얼에서 많이 사용하게 됩니다. createElement
또는 createElementNS
로 요소를 만들고 appendChild
로 다른 요소에 추가합니다.
다음은 CSV 파일을 파싱하고 KML 파일을 만드는 단계입니다.
- geocoding_for_kml.py를 모듈로 가져옵니다.
- CSV 파일의
DictReader
를 만듭니다.DictReader
는 각 행에 하나씩 있는dicts
의 모음입니다. - Python의
xml.dom.minidom.Document()
을 사용하여 문서를 만듭니다. createElementNS.
을 사용하여 루트<kml>
요소를 만듭니다.- 문서
에 추가합니다.
createElement
를 사용하여<Document>
요소를 만듭니다.appendChild
을 사용하여<kml>
요소에 추가합니다.- 각 행에 대해
<Placemark>
요소를 만들고<Document>
요소에 추가합니다. - 각 행의 각 열에 대해
<ExtendedData>
요소를 만들고 8단계에서 만든<Placemark>
요소에 추가합니다. <Data>
요소를 만들고<ExtendedData>
요소에 추가합니다.<Data>
요소에 이름 속성을 부여하고setAttribute
을 사용하여 열 이름 값을 할당합니다.<value>
요소를 만들어<Data>
요소에 추가합니다. 텍스트 노드를 만들고createTextNode
를 사용하여 열의 값을 할당합니다. 텍스트 노드를<value>
요소에 추가합니다.<Point>
요소를 만들고<Placemark>
요소에 추가합니다.<coordinates>
요소를 만들어<Point>
요소에 추가합니다.- 주소를 행에서 추출하여 Address1,Address2,City,State,Zip 형식의 단일 문자열이 되도록 합니다. 따라서 첫 번째 행은
1600 Amphitheater Parkway,,Mountain View,CA,94043
입니다. 쉼표가 서로 옆에 있어도 괜찮습니다. 이를 위해서는 CSV 파일의 구조와 주소를 구성하는 열을 미리 알고 있어야 합니다. - KML에서 사용할 주소 지오코딩에 설명된 geocoding_for_kml.py 코드를 사용하여 주소를 지오코딩합니다. 위치의 경도와 위도인 문자열을 반환합니다.
- 텍스트 노드를 만들고 14단계의 좌표 값을 할당한 다음
<coordinates>
요소에 추가합니다. - KML 문서를 파일에 씁니다.
- 열 이름 목록을 스크립트에 인수로 전달하면 스크립트가 해당 순서대로 요소를 추가합니다. 요소의 순서가 중요하지 않다면
dict.keys()
를 사용하여list
를 생성할 수 있습니다. 하지만dict.keys()
은 문서의 원래 순서를 유지하지 않습니다. 이 인수를 사용하려면 다음과 같이 필드 이름 목록을 쉼표로 구분된 목록으로 전달합니다.python csvtokml.py Office,Address1,Address2,Address3,City,State,Zip,Phone,Fax
샘플 Python 코드
Python 2.2를 사용하여 CSV 파일에서 KML 파일을 만드는 샘플 코드는 아래와 같습니다. 여기에서 다운로드할 수도 있습니다.
import geocoding_for_kml
import csv
import xml.dom.minidom
import sys
def extractAddress(row):
# This extracts an address from a row and returns it as a string. This requires knowing
# ahead of time what the columns are that hold the address information.
return '%s,%s,%s,%s,%s' % (row['Address1'], row['Address2'], row['City'], row['State'], row['Zip'])
def createPlacemark(kmlDoc, row, order):
# This creates aelement for a row of data.
# A row is a dict.
placemarkElement = kmlDoc.createElement('Placemark')
extElement = kmlDoc.createElement('ExtendedData')
placemarkElement.appendChild(extElement)
# Loop through the columns and create a element for every field that has a value.
for key in order:
if row[key]:
dataElement = kmlDoc.createElement('Data')
dataElement.setAttribute('name', key)
valueElement = kmlDoc.createElement('value')
dataElement.appendChild(valueElement)
valueText = kmlDoc.createTextNode(row[key])
valueElement.appendChild(valueText)
extElement.appendChild(dataElement)
pointElement = kmlDoc.createElement('Point')
placemarkElement.appendChild(pointElement)
coordinates = geocoding_for_kml.geocode(extractAddress(row))
coorElement = kmlDoc.createElement('coordinates')
coorElement.appendChild(kmlDoc.createTextNode(coordinates))
pointElement.appendChild(coorElement)
return placemarkElement
def createKML(csvReader, fileName, order):
# This constructs the KML document from the CSV file.
kmlDoc = xml.dom.minidom.Document()
kmlElement = kmlDoc.createElementNS('http://earth.google.com/kml/2.2', 'kml')
kmlElement.setAttribute('xmlns','http://earth.google.com/kml/2.2')
kmlElement = kmlDoc.appendChild(kmlElement)
documentElement = kmlDoc.createElement('Document')
documentElement = kmlElement.appendChild(documentElement)
# Skip the header line.
csvReader.next()
for row in csvReader:
placemarkElement = createPlacemark(kmlDoc, row, order)
documentElement.appendChild(placemarkElement)
kmlFile = open(fileName, 'w')
kmlFile.write(kmlDoc.toprettyxml(' ', newl = '\n', encoding = 'utf-8'))
def main():
# This reader opens up 'google-addresses.csv', which should be replaced with your own.
# It creates a KML file called 'google.kml'.
# If an argument was passed to the script, it splits the argument on a comma
# and uses the resulting list to specify an order for when columns get added.
# Otherwise, it defaults to the order used in the sample.
if len(sys.argv) >1: order = sys.argv[1].split(',')
else: order = ['Office','Address1','Address2','Address3','City','State','Zip','Phone','Fax']
csvreader = csv.DictReader(open('google-addresses.csv'),order)
kml = createKML(csvreader, 'google-addresses.kml', order)
if __name__ == '__main__':
main()
샘플 KML 생성됨
이 스크립트가 만드는 KML의 샘플은 아래에 나와 있습니다.
일부 <value>
요소에는 공백만 있습니다. 필드에 데이터가 없기 때문입니다. 여기에서 전체 샘플을 다운로드할 수도 있습니다.
<?xml version="1.0" encoding="utf-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
<Document>
<Placemark>
<ExtendedData>
<Data name="Office">
<value>
Headquarters
</value>
</Data>
<Data name="Address1">
<value>
1600 Amphitheater Parkway
</value>
</Data>
<Data name="City">
<value>
Mountain View
</value>
</Data>
<Data name="State">
<value>
CA
</value>
</Data>
<Data name="Zip">
<value>
94043
</value>
</Data>
<Data name="Phone">
<value>
650-253-0000
</value>
</Data>
<Data name="Fax">
<value>
650-253-0001
</value>
</Data>
</ExtendedData>
<Point>
<coordinates>
-122.081783,37.423111
</coordinates>
</Point>
</Placemark>
...
스크린샷
아래는 Google 어스에서 해당 KML 파일이 어떻게 표시되는지 보여주는 스크린샷입니다.
각 <Placemark>
요소에는 <BalloonStyle><text>
및 <description>
요소가 없으므로 풍선은 기본적으로 <Data>
요소를 기반으로 테이블 스타일을 사용합니다.

지오코딩 고려사항
'KML에서 사용할 주소의 지오코딩'에 언급되었지만 다시 한번 강조합니다. 지오코딩 요청에는 IP를 기반으로 지오코더의 최대 쿼리 비율과 일일 15,000개의 쿼리가 적용됩니다. 또한 지오코더가 처리할 수 있는 것보다 빠르게 쿼리하면 지오코더에서 620
상태 코드를 반환합니다. (전체 상태 코드 목록은 여기에서 확인할 수 있습니다.)
지오코더에 쿼리를 너무 빠르게 보내지 않으려면 각 지오코드 요청 간에 지연 시간을 지정하면 됩니다. 620
상태를 수신할 때마다 이 지연 시간을 늘리고 while
루프를 사용하여 다음 주소로 반복하기 전에 주소를 성공적으로 지오코딩했는지 확인할 수 있습니다. 즉, CSV 파일이 매우 큰 경우 지오코딩 코드를 수정하거나 위치 표시자를 만드는 속도를 추적하고 너무 빠른 경우 속도를 늦춰야 할 수 있습니다.
결론
이제 Python을 사용하여 CSV 파일에서 KML 파일을 만들 수 있습니다. 제공된 코드를 사용하면 KML 파일이 Google 어스에서만 작동합니다. <ExtendedData>
대신 <description>
를 사용하여 지도와 Earth 모두에서 작동하도록 수정할 수 있습니다.
또한 이 코드 샘플을 XML을 지원하는 다른 프로그래밍 언어로 쉽게 변환할 수 있습니다.
이제 모든 CSV 파일을 KML로 변환했으므로 PHP 및 MySQL을 사용하여 KML 만들기 및 ExtendedData에 관한 Google 개발자 가이드 문서인 맞춤 데이터 추가와 같은 다른 KML 문서를 확인해 보세요.