【Streamlit】無線局情報検索アプリ

Streamlit
この記事は約14分で読めます。

こんにちは、JS2IIUです。
総務省の電波利用ホームページでは、無線局等の情報を検索するためのWeb-APIを提供しています。このAPIを利用することで、無線局の詳細情報をプログラムから取得し、さまざまな用途に活用することが可能です。今回もよろしくお願いします。

無線局検索APIの概要

無線局検索APIは、総務省が管理する無線局データベースにアクセスし、特定の条件に合致する無線局の情報を取得するためのインターフェースを提供しています。これにより、無線局のコールサイン、名称、所在地、種別、目的、許可日、有効期限、移動範囲、通信事項、通信相手などの詳細情報を取得することができます。

無線局検索APIの主な機能

  • 無線局情報の取得:指定した条件に基づいて、無線局の詳細情報を取得します。
  • 検索条件の指定:コールサイン、無線局名、所在地、種別など、さまざまな条件で検索が可能です。
  • データ形式:取得したデータはJSON形式などで提供され、プログラムでの処理が容易です。

無線局検索APIの利用方法

  1. APIのエンドポイント:APIのURLに対してHTTPリクエストを送信します。無線局の情報を検索する場合はhttps://www.tele.soumu.go.jp/musen/listを指定します。
  2. 検索条件の指定:クエリパラメータとして、検索条件を指定します。
  3. データの取得:レスポンスとして返されるJSONデータを解析し、必要な情報を抽出します。JSON以外に、CSV, XML形式でレスポンスを受け取ることもできます。

サンプルコード

サンプルコードが実際に動くのをお試しいただけます。こちらのStreamlit Cloudからアクセスしてください。

https://soumu-musen-search.streamlit.app
Python
import streamlit as st
import requests
import pandas as pd
from geopy.geocoders import Nominatim

def get_radio_info(call_sign):
    api_url = "https://www.tele.soumu.go.jp/musen/list"  # 正確なエンドポイントを適宜設定
    params = {
        "ST": 1,  # 免許情報検索
        "DA": 1,  # 詳細情報取得
        "OW": "AT", # アマチュア局
        "OF": 2,  # JSON形式
        "DC": 1,  # 取得件数
        "SC": 1,  # スタートカウント
        "MA": call_sign,
    }
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36'
        }

    response = requests.get(api_url, params=params, headers=headers)
    print(response.status_code)
    if response.status_code == 200:
        return response.json()
    else:
        st.error("無線局情報の取得に失敗しました。")
        return None

def extract_info(data):
    if "musen" not in data or len(data["musen"]) == 0:
        st.error("該当する無線局が見つかりませんでした。")
        return None

    records = []
    for item in data["musen"]:
        detail = item.get("detailInfo", {})
        record = {
            "コールサイン": detail.get("identificationSignals", ""),
            "無線局名": detail.get("name", ""),
            "住所": detail.get("radioEuipmentLocation", ""),
            "種別": detail.get("radioStationCategory", ""),
            "目的": detail.get("radioStationPurpose", ""),
            "許可日": detail.get("licenseDate", ""),
            "有効期限": detail.get("validTerms", ""),
            "移動範囲": detail.get("movementArea", ""),
            "通信事項": detail.get("commMatter", ""),
            "通信相手": detail.get("commPartner", ""),
        }
        records.append(record)

    return pd.DataFrame(records)

def get_coordinates(address):
    geolocator = Nominatim(user_agent="streamlit-radio-app")
    location = geolocator.geocode(address)
    if location:
        return location.latitude, location.longitude
    return None, None

def main():
    st.title("無線局情報検索アプリ")

    call_sign = st.text_input("コールサインを入力してください", "JS2IIU")

    if st.button("検索"):
        st.write("無線局情報を取得しています...")

        # APIから無線局情報を取得
        data = get_radio_info(call_sign)
        if data:
            df = extract_info(data)
            if df is not None:
                st.dataframe(df)

                # 住所を地図に表示
                for address in df["住所"].unique():
                    lat, lon = get_coordinates(address)
                    if lat and lon:
                        st.map(pd.DataFrame([{"lat": lat, "lon": lon}]))

if __name__ == "__main__":
    main()

コードの解説

このコードは 「無線局情報検索アプリ」 をStreamlitで実装しています。ユーザーが無線局のコールサインを入力すると、総務省の無線局情報を取得し、データを表示しつつ、住所に基づいた地図も表示します。

以下、各部分をステップごとに詳細に解説します。


① インポート文

Python
import streamlit as st
import requests
import pandas as pd
from geopy.geocoders import Nominatim
各ライブラリの役割
  • Streamlit (st)
    • Webアプリケーションを構築するためのPythonライブラリ。
  • requests
    • HTTPリクエストを送信し、APIからデータを取得するために使用。
  • pandas (pd)
    • データの操作・整形を行うためのライブラリ。検索結果をDataFrame形式で管理。
  • geopy.geocoders.Nominatim
    • 住所を緯度・経度に変換(ジオコーディング)するためのライブラリ。

