よちよちpython

独習 python/Qpython/Pydroid3/termux/Linux

【folium】コマンドライン引数からブログ貼り付け用地図データを一発で出力するPythonプログラム

🎍明けましておめでとうございます。🐂🎍
今年もどうぞよろしくお願いいたします。

新年最初の投稿、今回は
コマンドライン引数で渡した地名から地図作成し、それのブログ貼り付け用htmlを出力するプログラム
を作ります。

今まで何度かfoliumでの地図作成やそのブログ貼り付け用プログラムについて投稿しておりますが、JupyterNotebookを開く必要があり面倒でした。

今回の改良は、ターミナルだけでそれが出来る。かなり便利なものになりました(自画自賛



目次




実行環境


  • Androidスマホ
  • termux(スマホのターミナルアプリ)
  • Python3.9
  • 使用ライブラリ
    • 標準ライブラリ(インストール不要)
    • 外部ライブラリ(別途インストール)
      • requests(座標取得用)
      • BeautifulSoup(座標取得用)
      • tqdm(座標取得時の進捗状況表示用)
      • folium(地図作成用)


コードの作成と実行確認はAndroidスマホで行いましたが、Windows等のPCでも動くと思います。



手順説明


仕様や使用上の手順は以下の通りです。


(入力) : 地名・住所

(出力) : 貼り付け用html

  1. ターミナルから、地名や住所コマンドライン引数で渡す(複数可

  2. 受け取ったコマンドライン引数から、地名・住所の座標geocoding.jpAPIで取得

  3. 取得した座標foliumに渡して地図を作成し、貼り付け用htmlを出力



実装


説明抜きで。

# ライブラリのインポート
import requests
from bs4 import BeautifulSoup
import time
from tqdm import tqdm
import folium
import sys

##############################
#座標取得関数
##############################
def get_lat_lon_from_address(address_l):
    url = 'http://www.geocoding.jp/api/'

    latlons = []
    # 座標取得とその進捗
    for address in tqdm(address_l):
        payload = {'v': 1.1, 'q': address}
        r = requests.get(url, params=payload)
        ret = BeautifulSoup(r.content,'lxml')

        if ret.find('error'):
            raise ValueError(f"Invalid address submitted. {address})")
        else:
            lat = ret.find('lat').string
            lon = ret.find('lng').string
            latlons.append([lat,lon])
            time.sleep(2)
    return latlons




##############################
# 地図作成関数
##############################
def make_map(latlong_list):
    ## 地図の中心座標 ##
    # 最初の座標
    latlng_1 =  latlng_list[0]
    # 最初の地名
    name_1 = address_list[0]

    # マップ作成
    map = folium.Map(latlng_1, zoom_start=zoom)
    # ピンを差す
    for name,location in zip(address_list, latlng_list):
        folium.Marker(location=location, popup=name).add_to(map)

    print(map._repr_html_())




##############################
# 実行
##############################
if __name__ == '__main__':
    # 取得したい座標の地名や住所
    address_list = sys.argv[1:] #コマンドライン引数
    # ズーム設定
    zoom=10

    # 座標取得
    latlng_list = get_lat_lon_from_address(address_list)

    # 地図作成
    make_map(latlng_list)



実行方法


ターミナルから動かします。
コマンドライン引数で渡す地名はスペースをあける。複数可ですが大量だと座標取得に時間が掛かるので注意。

$ python make_map_html.py 東京都庁 東京タワー 東京駅



ターミナルに出力されるもの


実行すると下記がターミナルに出力されます。
長いですが、全部貼ります。

100%|███████████| 3/3 [00:11<00:00,  3.89s/it]
<div style="width:100%;"><div style="position:relative;width:100%;height:0;padding-bottom:60%;"><span style="color:#565656">Make this Notebook Trusted to load map: File -> Trust Notebook</span><iframe src="about:blank" style="position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;" data-html=%3C%21DOCTYPE%20html%3E%0A%3Chead%3E%20%20%20%20%0A%20%20%20%20%3Cmeta%20http-equiv%3D%22content-type%22%20content%3D%22text/html%3B%20charset%3DUTF-8%22%20/%3E%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%3Cscript%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20L_NO_TOUCH%20%3D%20false%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20L_DISABLE_3D%20%3D%20false%3B%0A%20%20%20%20%20%20%20%20%3C/script%3E%0A%20%20%20%20%0A%20%20%20%20%3Cscript%20src%3D%22https%3A//cdn.jsdelivr.net/npm/leaflet%401.6.0/dist/leaflet.js%22%3E%3C/script%3E%0A%20%20%20%20%3Cscript%20src%3D%22https%3A//code.jquery.com/jquery-1.12.4.min.js%22%3E%3C/script%3E%0A%20%20%20%20%3Cscript%20src%3D%22https%3A//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js%22%3E%3C/script%3E%0A%20%20%20%20%3Cscript%20src%3D%22https%3A//cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.js%22%3E%3C/script%3E%0A%20%20%20%20%3Clink%20rel%3D%22stylesheet%22%20href%3D%22https%3A//cdn.jsdelivr.net/npm/leaflet%401.6.0/dist/leaflet.css%22/%3E%0A%20%20%20%20%3Clink%20rel%3D%22stylesheet%22%20href%3D%22https%3A//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css%22/%3E%0A%20%20%20%20%3Clink%20rel%3D%22stylesheet%22%20href%3D%22https%3A//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css%22/%3E%0A%20%20%20%20%3Clink%20rel%3D%22stylesheet%22%20href%3D%22https%3A//maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css%22/%3E%0A%20%20%20%20%3Clink%20rel%3D%22stylesheet%22%20href%3D%22https%3A//cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css%22/%3E%0A%20%20%20%20%3Clink%20rel%3D%22stylesheet%22%20href%3D%22https%3A//rawcdn.githack.com/python-visualization/folium/master/folium/templates/leaflet.awesome.rotate.css%22/%3E%0A%20%20%20%20%3Cstyle%3Ehtml%2C%20body%20%7Bwidth%3A%20100%25%3Bheight%3A%20100%25%3Bmargin%3A%200%3Bpadding%3A%200%3B%7D%3C/style%3E%0A%20%20%20%20%3Cstyle%3E%23map%20%7Bposition%3Aabsolute%3Btop%3A0%3Bbottom%3A0%3Bright%3A0%3Bleft%3A0%3B%7D%3C/style%3E%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cmeta%20name%3D%22viewport%22%20content%3D%22width%3Ddevice-width%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20initial-scale%3D1.0%2C%20maximum-scale%3D1.0%2C%20user-scalable%3Dno%22%20/%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cstyle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23map_df18df21365f4a469ad2345ae245859b%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20position%3A%20relative%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20width%3A%20100.0%25%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20height%3A%20100.0%25%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20left%3A%200.0%25%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20top%3A%200.0%25%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C/style%3E%0A%20%20%20%20%20%20%20%20%0A%3C/head%3E%0A%3Cbody%3E%20%20%20%20%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22folium-map%22%20id%3D%22map_df18df21365f4a469ad2345ae245859b%22%20%3E%3C/div%3E%0A%20%20%20%20%20%20%20%20%0A%3C/body%3E%0A%3Cscript%3E%20%20%20%20%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20map_df18df21365f4a469ad2345ae245859b%20%3D%20L.map%28%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22map_df18df21365f4a469ad2345ae245859b%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20center%3A%20%5B35.689634%2C%20139.692101%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20crs%3A%20L.CRS.EPSG3857%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20zoom%3A%2010%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20zoomControl%3A%20true%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20preferCanvas%3A%20false%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%29%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20tile_layer_fd0924c5c0514c0992a5aaefa4a9d0ad%20%3D%20L.tileLayer%28%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22https%3A//%7Bs%7D.tile.openstreetmap.org/%7Bz%7D/%7Bx%7D/%7By%7D.png%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%22attribution%22%3A%20%22Data%20by%20%5Cu0026copy%3B%20%5Cu003ca%20href%3D%5C%22http%3A//openstreetmap.org%5C%22%5Cu003eOpenStreetMap%5Cu003c/a%5Cu003e%2C%20under%20%5Cu003ca%20href%3D%5C%22http%3A//www.openstreetmap.org/copyright%5C%22%5Cu003eODbL%5Cu003c/a%5Cu003e.%22%2C%20%22detectRetina%22%3A%20false%2C%20%22maxNativeZoom%22%3A%2018%2C%20%22maxZoom%22%3A%2018%2C%20%22minZoom%22%3A%200%2C%20%22noWrap%22%3A%20false%2C%20%22opacity%22%3A%201%2C%20%22subdomains%22%3A%20%22abc%22%2C%20%22tms%22%3A%20false%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%29.addTo%28map_df18df21365f4a469ad2345ae245859b%29%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20marker_a07e46ddf86b40c2af118233544e6df6%20%3D%20L.marker%28%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B35.689634%2C%20139.692101%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%29.addTo%28map_df18df21365f4a469ad2345ae245859b%29%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20var%20popup_c7090eca961a406ab868085c87c2b20e%20%3D%20L.popup%28%7B%22maxWidth%22%3A%20%22100%25%22%7D%29%3B%0A%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20html_e876993ae2f84f0cab6e0b8b44a051d1%20%3D%20%24%28%60%3Cdiv%20id%3D%22html_e876993ae2f84f0cab6e0b8b44a051d1%22%20style%3D%22width%3A%20100.0%25%3B%20height%3A%20100.0%25%3B%22%3E%E6%9D%B1%E4%BA%AC%E9%83%BD%E5%BA%81%3C/div%3E%60%29%5B0%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20popup_c7090eca961a406ab868085c87c2b20e.setContent%28html_e876993ae2f84f0cab6e0b8b44a051d1%29%3B%0A%20%20%20%20%20%20%20%20%0A%0A%20%20%20%20%20%20%20%20marker_a07e46ddf86b40c2af118233544e6df6.bindPopup%28popup_c7090eca961a406ab868085c87c2b20e%29%0A%20%20%20%20%20%20%20%20%3B%0A%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20marker_65d477c1a77e497ca53e6e6682961cd5%20%3D%20L.marker%28%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B35.658581%2C%20139.745433%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%29.addTo%28map_df18df21365f4a469ad2345ae245859b%29%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20var%20popup_867359a088614e528a5ec27e7c1a4ce7%20%3D%20L.popup%28%7B%22maxWidth%22%3A%20%22100%25%22%7D%29%3B%0A%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20html_c78bcbec7680402eb923b12c9e50c7b1%20%3D%20%24%28%60%3Cdiv%20id%3D%22html_c78bcbec7680402eb923b12c9e50c7b1%22%20style%3D%22width%3A%20100.0%25%3B%20height%3A%20100.0%25%3B%22%3E%E6%9D%B1%E4%BA%AC%E3%82%BF%E3%83%AF%E3%83%BC%3C/div%3E%60%29%5B0%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20popup_867359a088614e528a5ec27e7c1a4ce7.setContent%28html_c78bcbec7680402eb923b12c9e50c7b1%29%3B%0A%20%20%20%20%20%20%20%20%0A%0A%20%20%20%20%20%20%20%20marker_65d477c1a77e497ca53e6e6682961cd5.bindPopup%28popup_867359a088614e528a5ec27e7c1a4ce7%29%0A%20%20%20%20%20%20%20%20%3B%0A%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20marker_95c657e0c3fd49f0b2c8f5e93a90d284%20%3D%20L.marker%28%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B35.681236%2C%20139.767125%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%29.addTo%28map_df18df21365f4a469ad2345ae245859b%29%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20var%20popup_ea44fc319a1f44a8b891f116c61e274a%20%3D%20L.popup%28%7B%22maxWidth%22%3A%20%22100%25%22%7D%29%3B%0A%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20html_315fd09e5e594eca9c25f7cb3a39d75d%20%3D%20%24%28%60%3Cdiv%20id%3D%22html_315fd09e5e594eca9c25f7cb3a39d75d%22%20style%3D%22width%3A%20100.0%25%3B%20height%3A%20100.0%25%3B%22%3E%E6%9D%B1%E4%BA%AC%E9%A7%85%3C/div%3E%60%29%5B0%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20popup_ea44fc319a1f44a8b891f116c61e274a.setContent%28html_315fd09e5e594eca9c25f7cb3a39d75d%29%3B%0A%20%20%20%20%20%20%20%20%0A%0A%20%20%20%20%20%20%20%20marker_95c657e0c3fd49f0b2c8f5e93a90d284.bindPopup%28popup_ea44fc319a1f44a8b891f116c61e274a%29%0A%20%20%20%20%20%20%20%20%3B%0A%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%0A%3C/script%3E onload="this.contentDocument.open();this.contentDocument.write(    decodeURIComponent(this.getAttribute('data-html')));this.contentDocument.close();" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>



ブログ編集画面にコピペ


上で出力された「<div style なんとかかんとか </div></div>」を全部コピーして、ブログ編集画面に貼り付ければ地図が表示されます。

コピーする手間を省く


↑の長いhtmlをコピーするのが面倒ですので、実行コマンドを工夫してその手間を省きます。
出力がクリップボードにセットされ、コピーする手間を省くことができます。



AndroidのTermuxの場合

$ python make_map_html.py 東京都庁 東京タワー 東京駅 | termux-clipboard-set



Windowsコマンドプロンプトの場合

$ python make_map_html.py 東京都庁 東京タワー 東京駅 | clip

詳しいことやPowerShellの場合の説明はコチラをリンクしておきます。



macOSの場合

$ python3 make_map_html.py 東京都庁 東京タワー 東京駅 | pbcopy

解説ページをリンクしておきます。



地図をブログに貼り付け


実行でパイプ|を使った場合は、既にクリップボードにコピーされていますので、後はブログ編集画面を開いて「貼り付け」るだけです。

貼り付けると↓のような地図が表示される

Make this Notebook Trusted to load map: File -> Trust Notebook



おわりに


地図のズームは、コード(make_map_html.py)の中程「実行」部分に「ズーム設定 zoom=10」としています。この数値を大きくすればズームインして近づき、小さくすればズームアウトして全体的な地図ができます。
「zoom」もコマンドライン引数で渡せるようにすれば尚よし。

マーカーやタイルの種類が選べるように改良してもよし。



以上です。