Python 元素位置的可见性或元素可点击-最终解决方案?
我读了一些关于在selenium中检查元素在页面上是否可见的功能(对于用户),以便用户可以悬停或单击该元素。 我们有以下选择: 1.所处元素的可见性\u 检查元素是否由DOM中的定位器定位,以及元素是否在网页上可见的预期条件可见性意味着不仅显示元素,而且元素的高度和宽度都大于0。 2.元素可点击 等待定位器标识的元素被启用并可见,以便您可以单击它。请注意,元素应处于可见状态 问题就在这里。 我有一页: 其中,我必须将鼠标悬停在元素上Python 元素位置的可见性或元素可点击-最终解决方案?,python,selenium,visibility,Python,Selenium,Visibility,我读了一些关于在selenium中检查元素在页面上是否可见的功能(对于用户),以便用户可以悬停或单击该元素。 我们有以下选择: 1.所处元素的可见性\u 检查元素是否由DOM中的定位器定位,以及元素是否在网页上可见的预期条件可见性意味着不仅显示元素,而且元素的高度和宽度都大于0。 2.元素可点击 等待定位器标识的元素被启用并可见,以便您可以单击它。请注意,元素应处于可见状态 问题就在这里。 我有一页: 其中,我必须将鼠标悬停在元素上 "button.account-standard__
"button.account-standard__toggle-button"
“框架”展开。
在其中,我必须单击元素`
"div.account-standard__popup button.account-content__button.account-content__button--large"
我希望在等待该元素对用户可见后进行单击-这仅在将鼠标悬停在第一个元素上后才可能发生,但:
如果第二个按钮(即使我没有点击第一个按钮)在DOM中,并且高度和宽度都大于0,该怎么办。
即使用户实际上看不到该条件,也会满足该条件。
在这种情况下,第二种方式(元素可点击)不是更好吗
如果鼠标悬停,但由于某种原因,在selenium找到并单击第二个按钮之前,展开的帧消失/折叠或其他情况会怎样
下面是一个悬停按钮的屏幕(右上角-一个模仿人类的按钮),下面是一个带有“登录”按钮的扩展框架
检查中的选择位于将鼠标悬停在上一个按钮上后出现的第二个按钮中。
还有这些图形值它们始终不变,无论我是否将鼠标悬停在第一个按钮上,它们都不会改变。
除非我的开发工具有问题
我以前写过这些代码。
但我担心它不能预测,例如,当您将鼠标悬停在第一个按钮上时,页面上会加载一些内容,可展开元素会在驱动程序找到第二个按钮并单击之前消失。
我知道我可以使用“wait.untill(ec.visible…),但我希望避免可能的时间异常。
如图所示,当我们将鼠标悬停在按钮1上时,在该Li的最高div中,它出现在类名--“可见”中
def move_to_login_page_from_main_page(驱动程序):
wait=WebDriverWait
CSS\u account=“button.account-standard\u toggle-button”
CSS\u login=“div.account-standard\u弹出按钮。account-content\u按钮。account-content\u按钮--大”
CSS\u roll\u out\u frame=“div.account-standard——可见”
应为\u url=“account.tvn.pl”
尝试次数=0
当尝试0时:
log_in_button=roll_out_frames.find_元素(By.CSS_SELECTOR,CSS_login)
ac(驱动程序)。移动到元素(登录按钮)。单击(登录按钮)。执行()
等待(驱动程序,10,1)。直到(ec.url\u包含(预期的\u url))
打破
其他:
时间。睡眠(1)
尝试次数+=1
def从主页面移动到登录页面(驱动程序):
wait=WebDriverWait
CSS\u account=“button.account-standard\u toggle-button”
CSS\u login=“div.account-standard\u弹出按钮。account-content\u按钮。account-content\u按钮--大”
应为\u url=“account.tvn.pl”
尝试次数=0
虽然下拉元素的定位器不是唯一的,但它正在检测其他元素,请使用:
现在,如果您在不单击下拉按钮的情况下使用下拉内容的可见性,它将超时
driver.get('https://tvn24.pl/')
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,
'#onetrust-accept-btn-handler'))).click()
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,
".account-standard__toggle-button"))).click()
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'[class="account-standard__popup"] button[class="account-content__button account-content__button--large"]')))
这将首先等待接受cookies,然后单击确定,然后单击悬停按钮,然后单击显示的下拉按钮
查找唯一定位器的策略:
如果无法获取元素的唯一属性,请查找唯一的同级、父级或子级,并引用该元素
在这种情况下:
[class="account-standard__popup"]
此父元素是可用于唯一定位子元素的唯一引用:
button[class="account-content__button account-content__button--large"]
回答您的问题:
请参阅is_clickable方法。您可以看到它将首先检查可见性。
因此,如果use you element_是可见的,它将不会检查is_enabled(),否则它将检查按钮是否已启用,这意味着它将确保按钮或元素不具有禁用的html属性
如果按钮是使用css类启用或禁用的,而不是使用HTML disabled属性,那么使用可见性和clicakable之间没有区别
按原样启用将不会通过css检查元素禁用状态,而只通过html禁用属性检查元素禁用状态
class element_to_be_clickable(object):
""" An Expectation for checking an element is visible and enabled such that
you can click it."""
def __init__(self, locator):
self.locator = locator
def __call__(self, driver):
element = visibility_of_element_located(self.locator)(driver)
if element and element.is_enabled():
return element
else:
return False
下拉元素的定位器不是唯一的。如果正在检测其他元素,请使用:
现在,如果您在不单击下拉按钮的情况下使用下拉内容的可见性,它将超时
driver.get('https://tvn24.pl/')
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,
'#onetrust-accept-btn-handler'))).click()
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,
".account-standard__toggle-button"))).click()
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'[class="account-standard__popup"] button[class="account-content__button account-content__button--large"]')))
这将首先等待接受cookies,然后单击确定,然后单击悬停按钮,然后单击显示的下拉按钮
查找唯一定位器的策略:
如果无法获取元素的唯一属性,请查找唯一的同级、父级或子级,并引用该元素
在这种情况下:
[class="account-standard__popup"]
此父元素是可用于唯一定位子元素的唯一引用:
button[class="account-content__button account-content__button--large"]
回答您的问题:
请参阅is_clickable方法。您可以看到它将首先检查可见性。
因此,如果use you element_是可见的,它将不会检查is_enabled(),否则它将检查按钮是否已启用,这意味着它将确保按钮或元素不具有禁用的html属性
如果按钮是使用css类启用或禁用的,而不是使用HTML禁用属性,则使用可见性和clica之间没有区别
function isVisible(elem) {
if (!(elem instanceof Element)) throw Error('DomUtil: elem is not an element.');
const style = getComputedStyle(elem);
if (style.display === 'none') {console.log('display'); return false;}
if (style.visibility !== 'visible') {console.log('visibility'); return false;}
if (style.opacity < 0.1) {console.log('opacity'); return false;}
if (elem.offsetWidth + elem.offsetHeight + elem.getBoundingClientRect().height +
elem.getBoundingClientRect().width === 0) {
console.log('client'); return false;
}
const elemCenter = {
x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
y: elem.getBoundingClientRect().top + elem.offsetHeight / 2
};
if (elemCenter.x < 0) {console.log('x<0'); return false;}
if (elemCenter.x > (document.documentElement.clientWidth || window.innerWidth)) {console.log('width'); return false;}
if (elemCenter.y < 0) {console.log('y<0'); return false;}
if (elemCenter.y > (document.documentElement.clientHeight || window.innerHeight)) {console.log('height'); return false;}
let pointContainer = document.elementFromPoint(elemCenter.x, elemCenter.y);
do {
if (pointContainer === elem) {console.log('point continter'); return true;} else { console.log(pointContainer)}
} while (pointContainer = pointContainer.parentNode);
return false;
}
isVisible(document.getElementsByClassName('account-content__button--large')[1])