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

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

新規登録して質問してみよう
ただいま回答率
85.36%
スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Python

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

selenium

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

Q&A

2回答

10352閲覧

【python】seleniumを用いたスクレイピングでの、エラー(StaleElementReferenceException)について

konie

総合スコア0

スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Python

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

selenium

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

0グッド

1クリップ

投稿2022/08/12 11:19

編集2022/08/15 04:52

エラーメッセージ

StaleElementReferenceException: Message: stale element reference: stale element not found

調べてみても、この"stale element not found"というエラーへの対処法が見つからず、いろいろ試してみたのですが、改善されずに困っています。

実現したいこと

<div class="class"> #選択項目のボックス。ここをクリックすることで項目リストを表示 <select id="id" name="name" class="class1 class2 class3"> <option value>aaa</otpion> <option value="value1">bbb</otpion> <option value="value2">ccc</otpion> <option value="value3">ddd</otpion> </select> </div>

上記のものが、ウェブページのコードの一部分を抜粋したものになります。実際のページ上では、ボックスをクリックすることで選択可能なリストが表示され、そこから自分が指定したい項目を選ぶものです。
スクレイピングの際に、この項目を自由に指定してデータを拾ってきたいと考えています。

試したこと

Python

1from selenium import webdriver 2from selenium.webdriver.support.ui import Select 3 4driver = webdriver.Chrome("C:******") 5URL = "https://******" 6driver.get(URL) 7 8driver.find_element_by_xpath("xpath1").click() 9driver.find_element_by_xpath("xpath2").send_keys("id") 10driver.find_element_by_xpath("xpath3").send_keys("password") 11driver.find_element_by_xpath("xpath4").click() 12 13#以下がエラー箇所になります。 14#1つ目(調べた結果、もっとも一般的そうな方法だと思われます) 15element=driver.find_element_by_name("name") 16select = Select(element) 17select.select_by_index(n) #indexでもvalueでもtextでも試しました 18 19#2つ目(項目ををクリックする方法) 20driver.find_element_by_css_selector("class").click() 21element = driver.find_element_by_css_selector(".class > class1 :nth-child(n)").click() 22 23#3つ目 24element = driver.find_element_by_xpath("デベロッパーツールから拾ってきたXPATH") 25driver.execute_script("arguments[0].click()", element) 26element = driver.find_element_by_css_selector(".class > class1") 27select = Select(element) 28select.select_by_index(1) 29 304つ目(項目がクリックされていないとだめなのかと考え、クリック後1つ目を実行) 31driver.find_element_by_css_selector(".class").click() 32element = driver.find_element_by_css_selector(".class > class1") 33select = Select(element) 34select.select_by_index(n) 35 36 37#頂いた意見を基に実行したコード 38time.sleep(5) 39element = driver.find_element_by_name("name") 40time.sleep(5) 41 42select = Select(element) 43time.sleep(5) 44select.select_by_index(1)

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

