1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Python 不動産ライブラリAPIを使ってみる コーディング編

Posted at

行動変容アプリのコーディング編を書いていく。⇒ 前回の記事はこちら

目次
1.UIの作成
2.APIリクエストの作成
3.ディレクトリ構造の確認
4.次回(デプロイ編)

1.UIの作成

まず初めにUIについて考える。
UIとは、画面のボタンや文字などの操作部分であり、ユーザーが直感的に使いやすいものである必要がある。
不動産取引情報にAPIリクエストを送るために、以下のデータをユーザーから入力が必要。

【必要なユーザー入力】
・都道府県名
・市町村名
・検索したい取引年度

上記の3つのユーザー入力に必要な入力フィールドと、検索ボタンを1つ設置したシンプルなUIを考える。

main.py
import streamlit as st
from src.send_api import connect_api
from src.pref_data import pref_id, change_index

# フッターのHTMLとCSS
footer = """
    <style>
    .footer {
        position: fixed;
        left: 0;
        bottom: 0;
        width: 100%;
        background-color: #f1f1f1;
        color: black;
        text-align: center;
        padding: 10px;
    }
    </style>
    <div class="footer">
        <p>不動産価格(取引価格・成約価格)情報取得API(国土交通省)を基に、作成しています。</p>
    </div>
    """

# フッターを挿入
st.markdown(footer, unsafe_allow_html=True)

# 画面に表示するアプリ名
st.title("不動産取引情報検索")

# 3つのユーザー入力用フィールドを設置(カラムで横並びに設定)
input_col1, input_col2, input_col3 = st.columns(3)
with input_col1:
    prefecture = st.selectbox(
        label="都道府県", options=[index for index, i in pref_id.items()]
    ) # pref_idについては、後ほど実装
with input_col2:
    city = st.text_input(label="市町村(空白可)", placeholder="大阪市")
with input_col3:
    year = st.number_input(label="取引時期(西暦)", value=2024, step=0)

# 検索ボタンを設置(connect_api関数は後ほど実装)
search = connect_api(api_key, prefecture, city, year) if st.button("検索") else None

2.APIリクエストの作成

前項のコードでは未定義のもの
pref_id
connect_api関数

【pref_idについて】
都道府県については47個しかないため、予めpref_idとしてpref_data.pyに辞書型データとして格納しておき、モジュールとして呼び出す仕様とした。

pref_data.py
pref_id = {
    "北海道": "01",
    "青森県": "02",
    "岩手県": "03",
    "宮城県": "04",
    "秋田県": "05",
    "山形県": "06",
    "福島県": "07",
    "茨城県": "08",
    "栃木県": "09",
    "群馬県": "10",
    "埼玉県": "11",
    "千葉県": "12",
    "東京都": "13",
    "神奈川県": "14",
    "新潟県": "15",
    "富山県": "16",
    "石川県": "17",
    "福井県": "18",
    "山梨県": "19",
    "長野県": "20",
    "岐阜県": "21",
    "静岡県": "22",
    "愛知県": "23",
    "三重県": "24",
    "滋賀県": "25",
    "京都府": "26",
    "大阪府": "27",
    "兵庫県": "28",
    "奈良県": "29",
    "和歌山県": "30",
    "鳥取県": "31",
    "島根県": "32",
    "岡山県": "33",
    "広島県": "34",
    "山口県": "35",
    "徳島県": "36",
    "香川県": "37",
    "愛媛県": "38",
    "高知県": "39",
    "福岡県": "40",
    "佐賀県": "41",
    "長崎県": "42",
    "熊本県": "43",
    "大分県": "44",
    "宮崎県": "45",
    "鹿児島県": "46",
    "沖縄県": "47",
}

【connect_api関数について】
都道府県についてはデータ数が少ないため、予めデータとして準備するのも手間ではないが、各都道府県の市町村コードを全て調べてデータ化するのは少し骨が折れる。
調べたところ、市町村コードを取得できるAPIが予め用意してあるため、APIリクエストする際に、ユーザーが入力した市町村コードを取得する仕様とした。
⇒ 都道府県内市区町村一覧取得API

