ATOKで天気予報を呼び出す

ジャストシステムが今日発表した、「ATOKダイレクト API for Perl/Ruby」は面白そうです。面白そうというのと、役に立つというのはまた別の話だったりするのですが、工夫すればいろいろと作ることができるはず。(続編(ATOKRSSリーダ)はd:id:atzy:20081031:p1)

ATOKダイレクト API for Perl/Ruby


天気予報を探す

とりあえず、簡単なところで、天気予報Webサービスを呼び出してみます。
天気予報をXMLで提供しているのは、私が知る限りではライブドアのサービス*1があります。つまりお天気Webサービスというやつです。無駄にSOAPとかで提供しておらず、また、JSONなどでもありません。RESTですので運よくRubyでも処理がしやすい*2と言えます。

ウェブサービスを呼び出す

どうやら、地域と日付(今日・明日・明後日)を指定して取り出せるということですが、指定できる都市が少々多いですので、それをIDに変換する操作(例えば東京は63とか)がめんどくさいといえます。
しかし、スクリプトの助けを借りて、都市とIDを変換するメソッドを書きました。

取り出せる値は、天気や最低・最高気温、説明文などのようです。他にもあるんでしょうが、とりあえずはそのあたりだけ取り出しておきましょう。ライブドアの該当する都市の天気予報ページのURLも出てくるようですので、そいつも取り出しておきます。(このURLは後で出てきますがATOKからそのページに飛べるようにした部分で利用されています。)

渡された都市名をIDに変換、Webサービスに接続、XMLを取得、XMLから情報の取得、までを行うスクリプトをちゃちゃっといい加減に作成いたしました。

プラグインを記述する

ATOKダイレクト API for Perl/Rubyは、いやに簡単にプラグインが作れるようで、何でもありになっております。
先ほど作ったお天気サービス接続スクリプトをサンプル内にほぼそのまま埋め込んで少しだけ書き換えます。次のようになります。

HTTPプロキシを使う設定になっていますから、環境に合わせてそこだけ書き換えちゃって下さい。HTTPプロキシを使わないなら、:proxy => "http://#{PROXY_HOST}:#{PROXY_PORT}/" と書かれているところを :proxy => nil とでも書き換えて下さい。

#! /usr/bin/ruby -Ku
require 'open-uri'
#require 'kconv'
require 'rexml/document'

PROXY_HOST = 'あなたの環境に合わせて下さい'
PROXY_PORT = あなたの環境に合わせて下さい
DAY_NAME = ["今日", "明日", "明後日"]

