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

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

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

Google Chromeは携帯、テレビ、デスクトップなどの様々なプラットフォームで利用できるウェブブラウザです。Googleが開発したもので、Blink (レンダリングエンジン) とアプリケーションフレームワークを使用しています。

Python 3.x

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

selenium

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

Q&A

解決済

2回答

4313閲覧

SeleniumでiFrameに飛んだあと、処理が進まない。

ji-desuji

総合スコア11

Chrome

Google Chromeは携帯、テレビ、デスクトップなどの様々なプラットフォームで利用できるウェブブラウザです。Googleが開発したもので、Blink (レンダリングエンジン) とアプリケーションフレームワークを使用しています。

Python 3.x

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

selenium

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

0グッド

0クリップ

投稿2020/02/22 04:42

編集2020/05/24 11:00

前提・実現したいこと

pythonとSeleniumでChromeの自動化を行っています。
iFrameに飛んだ後に、ボタンをクリックしたいのですが、クリックできる場合とクリックできない場合があります。
なぜクリックできない場合があるのでしょうか?
対策方法を教えて頂きたいです。

◆クリックできた場合
新しいウィンドウが開く
◆クリックできない場合
ウィンドウが開かず、コードもそれ以上進みません。エラー等も表示されません。
ctrl + C で動作を止めると下記のメッセージが表示されます。

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

ディレクトリ、ファイル名は修正しています。 Traceback (most recent call last): File "c:/Users/test.py", line 373, in <module> test_1() File "c:/Users/test.py", line 158, in test_1 driver.switch_to.frame(iframe) File "C:\Users\AppData\Python\Python38\lib\site-packages\selenium\webdriver\remote\switch_to.py", line 89, in frame self._driver.execute(Command.SWITCH_TO_FRAME, {'id': frame_reference}) File "C:\Users\AppData\Python\Python38\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 319, in execute response = self.command_executor.execute(driver_command, params) File "C:\Users\AppData\Python\Python38\lib\site-packages\selenium\webdriver\remote\remote_connection.py", line 374, in execute return self._request(command_info[0], url, body=data) File "C:\Users\AppData\Python\Python38\lib\site-packages\selenium\webdriver\remote\remote_connection.py", line 397, in _request resp = self._conn.request(method, url, body=body, headers=headers) File "C:\Users\AppData\Python\Python38\lib\site-packages\urllib3\request.py", line 79, in request return self.request_encode_body( File "C:\Users\AppData\Python\Python38\lib\site-packages\urllib3\request.py", line 171, in request_encode_body return self.urlopen(method, url, **extra_kw) File "C:\Users\AppData\Python\Python38\lib\site-packages\urllib3\poolmanager.py", line 330, in urlopen response = conn.urlopen(method, u.request_uri, **kw) File "C:\Users\AppData\Python\Python38\lib\site-packages\urllib3\connectionpool.py", line 665, in urlopen httplib_response = self._make_request( File "C:\Users\AppData\Python\Python38\lib\site-packages\urllib3\connectionpool.py", line 421, in _make_request six.raise_from(e, None) File "<string>", line 3, in raise_from File "C:\Users\AppData\Python\Python38\lib\site-packages\urllib3\connectionpool.py", line 416, in _make_request httplib_response = conn.getresponse() File "C:\Users\AppData\Local\Programs\Python\Python38\lib\http\client.py", line 1322, in getresponse response.begin() File "C:\Users\AppData\Python\Python38\lib\http\client.py", line 303, in begin version, status, reason = self._read_status() File "C:\Users\AppData\Python\Python38\lib\http\client.py", line 264, in _read_status line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1") File "C:\Users\AppData\Python\Python38\lib\socket.py", line 669, in readinto return self._sock.recv_into(b) KeyboardInterrupt

該当のソースコード

python

