如何使用 Selenium 单击多个元素同时避免陈旧元素错误
How to use Selenium to click through multiple elements while avoiding Stale Element Error
我正在努力制作一个网站 map/tree(使用 anytree),为了做到这一点,我需要 Selenium 来查找页面上的特定元素(代表类别),然后系统地点击这些元素,在每个新页面上寻找新类别,直到我们没有找到更多类别,即。所有的叶子和树都被填充了。
我已经写了很多。尝试遍历我的元素列表时出现我的问题。我目前尝试以深度优先的方式填充树,向下填充到叶子,然后弹出回到原始页面,以对列表中的下一个元素继续相同的操作。但是,这会导致 Stale element reference
错误,因为我的页面会重新加载。有什么解决方法?我能否以某种方式在新 window 中打开新链接,以便保留旧页面?我为该异常找到的唯一修复方法是巧妙地捕获它,但这对我没有帮助。
到目前为止,这是我的代码(问题出在 for 循环中):
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 工作过。但是,我可以给你克服陈旧的想法。
通常,如果在启动 web 元素后元素属性或某些内容发生更改,我们将收到 Stale Exception。例如,在某些情况下,如果用户尝试单击同一页面上的同一元素,但在页面刷新后,会出现 staleelement 异常。
为了克服这个问题,我们可以创建新的网络元素以防页面更改或刷新。下面的代码可以给你一些想法。(它在 java 但概念是一样的)
示例:
webElement element = driver.findElement(by.xpath("//*[@id='Whosebug']"));
element.click();
//page is refreshed
element.click();//This will obviously throw stale exception
为了克服这个问题,我们可以将 xpath 存储在一些字符串中,并使用它创建一个新的网络元素。
String xpath = "//*[@id='Whosebug']";
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
希望对您有所帮助。
xpath 变量不是星号,它是所需元素的 xpath。出现陈旧异常,因为我们在浏览器中单击了某些内容。这需要在您每次单击时找到所有元素。所以在每个循环中我们找到所有元素 driver.find_elements_by_xpath(xpath)。我们得到一个元素列表。但那时我们只需要其中之一。因此,我们采用特定索引处的元素表示 idx,其范围从 0 到元素数。
xpath = '*'
for idx, _ in enumerate(range(len(driver.find_elements_by_xpath(xpath)))):
element = driver.find_elements_by_xpath(xpath)[idx]
element.click()
我正在努力制作一个网站 map/tree(使用 anytree),为了做到这一点,我需要 Selenium 来查找页面上的特定元素(代表类别),然后系统地点击这些元素,在每个新页面上寻找新类别,直到我们没有找到更多类别,即。所有的叶子和树都被填充了。
我已经写了很多。尝试遍历我的元素列表时出现我的问题。我目前尝试以深度优先的方式填充树,向下填充到叶子,然后弹出回到原始页面,以对列表中的下一个元素继续相同的操作。但是,这会导致 Stale element reference
错误,因为我的页面会重新加载。有什么解决方法?我能否以某种方式在新 window 中打开新链接,以便保留旧页面?我为该异常找到的唯一修复方法是巧妙地捕获它,但这对我没有帮助。
到目前为止,这是我的代码(问题出在 for 循环中):
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 工作过。但是,我可以给你克服陈旧的想法。
通常,如果在启动 web 元素后元素属性或某些内容发生更改,我们将收到 Stale Exception。例如,在某些情况下,如果用户尝试单击同一页面上的同一元素,但在页面刷新后,会出现 staleelement 异常。
为了克服这个问题,我们可以创建新的网络元素以防页面更改或刷新。下面的代码可以给你一些想法。(它在 java 但概念是一样的)
示例:
webElement element = driver.findElement(by.xpath("//*[@id='Whosebug']"));
element.click();
//page is refreshed
element.click();//This will obviously throw stale exception
为了克服这个问题,我们可以将 xpath 存储在一些字符串中,并使用它创建一个新的网络元素。
String xpath = "//*[@id='Whosebug']";
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
希望对您有所帮助。
xpath 变量不是星号,它是所需元素的 xpath。出现陈旧异常,因为我们在浏览器中单击了某些内容。这需要在您每次单击时找到所有元素。所以在每个循环中我们找到所有元素 driver.find_elements_by_xpath(xpath)。我们得到一个元素列表。但那时我们只需要其中之一。因此,我们采用特定索引处的元素表示 idx,其范围从 0 到元素数。
xpath = '*'
for idx, _ in enumerate(range(len(driver.find_elements_by_xpath(xpath)))):
element = driver.find_elements_by_xpath(xpath)[idx]
element.click()