"BOKU"のITな日常

62歳・文系システムエンジニアの”BOKU”は日々勉強を楽しんでます

Webアプリケーションで自動的に入力・選択するTipsあれこれ/Selenium&python

Seleniumpythonの組合せで、Webアプリケーションを自動化して使う「個人的なTips」を3回続き物で書こうかなと思ってます。

今回は1回目の「入力」「選択」なんかに関わる部分です。

f:id:arakan_no_boku:20190914133925j:plain

 

はじめに

 

seleniumを使って、Webアプリケーションをpythonプログラムから自動制御する方法について書きます。

主な内容としては。

  • 書こうと思ったきっかけと3回にわけた構成
  • 記事を書く上での前提事項について

を書いて、あと、本文部分で

  • inputタグ(text、password)等への入力方法
  • 半角カタカナなど文字化けするものへの対応
  • jQueryのDatePickerへの入力方法
  • Selectでの選択方法

などについて書いてます。

 

3回にわけて書いていきます

 

seleniumをWebアプリケーションのテストで良く使います。

ただ、全面的な自動化はしません。

あまり全自動化にこだわると、テストコードの作成やメンテナンスにかかるコストがバカにならないからです。

なので、テストで何回も繰り返す面倒なところだけ部分的に自動化しています。

似たような使い方をする誰かの参考になればいいなのスタンスで、はじめます。

長くなるので、3回にわけます。

  • 1回目:入力したり、選択したりのTipsあれこれ(今回)
  • 2回目:何かをクリックする場合のTipsあれこれ(9/24火曜日公開予定)
  • 3回目:Webアプリの値を参照したり、スクロールしたり他Tips(9/26木曜日公開予定)

今回は、1回目です。

 

シリーズ共通の前提

 

MyRpaToolsというクラスにメソッドを部品として作っていきます。

使う時には、MyRpaToolsのインスタンスを生成して、操作の流れにあわせて、ペタペタと部品を貼っていきます。

使い方のイメージはこうです。

import my_rpa_tools as my
from selenium import webdriver
import time


# Edge WebDriver initial setting
driver = webdriver.Edge(
    executable_path='C:\\windows\\system32\\MicrosoftWebDriver.exe')
driver.get('https://coopweb.itecs.local/pro_staff/ps_login.php')
auto = my.MyRpaTools(driver)
# login
auto.input_text('login_id', 'user0001')

クラス(パーツを定義)は「my_rpa_tools.py」にまとめています。

上記例だと、Edgeドライバーです。

いったん「driver」オブジェクトをセットして、それを引数にして「MyRpaTools」クラスインスタンスを生成します。

上記ではその名前を「auto」にしていて、「auto.input_text」のように、クラスで定義したメソッドを並べていきます。

なので。

記事中のソースサンプルは、その部品となるメソッドをのせてます。

クラスの構造はこうです。

my_rpa_tools.py

from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.ui import WebDriverWait as wait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC


class MyRpaParts():
    def __init__(self, web_driver):
        self.driver = web_driver
        self.scroll_height = 0

初期化時に、self.driverにweb_driverをうけとって内部で保持し、それを各メソッドの中で使っていきます。 

セレクタは「name」を使ってます。

一部jQueryを使っているのですが、その場合だけIDセレクタにしています。

理由は自分のよく使う環境だと、それが適切だからです。

なお、定義したクラスのソース全体は3回目の末尾にのせる予定です。

arakan-pgm-ai.hatenablog.com

 

個別の入力部品群

 

個別の入力部品の定義を書いていきます。

 

まずは普通のテキストボックスへの入力

 

普通の「<input type="text"  name="text001" value="" />」に対応するものです。

    def input_text(self, name, value):
        element = self.driver.find_element_by_xpath(
            "//input[@name='" + name + "'][@type='text']")
        element.send_keys(value)

send_keysを使ってます。

使い方は。

auto.input_text('login_id_name', 'user0001')

です。

同じようなテキストボックスでも、typeがnumberだったりpasswordだったりしますので、以下のような定義も作っておきます。

    def input_number(self, name, value):
        element = self.driver.find_element_by_xpath(
            "//input[@name='" + name + "'][@type='number']")
        element.send_keys(value)

とか 

    def input_password(self, name, value):
        element = self.driver.find_element_by_xpath(
            "//input[@name='" + name + "'][@type='password']")
        element.send_keys(value)    

とかですね。

これにはいくつかの制限事項があり、大きなものは以下の2つです。

  • 半角カタカナの入力が文字化けしてしまう。
  • 画面上から隠れているとエラーになる

 

半角カタカナの入力を文字化けさせない

 

Seleniumだけではできません。

