2

我正在制作一些站点地图/树(使用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))
4

2 回答 2

3

我没有在 python 中工作过,但在 java/selenium 上工作过。但是,我可以给你克服陈旧的想法。

通常,如果在启动 web 元素后元素属性或某些内容发生更改,我们将收到 Stale Exception。例如,在某些情况下,如果用户尝试单击同一页面上的同一元素,但在页面刷新后,会出现 staleelement 异常。

为了克服这个问题,我们可以创建新的 web 元素,以防页面发生更改或刷新。下面的代码可以给你一些想法。(它在java中,但概念是一样的)

例子:

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

为了克服这个问题,我们可以将 xpath 存储在一些字符串中,并使用它来创建一个新的 web 元素。

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

希望这对您有所帮助。

于 2017-06-19T14:49:02.373 回答
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()
于 2020-07-16T07:12:35.103 回答