send_api.py
# APIによるデータ取得

# インポート
import streamlit as st
import requests
import pandas as pd
from src.pref_data import pref_id

# API接続関数
def connect_api(api_key: str | int, prefecture: str, city: str | None, year: int):
    api_key = api_key
    url = "https://www.reinfolib.mlit.go.jp/ex-api/external/XIT002"
    headers = {"Ocp-Apim-Subscription-Key": f"{api_key}"}
    params = {"year": year, "area": pref_id[prefecture]}
    response = requests.get(url, headers=headers, params=params)
    json_data = response.json()

    #  市町村コードの取得
    def send_city_id(json_data, city: str | None):
        try:
            for item in json_data["data"]:
                if item["name"] == city:
                    return item["id"]
            if city == "":
                return None
            else:
                return "該当する市町村が存在しません"
        except KeyError:
            return "該当する市町村が存在しません"

    #  入力された市町村が存在しない場合
    city_id = send_city_id(json_data, city)
    url = "https://www.reinfolib.mlit.go.jp/ex-api/external/XIT001"
    params["city"] = city_id
    response = requests.get(url, headers=headers, params=params)
    json_data = response.json()

    #  検索結果に応じた内容を画面描画
    try:
        df = pd.DataFrame(json_data["data"])
        df["TradePrice"] = df["TradePrice"].apply(lambda x: f"¥{int(x):,}")
        df = df.drop(
            columns=[
                "PriceCategory",
                "Prefecture",
                "MunicipalityCode",
                "UnitPrice",
                "Frontage",
                "PricePerUnit",
            ]
        )
        df = df.rename(columns=change_index)
        df.rename(
            columns={"用途地区": "取引価格", "取引価格": "用途地区"}, inplace=True
        )
        df["取引価格"], df["用途地区"] = df["用途地区"], df["取引価格"]
        st.link_button("空き家を登録してみる(外部サイト)", url=my_url)
        st.write(f"{year}年の{prefecture}{city}の取引情報")
        st.write(f"取引件数{str(len(df))}")
        st.dataframe(df)

    except KeyError:
        st.write("該当する市町村が存在しません")

上記のコードでは未定義のもの

change_index
api_key

【change_indexについて】
APIリクエストで取得したデータが英語のため、和訳して表示することを考える。
データ数は20データ程しかないため、都道府県データと同じように、pref_data.pyに辞書型データとして格納し、change_indexモジュールとして呼び出す仕様とした。

pref_data.py
# 下記を追記

change_index = {
    "PriceCategory": "情報種別",
    "Type": "取引種別",
    "Region": "用途地区",
    "Municipality": "市町村",
    "DistrictName": "地名",
    "TradePrice": "取引価格",
    "FloorPlan": "間取り",
    "Area": "面積(㎡)",
    "LandShape": "土地の形状",
    "TotalFloorArea": "延床面積(㎡)",
    "BuildingYear": "建築年",
    "Structure": "建物構造",
    "Use": "建物用途",
    "Purpose": "取引後の利用用途",
    "Direction": "前面道路の方位",
    "Classification": "前面道路の種類",
    "Breadth": "前面道路の幅員(m)",
    "CityPlanning": "都市計画区域",
    "CoverageRatio": "建蔽率(%)",
    "FloorAreaRatio": "容積率(%)",
    "Period": "取引時期",
    "Renovation": "リノベの有無",
    "Remarks": "備考"
}

【api_key】
connect_api関数にAPIキーを渡す必要があるが、大変機微な情報であるため、ハードコーディングはできない。
そのため秘匿化処理を含めて、次回のデプロイ編で解説する。

3.ディレクトリ構造の確認

現在のディレクトリ構造を確認してみる。
_ init _.pyについては ⇒ Python init.pyってなに?

my_project/
│
├── main.py
├── __init__.py
│
├── src/
│   ├── __init__.py
│   ├── pref_data.py
│   ├── send_api.py
│

4.次回(デプロイ編)

次回、Streamlitクラウドへデプロイした話を書く予定。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?