DDRで消費したカロリーを自動でツイートする (その5)
Windowsのタスクスケジューラを使う
まずはお手軽な方法として、Windowsのタスクスケジューラを使うことを考えました。タスクスケジューラはWindows 7の場合、表示方法を大きいアイコンに変更し、管理ツールを開くとあります。
下記のように設定すると、毎日0:10に自動で動作させることができます。ただし、PCは起動した状態でなければなりません。スリープから復帰するという項目はありますが、多くの場合はあてにならないようです。
- タスクスケジューラライブラリの下にフォルダを作成
- 作成したフォルダの中に新しいタスクを作成
- 「ユーザーがログオンしているかどうかにかかわらず実行する」を選択
- トリガーを毎日、0:10に設定
- 操作を下記のように設定
最初、rubyソースと同じディレクトリにバッチファイルを作成してそれを起動しようとしたのですが、カレントディレクトリが合っていないため実行できませんでした。
これで自動で定期実行することはできるようになりましたが、実行したい時間にPCを立ち上げておく必要があるのが若干わずらわしい点です。次回はこれを解消するため、VPSでの自動実行について書きたいと思います。
参考にした記事
DDRで消費したカロリーを自動でツイートする (その4)
アプリケーションを登録する
今回は、開発用に別アカウントをとってみました。お手軽に目的を達成したい場合、メインアカウントで登録したほうがOAuth認証の手間がないため簡単です。
下記の記事を参考に、アプリケーションを登録しました。ここで、アプリケーションのConsumer keyとConsumer secret、またアプリを登録したアカウント用のAccess tokenとAccess token secretが取得できます。
開発用アカウントにつぶやく
今回はTwitter Gemを使ってみます。
gem install twitter
clientをnewしてコンフィグした後、updateメソッドをを呼び出すことでつぶやけるようです。ドキュメントの例となんら変わらないのですが、下記のコードでつぶやくことができました。
#! /usr/bin/ruby -Ku require "twitter" CONSUMER_KEY = "" # アプリケーションのものに置き換える CONSUMER_SECRET = "" # アプリケーションのものに置き換える ACCESS_TOKEN = "" # つぶやき先アカウントのものに置き換える ACCESS_SECRET = "" # つぶやき先アカウントのものに置き換える client = Twitter::REST::Client.new do |config| config.consumer_key = CONSUMER_KEY config.consumer_secret = CONSUMER_SECRET config.access_token = ACCESS_TOKEN config.access_token_secret = ACCESS_SECRET end client.update("投稿テスト")
自分のアカウントにつぶやく
開発者以外のアカウントにつぶやくためには、OAuth認証でつぶやきを許可する必要があります。
本来はアプリ連携用のリンクとコールバックURLを使って認証するようですが、今回は自分しか使わないので下記を参考に、コマンドラインで飛び先のURLを取得してブラウザに貼り付ける方法をとりました。
ここで得られたaccess tokenとaccess secretを使ってアクセスすると、認証したアカウントでつぶやくことができます。当然、流出しないように気をつける必要があります。
これで、実行するとeAMUSEMENTから消費カロリーを取得して、twitterに投稿することができるようになりました。
次回は自動実行について書きたいと思います。
DDRで消費したカロリーを自動でツイートする (その3)
Mechanizeを使う
さて、前回HTMLからデータを取り出すことはできましたが、自分のデータを持ってくるためにはeAMUSEMENTのサイトにログインする必要があります。
ここでMechanizeというライブラリを使うと、ブラウザのようにセッションを維持してログインしてから別のページに遷移することが可能になります。また、MechanizeはNokogiriのオブジェクトを返すため、Nokogiriとスムーズに連携することができます。
実際にコードを書いてみます。出力は前回と同じですので割愛します。
#! /usr/bin/ruby -Ku require "mechanize" # 前回作成した process_html 関数 require "./process_ddr_workout_html.rb" KONAMI_ID = "foobar" # 自分のKONAMI IDを指定 KONAMI_PASS = "******" # 自分のパスワードを指定 # エージェント生成 agent = Mechanize.new # ログイン agent.get("https://p.eagate.573.jp/gate/p/login.html") agent.page.encoding = "SJIS" form = agent.page.forms.first form.field("KID").value = KONAMI_ID form.field("pass").value = KONAMI_PASS agent.submit(form, form.buttons.first) # ワークアウト履歴のページを要求 agent.get("http://p.eagate.573.jp/game/ddr/ac/p/playdata/workout.html") agent.page.encoding = "SJIS" # 解析してメッセージを作成 (agent.page.root は Nokogiri::HTML::Document) message = process_html(agent.page.root, Date.today - 1) # 結果を表示 puts message
SSL証明書エラーへの対処
Windows環境で実行した場合、"certificate verify failed (OpenSSL::SSL::SSLError)" というようなエラーが出てうまく動きませんでした。
1つの方法は、証明書を無視することです。下記のコードを追加すると、証明書の検証をしなくなります。(定数を書き換えている旨の警告が出ます)
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
とりあえず動かすには良いですが、偽のeAMUSEMENTサイトが存在した場合にIDとパスワードを送ってしまうことになります。
もう1つの方法は、Ruby用に証明書をインストールすることです。下記のサイトから、cacert.pemを入手して適当なディレクトリに置きます。これはMozillaにインストールされている証明書を変換したもののようです。
次に、環境変数にSSL_CERT_FILEを追加して、cacert.pemのパスを指定します。ユーザー環境変数でも問題ないようです。
参考にした記事:
- スクレイピングのためのNokogiri利用メモ - それはそれ。これはこれ。
- エラー:OpenSSL::SSL::SSLError SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed - komiyakの通り道
- igaiga diary(2013-06-17)
これで、eAMUSEMENTのサイトから情報を取得できるようになりました。
次回はTwitterのAPIを使ってツイートする部分について書きたいと思います。
DDRで消費したカロリーを自動でツイートする (その2)
Nokogiriを使う
RubyでHTMLを解析にするにはNokogiriというライブラリが便利のようなので、これを使うことにしました。
参考にした記事:
HTMLの構造を調べる
データを取り出すために、目的のHTMLの構造を調べてみます。
丸で囲んだ部分が取り出したいデータです。
Firefoxの機能で構造を調べてみました。
idが"workout_log"のdivの下にtableがあり、その中に目的のデータが入っていることがわかりました。Nokogiri::XML::Node#xpathメソッドを使って、ドキュメントから特定のidを持つdivの下のtableの集合を取得します。
実際にローカルに保存したHTMLを解析してみました。昨日の日付のデータがなければプレー履歴がないということにします。
#! /usr/bin/ruby -Ku require "date" require "nokogiri" def process_html(doc, date) message = "" matched = false # 日付をフォーマット date_form = date.strftime("%Y-%m-%d") # テーブルを検索 table = doc.xpath("//div[@id='workout_log']/table") # テーブル内を探索 table[0].children.each do |tr| # 日付 play_date = tr.children[2].inner_text # 日付が一致する? if play_date == date_form matched = true times = tr.children[4].inner_text cal = tr.children[6].inner_text message = date_form + "にDDRを" + times + "プレーし、" + cal + "消費しました。" end end if !matched message = date_form + "はDDRをプレーしませんでした。" end return message end # HTMLを開く open("./workout.html") {|f| # Nokogiriでパース doc = Nokogiri.HTML(f) # ドキュメント内から昨日の日付のレコードを探し、メッセージを表示 puts process_html(doc, Date.today - 1) }
実行すると、下記のような結果となります。
> ruby nokogiritest.rb 2014-01-29にDDRを2回プレーし、262.25 kcal消費しました。
これで、対象のHTMLがあればツイートしたい文章を作ることができるようになりました。しかしながら、eAMUSEMENTサイトはログインが必要なので単純にopen-uriで持ってくることはできません。次回はそのあたりを書きたいと思います。
DDRで消費したカロリーを自動でツイートする (その1)
DDRと言えば何の略でしょうか?
今回の話題はSDRAMの話ではありません。十数年前に一世を風靡したあのゲーム――DanceDanceRevolutionのほうの話です。「まだ今もあるの?」という声も聞かれますが、アーケードでは去年の4月に新作がリリースされている現役機種です。
私も運動不足が気になるオトシゴロのため、1年ほど前からプレーしています。やはりゲーム性があると励みになりますね。
さて、そのDDRですが、体重を設定すると推定消費カロリーが計算され、コナミのサイトでも確認することができます。しかし、データがあるなら閲覧するだけでなく活用したくなるのがプログラマの性。HTMLからデータを抽出して、ワークアウトの履歴をツイートできないか? と思い始めました。
やりたいことを整理すると、下の3つの要素が含まれていることがわかりました。
1. や 2. を実現するには何かプログラムが必要ですが、内容からして今時のモダンな言語が適していそうです。丁度使ってみたかったのでRubyを使うことにしました。
次回から、この自動ツイートを実現するまでの道のりを書いていきたいと思います。