11
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RAdvent Calendar 2015

Day 11

TokyoRのATNDを監視してメールを送るツールを作ってみた

Posted at

TokyoRのATNDを監視してメールを送るツールを作ってみた

動機

ほぼ毎月開催されている「R勉強会@東京(#TokyoR)」は人気が高く、ATNDに参加募集があがってから2〜3日で定員を超えてしまうこともしばしばです。

twitterのタイムラインをチェックする、ハッシュタグ#TokyoRのツイートをチェックする、ATNDの検索ページをブックマークしておいてちょくちょく検索してみる、などをしていれば問題なく参加登録できますが、根が面倒くさがりなもので、「ATNDをチェックして、最新の開催情報を自分にメールする仕組み」が欲しくなりました。

「欲しいものは作れ」という声が聞こえた気がするので自分で作ってみます。

材料

  • Rスクリプト(自作)
  • mailgunアカウント(フリー)←自由に踏めるメールサーバーがある人は不要
  • herokuアカウント(フリー)

手順

ATNDからの情報取得方法を決める

ぱっと思いついたのはATNDのAPI(http://api.atnd.org) を使うことです。
キーワード「tokyor」を含むイベントのうち最新のものは以下のクエリで取得できます。
http://api.atnd.org/events/?keyword=tokyor&count=1
なお、デフォルトでは結果はxmlで戻ってきます。formatオプションでjsonも指定できます。
http://api.atnd.org/events/?keyword=tokyor&count=1&format=json

Rスクリプト(前半)を書く

まずは手元のMacで動くRスクリプトを書いてみます。

{curl}{jsonlite}を使います。

library(curl)
library(jsonlite)
con <- curl("http://api.atnd.org/events/?keyword=tokyor&count=1&format=json")
df <- fromJSON(readLines(con, warn = FALSE))$events$event
bodymessage <- paste(substr(df$started_at, 1, 10), df$title, df$event_url, sep = " ")

bodymessage
# 2015-10-10 第51回R勉強会@東京(#TokyoR) http://atnd.org/events/70522

xmlでもやってみました。
R Advent Calendar 2014の7日目にdichika氏が投稿された「R Advent Calendar 2014に記事が追加されたらメールが届くようにした(http://d.hatena.ne.jp/dichika/20141207) 」を参考に書いていきます。
html()はdeprecatedだからread_xml()使えと言われたりhtml_node()xml_node()もdeprecatedだ{xml2}を使えと言われたりして苦しみながらなんとか書き上げました。xmlから中身を取り出すのは初めてなので、もっとスマートなやり方があるのかもしれません。

#devtools::install_github("hadley/rvest")
library(rvest)
result <- read_xml("http://api.atnd.org/events/?keyword=tokyor&count=1") %>%
  xml_children() %>%
  xml_children() %>%
  xml_children() %>%
  xml_text()

bodymessage <- paste(substr(result[6], 1, 10), result[2], result[5], sep = " ")

今回私は{curl}{jsonlite}を使う方でいきます。

Rスクリプト(後半)を書く

後半のスクリプトはほぼ先ほどのdichika氏の記事から丸ぱくりです。
ただ、私の環境ではgmailをsmtpサーバーとして使おうとすると認証がうまくいきませんでした。
そこで、send.mail()のヘルプに出ている、認証を使わない方法

send.mail(from = "foo@gmail.com",
          to = "foo+test@gmail.com",
          subject = "最新TokyoR開催情報",
          body = message,
          smtp = list(host.name = "aspmx.l.google.com", port = 25),
          authenticate = FALSE,
          send = FALSE)

にしてみたところ、うまくはいきますが、gmailから「送信元偽装してるな。お前フィッシングだろ」と目をつけられます。このスクリプトを繰り返し実行していると、googleから迷惑メール送信アカウントとしてマークされてしまうかもしれません。

それはいやなので、アプリからのメール送信に使えるサービスを探したところ、mailgun (https://mailgun.com) というサービスがありました。フリーのアカウントで月間1万通まで無料でメールを送信できます。APIでの利用が推奨されていますが、smtpでの送信も可能です。登録も簡単です。mailgunやgmailに頼らなくても自由に使えるメールサーバーを持っているかたはどうぞそちらをお使いください。

#install.packages(mailR)
library(mailR) # Java6SE runtimeが無いと突然落ちるので注意
send.mail(from = "postmaster@sandboxxxxx.mailgun.org",
          to = "my@address.com",
          subject = "最新TokyoR開催情報",
          body = bodymessage,
          encoding = "utf-8",
          html = FALSE,
          smtp = list(host.name = "smtp.mailgun.org", 
                      port = 465, 
                      user.name = "postmaster@sandboxxxxx.mailgun.org",
                      passwd = "xxxxxx", 
                      ssl = TRUE),
          authenticate = TRUE,
          send = TRUE,
          debug = FALSE) # うまく動かないときはここをTRUEにする

dichika氏のソースにはlibrary(mailR)のコメントに「Java runtimeが無いと突然落ちるので注意」と書いてありました。私のMacにはJava8のruntimeが入っているので大丈夫だろうと思ってスクリプトを実行したら、いきなり落ちました。Java6SEが必要だそうです。ちょっとだけコメントを修正しました。

Macの場合はここ(https://support.apple.com/kb/DL1572) からDLします。

herokuアプリとして登録する

heroku (https://www.heroku.com) は手軽に使えるPaaSのひとつです。rubyやpythonでの利用が普通ですが、サードパーティのbuildpackageを使うことでRでも使えます。

herokuでRを動かすためのbuildpackageはこちら(https://github.com/virtualstaticvoid/heroku-buildpack-r) です。readmeも丁寧ですしサンプルプログラムも豊富なので、使い方の説明は割愛します。
私がはまったのは1つだけ。パッケージをインストールするためのinit.rをinit.Rとしていて、それが原因でgit push heroku masterがうまくいかなかったのですが、ログからはそれが読み取れなくて悩みました。

init.r : パッケージインストール部分

install.packages("curl", repos = "http://cran.rstudio.com")
install.packages("jsonlite", repos = "http://cran.rstudio.com")
install.packages("mailR", repos = "http://cran.rstudio.com")

whenTokyoR.R:メイン

Sys.setlocale("LC_ALL", "ja_JP.UTF-8") # これを入れないと漢字が消える

library(curl)
library(jsonlite)
con <- curl("http://api.atnd.org/events/?keyword=tokyor&count=1&format=json")
df <- fromJSON(readLines(con, warn = FALSE))$events$event
bodymessage <- paste(substr(df$started_at, 1, 10), df$title, df$event_url, sep = " ")

library("mailR") # Java6SE runtimeが無いと突然落ちるので注意
send.mail(from = "postmaster@sandboxxxxxxx.mailgun.org",
          to = "my@address.com",
          subject = "latest TokyoR event",
          body = bodymessage,
          encoding = "utf-8",
          html = FALSE,
          smtp = list(host.name = "smtp.mailgun.org", 
                      port = 465, 
                      user.name = "postmaster@sandboxxxxxxx.mailgun.org",
                      passwd = "xxxxxxxxxxx",
                      ssl = TRUE),
          authenticate = TRUE,
          send = TRUE,
          debug = FALSE) # うまく動かないときはここをTRUEにする

スクリプトを入れたフォルダーで以下を実行します。

$ git init
$ git add . 
$ git commit -m 'init'
$ heroku create --stack cedar-14 --buildpack https://github.com/virtualstaticvoid/heroku-buildpack-r.git#cedar-14
$ git push heroku master

deployの際にinit.rで指定したパッケージがインストールされます。5分位待って、deployが完了したら、以下のコマンドでスクリプトを実行してみます。

$ heroku run R -f ./whenTokyoR.R --gui-none --no-save

指定したアドレス(上のサンプルではmy@address.com)あてにメールが届いたら成功です。

定期的にスクリプトを実行する

ここまででは、まだスクリプトは手動で実行する必要があり、うれしくありません。手動でスクリプトを流すんなら、ブラウザでブックマークを開いたほうが楽チンです。

幸い、herokuには定期的に処理を流すオプション(add-on)があります。
アプリの管理画面上でResourcesタブを選択し、Add-ons欄で Heroku Scheduler を追加します。

Heroku Schedulerの設定画面で R -f ./whenTokyoR.R --gui-none --no-saveをセットし、FrequencyをDaily,Hourly,Every 10 minutesから選択して保存したら完了です。指定した間隔で処理が流れ、メールが飛んできます。

今後の課題

更新がないのに延々と同じ内容のメールが来るのもうざいので、前回の結果を覚えておき、更新があったときだけメールを飛ばすようにしたいです。

今日はここまで。
Enjoy!!

11
13
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?