Rubyで駅すぱあとWebサービスの周辺駅検索の結果を地図画像上に描画する

## 概要

- Ruby を使って2つの WebAPI をマッシュアップするサンプル
- 駅すぱあとWebサービスの周辺駅検索を利用して駅情報を取得
- Yahoo!スタティックマップAPIを利用して駅情報を地図上に表示

## ソースコード

```ruby
require 'json'
require 'uri'
require 'open-uri'

# 駅すぱあとWebサービス
# @see http://docs.ekispert.com/
class Ekispert

  # Ekispertオブジェクトを生成する
  # @param access_key [String] アクセスキー
  # @return [Ekispert]
  def initialize(access_key)
    @access_key = access_key
  end

  # 緯度経度から周辺駅を検索する
  # @see http://docs.ekispert.com/v1/api/geo/station.html
  # @param lat [String] 緯度
  # @param lon [String] 経度
  # @return [Array]
  def geo_station(lat, lon, radius)
    base_url = 'https://api.ekispert.jp/v1/json/geo/station'
    params = {
      'key' => @access_key,
      'geoPoint' => geo_point(lat, lon, radius),
      'gcs' => 'wgs84',
    }
    url = base_url + '?' + URI.encode_www_form(params)
    #puts url # debug
    json = open(url).read
    json2stations(json)
  end

  private

  # geoPointパラメータの値を生成する
  # @see http://docs.ekispert.com/v1/dictionary/coordinate-information/
  # @param lat [String] 緯度
  # @param lon [String] 経度
  # @return [String]
  def geo_point(lat, lon, radius)
    "#{lat},#{lon},wgs84,#{radius}"
  end

  # 周辺駅検索レスポンスJSON文字列を駅データの配列にする
  # @param json [String] JSON文字列
  # @return [Array]
  def json2stations(json)
    stations = []
    data = JSON.parse(json)
    #puts JSON.pretty_generate(data) # debug
    data['ResultSet']['Point'].each do |p|
      stations << {
        'name' => p['Station']['Name'],
        'lat'  => p['GeoPoint']['lati_d'],
        'lon'  => p['GeoPoint']['longi_d'],
      }
    end
    stations
  end

end

# YOLP (Yahoo! Open Local Platform)
# @see https://developer.yahoo.co.jp/webapi/map/
class YOLP

  # YOLPオブジェクトを生成する
  # @param appid [String] アプリケーションID
  # @return [YOLP]
  def initialize(appid)
    @appid = appid
  end

  # 地図画像を取得する
  # @see https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/static.html
  # @param map [Hash] 地図生成のパラメータ
  # @param pois [Array] POIデータの配列
  # @return [String] 地図画像データ
  def static_map(map, pois)
    base_url = 'https://map.yahooapis.jp/map/V1/static'
    params = {
      'appid'  => @appid,
      'width'  => map['width'],
      'height' => map['height'],
    }
    pois.each_with_index do |p, i|
      params["pin#{i}"] = "#{p['lat']},#{p['lon']},#{label(p['name'])}"
    end
    url = base_url + '?' + URI.encode_www_form(params)
    #puts url # debug
    open(url).read
  end

  private

  # pin パラメータに指定するラベル文字列を生成する
  # @param name [String] POI名称
  # @return [String] pinパラメータに指定するラベル文字列
  def label(name)
    name.gsub(/／(.+?)$/, "\n(\\1)")
  end

end

begin

  access_key = '<YOUR ACCESS KEY>' # アクセスキー

  lat = '35.170897'  # 名古屋駅付近の緯度
  lon = '136.884938' # 名古屋駅付近の経度
  radius = '350' # 単位はメートル

  stations = Ekispert.new(access_key).geo_station(lat, lon, radius)
  stations.each_with_index do |s, i|
    puts "(#{i})#{s['name']}\n   #{s['lat']}, #{s['lon']}\n\n"
  end

  appid = '<APPLICATION ID>' # アプリケーションID
  map = {
    'width'  => '600',
    'height' => '600',
  }
  output_file = 'ekimap.png'

  image = YOLP.new(appid).static_map(map, stations)
  open(output_file, 'wb').write(image)

rescue Exception => e
  puts "ERROR: #{e.message}"
end
```

## 実行結果

### 出力されたテキスト

```
(0)名古屋駅／名古屋市営バス
   35.1713, 136.884192

(1)近鉄名古屋
   35.17048, 136.883026

(2)名古屋
   35.170731, 136.882609

(3)名鉄名古屋
   35.169036, 136.884053

(4)名鉄バスセンター／名鉄バス
   35.168862, 136.884711

(5)名鉄ＢＣ(高速・連絡バス)
   35.168509, 136.884787

(6)名古屋・名鉄バスセンター／三重交通
   35.167931, 136.884206
```

鉄道駅だけでなくバス停も取得できている。ドキュメントによると、駅の交通種別を指定できる type パラメータを利用すれば、鉄道、飛行機、船、バスなどで絞り込みが可能。

### 出力された地図画像

![ekimap.png](https://qiita-image-store.s3.amazonaws.com/0/139365/0fc3086b-0355-b908-2842-df8a5baa6079.png)

## レスポンスJSONの一部を抜粋

参考情報として、駅すぱあとWebサービスの周辺駅検索のレスポンスJSONの一部をここに抜粋しておく。

```
{
  "ResultSet": {
    "apiVersion": "1.27.0.0",
    "engineVersion": "201712_04a",
    "Point": [
      {
        "Station": {
          "code": "40729",
          "Name": "名古屋駅／名古屋市営バス",
          "Type": {
            "text": "bus",
            "detail": "local"
          },
          "Yomi": "なごやえき"
        },
        "Prefecture": {
          "code": "23",
          "Name": "愛知県"
        },
        "GeoPoint": {
          "longi": "136.53.3.9",
          "lati": "35.10.16.67",
          "longi_d": "136.884192",
          "gcs": "wgs84",
          "lati_d": "35.1713"
        },
        "Distance": "81"
      },
```

## 参考資料

- [駅すぱあとWebサービス \- システム連携サービス \- サービス・製品紹介 \- 駅すぱあとワールド](https://ekiworld.net/service/sier/webservice/index.html)
- [緯度経度からの周辺駅検索 \- 駅すぱあとWebサービス Documents 駅データ・路線検索のWebAPI](http://docs.ekispert.com/v1/api/geo/station.html)
- [座標情報 \- 駅すぱあとWebサービス Documents 駅データ・路線検索のWebAPI](http://docs.ekispert.com/v1/dictionary/coordinate-information/)
- [YOLP\(地図\):Yahoo\!スタティックマップAPI \- Yahoo\!デベロッパーネットワーク](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/static.html)