QRZ.COM XML サービスについてのメモ(承前)

#Amateur_radio #PCとプログラム覚え

前記事QRZ.COM XML サービスについてのメモ(前置き) の続きです。

文書の場所

QRZ.COMが提供するXMLサービスの規格文書は次のリンクにあります。
https://www.qrz.com/XML/current_spec.html
正式名称は「QRZ XML Logbook Data Specification」です。version1.34が最新文書となります(2020年7月15日)。
ただし実際のXMLバージョンは1.36となっているようです。いつリビジョンアップしたのかはわかりません。

著者はAA7BQのFred Lloyd、VA7STVのStephen McLauglin両氏で、aa7bqコールサインは本文書内の利用例のためにも使われています。

仕様概要


仕様はシンプルです。

(1)qrz.comの特定URIに、GETあるいはPOSTでqrz.comの自分のユーザ名とパスワードを投げます。

(2)認証されたらセッション情報がXML形式で返されアクセスkeyが得られます。
※認証失敗した場合はError項目がXML形式で返されます。

(3)上記keyを用いて、検索したいコールサインのリクエストを行います。これもGET/POSTどちらも可能です。

(4)成功したら、該当コールサインのQRZDatabaseに格納されている情報がXML形式で返されます。QRZ.COMにブラウザでアクセスしコールサイン検索を行ったときに表示される「detail」項目の情報です。

以下、順を追ってその内容を見ていきます。


認証用のURI・パラメタと返されるXML要素

認証用URIは次のようになっています。
3種類のパターンがありますが最新バージョン用のものだけ掲出しておきます。
https://xmldata.qrz.com/xml/current/?username=xx1xxx;password=abcdef
(POSTの場合?以下を除いたURIにusername,passwordの値を投げます)。

成功すると次のようなXMLが返ります。ただし同例は、旧いバージョンでの取得結果ですので、最新クエリ結果とは異なっている場合があります。ご注意ください。



省略
14
non-subscriber<−−−無料の場合のユーザはnon-subscriberとなります
日付
cpu: 0.098s

失敗すると次のようになります。



Username/password incorrect <−−−エラーの要素が表示される
日付
cpu: 0.096s


コールサインクエリ用URIとXML要素

上記Key要素で囲まれた文字列を用いて、次のURIにアクセスします。先の例と同様GETでもPOSTでもかまいません。なお以下のURIはGET表現です。

https://xmldata.qrz.com/xml/current/?s=キー;callsign=コールサイン

文書の中で、著者の一人のaa7bqのコールサインを使ったXML例が掲載されています。
<もし有料のサービス登録済ユーザがリクエストすればどのような項目を得ることが出来るか>という例です。
なお同コールサインへのクエリについては、有料未登録ユーザでも同じようなフルの項目が得られるようになっているようです(実際に試すとわかります)。

 
<−−−現在は1.36です
  
      AA7BQ 
      N6UFT,KJ6RK,DL/AA7BQ 
      291 
      FRED L 
      LLOYD 
      8711 E PINNACLE PEAK RD 193 
      SCOTTSDALE 
      AZ 
      85255 
      United States 
      291 
      34.23456 
      -112.34356 
      DM32af <−−グリッドロケーター
      Maricopa 
      04013 
      USA 
      2000-01-20 
      2010-01-20 <−−−昔の例なので、現在とは違っている
      KJ6RK 
      E 
      HAI 
      NONE <--任意だが、qslマネージャが個人の場合はそのコールサインなど、またビューロ経由の場合via bureauと記載される場合が多い
      [email protected] 
      https://www.qrz.com/db/aa7bq 
      115336 
      3937/2003-11-04 
      https://files.qrz.com/q/aa7bq/aa7bq.jpg 
      3626 
      2003-11-04 19:37:02 
      6200 
      602 
      Mountain 
      -7 
      N 
      Y <--eQSLを使っているか(Yとなっているが、文書では0/1あるいはブランクを返すとなっている。齟齬があるが理由不明)
      Y <--郵便QSL配送可能か(同上)
      なおこの例ではlotwのノードフィールドはない。現行バージョン1.36でクエリすると返ってくる。
      3 
      2 
      user 
      c/o QRZ LLC 
      The Boss 
      FRED "The Boss" LLOYD 
      1953 
  
  
      2331uf894c4bd29f3923f3bacf02c532d7bd9 
      123 
      Wed Jan 1 12:34:03 2013 
      Sun Nov 16 04:13:46 2012 
  

