因为在Selenium网络自动化中元素无法交互,所以无法发送键。

huangapple go评论73阅读模式
英文:

I cannot send keys because element not interactable in selenium web automation

问题

在以下代码中,我无法在相应的字段中发送用户名或密码。我每次都收到一个"元素不可交互"的异常。请问有人可以告诉我如何解决这个问题吗?

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException, ElementNotInteractableException
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
import sys

def main():
    path = r'path\to\chromedriver.exe'
    options = webdriver.ChromeOptions()
    driver = webdriver.Chrome(executable_path=path, options=options)
    driver.get("https://banking.dkb.de/login")

    try:
        # 接受cookies #
        frame = driver.find_element(By.XPATH, "//iframe[@id='privacy-iframe']")
        driver.switch_to.frame(frame)
        button = driver.find_element(By.XPATH, "//button[@aria-label='Refuse all cookies']")
        button.click()

        # 为了能够在接受cookies后找到元素
        driver.get("https://banking.dkb.de/login")

        # 登录
        element = driver.find_element(By.XPATH, "//input[@id='username']")
        element.send_keys("123456789")
        element = driver.find_element(By.XPATH, "//input[@id='password']")
        element.send_keys("abcdefg")
        element = driver.find_element(By.XPATH, "//div[@class='sc-11z3xzm-3 bFajen']/button")
        element.click()

    except NoSuchElementException:
        print('元素未找到')
        driver.close()
        driver.quit()
        sys.exit(0)

    except TimeoutException:
        print('超时异常')
        driver.close()
        driver.quit()
        sys.exit(0)

    except ElementNotInteractableException:
        print('元素不可交互')
        driver.close()
        driver.quit()
        sys.exit(0)

main()

网站HTML的屏幕截图

我尝试设置隐式等待和显式等待,以及通过JavaScript点击字段来设置值,但仍然没有起作用。有人可以帮助我解决这个问题吗?

英文:

In the code below I cannot send the username or password in the corresponding fields. I receive every time an "Element not interactable" exception. Could anyone please tell me how to solve the problem?

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException, ElementNotInteractableException
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
import sys


def main():
    path = r'path\to\chromedriver.exe'
    options = webdriver.ChromeOptions()
    driver = webdriver.Chrome(executable_path=path, options=options)
    driver.get("https://banking.dkb.de/login")

    try:
        # Accept cookies #
        frame = driver.find_element(By.XPATH, "//iframe[@id='privacy-iframe']")
        driver.switch_to.frame(frame)
        button = driver.find_element(By.XPATH, "//button[@aria-label='Refuse all cookies']")
        button.click()

        # In order to be able to find the elements after accepting cookies
        driver.get("https://banking.dkb.de/login")

        #Logging in
        element = driver.find_element(By.XPATH, "//input[@id='username']")
        element.send_keys("123456789")
        element = driver.find_element(By.XPATH, "//input[@id='password']")
        element.send_keys("abcdefg")
        element = driver.find_element(By.XPATH, "//div[@class='sc-11z3xzm-3 bFajen']/button")
        element.click()

    except NoSuchElementException:
        print('Element not found')
        driver.close()
        driver.quit()
        sys.exit(0)

    except TimeoutException:
        print('Timeout exception')
        driver.close()
        driver.quit()
        sys.exit(0)

    except ElementNotInteractableException:
        print('Element not interactable')
        driver.close()
        driver.quit()
        sys.exit(0)


main()

Screenshot of the Website HTML

I tried setting an implicit and explicit wait and setting the value through a javascript clicking the field but still didn't work. Could anyone please help me to solve the problem?

答案1

得分: 0

Selenium Actions应该能帮助您在这种情况下

from selenium.webdriver.common.action_chains import ActionChains

actions = ActionChains(driver)
driver.find_element(By.CSS_SELECTOR("[data-testid=sui-input-username]")).click();
# 登录
element = driver.find_element(By.XPATH, "//input[@id='username']")
actions.send_keys('login', element).perform()

我在Java中为您的网站采用了类似的方法,它对我有效。此外,我认为您在关闭Cookie模态窗口后不需要刷新页面。您只需等待模态窗口不可见,然后切换回默认上下文。

检查模态窗口的不可见性

refuseButtonSelector = "//button[@aria-label='Refuse all cookies']"
wait = WebDriverWait(driver, 10)
button = driver.find_element(By.XPATH, refuseButtonSelector)
button.click()

wait.until(EC.invisibility_of_element_located((By.XPATH, refuseButtonSelector)))
driver.switch_to.default_content()
英文:

Selenium Actions should help you in this case

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