module Atok_plugin

  def run_process(request_data)
    result_data = {}
    candidate_array = []
    city = request_data['composition_string']
    3.times{|day|
      weather = getLivedoorWeather(city, day)
      if weather.nil?
        candidate_array.push({'hyoki' => 'error'})
      else
        if weather["max"]
          weather_telop = "[#{DAY_NAME[day]}] #{weather['weather']}(#{weather['min']}-#{weather['max']}℃)"
        else
          weather_telop = "[#{DAY_NAME[day]}] #{weather['weather']}"
        end
        candidate_array.push({'hyoki' => weather_telop,
                              'comment' => weather["description"],
                              'alternative' => weather["url"],
                              'alternative_type' => "url_jump_string" })
      end
    }
    result_data['candidate'] = candidate_array
    result_data
  end

  def getLivedoorWeather(city, day = 0)
     city_id = city2Id(city)
     return nil if city_id == -1
     day_name = 'today'
     if day == 1
       day_name == 'tomorrow'
     elsif day == 2 
       day_name = 'dayaftertomorrow'
     end
     open("http://weather.livedoor.com/forecast/webservice/rest/v1?city=#{city_id}&day=#{day_name}",
          :proxy => "http://#{PROXY_HOST}:#{PROXY_PORT}/") {|f|
       xml = ''
       f.each_line {|line|
          xml << line
       }
#       puts xml
       weatherresult = REXML::Document.new(xml)
       list_list = []
       w = weatherresult.elements['/lwws/telop'].text
       desc = weatherresult.elements['/lwws/description'].text
       url = weatherresult.elements['/lwws/link'].text
       min = weatherresult.elements['/lwws/temperature/min/celsius'].text
       max = weatherresult.elements['/lwws/temperature/max/celsius'].text
       return {'weather' => w,
               'description' => desc,
               'url' => url,
               'min' => min,
               'max' => max}
     }
  end
  
  def city2Id(city)
    case city
    when "稚内"
      return 1
    when "旭川"
      return 2
    when "留萌"
      return 3
    when "札幌"
      return 4
    when "岩見沢"
      return 5
    when "倶知安"
      return 6
    when "網走"
      return 7
    when "北見"
      return 8
    when "紋別"
      return 9
    when "根室"
      return 10
    when "釧路"
      return 11
    when "帯広"
      return 12
    when "室蘭"
      return 13
    when "浦河"
      return 14
    when "函館"
      return 15
    when "江差"
      return 16
    when "青森"
      return 17
    when "むつ"
      return 18
    when "八戸"
      return 19
    when "秋田"
      return 20
    when "横手"
      return 21
    when "盛岡"
      return 22
    when "宮古"
      return 23
    when "大船渡"
      return 24
    when "仙台"
      return 25
    when "白石"
      return 26
    when "山形"
      return 27
    when "米沢"
      return 28
    when "酒田"
      return 29
    when "新庄"
      return 30
    when "福島"
      return 31
    when "小名浜"
      return 32
    when "若松"
      return 33
    when "水戸"
      return 54
    when "土浦"
      return 55
    when "宇都宮"
      return 56
    when "大田原"
      return 57
    when "前橋"
      return 58
    when "みなかみ"
      return 59
    when "さいたま"
      return 60
    when "熊谷"
      return 61
    when "秩父"
      return 62
    when "東京"
      return 63
    when "大島"
      return 64
    when "八丈島"
      return 65
    when "父島"
      return 66
    when "千葉"
      return 67
    when "銚子"
      return 68
    when "館山"
      return 69
    when "横浜"
      return 70
    when "小田原"
      return 71
    when "甲府"
      return 75
    when "河口湖"
      return 76
    when "富山"
      return 44
    when "伏木"
      return 45
    when "金沢"
      return 46
    when "輪島"
      return 47
    when "福井"
      return 48
    when "敦賀"
      return 49
    when "新潟"
      return 50
    when "長岡"
      return 51
    when "高田"
      return 52
    when "相川"
      return 53
    when "長野"
      return 72
    when "松本"
      return 73
    when "飯田"
      return 74
    when "静岡"
      return 34
    when "網代"
      return 35
    when "三島"
      return 36
    when "浜松"
      return 37
    when "名古屋"
      return 38
    when "豊橋"
      return 39
    when "岐阜"
      return 40
    when "高山"
      return 41
    when ""
      return 42
    when "尾鷲"
      return 43
    when "大津"
      return 77
    when "彦根"
      return 78
    when "京都"
      return 79
    when "舞鶴"
      return 80
    when "大阪"
      return 81
    when "神戸"
      return 82
    when "豊岡"
      return 83
    when "奈良"
      return 84
    when "風屋"
      return 85
    when "和歌山"
      return 86
    when "潮岬"
      return 87
    when "岡山"
      return 88
    when "津山"
      return 89
    when "広島"
      return 90
    when "庄原"
      return 91
    when "松江"
      return 92
    when "浜田"
      return 93
    when "西郷"
      return 94
    when "鳥取"
      return 95
    when "米子"
      return 96
    when "下関"
      return 97
    when "山口"
      return 98
    when "柳井"
      return 99
    when ""
      return 100
    when "徳島"
      return 101
    when "日和佐"
      return 102
    when "高松"
      return 103
    when "松山"
      return 104
    when "新居浜"
      return 105
    when "宇和島"
      return 106
    when "高知"
      return 107
    when "室戸"
      return 108
    when "清水"
      return 109
    when "福岡"
      return 110
    when "八幡"
      return 111
    when "飯塚"
      return 112
    when "久留米"
      return 113
    when "大分"
      return 114
    when "中津"
      return 115
    when "日田"
      return 116
    when "佐伯"
      return 117
    when "長崎"
      return 118
    when "佐世保"
      return 119
    when "厳原"
      return 120
    when "福江"
      return 121
    when "佐賀"
      return 122
    when "伊万里"
      return 123
    when "熊本"
      return 124
    when "阿蘇乙姫"
      return 125
    when "牛深"
      return 126
    when "人吉"
      return 127
    when "宮崎"
      return 128
    when "延岡"
      return 129
    when "都城"
      return 130
    when "高千穂"
      return 131
    when "鹿児島"
      return 132
    when "鹿屋"
      return 133
    when "種子島"
      return 134
    when "名瀬"
      return 135
    when "那覇"
      return 136
    when "名護"
      return 137
    when "久米島"
      return 138
    when "南大東島"
      return 139
    when "宮古島"
      return 140
    when "石垣島"
      return 141
    when "与那国島"
      return 142
    else
      return -1
    end
  end

