![見出し画像](https://assets.st-note.com/production/uploads/images/34104979/rectangle_large_type_2_ca96eab0d57f343eadde60be504a17af.jpg?width=1200)
Google マイマップに登録した場所を、 KMLファイル経由でワークシートに取り込むプログラム、Python 編
少し前に LibreOffice を使って KML ファイルをワークシートに取り込むことを記事にしたが、Python でもやってみた。
Python では、 KML ファイルから情報を抽出して、csv ファイルにするところまでを処理。
何をするスクリプトか
Google マイマップに登録した場所のデータを 手作業で KML ファイルにエクスポートしたら、そのファイルから場所の名前と緯度経度を読み取って csv ファイルに保存する。
Google マイマップからエクスポートした KML ファイルのフォーマットは、ざっとこんな感じ。
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>自然観察園地番杭</name>
<Style id="icon-1899-0288D1-normal">
・
・
・
<Placemark>
<name>E30</name>
<styleUrl>#icon-1899-0288D1-nodesc</styleUrl>
<Point>
<coordinates>
139.2942621,35.4413589,0
</coordinates>
</Point>
</Placemark>
・
・
・
</Document>
</kml>
Placemark が登録した場所の数だけある。各 Placemark から name と coordinates を抽出する。
Script 1
自分のレベルに合わせてあまり無理しないで作ったもの。
#-*- coding: UTF-8 -*-
# KML ファイルから名前と緯度経度を読み取る。
import re
import csv
import glob
# タグで囲まれた箇所を抽出する正規表現
pattern_p = re.compile('<Placemark>([\s\S]*?)</Placemark>')
pattern_n = re.compile('<name>([\s\S]*?)</name>')
pattern_c = re.compile('<coordinates>[\s\t\n]*(\d+\.\d+),(\d+\.\d+),\d+[\s\S]*</coordinates>')
# 同じフォルダーにある KML ファイルを処理する
# ただし最初にみつかった KML ファイルだけ
files = glob.glob('./*.kml')
fname = files[0]
with open(fname, 'r', encoding="utf-8") as myfile:
s = myfile.read()
# Placemark タグで囲まれた箇所を全て抽出
Placemarks = pattern_p.findall(s)
# name と coordinates を書き出す
with open('./Coordinates.csv', 'w') as csvfile:
writer = csv.writer(csvfile)
# 個々の Placemark から、name と coordinates を抽出する。
for Placemark in Placemarks:
# 名前を抽出
mName = pattern_n.search(Placemark)
MyName = mName.group(1)
# 緯度経度を抽出
mLocation = pattern_c.search(Placemark)
MyLocation = mLocation.group(2) + ',' + mLocation.group(1)
# データを書き出す、1行分
writer.writerow([MyName, MyLocation])
print(csvfile.read)
この緯度経度を抽出するための正規表現は、マイナスの符号を考慮していない。
※ マイナスの緯度は南半球、マイナスの経度は西周りのエリア。
Script 2
Python の場合、色々と便利なやり方が使えるので、かなり背伸びして作ってみたもの。
・KML ファイルを読み込んで、1回の検索で、必要なすべてのデータを抽出する。finditer()
・正規表現は、より詳細を記述した。
・抽出する要素は、名前付きのグループを定義した。
'name', 'latitude', 'longitude'
・改行をまたいでマッチさせる re.DOTALL
・全データのリストを作ってから、最後に csv ファイルに書き出すようにした。
# -*- coding: UTF-8 -*-
# KML ファイルから名前と緯度経度を読み取る。
# finditerを使い、一度の検索実行で、全文からすべての name と coordinates を抽出
# KML ファイルには、name が先、coordinates はそれよりも後に現れることを期待する
import re
import csv
import glob
# タグで囲まれた箇所を抽出する正規表現パターン
pattern_p = re.compile('<Placemark>.*?' # Placemark 開始タグとすべての文字、最短一致で
'<name>(?P<name>.*?)</name>' # name タグで囲まれた部分、最短一致、名前付きでグループ化
'.*?' # すべての文字、最短一致で
'<coordinates>\s*?' # coordinates 開始タグと空白文字(改行を拾うことを狙う)最短一致で
'(?P<longitude>-?(\d*\.)?\d+),' # 経度の値とコンマ、浮動小数点数、名前付きでグループ化
'(?P<latitude>-?(\d*\.)?\d+),' # 緯度の値とコンマ、浮動小数点数、名前付きでグループ化
'-?(\d*\.)?\d+' # 高度の値、浮動小数点数
'\s*?</coordinates>' # すべての文字最短一致からの coordinates 終了タグ
'.*?</Placemark>', re.DOTALL | re.VERBOSE) # すべての文字最短一致からの Placemark 終了タグ
# re.DOTALL で、'.' 特殊文字を、改行を含むあらゆる文字にマッチさせる。re.S としても同じ。
# これにより、改行を含んでマッチさせるパターンを考えなくて済む。
# re.VERBOSE は RE.X に同じ。コメントを書くため。
# 同じフォルダーにある KML ファイルを処理する
# ただし最初にみつかった KML ファイルだけ
files = glob.glob('./*.kml')
fname = files[0]
# KML ファイルを開き、読み込む
with open(fname, 'r', encoding="utf-8") as myfile:
kml_text = myfile.read()
# Placemark タグで囲まれた箇所を全て抽出
Placemarks = pattern_p.finditer(kml_text)
# 空のリストを用意する
MyList = []
# Placemark の集合から、Placemark を1つずつ処理する。
for Placemark in Placemarks:
# 名前
MyName = Placemark.group('name')
# 緯度経度のデータを作る
MyLocation = Placemark.group('latitude') + ',' + Placemark.group('longitude')
# "名前"、"緯度,経度" をリストに追加
MyList.append([MyName, MyLocation])
# データを全部書き出す
with open('./Coordinates.csv', 'w') as csvfile:
writer = csv.writer(csvfile)
writer.writerows(MyList)
print(csvfile.read)
最後に
正規表現を使わない方法もあるが、これは正規表現を学ぶことを目的として作ったものだ。
Python は、楽。LibreOffice Basic は面倒臭い。
以前投稿した Python Script の中で、close() と書いて csv ファイルを閉じていたが、この with ステートメントを使った書き方の場合、ファイルを close() する必要はないのだった。
t.koba