Macのcronでpython fileを実行 (print, csv fileの出力, seleniumによるwebbrowserの起動)

hello cron_crontab -e データサイエンティスト

MacでPythonのウェブスクレイピングを定期的に行うための準備として、Macのcronでpython fileを実行 するための設定を行いましたので備忘録として以下に示します。

Macのcronでpython fileを実行

まずはcronを実行してpythonを実行して’hello cron’と表示させるようにします。

Pythonについては以下の記事で広く学習方法などをまとめているので興味がある人は参照してみてください。

機械学習を理解するために Pythonを独学で学ぶ
この記事では、プログラミング初心者が人工知能を学ぶために、まず「 Pythonを独学で学ぶ 」ことを目的とした記事です。 はじめは「Pythonって何? 蛇?」というレベルでしたが、人工知能を学ぶ上でどのようにしてこの「Python」...

pythonのコードを以下のように記述します。

print('hello cron')

私はJupyter labを用いているので、Jupyter labでipynb形式で作成し実行可能か確認したのちに、以下の手順で「.py」形式のファイルをexportし’hello-cron.py’と名前をつけて保存します。

export .py from jupyter lab

ターミナルを起動し、cronを実行するためにターミナルに「crontab -e」と入力しEnterで設定を行います。するとvim/viが立ち上がるので以下のコマンドの通り操作を行います。

# cronの編集
crontab -e

# macでvim/viの編集・ターミナルに戻る方法
## 編集開始は「i」を押すことで左下に--insert--と表示されて入力できるようになる。

## 入力後「esc」でコマンド入力モードに変更
## 保存してから終了する場合
:wq

## 保存せずに終了する場合
:q!

crontab -eで入力するコマンドは以下の通りで、「毎分’hello-cron.py’を実行する」というコマンドです。またこのpythonファイルでは「print()」を実行させますが、この結果はターミナル上で「’mail’」コマンドを実行しないと見れないので、実行コマンドの後ろに

‘>> /Users/mark/Desktop/cron_error.txt 2>&1’

と入力します。このように記載することでデスクトップに「cron_error.txt」というlog fileを作成することができます。

* * * * * python3 /Users/mark/Desktop/hello-cron.py >> /Users/mark/Desktop/cron_error.txt 2>&1

実際にターミナル(vi)での表示は以下のようになります。

hello cron_crontab -e

無事に保存されると以下のようにシステムメッセージとターミナル中に「installing new crontab」と表示されます。

crontab -e save

デスクトップに「cron_error.txt」というファイルが作成されているのでそちらを確認すると、定期的に実行しようとしていますが、'[Errno 1] Operation not permitted’とエラーlogが表示されております。

show cron_error_fail

こちらはcronがこのpython fileを実行するための権限を有していないために起こるエラーです。cronに権限を持たせるために、左上のappleマークから「システム環境設定」→「フルディスクアクセス」→「鍵をクリック」→「+マークをクリック」

 

その後以下の通り設定を行うことでcronからの実行が可能となります。

再び「cron_error.txt」ファイルを開くと今度はしっかりとpython fileが実行されて「’hello cron’」と出力されていることを確認できました。

show cron_error_success

cronの起動でcsv fileを作成・保存する to_csv.py

次に以下のpython fileを「test.py」として用意して、「pandas dataframeの作成」および「dataframeからcsv作成」を行います。前回の例と同様の手順で以下のpython fileを作成し「to_csv.py」としてデスクトップに保存します。

import pandas as pd
board_df = pd.DataFrame({ 'col1' : [1,2,3], 'col2' : [3,4,5]}) 

# csv形式にfile保存、日本語は文字化けするのでencodingを指定します 
import datetime as dt
now = dt.datetime.now()
time = now.strftime('%Y%m%d-%H%M%S')
board_df.to_csv("/Users/mark/Desktop/test_{}.csv".format(time), encoding='utf_8_sig') 

# folder path: /Users/mark/Desktop/はご自身のpathに合わせて変更ください

これをcrontab -eで実行するには以下のように記述します。

そして、実行結果をcron_error.txtで確認すると「ModuleNotFoundError: No module named pandas」と表示されてしまいます。

この原因としてはcronの環境変数がpythonの実行環境と一致していないために生じるエラーであり解決方法として、以下の2つが考えられます。

  1. cronにpython実行時の「PATH」を指定
  2. cronの実行環境にmoduleをインポート

PATHを通す

