selenium 错误:在try语句之后,未将过时元素附加到页

qrjkbowd  于 2022-11-24  发布在  其他
关注(0)|答案(1)|浏览(146)

我有下面的try语句,它基本上找到了一个重置当前页面的按钮。总之,页面重新加载,

try:
    reset_button = D.find_element(By.XPATH,"//button[starts-with(@class,'resetBtn rightActionBarBtn ng-star-inserted')]")
    reset_button.click()
    D.implicitly_wait(5)
    ok_reset_botton = D.find_element(By.ID,'okButton')
    D.implicitly_wait(5)
    print(ok_reset_botton)
    ok_reset_botton.click()
    D.implicitly_wait(5)
    # Trying to reset current worksheet
except:
    pass
print(D.current_url)
grupao_ab = D.find_element(By.XPATH,'//descendant::div[@class="slicer-restatement"][1]')
D.implicitly_wait(5)
grupao_ab.click()

奇怪的是,每次执行try语句时,我都会得到以下错误日志

selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document

下面一行代码根据日志中发生的

grupao_ab.click()

当我看了一下selenium给出的原因时,它说这是因为元素不再位于给定的DOM上,但元素grupao_ab甚至没有在该页面中定义,那么为什么它会给我这个错误呢?如果需要任何额外的信息,请评论。

7uzetpgm

7uzetpgm1#

首先,StaleElementReferenceException意味着您试图访问的web元素引用不再有效。这通常发生在页面重新加载之后。这正是这里所发生的。
事情的经过如下:你点击了reset按钮,然后你立刻收集了grupao_ab元素,然后试着点击它。但是在你找到grupao_ab = D.find_element(By.XPATH,'//descendant::div[@class="slicer-restatement"][1]')grupao_ab元素和你试着点击它的那一行之间,重新加载开始了。所以之前收集的web元素,实际上是对DOM上一个物理元素的引用,不再指向该web元素。
您可以在此处执行以下操作:点击刷新按钮后,设置一个短暂的延迟,以便开始刷新,然后等待grupao_ab元素变为可点击。WebDriverWaitexpected_conditions应使用显式等待。
另外,你应该知道D.implicitly_wait(5)不是一个暂停命令。它为find_elementfind_elements方法设置等待搜索元素出现的超时。通常我们根本不设置这个超时,因为使用WebDriverWaitexpected_conditions显式等待更好。而不是implicitly_wait隐式等待。而且永远不要混合这两种类型的等待。
即使您希望将implicitly_wait设置为某个值(通常无需再次设置),此设置也会应用于整个driver会话。
请尝试按以下方式更改代码:

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

wait = WebDriverWait(driver, 20)

try:
    wait.until(EC.element_to_be_clickable((By.XPATH, "//button[starts-with(@class,'resetBtn rightActionBarBtn ng-star-inserted')]"))).click()
    wait.until(EC.element_to_be_clickable((By.ID, "okButton"))).click()
    print(ok_reset_botton)
    time.sleep(0.5) # a short pause to make reloading started
except:
    pass
print(D.current_url)
#wait for the element on refreshed page to become clickable
wait.until(EC.element_to_be_clickable((By.XPATH, '//descendant::div[@class="slicer-restatement"][1]'))).click()

相关问题