如何使用Selenium来单击多个元素,同时避免过时的元素错误 [英] How to use Selenium to click through multiple elements while avoiding Stale Element Error

查看:575
本文介绍了如何使用Selenium来单击多个元素,同时避免过时的元素错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在某种程度上制作站点地图/树(使用anytree),为此,我需要Selenium在页面上查找特定元素(代表类别),然后系统地单击这些元素,以查找在每个新页面上查找新类别,直到我们不再点击其他类别为止.所有的叶子和树被填充.

I'm working on making somewhat of a site map/tree (using anytree) and in order to do so, I need Selenium to find particular elements on a page (representing categories) and then systematically click through these elements, looking for new categories on each new page until we hit no more categories, ie. all leaves and the tree is populated.

我已经写了很多这样的书.尝试遍历元素列表时会出现我的问题.我目前尝试先深度填充树,然后到树叶,然后再弹出回到原始页面,以与列表中的下一个元素继续相同的操作.但是,这会导致Stale element reference错误,因为我的页面会重新加载.有什么解决方法?我可以以某种方式在新窗口中打开新链接,以便保留旧页面吗?我找到的唯一解决该异常的方法是巧妙地捕获它,但这对我没有帮助.

I have much of this already written. My issue arises when trying to iterate through my elements list. I currently try to populate the tree depth-first, going down to the leaves and then popping back up to the original page to continue the same thing with the next element in the list. This, however, is resulting in a Stale element reference error because my page reloads. What is a workaround to this? Can I somehow open the new links in a new window so that the old page is preserved? The only fixes I have found for that exception are to neatly catch it, but that doesn't help me.

到目前为止,这是我的代码(问题出在for循环中):

Here is my code so far (the issue lies in the for loop):

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from anytree import Node, RenderTree

def findnodes(driver) :
    driver.implicitly_wait(5)
    try:
        nodes = driver.find_elements_by_css_selector('h3.ng-binding')
    except:
        nodes = []
    return nodes

def populateTree(driver, par) :

    url = driver.current_url
    pages = findnodes(driver)
    if len(pages)>0 :
        for page in pages:
            print(page.text)
            Node(page.text, parent=par)
            page.click()
            populateTree(driver, page.text)
            driver.get(url)

driver = webdriver.Chrome()
#Get starting page
main ='http://www.example.com'
root = Node(main)
driver.get(main)

populateTree(driver, root)

for pre, fill, node in RenderTree(root):
    print("%s%s" % (pre, node.name))

推荐答案

我尚未在python中工作,但已在java/selenium上工作.但是,我可以为您提供克服陈旧的想法.

I haven't worked in python but have worked on java/selenium. But,I can give you the idea to overcome staleness.

通常,如果在启动Webelement后更改了元素属性或某些内容,则将获得Stale Exception.例如,在某些情况下,如果用户尝试在同一页面上单击同一元素,但在页面刷新后单击,则会获得跟踪例外.

Generally we will be getting the Stale Exception if the element attributes or something is changed after initiating the webelement. For example, in some cases if user tries to click on the same element on the same page but after page refresh, gets staleelement exception.

为克服这个问题,如果页面被更改或刷新,我们可以创建新的web元素.下面的代码可以给您一些想法(它在Java中,但是概念是相同的)

To overcome this, we can create the fresh webelement in case if the page is changed or refreshed. Below code can give you some idea.(It's in java but the concept will be same)

示例:

 webElement element = driver.findElement(by.xpath("//*[@id='StackOverflow']"));
 element.click();
 //page is refreshed
 element.click();//This will obviously throw stale exception

要克服这一点,我们可以将xpath存储在某个字符串中,并在使用时使用它创建一个全新的Web元素.

To overcome this, we can store the xpath in some string and use it create a fresh webelement as we go.

String xpath = "//*[@id='StackOverflow']";
driver.findElement(by.xpath(xpath)).click();
//page has been refreshed. Now create a new element and work on it
driver.findElement(by.xpath(xpath)).click();   //This works

希望这对您有所帮助.

这篇关于如何使用Selenium来单击多个元素,同时避免过时的元素错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