Selenium 无法点击元素,因为其他元素遮住了它

Selenium can't click element because other element obscures it

设置

我正在使用 Python 3.x 和 Selenium 来填写查询字段,然后单击搜索按钮,

# element containing the product search bar and buttons
search_area = el_id('Products').find_element_by_class_name('searchArea')

# insert name of file to be duplicated
name_field = search_area.find_element_by_xpath("//input[@type='text']")
name_field.clear()
name_field.send_keys('to_be_duplicated')  

# click search button
search_area.find_element_by_xpath('span/a[1]').click()

其中 el_id(x) = browser.find_element_by_id(x).


问题

执行上面的代码会出现以下错误,

ElementClickInterceptedException: Element <a class="button button-fleft searchButton" href="#"> is not clickable at point (577.6166763305664,225.06666564941406) because another element <div class="blockUI blockOverlay"> obscures it

我可以通过在抓取并单击按钮之前插入一个硬等待来解决这个错误,就像这样,

# click search button
time.sleep(1)
search_area.find_element_by_xpath('span/a[1]').click()

但我宁愿用不同的方式解决它,所以我按照 this answer 做了以下操作,

# click search button
search_button = search_area.find_element_by_xpath('span/a[1]')
WebDriverWait(driver, 10).until_not(EC.visibility_of_element_located((By.XPATH, 
"//*[@id="Products"]/tbody/tr[1]/td/div/input")))
search_button.click()

但我得到了完全相同的错误。

我也试过this answer,但同样的错误。

我该如何解决这个问题?

有几种方法可以做到这一点,其中一种方法是 Javascript 执行者。

你可以说:

element = driver.find_element_by_xpath("//div[@class='blockUI blockOverlay']")

driver.execute_script("arguments[0].style.visibility='hidden'", element)

这样,您可以用 class = 'blockUI blockOverlay' 屏蔽 div 如果我是正确的,你的元素可以被点击。

的 nr.5 之后,我通过暗示代码在尝试单击之前等待临时覆盖消失来解决它,

wait.until(EC.invisibility_of_element_located((By.XPATH,
              "//div[@class='blockUI blockOverlay']")))
el_xp("//input[@value='Save']").click()

此外,您可以尝试通过 JavaScript 单击该元素,如下所示:


# element containing the product search bar and buttons
search_area = el_id('Products').find_element_by_class_name('searchArea')

# click element by executing javascript
driver.execute_script("arguments[0].click();", search_area)

接受的答案要求您知道哪个元素将用作叠加层。如果这种期望不正确(正如@Blaszard 在接受的答案下的评论中提到的那样),那么您可以使用这个通用函数来获取显示在另一个元素上方的任何元素:

def getOverlappingElement(driver: WebDriver, element: WebElement) -> Optional[WebElement]:
  rect = element.rect
  result = driver.execute_script("return document.elementFromPoint(arguments[0], arguments[1]);",
                                 rect['x'] + rect['width'] // 2, rect['y'] + rect['height'] // 2)
  if result == element:
    result = None
  return result

当你像 getOverlappingElement(button) 这样调用函数时,它将 return 显示在 button 上方的元素或它 returns None,当button 没有重叠。

该方法不包括元素部分重叠的情况。 大多数情况下,当整个页面被加载动画或广告覆盖时,它是有效的。