天気予報 botを定期実行しよう
こんにちは、kazutoです。以前、作成した天気予報 botをcronコマンドを用いて、本格的に稼動させていきましょう。
事前準備
今回は、cronコマンドを用いて、Twitter botを定期実行させていきます。なので、天気予報 botを作成をしていない方は、下記の記事を参照をし、botを作成してから、こちらの記事を参照する事をお勧めします。
- 天気予報APIを用いて5日間の天気情報を取得しよう
- TwitterのAPIを使った天気予報botを作成してみよう
- Twitter bot プロフィール設定[拡張編]
- Twitter bot 検索機能[拡張編]
- Twitter bot 分析機能[拡張編]
なお、忙しい方は、こちらの記事からソースコードをコピペをして、初めていきましょう。
※「Twitter bot [総集編]」から始める方
Twitter APIのAPIKEYなどをTwitter Developer
にて、ご自身で取得をしてください、下記にURLを貼り付けておきます。
https://developer.twitter.com/en
定期実行するファイルを作成しよう
まずは、定期実行するファイルを作成していきましょう。また、cronが動作しているか確認をするために、cron.logファイルも、作成をしていきましょう。
touch periodic_execution.rb
touch cron.log
ls
...
periodic_execution.rb
cron.log
ファイルを作成ができたのを確認をできたら、次のステップに進みましょう。
ツイート機能を実装しよう
次にperiodic_execution.rbファイルに天気予報を取得をして、ツイートする機能を実装していきましょう。
class Wetaher
#...省略
def tokyo
@citys[0]
end
end
require"/Users/kazuto/projects/environment/wther/config.rb"
require "json"
require "open-uri"
require "csv"
require "/Users/kazuto/projects/environment/weather/weather_class.rb"
require "/Users/kazuto/projects/environment/weather/tweet.rb"
require "/Users/kazuto/projects/environment/weather/search.rb"
require "/Users/kazuto/projects/environment/weather/analysis.rb"
def today_weather_in_tokyo()
citys=CSV.read("/Users/kazuto/projects/environment/weather/citys.csv",headers: true)
weather = Wetaher.new(citys)
tokyo = weather.tokyo()
datas=weather.get_weather_forecast(tokyo)
current_time_weather=weather.current_time_weather(datas)
tweet = Tweet.new(current_time_weather)
tweet.updata()
puts "成功しました"
end
today_weather_in_tokyo()
では、ソースコードの解説をしていきます。
require"/Users/kazuto/projects/environment/wther/config.rb"
require "json"
require "open-uri"
require "csv"
require "/Users/kazuto/projects/environment/weather/weather_class.rb"
require "/Users/kazuto/projects/environment/weather/tweet.rb"
require "/Users/kazuto/projects/environment/weather/search.rb"
require "/Users/kazuto/projects/environment/weather/analysis.rb"
今回は、cronのPATHの関係上、requireメソッドでファイルを読み込むをする方法を相対パスでは無く、絶対パス
で設定しています。相対パスで設定しまうと、ファイルが読み込まれず、実行されませんので、注意をしてください。
def today_weather_in_tokyo()
citys=CSV.read("/Users/kazuto/projects/environment/weather/citys.csv",headers: true)
weather = Wetaher.new(citys)
tokyo = weather.tokyo()
datas=weather.get_weather_forecast(tokyo)
current_time_weather=weather.current_time_weather(datas)
tweet = Tweet.new(current_time_weather)
tweet.updata()
puts "成功しました"
end
今回は、東京の天気を取得をしてツイートしていきます。したがって、上記のメソッドを定義をしました。では、解説をしていきます。
citys=CSV.read("/Users/kazuto/projects/environment/weather/citys.csv",headers: true)
まずは、CSVファイルを読み込む、都市を取得をします。
weather = Wetaher.new(citys)
次に、Wetaherクラスのインスタンスを生成をします。
tokyo = weather.tokyo()
東京の詳細情報を取得をします。
datas = weather.get_weather_forecast(tokyo)
get_weather_forecastメソッドを用いて、OpenWeatherMapにGETリクエストを送り、レスポンスとして、天気情報を取得をしています。
current_time_weather=weather.current_time_weather(datas)
current_time_weatherメソッドを用いて、現在時刻に最も近い、観測時間の天気情報のみを抽出をしています。(現在時刻以降)
tweet = Tweet.new(current_time_weather)
次に取得した天気情報が格納されている変数current_time_weatherを引数に渡して、Tweetクラスのインスタンスを生成をします。
tweet.updata()
最後にupdateメソッドを呼び出して、ツイートをします。
以上で、ツイート機能の実装は終了になります。以前、作成したメソッドを再利用する形で実装をしたので、とてもシンプルに機能を追加をできました。では、実際にツイートができるのか確認をしておきましょう。
ruby periodic_execution.rb
上記の画像の通り、ツイートができたら、次のステップに進みましょう。
cronコマンドで定期実行を行う時間を設定しよう
periodic_execution.rbファイルが作成できたので、cronコマンドの設定を行っていきましょう。
- cronコマンドとは
- cronを使える様にしよう
- vimを用いて、crontabファイルに時間を設定しよう
cronコマンドとは
cronコマンドとは、定時実行のスケジュール管理を行うために用いられるコマンド
です。また、crontabファイルという、コマンドの定時実行のスケジュール管理を行うために用いられるファイル内に、
- PATH
- 実行させたい時間
- 実行させたいコマンド
- 実行させたいファイル
を設定していきます。
まあ、要するにcronコマンドを用いて、crontabファイル内に記述されているジョブを実行していく
という事です。なお、注意点として、PCがスリープモードなどPC が起動していない状態で、cronコマンドは、実行できませんので注意をしてください。(一時期にスリープモードを解く設定を行えば大丈夫です。)
cronを使える様にしよう
では、cronコマンドを使える様にしていきましょう。まずは、whichコマンドを用いて、cronコマンドが保存されている、ディレクトリを探しましょう。
which cron
/usr/sbin/cron
おそらく、/usr/sbin/cronと出力がされると思います。
次にmacの環境設定を開き、「セキュリティとプライバシー」を開き、鍵マークをクリックをし、パスワードを入力をして鍵を開きましょう。その後、「フルディスクアクセス」という項目を選択をして、+ボタンをクリックをしてください。
+ボタンをクリックをしたら、上記の画面が出てきます。
Command Shift G
上記、3つのキーを同時に押してください。その後、「フォルダの場所を入力:」というポップアップが出てくると思いますので、検索フォームにcronコマンドのパスを入力をしましょう。
cronコマンドが見つかったら、開くをクリックをしましょう。
開くをクリックをしたら、「セキュリティとプライバシー」という項目が表示されている画面上に戻ってきます。cronコマンドにチェックマークが記載されているのが、確認ができると思いますので、鍵マークをクリックをして、鍵を閉じましょう。
以上で、「cronを使える様にしよう」の解説を終了します。
今回、何の設定をしたのか、疑問に持たれると思いますので、簡単に説明をしておきます。簡単に解説をすると、cronコマンドを全てのファイルで使える様にする設定を行いました。
vimを用いてcrontabファイルに時間を設定しよう。
cronコマンドの設定が完了をしたら、次にvimを用いて、crontabファイルにジョブをセットをしていきましょう。
crontab -e
crontabコマンドに-eをオプションを付け足す事により、crontabファイル内で作業を行える様になります。
#文字コード(自分の環境に合わせる)
LC_CTYPE=ja_JP.utf8
LANG=ja_JP.utf8
#OpenWeatherMap API
WEATHER_API_KEY='(APIKEY)を入力'
WEATHER_URL='http://api.openweathermap.org/data/2.5/forecast'
#twitter API
CONSUMER_KEY ='(APIKEY)を入力します'
CONSUMER_SECRET='(APIKEYSECRET)を入力します'
ACCESS_TOKEN ='(ACCESSTOKEN)を入力します'
ACCESS_TOKEN_SECRET ='(ACCESSTOKENSECRET)を入力します'
PATH=/Users/kazuto/opt/anaconda3/bin:/usr/local/opt/mysql@5.6/bin:/Users/kazuto/.rbenv/shims:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
#(分) (時) (日) (月) (曜) 実行したいコマンド
1 9 * * * ruby -Ku /Users/kazuto/projects/environment/weather/periodic_execution.rb >> /Users/kazuto/projects/environment/weather/cron.log 2>&1
では、解説をしていきます。
#文字コード(自分の環境に合わせる)
LC_CTYPE=ja_JP.utf8
LANG=ja_JP.utf8
まずは、文字コードを設定をします。僕の場合、crontabファイルの環境とローカル環境で使われている文字コードが違ったため、上記の様に文字コードの設定を行っています。(ご自身の環境に合わせてください。)
#OpenWeatherMap API
WEATHER_API_KEY='(APIKEY)を入力'
WEATHER_URL='http://api.openweathermap.org/data/2.5/forecast'
#twitter API
CONSUMER_KEY ='(APIKEY)を入力します'
CONSUMER_SECRET='(APIKEYSECRET)を入力します'
ACCESS_TOKEN ='(ACCESSTOKEN)を入力します'
ACCESS_TOKEN_SECRET ='(ACCESSTOKENSECRET)を入力します'
次に各種、環境変数の設定を行っていきます。crontabファイルは、少し特殊で、.zshrcファイルが読み込まれません
。つまり、以前、設定した環境変数は、読み込まれないままperiodic_execution.rb ファイルを実行してしまい、認証に失敗してしまいます。(Twitter API)したがって、.zshrcファイルと同じ環境をcrontabファイルでも再現をします
(必要な部分のみ)。
#OpenWeatherMap API
WEATHER_API_KEY='(APIKEY)を入力'
WEATHER_URL='http://api.openweathermap.org/data/2.5/forecast'
まずは、OpenWeatherMap APIの設定を行いましょう。.zshrcファイルからコピペをして設定をしてください。
#twitter API
CONSUMER_KEY ='(APIKEY)を入力します'
CONSUMER_SECRET='(APIKEYSECRET)を入力します'
ACCESS_TOKEN ='(ACCESSTOKEN)を入力します'
ACCESS_TOKEN_SECRET ='(ACCESSTOKENSECRET)を入力します'
次にtwitter APIの設定を行いましょう。.zshrcファイルからコピペをして設定をしてください。
PATH=/Users/kazuto/opt/anaconda3/bin:/usr/local/opt/mysql@5.6/bin:/Users/kazuto/.rbenv/shims:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
次にPATHを設定をしていきましょう。PATHも、.zshrcファイルが読み込まれていない関係上、PATHも通っていません。以下のコマンドを実行してください。
echo $PATH
/Users/kazuto/opt/anaconda3/bin:/usr/local/opt/mysql@5.6/bin:/Users/kazuto/.rbenv/shims:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
echoコマンドを実行すると、あなたの環境に設定されているPATHを取得する事ができます。実行結果をコピペをして、crontab ファイルに貼り付けておきましょう。
#(分) (時) (日) (月) (曜) 実行したいコマンド
1 9 * * * ruby -Ku /Users/kazuto/projects/environment/weather/periodic_execution.rb >> /Users/kazuto/projects/environment/weather/cron.log 2>&1
次にジョブを設定をしていきましょう。
#(分) (時) (日) (月) (曜)
1 9 * * *
上記は、毎朝9時01分に実行となります。左から分、時、月、曜とジョブを実行する時間を設定できます。
-Ku
-kuとする事でUTF-8という文字コードに指定をしています。
/Users/kazuto/projects/environment/weather/periodic_execution.rb >> /Users/kazuto/projects/environment/weather/cron.log 2>&1
こちらは、periodic_execution.rbファイルを実行した結果の標準出力と標準エラー出力の追加出力を行っています。
“>>”と記述する事で、指定したファイルの末尾にログを追加する事ができます。
“2>&1″は、標準エラー出力を標準出力に流すという意味です。つまり、エラーログと実行結果(periodic_execution.rb)をcron.logというファイルにまとめて出力
をするという事です。
概要については、下記の表を参照してください。
識別番号 | 名称 | 概要 |
---|---|---|
0 | 標準入力 | 入力した内容(コマンド) |
1 | 標準出力 | コマンドを実行したときに画面に表示されるもの |
2 | 標準エラー出力 | エラーが発生したときに表示されるエラーメッセージ |
※識別番号について
OS(Linux)が入出力を識別するための番号。この識別番号を用いて、ファイルにログを書き込んでいきます。この様な識別子の事をファイルディスクリプタ
と言います。
echo Hellow world !! > Test.txt
cat Test.txt
Hellow world !!
通常、コマンドを実行してエラーが起きなかった場合は、標準出力(1)の結果をファイル内に書き込みます。
ls ccc > Test.txt
ls: ccc: No such file or directory
cat Test.txt
何も出力されない...
逆にコマンドを実行してエラーが起きた場合は、標準エラー出力(2)がされますが、ファイルに書き込まれません
。
ls ccc 2>Test.txt
cat Test.txt
ls: ccc: No such file or directory
では、次に標準エラーをファイルに書き込んでみましょう。lsコマンドのファイル指定の次に2と「標準エラー」を表す記述を追加をしましょう。catコマンドでファイルの中身をみてください。エラー内容が書き込まれているのがわかると思います。
上記の一連の流れから、コマンドを実行する際は、識別番号を設定しなくとも、デフォルトで「標準出力(1)」である事がわかります。
> 上書き追加
& ビット単位でのAND
1 標準出力
2 標準エラー出力
[x]>&[y]
[x]>&[y]が与えられると、xで示されるファイル記述子は、
出力ファイル記述子yのコピーになります。
2>&1
2で示されるファイル記述子は、
出力ファイル記述子1のコピーになります。
/Users/kazuto/projects/environment/weather/cron.log 2>&1
したがって、”2>&1″と記述をする事で、標準出力 と標準エラー出力 の両方を、 cron.logファイルに追加できます。
以上で、「vimを用いてcrontabファイルに時間を設定しよう。」の解説は終了になります。ここまで、実装ができたのなら、毎朝09:01にあなたが作成をした、天気予報 botが東京の天気情報を自動でツイートをしてくれます。では、最後のトピックで、時間を変更をして、定期実行をしてくれるかを試してみましょう。
天気予報bot 起動をしよう
では、crontabファイルの時間の設定を変更をして、天気予報 botを起動をしてみましょう。
crontab -e
#before
1 9 * * * ruby -Ku /Users/kazuto/projects/environment/weather/periodic_execution.rb >> /Users/kazuto/projects/environment/weather/cron.log 2>&1
#after
*/1 * * * * ruby -Ku /Users/kazuto/projects/environment/weather/periodic_execution.rb >> /Users/kazuto/projects/environment/weather/cron.log 2>&1
:wqをして保存をしておきましょう。
crontabの設定を変更後、ご自身が作成したアカウントでツイートができているのを確認をしてください。ツイートを確認ができたらbotの定期実行に成功した事になります。
またcron.logファイルに「成功」と出力されているのを確認をしておきましょう。
以上で、「天気予報 botを定期実行しよう」の解説を終了します。今回は、ソースコードを書いていくよりも、 Linuxコマンドを実行する方が多かった気がします。
まとめ:天気予報 botを定期実行しよう
今回は、天気予報 botをcronコマンドを用いて、定期実行させていきました。実行する時間をセットできるのは、とても便利なコマンドだと思います。この定期実行という機能を他のAPI、サービスを用いれば、下記の事ができると思います。
- 毎朝、LINE(LINE Notify)に天気情報を通知をする
- 9時、15時、18時にYoutube APIを用いて、任意なキーワードに対して、再生回数が多い、上位3動画を集計をし、CSVファイルまたは、スプレッドシート(google)に書き込む。
- 定期的にニュースサイトに対してスクレイピングをする。
- 定期的にRSSから更新情報を取得をし、更新があれば、gmailに更新情報を送信をする。
などです。結構、簡単に実現ができそうです。時間があれば試してみても良いかもしれません。
以上、kazutoでした。