[Python應用]Google Maps多天時間軸的合併

Richardhess
8 min readMay 11, 2021

--

前言

今天要示範的是將Google Maps上多天的時間軸合併成一份完整的地圖。

相信幾乎每個人的手機裡都有安裝Google Maps,當手機定位打開時Google Maps便會記下手機當天移動的路徑。有些人基於個資與安全問題會將該功能關掉,我個人反而很喜歡這個功能,因為可以很方便地直接看到以前去過的地方。舉例來說,我曾經吃過一家很好吃的餐廳但不記得在哪裡了,只知道餐廳在新竹的某個地方。透過Google Maps "你的時間軸" 功能,能夠以整個過去時間的方式來檢視全世界我曾到訪的地方,用此方法查看新竹縣市後很快地便找到了餐廳。又或是旅行後,可以透過時間軸細細回味曾經去過的地方也是一件很有趣的事情。

這次要示範的例子是將我去冰島環島12天的路徑合併成一張完整的圖。

目的

在時間軸中開啟環島日期的地圖並將它們全部下載下來(KML檔),將這些KML檔合併成一份並上傳到Google Maps,在Google Maps中顯示12天環島的全部路徑。

需要將地圖一次合併的原因是,Google Maps一次只允許上傳一個KML檔,意味著12天環島的地圖必須分12次上傳,非常不人性化也耗費時間(每上傳一張地圖都要跑一下),透過以下方法將多天的地圖合併後只需上傳一次。

事前準備

在Google Maps中從"選單"點選"你的時間軸",調整想要的日期。在這裡可以編輯你的地圖,例如將行經的路線改成對齊道路,或是修正經過的地點。完成後畫面右下角有個齒輪的圖標,點選"將這天的資料匯出為KML"並儲存在適當的資料夾。重複以上步驟直到選完全部的日期。

點選右下角的齒輪圖標並匯出KML檔

程式碼

1. 觀察KML檔

首先觀察KML檔裡面寫了什麼以及編排的規則,才能從中取出需要的部分。可以用文字文件或其他軟體開啟,這邊為了方便閱讀我們用Notepad++,開啟後應會看到一堆標籤和經緯度,我們擷取部分的畫面查看。

KML檔內的內容(將部份個資覆蓋)

將KML檔仔細閱讀後會發現,其實編寫規則很簡單。第一部分是開頭,包含檔案的設定以及個人帳戶的資訊;第二部分是內容,記錄了停留的點以及移動的路徑;第三部分是結尾,表示這份檔案已經結束。以下將KML檔內容視覺化。

KML檔內容簡介

由於開頭和結尾不影響內容,我們要做的是找出表示內容的標籤。經觀察後找到,能在地圖標示出地點的標籤是"<Placemark>"。在"<Placemark>"裡面還包含了許多資訊如:"<name>"、"<address>"、"<coordinates>"等標籤。我們將其中一份地圖KML檔上傳到Google Maps並觀察。

以上的資訊在"<ExtendedData>"標籤裡面

現在知道了目標是"<Placemark>",我們只要利用Python將每份KML檔裡的該標籤內容提取出來,便可完成地圖的合併。

2. 讀取並寫下KML檔

這裡我們使用到兩種引用:fastkml和os,fastkml需要先在Anaconda安裝。

pip install fastkml

由於需要開啟多個KML檔且檔名未知,我們需要直接開啟整個資料夾內的KML檔,所以使用os的listdir()。路徑path為存放KML檔的資料夾路徑,因個資的關係將Users後以星號碼掉。

from fastkml import kml
import os
path = 'C:/Users/***/PyML/google map/data map'
#換成自己的資料夾路徑
dirs = os.listdir(path)
k = open("output.kml", "w", encoding="utf-8")
#將輸出的kml檔命名為output.kml

3. 抓取標籤內容

方法很簡單,使用find()的功能尋找Placemark的第一個位置,rfind()尋找最後一個位置,將兩個位置中間的文字全部寫在上面開的output.kml檔裡。同時,如果是第一份檔案,我們需要將他的開頭也存下來。開頭的最後一個標籤是"<style>",同樣的使用rfind()功能去尋找。

由於找到Placemark位置後記錄的是"P"的位置,必須做調整才能完整包覆到整的"<Placemark>","<style>"也是一樣的處理方式。這裡使用一個函式去處理以上的工作。

def fileCombine(i):

#儲存placemark的起末位置
placemark = []
with open('data map/'+dirs[i], 'r', encoding="utf-8") as myfile:
f = myfile.read()
placemark.append(f.find('Placemark'))
placemark.append(f.rfind('Placemark'))

#若為第一個檔案,儲存開頭並寫入
if i == 0:
k.write(f[0:f.rfind('Style')+6])

#寫入Placemark裡的內容
k.write(f[placemark[0]-1 : placemark[1]+10])

4. 丟進迴圈並完成檔案

將寫好的函式丟進迴圈跑就可以了。最後再加上結尾並關閉k,便可在資料夾中找到彙整好的KML檔。

for i in range(len(dirs)):
fileCombine(i)
k.write("</Document></kml>")
k.close()

5. 完整程式碼

from fastkml import kml
import os
path = 'C:/Users/***/PyML/google map/data map'
dirs = os.listdir(path)
k = open("output.kml", "w", encoding="utf-8")def fileCombine(i):

placemark = []
with open('data map/'+dirs[i], 'r', encoding="utf-8") as myfile:
f = myfile.read()
placemark.append(f.find('Placemark'))
placemark.append(f.rfind('Placemark'))

if i == 0:
k.write(f[0:f.rfind('Style')+6])

k.write(f[placemark[0]-1 : placemark[1]+10])
for i in range(len(dirs)):
fileCombine(i)
k.write("</Document></kml>")
k.close()

結果

將輸出的KML檔上傳到Google Maps。在"選單"中點選"你的地點",選取最右邊的"地圖",最底下選取"建立地圖"。在左上的欄位"未命名的圖層"中點選"匯入",將剛剛輸出的KML檔上傳。合併後的地圖仍然可以新增標點,在搜尋欄的下方有一排的功能表可以使用。成果如下,成功得到完整12天的冰島環島路線圖。

輸出後的合併地圖

透過地圖合併顯示完整路徑,可以更清楚的向別人展現自己旅遊的經歷,也很適合拿來做簡報或寫旅遊日誌。我很喜歡旅行,可以在旅途結束後將自己的足跡展現出來向朋友分享是一件很開心的事,透過這次整理旅遊日誌來練習Python以及對Google Maps的應用。

希望這次的教學可以幫助到有需要的人,我室友看到後已經決定要用走路的方式在地圖上"畫畫"了,大家不妨實驗看看自己過去一周甚至一個月所移動的路徑究竟長什麼樣子,祝玩得愉快!

討論

既然我們已經了解KML檔的內容了,為什麼不直接在檔案內做更多的修改?

第一個原因是其實我還沒想到可以做什麼額外的應用,因此這次只做單純的合併。關於Placemark的部分可以透過編改KML檔讓他換樣式及顏色,也可以針對ExtendedData內的文字去做修改,不過並沒有特別的目的這麼做便不在文章內介紹了。

第二個原因是不需要大量重複的動作的話不太需要用程式去跑。拿到一張完整天數的地圖,我會想要一個個點進去慢慢整理做了什麼事情、拍了哪張照片,有些地方可能會額外加上標記;這些事情用Google Maps的介面就很方便了,便不直接在KML檔裡做變動。

--

--