【再掲】Classiアンケートの回答を自動化する

`※この記事ではWindows環境でPython3.7を用いています。ついでにChromeも入れておいてください。
また、筆者はPython初学者ですので、用語等間違いがあるかもしれません。指摘等あればコメントしてくださると助かります。`
　Classiのアンケートの回答を自動化したくて作ってみました。
　~~1年半前に掲載して削除したものが残ってたのでその再掲です。~~

:::note warn
　警告
・担当教員にばれて怒られても責任はとれません。
・不正アクセスはダメ！ゼッタイ！
:::

# Classi とは？
>　Classiは、学校のICT化を多角的にサポートする教育プラットフォームです。PCやタブレット、スマートフォンにも対応し、中学校、高校、専門学校など多くの教育現場で活用されています。

# 準備
## まずはSeleniumをインストール。
　コマンドプロンプトで`py -m pip install selenium`と実行しよう。
## ChromeDriverをダウンロード。
　以下のサイトからChromeDriverをダウンロード。
[https://chromedriver.chromium.org/downloads](https://chromedriver.chromium.org/downloads)
 使っているChromeと同じバージョンをダインロードしてください。
ダウンロードが完了したらZIPを解凍して任意の場所に移動しておいてください。


# プログラムの流れ
## 1. 必要なライブラリをインポートする。
``` python:classi.py
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains
```
先ほど入れたseleniumをインポートします。

## 2. Chromeを開く。
``` python:classi.py
driver = webdriver.Chrome(executable_path='xxx\\chromedriver.exe')
URL = "https://auth.classi.jp/students?backurl=https%3A%2F%2Fplatform.classi.jp%2F"
driver.get(URL)
```
　１行目の`executable_path='xxx\\chromedriver.exe'`には先ほどダウンロードしたChromeDriverのパスを入れてください。
　Chromeを開き、Classiに移動します。

## 3.ログインしてアンケート一覧画面に移動する。
``` python:classi.py
#IDとパスワードの入力
User_ID = "IDxxx"
User_pass = "PASSxxx"
#IDとパスワードを入力する場所を探す
ID_box = driver.find_element_by_name("classi_id")
pass_box = driver.find_element_by_name("password")
#IDとパスワードを入力、Enterキーを押す
ID_box.send_keys(User_ID)
pass_box.send_keys(User_pass)
pass_box.send_keys(Keys.RETURN)
#アンケート一覧へ
driver.get("https://platform.classi.jp/questionnaire#/reply/list")
```
`IDxxx`と`PASSxxx`に自分のIDとパスワードを入力して、変数に代入します。
`.find_element_by_name("classi_id")`で、`name`から要素を取得します。

## 4.アンケートを選択する。
```python:classi.py
#アンケート実施画面へ
driver.find_element_by_xpath("/html/body/div[1]/div/div/article/div/section/div/div/div/table[1]").click()
time.sleep(1)
driver.find_element_by_xpath("/html/body/div[1]/div/div/article/div/form/div[2]/button").click()
time.sleep(1)
#回答するをクリック
driver.find_element_by_xpath("/html/body/div[1]/div/div/article/div/form/div[2]/button").click()
time.sleep(1)
```
この時、選択するアンケートは一番上にあるアンケートです。また**他のアンケートが未回答で残っている場合にはバグりやすいので回答してなくしておきましょう**。
`time.sleep(1)`を追加しているのは、ページを移る時間を考慮しているためです。

## 5.アンケートに回答する。
※この例では、上から`選択問題`、`選択問題`、`記述問題`という３問で構成されているアンケートです。

```python:classi.py
#回答
 #1.選択問題1。2項目目を選択
driver.find_element_by_xpath("/html/body/div[1]/div/div/article/div/form/div[1]/div[2]/div/div/dl[1]/dd[2]/ul/li[2]").click()
 #2.選択問題2．3項目目を選択
driver.find_element_by_xpath("/html/body/div[1]/div/div/article/div/form/div[1]/div[3]/div/div/dl[1]/dd[2]/ul/li[3]").click()
 #3.自由記述
textbox = driver.find_element_by_xpath("/html/body/div[1]/div/div/article/div/form/div[1]/div[4]/div/div/dl[1]/dd[2]/div/label/textarea")
textbox.send_keys("・英語\n・数学\n・物理\n・化学")
time.sleep(1)

#スクロール+一時保存
element = driver.find_element_by_xpath("/html/body/div[1]/div/div/article/div/form/div[2]/button[2]")
actions = ActionChains(driver)
actions.move_to_element(element)
actions.perform()
driver.find_element_by_xpath("/html/body/div[1]/div/div/article/div/form/div[2]/button[2]").click()
time.sleep(1)
```
　Classiのアンケートは一番上の問題から`div2`、`div3`、`div4`...という順番で指定されています。３問以上ある場合には`div5`...と増やせばいいのです。
　また、**選択問題と自由記述問題で形式が異なるので注意が必要**です。
　選択問題ではxpathの一番最後でクリックする項目を指定します。例)`li[2]`

