首页 > 解决方案 > Python Selenium 悬停动作在内存中连接

问题描述

我正在测试一个网站,该网站的菜单带有悬停时出现的子菜单。

我创建了一个函数来与这个菜单交互:

def go_to(navbar_item, menu_item):
    # find the navbar item
    assets_main_menu = driver.find_element(By.ID, navbar_item)
    #hover over the navbar item, so the submenu appears
    hover.move_to_element(assets_main_menu).perform()
    # find the submenu item
    xpath = "//*[contains(text(), \'" + menu_item + "\')]"
    destination = driver.find_element_by_xpath(xpath)
    # hover over the submenu item and clicks
    hover.move_to_element(destination).click().perform()

问题是我多次使用此功能,例如:

# action 1
go_to('navbar item1 id', 'submenu item1')
do_something()
# action 2
go_to('navbar item1 id', 'submenu item2')
do something()
# action 3
go_to('navbar item1 id', 'submenu item3')
do_something()

selenium 实际上重复了前面的步骤,通过过去的菜单项,例如:

实际输出 动作 1,做某事 -> 动作 1,动作 2,做某事 -> 动作 1,动作 2,动作 3,做某事

相反,我的期望输出将是:

行动1,做某事-> 行动2,做某事-> 行动3,做某事


我尝试取消设置变量:

navbar_item,menu_item,悬停,xpath,目的地。

在函数结束时没有运气。

我也尝试在我的函数中实例化悬停

悬停=动作链(驱动程序);

但在最后一次尝试中,我的代码停止了工作。

标签: pythonseleniummemoryhover

解决方案


当你调用一个动作链时,perform()并没有清除前面的步骤。您只是真正共享了您的函数,因此真正的罪魁祸首是您的代码结构以及 python 如何使用变量。

我在你的函数中注意到,你传入了两个strings,但你的函数知道什么driverhover是什么。听起来您正在使用全局变量。

为了演示您的问题,我使用点击计数器为您创建了这个简单的页面:

<html>
    <body>
        <button id="button" onclick="document.getElementById('input').value = parseInt(document.getElementById('input').value) + 1">Click me</button>
        <input id="input" value="0"></input>
    </body>
</html>

这是一个平面页面,每次按下按钮时都会敲出一个数字: 点击器

然后,为了向您展示发生了什么,我创建了一个类似版本的代码:

driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get(r"c:\git\test.html")

actions = ActionChains(driver)

def ClickByActions(element):
    actions.move_to_element(element).click().perform()

#find the button and click it a few times...
button = driver.find_element_by_id('button')
ClickByActions(button)
ClickByActions(button)
ClickByActions(button)

有了这个,您希望最终点击计数值为 3。但是,它是 6。 在此处输入图像描述

和你的问题一样。第一次调用+1,第二次调用+1+1,第三次调用+1+1+1。

最后!解决方案 - 使用您的驱动程序在函数中创建动作链:

def ClickByActions(element):
    localActions = ActionChains(driver)
    localActions.move_to_element(element).click().perform()

最终结果

我在评论中注意到你说你试过这个。你能试试:

  • 不使用hover但使用另一个名称 -
  • 传入驱动程序而不是依赖它作为全局变量。为此,您将使用go_to(navbar_item, menu_item, driver)
  • 显然hover.reset_actions()也应该工作 - 但这对我不起作用。

如果这些不起作用,请分享您的站点 URL,以便我可以在您的实际站点上尝试或说出错误是什么并描述发生了什么。


推荐阅读