Python の overpass を用いて OpenStreetMap のデータをダウンロード

【概要】Python の overpass パッケージを使用して、OpenStreetMap から地図データをダウンロードする方法を解説する。Google Map で緯度経度を調べ、Overpass API を通じてポイントやラインのデータを取得し、GeoJSON 形式で処理する手順を示す。

【目次】

  1. 前準備
  2. Google Map を用いて緯度経度を調べる
  3. Python を用いて OpenStreetMap のデータをダウンロード
OpenStreetMap (https://www.openstreetmap.org)は、世界規模で利用可能な無料のオンライン地図データベースである。道路、建物、河川などの地理情報がオープンデータとして提供されており、地図アプリケーションの開発、経路探索、地理情報の分析などに活用できる。

Python の overpass パッケージは、OpenStreetMap の Overpass API を Python から利用するラッパーライブラリである。Overpass API は、OpenStreetMap のデータベースから条件を指定してデータを抽出するための問い合わせインターフェースである。

前提知識: 本記事は、Python の基本的な操作(変数、リスト、辞書、for文など)を理解していることを前提とする。

注意事項: Overpass API には利用制限がある。短時間に大量のリクエストを送信すると、一時的にアクセスが制限される場合がある。また、OpenStreetMap のデータは Open Database License (ODbL) の下で提供されており、利用時にはライセンス条件に従う必要がある。

前準備

本記事のプログラムを実行するには、以下の環境構築が必要である。

Python 3.12 のインストール(Windows 上) [クリックして展開]

以下のいずれかの方法で Python 3.12 をインストールする。Python がインストール済みの場合、この手順は不要である。

方法1:winget によるインストール

管理者権限コマンドプロンプトで以下を実行する。管理者権限のコマンドプロンプトを起動するには、Windows キーまたはスタートメニューから「cmd」と入力し、表示された「コマンドプロンプト」を右クリックして「管理者として実行」を選択する。

winget install --id Python.Python.3.12 -e --scope machine --silent --accept-source-agreements --accept-package-agreements --override "/quiet InstallAllUsers=1 PrependPath=1 Include_test=0 Include_pip=1 Include_launcher=1 InstallLauncherAllUsers=1 TargetDir=\"C:\Program Files\Python312\""
powershell -Command "$p='C:\Program Files\Python312'; $s=\"$p\Scripts\"; $m=[Environment]::GetEnvironmentVariable('Path','Machine'); if($m -notlike \"*$s*\") { [Environment]::SetEnvironmentVariable('Path', \"$p;$s;$m\", 'Machine') }"

--scope machine を指定することで、システム全体(全ユーザー向け)にインストールされる。このオプションの実行には管理者権限が必要である。インストール完了後、コマンドプロンプトを再起動すると PATH が自動的に設定される。

方法2:インストーラーによるインストール

  1. Python 公式サイト(https://www.python.org/downloads/)にアクセスし、「Download Python 3.x.x」ボタンから Windows 用インストーラーをダウンロードする。
  2. ダウンロードしたインストーラーを実行する。
  3. 初期画面の下部に表示される「Add python.exe to PATH」に必ずチェックを入れてから「Customize installation」を選択する。このチェックを入れ忘れると、コマンドプロンプトから python コマンドを実行できない。
  4. 「Install Python 3.xx for all users」にチェックを入れ、「Install」をクリックする。

インストールの確認

コマンドプロンプトで以下を実行する。

python --version

バージョン番号(例:Python 3.12.x)が表示されればインストール成功である。「'python' は、内部コマンドまたは外部コマンドとして認識されていません。」と表示される場合は、インストールが正常に完了していない。

Build Tools for Visual Studio 2022 のインストール(Windows 上)

geopandas などの Python パッケージは、インストール時に C言語で記述された拡張モジュールのコンパイルが必要になる場合がある。このコンパイルには Visual Studio Build Tools が必要である。

p>以下のコマンドを管理者権限コマンドプロンプトで実行する (手順:Windowsキーまたはスタートメニュー → cmd と入力 → 右クリック → 「管理者として実行」)。

REM VC++ ランタイム
winget install --scope machine --id Microsoft.VCRedist.2015+.x64 -e --silent --disable-interactivity --force --accept-source-agreements --accept-package-agreements --override "/quiet /norestart"

REM Build Tools + Desktop development with C++(VCTools)+ 追加コンポーネント(一括)
winget install --id Microsoft.VisualStudio.2022.BuildTools --accept-source-agreements --accept-package-agreements ^
    --override "--passive --wait --norestart --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended --add Microsoft.VisualStudio.Component.VC.Llvm.Clang --add Microsoft.VisualStudio.ComponentGroup.ClangCL --add Microsoft.VisualStudio.Component.VC.CMake.Project --add Microsoft.VisualStudio.Component.Windows11SDK.26100"

--add で追加されるコンポーネント

上記のコマンドでは,まず Build Tools 本体と Visual C++ 再頒布可能パッケージをインストールし,次に setup.exe を用いて以下のコンポーネントを追加している。

インストール完了の確認

winget list Microsoft.VisualStudio.2022.BuildTools

上記以外の追加のコンポーネントが必要になった場合は Visual Studio Installer で個別にインストールできる。

必要な Python ライブラリのインストール(Windows上)

  1. Windowsで、管理者権限コマンドプロンプトを起動する(手順: Windowsキーまたはスタートメニュー > cmd と入力 > 右クリック > 「管理者として実行」)。
  2. 以下のコマンドを実行し、必要なライブラリをインストールする。
    pip install -U overpass
    pip install -U geopandas
    

Google Map を用いて緯度経度を調べる

OpenStreetMap からデータをダウンロードするには、対象地域の緯度経度の指定が必要である。ここでは Google Map を使用して座標を取得する。

  1. Google Map を開く。

    https://www.google.co.jp/maps

  2. Google Map で任意の場所に移動する。
    Google Map の画面
  3. 目的の場所で右クリックし、「この場所について」を選択する。
    Google Map で右クリックメニューを表示した画面
  4. 画面下部に緯度と経度が表示される。この値を記録しておく。
    Google Map で緯度経度が表示された画面

Python を用いて OpenStreetMap のデータをダウンロード

Python プログラムの実行

【サイト内の関連ページ】 Python のまとめ: 別ページ »

OpenStreetMap のデータ構造: OpenStreetMap のデータは、ノード(点)、ウェイ(線)、リレーション(複数要素の組み合わせ)の3種類で構成される。ノードは緯度経度を持つ点で、店舗や交差点などを表す。ウェイは複数のノードを順に結んだ線で、道路や河川などを表す。各要素には タグ(キーと値のペア)が付与され、要素の種類や属性を示す。例えば、道路には「highway=primary」(主要道路)のようなタグが付く。

  1. Python で、ダウンロードしたい地図の緯度と経度を設定する。

    以下の Python プログラムを実行する。緯度と経度には、前節で取得した値を使用する。

    MapQuery の引数は、取得範囲を示すバウンディングボックス(南端の緯度、西端の経度、北端の緯度、東端の経度)である。以下の例では、指定した座標を中心に約200m四方の範囲を取得する。

    (実行例)

    import overpass
    lat = 34.4461
    lon = 133.2315
    api = overpass.API()
    map_query = overpass.MapQuery(lat - 0.001, lon - 0.001, lat + 0.001, lon + 0.001)
    response = api.Get(map_query)
    
    Python で overpass を使用したコードの実行画面
  2. 結果である response オブジェクトを確認する。

    取得したデータは GeoJSON 形式 で返される。GeoJSON は地理情報データを表現するための JSON ベースの標準フォーマットであり、多くの GIS ツールやライブラリで利用できる。

    print(response)
    
    response オブジェクトの出力結果
  3. 取得したいデータのタイプを指定して抽出する。

    以下は、「ライン」データのうち「highway」タグを持つもの(道路データ)を抽出する例である。

    以下の Python プログラムを実行する。

    import json
    # GeoJSON データから必要な情報を抽出
    data = json.loads(response)
    # highway タグを持つラインのみを抽出
    highways = []
    for feature in data['features']:
        if feature['geometry']['type'] == 'LineString':
            if 'highway' in feature['properties']:
                highways.append(feature)
    print(f"highway タグを持つラインの数: {len(highways)}")
    # 最初の highway を表示
    if highways:
        print(highways[0])
    
  4. ライン」データの構造を確認する。

    ラインは複数のポイント(座標)で構成される。

    • ラインが線分の場合: 端点が2個
    • ラインが折れ線の場合: 端点が2個に加え、中間点が存在する

    以下の Python プログラムを実行する。

    # ラインのデータ構造を確認
    for i, highway in enumerate(highways[:3]):  # 最初の3つだけ表示
        print(f"ライン {i+1}:")
        print(f"  ID: {highway['id']}")
        print(f"  タイプ: {highway['properties'].get('highway', '不明')}")
        print(f"  名前: {highway['properties'].get('name', '名前なし')}")
        # 座標点の数を確認
        coords = highway['geometry']['coordinates']
        print(f"  ポイント数: {len(coords)}")
        print(f"  座標: {coords}")
        print()
    

    出力の各行は1個の「ライン」オブジェクトを表す。coordinates には、ラインを構成する各ポイントの座標が格納されている。

    注意: GeoJSON の座標は(経度、緯度)の順で格納される。これは一般的な(緯度、経度)の順とは逆である。

  5. ノード」データの構造を確認する。

    以下の Python プログラムを実行する。

    # ノード(ポイント)のデータを抽出
    nodes = []
    for feature in data['features']:
        if feature['geometry']['type'] == 'Point':
            nodes.append(feature)
    
    print(f"ポイントの総数: {len(nodes)}")
    # 最初の数個のノードを表示
    for i, node in enumerate(nodes[:3]):  # 最初の3つだけ表示
        print(f"ノード {i+1}:")
        print(f"  ID: {node['id']}")
        print(f"  緯度経度: {node['geometry']['coordinates']}")
        print(f"  タグ: {node['properties']}")
        print()
    

    出力の各行は1個の「ポイント」オブジェクトを表す。各ポイントは ID座標、およびタグ(属性情報)を持つ。

まとめ

本記事で取得したデータの構造は以下のとおりである。

取得したデータは geopandas などのライブラリを使用して、地図上への可視化や空間分析に活用できる。