end

実はほとんどの行をしめるのが、どうでもよい処理とも言える地名とIDの変換です。

インストール

このファイルを、例えばweather.rbで保存しておいて、その後はセットアップ手順に沿って作っていくだけです。セットアップツールはダウンロードして展開して下さい。また、ジャストシステムが指定するバージョンのRubyが必要です。

具体的なプラグインのインストールですが、SETUP.EXEがあるフォルダに、pluginフォルダを作って、そのフォルダにweather.rbを保存。それから、SETUP.EXEがあるフォルダに、SETUPINFO.XMLというファイルを配置します。内容は適当でOKですが、先ほど作ったweather.rbというファイル名と、そのファイルを入れたフォルダ名(plugin)は指定しておきましょう。

<?xml version="1.0" encoding="UTF-8" ?>
<setup_info_list>
  <setup_info>
    <data_folder_name>plugin</data_folder_name>
    <plugin_file_name>weather.rb</plugin_file_name>
    <plugin_enable>true</plugin_enable>
    <only_individual_run>false</only_individual_run>
    <add_position>1</add_position>
  </setup_info>
</setup_info_list>

で、SETUP.EXEを動かすと勝手にプラグインフォルダにインストールされるようです。
プラグインフォルダは、例えばC:\JUST\ATOK\ATOKDIRECT\PLUGINですが、環境によって異なります。

使い方

例えば「とうきょう」とATOKで打ち込んで、変換して「東京」になった時点(未確定)で、Ctrl + Insertを押します。すると、最初に示したような変換候補ウィンドウが出てきます。Enterで確定もできますがあまり意味がありません。というか基本的には見るだけですね。ただし、Shift + Enter で該当するライブドアの天気予報ページに飛べますから、そちらを使ってもよいでしょう。

イデア

Yahoo!のVJEを叩くことはできましたが、これは実際問題それほど役にたちそうにはありませんね。文節区切りを扱うのが難しいですから。
もう少し面白いことに使いたいものです。天気予報と似たところでは株価検索があるでしょうが、たぶん配信しているサービスはないのじゃないかなあ。

逆にネットワーク側に送信するということも考えられるかもしれません。例えば、Twitterでつぶやくのに、いちいちアプリを切替えるのがめんどくさいから、つぶやきの言葉を書くとかでしょうか。でも、ATOKダイレクトの仕組みだと、一気に変換した部分しか送れないからバッファ(というか一時ファイル)にためておいて、特定のコマンドで送信という感じでしょうか。そうだとしたら恐ろしく使いにくいといえます。

あまり意味はないかもしれませんが、シェルの代わりみたいにすることもできるかな。コマンドを起動したり。

追記:RSSリーダにしてみました。(d:id:atzy:20081031:p1)

*1:個人利用に関しては問題ないと書いてあります。

*2:私が使ったことがないだけでJSONだったらRubyから簡単に扱えそうな気もします。