はじめに
GoogleStreetViewのAPIを利用してパノラマ画像をダウンロードする際に、いい感じの記事が見つからず少し悩んだのでメモ。
ソースコードの全体像はこちら
import argparse
import requests
import google_streetview.api
from bs4 import BeautifulSoup
# デバック用パッケージ
from icecream import ic
class StreetViewRepository:
def __init__(self, api_key, size=(600, 300)):
self.api_key = api_key
self.size = str(size[0]) + "x" + str(size[1])
def _create_param(
self, location: str, pitch: int, heading: int, fov: int = 90
) -> {}:
params = [
{
"size": self.size, # max 640x640 pixels
"location": location,
"pitch": str(pitch), # 上下の角度 -90~90 (-90: 真下, 90: 真上)
"heading": str(heading), # 方位 0~360 (0:北, 90:東, 180:南, 270:西)
"fov": str(fov), # ズーム 0~120
"key": self.api_key,
}
]
return params
def get_pano_for_address(
self, address: str, pitch: int, heading: int, fov: int = 90
):
"""住所からGoogleStreetViewの画像を返すプログラム
Args:
address (str): 検索対象の住所
pitch (int): 上下方向の角度
heading (int): 水平方向の角度
fov (int): ズーム
"""
target_coodinate = self._coordinate(address)
location = str(target_coodinate[0]) + "," + str(target_coodinate[1])
ic(address, location)
params = self._create_param(location, pitch, heading)
results = google_streetview.api.results(params)
ic(results.preview())
results.download_links("downloads")
def _coordinate(self, address) -> []:
"""
addressに住所を指定すると緯度経度を返す。
>>> coordinate('東京都文京区本郷7-3-1')
['35.712056', '139.762775']
"""
URL = "http://www.geocoding.jp/api/" # Geocording Apiを利用する。
payload = {"q": address}
html = requests.get(URL, params=payload)
soup = BeautifulSoup(html.content, "html.parser")
if soup.find("error"):
raise ValueError(f"Invalid address submitted. {address}")
latitude = soup.find("lat").string
longitude = soup.find("lng").string
return [latitude, longitude]
def download_photo(
api_key: str, address: str, pitch: int = 0, heading: int = 0, fov: int = 90
):
"""住所からGoogleStreetViewの画像を保存する
Args:
api_key (str): GoogleStreetViewから取得するAPIキー
address (str): 検索対象の住所
pitch (int): 上下方向の角度
heading (int): 水平方向の角度
fov (int): ズームの割合
"""
# 初期化
sr = StreetViewRepository(api_key=api_key)
# 画像のダウンロード処理
sr.get_pano_for_address(
address=address,
pitch=pitch,
heading=heading,
fov=fov,
)
if __name__ == "__main__":
# 引数の設定
parser = argparse.ArgumentParser()
parser.add_argument("api_key", help="GoogleStreetViewから取得するAPIキー")
parser.add_argument("address", help="検索対象の住所")
parser.add_argument("--pitch", default=0, help="上下方向の角度")
parser.add_argument("--heading", default=0, help="水平方向の角度")
parser.add_argument("--fov", default=0, help="ズームの割合")
args = parser.parse_args()
download_photo(
api_key=args.api_key,
address=args.address,
pitch=args.pitch,
heading=args.heading,
fov=args.fov,
)
実行コマンドを以下に示す。${APIキー}
の箇所には、各自で取得したAPIキーを入力する。
$ python street_view_download.py ${APIキー} 東京都千代田区
ic| address: '東京都千代田区', location: '35.694031,139.753772'
[0] UdOQn3fvD27X6L7Mr48uog
===========================
date: 2020-02
location:
lat: 35.6942363
lng: 139.7538972
pano_id: UdOQn3fvD27X6L7Mr48uog
status: OK
ic| results.preview(): None
$
APIの有効化
GoogleStreetViewApiを利用する認証キーの取得方法は、以下の公式のドキュメントを参照。APIの利用にはクレジットカードの登録が必要になるので注意。
実装
google-streetview
GoogleStreetViewをPythonで利用する際には、非公式のライブラリのgoogle-streetview
を利用するのが一番簡単。
インストールは、以下のコマンドで実施する。
pip install google_streetview
指定可能なオプション
GoogleStreetViewのAPIを利用して画像をダウンロードする際に、指定可能なオプションを以下に示す。
ズームや上下の角度の調整など、かなり細かい範囲まで指定できる。
パラメータ名 | 意味 | フォーマット |
---|---|---|
size | ダウンロードする画像のサイズ | {縦}x{横} |
location | 緯度経度 | {緯度},{経度} |
heading | 方位(0:北, 90:東, 180:南, 270:西) | [0-360]の範囲の数字 |
fov | ズームの量 | [0-120]の範囲の数字 |
pitch | 上下の角度 -90~90 (-90: 真下, 90: 真上) | [-90-90]の範囲の数字 |
ダウンロードする画像のサイズを、{縦}x(エックスの小文字){横}
で指定するなど、少し引っ掛かりポイントがあるので注意。筆者も最初はエックスの小文字を算術記号の×
を入力していたため、ダウンロードできず少し悩んだ。
住所->緯度経度に変換
APIは緯度経度を入力することで、その地点の画像をダウンロードできると言う仕組みである。しかし、日本のある地点の画像をダウンロードしたいときは、緯度経度を入力するより、住所の入力からその地点の画像をダウンロードできるほうが簡単。その為、入力した日本の住所を緯度経度に変換するコードを作成した。
実装には、以下の方のコードを参考にした。
住所から緯度経度を取得するpythonスニペット - Qiita
def _coordinate(self, address) -> []:
"""
addressに住所を指定すると緯度経度を返す。
>>> coordinate('東京都文京区本郷7-3-1')
['35.712056', '139.762775']
"""
URL = "http://www.geocoding.jp/api/" # Geocording Apiを利用する。
payload = {"q": address}
html = requests.get(URL, params=payload)
soup = BeautifulSoup(html.content, "html.parser")
if soup.find("error"):
raise ValueError(f"Invalid address submitted. {address}")
latitude = soup.find("lat").string
longitude = soup.find("lng").string
return [latitude, longitude]
実行
作成したプログラムで、試しにスカイツリーの地点のStreetViewの画像をダウンロードしてみる。実行コマンドは以下の通り。
$ python street_view_download.py ${APIキー} 東京都墨田区押上1丁目1−2n
ic| address: '東京都墨田区押上1丁目1−2', location: '35.710256,139.810795'
[0] CAoSLEFGMVFpcE5ZVERCVHVLaHhsYkxtdXN5S25NTk5XOWtjaWFydGNoaHlMbWFR
=====================================================================
date: 2020-09
location:
lat: 35.71023864335756
lng: 139.8107896372676
pano_id: CAoSLEFGMVFpcE5ZVERCVHVLaHhsYkxtdXN5S25NTk5XOWtjaWFydGNoaHlMbWFR
status: OK
ic| results.preview(): None
ダウンロードされた画像はこちら。なんとスカイツリーの中に進入できた。
おわりに
いろんな地点の画像を簡単にダウンロードできて便利。APIの呼び出し回数だけには注意。
GitHub - sey323/google-streetview-downloader: Download Image from Google Streetview in Japan