web-dev-qa-db-ja.com

StaleElementReferenceException on Python Selenium

PythonでSeleniumを使用しているときに次のエラーが表示されます。

Selenium.common.exceptions.StaleElementReferenceException: Message: u'stale element reference: element is not attached to the page document\n

興味深いことに、エラーはforループのさまざまな時点でポップアップします。時々それは例えばを通り抜けます。 4回の繰り返しとその他の時間7。

実行されている関連コードの一部は次のとおりです。

for i in range(0, 22):
    u = driver.find_elements_by_id("data")
    text = u[0].get_attribute("innerHTML")
    driver.find_elements_by_class_name("aclassname")[0].click()

このエラーは何を意味し、これを修正しようとすることができますか?

35
bill999

SeleniumサポートExplicitおよびImplicit待機。ページがロードされるのに一定の時間待つだけで十分だと思う場合は、次を使用します。

driver.implicitly_wait(secs)

しかし、特別なイベント(たとえば、特定の要素がロードされるのを待つ)を待ちたい場合は、次のようなことができます:

from Selenium.webdriver.support.ui import WebDriverWait
...
...
def find(driver):
    element = driver.find_elements_by_id("data")
    if element:
        return element
    else:
        return False
element = WebDriverWait(driver, secs).until(find)
16
Nima Soroush

これは、要素がDOMに存在しないか、変更されたことを意味します。

あなたはforループの中にいます。反復中に何が起こるか考えてください:

  1. 要素をクリックすると何かが変わります(最後の行)
  2. そのため、ページは変化しています
  3. 次の反復を入力します。今、新しい要素(ループ内の最初の行)を見つけようとしています。
  4. 要素を見つけました
  5. 変化し終わる
  6. 属性を取得して使用しようとしています
  7. バム!要素は古いです。手順4で取得しましたが、手順5で変更が完了しました

次のコードは、要素を見つけるのに役立ちます。

from Selenium.common.exceptions import NoSuchElementException
from Selenium.common.exceptions import StaleElementReferenceException
from Selenium.webdriver.common.by import By
from Selenium.webdriver.support.ui import WebDriverWait
from Selenium.webdriver.support import expected_conditions

ignored_exceptions=(NoSuchElementException,StaleElementReferenceException,)
your_element = WebDriverWait(your_driver, some_timeout,ignored_exceptions=ignored_exceptions)\
                        .until(expected_conditions.presence_of_element_located((By.ID, Your_ID)))
16
Emilio M.

Webページが更新されたり、別のウィンドウやフォームから切り替えられたりして、要素ユーザーにアクセスしようとすると、古い要素の例外が発生します。

Forループを使用してtry --exceptブロックでwebdriverwaitを使用します:EX:

Staleelementexceptionを取得したコード:


driver.find_element_by_id(tc.value).click()

driver.find_element_by_xpath( "xpath")。click()


修正:

from Selenium.webdriver.common.by import By
from Selenium.webdriver.support.ui import WebDriverWait
from Selenium.webdriver.support import expected_conditions as EC

driver.find_element_by_id(tc.value).click()
for i in range(4):
   try:
        run_test = WebDriverWait(driver, 120).until( \
        EC.presence_of_element_located((By.XPATH, "xpath")))
        run_test.click()
        break
   except StaleElementReferenceException as e:
        raise e
4
rajkrish06
>>>Stale Exceptions can be handled using **StaleElementReferenceException** to continue to execute the for loop.  

from Selenium.common import exceptions  

# and customize your code of for loop as:  

for i in range(0, 22):  
   try:  
        u = driver.find_elements_by_id("data")  
        text = u[0].get_attribute("innerHTML")  
        driver.find_elements_by_class_name("aclassname")[0].click()  
   except exceptions.StaleElementReferenceException,e:
        print(e)
        pass  

注:Python 3+:update exceptions.StaleElementReferenceException、e-> exceptions.StaleElementReferenceException as e

4
Vishal

ここでの答えを超えて、ActionChainsを使用していて、ページが変更された場合は、ActionChainsオブジェクトを必ず再インスタンス化してください(古いオブジェクトを再利用しないでください)。つまりこれを行う;

action_chain = ActionChains(driver)     
action_chain.double_click(driver.find_element_by_xpath("//tr[2]/p")).perform()

または、インスタンス化を使用しないでください。

ActionChains(driver).double_click(driver.find_element_by_xpath("//tr[2]/p")).perform()
2
n00b

これは、この問題のpythonソリューションです:

def clickAndCatchStaleRefException(locator):



    driver = sel2._current_browser()
    result = False
    attempts = 0

    locator = locator[6:]
    # This line is optional because sometimes you pass a xpath from a varibles file
    # that starts with 'xpath='. This should be omitted otherwise the find_element_by_xpath 
    # function will throw an error.
    # But if you pass an xpath directly you don't need this


    while attempts < 2:
        try:
            driver.find_element_by_xpath(locator).click()
            result = True
            break
        except EC as e:
            raise e
        finally:
            attempts += 1
    return result
0
Rashid

私のために働いているもう1つのソリューションをここに追加したいと思います。

同じページのコンテンツ領域を更新した後、ウェブページのトップメニューパネルのボタンにアクセスしようとしましたが、次のエラーが発生しました。

    raise exception_class(message, screen, stacktrace)
Selenium.common.exceptions.StaleElementReferenceException: Message: The element reference of <span id="dk1-combobox" class="dk-selected combinationText visibleElements "> is stale; either the element is no longer attached to the DOM, it is not in the current frame context, or the document has been refreshed

次に、Webページの古い要素をクリックするためのソリューションの検索を開始しました。 2日間考えてグーグルで調べた後、解決策を見つけました。

ページの古い要素にアクセスするには、まず特定のセクションにマウスを合わせてクリックオプションを実行する必要があります

EditReport1 = driver.find_element_by_id('internalTab1')
ActionChains(driver).move_to_element(EditReport1).click(EditReport1).perform()

move_to_elementは、クリック操作が正常に実行される要素のコントロールを取得したら、アクセスする必要がある古い要素の上にマウスを移動します。

これは私のために働いています。誰かがそれが機能していると思うなら、あなたのものもコメントしてください。これは将来他の人を助けるでしょう。

ありがとうございました

0
JG's Spark