Selenium × Python × HerokuでGoogle ClassroomをスクレイピングするBOTを作った
はじめに
こんにちは。今回はSelenium × Python × Herokuを使ってGoogle Classroomをはじめとしたログインしないとアクセスできないサービスをスクレイピングする方法を書き留めておこうと思います。
バッググラウンド
そもそも何がしたいのかを説明します。
わが校では夕飯を食堂で頼めるという仕組みがありまして、毎日(次の日の)申請フォーム(Google Form)がクラスルーム(Google Classroom)送られてきます。当日の午前10:30が締め切りなのですが、意外に忘れる人が多くこれを防止するためにLINE BOTを作ろうと思いました。
今回の趣旨
今回、大きくやりたいことをまとめると以下のような形になると思います。
-
Heroku×Python環境を構築したい。 -
SeleniumをPythonで使いたい。 -
SeleniumをHeroku上で動かしたい。 -
SeleniumでGoogle Classroom(など)に入りたい。
1. 環境構築
1.1. PackageのインストールとHeroku Appの生成
Python × Herokuの環境構築は多くの方がやられているものと大差ありませんので少し省きつつ構築していきます。また、Pythonやpipはインストールされているものとします。
まずは必要なpackageをインストールしていきます。
$ pip install flask
$ pip install selenium
次に、Heroku関係の構築をします。
$ heroku login
出てきたURLにアクセスしてログインしてください。
アプリケーションを生成します。なお、フォルダをその場で生成するのでフォルダ移動を行った後に実行してください。
$ heroku create -a <app-name>
$ cd <app-name>
これでまずは完了です。
1.2. 設定ファイルの準備
次はファイルを作ってアプリとしてdeployする準備をしましょう。
先ほど生成した<app-name>フォルダ内にmain.pyを生成します。
main.pyに仮のコードを書きましょう。
from flask import Flask, request, abort, jsonify
import os
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
app = Flask(__name__)
@app.route("/")
def hello_world():
return "hello world!"
これでhello_worldのwebhookができます。これだけだとHerokuでは動いてくれません。ほかの設定ファイルが必要です。
これでpythonのバージョンとインストールしたpackageのバージョンを確認します。
$ python --version
$ pip freeze
以下の三つの設定ファイルを<app-name>フォルダ内に生成します。
runtime.txtに先ほど確認したpythonのバージョンを書き入れます。
python-3.10.4
requirements.txtはHerokuに必要なpackageを教えます。先ほどpip freezeで出力されたもののうち、必要なものだけ抜き出します。
Flask==2.1.0
selenium==4.1.3
最後にHerokuに実行方法を教えます。
web: python main.py
これで初期設定はできました。次はHerokuにdeployしましょう。
1.3. HerokuへのDeploy
deployにはgitを使いますのでインストールを済ましておいてください。
gitでコミットします。
$ git init
Initialized empty Git repository in .git/
一応、Herokuのリポジトリとつながっているか確認します。
$ git remote -v
heroku https://git.heroku.com/<app-name>.git (fetch)
heroku https://git.heroku.com/<app-name>.git (push)
こうなってれば正解です。なって無ければ以下のコマンドをたたいてください。ちなみに僕はなぜかなっていませんでした。
$ heroku git:remote -a <app-name>
最後にdeployの方法ですが、普通のgitと同じようにcommitしてpushするだけです。
$ git add .
$ git commit -m "My first commit"
$ git push heroku main
個人的にはGithub Desktopを使うとやりやすいと思います。(remote先には十分注意してください。)
ちなみに、webhookとなっているのでhttps://<app-name>.herokuapp.com/にアクセスするとhello world!と表示されると思います。
2. Heroku上でSeleniumを動かす
早速Seleniumを動かしていきましょう。
今回はhttps://<app-name>.herokuapp.com/seleniumにPOSTに対して応答するように実装します。
# ...省略
@app.route("/selenium", methods=['POST'])
def seleniumFunc():
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument("--disable-dev-shm-usage")
driver = webdriver.Chrome(options=options)
driver.get("<your-url>")
# スクレイピング
# 終了
driver.quit()
コードはこれだけです。ですが、触ったことある人ならご存じの通り、SeleniumにはGoogle Chrome本体とChrome Driverなるものが必要です。これらは、Heroku側で準備してもらいます。
まずはHerokuダッシュボードの<app-name>プロジェクトの設定を開いてください。
https://dashboard.heroku.com/apps/<app-name>/settings
Buildpacksに以下の二つを追加してください。
https://github.com/heroku/heroku-buildpack-chromedriver.git
https://github.com/heroku/heroku-buildpack-google-chrome.git
これで次のdeployから設定が適応されます。
これでhttps://<app-name>.herokuapp.com/seleniumに適切なPOSTをすることで内容が実行されます。もちろんFlaskの管轄ですのでGETなどの設定は@app.route("/selenium", methods=['POST'])をいじることで可能です。
3. SeleniumでGoogleログインする
最後はちょっとしたオマケです。Googleのサービスは優秀で基本的にGoogle Apps Scriptでいじることができます。ですが、Classroomはそうはいきません。生徒の立場である私からでは何もすることができません。そこでスクレイピングをすることでどうにかしようというわけです。
GoogleはサイトにアクセスするとCookieやキャッシュからログイン情報を読み取ります。Herokuでは毎回要求されますのでこれさえ突破してしまえばなんということはありません。
# ...省略
@app.route("/selenium", methods=['POST'])
def seleniumFunc():
# ...省略...
driver.get("https://classroom.google.com/u/1/c/XXXXXXX")
# ログイン情報
login_id = "<your-google-account-mailaddress>"
login_pw = "<your-google-account-password>"
# メールアドレス入力
el_id = driver.switch_to.active_element
el_id.send_keys(login_id)
el_id.send_keys(Keys.ENTER)
sleep(5)
# パスワード入力
el_pw = driver.switch_to.active_element
el_pw.send_keys(login_pw)
el_pw.send_keys(Keys.ENTER)
sleep(10)
# スクレイピング
# 終了
driver.quit()
これで好きなようにスクレイピングできます。簡単ですね。
パスワードべた書きで怖いよってかたはHeroku標準の環境変数を利用できます。
$ heroku config:set GOOGLE_MAILADDRESS="<your-google-account-mailaddress>" --app <app-name>
$ heroku config:set GOOGLE_PASSWORD="<your-google-account-password>" --app <app-name>
べた書きの代わりに以下のように書けば利用できます。
# ...省略...
login_id = os.environ["GOOGLE_MAILADDRESS"]
login_pw = os.environ["GOOGLE_PASSWORD"]
さいごに
今回は「Selenium × Python × HerokuでGoogle ClassroomをスクレイピングするBOTを作った」ということでHeroku環境でもスクレイピングをしたい方におすすめのやり方を書きました。
Chrome DriverやChromeが用意されていたり、環境変数が簡単に使えちゃうHeroku最強ですね!なんでもwebhookにできちゃったり...ほんとにもっと早く出会いたかった代物です。
まぁ一つ難点を挙げるとすれば、Add-onが無料のものであってもクレジットカード登録が必要という点ですね。私は学生でクレジットカードないのでAdd-onが利用できませんでした。今回作ったBOTは定時でスクレイピングやデータベース処理などを実行するのですがそれらはすべてGoogle Apps Script側で実装してfetchでこのwebhookをたたいてます。GASはトリガー機能が標準だったり、Google Spread Sheetという最強(笑)のデータベースもあってこっちも扱いやすいです。
ですが、Google関係のことしかできなかったりと未来はHerokuのほうが明るいなと思いました。なにせPythonで書けるというがでかい...
さて、ここまでお付き合いありがとうございました。ご自愛くださいませ。
Discussion