Selenium on Colaboratory と時間制限回避手法に関するポエム

## 今回の神

Google Colaboratory 上でSelenium-webdriverが動くらしい（すごい）

![screenshot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219661/f53d54f8-b796-f940-30c6-ea9473f2143d.png)

[python - WebDriverException: Message: Service /content/chromedriver unexpectedly exited. Status code was: -6 with ChromeDriver Google Colab and Selenium - Stack Overflow](https://stackoverflow.com/questions/53532060/webdriverexception-message-service-content-chromedriver-unexpectedly-exited)

執筆時点(2019/05/03)で1000回も閲覧されていないとかいう知名度の低い情報でしたが、最高ソリューションなので書き残します（加えて、 **Colabaratory の時間制限を回避できるかもしれない可能性について提案します** ←これはつまり**ポエム**です【要検証】）

## Colaboratory上でseleniumを動かす

以下のコードを Colaboratory へコピペするだけでとりあえず動きます。それさえも億劫なひとのために、動作検証用の Colaboratory へのリンクも[こちら](https://colab.research.google.com/drive/1xamLrOOVVnJ0u-CL4BlqzkKCiezKYJia)に用意してあります。
◇ [selenium_on_colaboratory_for_share.ipynb - Colaboratory](https://colab.research.google.com/drive/1xamLrOOVVnJ0u-CL4BlqzkKCiezKYJia)

> ```terminal
# install chromium, its driver, and selenium
!apt-get update
!apt install chromium-chromedriver
!cp /usr/lib/chromium-browser/chromedriver /usr/bin
!pip install selenium
```

> ```python
# set options to be headless, ..
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
# open it, go to a website, and get results
wd = webdriver.Chrome('chromedriver',options=options)
wd.get("https://www.google.com")
print(wd.page_source)  # results
```


## 可能性の話（この記事の本題）

> 　あとGoogle Coloaboratory上でSeleniumを動かすのは、難しいらしいです（← WebDriverの起動が難しいっぽい）。もし可能だった場合、Google Coloaboratory_fileAでselenumを起動させてGoogle Coloaboratory_fileBを起動し、12時間切れる前にGoogle Coloaboratory_fileBでselenumを起動させてGoogle Coloaboratory_fileCを起動(...以下エンドレスリピート）みたいなウンコプログラムを記述していたのだがorz
> ◆ [Google Colaboratoryを定期実行する方法について考える - Qiita](https://qiita.com/Fortinbras/items/4cfa9269af2ab8d1d4d5)

上記の記事を書いた方は Colaboratory から Selenium が使えるようになったことを知らなかったようですが、発想はかなり面白いと思います。Colaboratory で任意の処理を行なう一方で、制限時間が近づいたらまた別の Colaboratoryに処理を引き継げばいいのでは？どうやったら実現できるか以下のように考えてみました。

1. Colaboratory_**A**で処理を開始する
2. 制限時間が近づいたら、データをGithubに退避させる
3. Colaboratory_**A**からColaboratory_**B**を起動する
4. Githubからデータをcloneし、再度処理を開始する
5. （１に戻って繰り返す）

このようにすれば、理論上は24時間365日、**TPUがフル稼働する無料のPython環境**も夢じゃないかも………！？

### 実装方法の概要

Colaboratoryの起動云々はSeleniumにやらせるとしても、「データをGithubに退避させる」ってどうやるんじゃい、という話があったのですがそこはさすが天下のPython、すでに[GitPython](https://github.com/gitpython-developers/GitPython)というライブラリが提供されていました。

- [gitpython-developers/GitPython: GitPython is a python library used to interact with Git repositories.](https://github.com/gitpython-developers/GitPython)
- [GitPython Documentation — GitPython 2.1.11 documentation](https://gitpython.readthedocs.io/en/stable/)

これを使えば、`clone`, `add`, `commit`, `push` という最低限のGit操作は簡単にできるようになります。

これであとは、ページのソースとにらめっこしながらSeleniumくんのコードを書くだけや❗❗　勝ったッ❗❗❗❗　第三部、完 ❗❗❗❗❗👉👉👉


## 現在ブチ当たっている壁

けれども大前提として、Colaboratoryを実行するためにはまず**Googleのアカウントにログインする必要**がありました。しかしそこはさすがのGoogle、Seleniumからメールアドレスとパスワードを入力してログインできたと思ったのもつかの間、当然の権利であるかのように画像認証のページへと遷移させられてしまいました。**失敗**です………。

そこでは再度パスワードと、例のグニャグニャしたランダムな文字列を読み取って入力することが求められていました。Seleniumを駆使してその画像をColaboratory上に表示することまではできたものの、テキストを入力するのはcolaboratory単体でやるには至難の業、ほぼ不可能な気がします。

画像認証を突破するために、Colaboratoryの外からどうにかしてテキストを入力する方法を考えねばなりません（そして都合上、なるべく無料で使える方法を検討したい…）。

## 改善案

画像を取得するところまではできているので、今度はそれを`GAS`こと [Google App Script](https://developers.google.com/apps-script/) に POST して、それをさらに手元の Slack に投げてもらい、画像を確認してテキストを再度 GAS に投げ返し、それを受け取った GAS が Colaboratory に差し戻す……みたいな

ちょうど、 Colaboratory_A, _B, _C..., を複製していくにあたってGASを使おうと考えていたので都合も良いのですが、まだ完全に理解できておらず、実装が追いついていない状況です~~（これを読んだGAS職人に任せたいと思います）~~

また、私の場合は二段階認証を設定していないアカウントで試行したため画像認証が必要になったかもしれないということも考えられます。二段階認証を設定していれば、メールアドレスとパスワードを入力した後、認証コードを入力するだけでよくなるかもしれません。

最終的なシステム全体の構成としては、以下のようになると思います

- **Colaboratory** (Selenium + Git + 任意のpythonコードによる処理)
- **Google App Script** (ログイン時のやり取りを仲介 + Colaboratoryの複製・削除)
- **Slack** (ログイン時の認証情報の入力 + 進捗状況の監視)

処理の流れは以下の通り

1. Colaboratory_**A**で処理を開始する
2. 制限時間が近づいたら、データを Github に退避させる
3. Selenium 経由でGoogleアカウントにログイン
4. その際、GASとslackで人力による入力
5. Colaboratory_**A**からColaboratory_**B**を起動する
6. Githubからデータをcloneし、再度処理を開始する
7. （１に戻って繰り返す）

※二回目以降のログインは、chromeのプロファイル情報が引き継げれば省略できる可能性があるが、今の所不明（できない可能性が高い？）
cf. [Python + Selenium + Chrome で自動ログインいくつか - Qiita](https://qiita.com/memakura/items/dbe7f6edadd456da1c5d)


## おわりに

こんなポエムを書いて検索汚染するのは忍びないという気持ちはありつつも、これを少し改善すれば正しくすべてPythonユーザーにとっての桃源郷が広がっていること間違いなしだと考えたので書き残しました。誰か、実現してくれ～～～～🙏🙏🙏🙏🙏（他力本願）

- [今回のソースコード（Regular_execution_by_Selenium.ipynb）](https://colab.research.google.com/drive/1vT_RjrH_R-L3Hzq-3lYnzUC7NR-BH1eF)

### 参考文献

###### Selenium on Colaboratory の先駆者様たち
- [Colaboratory上でSeleniumが使えないか試した(そしてダメだった) - Qiita](https://qiita.com/FrozenVoice/items/5348a74feeb5e8b8b8ad)
- [GoogleColaboratoryにSeleniumの実行環境を用意する（失敗） - Qiita](https://qiita.com/taikomegane/items/58184ea359788ff32147)
- [ColaboratoryでSeleniumが使えた：javascriptで生成されるページも簡単スクレイピング - Qiita](https://qiita.com/ftoyoda/items/fe3e2fe9e962e01ac421)
- [python - WebDriverException: Message: Service /content/chromedriver unexpectedly exited. Status code was: -6 with ChromeDriver Google Colab and Selenium - Stack Overflow](https://stackoverflow.com/questions/53532060/webdriverexception-message-service-content-chromedriver-unexpectedly-exited)


###### Google Colaboratory を定期実行したい人たち
- [Google Colaboratoryの90分セッション切れ対策【自動接続】 - Qiita](https://qiita.com/enmaru/items/2770df602dd7778d4ce6)
- [Google Colaboratory の 90分ルールを回避したい。 - Qiita](https://qiita.com/Gimina_Graph/items/4bdf3e3c3658eeb0eba8)
- [Google Colaboratoryを定期実行する方法について考える - Qiita](https://qiita.com/Fortinbras/items/4cfa9269af2ab8d1d4d5)
- [Google Colaboratory で機械学習させる際のインフラ整備 - Qiita](https://qiita.com/iZuno-K/items/453cbc023a477359f272)

###### Selenium 関連

- [Selenium with Python — Selenium Python Bindings 2 documentation](https://selenium-python.readthedocs.io/)
- [Selenium API(逆引き)](http://www.seleniumqref.com/api/webdriver_gyaku.html)
- [Python + Selenium + Chrome で自動ログインいくつか - Qiita](https://qiita.com/memakura/items/dbe7f6edadd456da1c5d)
- [Selenium でgoogleログイン：パソコン鳥のブログ](https://s.webry.info/sp/vogel.at.webry.info/201812/article_8.html)


###### GitPython 関連

- [GitPythonを使う - Qiita](https://qiita.com/TakesxiSximada/items/ea778bb98b8c057ffd07)
- [gitpython つかってみた - 俺は面倒が嫌いなんだ](http://rane.hatenablog.com/entry/2015/06/18/203339)
- [gitpython-developers/GitPython: GitPython is a python library used to interact with Git repositories.](https://github.com/gitpython-developers/GitPython)
- [GitPython Documentation — GitPython 2.1.11 documentation](https://gitpython.readthedocs.io/en/stable/)