大学シャトルバスのタイムテーブルを呟く Bot
まぁ今更 Twitter の Bot を作ったところで特に目新しい話が出る訳ではありませんが、備忘録という事で。先ず、うちの大学のシャトルバス運行タイムテーブルが大学のアクセスとして載せられていまして、バスに乗ろうという時にはわざわざそこにアクセスするか、表を持ち歩かないと駄目でした。まぁ両方めんどくさいんで、よく見てる Twitter に情報を定期 post すれば良いんじゃない? っていう安直な発想です。
スクレイピング
先ず、作り始める上で重要なのはどこから元になるデータを調達するのか? というところです。コレは自分が手作業で打ち込み業務を行ってもなんら問題はなく、その場合はこの章は無駄になる訳ですが、Web の情報且つ現在運営されている法人のサイトですのでいつタイムテーブルが変更されるか分かりません。ですので、タイムテーブルが変わっても自動更新出来る Bot にする必要がありました。何せめんどくさいですから。自動更新するには紙からの入力はあり得ないので、結果 Web から取得する事になりました。
と、言う訳でスクレイピング*1する必要があります。言語は Ruby でライブラリはスクレイピングに nokogiri, tweet 用に twitter を使いました。
Gemfile の作成から。
source :rubyforge gem 'twitter', '4.5.0' gem 'nokogiri', '1.5.6'
$ sudo gem install bundler $ bundle install --path vendor/bundler
これで準備が ok です。
- nokogiri の使い方
require 'nokogiri' require 'open-uri' bus_schedule = "http://#{URI}" doc = Nokogiri::HTML(open(bus_schedule)) # Xpath or CSS doc.xpath("xpath") doc.css("attr")
Xpath, CSS 共に指定した要素とマッチする場合、マッチ箇所を DOM として返されます。後は each なり map なりを使って個別に node を取り出して調理するだけでした。簡単。
参考ページは以下です。
Tweet 機能
とは言え、こちらも正直な所 twitter ライブラリを使えば後は登録してポンなので別段特別な事はしておらず。以下の通りです。
requrie 'tiwtter' require 'yaml' config_file = "ENV['HOME']/.key.yml" env = YAML::load File.open(config_file) Twitter.configure do |config| config.consumer_key = CONSUMER_KEY config.consumer_secret = CONSUMER_SECRET config.oauth_token = OAUTH_TOKEN config.oauth_token_secret = OAUTH_TOKEN_SECRET end client.update("テストツイーョ")
やった事と言えば ${HOME}/.key.yml にトークンと鍵を置いて読み込むようにした程度です。次でも説明しますが、.key.yml は諸事情の為ホームディレクトリに置いています。
スクリプトの daemon 化
Ruby 1.9 からスクリプトを daemon*3 化する為のメソッドが追加されました。Process.daemon を実行すると、スクリプトは daemon 化します。ただし、注意点として、カレントディレクトリが変更される (らしい) ので絶対 PATH で書いています*4。
仕上げ
Bot の作成という事で、勝手に死なれては困ります。なので、tweet のタイミングで Error ハンドリングを行って呟きに失敗したら時間を空けてトライするようにしました。
require 'time' Process.daemon while true begin if Time.now.min % 10 == 0 and (7 <= Time.now.hour and Time.now.hour <= 23) tweet = "テストツイーョ" client.update(tweet) end sleep 60 rescue => ex sleep 10 retry end end
上から、プロセスをデーモン化し、無限ループによって tweet する Bot の完成。sleep を入れているのは、無意味にマシンのリソースを食い潰すのを防ぐ意味と、Twitter への DOS 攻撃にならないようアクセス制限を設ける意味があります。begin, rescue, end の構文はエラー処理ですね。エラーが出た時は 10 秒待機した後、処理のやり直しを行うだけです。後は、何回も連続して呟きに行かないよう呟きが成功した場合は 1 分待ち、条件分岐で現在時刻の分が 10 で割り切れる時間の時且つ、7 時 ~ 23 時にのみ tweet 可能にすれば無意味な Twitter へのアクセスはなくなります。