質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

3回答

11792閲覧

python seleniumで、サイトのボタンのエレメントをclass nameから取得したいがNoSuchElementExceptionで失敗する

HoriemonHack

総合スコア54

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

0クリップ

投稿2020/09/22 11:20

前提・実現したいこと

python seleniumで、とあるサイトのボタンのエレメントを、xpath以外(ここではclass name)から取得したく、コードを書いて実行しましたが、下記のようなエラーがでてしまいます。
(xpathであれば成功することは確認済み)

HTMLを見る限り、class="~~~"と書いてある部分からclass nameを知ることができるので、
driver.find_element_by_class_name を用いて取得できると考えていました。

xpathではエレメントを取得できることを確認済みですが、サイトの構成が変わってしまった場合に
対応できないため、サイトの構成にさほど影響を受けないエレメントでwebを操作したいというポリシーで
質問させていただいています。

質問内容

①HTMLにはclass="~~~"と書いてあるにもかかわらず、driver.find_element_by_class_nameで取得できないのはなぜでしょうか。

②①で、class nameでの取得が理屈上難しい場合、xpathを用いない要素の取得方法は他にありますでしょうか。

発生している問題・エラーメッセージ

selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":".btn btn-block btn-neg-light-gray btn-text-blue btn-icon-right btn-arrow-next"} (Session info: chrome=85.0.4183.102)

エレメントを取得したいボタンのHTMLソース

HTML

1<button type="submit" class="btn btn-block btn-neg-light-gray btn-text-blue btn-icon-right btn-arrow-next"> 2パスワードを入力する 3</button>

該当のソースコード

Python

1from selenium import webdriver 2from selenium.webdriver.support.ui import WebDriverWait 3from selenium.webdriver.support import expected_conditions 4from selenium.webdriver.common.by import By 5from selenium.webdriver.support import expected_conditions as EC 6import time 7from datetime import datetime 8from selenium.common.exceptions import TimeoutException 9 10 11MaxWaitTime = 100 12driver = webdriver.Chrome("c:/driver/chromedriver.exe") 13driver.get('URL') 14 15WebDriverWait(driver, MaxWaitTime).until(EC.presence_of_all_elements_located) 16 17element2 = driver.find_element_by_class_name("btn btn-block btn-neg-light-gray btn-text-blue btn-icon-right btn-arrow-next") 18element2.click()

試したこと

下記のように、XPATHでの指定であればエレメントを取得し、ボタンをクリックできました。

Python

1element2 = driver.find_element_by_xpath("/html/body/div/main/div/div/div/div/form/div[2]/div[2]/button")

環境

windows10
python 3.8.0
chromedriver :v85

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

おそらくクラス名に空白が含まれているのが原因かと思われます。
find_element_by_css_selectorの使用を検討されてはどうでしょうか?

seleniumでby_class_nameでスペースが入った要素が取得できずエラーになる時の対処法

投稿2020/09/22 12:11

meg_

総合スコア10760

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

HoriemonHack

2020/09/25 13:45

まさにこれが原因でした。ありがとうございます!
guest

0

どうしてもclassで取得したいなら

python

1element = driver.find_element_by_class_name('btn-arrow-next')

などとどれか1つに絞りましょう。
今回は

  • btn-neg-light-gray
  • btn-text-blue
  • btn-icon-right

などなど色々選択肢がありますが、
パスワード入力画面なので「次へ」的な意味合いのclassは1つしかなさそうだと推察し、
btn-arrow-nextを選んでみました。

画面上にclass属性にbtn-arrow-nextが含まれる要素が複数あったらこれは効かないかもしれません。

この手のボタンで全要素が被っていることはないとは思うので、

python

1element = driver.find_element_by_css_selector('.btn.btn-block.btn-neg-light-gray.btn-text-blue.btn-icon-right.btn-arrow-next')

などにすれば間違いはないと思います。

ついでに

この画面にはclass属性にbtnが含まれる要素は複数ありませんか?(bootstrapにはよくある話なので)

python

1btn_elements = driver.find_elements_by_class_name('btn') 2print(len(btn_elements))

と打つとその個数が出力されます。

elementではなくelementsになっていることに注目してください。
sをつけると当てはまる全ての要素がリストになって返ってきます。
1つもなければ空のリストが返るので存在判定などに使えます。

リストで返るので、そのうち3番目の要素にアクセスしたいのならば

python

1btn_elements[2]

といった感じで見ることができます。

class属性にbtnが含まれる要素が複数ある場合、

python

1driver.find_element_by_class_name('btn')

python

1driver.find_elements_by_class_name('btn')[0]

は同じ要素を指します。

find_element_by_◯◯とやると複数あった場合は1番目が返ります。

「画面上にclass属性にbtn-arrow-nextが含まれる要素が複数あったらこれは効かないかもしれません。」
と先ほど書いたのは目的の要素が必ずしも先頭にあるとは限らないからです。

おまけ

xpathだとこのような取得方法もあります。

python

1driver.find_element_by_xpath('//button[@class="btn-arrow-next"]')

投稿2020/09/23 15:33

shirai

総合スコア1290

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

要素のクラスが複数あり、クラスを複数指定したいときは、.で繋ぎます。順不同です。

Python

1element2 = driver.find_element_by_class_name("btn.btn-block.btn-neg-light-gray.btn-text-blue btn-icon-right.btn-arrow-next")

全部指定せず、1つか2つの指定だけで特定できるのならそれでもいいです。

投稿2020/09/22 14:03

編集2020/09/23 15:40
otn

総合スコア85901

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問