ちなみに有料未登録ユーザがクエリを発行すると、実際は次の情報しか得られません。


コールサイン
ファーストネーム
ラストネーム
住所

その他の機能

他にも対象局の経歴(biography)情報を取得する(htm=コールサイン)、DXCC情報にかかわるクエリも発行出来ます。(前者の場合はXMLではなくhtmlで情報が返ります。)

また、この文書には他に緯度経度とグリッドデータについての計算方法(考え方)の項目があって興味深いのですが、本記事の主旨から外れるところがあるので、これは別記事で記載することにします。


テスト用コード(python)

上の接続・検索手順を踏まえたPython のテスト用コードは次のようになります。
※QRZ.COMに未登録コールサインの処理はしていません。単純にエラーが返ります。
実行ディレクトrには、コードの実行ファイル以外に、自分のユーザ名、パスワードを二行で書いたcredentials.txtという名前のファイルを置きます。

import requests
from xml.etree import ElementTree

def get_credentials():
    with open('credentials.txt', 'r') as file:
        lines = file.readlines()
        username = lines[0].strip()
        password = lines[1].strip()
        return username, password

def get_session_key(username, password):
    url = "https://xmldata.qrz.com/xml/current/"
    data = {'username': username, 'password': password}
    response = requests.post(url, data=data)
    if response.status_code != 200:
        raise Exception(f"認証リクエストでエラーが発生しました。ステータスコード: {response.status_code}")

    root = ElementTree.fromstring(response.content)
    namespace = {'ns': 'http://xmldata.qrz.com'}
    key_element = root.find(".//ns:Key", namespace)
    if key_element is None:
        raise Exception("XMLレスポンスにKeyエレメントが存在しません。")
    return key_element.text

def check_for_error_in_response(response):
    root = ElementTree.fromstring(response.content)
    namespace = {'ns': 'http://xmldata.qrz.com'}
    error_element = root.find(".//ns:Error", namespace)
    return error_element is not None

def fetch_and_save_data(callsign):
    username, password = get_credentials()

    try:#セッションキーが変わることがあるので、その対策もしている
        with open('latest.key', 'r') as file:
            session_key = file.read().strip()
    except FileNotFoundError:
        session_key = None

    if session_key:
        url = "https://xmldata.qrz.com/xml/current/"
        data = {'s': session_key, 'callsign': callsign}
        response = requests.post(url, data=data)
        if not check_for_error_in_response(response):
            with open(f"{callsign}.txt", "w") as file:
                file.write(response.text)
            return

    session_key = get_session_key(username, password)
    with open('latest.key', 'w') as file:
        file.write(session_key)

    url = "https://xmldata.qrz.com/xml/current/"
    data = {'s': session_key, 'callsign': callsign}
    response = requests.post(url, data=data)
    if response.status_code != 200 or check_for_error_in_response(response):
        raise Exception(f"新しいキーでのリクエストでエラーが発生しました。ステータスコード: {response.status_code}, レスポンス: {response.text}")

    with open(f"{callsign}.txt", "w") as file:
        file.write(response.text)


# fetch_and_save_data("コールサイン")
# 上が実際の実行メソッドです。コメントを外し、実際に情報を得たいコールサインを書いてください。同じディレクトリに、
# コールサイン.txt名のファイルが出来ます。
Popup