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

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

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

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

selenium

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

Q&A

解決済

1回答

2295閲覧

Seleniumでelementがないものを探す方法を知りたい

SnowBallEffect

総合スコア28

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

selenium

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

0グッド

0クリップ

投稿2020/02/13 01:45

編集2020/02/18 08:04

前提・実現したいこと

PythonのSeleniumを使って自動的にサイトにログインしたいのですが、ログインする際にいくつかセキュリティー質問に答えないとなりません。その質問も自動ログインにしたいので、そこでもSeleniumを使いいます。その一つのセキュリティー質問に対してなのですが、通常であればelementがあるのですが、これにはありません。例えば、id = What is the name of your favorite city for traveling? とか書いているはずなのですが、ただのテキストのようです。下に詳細を書きました。

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

Message: no such element: Unable to locate element: {"method":"id","selector":"stbwebre_settlement_data_system"}

該当のソースコード

HTML5

1<div _ngcontent-c6="" class="col-md-7" style="padding-top:calc(.375rem + 1px); padding-bottom: calc(.375rem + 1px);"> What is the name of your favorite city for traveling? </div>

試したこと

driver.find_element_by_xpath("//div[@"" = 'What is the name of your favorite city for traveling?']")

driver.find_element_by_xpath("//div[@class = 'col-md-7']")だと違う場所を見てるのでダメみたいです。どうしてもWhat is the name of your favorite city for traveling?を見に行かないと答えがあるボックスに答えを入力できないみたいです。助けてください!!

以下がセキュリティー質問のページです。

イメージ説明

Consoleにdocument.getElementsByTagName('form')と入力しても何も出てこないようです。
イメージ説明

イメージ説明

イメージ説明

また、secretEnteredAnswerが複数出ているというエラーは出ていないでそうです。

document.getElementsByTagName('form')を入力しました

イメージ説明

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

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

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

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

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

otn

2020/02/13 04:30

divというelementがあるじゃない??と思ったら、xpathでのテキストノードの指定方法がわからなかったと言うことですね。 elementという言葉の使い方を誤っています。
guest

回答1

0

ベストアンサー

driver.find_element_by_xpath('//div[text()=" What is the name of your favorite city for traveling? "]')
ならどうでしょうか?

追記

ではmainfunctionを以下のようにしてみてください。

python

1 2# 文言に合わせて入力する文字列を変える 3if 'sport' in driver.find_element_by_tag_name('form').text: 4 driver.find_element_by_id('secretEnteredAnswer').send_keys(sport_answer) 5elif 'traveling' in driver.find_element_by_tag_name('form').text: 6 driver.find_element_by_id('secretEnteredAnswer').send_keys(travel_answer) 7else: 8 driver.find_element_by_id('secretEnteredAnswer').send_keys(spouse_answer) 9 10# チェックボックスをクリック 11driver.find_element_by_id('storeDeviceCookie').click() 12 13# オレンジ色のボタンをクリック 14driver.find_element_by_class_name('btn-warning').click()

これでダメだった場合調べていただきたいのですが、
開発者ツールのconsoleタブに以下3つを打ち込んでいただいて、
それぞれ配列が何個だったか教えてください。

javascript

1document.getElementsByTagName('iframe') 2document.getElementsByTagName('frame') 3document.getElementsByClassName('btn-warning')

また、同じく開発者ツールで以下を打ち込んだ時に、
回答入力欄にaaaaaと表示されるか確認してください。

javascript

1document.getElementById('secretEnteredAnswer').value='aaaaa'

投稿2020/02/13 02:23

編集2020/02/17 15:57
shirai

総合スコア1290

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

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

SnowBallEffect

2020/02/13 04:35

返信ありがとうございます。残念ながら driver.find_element_by_xpath('//div[text()=" What is the name of your favorite city for traveling? "]') だと探せないようです。driver.find_element_by_xpath('//div[contains(text()=" What is the name of your favorite city for traveling? "]'))も同じくダメです。。。。
shirai