1target = driver.find_element_by_id('iframeのid要素') 2driver.execute_script('arguments[0].scrollIntoView(true);', target)#iFrameの要素までスクロールする 3time.sleep(2) 4 5iframe = driver.find_element_by_id('iFrameのid要素') 6print(iframe)#ここまで正常に動作 7driver.switch_to.frame(iframe)#<-★Debugで確認すると、ここで止まることがある。 8time.sleep(2) 9 10driver.find_element_by_name("button").click()#ボタンを押す 11time.sleep(2) 12 13driver.switch_to.window(driver.window_handles[-1])#新しいウィンドウを有効にする 14time.sleep(2)

試したこと

sleepが足りないのかと思い、5秒程度まで長くしてみたのですがそれでも効果ありませんでした。
約3回に1回失敗している感じです。
⇒2020/5/17現在は、10~20回に1回しかアクセスできない状態。

下記コードで、log.txtにソースを出力して確認はできた。

python

1target = driver.find_element_by_id('iframeのid要素') 2driver.execute_script('arguments[0].scrollIntoView(true);', target)#iFrameの要素までスクロールする 3time.sleep(2) 4 5iframe = driver.find_element_by_id('iFrameのid要素') 6with open('log.txt', 'w+',encoding="utf-8_sig") as f: 7 f.writelines(driver.page_source) 8driver.switch_to.frame(iframe)#<-★Debugで確認すると、ここで止まることがある。 9time.sleep(2) 10 11driver.find_element_by_name("button").click()#ボタンを押す 12time.sleep(2) 13 14driver.switch_to.window(driver.window_handles[-1])#新しいウィンドウを有効にする 15time.sleep(2)

switchの後で、コード出力すると、iFrame内のコードが表示される
ただし、switchに成功するまで確認する必要あり。

python

1target = driver.find_element_by_id('iframeのid要素') 2driver.execute_script('arguments[0].scrollIntoView(true);', target)#iFrameの要素までスクロールする 3time.sleep(2) 4 5iframe = driver.find_element_by_id('iFrameのid要素') 6driver.switch_to.frame(iframe)#<-★Debugで確認すると、ここで止まることがある。 7with open('log.txt', 'w+',encoding="utf-8_sig") as f: 8 f.writelines(driver.page_source) 9time.sleep(2) 10 11driver.find_element_by_name("button").click()#ボタンを押す 12time.sleep(2) 13 14driver.switch_to.window(driver.window_handles[-1])#新しいウィンドウを有効にする 15time.sleep(2)

Workaroundのソースコード

賢い方法ではないですが、下記方法にて何とか処理を進めることができました。
20回実行し、10回1回目OK、10回2回目でOK。
なぜか、tryで処理を入れたところ、成功率が上がりました。
絶対に失敗したくないので、念のため、5回tryしています。

python

1driver.switch_to.frame(driver.find_element_by_id('iframeのid')) 2try: 3 print('1回目') 4 driver.find_element_by_name('buttonのname').click() 5except: 6 try: 7 time.sleep(1) 8 driver.refresh() 9 time.sleep(2) 10 print('2回目') 11 driver.switch_to.frame(driver.find_element_by_id('iframeのid')) 12 driver.find_element_by_name('buttonのname').click() 13 except: 14 try: 15 time.sleep(1) 16 driver.refresh() 17 time.sleep(2) 18 print('3回目') 19 driver.switch_to.frame(driver.find_element_by_id('iframeのid')) 20 driver.find_element_by_name('buttonのname').click() 21 except: 22 try: 23 time.sleep(1) 24 driver.refresh() 25 time.sleep(2) 26 print('4回目') 27 driver.switch_to.frame(driver.find_element_by_id('iframeのid')) 28 driver.find_element_by_name('buttonのname').click() 29 except: 30 try: 31 time.sleep(1) 32 driver.refresh() 33 time.sleep(2) 34 print('5回目') 35 driver.switch_to.frame(driver.find_element_by_id('iframeのid')) 36 driver.find_element_by_name('buttonのname').click() 37 except: 38 print('NG') 39 40 41driver.switch_to.window(driver.window_handles[-1])#新しいウィンドウを有効にする 42time.sleep(2)

補足情報(FW/ツールのバージョンなど)

Python 3.8
Chrome Version: 80.0.3987.116(Official Build) (64 ビット)
Visual studio code

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

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

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

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

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

guest

回答2

0

ベストアンサー

