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()
このエラーは何を意味し、これを修正しようとすることができますか?
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)
これは、要素がDOMに存在しないか、変更されたことを意味します。
あなたはforループの中にいます。反復中に何が起こるか考えてください:
次のコードは、要素を見つけるのに役立ちます。
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)))
Webページが更新されたり、別のウィンドウやフォームから切り替えられたりして、要素ユーザーにアクセスしようとすると、古い要素の例外が発生します。
Forループを使用してtry --exceptブロックでwebdriverwaitを使用します:EX:
driver.find_element_by_id(tc.value).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
>>>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
ここでの答えを超えて、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()
これは、この問題の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
私のために働いているもう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は、クリック操作が正常に実行される要素のコントロールを取得したら、アクセスする必要がある古い要素の上にマウスを移動します。
これは私のために働いています。誰かがそれが機能していると思うなら、あなたのものもコメントしてください。これは将来他の人を助けるでしょう。
ありがとうございました