読者です 読者をやめる 読者になる 読者になる

Rubyを使って、アルクマスケジュールをGoogleカレンダーへと登録する

Google Ruby

昨年、GoogleAppEngineとGoogleAppsScriptなどを使い、アルクマスケジュールでいろいろと試してみていました。


ただ、アドベントカレンダー用に急ごしらえで作った部分もあり、正直12月以降についてはあまり考慮していなかったため、残念な部分が残っていました。
そのため、アルクマスケジュールをGoogleカレンダー化する部分を、Rubyを使って改良してみました。


なお、Googleカレンダーへ登録する際は、削除後の新規登録としています。
また、以前作ったアプリに対応させるためだけを目的として作ったため、イベントの開始・終了時刻があるものも終日の予定としています。



■環境


他には、Google Calendar API を有効化し、「CLIENT ID」などの認証キーを取得しておきます。詳しくは前回の記事を参照して下さい。
Windows7 + Ruby + google-api-clientで、GoogleAPI向けOAuth認証用のYAMLファイルを取得する - メモ的な思考的な



ソースコードと使い方

今のところ、コマンドラインから実行するようになっています。
thinkAmi/arukuma2gcal · GitHub



■調べたことなど

ジオコーディングについて

今回もジオコーディングはGoogle Geocoding APIを使用することにしました。APIをそのまま使っても良かったのですが、他のジオコーディングAPIを呼べそうなgemの「geocoder」があったため、そちらを使うことにしました。
ただ、連続してGoogle Geocoding APIを呼び出すと制限に引っかかるため、呼び出しは1秒に1回としています。


以下のような感じで使っています。

Geocoder.configure(lookup: :google, language: :ja, timeout: 5)

geo_params = {
  countrycodes: 'ja'
}

begin
  result = Geocoder.search(place, params: geo_params)

  if result.size > 0
    result.first.coordinates.join(',')
  else
    DEFAULT_LAT + ',' + DEFAULT_LNG
  end
rescue Exception => e
  puts $!
  DEFAULT_LAT + ',' + DEFAULT_LNG
end


なお、緯度経度を取得していろいろとやるには、Geocoder.searchの戻り値(result)を

result.first.coordinates.join(',')

のようにGeocoder::Result::Google#coordinatesメソッドを使って取得するか、

result.first.geometry["location"]["lat"].to_s + ',' + result.first.geometry["location"]["lng"].to_s

のようにハッシュから取得します。


Geocoder.searchの結果は以下が参考になりました。
Ruby geocoderがすごい - もぎゃろぐ



スクレイピングについて

「nokogiri」gemを使いました。
なお、アルクマスケジュールを確認すると、前後に改行コードやスペースが入っていることが多かったため、以下のように改行やスペースを消すようにしました。

item.xpath(xpath).text.gsub(/(\r\n|\r|\n)/, '').strip
カレントディレクトリのrequireについて

「require_relative」を使って読み込みました。
Ruby1.9.2以降でrequireする際の注意点 - Qiita
Rubyのrequireで相対的にパスを指定する方法 - QA@IT



一件目の削除について

今回の作り方だと、一件目にタイトルが入ってくるため、dropメソッドを使って削除しました。

@doc.xpath('//div[@class="schedule aug"]/table/tr').drop(1).each do |item|
  # hoge
end

How to act differently on first iteration in a Ruby loop? - Stack Overflow



google-api-clientにアプリ名とバージョンを渡す

渡さないとワーニングが出たため、、適当なものを渡しました。
google-api-clientのコマンドライン版でも、アプリ名などを渡しているようです。
https://github.com/google/google-api-ruby-client/blob/master/bin/google-api#L166



Events#listについて

日付については、今のところは以下を参考にUTCのISO8601形式で設定します。
[Ruby]Google Calendar APIでカレンダーを取得するスクリプト - Blogaomu


以下のIssueが閉じられれば、今後やり方が変わるかもしれません。
When providing parameters to execute(), + is replaced by space · Issue #38 · google/google-api-ruby-client · GitHub


また、以下のパラメータも追加しています。

  • singleEvents: このパラメータが無いと、手元のカレンダーでは取得できるイベント数が不定になっていた
  • maxResults: デフォルト値が不明なので、取得する件数を確実にするため*1
  • showDeleted: 削除したイベントを取得しないと明確にするため

Events: list - Google Calendar API — Google Developers



*1:300件/月のイベントは、さすがに無いはず...