hagetak's blog

どうも、はげたかです。

今日の一言:カテゴリ分けをしっかりしたらPVあがるかな?

rubyとcrontabで毎朝、休講情報を取得するプログラムを作成した話

はじめに

私は、学内アルバイトとして、TA(Teaching Assistant)をしている。基本的な業務は、簡単なエクセルの使い方やワードの使い方などを教えている。 しかし、TAは、授業を履修していないため、休講情報が全く来ない。

ちょっとムカついたので、自動で休講情報を取得しようと考えた。

f:id:hagetak:20150607175041j:plain

ロジック

--- ruby ---

  1. 外部からアクセス可能(basic認証)なウェブサイトの休講情報を取得する
  2. 整形させる
  3. 当日の休講情報を抽出/出力

crontabで、上記のプログラムを毎朝実行し、メールする。 これらを、ウェブサービスを公開するために借りたVPSにおいておく。

書いてみた。

require 'nokogiri'
require 'mechanize'

agent = Mechanize.new
agent.add_auth('http://www.gakkounowebsite.info/', 'userid', 'password')
@page = agent.get('http://www.gakkounowebsite.info/?page_id=1028')

@content = @page.search('.entry-content')

@class_datas = []

# 検索用 => "6月12日"という文字列を検索するために
b = Time.now
@today = "#{b.month}#{b.day}"

# <p>6月12日 情報倫理<br>\n 教室:1201教室... </p>
# <p>6月12日 財務諸表<br>\n 教室:1203教室... </p>
# => ['6月12日 情報倫理...', '6月12日 財務諸表']
@content.xpath("//p").each do |c|
    @class_datas << c
end

a = []
@sending_datas = []
# [0] => date
# [!0] => className, teacher, remarks
# @class_datas[0] => "6月22日(月)\n 2限:情報演習・基礎 \n 担当:斉藤先生 \n 補講:課題指示あり"
# a[0] => ["6月22日(月)", "2限:情報演習・基礎", "担当:斉藤先生", "補講:課題指示あり"]
@class_datas.each do |info|
    a << info.text.split("\n")
end

# 本日休講の項目を取得
a.each do |s|
    s[0].tr!("0-9", "0-9")
    @sending_datas << s if(s[0].to_s.match(@today))
end

puts '休講情報はありません' unless @sending_datas
@sending_datas.each do |s|
    puts '*** ' * 10
    puts s
end

今こうしてみると、読みづらく、気持ち悪いね。整形作業に手間がかかってる感じ。もう少し簡単にできないだろうか...。

crontabの設定

crontabについて学んだことは、後日記事にする。 さて、このプログラム(fetch_class_info.rb)をcrontabで動かしたいと思う。

いかのプログラムを書いて、動かしている。

35 7 * * * /home/hagetak/.rbenv/shims/ruby  /home/hagetak/cron/fetch_class_info.rb | mail -s `echo $(date +'\%Y/\%m/\%d')休講情報` your_email_address@domain.com

一つ一つ見てみると、わかるだろう。

minites hour * * * [実行するプログラム]

という感じで、この例では、毎日7時35分に実行するプログラムだ。所有者・実行者が違うと、PATHが通っていない可能性があるので、絶対参照でプログラムを実行させることにした。

実行させたい大本のプログラム(ruby だったり, pythonだったり...)は、whichコマンドで確認することができる。

> which ruby 
  => /home/hagetak/.rbenv/shims/ruby

ruby yourprogram.rb

で実行できるので、rubyファイルは絶対参照で記述。

次のステップは、少しややこしい。(件名を日本語/変更したくない場合はこの処理は飛ばして良い)

mail -s echo $(date +'\%Y/\%m/\%d')休講情報 your_email_address@domain.com

実行した結果を mail コマンドに受け渡し、送信するというモノだ。

echo $(date +'\%Y/\%m/\%d')休講情報

これは、いつの休講情報かわからないために追加したもの。

crontabのshに問題があるため、dateコマンド内の%はバックスラッシュでエスケープすること

この処理で引っかかって、1日ずっと考えていた...。

dateコマンド と crontab の コマンドライン中の %(パーセント)記号 - keigoiの日記

さて、これらをまとめると、以下に置き換えられるだろう。

result of your program | mail -s "件名" your_email_address@domain.com

cron処理結果を、subjectを日本語にしてメールする方法 | Web開発者の備忘録

知見

  • いきなり毎朝...で設定すると気が遠くなるので、以下に変更すると良い(毎分)

*/1 * * *

  • メールが届かない!ってときは、次のコマンドを打つと出ている

mail

  • 件名とかいらない。ってときは簡略なものでできる
MAILTO="your_email_address@domain.com"

*/2  *  *  *  * /usr/bin/ruby /Users/hagetak/cron/fetch_class_info.rb