サイトアイコン アマチュア無線局JS2IIU

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

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

無線局検索APIの概要

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

無線局検索APIの主な機能

無線局検索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
https://js2iiu.com/wp-content/uploads/2025/03/soumu.mov
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
各ライブラリの役割

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

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リクエストの作成
2. HTTPリクエストを送信
Python
response = requests.get(api_url, params=params, headers=headers)
3. レスポンスの確認
Python
if response.status_code == 200:
    return response.json()

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

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. データの検証
2. 必要な情報を抽出
3. 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

⑤ メイン関数

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構築
2. 検索実行

⑥ アプリの実行

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

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

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

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

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

モバイルバージョンを終了