こんばんは。二度目の投稿の@0yanです。
今回はSeleniumでEラーニングの受講者情報更新を自動化しました(社内業務自動化の一環です)。
Seleniumでクリックできない問題にドハマったので、同じことで悩んでいる人の一助になれば幸いです。
なお、本記事は私と同じく、Selenium初心者の方を対象としております。
やったこと
Seleniumで
1.Eラーニングの管理者ログインページに遷移
2.ログイン
3.受講者一覧ページに遷移
4.受講者詳細ページに遷移
5.上司という項目を更新、登録ボタン押下(受講者一覧ページに戻る)
6.上記4,5を約250回繰り返す
という作業を自動化しました。
自動化の背景
私の所属会社では、求人情報サイトを運営する某大手企業のEラーニングを利用しております。
- コンテンツが充実している(考え方やコンピテンシーからプログラミングや語学まで幅広いコンテンツが揃っている)
- 管理者(人事)側で、受講者毎にオススメ講座を設定出来る
- 受講報告メールがイケてる(「会社に対する提案」という項目があり、そこから組織改善につながるアイディアが得られる)
といった良い点が沢山あるにも関わらず、同業他社と比べて安価で非常に気に入っております。
しかしながら、この素晴らしいEラーニングにも一点だけ不満があります。それは受講者一括更新機能の対象項目に、一部の項目が入っていないこと。
問題の項目は(受講者の)上司という項目なのですが、これを設定しないと受講報告メールが上司に飛ばないのです。
受講報告メールが上司に飛ばないと困るので、当然、設定するわけですが、会計年度が切り替わるときに発生する大規模な体制変更の際は、上司の変更作業だけで一日が終わってしまいます。
しかも、クリックするだけの簡単なお仕事。価値を生まない、誰でもできる作業に段々嫌気が差してきます。
そこで今回、Python版Seleniumを使ってこの作業を自動化することにしたのです。
環境
Windows 10 Home(64bit)
Google Chrome 75.0.3770.90
Python 3.6.8(Anaconda3をインストール)
chromedriver-binary 74.0.3729.6.0
selenium 3.141.0
ライブラリ周り
SeleniumとWebDriver(今回はChromeDriver)のインストール、Seleniumの基本操作については、@memakura さんの記事を参考にさせて頂きました。
@memakura さん、ありがとうございました!
# coding: utf-8
import csv
import time
import chromedriver_binary
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
コーディング
やったこと(再掲)
Seleniumで
1.Eラーニングの管理者ログインページに遷移
2.ログイン
3.受講者一覧ページに遷移
4.受講者詳細ページに遷移
5.上司という項目を更新、登録ボタン押下(受講者一覧ページに戻る)
6.上記4,5を約250回繰り返す
という作業を自動化しました。
1.Eラーニングの管理者ログインページに遷移
管理者ログインページにアクセスします。
def main():
driver = webdriver.Chrome()
driver.get('管理者ログインページのURL')
2.ログイン
テキストボックスにログインIDとパスワードを入力し、ログインボタンを押下します。
driver.find_element_by_xpath('ログインIDテキストボックスのxpath').send_keys('ログインID')
driver.find_element_by_xpath('パスワードテキストボックスのxpath').send_keys('パスワード')
driver.find_element_by_xpath('ログインボタンのxpath').click()
3.受講者一覧ページに遷移
管理者ページTOPから受講者一覧ページに遷移します。
driver.find_element_by_xpath('受講者一覧ページへの遷移ボタンのxpath').click()
4.受講者詳細ページに遷移
受講者一覧ページは、下図のようなカードが沢山並んだ構造となっており、受講者氏名に受講者詳細ページへのリンクがはられています。
また、受講者氏名のxpathは「~[@id="student_受講者番号"]~」のようになっています。
なので今回は、下図のようなCSVをフォーマットとし、xpath内の受講者番号を可変とすることで、受講者一覧ページ内の特定の受講者氏名をクリックできるようにしました。
with open(file='.\\update_boss.csv', mode='r', encoding='utf-8-sig', newline='') as csv_file:
reader = csv.DictReader(csv_file)
for row in reader:
try:
student_number = row['受講者番号']
# 受講者氏名を受講者番号で検索してクリック
driver.find_element_by_xpath('~[@id="student_{}"]~'.format(student_number)).click()
except:
# 受講者番号が受講者一覧ページにない場合はログ残す
print('受講者番号検索エラー({})'.format(row['受講者番号']))
5.上司という項目を更新、登録ボタン押下(受講者一覧ページに戻る)
with open ステートメントの続きです。エラーとなっていなければ、受講者詳細ページに遷移しています。
このページで苦戦しました・・・!
苦戦した点
1.テキストボックスを選択できない
上司を入力するテキストボックスがページ最下部にあり、前ページから遷移してきた直後は見えない状態になっています。
それが理由なのかはわかりませんが、find_element_by_xpathメソッドだけではテキストボックスを選択できませんでした。
そのため、execute_scriptメソッドを使い、JavaScriptでページ最下部までスクロール。
これで解決できました。
2.候補者リストをクリックできない
テキストボックスに上司の氏名を入力すると、登録されている受講者リストから候補者の氏名が出てきます(下図参照)。
しかし、なぜか候補者リストをクリックできませんでした。
ページのソースを見ると、selectタブになっていたため、「プルダウンリストのように、Selectクラスのインスタンスを生成して選択する必要があるのか?」と考え、それを試しましたがうまくいかず・・・。
四苦八苦しましたが、候補者リストが出てきてから1秒待ったらクリックできました。
try:
# JavaScriptでページ最下部までスクロール
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# 現在の上司を消す(余裕をみて3回バックスペース)
for i in range(3):
driver.find_element_by_xpath('~[@id="edit_student_{}"]~'.format(student_number)).send_keys(Keys.BACK_SPACE)
# 上司を入力し、候補者リストを表示させる
boss = row['上司']
driver.find_element_by_xpath('~[@id="edit_student_{}"]~'.format(student_number)).send_keys(boss)
# 候補者リストをクリック(1秒以上待たないとエラーになる)
time.sleep(1)
driver.find_element_by_xpath('候補者リストのxpath').click()
# 登録するボタンをクリック
driver.find_element_by_xpath('~[@id="edit_student_{}"]~'.format(student_number)).click()
except:
print('上司更新エラー({})'.format(row['受講者番号']))
# 一時停止
time.sleep(1)
さいごに
Qiitaへの記事投稿をTwitterでもつぶやいております。
フォローして頂けますと幸いです(ユーザー名は@0yan_sです)。
長文にも関わらず、最後までご覧頂き誠にありがとうございました。