1. 程式人生 > >Python解析和生成用於Google Earth的KML格式檔案,解決Python3匯入pyKML錯誤

Python解析和生成用於Google Earth的KML格式檔案,解決Python3匯入pyKML錯誤

0 格式介紹

Google Earth生成的檔案格式是KML/KMZ,這裡介紹如何解析和生成KML格式檔案,KMZ格式可以在Google Earth中另存為KML格式。

更詳細的瞭解KML可以檢視Google 官方教程。KML用於Google Earth和Google Map中顯示地理資料,使用包含巢狀的元素和屬性的結構(基於標記),符合 XML 標準。KML基本格式:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
    <Placemark>
<name>Simple placemark</name> <description>Not a real place.</description> <LineString> <coordinates> 120.315681310226,39.95885231106518,0 120.3157179045997,39.9586874087592,0 </coordinates
>
<coordinates> 120.3158141778864,39.95791322572761,0 120.3158808732796,39.95791590956513,0 </coordinates> </LineString> </Placemark> </kml>

上述檔案的解釋:

  • XML 標頭。
  • KML 名稱空間宣告。
  • 地標物件元素。
    • 用作地標標籤的名稱。
    • 地標的描述。
    • 該地標有兩條路徑,以及描述路徑的經度、緯度和高度(可以省略)。

1 Python庫pyKML

pyKML用於生成、解析和驗證KML檔案。

1.1 安裝

Linux下使用conda:
$ conda install -c conda-forge pykml
使用pip:
$ pip install pykml

1.2 問題

1.2.1 parser模組

如果是Python 3.x,pyKML在匯入parser的時候會出現以下問題,沒有模組urllib2 。

In [1]: from pykml import parser
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-1-386e0923aa06> in <module>()
----> 1 from pykml import parser

~/miniconda3/lib/python3.6/site-packages/pykml/parser.py in <module>()
      6 import sys
      7 import os
----> 8 import urllib2

ModuleNotFoundError: No module named 'urllib2'

原因是Python 2.x的urllib 和urllib2 模組在Python 3.x中被合併在了urlllib中。這裡使用url是為了驗證KML檔案的有效性。

開啟檔案~/miniconda3/lib/python3.6/site-packages/pykml/parser.py 替換第8行為from urllib.request import urlopen。再次嘗試匯入,提示缺少庫檔案libiconv.so.2

In [2]: from pykml import parser
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-1-386e0923aa06> in <module>()
----> 1 from pykml import parser

~/miniconda3/lib/python3.6/site-packages/pykml/parser.py in <module>()
      7 import os
      8 from urllib.request import urlopen
----> 9 from lxml import etree, objectify

ImportError: libiconv.so.2: cannot open shared object file: No such file or directory

安裝庫$ conda install -c conda-forge libiconv,匯入成功!或者嘗試按照lxml官方教程安裝lxml模組。

1.2.2 factory模組

factory.py模組的print語句改成python3.x風格,kml2pykml()方法最後一行改為:

print(write_python_script_for_kml_document(doc))

1.3 解析檔案

解析KML格式的字串:

In [1]: from pykml import parser
In [2]: kml_str = '<kml xmlns="http://www.opengis.net/kml/2.2">' \ # 定義kml格式的字元
  ....:              '<Document>' \
  ....:                '<Folder>' \
  ....:                  '<name>sample folder</name>' \
  ....:                '</Folder>' \
  ....:              '</Document>' \
  ....:            '</kml>'
In [9]: root = parser.fromstring(kml_str)
In [10]: print(root.Document.Folder.name.text)
sample folder

解析格式介紹中的KML檔案,Placemark標籤下有兩條路徑,從檔案中獲取兩條路徑中所有點的座標:

In [11]: with open(KML_FILE, 'r') as f:
In [12]: kml = parser.parse(f).getroot()
In [13]: for each in kml.Placemark: # 遍歷所有的Placemark
In [14]:      print(each.LineString.coordinates)

或者使用 findall( ) 查詢所有的Placemark1

In [15]: placemarks = kml.findall('.//{http://www.opengis.net/kml/2.2}Placemark')
In [16]: for each in placemarks:
In [17]:     print(each.LineString.coordinates)

1.4 生成和驗證

生成和驗證KML檔案可參考pyKML官方教程