我正在制作一些站点地图/树(使用anytree),为了做到这一点,我需要Selenium在页面上找到特定元素(代表类别),然后系统地点击这些元素,在每个新页面上寻找新的类别,直到我们没有更多的类别,即。所有树叶和树都填充了。
我已经写了很多这个。尝试迭代我的元素列表时出现了我的问题。我目前尝试填充树的深度优先,向下到叶子,然后弹回到原始页面继续与列表中的下一个元素相同的事情。但是,这会导致Stale element reference
错误,因为我的页面会重新加载。这是一个什么解决方法?我可以以某种方式在新窗口中打开新链接,以便保留旧页面吗?我发现这个例外的唯一修复是整齐地抓住它,但这对我没有帮助。
到目前为止,这是我的代码(问题出在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))
答案 0 :(得分:1)
我还没有在python中工作但是曾经在java / selenium上工作过。但是,我可以给你一个克服陈旧性的想法。
一般来说,如果在启动webelement之后更改了元素属性或某些内容,我们将获得Stale Exception。例如,在某些情况下,如果用户尝试在同一页面上单击同一元素但在页面刷新后,则会获取staleelement异常。
为了解决这个问题,我们可以创建新的webelement,以防页面被更改或刷新。下面的代码可以给你一些想法。(它在java中,但概念将是相同的)
示例:强>
webElement element = driver.findElement(by.xpath("//*[@id='StackOverflow']"));
element.click();
//page is refreshed
element.click();//This will obviously throw stale exception
为了解决这个问题,我们可以将xpath存储在某个字符串中,然后使用它创建一个新的webelement。
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
希望这会对你有所帮助。
答案 1 :(得分:0)
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()