Googleロケーション履歴のPython3＋foliumによる地図表示のサンプル

タイトル通りです．次の記事を参考にさせていただきました．

* [Googleロケーション履歴を使って整形(pandas)と地図上に表示(folium)させることを考える[初心者のPython3]](https://qiita.com/jam-goat/items/99dbdd4976544686a0ba)

参考というかほとんどパクりですが（正直），[pandas](https://pandas.pydata.org/)は使わなかったのと，次の実行例のように，年月を入力すると，履歴のある日の地図表示のHTMLファイルを半自動的に生成するようにしたことから，若干お手軽化＋ちょい機能の例として公開している次第です．
![lmap-exec-sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672267/331ea2aa-044b-280c-1d49-58e608a587ff.png)

生成されたHTMLファイルの表示例（帰省時の新幹線移動^^;）：
![kanto-loc20211017.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672267/bfa209a7-b6ec-0e65-aa2b-a03b6acc8552.png)

動作確認環境は次の通りです．

* Windows 10
* Python 3.10.0
* folium 0.12.1（pipでインストール）

# Googleロケーション履歴の取得

1. Webブラウザで自身のGoogleアカウントでログイン（下図は筆者の例）
![Qiita-Google-login.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672267/f08576c9-c95b-7f23-bd93-60b99ed9599d.png)
2. 『Googleデータエクスポート (https://takeout.google.com/) 』にアクセス
![Qiita-Google0-takeout.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672267/b6b4a97d-d987-f826-8a82-1f5b2ce52cea.png)
3. 『選択をすべて解除』で一旦全てのエクスポート対象を解除
![Qiita-Google1-uncheck.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672267/d2470489-0816-038f-1696-1967f26ff489.png)
4. 『ロケーション履歴』にチェック
![Qiita-Google2-loccheck.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672267/8fe70870-6756-1313-9ddb-cd48029e5c82.png)
5. 『次のステップ』をクリック
![Qiita-Google3-nextstep.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672267/5696d03d-ef60-17a3-b2f8-06f9c0b7f5f0.png)
6. 配信方法等を選択し，『エクスポートを作成』をクリックしてエクスポート開始
![Qiita-Google4-export.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672267/5868dff6-8f93-dc5c-bac5-bf90fa49b447.png)
7. ダウンロードした`takeout-20XXXXXXTXXXXXXZ-XXX.zip`から`Takeout`→`ロケーション履歴`の**`ロケーション履歴.json`**を抽出

# プログラムコード本体

抽出した『**`ロケーション履歴.json`**』と同じフォルダにプログラムファイルが置いてあることを前提としています．コマンドプロンプトで『`python loc-map.py`』等して実行することもできますが，プログラムファイルのダブルクリックでも使用できるかと思います．

```Python:loc-map.py
from json import load
from datetime import datetime, timezone, timedelta
from folium import Map, PolyLine
from os.path import isfile
from calendar import monthrange

# 引数にロケーション履歴本体の辞書型データ`ld`と文字列20XX-XX-XX形式の日付`ds`を指定
def loc_html(ld, ds):
    lo, la = [], []
    for x in ld:
        # 座標情報を含む指定した日付の履歴データのみ抽出
        if 'longitudeE7' in x and 'latitudeE7' in x:
            t1 = str(datetime.fromtimestamp(float(x['timestampMs'])/1000,
                                            timezone(timedelta(hours=9))))
            if t1[:t1.find(' ')] == ds:
                lo.append(float(x['longitudeE7'])/10000000)
                la.append(float(x['latitudeE7'])/10000000)
    if len(la) <= 0:
        print(ds + 'のロケーション履歴はありません')
    else:
        # 履歴データ群をfolium（Map，PolyLine）で地図上に直線で結んだHTMLファイルを保存
        m = Map(location=[la[0], lo[0]], zoom_start=20)
        for i in range(len(la)-1):
            lc = [[la[i],lo[i]], [la[i+1],lo[i+1]]]
            PolyLine(locations=lc).add_to(m)
        m.save('loc-map-' + ds + '.html')
        print('ファイルloc-map-' + ds + '.htmlに保存しました')

lfile = "ロケーション履歴.json"
if isfile(lfile):
    # モジュールjsonのメソッドloadで読み込み，位置データ構造のみ抽出
    with open(lfile) as file: ld = load(file)['locations']
else:
    print(lfile + "がありません")
    exit()

y = int(input("処理年を西暦で入力して下さい："))
m = int(input("処理月を入力して下さい："))
dn = monthrange(y, m)[1]

# 日付は"20XX-XX-XX"の形式
ms = ('' if m > 9 else '0') + str(m)
for c in range(dn):
    ds = str(y) + '-' + ms + '-' + ('' if c+1 > 9 else '0') + str(c+1)
    loc_html(ld, ds)

input("Enterキーを押すと終了します")
```

# 備考

## 記事に関する補足
* ちょい機能という割には精度はガン無視だしデータの整合性チェック（時系列の確認など）もしていないので，どちらかというと，お手軽化による参考記事の劣化版かもとか．あと，処理が遅い．洗練した方がいいかなあ．

## 更新履歴
* 2021-11-09：プログラムコードの整合性修正
* 2021-10-19：初版公開