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のパスを指定します。ユーザー環境変数でも問題ないようです。

参考にした記事:

これで、eAMUSEMENTのサイトから情報を取得できるようになりました。
次回はTwitterAPIを使ってツイートする部分について書きたいと思います。

DDRで消費したカロリーを自動でツイートする (その2)

Nokogiriを使う

RubyでHTMLを解析にするにはNokogiriというライブラリが便利のようなので、これを使うことにしました。
参考にした記事:

HTMLの構造を調べる

データを取り出すために、目的のHTMLの構造を調べてみます。
f:id:shimazakky:20140130013046p:plain
丸で囲んだ部分が取り出したいデータです。
Firefoxの機能で構造を調べてみました。
f:id:shimazakky:20140130013137p:plain
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. コナミのサイトからワークアウト履歴のページを取得し、HTMLを解析してデータを抽出する。
  2. 抽出したデータをTwitterAPIを使ってツイートする。
  3. 一日一回定期実行する。

1. や 2. を実現するには何かプログラムが必要ですが、内容からして今時のモダンな言語が適していそうです。丁度使ってみたかったのでRubyを使うことにしました。

次回から、この自動ツイートを実現するまでの道のりを書いていきたいと思います。

ブログ開設しました

はじめまして。shimazakkyと申します。

技術的なものごとを公開する場が欲しくなり、数年ぶりにブログを書くことにしました。

手短に自己紹介をしますと、とあるSIerで組み込みソフトエンジニアをしています。言語はC/C++が中心ですが、最近はC#も使っています。

組み込み屋をやっているのでデジタル回路やHDLに関心を持っていますが、ほとんど何もやっていません。

マイペース更新ですが、よろしくお願いします。