まずはターミナルで以下のコマンドを入力しPython3のPATHを確認しましょう。すると「/usr/local/bin/python3」であることがわかりました。これをcrontab -eでPATHとして指定します。

# python3のパスの確認 
$ which python3 
>> /usr/local/bin/python3

私の場合には上記のPATHの指定方法だと、「/bin/sh: python3: command not found」のエラーが出てしまったため、以下の表記方法でPATHの指定を試みました。

しかしこの方法でもlog fileに「ModuleNotFoundError: No module named pandas」のエラー表示が出てしまいました。

そこで以下の複数のPATHを設定することでcronの実行をターミナルでの実行環境と同じとすることができます。

PATH=/home/mark/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
# 'mark'はuser nameなのでご自身のものに変更してください

しかし、この時点ではまだ「ModuleNotFoundError: No module named pandas」のエラーが出ておりました。この原因は私が普段Jupyter Lab環境でPythonを使っていたことでした。

Jupyter Lab (Anaconda)環境でのmoduleインストール先確認

色々と調べてみて分かったのですが、私が普段実行環境として用いているのはJupyter Lab (Jupyter notebook)であり、pandasなどのmoduleはjupyter lab中で’!pip install’で入れておりました。

Pythonのimport文で標準ライブラリやpipでインストールしたパッケージをインポートするときに探索されるパス(ディレクトリ)をモジュール検索パス(Module Search Path)と呼び、importの対象となるディレクトリのパスであるモジュール検索パスをJupyter Labを用いて以下の’sys’で確認してみました。

より詳細には以下のサイトを参照ください。

Pythonでimportの対象ディレクトリのパスを確認・追加(sys.pathなど) | note.nkmk.me
Pythonのimport文で標準ライブラリやpipでインストールしたパッケージ、自作のパッケージなどをインポートするときに探索されるパス(ディレクトリ)をモジュール検索パス(Module Search Path)と呼ぶ。 6. モジュ ...
import sys
import pprint

pprint.pprint(sys.path)

#結果
['/Users/mark/Jupyter Lab/20_Scrayping',
 '/opt/anaconda3/lib/python38.zip',
 '/opt/anaconda3/lib/python3.8',
 '/opt/anaconda3/lib/python3.8/lib-dynload',
 '',
 '/opt/anaconda3/lib/python3.8/site-packages',
 '/opt/anaconda3/lib/python3.8/site-packages/aeosa',
 '/opt/anaconda3/lib/python3.8/site-packages/IPython/extensions',
 '/Users/mark/.ipython']

するとこれらのファイルは’/opt/anaconda3’を示しており、ターミナルからでは各種moduleをimportできないことがわかりました。

そのため、ターミナルでpandasを改めてインストールするため「pip3 install pandas」を実行することでようやくcsv fileを書き出すことができました。

cronによるselenium立ち上げの確認 selenium_open.py

Selenium, Chromium-Chromedriverのインストール

Macのターミナルから以下のコマンドを入力してインストールを行います。

pip3 install selenium

pip3 install chromedriver_binary

pip3 install webdriver-manager

Chromedriverはこちらからダウンロードします。

 

インストールが終わったら以下のコードを打ち込んでSeleniumからWebブラウザ(今回はChromeをシークレットモード)が立ち上がることを確認します。

import time # スリープを使うために必要
from selenium import webdriver # Webブラウザを自動操作する(python -m pip install selenium) 
import chromedriver_binary # パスを通すためのコード
from webdriver_manager.chrome import ChromeDriverManager #Seleniumで開くためのversionの齟齬を修正してくれる
#driver = webdriver.Chrome(ChromeDriverManager().install())

from selenium.webdriver.chrome.options import Options # オプションを使うために必要 
import pandas as pd
option = Options() # オプションを用意
option.add_argument('--incognito') # シークレットモードの設定を付与 

# Sleniumでwebブラウザを起動する
browser = webdriver.Chrome(ChromeDriverManager().install(), options=option) # Chromeを準備(optionでシークレットモードにしている)

# 5秒間保持する
time.sleep(5)

# Sleniumでwebブラウザを停止する
browser.quit()

これを実行して無事にブラウザが立ち上がり数秒後に閉じれば成功です。

最後に

今回はMacのcronを用いてpython fileの自動実行を行いました。まずは手元のMacで自動実行のための準備を整えたら今度は自動実行専用の環境としてRasberry Piを用いてスクレイピングなどを行っていきたいと思います。

Rasberry Piのcronを用いて自動実行を行う記事も興味のある方はぜひご参照ください。

コメント

タイトルとURLをコピーしました