Python, Selenium : '元素不再附加到 DOM

5 投票
2 回答
13697 浏览
提问于 2025-04-18 07:35

我正在抓取一个网站,www.lipperleaders.com。我想提取新加坡的基金详情。我已经成功实现了下拉选择,并提取了提交选项后出现的第一页内容。但是,当我尝试点击“下一页”按钮时,出现了错误 'Element is no longer attached to the DOM'

我的代码大约有100行,但我可以给你一个大概的执行流程:

...                    # creating driver object and all the imports
def main():
    ...
    result = find_elements_by_tag_name('span')  
    ...
    driver.find_element_by_id("ctl00_ContentPlaceHolder1_ucDataPager_btnNext").click()
    main()
main()

这段代码在第一页运行得很好,但当再次调用 main() 方法以点击下一页时,就出问题了。在这个递归方法之前,我也尝试过把它放在一个循环里,结果也是同样的错误。

如果我这样写代码:

# some code
result = find_elements_by_tag_name('span')  
driver.find_element_by_id("ctl00_ContentPlaceHolder1_ucDataPager_btnNext").click()
# some code
driver.find_element_by_id("ctl00_ContentPlaceHolder1_ucDataPager_btnNext").click()
.
.

这段代码在加载下一页时没有任何错误,后面的代码也能正常执行。但是我不能为500页都写相同的 driver.find_element_by_id().click(),这样我还得重复每一页相关的其他代码。所以我才尝试使用循环或递归,但对我来说都不管用。

请告诉我,我的方法有什么问题。

2 个回答

1

这看起来是一个“过时元素异常”,通常发生在你试图查找某个元素的时候。这个元素每次都会加载,但你之前已经找到了它,所以它就变成了过时的。

我建议使用一些自定义的方法来避免这个问题,下面是一个最简单的解决方案:

void clickOnStaleElement(String id, WebDriver driver) {
    try {
        driver.find_element_by_id(id).click();
    } catch (StaleElementReferenceException e) {
        // Trying to find element stale element
        clickOnStaleElement(id, driver);
    } catch (NoSuchElementException ele) {
        clickOnStaleElement(id, driver);
    }
 }
8

问题在于,有一些JavaScript代码把这个元素给移除了。所以你需要让驱动程序等一下这个元素的出现:可以通过设置 implicitly_wait 来实现,具体可以参考:

from selenium import webdriver

ff = webdriver.Firefox()
ff.implicitly_wait(10) # seconds
...
myDynamicElement = ff.find_element_by_id("myDynamicElement")

来自 http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp#implicit-waits

撰写回答