↓ メインコンテンツへスキップ
  1. 補講/
  2. 補講02講 Webアプリケーション(Docker)/

応用 郵便番号検索 REST API

概要
#

これまでの内容の応用として、郵便番号を検索するサンプル REST アプリケーションを紹介します。 このアプリケーションは、郵便番号を与えると、その郵便番号に対応する住所を返す REST API です。

郵便番号のデータは、日本郵政グループが提供する 郵便番号データダウンロード からダウンロードしたデータを利用しています。

利用方法
#

ダウンロードして展開してできたディレクトリに移動して以下のどちらかのコマンドで起動できます。

  • docker compose up
  • python3 app/zipcode_rest.py app/data/utf_ken_all.csv

起動後、以下のようなコマンドで郵便番号検索ができます。

demo

上記のデモでは以下のコマンドを入力しています。

$ curl http://localhost:5001/zipcode/1000001     # 100-0001 を検索する
$ curl http://localhost:5001/zipcode/prefs/東京都 # 東京都の郵便番号一覧を調べる
$ curl -i http://localhost:5001/zipcode/1000001  # レスポンスヘッダも表示するようにする
$ curl -i http://localhost:5001/zipcode/1000001 -X DELETE  # 削除する
$ curl -i http://localhost:5001/zipcode/1000001 -X DELETE  # 何度実行しても結果は同じ
$ curl http://localhost:5001/zipcode/1000001     # 削除したので、100-0001 は見つからない。
$ # 100-0001 を登録し直すことにする。
$ # curl で JSON を POST メソッドで送るとき、Content-Type の指定が必要。"
$ curl http://localhost:5001/zipcode/1000001 -X POST -d '{"address": "千代田区千代田", "address_yomi": "チヨダクチヨダ", "pref": "東京都", "zipcode": 1000001 }' -H 'Content-Type: application/json'
$ curl http://localhost:5001/zipcode/1000001  # 登録し直したので、今度は見つかる。"
$ # 再度同じ情報を登録しようとすると、エラーになる。"
$ curl http://localhost:5001/zipcode/1000001 -X POST -d '{"address": "千代田区千代田", "address_yomi": "チヨダクチヨダ", "pref": "東京都", "zipcode": 1000001 }' -H 'Content-Type: application/json'

郵便番号検索 REST API
#

以下は、https://github.com/ksubpb/zipcode_flask_rest からの転載です。

GET /zipcode/prefs/{prefecture}
#

指定された都道府県の郵便番号の一覧をJSONで取得します。 指定された都道府県が見つからない場合は、404 を返す。 都道府県は、兵庫県や、東京都などのように、日本語で指定し、県や府は省略しないでください。

GET /zipcode/{zipcode}
#

指定された郵便番号の住所などをJSONで取得します。 郵便番号が見つからない場合は、404 を返し、 見つかった場合は、200 および JSON をレスポンスのボディに入れて返します。

DELETE /zipcode/{zipcode}
#

指定された郵便番号のデータを削除します。 このリクエストは常に成功します。 指定された郵便番号が見つかれば、そのデータを削除し、見つからなければ何もしません。

POST /zipcode/{zipcode}
#

指定された郵便番号のデータを追加します。 郵便番号のデータは JSON 形式で、HTTP リクエストボディに与えます。 有効なデータは、GET /zipcode/{zipcode} で取得できるデータと同じです。

PUT /zipcode/{zipcode}
#

指定された郵便番号のデータを更新します。 郵便番号のデータは JSON 形式で、HTTP リクエストボディに与えます。 有効なデータは、GET /zipcode/{zipcode} で取得できるデータと同じです。

プログラムコード
#

プログラムは、database.pyとzipcode_rest.pyの2つのファイルから構成されています。 database.py では、コマンドライン引数で与えられた csv ファイルを読み込み、データベースを構築します。 一方、zipcode_rest.py では、Flask を使って REST API を提供します。

database.py
#

ZipCodeクラス
#

郵便番号とそれに対応する住所などの情報を保持するクラスです。 コンストラクタと、オブジェクトを JSON に変換する to_json メソッドを持っています。

ZipCodeBuilderクラス
#

csv ファイルを読み込んで、ZipCode オブジェクトを作成し、データベースを構築するクラスです。 buildメソッドでcsvのファイル名を受け取り、中身を読み取ります。 1行につき、1つの ZipCode オブジェクトを作成し、ディクショナリに追加します。 このディクショナリがデータベースとなり、buildメソッドの返り値として返します。

zipcode_rest.py
#

REST API の各エンドポイントごとにメソッドを作成しています。 各エンドポイントでは、JSON 形式でデータを返すようにしています。 そのため、jsonify 関数を用いて、データを JSON に変換しています。

また、Flask で日本語を含む JSON を返そうとすると、文字化けが発生することがあります(ブラウザで見る分には影響を感じませんが)。 Flask はデフォルトで ASCII 文字以外をエンコードして返すためです。 これに対応するため、zipcode_rest.py の 5行目に app.json.ensure_ascii = False という行を入れています。 これにより、日本語を含む JSON を正しく返すことができます。 ただし、返されるJSONをそのまま JavaScript に変換する場合、セキュリティ上の問題が発生する場合があるため、基本的には ensure_ascii = True にしておくことが推奨されます。