Python の overpass を用いて OpenStreetMap のデータをダウンロード
【概要】Python の overpass パッケージを使用して、OpenStreetMap から地図データをダウンロードする方法を解説する。Google Map で緯度経度を調べ、Overpass API を通じてポイントやラインのデータを取得し、GeoJSON 形式で処理する手順を示す。
【目次】
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 に標準で搭載されているパッケージ管理ツールである。
- Windowsで、管理者権限でコマンドプロンプトを起動する(手順: Windowsキーまたはスタートメニュー >
cmdと入力 > 右クリック > 「管理者として実行」)。 - winget が利用可能か確認する:
winget --version
- 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
【関連する外部サイト】
【サイト内の関連ページ】
- Python詳細ガイド: Pythonまとめ »
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上)
- Windowsで、管理者権限でコマンドプロンプトを起動する(手順: Windowsキーまたはスタートメニュー >
cmdと入力 > 右クリック > 「管理者として実行」)。 - 以下のコマンドを実行し、必要なライブラリをインストールする。
pip install -U overpass pip install -U geopandas
Google Map を用いて緯度経度を調べる
OpenStreetMap からデータをダウンロードするには、対象地域の緯度と経度の指定が必要である。ここでは Google Map を使用して座標を取得する。
- Google Map を開く。
- Google Map で任意の場所に移動する。
- 目的の場所で右クリックし、「この場所について」を選択する。
- 画面下部に緯度と経度が表示される。この値を記録しておく。
Python を用いて OpenStreetMap のデータをダウンロード
Python プログラムの実行
- Windows では python(Python ランチャーは py)
- Ubuntu では python3
【サイト内の関連ページ】 Python のまとめ: 別ページ »
OpenStreetMap のデータ構造: OpenStreetMap のデータは、ノード(点)、ウェイ(線)、リレーション(複数要素の組み合わせ)の3種類で構成される。ノードは緯度経度を持つ点で、店舗や交差点などを表す。ウェイは複数のノードを順に結んだ線で、道路や河川などを表す。各要素には タグ(キーと値のペア)が付与され、要素の種類や属性を示す。例えば、道路には「highway=primary」(主要道路)のようなタグが付く。
- 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)
- 結果である response オブジェクトを確認する。
取得したデータは GeoJSON 形式 で返される。GeoJSON は地理情報データを表現するための JSON ベースの標準フォーマットであり、多くの GIS ツールやライブラリで利用できる。
print(response)
- 取得したいデータのタイプを指定して抽出する。
以下は、「ライン」データのうち「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]) - 「ライン」データの構造を確認する。
ラインは複数のポイント(座標)で構成される。
- ラインが線分の場合: 端点が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 の座標は(経度、緯度)の順で格納される。これは一般的な(緯度、経度)の順とは逆である。
- 「ノード」データの構造を確認する。
以下の 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、座標、およびタグ(属性情報)を持つ。
まとめ
本記事で取得したデータの構造は以下のとおりである。
- ラインデータ: 複数のポイント座標で構成され、道路や河川などの線形要素を表す
- ポイントデータ: ID、座標(経度、緯度)、およびタグ(属性情報)で構成される
取得したデータは geopandas などのライブラリを使用して、地図上への可視化や空間分析に活用できる。