WebAPIをpythonで作る

WebAPI

WebAPIとは

pythonでホームページを作成して表示するところはやってきました。ただ、Webはホームページ表示だけではありません。 実は、画面に表示せずに仕事を行うことができます。WebAPIはその一つで、Webに対しての問い合わせ、例えば、この緯度経度は何市何町とか、この町の郵便番号はとかの問い合わせに、ホームページ表示ではなくデータだけを返すやりかたです。 データの返し方はjsonとかxmlとかいう決められたフォーマットで返し、それをプログラムで受信して加工して使用します。

WebAPI

たとえばxmlデータは次のようなフォーマットで、内容に関しては自分で自由で決められます。

<?xml version="1.0" encoding="UTF-8"?>
<pocketMoney>
	<payment>
		<content>
			<date>1月20日</date>
			<train>780</train>
			<eat>980</eat>
			<coffee>250</coffee>
		</content>
	</payment>
</pocketMoney>

jsonデータは、javascript用のフォーマットで次のようなものです。

[
  {"id" : "1", "name" : "suzuki"},
  {"id" : "2", "name" : "tanoue"}
]

リクエストに対するレスポンスをこのようなxmlやjsonで返すとWEBAPIとして、WEB上または、ローカルから呼び出して利用することができるようになります。

pythonでjsonをレスポンスで返すには、jsonify()関数に返したい辞書を入れてあげれば利用できます。

簡単なサンプルを作る(サーバー側 Flask)

日付を渡して、その前後の日付を返すWEBAPI

Flaskを使ってローカルで動くWEBAPIを作って、日付を返すWEBAPIの実験をしましょう

webapisampleのソース

webapisampleフォルダーを作成し、app.pyを作成します

#!/usr/bin python3
# -*- coding: utf-8 -*-

# pip install python-dateutil
# flask run
# localhost:5000/?year=2021&month=2&day=25&delta=pd10
# {"day":7,"month":3,"year":2021}

from flask import Flask, jsonify, make_response, request
from dateutil.relativedelta import relativedelta
from datetime import datetime
import json

app = Flask(__name__)

@app.route('/', methods=['GET'])
def retDate():
	today = datetime.today()
	#パラメータ取得
	syear = request.args.get("year",default='')
	year = today.year if syear == '' else int(syear)
	smonth = request.args.get("month",default='')
	month = today.month if smonth == '' else int(smonth)
	sday = request.args.get("day",default='')
	day = today.day if sday == '' else int(sday)
	strDelta = (request.args.get("delta"))
	thatday = today.replace(year=year,month=month,day=day)

	#deltaパラメータの解析
	pmDelata = strDelta[0]	#p->plus, m->minus
	scaleDelta = strDelta[1] #y->year,m->month,d->day
	valueDelta = int(strDelta[2:]) #pm10->+10 month, md3->-3 day

	#日付計算
	pmValue = 1 if pmDelata=='p' else -1
	if scaleDelta=='y':
		efectDay = thatday + (relativedelta(years=valueDelta) * pmValue)
	elif scaleDelta=='m':
		efectDay = thatday + (relativedelta(months=valueDelta) * pmValue)
	elif scaleDelta=='d':
		efectDay = thatday + (relativedelta(days=valueDelta)*pmValue)

	result = {
		'year': 	efectDay.year,
		'month':	efectDay.month,
		'day':		efectDay.day
	}
	return make_response(jsonify(result))

if __name__ == '__main__':
	app.run(host='0.0.0.0', port=5000,debug=True)

コマンドプロンプトで、webapisampleのフォルダーに移動し、flask runで起動します。

続いて、ブラウザを立ち上げ localhost:5000/?year=2021&month=2&day=25&delta=pd10 と入力します。すると画面に {"day":7,"month":3,"year":2021}と表示されます。これがWEBAPIの答えで、2021年2月25日の10日後は何日かという質問にWEBAPIがjsonで2021年3月7日と答えを返してきたところです。

簡単なサンプルを作る(クライアント側 python)

先に作ったWEBAPIをローカルのpythonから呼び出すプログラム

pythonのプログラムを作り、WEBAPIを経由して日付の計算を行う実験を行います。

webapicall.pyのソース

適当なフォルダーを作成し、webapicall.pyを作成します

#!/usr/bin python3
# -*- coding: utf-8 -*-

# python webapicall.py 2021 2 25 pd10
# 2021/2/21の10日後
# python webapicall.py 2021 2 25 mm2
# 2021/2/21の2ヶ月前
# xynn -> x:plus or minus, y:d day,m month,y year, nn is number

import requests
import sys
from datetime import datetime

year = 0
month = 0
day = 0
pmdata = "pd1"
argc = len(sys.argv)
if argc == 5:
	pmdata = (sys.argv[4])
	day = int(sys.argv[3])
	month = int(sys.argv[2])
	year = int(sys.argv[1])
else:
	sys.exit()

param = {"year": year, "month": month, "day":day,"delta":pmdata}

url = "http://localhost:5000"
data = requests.get(url, param).json()

ayear = data['year']
amonth = data['month']
aday = data['day']
print(year,"年",month,"月",day,"日->",pmdata,"->",ayear,"年",amonth,"月",aday,"日")

実行すると、このような結果になります

クライアント側
python webapicall.py 2021 2 25 pd10
2021 年 2 月 25 日-> pd10 -> 2021 年 3 月 7 日
				
python webapicall.py 2021 2 25 mm2
2021 年 2 月 25 日-> mm2 -> 2020 年 12 月 25 日

サーバー側
127.0.0.1 - - [06/Jan/2022 15:01:18] "GET /?year=2021&month=2&day=25&delta=pd10 HTTP/1.1" 200 -
127.0.0.1 - - [06/Jan/2022 15:01:33] "GET /?year=2021&month=2&day=25&delta=mm2 HTTP/1.1" 200 -