② 無線局情報を取得する関数

Python
def get_radio_info(call_sign):
    api_url = "https://www.tele.soumu.go.jp/musen/list"
    params = {
        "ST": 1,
        "DA": 1,
        "OW": "AT",
        "OF": 2,
        "DC": 1,
        "SC": 1,
        "MA": call_sign,
    }
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36'
    }

    response = requests.get(api_url, params=params, headers=headers)
    print(response.status_code)
    if response.status_code == 200:
        return response.json()
    else:
        st.error("無線局情報の取得に失敗しました。")
        return None
1. APIリクエストの作成
  • api_url
    • 無線局情報を取得するための総務省のAPIエンドポイント(実際の有効性は確認が必要)。
  • params
    • APIに送信するパラメータの辞書。
    • ST: 1 → 免許情報を検索
    • DA: 1 → 詳細情報を取得
    • OW: "AT" → アマチュア無線局を指定
    • OF: 2 → JSON形式でのレスポンスを要求
    • MA: call_sign → 入力されたコールサイン
  • headers
    • User-Agentを指定してリクエスト。WebサービスがBotと誤認しないようにします。
2. HTTPリクエストを送信
Python
response = requests.get(api_url, params=params, headers=headers)
  • requests.get でGETリクエストを送信。
3. レスポンスの確認
Python
if response.status_code == 200:
    return response.json()
  • ステータスコードが 200(成功) の場合は、JSON形式のデータを返す。
  • それ以外の場合はエラーメッセージを表示し、Noneを返す。

③ 無線局情報を抽出する関数

Python
def extract_info(data):
    if "musen" not in data or len(data["musen"]) == 0:
        st.error("該当する無線局が見つかりませんでした。")
        return None

    records = []
    for item in data["musen"]:
        detail = item.get("detailInfo", {})
        record = {
            "コールサイン": detail.get("identificationSignals", ""),
            "無線局名": detail.get("name", ""),
            "住所": detail.get("radioEuipmentLocation", ""),
            "種別": detail.get("radioStationCategory", ""),
            "目的": detail.get("radioStationPurpose", ""),
            "許可日": detail.get("licenseDate", ""),
            "有効期限": detail.get("validTerms", ""),
            "移動範囲": detail.get("movementArea", ""),
            "通信事項": detail.get("commMatter", ""),
            "通信相手": detail.get("commPartner", ""),
        }
        records.append(record)

    return pd.DataFrame(records)
1. データの検証
  • "musen"キーが存在しない、またはデータが空の場合はエラーメッセージを表示。
2. 必要な情報を抽出
  • APIから得たデータから 無線局の詳細情報 を取得し、以下の項目を抽出:
    • コールサイン、無線局名、住所、種別、目的、許可日、有効期限、移動範囲、通信事項、通信相手
3. DataFrameに変換
  • 抽出したデータをPandasのDataFrameに変換して返す。

④ 住所を緯度・経度に変換する関数

Python
def get_coordinates(address):
    geolocator = Nominatim(user_agent="streamlit-radio-app")
    location = geolocator.geocode(address)
    if location:
        return location.latitude, location.longitude
    return None, None
  • Nominatim オブジェクトを作成し、住所から緯度・経度を取得。
  • ジオコーディング が成功した場合は、(緯度, 経度) を返す。

⑤ メイン関数

Python
def main():
    st.title("無線局情報検索アプリ")

    call_sign = st.text_input("コールサインを入力してください", "JS2IIU")

    if st.button("検索"):
        st.write("無線局情報を取得しています...")

        data = get_radio_info(call_sign)
        if data:
            df = extract_info(data)
            if df is not None:
                st.dataframe(df)

                for address in df["住所"].unique():
                    lat, lon = get_coordinates(address)
                    if lat and lon:
                        st.map(pd.DataFrame([{"lat": lat, "lon": lon}]))
1. アプリのUI構築
  • st.title() → アプリのタイトルを表示。
  • st.text_input() → コールサインを入力するテキストボックスを表示(デフォルトは”JS2IIU”)。
  • st.button() → 検索ボタン。
2. 検索実行
  • 無線局情報の取得get_radio_info()を呼び出す。
  • データフレームを表示st.dataframe()で検索結果をテーブル表示。
  • 住所から緯度・経度を取得し地図表示st.map()で地図を描画。

⑥ アプリの実行

Python
if __name__ == "__main__":
    main()

この行でアプリケーションを実行。Streamlitでこのコードを動かせば、ブラウザにインターフェースが表示されます。

参考になるWEBサイトのリンク

最後に、書籍のPRです。
24年9月に出版された「ハイパーモダンPython-信頼性の高いワークフローを構築するモダンテクニック」、Claudio Jolowicz著、嶋田、鈴木訳。開発環境の構築、プロジェクトの管理、テストに関して実践的な内容でとても参考になる一冊です。ぜひ手に取ってみてください。

最後まで読んでいただきありがとうございます。

コメント

タイトルとURLをコピーしました