## 6.送信してタブを閉じる。
```python:classi.py
#送信
driver.find_element_by_xpath("/html/body/div[1]/div/div/article/div/form/div[2]/button[3]").click()
time.sleep(1)
driver.find_element_by_xpath("/html/body/div[8]/div/div/div/div[3]/button[2]").click()
#とじる
time.sleep(5)
driver.quit()
```
あとは送信してタブを閉じるだけです。

#完成！！！
完成したコードはこちら↓

``` python:classi.py
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains

driver = webdriver.Chrome(executable_path='xxx\\chromedriver.exe')
URL = "https://auth.classi.jp/students?backurl=https%3A%2F%2Fplatform.classi.jp%2F"
driver.get(URL)

#IDとパスワードの入力
User_ID = "IDxxx"
User_pass = "PASSxxx"
#IDとパスワードを入力する場所を探す
ID_box = driver.find_element_by_name("classi_id")
pass_box = driver.find_element_by_name("password")
#IDとパスワードを入力、Enterキーを押す
ID_box.send_keys(User_ID)
pass_box.send_keys(User_pass)
pass_box.send_keys(Keys.RETURN)
#アンケート一覧へ
driver.get("https://platform.classi.jp/questionnaire#/reply/list")

#アンケート実施画面へ
driver.find_element_by_xpath("/html/body/div[1]/div/div/article/div/section/div/div/div/table[1]").click()
time.sleep(1)
driver.find_element_by_xpath("/html/body/div[1]/div/div/article/div/form/div[2]/button").click()
time.sleep(1)
#回答するをクリック
driver.find_element_by_xpath("/html/body/div[1]/div/div/article/div/form/div[2]/button").click()
time.sleep(1)

#回答
 #1.選択問題1
driver.find_element_by_xpath("/html/body/div[1]/div/div/article/div/form/div[1]/div[2]/div/div/dl[1]/dd[2]/ul/li[2]").click()
 #2.選択問題1
driver.find_element_by_xpath("/html/body/div[1]/div/div/article/div/form/div[1]/div[3]/div/div/dl[1]/dd[2]/ul/li[3]").click()
 #3.自由記述
textbox = driver.find_element_by_xpath("/html/body/div[1]/div/div/article/div/form/div[1]/div[4]/div/div/dl[1]/dd[2]/div/label/textarea")
textbox.send_keys("・英語\n・数学\n・物理\n・化学")
time.sleep(1)

#スクロール+一時保存
element = driver.find_element_by_xpath("/html/body/div[1]/div/div/article/div/form/div[2]/button[2]")
actions = ActionChains(driver)
actions.move_to_element(element)
actions.perform()
driver.find_element_by_xpath("/html/body/div[1]/div/div/article/div/form/div[2]/button[2]").click()
time.sleep(1)

#送信
driver.find_element_by_xpath("/html/body/div[1]/div/div/article/div/form/div[2]/button[3]").click()
time.sleep(1)
driver.find_element_by_xpath("/html/body/div[8]/div/div/div/div[3]/button[2]").click()
#とじる
time.sleep(5)
driver.quit()
```


#おわりに
　結局、このプログラムはどんなアンケートが何問あるかを知っておかなければ使えないんですよね。仮に、同じ内容のアンケートが定期的に配信されるのであれば使える(と思う)ので良ければ活用してみてください。
　ただし、自動回答であることが担当教員にばれても(~~ばれるとは思わないが~~)責任はとれません。ご了承ください。

 ここまで読んでくださりありがとうございました！