"BOKU"のITな日常

還暦越えの文系システムエンジニアの”BOKU”は新しいことが大好きです。

Djangoで都道府県・市区町村一覧を取得するWeb-APIプロキシを作ってみる

Djangoで「Web-APIプロキシ」を作ってみます。

今回は、APIキーを渡したり、パラメーターを受け渡ししたりするパターンの例です。

f:id:arakan_no_boku:20190909212423j:plain
 

この記事の前提

 

記事中のソースは、Djangoのrestフレームワークを使っています。

Djangoのrestフレームワークで、Web-APIプロキシ的Web-APIを作る方法などについては以下の記事に書いています。

arakan-pgm-ai.hatenablog.com

上記の記事の中では「郵便番号API」をとりあげてます。

ユーザ登録も、API-KEYも何も必要ない気軽に使えるAPIだからです。

ipcloud.ibsnet.co.jp

これについては、上記の記事の中でサンプル的に実装していますが、クラスベースの実装を再掲しておきます。

adress_from_zip.py

import requests
from rest_framework.views import APIView
from rest_framework.response import Response


class AddressFromZip(APIView):

    def get(self, request):
        zipcode = request.GET.get(key="zipcode", default="1000011")
        resp = requests.get(
            'http://zipcloud.ibsnet.co.jp/api/search?zipcode=' +
            str(zipcode) +
            '&limit=1')
        return Response(resp.json(), status=resp.status_code)

 

地域経済分析システムAPI内閣府 地方創生推進室

 

利用には「登録(無料)が必要」です。

登録には、メールアドレスと名前と市区町村レベルの所在地が必要です。

登録すると、API-KEYが送られてくるので、このAPIキーをリクエストヘッダー「X-API-KEY」にセットして、利用しないといけないことになってます。

以下の概要で一覧が見れますが、このAPIからとれる情報はものすごく多いです。

https://opendata.resas-portal.go.jp/docs/api/v1/index.html

f:id:arakan_no_boku:20190902203127p:plain

共通として「都道府県・市区町村」とか「産業分類」「職業分類」などが取得できて、

それらの組合せをキーにして「人口」とか「従業員数」とかみたいな個別情報が取得できるみたいな構造になってます。

今回は、「都道府県一覧 api/v1/prefectures」と「市区町村一覧 api/v1/cities」の取得と、それをキーにして人口情報を取得するという例・・というか、自分がテストとかに使うためにやってみたものを紹介してみます。

 

APIラッパーが必要な理由

 

JavaScriptからWebAPI呼出しをすると「Access-Control-Allow-Origin」のエラーになるものがあります。

もちろん、すべてではないですが、エラーになるものを個別対応するのは、かなり、面倒です。

なので、django restフレームワーク等で内部でWEB-APIを処理して結果を返す「WEB-APIプロキシ」を使り、そこでCORS(Cross-Origin Resource Sharing:オリジン間リソース共有)対応をしておけば、安心して使えるというわけです。

しかも。

この方法だと特定のURLからのアクセスのみリソース共有を許す「ホワイトリスト」が使えますので、「CORS_ORIGIN_ALLOW_ALL」などで何でもOKにするよりも、セキュリティ的に強固になります。

ということでAPIラッパーの例を作ります。

 

都道府県コード一覧取得

 

都道府県コードの一覧を取得するソースコードです。

prefectures_api.py

import requests
from rest_framework.views import APIView
from rest_framework.response import Response


class Prefectures(APIView):

    def get(self, request):
        headers = {'X-API-KEY': 'noxxxxxxxxxjK'}
        resp = requests.get(
            'https://opendata.resas-portal.go.jp/api/v1/prefectures',
            headers=headers)
        return Response(resp.json(), status=resp.status_code)

補足します。

ポイントはAPIキーの渡し方です。

headersに渡す必要があるので、上記のようなやり方をします。

 

市区町村コード一覧取得

 

都道府県コードをキーに、市区町村一覧を取得する処理です。

ソースコードはこんな感じです。

municipalities_api.py

import requests
from rest_framework.views import APIView
from rest_framework.response import Response


class Municipalities(APIView):

    def get(self, request):
        pref_code = request.GET.get(key="prefCode", default="13")
        headers = {'X-API-KEY': 'nomgUp7A61gOWlvNTaGVjX1u7IvakZUf9MBcwOjK'}
        params = {'prefCode': pref_code}
        resp = requests.get(
            'https://opendata.resas-portal.go.jp/api/v1/cities',
            headers=headers,
            params=params)
        return Response(resp.json(), status=resp.status_code)

ポイントはパラメータを受けるところと、パラメータを渡すところです。 

デフォルトは「13」(つまり東京)にしています。

基本、本物のAPIパラメータと同じ名前にしています。

 

URLSの構成

 

上記のようにクラスベースで実装したAPIは、urls.pyに以下のように登録して使います。

urls.py

from django.contrib import admin
from django.urls import path
from . import views
from . import adress_from_zip as zip
from . import prefectures_api as pref
from . import municipalities_api as city

urlpatterns = [
    path(
        'admin/',
        admin.site.urls),
    path(
        'api/v1/addresses/zip/get',
        zip.AddressFromZip.as_view(),
        name='cls-v'),
    path(
        'api/v1/prefectures',
        pref.Prefectures.as_view(),
        name='pref-v'),
    path(
        'api/v1/cities',
        city.Municipalities.as_view(),
        name='city-v'),
]

例えば、市区町村コード取得の場合だと。 

http://localhost:8000/api/v1/cities?prefcode=10

 のように使います。

実際のRESASのAPIコールのURLは

https://opendata.resas-portal.go.jp/api/v1/cities?prefCode=10

 なので、ドメイン以外のURLやパラメータ名はあわせてやるようにしてます。

取得した結果はこんな感じ。

f:id:arakan_no_boku:20190902234709p:plain

APIを直接処理した場合と同じようなJSONが返せています。

よしよし。

今回はheadersやparamsを使う「Web-APIプロキシ」を試しにやってみました。

今回はこんなところで。

ではでは。