[Python #8] API / Web API

こんにちは、pythonチームのH.Iです。
学生の多くの人は夏季休業に入っているのではないでしょうか。
外に出るのも暑いですし家の中でコーディングするのが健康的な過ごし方だと思っています。

今回は表題の通り、【API】についてお話ししたいと思います。

Pythonでシステムを作る際いろいろなAPIのお世話になります。
使い方が分かっていれば知識があまりなくてもそんなに困らないですが、どういうものなのか理解しておいて損はないと思います。

APIとは

「API」とは、Application Programming Interfaceの略称です。

とりあえず、「アプリケーション」と「プログラミング」と「インターフェイス」に関係しているということは分かりますね。

結局のところどういうものなのかというと、あるプログラムA(アプリケーションA)の機能の一部を別のプログラムB(アプリケーションB)が使えるようにする架け橋のような存在(インターフェイス)であり、仕組みのことです。

技術的なことを言えば、プログラムB側(クライアント)からプログラムA側の公開されているAPIサーバーに向けてリクエストを送り、そのレスポンスとして返ってきた機能を使うという形です。

APIを利用することで、世の中に既に出回っている機能を自分のシステムに組み込みたいときに、一からコーディングなどをすることなくその機能だけを使うことができます。

そして、APIの中でもHTTPもしくはHTTPSの通信によってやり取りされるものが、【Web API】と呼ばれるものです。

Web API以外のAPIは、やり取りするプログラム間で同じ言語を使っていなければいけないのですが、Web APIの場合は言語が違っていても通信することができます。

PythonでWeb APIを利用しながらシステムを作ることは珍しくないと思いますので、今回は実際に無料で公開されているWeb APIを使いながら、Web APIとはどのようなものなのかをつかんでもらいたいと思います。

国土地理院API

今回は、国土地理院が提供しているジオコーディング用のAPIを利用したいと思います。

このAPIは認証を必要としないため大変簡単に利用できます。

ちなみにジオコーディング(geocoding)というのは、住所や地名を緯度経度情報に変換することです。その逆を逆ジオコーディング(reverse geocoding)といい、国土地理院APIではそのどちらの機能も利用できます。

PythonでWebAPIを利用する方法は様々ありますが、今回はrequestsライブラリを使ってやっていきたいと思います。

流れ

PythonでWeb APIのリクエストを送り、返ってくるまでの大まかな流れを説明します。

まず、大体のWeb APIは、「ベースとなるURL」に「クエリパラメータ」を付け加えてリクエストを送ります。

そして、返り値をjson形式で取得して、それを加工しながら使います。

今回の国土地理院のジオコーディング用APIの「ベースとなるURL」は、下記の通りです。

"https://msearch.gsi.go.jp/address-search/AddressSearch"

クエリパラメータとして、例えば東京タワーの住所である「東京都港区芝公園4丁目2−8」を付け加えたりします。

コーディング

大体の流れは分かったと思うので、実際にコーディングしながら見ていきたいと思います。

インポート

import requests ##リクエスト送信用
import urllib ##クエリパラメータのエンコード用

urllibは、クエリパラメータを「ベースとなるURL」に付け加える場合に使用します。こちらを使う場合と使わない場合両方ご紹介します。

リクエスト

クエリパラメータをparamsで指定する場合

base_url = 'https://msearch.gsi.go.jp/address-search/AddressSearch'
params = {'q':'東京都港区芝公園4丁目2−8'}
res = requests.get(base_url,params=params)

paramsは、keyが'q'、valueが'検索したい住所'の辞書型にします。
この「paramsを使ったリクエスト」については別の記事で詳しく説明します(T.Sさんがしてくれる予定です。)

エンコードしたURLを「ベースとなるURL」に付け加える場合

base_url = 'https://msearch.gsi.go.jp/address-search/AddressSearch'
q = urllib.parse.quote('東京都港区芝公園4丁目2−8')
url = f'{base_url}?q={q}'
res = requests.get(url)

ここでしているエンコードはURLエンコードやパーセントエンコーディングと呼ばれるものです。
例えば今回の「東京都港区芝公園4丁目2−8」は、「%E6%9D%B1%E4%BA%AC%E9%83%BD%E6%B8%AF%E5%8C%BA%E8%8A%9D%E5%85%AC%E5%9C%92%EF%BC%94%E4%B8%81%E7%9B%AE%EF%BC%92%E2%88%92%EF%BC%98」に変換されています。

レスポンス

返り値をjson形式(辞書型)で取得します。

res_json = res.json()


res_jsonを出力すると、以下のようになります。

#------
[{'geometry': {'coordinates': [139.745468, 35.658649], 'type': 'Point'},
'type': 'Feature',
'properties': {'addressCode': '', 'title': '東京都港区芝公園四丁目2番'}}]
#------

リストの中に辞書型の要素が入っている形ですね。これは、住所やキーワードで検索する場合は緯度経度座標の候補が複数出てくるためです。

ここまで来たらあとは中身を取り出すだけです。

coordinates = res_json[0]['geometry']['coordinates']
lon, lat = coordinates[0], coordinates[1]
print(f'lat, lon : {lat},{lon}')

最後のprint文の出力結果は以下のようになります。

#-----
lat, lon : 35.658649,139.745468
#-----

関数化

関数化して使いやすくしたものが以下です。

import requests ##リクエスト送信用
import time
def geocoding(address): #ジオコーディング
base_url = 'https://msearch.gsi.go.jp/address-search/AddressSearch'
params = {'q':address}

time.sleep(1)
res = requests.get(base_url,params=params)
print('Status Code :',res.status_code)
res_json = res.json()[0]

coordinates = res_json['geometry']['coordinates']
lon, lat = coordinates[0], coordinates[1]
print(f'lat, lon : {lat},{lon}')
return lat, lon

おわりに

いかがだったでしょうか。大体APIってどんなものか、Pythonで実装するときにはどうすればいいかなど掴んでいただけたでしょうか。

今回は認証を使わないWebAPIを例に挙げましたが、GoogleAPIのような認証を必要とするものもいつかご紹介できたらと思います。

ファイナルアンサーではこのように様々な技術をシステム開発に役立てています。

興味がある方はぜひエントリーしてみてください!

参考

Web APIとは?初心者にもわかる基本的な仕組みと活用方法

国土地理院APIでお手軽ジオコーディング&逆ジオコーディング

PythonでURLエンコード・デコード(urllib.parse.quote, unquote)

Pythonロゴの提供元