Selenium (Python) - 在启用后单击禁用按钮
Selenium (Python) - click on disabled button after it is enabled
我将 Selenium 与 Python 结合使用来自动执行上传文件的过程。有一个“上传”按钮,默认情况下是禁用的,只有在选择要上传的文件时才可以点击。
禁用按钮的 HTML 是 -
<button type="button" id="upload-button" data-bi-id="upload-button" class="ms-Button ms-Button--primary is-disabled root-296" disabled="" aria-label="Upload" aria-disabled="true" data-is-focusable="false">
按钮变成可点击后的 HTML 是 -
<button type="button" id="upload-button" data-bi-id="upload-button" class="ms-Button ms-Button--primary root-437" aria-label="Upload" data-is-focusable="true" tabindex="0">
我正在使用-
WebDriverWait(browser, 15).until(EC.element_to_be_clickable((By.ID,"upload-button"))).click()
但是它不起作用。我相信这是点击禁用按钮(即使选择了文件并且按钮已变为可点击)。我也试过 -
WebDriverWait(browser, 15).until(EC.element_to_be_clickable((By.CLASS_NAME,"ms-Button ms-Button--primary root-437"))).click()
但这给出了 TimeOut Exception
。那么这个按钮变成可点击后怎么办才能点击呢。我尝试了一些来自 Internet 的解决方案,但其中 none 似乎有效。
您似乎使用了错误的 ID 值。
WebDriverWait(browser, 15).until(EC.element_to_be_clickable((By.ID,"upload-button"))).click()
或者使用这个 css 选择器
WebDriverWait(browser, 15).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#upload-button[data-is-focusable='true']"))).click()
关于您的代码的当前版本,我认为您可能是正确的,它在真正启用之前单击了按钮。你有
WebDriverWait(browser, 15).until(EC.element_to_be_clickable((By.ID,"upload-button"))).click()
您正在等待此元素成为 clickable
。我想尝试弄清楚这到底是什么意思,所以我查看了源代码。 element_to_be_clickable
满意As soon as the element is "visible" and "enabled".
据我所知,可见性定义为 DOM 和 height/width 均 > 0。根据您的描述,听起来您的按钮立即可见。所以一旦“启用”,element_to_be_clickable
就满足了,等待就会结束。
这就引出了一个问题,到底是什么决定了一个元素是否“启用”?我发现selenium的is_enabled
(在源代码中需要element_to_be_clickable
才能通过),本质上是对W3C specification for disabled()
的否定。它归结为这一行,它表示如果 The element is a button, input, select, textarea, or form-associated custom element, and the disabled attribute is specified on this element (regardless of its value).
元素被“禁用”
就是这样。您的元素确实具有“已禁用”属性,但它还有一些其他可能导致它被禁用的东西——class 名称包含 is-disabled
,它有 aria-disabled="true"
以及data-is-focusable="false"
,所有这些都会在按钮完全可点击时发生变化。我想知道 disabled 属性是否先于其他也会导致元素被禁用的东西消失,所以就像你说的那样,也许你的点击在按钮准备好之前就已经注册了。为了调试这个,我会尝试在执行 WebDriverWait
之后和单击按钮之前临时添加一个硬等待,几秒钟。
为了你的 class 名字,
WebDriverWait(browser, 15).until(EC.element_to_be_clickable((By.CLASS_NAME,"ms-Button ms-Button--primary root-437"))).click()
我怀疑这是一个动态的 class 名称,特别是 root-437
部分,所以也许这就是它不起作用的原因。
最后,您是否打算通过单击按钮从您的文件系统上传?因为它只能与您的网络浏览器交互,而不能在您的 OS 上浏览 window,所以这是行不通的。上传文件有一种特殊的方式——您必须识别文件输入元素,并使用 send_keys()
.
将您要上传的文件的绝对路径发送到该元素
如您所见,按钮元素在仍处于禁用状态时包含 class is-disabled
和属性 disabled
,而在启用时不包含这些属性。
所以预期的条件是定位到下面定义的元素 xpath
:
//button[@id='upload-button' and(not(contains(@class,'is-disabled'))) and(not(@disabled))]
换句话说,您应该使用以下内容:
WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.XPATH, "//button[@id='upload-button' and(not(contains(@class,'is-disabled'))) and(not(@disabled))]")))
您也可以根据缺少上述两个属性之一来定位启用的按钮。
尝试使用隐式单击而不显式等待:
driver.implicitly_wait(15)
driver.find_element_by_xpath('//button[@data-is-focusable="true"]').click()
或
driver.implicitly_wait(15)
driver.find_element_by_xpath('//button[@data-is-focusable="true" and @tabindex="0"]').click()
如果这没有帮助,请在您的问题中添加更多详细信息。
我将 Selenium 与 Python 结合使用来自动执行上传文件的过程。有一个“上传”按钮,默认情况下是禁用的,只有在选择要上传的文件时才可以点击。
禁用按钮的 HTML 是 -
<button type="button" id="upload-button" data-bi-id="upload-button" class="ms-Button ms-Button--primary is-disabled root-296" disabled="" aria-label="Upload" aria-disabled="true" data-is-focusable="false">
按钮变成可点击后的 HTML 是 -
<button type="button" id="upload-button" data-bi-id="upload-button" class="ms-Button ms-Button--primary root-437" aria-label="Upload" data-is-focusable="true" tabindex="0">
我正在使用-
WebDriverWait(browser, 15).until(EC.element_to_be_clickable((By.ID,"upload-button"))).click()
但是它不起作用。我相信这是点击禁用按钮(即使选择了文件并且按钮已变为可点击)。我也试过 -
WebDriverWait(browser, 15).until(EC.element_to_be_clickable((By.CLASS_NAME,"ms-Button ms-Button--primary root-437"))).click()
但这给出了 TimeOut Exception
。那么这个按钮变成可点击后怎么办才能点击呢。我尝试了一些来自 Internet 的解决方案,但其中 none 似乎有效。
您似乎使用了错误的 ID 值。
WebDriverWait(browser, 15).until(EC.element_to_be_clickable((By.ID,"upload-button"))).click()
或者使用这个 css 选择器
WebDriverWait(browser, 15).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#upload-button[data-is-focusable='true']"))).click()
关于您的代码的当前版本,我认为您可能是正确的,它在真正启用之前单击了按钮。你有
WebDriverWait(browser, 15).until(EC.element_to_be_clickable((By.ID,"upload-button"))).click()
您正在等待此元素成为 clickable
。我想尝试弄清楚这到底是什么意思,所以我查看了源代码。 element_to_be_clickable
满意As soon as the element is "visible" and "enabled".
据我所知,可见性定义为 DOM 和 height/width 均 > 0。根据您的描述,听起来您的按钮立即可见。所以一旦“启用”,element_to_be_clickable
就满足了,等待就会结束。
这就引出了一个问题,到底是什么决定了一个元素是否“启用”?我发现selenium的is_enabled
(在源代码中需要element_to_be_clickable
才能通过),本质上是对W3C specification for disabled()
的否定。它归结为这一行,它表示如果 The element is a button, input, select, textarea, or form-associated custom element, and the disabled attribute is specified on this element (regardless of its value).
就是这样。您的元素确实具有“已禁用”属性,但它还有一些其他可能导致它被禁用的东西——class 名称包含 is-disabled
,它有 aria-disabled="true"
以及data-is-focusable="false"
,所有这些都会在按钮完全可点击时发生变化。我想知道 disabled 属性是否先于其他也会导致元素被禁用的东西消失,所以就像你说的那样,也许你的点击在按钮准备好之前就已经注册了。为了调试这个,我会尝试在执行 WebDriverWait
之后和单击按钮之前临时添加一个硬等待,几秒钟。
为了你的 class 名字,
WebDriverWait(browser, 15).until(EC.element_to_be_clickable((By.CLASS_NAME,"ms-Button ms-Button--primary root-437"))).click()
我怀疑这是一个动态的 class 名称,特别是 root-437
部分,所以也许这就是它不起作用的原因。
最后,您是否打算通过单击按钮从您的文件系统上传?因为它只能与您的网络浏览器交互,而不能在您的 OS 上浏览 window,所以这是行不通的。上传文件有一种特殊的方式——您必须识别文件输入元素,并使用 send_keys()
.
如您所见,按钮元素在仍处于禁用状态时包含 class is-disabled
和属性 disabled
,而在启用时不包含这些属性。
所以预期的条件是定位到下面定义的元素 xpath
:
//button[@id='upload-button' and(not(contains(@class,'is-disabled'))) and(not(@disabled))]
换句话说,您应该使用以下内容:
WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.XPATH, "//button[@id='upload-button' and(not(contains(@class,'is-disabled'))) and(not(@disabled))]")))
您也可以根据缺少上述两个属性之一来定位启用的按钮。
尝试使用隐式单击而不显式等待:
driver.implicitly_wait(15)
driver.find_element_by_xpath('//button[@data-is-focusable="true"]').click()
或
driver.implicitly_wait(15)
driver.find_element_by_xpath('//button[@data-is-focusable="true" and @tabindex="0"]').click()
如果这没有帮助,请在您的问题中添加更多详细信息。