Livedoorお天気Webサービスで遊ぶ

Livedoorのお天気Webサービス
(Livedoor Weather Web Service / LWWS)で遊んでみる。
仕様はこれ→お天気Webサービス仕様 - Weather Hacks - livedoor 天気情報

対応している地域をリストアップする

LWWSは全国142箇所の地域に対応している。
このXMLのcityタグを見ると分かる。→livedoor天気ならびにWeather Hacksに関するお知らせ - livedoor 天気情報
まずはこの142箇所の地域をリストアップしてみる。
以下のスクリプトを実行すると、
標準出力とforecastmap.txtに結果が出力される。
XMLの解析にはREXMLを使用した。

require 'open-uri'
require 'kconv'
require 'rexml/document'

url = "http://weather.livedoor.com/forecast/rss/forecastmap.xml"
wfile = "forecastmap.txt"
doc = nil

open(url){|f|
 doc = REXML::Document.new(f)
}

citys = Array.new
citys = REXML::XPath.match(doc, "//city/attribute::title")

id = 0
open(wfile, 'w'){|f|
  citys.each{|city|
    puts "%3d: #{city.to_s.tosjis}" % id+=1
    f.puts city.to_s.tosjis
  }
}


実行結果はちょっと長いけどこのようになる。

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

簡単なお天気情報を取得する

地域IDと予報日を指定して、お天気情報を取得する。

require 'open-uri'
require 'kconv'
require 'rexml/document'

def get_weather(city = 1, day = 'today')
  return if city < 1 or 142 < city
  return if day != 'today' and day != 'tomorrow' and day != 'dayaftertomorrow'

  url = 'http://weather.livedoor.com/forecast/webservice/rest/v1'
  query = "?city=#{city}&day=#{day}"
  url += query
  title = ""
  telop = ""
  doc = nil

  open(url){|f|
    doc = REXML::Document.new(f)
  }
  
  doc.elements.each("lwws/title"){|e|
    title = e.text.tosjis
  }

  doc.elements.each("lwws/telop"){|e|
    telop = e.text.tosjis
  }
      
  puts "#{title}: #{telop}".tosjis
end

get_weather(63, 'tomorrow')


上記のスクリプトを実行した結果が以下。
東京都(ID63)の明日の天気が出力される。

東京都 東京 - 明日の天気: 曇時々晴


明日は今日学んだことを発展させて、
もう少し何かやってみるかも・・・しれない。

1月から12月の月末を表示する

出力結果が整うように、
%を使ってmonthのフォーマットを調整してみた。
標準出力の整形にはcenterも役に立つ。

require "date"

today = Date.today

puts today.year.to_s.center(18)
puts "-" * 18

1.upto(12){|month|
  lday = Date.new(today.year, month, -1)
  month = "%2d" % month
  puts "#{month}月の最終日は#{lday.day}"
}


実行結果は以下。

       2007
------------------
 1月の最終日は31日
 2月の最終日は28日
 3月の最終日は31日
 4月の最終日は30日
 5月の最終日は31日
 6月の最終日は30日
 7月の最終日は31日
 8月の最終日は31日
 9月の最終日は30日
10月の最終日は31日
11月の最終日は30日
12月の最終日は31日

XMLをパースしたいのでREXMLの勉強中

ぶっちゃけまだ全然分からない。
ほんとに全然・・・。


XMLから抽出したい文字列があるのだけど、
それを実現することは適当な正規表現だけじゃ難しい。
また、正規表現でどうにかなったとしても、
それはすごく分かりづらい方法になってしまうと思う。
とても後から見返す気がおきないような・・・。


RubyにはREXMLというライブラリがあって、
今後もお世話になることがあるかもしれないので、
今の内に勉強しておこうと思う。

追記

何となくは使えるようになった。
番役に立ったのがここ。→http://codezine.jp/a/article/aid/1329.aspx?p=3
次点がここ。→http://circle.cc.hokudai.ac.jp/tsagara/programing/rexml.html
REXMLで何かやろうと思ったときは、
まずこの2つをチェックしてみるのが早いと思う。