在抓取数据时,Selenium错误“元素不再附加到DOM”

时间:2013-09-24 00:13:04

标签: python dom selenium exception-handling selenium-webdriver

        for i in driver.find_elements_by_class_name("endorse-count"):
            try:
                i.click()
            except:
                continue

            elem = WebDriverWait(driver, 100).until(EC.presence_of_element_located((By.CLASS_NAME, "dialog-window")))
            src = elem.get_attribute("innerHTML")

            add_skill(name, src)

            WebDriverWait(driver, timeout=10)

运行上面的代码时出现以下错误 -

selenium.common.exceptions.StaleElementReferenceException: Message: u'Element is no longer attached to the DOM' ; Stacktrace: 
    at fxdriver.cache.getElementAt (resource://fxdriver/modules/web_element_cache.js:7646)

代表行 -

src = elem.get_attribute("innerHTML")

登录后,我在LinkedIn用户个人资料页面上运行此代码。

我尝试在“i.click()” -

之后添加以下代码行
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

但后来我看到函数“add_skill(name,src)”没有被调用,并且没有调用driver.manage()之后的代码,虽然for循环和i.click()工作正常。

3 个答案:

答案 0 :(得分:1)

在确认目标元素已在页面上呈现之前,Selenium正在尝试完成操作(例如单击按钮或链接)。硒可能更耐心,但你必须明确地要求他。

例如,如果您正在测试发出AJAX请求的内容,您可以尝试这样的(在Ruby中):

# timeout is in seconds
def wait_for_ajax(timeout=x)
 time_limit, interval = (Time.now + timeout), 0.5
 loop do
   break if @driver.execute_script "return jQuery.active == 0"
   sleep interval
   raise "Wait for AJAX timed out after waiting for #{timeout} seconds" if Time.now > time_limit
 end
end

为了确保您的测试完全全面,请始终让Selenium在运行任务之前等待加载元素。

答案 1 :(得分:1)

我遇到了类似的问题,并在找到该元素之前尝试刷新页面,并且它有效...

driver.navigate().refresh();

虽然我无法推断这是如何运作的。

如果这对你有用,请告诉我。我只是想了解更多有关此例外的信息。

you can refer this page to learn about a similar issue

答案 2 :(得分:0)

我在尝试执行一些javascript(IJavaScripExecutor)时遇到了类似的问题。我创建了一个IWebElement并将其传递给JSE,但对我来说失败了。当我将driver.FindElement(BySelector)移动到我的JSE调用中时,它就可以了。 (C#代码提前。)

而不是:

IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
IWebElement tableEl = driver.FindElement(selector);
js.ExecuteScript(script, tableEl);

我必须这样做:

IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
js.ExecuteScript(script, driver.FindElement(selector));

您可能需要做类似的事情:将您的选择器或元素创建移动到您尝试执行的同一行。或者,也许,在你的情况下:

src = driver.find_element_by_class_name("dialog-window").get_attribute("innerHTML")

仔细检查后,这就是您的问题,当您尝试使用get_attribute方法时,会有一个陈旧的Web元素对象。