2020/02/13 16:33

ではprint(driver.page_source)と打ってください。 出力の中に件のdivタグはあるでしょうか。
SnowBallEffect

2020/02/14 01:07

そのコマンドを入れたら、探しているtextもその中にある事を確認しました。
shirai

2020/02/14 02:12

DOMいただいてもいいですか?URLでもいいです。
SnowBallEffect

2020/02/14 05:20

返信ありがとうございます。DOMは以下になります。念のためにURLも送りますね。https://portal.smtbusa.com/ ただ、URLからだとログインしていないので、下記のDOMは見えるかどうかは分かりません。。。 <form _ngcontent-c6="" novalidate="" class="ng-pristine ng-invalid ng-touched"><div _ngcontent-c6="" class="form-group row"><label _ngcontent-c6="" class="col-md-4 col-form-label">Security Question : </label><div _ngcontent-c6="" class="col-md-7" style="padding-top:calc(.375rem + 1px); padding-bottom: calc(.375rem + 1px);"> What is the name of your favorite city for traveling? </div></div><div _ngcontent-c6="" class="form-group row"><label _ngcontent-c6="" class="col-md-4 col-form-label">Security Question Answer : </label><div _ngcontent-c6="" class="col-md-7"><input _ngcontent-c6="" autocomplete="off" class="form-control form-control-sm ng-pristine ng-invalid ng-touched" formcontrolname="secretEnteredAnswer" id="secretEnteredAnswer" name="secretEnteredAnswer" ngbautofocus="" type="password"></div></div><div _ngcontent-c6="" class="form-group row"><label _ngcontent-c6="" class="col-md-4 col-form-label"></label><div _ngcontent-c6="" class="col-md-7"><input _ngcontent-c6="" formcontrolname="storeDeviceCookie" id="storeDeviceCookie" name="storeDeviceCookie" type="checkbox" value="Y" class="ng-untouched ng-pristine ng-valid"> &nbsp;&nbsp; <label _ngcontent-c6="">Yes, register my device as a safe device.</label></div></div><div _ngcontent-c6="" class="text-center"><button _ngcontent-c6="" class="btn btn-primary" type="submit">Submit</button></div></form>
shirai

2020/02/14 12:42

念のためelement取得前にsleep入れてみましょう from time impot sleep sleep(10) driver.find_element_by_xpath('//div[text()=" What is the name of your favorite city for traveling? "]') それでもだめなら前後のpythonプログラムも見していただいていいですか?
SnowBallEffect

2020/02/15 02:07

うーん、ダメですね。。。 sleep(10) を(30)に変更してもダメでした。 以下が私のコードです。def mainfunction()までは全てうまくいきます。 driver.find_element_by_id('portalLoginBtn').click() time.sleep(1) driver.find_element_by_id('smtbUsername').send_keys(username) driver.find_element_by_id('smtbPassword').send_keys(password) time.sleep(1) driver.find_element_by_id('loginButtonId').click() time.sleep(1) spouse_answer = 'Answer1' sport_answer = 'Answer2' travel_answer = 'Answer3' time.sleep(5) def mainfunction(): try: if driver.find_element_by_xpath("//div[text()='What is the name of your favorite city for traveling?']"): driver.find_element_by_id('secretEnteredAnswer').send_keys(spouse_answer) except: pass try: if driver.find_element_by_xpath("//div[text()='What is your favorite sport team?']"): driver.find_element_by_id('secretEnteredAnswer').send_keys(sport_answer) except: pass try: if driver.find_element_by_xpath("//div[text()='What is the name of your favorite city for traveling?']"): driver.find_element_by_id('secretEnteredAnswer').send_keys(travel_answer) except: pass mainfunction() driver.find_element_by_xpath("//button[@class = 'btn btn-primary']").click()
shirai

2020/02/16 15:05