from selenium.webdriver.common.action_chains import ActionChains
actions = ActionChains(driver)
driver.find_element(By.CSS_SELECTOR(&quot;[data-testid=sui-input-username]&quot;)).click();
#Logging in
element = driver.find_element(By.XPATH, &quot;//input[@id=&#39;username&#39;]&quot;)
actions.send_keys(&#39;login&#39;, element).perform()

<!-- end snippet -->

I did similar approach for your site in Java and it worked for me.
Also I think you don't need to refresh page after cookies modal is closed.
You just need to wait for modal to be not visible and switch to default context after that.

Check modal for invisbility

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

refuseButtonSelector = &quot;//button[@aria-label=&#39;Refuse all cookies&#39;]&quot;
wait = WebDriverWait(driver, 10)
button = driver.find_element(By.XPATH, refuseButtonSelector)
button.click()
wait.until(EC.invisibility_of_element_located((By.XPATH, refuseButtonSelector)))
driver.switch_to.default_content()

<!-- end snippet -->

答案2

得分: 0

以下是翻译好的部分:

这是完整的解决方案
```python
import time
from selenium.webdriver import Chrome, Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
import selenium.webdriver.support.expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains

def main():
    driver = Chrome()
    driver.get("https://banking.dkb.de/login")
    wait = WebDriverWait(driver, 10)

    # 切换到iframe并点击拒绝所有cookie的按钮
    iframe = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'iframe#privacy-iframe')))
    driver.switch_to.frame(iframe)
    driver.find_element(By.CSS_SELECTOR, 'button.btn.refuse-all').click()

    driver.get("https://banking.dkb.de/login")

    actions = ActionChains(driver)

    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'div[data-testid="sui-input-username"]'))).click()
    username = driver.find_element(By.CSS_SELECTOR, 'input#username')
    actions.move_to_element(username).send_keys('123456789').perform()

    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'div[data-testid="sui-input-password"]'))).click()
    password = driver.find_element(By.CSS_SELECTOR, 'input#password')
    actions.move_to_element(password).send_keys('abcdefg').perform()

    password.send_keys(Keys.ENTER)
    time.sleep(2)

main()

输出:

因为在Selenium网络自动化中元素无法交互,所以无法发送键。

一些注意事项

  • 网站可能会在iframe中显示一个cookie同意弹出窗口。因此,切换到相应的iframe并点击按钮拒绝所有cookie。

    iframe = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'iframe#privacy-iframe')))
    driver.switch_to.frame(iframe)
    driver.find_element(By.CSS_SELECTOR, 'button.btn.refuse-all').click()
    
  • 初始化ActionChains以执行鼠标移动和按键操作。

    actions = ActionChains(driver)
    
  • 使用提供的凭据登录,找到用户名输入字段,点击它,并输入用户名。

    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'div[data-testid="sui-input-username"]'))).click()
    username = driver.find_element(By.CSS_SELECTOR, 'input#username')
    actions.move_to_element(username).send_keys('123456789').perform()
    
  • 找到密码输入字段,点击它,并输入密码。

    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'div[data-testid="sui-input-password"]'))).click()
    password = driver.find_element(By.CSS_SELECTOR, 'input#password')
    actions.move_to_element(password).send_keys('abcdefg').perform()
    
  • 按Enter键提交登录表单。

    password.send_keys(Keys.ENTER)
    

<details>
<summary>英文:</summary>
Here&#39;s the complete solution:
```python
import time
from selenium.webdriver import Chrome, Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
import selenium.webdriver.support.expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
def main():
driver = Chrome()
driver.get(&quot;https://banking.dkb.de/login&quot;)
wait = WebDriverWait(driver, 10)
# Switch to the iframe and click on the button to refuse all cookies
iframe = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, &#39;iframe#privacy-iframe&#39;)))
driver.switch_to.frame(iframe)
driver.find_element(By.CSS_SELECTOR, &#39;button.btn.refuse-all&#39;).click()
driver.get(&quot;https://banking.dkb.de/login&quot;)
actions = ActionChains(driver)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, &#39;div[data-testid=&quot;sui-input-username&quot;]&#39;))).click()
username = driver.find_element(By.CSS_SELECTOR, &#39;input#username&#39;)
actions.move_to_element(username).send_keys(&#39;123456789&#39;).perform()
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, &#39;div[data-testid=&quot;sui-input-password&quot;]&#39;))).click()
password = driver.find_element(By.CSS_SELECTOR, &#39;input#password&#39;)
actions.move_to_element(password).send_keys(&#39;abcdefg&#39;).perform()
password.send_keys(Keys.ENTER)
time.sleep(2)
main()

output:

因为在Selenium网络自动化中元素无法交互,所以无法发送键。

Few notes:

  • The website may display a cookie consent popup within an iframe. Therefore, switch to the respective iframe and click on the button to refuse all cookies.

    iframe = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, &#39;iframe#privacy-iframe&#39;)))
    driver.switch_to.frame(iframe)
    driver.find_element(By.CSS_SELECTOR, &#39;button.btn.refuse-all&#39;).click()
    
  • Initialize ActionChains to perform actions like mouse movements and keystrokes

    actions = ActionChains(driver)
    
  • Log in with provided credentials, Find the username input field, click on it, and enter the username.

    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, &#39;div[data-testid=&quot;sui-input-username&quot;]&#39;))).click()
    username = driver.find_element(By.CSS_SELECTOR, &#39;input#username&#39;)
    actions.move_to_element(username).send_keys(&#39;123456789&#39;).perform()
    
  • Find the password input field, click on it, and enter the password.

    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, &#39;div[data-testid=&quot;sui-input-password&quot;]&#39;))).click()
    password = driver.find_element(By.CSS_SELECTOR, &#39;input#password&#39;)
    actions.move_to_element(password).send_keys(&#39;abcdefg&#39;).perform()
    
  • Press the Enter key to submit the login form.

    password.send_keys(Keys.ENTER)
    

huangapple
  • 本文由 发表于 2023年7月24日 00:30:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/76749285.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定