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>
요소에 name 속성을 부여하고setAttribute
를 사용하여 열 이름 값을 할당합니다.<value>
요소를 만들어<Data>
요소에 추가합니다. 텍스트 노드를 만들고createTextNode
를 사용하여 열 값을 할당합니다. 텍스트 요소를<value>
요소에 추가합니다.<Point>
요소를 만들어<Placemark>
요소에 추가합니다.<coordinates>
요소를 만들어<Point>
요소에 추가합니다.- Address1,Address2,City,State,Zip과 같은 형식의 단일 문자열이 되도록 행에서 주소를 추출합니다. 따라서 첫 번째 행은
1600 Amphitheater Parkway,,Mountain View,CA,94043
입니다. 쉼표를 나란히 붙여도 괜찮습니다. 이를 위해서는 CSV 파일의 구조와 주소를 구성하는 열이 무엇인지 미리 알고 있어야 합니다. - KML에서 사용할 주소 지오코딩에 설명된 지오코딩_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>
를 사용하여 지도와 어스 모두에서 작동하도록 수정할 수 있습니다.
또한 이 코드 샘플을 XML을 지원하는 다른 프로그래밍 언어로 쉽게 변환할 수 있습니다.
모든 CSV 파일을 KML로 변환했으므로 PHP 및 MySQL을 사용하여 KML 만들기 및 ExtendedData에 관한 Google 개발자 가이드 문서(커스텀 데이터 추가)와 같은 다른 KML 문서를 확인하는 것이 좋습니다.