このサイトは3つの質問のうちランダムでどれか1つが出題させるというセキュリティシステムなのでしょうか? その画面の画像もいただけたら幸いです。
SnowBallEffect

2020/02/17 01:52

返信ありがとうございます。はい、その通りです。ランダムで3つの質問が出されて、それに答えないといけません。画像をアップしたので、どうぞご覧ください。
shirai

2020/02/17 15:58

追記しました。
SnowBallEffect

2020/02/18 00:35

ありがとうございます。最終的には def mainfunction(): # 文言に合わせて入力する文字列を変える if 'sport' in driver.find_element_by_tag_name('form').text: driver.find_element_by_id('secretEnteredAnswer').send_keys(sport_answer) elif 'traveling' in driver.find_element_by_tag_name('form').text: driver.find_element_by_id('secretEnteredAnswer').send_keys(travel_answer) else: driver.find_element_by_id('secretEnteredAnswer').send_keys(spouse_answer) mainfunction() driver.find_element_by_xpath("//button[@class = 'btn btn-primary']").click() で解決できました。興味があるのですが、なぜdriver.find_element_by_tag_name('form').textではないとうまくいかなかったのでしょうか?
SnowBallEffect

2020/02/18 01:41

度々申し訳ございません。今、再度コードを動かしたら、spouseの答えしかがあっていなく、sport とtravelは何故か間違っている答えだと認識されているそうです。。。何回も確認しましたが、sport とtravelの答えはあっています。。。
shirai

2020/02/18 02:40

なるほど。。。 それではお願いがあるのですが、どの質問の時でもいいので開発者ツールのconsoleに以下を打ち込んでみてください。 document.getElementsByTagName('form') 配列は何個でてきますか? 配列の数が分からなかったら画像で張り付けて頂いても構いません。 また、consoleに黄色い背景でsecretEnteredAnswerというid属性が複数個所で利用されているという旨のwarningメッセージはでていないでしょうか。
SnowBallEffect

2020/02/18 04:16

早速の返信ありがとうございます。 document.getElementsByTagName('form')を入力しても何もでてきませんでした。また、secretEnteredAnswerでも複数個所で利用されているというメッセージも出てこなかったです。。。。
shirai

2020/02/18 06:04

画像見ましたが、document.getElementsByTagName('form')の入力場所がちがいますね。 一番広い窓のところに打ってあげてください。 https://ja.javascript.info/devtools で「青字で>」となってるところです。
SnowBallEffect

2020/02/18 08:05

間違えてすみません。。 今、新しい画像を追加しました
shirai

2020/02/18 08:09

では if 'sport' in driver.find_element_by_tag_name('form').text: と elif 'traveling' in driver.find_element_by_tag_name('form').text: を if 'sport' in driver.find_elements_by_tag_name('form')[1].text: と elif 'traveling' in driver.find_elements_by_tag_name('form')[1].text: に変えてください。 elementからelementsに変わってるのでお間違え無く。
shirai

2020/02/18 08:23 編集

ついでにですが、element.textとやると、その要素配下の全てのテキストが連結されて返ります。 例えば以下のulタグを指定してtextを取るとaiueoaaaaaという文字列が取得できます。 <ul> <li>aiueo</li> <li>aaaaa</li> </ul> その文字列にsportsと入っているか、それともtravelingと入っているか、それ以外かで判定していました。 また、最後の画像を見る限りformタグは2つあるようですが、htmlを張り付けてもらった時のclass属性から、2つ目の方のformタグであると判断し、 elementsにして該当するものをリストで返戻させて、2つ目を意味する[1]をターゲットにしました。
SnowBallEffect

2020/02/19 01:23

shiraiさん、 すごい!うまくいきました!さらに分かりやすい説明もしていただき本当にありがとうございました。今回はChromeのelementsだけではなくconsoleも大事なんだなと実感して勉強になりました。繰り返しになりますが、数日間にわたって、本当にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問