Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

CommonLispで駅すぱあとWebサービスのWebAPIを使って駅情報を取得してみる

はじめに

駅すぱあとWebサービスは経路検索・運賃計算・時刻表のAPIを提供しているオンラインサービスです
今回はこれの フリープラン をCommonLispで使ってみます

事前準備

手始めに 「駅すぱあとWebサービス フリープラン」利用お申し込み のページから申し込みする
しばらくするとアクセスキーが書かれたメールが来る

アクセスキーが手に入ったらスペシャル変数として定義しておく

(defparameter *api-key* "Your API Key")

ベースURLとして以下を定義する

(defparameter *base-url* "http://api.ekispert.jp/v1")

取得するデータのフォーマットは xmljson のどちらかを選べるので、今回は json を選択

(defparameter *format* "/json")

今回は駅情報を取得したいので station を指定
他の情報を取得したい場合は API一覧 から

(defparameter *station-info* "/station")

以上を全部つなげると http://api.ekispert.jp/v1/json/station となる

(defparameter *base-station-url* (concatenate 'string *base-url* *format* *station-info*))

これを使って駅情報を取得する

HTTPクライアントとして dexador を使用するのでロードしておく

(ql:quickload :dexador)

駅名で取得

とりあえず 東京 を指定してみる
駅名で取得する場合のクエリパラメータは以下のように指定する

name={station name}

以下のようにすることで旧駅名も指定できる

oldName={station name}

指定できるパラメータは 駅情報 parameters に記載されている

駅名には日本語を指定するためURLエンコードする必要がある
そのためURIライブラリの quri をロードする

(ql:quickload :quri)

以下のように指定する駅名に quri:url-encode を使用する

(defparameter *name* (quri:url-encode "東京"))

これで準備完了、早速取得してみる

(dex:get (format nil "~A?key=~A&name=~A" *base-station-url* *api-key* *name*))
取得結果
"{\"ResultSet\":{\"apiVersion\":\"1.27.0.0\",\"max\":\"9\",\"offset\":\"1\",\"engineVersion\":\"202012_02a\",\"Point\":[{\"Station\":{\"code\":\"22828\",\"Name\":\"東京\",\"Type\":\"train\",\"Yomi\":\"とうきょう\"},\"Prefecture\":{\"code\":\"13\",\"Name\":\"東京都\"},\"GeoPoint\":{\"longi\":\"139.46.13.59\",\"lati\":\"35.40.41.9\",\"longi_d\":\"139.770444\",\"lati_d\":\"35.678083\",\"gcs\":\"tokyo\"}},{\"Station\":{\"code\":\"29110\",\"Name\":\"成田空港(東京)\",\"Type\":\"plane\",\"Yomi\":\"なりたくうこう\"},\"Prefecture\":{\"code\":\"12\",\"Name\":\"千葉県\"},\"GeoPoint\":{\"longi\":\"140.23.26.0\",\"lati\":\"35.45.55.0\",\"longi_d\":\"140.390556\",\"lati_d\":\"35.765278\",\"gcs\":\"tokyo\"}},{\"Station\":{\"code\":\"22827\",\"Name\":\"羽田空港(東京)\",\"Type\":\"plane\",\"Yomi\":\"はねだくうこう\"},\"Prefecture\":{\"code\":\"13\",\"Name\":\"東京都\"},\"GeoPoint\":{\"longi\":\"139.47.19.0\",\"lati\":\"35.32.52.0\",\"longi_d\":\"139.788611\",\"lati_d\":\"35.547778\",\"gcs\":\"tokyo\"}},{\"Station\":{\"code\":\"22859\",\"Name\":\"とうきょうスカイツリー\",\"Type\":\"train\",\"Yomi\":\"とうきょうすかいつりー\"},\"Prefecture\":{\"code\":\"13\",\"Name\":\"東京都\"},\"GeoPoint\":{\"longi\":\"139.48.44.19\",\"lati\":\"35.42.25.59\",\"longi_d\":\"139.812278\",\"lati_d\":\"35.70711\",\"gcs\":\"tokyo\"}},{\"Station\":{\"code\":\"29073\",\"Name\":\"東京テレポート\",\"Type\":\"train\",\"Yomi\":\"とうきょうてれぽーと\"},\"Prefecture\":{\"code\":\"13\",\"Name\":\"東京都\"},\"GeoPoint\":{\"longi\":\"139.46.52.79\",\"lati\":\"35.37.27.9\",\"longi_d\":\"139.781332\",\"lati_d\":\"35.624194\",\"gcs\":\"tokyo\"}},{\"Station\":{\"code\":\"29372\",\"Name\":\"東京ディズニーシー・ステーション\",\"Type\":\"train\",\"Yomi\":\"とうきょうでぃずにーしーすてーしょん\"},\"Prefecture\":{\"code\":\"12\",\"Name\":\"千葉県\"},\"GeoPoint\":{\"longi\":\"139.53.34.0\",\"lati\":\"35.37.27.0\",\"longi_d\":\"139.892778\",\"lati_d\":\"35.624167\",\"gcs\":\"tokyo\"}},{\"Station\":{\"code\":\"29370\",\"Name\":\"東京ディズニーランド・ステーション\",\"Type\":\"train\",\"Yomi\":\"とうきょうでぃずにーらんどすてーしょん\"},\"Prefecture\":{\"code\":\"12\",\"Name\":\"千葉県\"},\"GeoPoint\":{\"longi\":\"139.52.55.0\",\"lati\":\"35.37.58.0\",\"longi_d\":\"139.881944\",\"lati_d\":\"35.632778\",\"gcs\":\"tokyo\"}},{\"Station\":{\"code\":\"29059\",\"Name\":\"東京ビッグサイト\",\"Type\":\"train\",\"Yomi\":\"とうきょうびっぐさいと\"},\"Prefecture\":{\"code\":\"13\",\"Name\":\"東京都\"},\"GeoPoint\":{\"longi\":\"139.47.41.0\",\"lati\":\"35.37.37.0\",\"longi_d\":\"139.794722\",\"lati_d\":\"35.626944\",\"gcs\":\"tokyo\"}},{\"Station\":{\"code\":\"29056\",\"Name\":\"東京国際クルーズターミナル\",\"Type\":\"train\",\"Yomi\":\"とうきょうこくさいくるーずたーみなる\"},\"Prefecture\":{\"code\":\"13\",\"Name\":\"東京都\"},\"GeoPoint\":{\"longi\":\"139.46.35.9\",\"lati\":\"35.37.5.9\",\"longi_d\":\"139.776416\",\"lati_d\":\"35.618083\",\"gcs\":\"tokyo\"}}]}}"
200
#<HASH-TABLE :TEST EQUAL :COUNT 7 {1002B77193}>
#<QURI.URI.HTTP:URI-HTTP http://api.ekispert.jp/v1/json/station?key=LE_uR3LCxKb4csTX&name=%E6%9D%B1%E4%BA%AC>
#<SB-SYS:FD-STREAM for "socket 192.168.11.9:35642, peer: 52.197.98.85:80" {1002B75973}>

色々ごちゃっと取れたけど、とりあえず使うのは最初のJSONデータだけ
JSONデータの内容の詳細は 駅情報 response に記載されている

JSONのままだとCommonLispでは使いづらいので、連想リストに変換する
そのために jonathan をロードする

(ql:quickload :jonathan)

もう一回取得

(jojo:parse
 (dex:get (format nil "~A?key=~A&name=~A" *base-station-url* *api-key* *name*))
 :as :alist)
取得結果
(("ResultSet"
  ("Point"
   (("GeoPoint" ("gcs" . "tokyo") ("lati_d" . "35.678083")
     ("longi_d" . "139.770444") ("lati" . "35.40.41.9")
     ("longi" . "139.46.13.59"))
    ("Prefecture" ("Name" . "東京都") ("code" . "13"))
    ("Station" ("Yomi" . "とうきょう") ("Type" . "train") ("Name" . "東京")
     ("code" . "22828")))
   (("GeoPoint" ("gcs" . "tokyo") ("lati_d" . "35.765278")
     ("longi_d" . "140.390556") ("lati" . "35.45.55.0")
     ("longi" . "140.23.26.0"))
    ("Prefecture" ("Name" . "千葉県") ("code" . "12"))
    ("Station" ("Yomi" . "なりたくうこう") ("Type" . "plane") ("Name" . "成田空港(東京)")
     ("code" . "29110")))
   (("GeoPoint" ("gcs" . "tokyo") ("lati_d" . "35.547778")
     ("longi_d" . "139.788611") ("lati" . "35.32.52.0")
     ("longi" . "139.47.19.0"))
    ("Prefecture" ("Name" . "東京都") ("code" . "13"))
    ("Station" ("Yomi" . "はねだくうこう") ("Type" . "plane") ("Name" . "羽田空港(東京)")
     ("code" . "22827")))
   (("GeoPoint" ("gcs" . "tokyo") ("lati_d" . "35.70711")
     ("longi_d" . "139.812278") ("lati" . "35.42.25.59")
     ("longi" . "139.48.44.19"))
    ("Prefecture" ("Name" . "東京都") ("code" . "13"))
    ("Station" ("Yomi" . "とうきょうすかいつりー") ("Type" . "train")
     ("Name" . "とうきょうスカイツリー") ("code" . "22859")))
   (("GeoPoint" ("gcs" . "tokyo") ("lati_d" . "35.624194")
     ("longi_d" . "139.781332") ("lati" . "35.37.27.9")
     ("longi" . "139.46.52.79"))
    ("Prefecture" ("Name" . "東京都") ("code" . "13"))
    ("Station" ("Yomi" . "とうきょうてれぽーと") ("Type" . "train") ("Name" . "東京テレポート")
     ("code" . "29073")))
   (("GeoPoint" ("gcs" . "tokyo") ("lati_d" . "35.624167")
     ("longi_d" . "139.892778") ("lati" . "35.37.27.0")
     ("longi" . "139.53.34.0"))
    ("Prefecture" ("Name" . "千葉県") ("code" . "12"))
    ("Station" ("Yomi" . "とうきょうでぃずにーしーすてーしょん") ("Type" . "train")
     ("Name" . "東京ディズニーシー・ステーション") ("code" . "29372")))
   (("GeoPoint" ("gcs" . "tokyo") ("lati_d" . "35.632778")
     ("longi_d" . "139.881944") ("lati" . "35.37.58.0")
     ("longi" . "139.52.55.0"))
    ("Prefecture" ("Name" . "千葉県") ("code" . "12"))
    ("Station" ("Yomi" . "とうきょうでぃずにーらんどすてーしょん") ("Type" . "train")
     ("Name" . "東京ディズニーランド・ステーション") ("code" . "29370")))
   (("GeoPoint" ("gcs" . "tokyo") ("lati_d" . "35.626944")
     ("longi_d" . "139.794722") ("lati" . "35.37.37.0")
     ("longi" . "139.47.41.0"))
    ("Prefecture" ("Name" . "東京都") ("code" . "13"))
    ("Station" ("Yomi" . "とうきょうびっぐさいと") ("Type" . "train")
     ("Name" . "東京ビッグサイト") ("code" . "29059")))
   (("GeoPoint" ("gcs" . "tokyo") ("lati_d" . "35.618083")
     ("longi_d" . "139.776416") ("lati" . "35.37.5.9")
     ("longi" . "139.46.35.9"))
    ("Prefecture" ("Name" . "東京都") ("code" . "13"))
    ("Station" ("Yomi" . "とうきょうこくさいくるーずたーみなる") ("Type" . "train")
     ("Name" . "東京国際クルーズターミナル") ("code" . "29056"))))
  ("engineVersion" . "202012_02a") ("offset" . "1") ("max" . "9")
  ("apiVersion" . "1.27.0.0")))

駅名に「東京」が入っている駅の情報が取得できた

さらに、連想リストを操作するのに便利なユーティリティ assoc-utils があるのでこれもロードする

(ql:quickload :assoc-utils)

取得した現在の駅情報をスペシャル変数として定義しておく

(defparameter *station-info*
  (jojo:parse
   (dex:get (format nil "~A?key=~A&name=~A" *base-station-url* *api-key* *name*))
   :as :alist))

以下のように駅名と駅コードを取り出してリスト表示できる

(let ((points (assoc-utils:aget
               (assoc-utils:aget *station-info* "ResultSet")
               "Point")))
  (mapcar
   (lambda (point)
     (let ((station (assoc-utils:aget point "Station")))
       (format t "Code: ~A, Name: ~A~%"
               (assoc-utils:aget station "code")
               (assoc-utils:aget station "Name"))
       station))
   points))
駅名リスト表示
Code: 22828, Name: 東京
Code: 29110, Name: 成田空港(東京)
Code: 22827, Name: 羽田空港(東京)
Code: 22859, Name: とうきょうスカイツリー
Code: 29073, Name: 東京テレポート
Code: 29372, Name: 東京ディズニーシー・ステーション
Code: 29370, Name: 東京ディズニーランド・ステーション
Code: 29059, Name: 東京ビッグサイト
Code: 29056, Name: 東京国際クルーズターミナル

名前に「東京」が入っている駅、以外と多い
成田空港と羽田空港の「(東京)」も駅名の一部なのか・・・

さいごに

駅すぱあとWebサービスをCommonLispから使って駅情報を取得してみました
導入も簡単でとても良いと思いました

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away