IT omoe

ITのこと知らないんですけどIT関連のことを気ままに綴ります

Rubyで天気予報の取得と画像のツイート

前回,前々回に引き続き,Twitter botの拡張をしていきます.わーい.

ottosan84.hatenablog.com

ottosan84.hatenablog.com

天気予報の取得とツイート

今回はbotのTL上で #お嬢天気予報 というハッシュタグをつけてつぶやいた人に対して,天気予報を送りつけるという機能を作ってみますた.

天気予報の取得

これも色々とやり方があると思いますが,今回はライブドア天気情報「Weather Hacks」の結果を利用します.例えば,滋賀県大津の天気の取得はこんな感じ.

require 'net/http'
require 'uri'
require 'json'

uri = URI.parse('http://weather.livedoor.com/forecast/webservice/json/v1?city=250010')
json = Net::HTTP.get(uri)
result = JSON.parse(json)
p result

city=の後のIDを変えてやることで,様々な地域の天気予報を取得することができます.これを実行すると,

{
"pinpointLocations"=>
[{
    "link"=>"http://weather.livedoor.com/area/forecast/2520101", 
    "name"=>"大津市南部"
 },{
    "link"=>"http://weather.livedoor.com/area/forecast/2520400",
    "name"=>"近江八幡市"
 },{
    "link"=>"http://weather.livedoor.com/area/forecast/2520600",
    "name"=>"草津市"
 },{
    "link"=>"http://weather.livedoor.com/area/forecast/2520700",
    "name"=>"守山市"
 },{
    "link"=>"http://weather.livedoor.com/area/forecast/2520800",
    "name"=>"栗東市"
 },{
    "link"=>"http://weather.livedoor.com/area/forecast/2520900",
    "name"=>"甲賀市"
 },{
    "link"=>"http://weather.livedoor.com/area/forecast/2521000",
    "name"=>"野洲市"
 },{
    "link"=>"http://weather.livedoor.com/area/forecast/2521100",
    "name"=>"湖南市"
 },{
    "link"=>"http://weather.livedoor.com/area/forecast/2521300",
    "name"=>"東近江市"
 },{
    "link"=>"http://weather.livedoor.com/area/forecast/2538300",
    "name"=>"日野町"
 },{
    "link"=>"http://weather.livedoor.com/area/forecast/2538400",
    "name"=>"竜王町"
 }], 
"link"=>"http://weather.livedoor.com/area/forecast/250010",
"forecasts"=>
[{
    "dateLabel"=>"今日",
    "telop"=>"晴時々曇",
    "date"=>"2016-02-21",
    "temperature"=>{
        "min"=>nil,
        "max"=>{"celsius"=>"10", "fahrenheit"=>"50.0"}
    },
    "image"=>{
        "width"=>50,
        "url"=>"http://weather.livedoor.com/img/icon/2.gif",
        "title"=>"晴時々曇",
        "height"=>31
        }
 },{
    "dateLabel"=>"明日",
    "telop"=>"晴のち曇",
    "date"=>"2016-02-22",
    "temperature"=>{
        "min"=>{"celsius"=>"2", "fahrenheit"=>"35.6"},
        "max"=>{"celsius"=>"9", "fahrenheit"=>"48.2"}},
    "image"=>{
        "width"=>50,
        "url"=>"http://weather.livedoor.com/img/icon/5.gif",
        "title"=>"晴のち曇",
        "height"=>31
        }
},{
    "dateLabel"=>"明後日",
    "telop"=>"曇のち雨",
    "date"=>"2016-02-23",
    "temperature"=>{
        "min"=>nil,
        "max"=>nil
    },
    "image"=>{
        "width"=>50,
        "url"=>"http://weather.livedoor.com/img/icon/13.gif",
        "title"=>"曇のち雨",
        "height"=>31
    }
}], 
"location"=>{
    "city"=>"大津",
    "area"=>"近畿",
    "prefecture"=>"滋賀県"
},
"publicTime"=>"2016-02-21T11:00:00+0900",
"copyright"=>{
    "provider"=>[{
        "link"=>"http://tenki.jp/",
        "name"=>"日本気象協会"
    }],
    "link"=>"http://weather.livedoor.com/",
    "title"=>"(C) LINE Corporation",
    "image"=>{
        "width"=>118,
        "link"=>"http://weather.livedoor.com/",
        "url"=>"http://weather.livedoor.com/img/cmn/livedoor.gif",
        "title"=>"livedoor 天気情報",
        "height"=>26
    }
},
"title"=>"滋賀県 大津 の天気",
"description"=>{
    "text"=>"近畿地方は、寒気の影響で北部を中心に雲が広がり、雨や雪の降っているところがあります。
            今日の滋賀県は、冬型の気圧配置となり北部を中心に雲が広がりやすく、夕方まで雪や雨の降るところがある見込みです。
            明日の滋賀県は、高気圧に覆われて概ね晴れますが、午後は気圧の谷の影響で次第に雲が広がるでしょう。",
    "publicTime"=>"2016-02-21T10:34:00+0900"
    }
}

