3

我不知道为什么move_to_element()ActionChains 不适用于 chromedriver >74。

(但它适用于 chromedriver 74 和 geckodriver。)

即使我在 ActionChains 之前添加了这三行,它仍然无法移动到元素。

WebDriverWait(driver, 60).until(EC.presence_of_element_located((By.XPATH, xxxxx)))
WebDriverWait(driver, 60).until(EC.visibility_of_element_located((By.XPATH, xxxxx))
drvier.execute_script("arguments[0].scrollIntoView();", element)

ActionChains(driver).move_to_element(element).click().perform()

并抛出如下错误:

selenium.common.exceptions.MoveTargetOutOfBoundsException:消息:将目标移出边界(会话信息:chrome=79.0.3945.117)

我也尝试使用Selenium MoveTargetOutOfBoundsException 中提到的 move_to_element_with_offset 即使在滚动到 element 之后,它仍然无法正常工作:

ActionChains(driver).move_to_element_with_offset(element, 5, 5).click().perform()

下面是我的 chromedriver 设置。对 ActionChains 有任何设置影响吗?

options = webdriver.ChromeOptions()
options.add_argument('--no-sandbox')
options.add_argument('log-level=3')
options.add_argument('--disable-dev-shm-usage')
options.add_argument('--no-proxy-server')
options.add_argument('--disable-extensions')
options.add_argument('--disable-infobars')
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(executable_path=chromedriver_path, chrome_options=options)
4

2 回答 2

2

由于您的用途是click()通过ActionChains而不是调用,presence_of_element_located()因此visibility_of_element_located()您需要使用expected_conditions,如下element_to_be_clickable()所示:

  • ActionChains一起使用:

    ActionChains(driver).move_to_element(WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "element_css")))).click().perform()
    
  • 如果你必须scrollIntoView()在调用之前click()你需要诱导WebDriverWait并且visibility_of_element_located()你可以使用以下 Locator Strategy

    WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, xxxxx))
    drvier.execute_script("arguments[0].scrollIntoView();", WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, xxxxx)))
    ActionChains(driver).move_to_element(WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "element_css")))).click().perform()
    
  • 注意:您必须添加以下导入:

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    

其他注意事项

确保这件事:

  • Selenium升级到当前级别版本 3.141.59
  • ChromeDriver已更新至当前ChromeDriver v79.0.3945.36级别。
  • Chrome已更新到当前的Chrome 版本 79.0级别。(根据ChromeDriver v79.0 发行说明
  • 通过IDE清理项目工作区并仅使用所需的依赖项重建项目。
  • 如果您的基本Web Client版本太旧,请通过Revo Uninstaller卸载它并安装最新的 GA 和已发布版本的Web Client
  • 重新启动系统
  • @Test非 root用户身份执行。
  • 始终driver.quit()tearDown(){}方法内调用以优雅地关闭和销毁WebDriverWeb 客户端实例。

更新

根据您的评论:

options.add_experimental_option('w3c', False)

为您工作,但根据ChromeDriver 75.0.3770.8的发行说明

已解决的问题 2536:将标准模式 (goog:chromeOptions.w3c:true) 设为默认模式 [Pri-2]

ChromeDriver 75.0解决了这个问题。

所以底线是,chromeOptions.w3c需要设置为true默认值。w3cchromedriver中关闭以解决错误将违反最佳实践。我们已经在以下讨论中详细讨论了这个问题:

于 2020-01-20T08:43:51.523 回答
2

move_to_element内部使用move_to

def move_to_element(self, to_element):
    if self._driver.w3c: # default in chromedriver 79
        self.w3c_actions.pointer_action.move_to(to_element)

def move_to(self, element, x=None, y=None):
    #...
    el_rect = element.rect
    left_offset = el_rect['width'] / 2
    top_offset = el_rect['height'] / 2
    left = -left_offset + (x or 0)
    top = -top_offset + (y or 0)

    self.source.create_pointer_move(origin=element, x=int(left), y=int(top))

鼠标指针根据元素位置移动偏移量。您正在定位元素,然后使用 JavaScript 将其滚动到视图中,因此偏移量是由错误的坐标计算的。

删除 JavaScript 滚动应该可以解决问题。

于 2020-01-20T09:24:03.930 回答