0
3

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.

初心者がPythonでウェブスクレイピング(3) crontab

Last updated at Posted at 2020-09-20

今回は、前回で「Yahoo!ニューススクレイピングをgoogleスプレッドシートに連携」をローカルで自動実行してみたいと思います。
自動実行にはcrontabを使います。
crontabを使えば、定期的にコマンドが実行できます。分、時、日、月、曜日で細かくスケジュールが設定できます。

crontabの使い方

主なオプション

オプション 説明
-e 編集。エディターが立ち上がってcrontabを編集できます。
-l 現在のcrontabを標準出力に表示します。
-r 現在のcrontabを削除します。

crontabのフィールド

crontabのフィールドは、分、時、日、月、曜日の5種類があり、最後に起動したい処理を記述します。

# cronの起動時間設定
 * * * * * (起動したい処理)
# | | | | |
# | | | | |- 曜日 day of week 0-7 (0 or 7 is Sunday, or use names example:"mon,wed,fri)
# | | | |--- 月 month         1-12 (or names example:"jan-mar")
# | | |----- 日 day of month  1-31
# | |------- 時 hour          0-23
# |--------- 分 minute        0-59

crontabの設定サンプル

以下、crontabの設定サンプルです。

crontab
* * * * * (起動したい処理)      # 毎分起動する
*/3 * * * * (起動したい処理)    # 3分ごとに起動する
20 * * * * (起動したい処理)     # 毎時20分
10,30 * * * * (起動したい処理)  # 毎時10分と30分(カンマ指定)
0-10 * * * * (起動したい処理)   # 毎時00〜10分に、1分毎に起動(ハイフン指定)

1 3 * * * (起動したい処理)    # 毎日3時01分
0 1,3 * * * (起動したい処理)  # 毎日1時と3時に、00分に起動(カンマ指定)
0 1-6 * * * (起動したい処理)  # 毎日1時〜6時まで、00分に起動(ハイフン指定)
0 */2 * * * (起動したい処理)  # 2時間ごとに起動する(0時、2時、4時、...)

# 0:sun 1:mon 2:tue 3:wed 4:thu 5:fri 6:sat 7:sun
0 9 * * 0 (起動したい処理)    # 毎週日曜日の午前9:00に起動
0 9 * * 1,3 (起動したい処理)  # 毎週月,水曜日の午前9:00に起動(カンマ指定)
0 9 * * 1-5 (起動したい処理)  # 毎週月〜金曜日の午前9:00に起動(ハイフン指定)

10 4 1 * * (起動したい処理)  # 毎月1日の4:10に起動
10 4 3,13 * * (起動したい処理)  # 毎月3日と13日の、4:10に起動(カンマ指定)
10 4 3-5 * * (起動したい処理)  # 毎月3〜5日の4:10に起動(ハイフン指定)

0 10 3 1 * (起動したい処理)  # 毎年1月3日の10:00に起動

(起動したい処理)の設定

次に、(起動したい処理)の設定の仕方について見ていきます。

まず、cronが動いた時間を記録するPGMを作ってテストします。

cron-test.py
from datetime import datetime

datetimestr = datetime.now().strftime("%Y/%m/%d %H:%M:%S")
print(datetimestr,'cronが動いた!')

このPGMを動かすために、通常、普通にpyがあるディレクトリに移動して、pythonを実行する時は、以下のような感じですね。

bash
% python cron-test.py

これをこのまま(起動したい処理)に記載してみます。
加えて、logはリダイレクトします。(logはユーザーのホームディレクトりに作られます。)

crontab
* * * * * python cron-test.py >> cron-test.log 2>&1
cron-test.log
/bin/sh: Applications: command not found

動きません。留意すべき落とし穴が3つあります。
①当該のディレクトリにあらかじめ移動しないと、うまく動かない。
②パスはフルパスでないと認識しない。
③cron独自にもつPATH環境変数がデフォルトだと、うまく動かない。

①当該のディレクトリにあらかじめ移動しないと、うまく動かない。

そもそもホームディレクトリで動こうとするみたいなので、正しいディレクトリに移動してから、動かしてみます。
通常コマンドと同様に、cdで実行ディレクトリに移動。;で区切ってpythonコマンドを指定します。

crontab
* * * * * cd /Users/inoken/git-repository/env2; python cron-test.py >> cron-test.log 2>&1
bash
python: can't open file 'cron-test.py': [Errno 2] No such file or directory

エラーは変わりますが、動きません。

②パスはフルパスでないと認識しない。

パスはとにかくフルパスでないと受け付けないようです。
とりあえず、pythonとpyファイルのフルパスを確認します。

bash
% which python   
/Users/inoken/git-repository/env2/env2/bin/python
% pwd
/Users/inoken/git-repository/env2
% ls -la | grep cron
-rw-r--r--   1 inoken  staff     131  9 19 17:46 cron-test.py

ディレクトリ移動した上で、さらにフルパス指定します。

crontab
* * * * * cd /Users/inoken/git-repository/env2; /Users/inoken/git-repository/env2/bin/python /Users/inoken/git-repository/env2/cron-test.py >> cron-test.log 2>&1
bash
/bin/sh: Applications: command not found