クリックした後一旦元に戻ってからwindowhandleを切り替えてみてください。

python

1driver.find_element_by_name("button").click()#ボタンを押す 2time.sleep(2) 3 4driver.switch_to.default_content() 5 6driver.switch_to.window(driver.window_handles[-1])#新しいウィンドウを有効にする 7time.sleep(2)

コメントを受けて追記

なるほど。
日によって成功確率が異なるということは、
サーバ(スクレイピング先)かクライアント(自PC)のどちらかが
極端にスペックが低い可能性が高いです。

自PCを見て異常がなさそうなら、
待ち方を変えてみましょう。
あとスクロールが悪さをしている可能性もあるので
これもつけたり外したりしてみてください。

python

1from selenium.common.exceptions import TimeoutException 2from selenium.webdriver.common.by import By 3from selenium.webdriver.support import expected_conditions as EC 4from selenium.webdriver.support.ui import WebDriverWait 5 6try: 7 WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.ID, 'iFrameのid要素'))) 8except TimeoutException: 9 print('20秒以内にページが読み込めませんでした。') 10 driver.quit() 11 exit() 12driver.switch_to.frame(driver.find_element_by_id('iFrameのid要素')) 13 14try: 15 WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'button'))) 16except TimeoutException: 17 print('20秒以内にボタンがクリックできませんでした。') 18 driver.quit() 19 exit() 20driver.find_element_by_name("button").click() 21 22driver.switch_to.window(driver.window_handles[-1]) 23print('最後までいけました。') 24driver.quit() 25exit()

これで「20秒以内にページが読み込めませんでした。」が頻発するようでしたら、

python

1try: 2 WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.ID, 'iFrameのid要素'))) 3except TimeoutException: 4 print('20秒以内にページが読み込めませんでした。') 5 driver.quit() 6 exit()

python

1driver.implicitly_wait(20)

に置き換えてみてください。

投稿2020/02/25 05:01

編集2020/05/19 12:59
shirai

総合スコア1290

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

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

ji-desuji

2020/05/05 07:03

返信が遅くなってしまい申し訳ございません。 コードを修正・追記しました。 default_content()も試しましたが、効果ありませんでした。 Debugで1行ずつ確認したところ、driver.switch_to.frame(iframe) で処理が止まってしまうことがあります。
shirai

2020/05/07 01:08

ならその手前でsleepを入れてみましょう。
shirai

2020/05/07 01:12

あ、すいませんもう入れてあるんですね。 switchの手前でprint(driver.page_source)と入れると 目的のiframeは出てきますか?
ji-desuji

2020/05/12 05:47

返信遅くなってしまい申し訳ございません。返信に気づいていませんでしたm(__)m 目的のiframeのコードが出てきておらず、全体のコードが出力されていました。 iframeの取得に問題があるのでしょうか?
shirai

2020/05/14 07:19

iframeの配下は表示されないはずですが、iframeタグ自体は出てくるはずです。それもないですか?
ji-desuji

2020/05/14 14:14

そうだったんですね。配下が表示されるのかと思っていました。 該当iframeのタグ自体は表示されました。
shirai

2020/05/14 15:10

3回に1回ほど失敗するということですが、 このiframeタグは毎回printされますか?
ji-desuji

2020/05/17 05:39

なぜか、いまはさらにアクセス率が落ちており、10~20回に1回しかアクセスできないです。 アクセスできないときも、毎回printされています。
shirai

2020/05/17 18:17

ではswitchした後にprintするとどうなりますか?
ji-desuji

2020/05/18 10:59

いつもありがとうございます。 switchの後に、入れるとiFrame内のコードが表示されました。 ただし、switchに成功するまで何度か繰り返しました。
shirai

2020/05/19 12:59

追記しました。
ji-desuji

2020/05/24 11:01

色々とありがとうございました。 wait系では解決しなかったので、別の方法にて何とか処理を進められました。 ”Workaroundのソースコード”に記載しました。
guest

0

driver.switch_to.window(driver.window_handles[1])#新しいウィンドウを有効にする

投稿2020/02/22 04:57

GKP

総合スコア6

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問