以下のように、JavaScriptを直接使って部品を定義します。

    def input_by_name(self, name, value):
        self.driver.execute_script(
            "document.getElementsByName('" + name + "')[0].value = '" + value + "';")

この方法を使うと、send_keysの制約をクリアできます。

もちろん、半角カタカナの文字化けも回避できます。

汎用敵なな名前のままだと、自動化対象の画面とつきあわせる時にわかりづらいので、これを内部で使って以下のような半角カタカナ専用メソッドを定義して使ってます。

    def input_text_kana(self, name, value):
        self.input_by_name(name, value)

jQueryが使えそうな環境なら、こんなのも使ってます。

    def input_direct_by_id(self, id, value):
        self.driver.execute_script(
            "$('#" + id + "').val('" + value + "');")    

 

 

今のところ、自分がやっている環境では、この程度で、テキスト入力については、ほぼほぼ対応できてます。

 

jQueryのDatepickerに入力する

 

自分の環境では、自動化対象のWEBアプリケーションは、jQueryのDatePickerも使われているます。

これは、JavaScriptでコントロールされていて、操作に従ってカレンダーが表示されたりするので、結構自動操作すると面倒なものです。

二通りの方法を使ってます。

ひとつは、普通に操作して当月の日付を選択入力するものです。

    def input_datepicker_current_month(self, name, select_day):
        self.driver.find_element_by_name(name).click()
        wait(self.driver, 10).until(EC.visibility_of_element_located(
            (By.XPATH, "//td[@data-handler='selectDay']/a[text()='" + select_day + "']"))).click()

日付のテキストボックスをクリックして、カレンダーが表示されるのをまって、指定した日付の部分を選択してます。 

でも。

これだと、当月以外の日付を入力するのが、とても面倒です。

生年月日みたいな30年前の日付とか言われると「地獄(笑)」です。

なので、日付を直接入力します。

    def input_datepicker_dairect(self, id, value):
        self.driver.execute_script(
            "$('#" + id + "').datepicker().datepicker('setDate','" + value + "');")

ここはjQueryを使っているので、nameではなく、idになっているので注意です。

使い方としては。

auto.input_datepicker_dairect('date_pick_id', '1988年9月1日(木)')

とか  

auto.input_datepicker_dairect('date_pick_id', '1988/09/01')

 のように指定の日付を直接入力します。

注意としては、日付のフォーマットです。

普通、設定しているjQueryのソースなんか見れないので、手入力で日付入力してみて結果として表示されるフォーマットで入力すれば問題ないですが、フォーマットが違うと変な日付になります。

 

複数行入力はごくシンプル

 

次は複数行入力(textarea)です。

普通にSeleniumの機能を使うなら、こんな感じ。

    def input_textarea(self, name, value):
        element = self.driver.find_element_by_xpath(
            "//textarea[@name='" + name + "']")
        element.send_keys(value)
    

もちろん、send_keys を使っているので、半角カタカナとかの制約は同じです。

回避するには、Textと同じようにJavaScriptを直接よぶパーツを使うことになりますが、今のところ、半角カタカナを複数行入力するようなケースは見たことがないので、用意してません。

 

Selectで選択する

 

Selectに関しては、Seleniumの機能をそのまま使うものしか用意してません。

特に困ってないので。

valueの値で選択するものです。

    def select_by_value(self, name, value):
        element = self.driver.find_element_by_name(name)
        element_select = Select(element)
        element_select.select_by_value(value)
    

オプションの 選択肢の「value」の値を確認して指定します。

Selectでよくあるパターンで、例えば、都道府県と市区町村とか、なんかの種別を選んで下に選択肢が表示されるみたいな、Ajax的な動きのものがあります。

このような、上の段の値によって、選択値が変更される場合は、下の段の更新がちゃんと終わるまで待ってやらないといけません。

そんな時は。

auto.select_by_value('parent_kind', '4')
time.sleep(1)
auto.select_by_value('child_type', '8')    

こんな感じで間にsleepとかはさんで待ってやるか、 waitとかを使って下段が表示されるまで待ちます。

waitを使う方がそれっぽいですが、自分はsleep()を好んで使ってます。

まず、わかりやすいです。

それに、1秒位の間があいた方が、自動で動いている画面を見ている時に見やすいということもあります。

スタンスとしては、まずsleep()でやっておいて、それでストレスを感じる部分だけwaitを使って細かくコントロールすればいいと思っています。

 

第一回目まとめ

 

入力・選択については、今のところ、こんなものです。

3回にわけている2回目、3回目はこちらです。

2回目

arakan-pgm-ai.hatenablog.com

3回目

arakan-pgm-ai.hatenablog.com

seleniumのインストールや、Webドライバの設定は、こちらの記事でまとめています。

arakan-pgm-ai.hatenablog.com

続きは次回で。

ではでは。