まだダメです。

ちなみにディレクトリ移動せず、pythonとpyファイルをフルパスにしても、同様に動きません。

crontab
* * * * * /Users/inoken/git-repository/env2/bin/python /Users/inoken/git-repository/env2/cron-test.py >> cron-test.log 2>&1
bash
/bin/sh: Applications: command not found

③cron独自にもつPATH環境変数がデフォルトだと、うまく動かない。

cronのenvを出力してみます。

crontab
* * * * * cd /Users/inoken/git-repository/env2; env > cron.log 2>&1

cdしてもPWDは変わってないのは不思議ですが、PATHが/usr/bin:/binにしか通っていません。

env
% cat ~/cron.log
SHELL=/bin/sh
USER=inoken
PATH=/usr/bin:/bin
PWD=/Users/inoken
SHLVL=1
HOME=/Users/inoken
LOGNAME=inoken
_=/usr/bin/env

ですので、PATHに少なくともpythonのパスを通します。
venv環境の環境変数を確認して、丸ごとパクります。

bash
% echo $PATH
/Users/inoken/git-repository/env2/env2/bin:/Users/inoken/google-cloud-sdk/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/Users/inoken/google-cloud-sdk/bin

そして、先頭にPATHを指定した後、サイクルとコマンドを指定します。

crontab
PATH=/Users/inoken/git-repository/env2/env2/bin:/Users/inoken/google-cloud-sdk/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/Users/inoken/google-cloud-sdk/bin

* * * * * cd /Users/inoken/git-repository/env2; /Users/inoken/git-repository/env2/bin/python /Users/inoken/git-repository/env2/cron-test.py >> cron-test.log 2>&1

長くて死にそうですが、仕方ありません。
PATHが塗り変わってくれて、ようやく無事動きました。

env
SHELL=/bin/sh
USER=inoken
PATH=/Users/inoken/git-repository/env2/env2/bin:/Users/inoken/google-cloud-sdk/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/Users/inoken/google-cloud-sdk/bin
PWD=/Users/inoken
SHLVL=1
HOME=/Users/inoken
LOGNAME=inoken
_=/usr/bin/env
bash
% cat ~/cron-test.log
2020/09/19 21:49:01 cronが動いた!
2020/09/19 21:50:00 cronが動いた!
2020/09/19 21:51:00 cronが動いた!

crontabでスプレイピングを自動実行

いよいよ本題。
スクレイピングのPGMを動かします。
と言っても、先ほどのテストpyファイル名を塗り替えるだけです。(log名は適宜。)

crontab
* * * * * cd /Users/inoken/git-repository/env2; /Users/inoken/git-repository/env2/bin/python /Users/inoken/git-repository/env2/requests-test2.py >> /Users/inoken/log/cron3h.log 2>&1
cron3h.log
2020/09/19 17:37:51 スクレイピングを終了しました。

スクリーンショット 2020-09-20 9.05.53.png

無事、自動実行に成功しました。

自動実行の課題

自動実行は成功しましたが、さらに難題があります。

④MacBookスリープ中は動かない。

ずっとスリープさせないのも無駄ですし、
他に何か方法はあるのかもしれませんが、難易度は高いでしょう。

1分おきや3分おきはテストは以下のようにできたとしても、それ以上大きいサイクルなどはスリープしてしまうと動かすことができません。

1分おき

bash
% cat /Users/inoken/log/cron-test.log
2020/09/19 17:50:01 cronが動いた!
2020/09/19 17:51:00 cronが動いた!
2020/09/19 17:52:00 cronが動いた!
2020/09/19 17:53:00 cronが動いた!

3分おき

% cat /Users/inoken/log/cron-test.log
2020/09/19 19:12:01 cronが動いた!
2020/09/19 19:15:00 cronが動いた!
2020/09/19 19:18:00 cronが動いた!

1日1回なら定期的にやる方法あり

ただ、1日1回なら定期的にやる方法はあります。
Macのシステム環境設定 > 省エネルギー > スケジュール で、
毎日のスリープ解除の時間を設定することができます。
スクリーンショット 2020-09-20 21.11.59.png

このスリープ解除されている時間帯にすかさずcrontabの時間を合わせて自動実行を行えば、一応実行は可能です。(スリープの設定によっては、またすぐスリープするので、夜中3:00にスリープ解除して、3:01に自動実行する、などすかさず自動実行すると良いです。)

crontab
1 3 * * * cd /Users/inoken/git-repository/env2; /Users/inoken/git-repository/env2/bin/python /Users/inoken/git-repository/env2/requests-test2.py >> /Users/inoken/log/cron3h.log 2>&1
bash
% cat /Users/inoken/log/cron3h.log
2020/09/20 03:01:29 スクレイピングを終了しました。

スクリーンショット 2020-09-20 21.22.24.png
無事に夜中の3:01に自動実行されました。

まとめ

Macでのcrontab実行にあたっての注意点
①当該のディレクトリにあらかじめ移動しないと、うまく動かない。
②パスはフルパスでないと認識しない。
③cron独自にもつPATH環境変数がデフォルトだと、うまく動かない。
④MacBookさんスリープ中は動かない。

参考サイト

0
3
0

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
0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?