"BOKU"のITな日常

還暦越えの文系システムエンジニアの”BOKU”は新しいことが大好きです。

Webアプリケーションで自動的に何かをクリックするTips/Selenium&python

Seleniumpythonの組合せで、Webアプリケーションを自動化して使う「個人的なTips」3回シリーズの2回目です。

今回は何かをクリックする行為に関わる部分です。

f:id:arakan_no_boku:20190914133925j:plain

 

記事の前提と留意点

 

内容的に「自分がよく使う」ケースをまとめています。

汎用的でなくても、似たような使い方をする誰かの参考になれば・・のスタンスです。

長くなるので、3回にわけていて、今回はその2回目です。

主な内容は。

です。

ソースのサンプルは、クラスの部品としてメソッドを定義するように書いてます。

その、使い方のイメージについては、末尾の方にかいてます。

なお、MyRpaToolsクラスのソースコード全体は3回目の末尾に掲載する予定です。

さて。

内容にはいります。

 

個別のクリック部品群

 

Seleniumで自動処理すると、やたらとクリックがでてきます。

以下に各ケースごとにまとめます。

 

Seleniumのclick()を使ったボタンのクリック

 

見た目は普通のボタンでも、typeが「submit」であるボタンと、「button」であるボタンがあります。

<input type="submit" id="sname" class="sname" name="sname" value="サブミット">
<input type="button" id="bname" class="bname" name="bname" value="ボタン">

 

それをちゃんと区別して使うSeleniumっぽいやつです。

   def click_submit(self, name):
        element = self.driver.find_element_by_xpath(
            "//input[@name='" + name + "'][@type='submit']")
        element.click()

    def click_button(self, name):
        self.driver.find_element_by_xpath(
            "//input[@type='button'][@name='" + name + "']").click()    

上がSubmit、下がbuttonです。

これらも、Selenium共通の制約があり、画面から隠れているボタンに対してclick()しようとするとエラーになります。

 

ボタンが押せない時にonClick()のJavaScriptを直接実行する

 

Seleniumの制約でボタンを押しすらい場合は、onClickで紐づいているJavaScriptを直接実行する方法が有効です。

    def execute_script(self, scr):
        self.driver.execute_script(scr)    

Seleniumのexcute_scriptを単純にラップしているだけですけど、便利です。

例えば。

<input type="button"  onclick="script_test();">

みたいなものがあれば、 

auto.execute_script("script_test();") 

みたいに、クリックされたとみなして、JavaScriptを実行してやれば、ボタンが画面から隠れていても、問題なく処理を続けられます。

 

チェックボックスラジオボタンのクリック(単純版)

 

チェックボックスラジオボタンを選ぶ時もクリックします。

普通にするなら簡単な話で、typeがcheckboxになったり、radioになったりするだけです。

    def click_checkbox(self, name):
        self.driver.find_element_by_xpath(
            "//input[@type='checkbox'][@name='" + name + "']").click()

    def click_radio(self, name):
        self.driver.find_element_by_xpath(
            "//input[@type='radio'][@name='" + name + "']").click()

でも。

こんなシンプルなケースは今時、ほとんどありません。

 

チェックボックスラジオボタンの上の要素をJavaScriptでクリック

 

たいてい、チェックボックスラジオボタンそのものをCSSで「displey:none」にして、画像やlabelをかぶせているようなケースがほとんどです。

例えばこんな感じ。

<label name="inner_chk">
<input type="checkbox" name="inner_chk">チェックする場所
</label>

こんな時に上の<label>の部分をクリックする必要があります。

ところが、Seleniumの機能を使ってClick()しようとすると、labelがclickable(クリック可能)ではない・・などとエラーがでてうまくいかなかったりします。

そんな時には、こういう手があります。

    def click_by_name(self, name):
        self.driver.execute_script(
            "document.getElementsByName('" + name + "')[0].click();")    

ようするに、JavaScriptの機能で直接click()しているわけです。

これだと、labelもクリックできます。

 

グループ化でnameが同じチェックボックスラジオボタンのクリック

 

radioボタンの場合に多いのですが、radioボタンをグループ化して、nameには同じ名前・・たとえば「radio_group_xxx」みたいな・・を設定している場合があります。

なので、実際には以下のように、同じ名前の複数のエレメントを取得して、その何番目(index)をクリックするという方を使います。

    def click_by_names(self, name, index):
        self.driver.execute_script(
            "document.getElementsByName('" + name + "')[" + index + "].click();")

例えば。 

ラジオボタンがグループされて、3つ並んでいる場合とかだと。

auto.click_by_names('radio_group_xxx', '1')
time.sleep(1)
auto.click_by_names('radio_group_xxx', '2')
time.sleep(1)
auto.click_by_names('radio_group_xxx', '3') 

 みたいにして、1秒おきに、上から順番にチェックする・・とかして、連動して表示が変わる部分の動作をテストで確認するみたいに使ってます。

 

リンクのクリック

 

これはとてもシンプルです。

一番楽なのは、リンクのテキストで識別してクリックするもの。

    def click_link_by_text(self, text):
        element = self.driver.find_element_by_link_text(text)
        element.click()    

例えば、「auto.click_link_by_text("カヨコ")」みたいな感じです。 

テキスト表示のリンクはこれでいけます。

ただ、テキストがなくて、画像に直接リンクをはったりしている場合もあるので、そういうときは、以下みたいにtitle属性に着目してみたり・・して、都度対応する必要があります。

    def click_link_titled(self, name):
        element = self.driver.find_element_by_xpath("//a[@title='" + name + "']")
        element.click()    

 

まあ、xpathの指定の仕方に慣れれば、たいてい対応できるので、いいんですけどね。

kurozumi.github.io

でも。

どうしても、識別する方法が見つからない場合には、<a>タグを全部ひろって、何番目のリンクをクリックする・・みたいな手も使います。

    def click_link_by_index(self, index):
        self.driver.execute_script("document.getElementsByTagName('a')[" + str(index) + "].click();")

これの使い方は。 

auto.click_by_index(2) 

とかして、HTMLの2番目のリンクをクリックします。

テキストなしに上部に画像を<a>タグで囲んだものが並んでいるアクションパネルもどきみたいなものがあるときには便利だったりします。

 

 使い方のイメージとか

 

Seleniumをダイレクトに書くとゴチャゴチャして、読みづらくなります。

そのため、MyRpaToolsというクラスに部品をまとめて、操作の流れにあわせて、1行ずつペタペタ部品を貼り付けていくような使い方を想定しています。

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

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')

上記例だと、Edgeドライバーを、「driver」という名前のオブジェクトにセットして、それを引数に「MyRpaTools」クラスインスタンスを生成してます。

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

 

二回目まとめ

 

今回は、クリックでした。

今のところ、個人的にこのくらいのバリエーションでいけてはいます。

とはいえ。

環境がかわると、また追加したりすることもあるので、その時は順次追加・更新していくつもりです。

なお。

seleniumのインストールやWEBドライバの取得等については、こちらの記事にまとめてます。

arakan-pgm-ai.hatenablog.com

今回はこんなところで。

ではでは。