こんな感じの結果が返ってきます.この中の,今日の天気や明日の天気の情報を利用していきたいと思います.

取得結果のツイート

天気予報が取得できたら,後はこの結果を表示したい形にしてツイートしてやるだけです.

require 'twitter'
require 'net/http'
require 'uri'
require 'json'

client_streaming = Twitter::Streaming::Client.new do |config|
  config.consumer_key = "YOUR_CONSUMER_KEY"
  config.consumer_secret = "YOUR_CONSUMER_SECRET"
  config.access_token = "YOUR_ACCESS_TOKEN"
  config.access_token_secret = "YOUR_TOKEN_SECRET"
end

client_rest = Twitter::REST::Client.new do |config|
  config.consumer_key = "YOUR_CONSUMER_KEY"
  config.consumer_secret = "YOUR_CONSUMER_SECRET"
  config.access_token = "YOUR_ACCESS_TOKEN"
  config.access_token_secret = "YOUR_TOKEN_SECRET"
end

USERNAME = "ottosan884_bot"
client_streaming.user do |object|
  case object
  when Twitter::Tweet
    username = object.user.screen_name # ユーザー名
    tweet = object.text                # ツイート内容
    tweet_id = object.id               # ツイートのID
    option = {:in_reply_to_status_id => tweet_id}
    if (!tweet.index("RT")) && (username != USERNAME)
      if (/#お嬢天気予報/ =~ tweet)
        puts username + ':' + tweet
        uri = URI.parse('http://weather.livedoor.com/forecast/webservice/json/v1?city=250010')
        json = Net::HTTP.get(uri)
        result = JSON.parse(json)
        today_tel = result['forecasts'][0]['telop'] #今日の天気
        tomor_tel = result['forecasts'][1]['telop'] #明日の天気
        min_tem = result['forecasts'][1]['temperature']['min']['celsius'] #明日の最低気温
        max_tem = result['forecasts'][1]['temperature']['max']['celsius'] #明日の最高気温
        client_rest.update("@#{username} #{result['title']}\n#{result['link']}\n予報の発表日時: #{result['publicTime']}\n今日: #{today_tel}\n明日: #{tomor_tel} 最低#{min_tem}度 最高#{max_tem}度\n#お嬢天気予報", option) 
# つづく

って感じです.

煽り画像を送りつける

画像のツイートはとても簡単ですが一応書き留めときます. 今回はお嬢botのTL上で #お嬢の煽り というタグをつけてつぶやかれたツイートに煽り画像を送りつけるという仕様です. まず送りつけたい画像を用意します.ディレクトリの中はこんな感じ. f:id:ottosan84:20160225155737p:plain

autorep.rbってのの中身はこんな感じ.上記の天気予報のプログラムの続きになってます.

#つづき
    elsif (/#お嬢の煽り/ =~ tweet)
        puts username + ':' + tweet
        files = Dir.glob("aori*")
        pic_id = client_rest.upload(File.new(files.sample))
        option = {
          :in_reply_to_status_id => tweet_id,
          :media_ids => pic_id
        }
        client_rest.update('@'+username+' #お嬢の煽り', option)
      end
    end
  end
end

Dir.glob()はカッコ内の条件に該当するファイル名を文字列の配列として返します.該当ファイルがない場合は空の配列を返します.今回,画像には全てaoriという文字列が含まれるようにしたので"aori*"(*は空文字列を含む任意の文字列)で全ての画像のファイル名がfilesという配列に格納されます.

後はuploadして得られたIDをoptionに加えてやれば画像をツイートすることができます.めでたしめでたし.

今後の展開

mcg.hateblo.jp

なんか天気予報もっと簡単に出来んじゃねえのって煽られてる()ので暇があればやってみたいな〜.とりあえずTwitter botシリーズはここで一旦キリを付けたいと思います. Gitにコードうpしました.-> https://github.com/ottosan/ojobot