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 のインストール(Windows上)

注: 既にPython(バージョン3.12を推奨)がインストール済みの場合は、この手順は不要である。

winget(Windowsパッケージマネージャー)を使用してインストールを行う。winget は Windows 10/11 に標準で搭載されているパッケージ管理ツールである。

  1. Windowsで、管理者権限コマンドプロンプトを起動する(手順: Windowsキーまたはスタートメニュー > cmd と入力 > 右クリック > 「管理者として実行」)。
  2. winget が利用可能か確認する:
    winget --version
    
    winget --version コマンドの実行結果
  3. Pythonをインストールする(以下のコマンドで Python 3.12 がインストールされる)。
    REM Python 3.12 をシステム領域にインストール
    winget install --scope machine --id Python.Python.3.12 -e --silent --accept-source-agreements --accept-package-agreements
    
    REM パス長制限の解除
    reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled /t REG_DWORD /d 1 /f
    reg query "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled
    
    REM Python のパス設定
    set "PYTHON_PATH=C:\Program Files\Python312"
    set "PYTHON_SCRIPTS_PATH=C:\Program Files\Python312\Scripts"
    if exist "%PYTHON_PATH%" setx PYTHON_PATH "%PYTHON_PATH%" /M >nul
    if exist "%PYTHON_SCRIPTS_PATH%" setx PYTHON_SCRIPTS_PATH "%PYTHON_SCRIPTS_PATH%" /M >nul
    for /f "skip=2 tokens=2*" %a in ('reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v Path') do set "SYSTEM_PATH=%b"
    echo "%SYSTEM_PATH%" | find /i "%PYTHON_PATH%" >nul
    if errorlevel 1 setx PATH "%PYTHON_PATH%;%PYTHON_SCRIPTS_PATH%;%SYSTEM_PATH%" /M >nul
    

【関連する外部サイト】

【サイト内の関連ページ】

Visual Studio 2022 Build Tools とランタイムのインストール

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

管理者権限でコマンドプロンプトを起動し(手順: Windowsキーまたはスタートメニュー > cmd と入力 > 右クリック > 「管理者として実行」)、以下を実行する。--scope machine オプションはシステム全体へのインストールを指定するもので、管理者権限が必要となる。

REM Visual Studio 2022 Build Toolsとランタイムをシステム領域にインストール
winget install --scope machine --wait --accept-source-agreements --accept-package-agreements Microsoft.VisualStudio.2022.BuildTools Microsoft.VCRedist.2015+.x64

REM インストーラー、セットアッププログラム、インストールパス
set "VS_INSTALLER=C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installer.exe"
set "VS_SETUP=C:\Program Files (x86)\Microsoft Visual Studio\Installer\setup.exe"
set "VS_PATH=C:\Program Files\Microsoft Visual Studio\2022\BuildTools"

REM C++開発ワークロードのインストール
"%VS_SETUP%" modify --installPath "%VS_PATH%" --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended --quiet --norestart
"%VS_SETUP%" modify --installPath "%VS_PATH%" --add Microsoft.VisualStudio.Component.VC.Llvm.Clang --includeRecommended --quiet --norestart
"%VS_SETUP%" modify --installPath "%VS_PATH%" --add Microsoft.VisualStudio.ComponentGroup.ClangCL --includeRecommended --quiet --norestart
"%VS_SETUP%" modify --installPath "%VS_PATH%" --add Microsoft.VisualStudio.Component.VC.CMake.Project --includeRecommended --quiet --norestart
"%VS_SETUP%" modify --installPath "%VS_PATH%" --add Microsoft.VisualStudio.Component.Windows11SDK.22621 --includeRecommended --quiet --norestart

必要な 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 などのライブラリを使用して、地図上への可視化や空間分析に活用できる。