2017-02-27 55 views
1

因此,我正在循环浏览一堆网页。目前,网页的结构都与后退按钮和前进按钮(//span/a)[2]相同。出于某种原因,我可以循环浏览第一页(有时是第二页)。但是我继续获得StaleElementReferenceException遍历页面并在Python中获取StaleElementReferenceException Selenium

下面是相关的代码:

for x in range(0,5): 
    print 'page %d' %(x) 
    WebDriverWait(driver, 10).until(
     EC.presence_of_element_located((By.XPATH, "(//span/a)[2]")) 
    ) 
    listItems = driver.find_elements_by_xpath("//td[@class='CourseCode']/a") 
    for element in listItems: 
     elementText = element.text 
     print(elementText) 
     writeFile.write(element.text + '\n') 
    driver.find_element_by_xpath("(//span/a)[2]").click() 

尤其这里是堆栈跟踪:

Traceback (most recent call last): 
File "getList.py", line 21, in lookup 
addListItems(driver, courseCodeFile) 
File "getList.py", line 44, in addListItems 
elementText = element.text 
File "/home/francisco/.local/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py", line 73, in text 
return self._execute(Command.GET_ELEMENT_TEXT)['value'] 
File "/home/francisco/.local/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py", line 494, in _execute 
return self._parent.execute(command, params) 
File "/home/francisco/.local/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 236, in execute 
self.error_handler.check_response(response) 
File "/home/francisco/.local/lib/python2.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 192, in check_response 
raise exception_class(message, screen, stacktrace) 
StaleElementReferenceException: Message: The element reference is stale. Either the element is no longer attached to the DOM or the page has been refreshed. 

我已经尝试了一堆没有用。奇怪的是,如果没有循环,我能够让这个函数正常工作两页。

在RTE之前的注意事项中,它将打印前一页中获得的前两个元素listItems的文本。

回答

1

您可以通过在WebDriverWait中使用stalenessOfExpected Condition来避免StaleElementReferenceExpection


StaleElementReferenceExpection发生在两种情况为例:

  1. 的元件已被完全删除。
  2. 该元素不再附加到DOM。

当您使用共同定位器在所有的网页,一旦你点击一个元素,硒仍引用到上一个页面中的定位器(DOM is NOT yet updated, still referencing to the old web page)

一个简单的解决方案是增加time.sleep在代码的结束,使DOM将得到更新,定位器将在DOM应用新的网页。

for x in range(0,5): 
    print 'page %d' %(x) 
    WebDriverWait(driver, 10).until(
     EC.presence_of_element_located((By.XPATH, "(//span/a)[2]")) 
    ) 
    listItems = driver.find_elements_by_xpath("//td[@class='CourseCode']/a") 
    for element in listItems: 
     elementText = element.text 
     print(elementText) 
     writeFile.write(element.text + '\n') 
    driver.find_element_by_xpath("(//span/a)[2]").click() 
    import time 
    time.sleep(0.5) //0.5 seconds 

另一种解决方案是检查在每个网页的独特元素,(如果你使用if-else & indexing等可能的)

+0

只是一些小的澄清,这可能无法在for loop。那么WebDriverWait的重点是什么?据我所知,这是等到该元素被加载。但是在这种情况下,它是否仍然引用旧的DOM? – Francisco

+1

是的,WebDriverWait将等待一些条件满足,比如Presence_Of_Element,Visibiliti_Of_Element等等。在您的情况下,因为定位符是相同的,它们都出现在当前页面和前一页面的DOM中,并给出异常。在这里寻找更多细节http://stackoverflow.com/questions/16166261/selenium-webdriver-how-to-resolve-stale-element-reference-exception&https://seleniumhq.github.io/selenium/docs/api /java/org/openqa/selenium/support/ui/ExpectedConditions.html#stalenessOf-org.openqa.selenium.WebElement-。试着用'stalenessOf'的条件代替睡眠。 –

+0

使用'staleness_of',它完美运行。如果你想更新你的答案,在'click()'之后的'(// span/a)[2]''上使用'staleness_of'。我很乐意选择这个解决方案。 – Francisco