【问题标题】:Python Selenium StaleElementReferenceException: Message: stale element reference: element is not attached to the page documentPython Selenium StaleElementReferenceException:消息:过时的元素引用:元素未附加到页面文档
【发布时间】:2022-01-21 02:17:18
【问题描述】:

我正在尝试在 python 中使用 selenium 和 chromedriver 从网站上抓取数据。登录网站后,我必须从一个下拉菜单中选择一些值,但我无法使用代码单击下拉菜单。我把代码写成:

from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver,60)
element=wait.until(EC.element_to_be_clickable((By.XPATH,"//input[@id='ContentPlaceHolder1_rcmbCapacityTranch_Input']")))
element.click()

当我运行上述代码行时,我得到 StaleElementReferenceException: Message: stale element reference: element is not attached to the page document 但当我将 time.sleep(2) 包含为:

time.sleep(2)
element=wait.until(EC.element_to_be_clickable((By.XPATH,"//input[@id='ContentPlaceHolder1_rcmbCapacityTranch_Input']")))
element.click()

现在,它已成功执行并单击下拉菜单并显示值,但有时 2 秒的时间休息是不够的,我必须给 5 秒,有时我必须给 10 秒的时间休息,这会减慢执行速度,有时这 10 秒的休息时间也失败了。
我还尝试了以下代码行:

staleElement = True
while(staleElement):
    try:
        xpath="//input[@id='ContentPlaceHolder1_rcmbCapacityTranch_Input']"
        element=wait.until(EC.element_to_be_clickable((By.XPATH,xpath)))
        element.click()
        staleElement = False
    except StaleElementReferenceException:
        staleElement = True

上述代码行成功执行,但未单击下拉菜单且未显示值,但是当我在 jupyter notebook 单元格中重新执行与上面相同的代码行时,下拉菜单被选中并显示值。 所以,谁能帮我解释一下我上面提到的事情背后的原因,并在没有sleep()的情况下给我解决问题的永久解决方案。
任何帮助将不胜感激。

【问题讨论】:

    标签: python python-3.x selenium selenium-webdriver web-scraping


    【解决方案1】:

    由于我没有进入该网站的凭据,我只能猜测。
    所以我的猜测是:该网站使用动态 DOM。
    这意味着在初始出现之后,Web 元素会继续重新构建,因此即使在 Selenium 捕捉到某些特定元素可单击或可见之后,该元素可能会立即继续更改,从而使初始元素引用变得陈旧。
    您可以尝试通过两种方式处理此问题:

    1. 首先设置wait 条件,然后设置延迟,然后设置另一个wait 条件。像这样:
    from selenium.webdriver.support import expected_conditions as EC
    wait = WebDriverWait(driver,60)
    wait.until(EC.element_to_be_clickable((By.XPATH,"//input[@id='ContentPlaceHolder1_rcmbCapacityTranch_Input']")))
    time.sleep(2)
    wait.until(EC.element_to_be_clickable((By.XPATH,"//input[@id='ContentPlaceHolder1_rcmbCapacityTranch_Input']"))).click()
    
    1. 捕捉到元素后,尝试单击它。如果引发过时元素异常,请等待该元素再次可单击,然后再次尝试单击它,直到单击成功。使用这样的循环,您通常会在 2-3 次迭代期间单击。
      所以请试试这个:
    from selenium.webdriver.support import expected_conditions as EC
    wait = WebDriverWait(driver,60)
    succeed = False
    while !succeed:
        try:
            wait.until(EC.element_to_be_clickable((By.XPATH,"//input[@id='ContentPlaceHolder1_rcmbCapacityTranch_Input']"))).click()
            succeed = True
        except:
            pass
    
    

    【讨论】:

      猜你喜欢
      • 2019-09-30
      • 1970-01-01
      • 2020-10-30
      • 2021-12-19
      • 1970-01-01
      • 2022-08-17
      • 2020-11-13
      • 2018-10-23
      • 2019-02-03
      相关资源
      最近更新 更多