ボックスクリック後に表示される項目リストにはXPATHが与えられておらず、そこからクリックする方法はできませんでした。time.sleep()でプログラムを止めてみたり、print(len(driver.find_elements_by_css_selector("class > class1 > option)))で、そもそも項目が存在するのかを表示させてみようとしたりもしたのですが、ダメでした(後者については、同様に"stale element not found"が表示されました)。

スクレイピングをはじめてまだ数日なので、至らない点もあると思いますが、ご教授頂けると幸いです。質問がございましたらお答えしますので、どうぞ宜しくお願い致します。

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

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

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

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

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

guest

回答2

0

確実な回答ではないと思いますが、私も同じエラーがでて、このページにたどり着き、2の回答を参考にして、エレメントの取得まで1000msウエイトしていたところを2000msにしたら、正常に処理されました。
参考まで。

投稿2024/04/01 10:32

osya335

総合スコア10

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

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

0

調べればわかりますが、stale というのは「古い」という意味です。
現在表示されているページではなく、過去に表示されていたページで取得した要素を操作しようとすると発生するエラーです。
ページ遷移してしまうと、遷移前のページで取得した要素は全て無効になります。
常に、現在表示されているページの要素だけを使うように設計し直します。

投稿2022/08/12 16:40

otn

総合スコア85855

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

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

konie

2022/08/13 04:02

回答頂き、ありがとうございます。 個人的に、エラーメッセージの訳が内容に結びついていなかったので、stale elementが過去に表示されていたページの要素を指していることはわかりました。 ありがとうございます。 ただ、otn様のご指摘については私も考え、"試したこと"で述べているコードの前にprint(driver.current_url)で、表示されているページに誤りがないかを確認しています。記載が足りず、申し訳ありません。"現在表示されているページの要素だけを使うように設計"というのは、current_urlを確認することでは達成できていないのでしょうか? 追って、ご教授頂けると嬉しいです。 よろしくお願い致します。
otn

2022/08/13 05:48

> current_urlを確認することでは達成できていないのでしょうか? 「確認」というのが具体的に何をやっているのか不明ですが、StaleElementReferenceException が出ていると言うことは、"現在表示されているページの要素だけを使うように設計"が出来ていないと言うことです。
konie

2022/08/13 13:35

current_urlと処理を行う対象があるページが同じということを確認するという意味合いでした。言葉が足らず、すみません。 よろしければ、仰っている設計方法について教えて頂けないでしょうか?
otn

2022/08/14 03:47 編集

設計方法と言っても、"現在表示されているページの要素だけを使うように設計" としか言い様がないですが、文章の意味がわからないのでしょうか?それとも具体的な方法でしょうか? 前者であれば、言い換えると「ページ遷移したら、それまでに取得した要素は使わない(使えないので)」ということです。 後者であれば、やりたいことも不明で、現在のコードも不明なので、なんとも言い様がないです。
konie

2022/08/14 04:23

文章の意味はわかってるつもりです。その点は始めから意識して、該当ページ内で取得した要素のみを使うようにしています。 後者について教えて頂きたいです。 現在のコードの流れとしては、 ①webdriverで目的のページを開く際に、ログインが求められる ・driver.getを使用 ②idとpasswordを入力してログイン ・XPATHを指定して、send_keysでidとpasswordを入力し、ログイン ③ログイン後に目的のページであるか、urlを確認した後、本質問でのエラー箇所となっている処理を実行 という流れです。 説明不足であれば追記致しますので、ご助力頂ければと思います。
otn

2022/08/14 04:45

抽象的に言われてもなんとも。 コードを質問文に追記しましょう。
konie

2022/08/14 05:37

追記致しました。 よろしくお願いします。
otn

2022/08/14 08:21

実行したコードをそのままコピペしていますか? エラーメッセージに書かれている行番号の行はどれですか?
konie

2022/08/14 09:29

もちろん秘匿すべき箇所は伏せていますが、そのままコピペしています。 エラーメッセージの対象になっているのは、select.select_by_index(n) です。
otn

2022/08/14 11:28 編集

> もちろん秘匿すべき箇所は伏せていますが、そのままコピペしています。 伏せているのは、****** と書いている部分のことだけでしょうか? > select.select_by_index(n) 2箇所ありますが。1箇所目ですか?2箇所目ですか?
konie

2022/08/14 11:45

*やXPATH1-4, ウェブページの構造に関するタグ名等についても仮のものです。 #◯つ目と書いてある部分が試してみたコードになります。select.select_by_index(n)が書かれているパターンの両箇所で、エラーをはいている感じです。
otn

2022/08/14 12:05

よくわかりません。1つめなのか2つめなのか、どちらなのでしょう? まあ、とりあえず、これからプログラムを読んでみます。
otn

2022/08/14 12:32 編集

読み始めると、ログインの後、早速意味不明のコードが。 > driver.find_element_by_name("name") は、選択したnameの要素を取得して、何にも代入してないのですが、これは一体何のつもりでしょうか? 削除し忘れですかね? > select.select_by_index(n) nが未定義ですね。実際には1とか2とかの数値を入れていると言うことですかね? とりあえず、書かれているコードの範囲では、stale elementのエラーは出る要因が無いです。 可能性としては、 1.stale elementのエラーの出た時に実行していたコードと、質問文のコードが異なる 2.これは経験が無いので自信が無いですが、ページ表示開始後、JavaScriptによるページの書き換えがまだ終わってない段階で後続のコードが動くと、もしかするとJavaScriptが削除したノードを参照してしまって、stale element というエラーになり得るのかも(そういう経験は無いので全くの想像ですが)。もしこれが当たっていれば、ページ遷移後に十分待ってから要素を取得すればいけるかも。
konie

2022/08/15 04:47

すみません。 driver.find_element_by_nameの部分は誤ったコードを記載していました。 修正したのでご確認頂ければ幸いです。 index(n)については、nに数値を入れているという認識で大丈夫です。 ひとまず、頂いた修正方法を試してみます! ありがとうございます。
konie

2022/08/15 04:54

只今、otnさんの意見として頂いていた、2の方法を実行してみたのですが、同様のstale element referenceのエラーが出てしまいました。 実行したコードを試したことに追加いたしましたので、確認とご教示を頂けると嬉しいです。
otn

2022/08/15 07:14 編集

私からは前回のコメント以上に言うことはありません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問