Selenium网络自动化中的元素不可交互异常

38
在下面的代码中,我不能在密码字段中发送密码键,我尝试点击字段、清除字段并发送键。但是在任何一种方法中都没有起作用。但是如果我进行调试和测试,则可以正常工作。
  public class TestMail {
   protected static WebDriver driver;

   protected static String result;

   @BeforeClass

   public static void setup()  {
              System.setProperty("webdriver.gecko.driver","D:\\geckodriver.exe");

   driver = new FirefoxDriver();

   driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);

  }

   @Test

 void Testcase1() {

   driver.get("http://mail.google.com");

   WebElement loginfield = driver.findElement(By.name("Email"));
   if(loginfield.isDisplayed()){
       loginfield.sendKeys("ragesh@gmail.in");
   }
   else{
  WebElement newloginfield = driver.findElemnt(By.cssSelector("#identifierId"));                                      
       newloginfield.sendKeys("ragesh@gmail.in");
      // System.out.println("This is new login");
   }


    driver.findElement(By.name("signIn")).click();

  // driver.findElement(By.cssSelector(".RveJvd")).click();

   driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
 // WebElement pwd = driver.findElement(By.name("Passwd"));
  WebElement pwd = driver.findElement(By.cssSelector("#Passwd"));

  pwd.click();
  pwd.clear();
 // pwd.sendKeys("123");
 if(pwd.isEnabled()){
     pwd.sendKeys("123");
 }
 else{
     System.out.println("Not Enabled");
 }
13个回答

25

"element not interactable"错误可能意味着两件事:

a. 元素没有正确地渲染:

解决方法只需要使用隐式/显式等待。

  • 隐式等待:

    driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);

  • 显式等待:

    WebDriverWait wait=new WebDriverWait(driver, 20); element1 = wait.until(ExpectedConditions.elementToBeClickable(By.className("fa-stack-1x")));

b. 元素已经渲染,但不在屏幕的可见部分:

解决方案就是滚动到该元素。根据Selenium的版本,可以用不同的方式处理,但我将提供适用于所有版本的解决方案:

    JavascriptExecutor executor = (JavascriptExecutor) driver;
    executor.executeScript("arguments[0].scrollIntoView(true);", element1);
  1. 如果所有方法都失败了,那么另一种方法是再次使用Javascript执行器,如下:

    executor.executeScript("arguments[0].click();", element1);

  2. 如果你仍然无法点击,则可能有两个原因:

1. Iframe

检查DOM以查看你正在检查的元素是否存在于任何框架中。如果是真的,那么在尝试任何操作之前,你需要切换到这个框架。

    driver.switchTo().frame("a077aa5e"); //switching the frame by ID
    System.out.println("********We are switching to the iframe*******");
    driver.findElement(By.xpath("html/body/a/img")).click();

2. 新标签页

如果打开了一个新的标签页,并且该元素存在于其中,则需要编写以下类似的代码来在尝试操作之前先切换到该标签页。

String parent = driver.getWindowHandle();
driver.findElement(By.partialLinkText("Continue")).click();
Set<String> s = driver.getWindowHandles();
// Now iterate using Iterator
Iterator<String> I1 = s.iterator();
while (I1.hasNext()) {
String child_window = I1.next();
if (!parent.equals(child_window)) {
    driver.switchTo().window(child_window);
    element1.click() 
}

25

尝试设置一个可能为10秒的隐式等待。

gmail.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

或者设置一个显式等待。显式等待是您定义的代码,用于在继续执行代码之前等待某个条件发生。在您的情况下,这是密码输入字段的可见性。(感谢ainlolcat的评论)

WebDriver gmail= new ChromeDriver();
gmail.get("https://www.gmail.co.in"); 
gmail.findElement(By.id("Email")).sendKeys("abcd");
gmail.findElement(By.id("next")).click();
WebDriverWait wait = new WebDriverWait(gmail, 10);
WebElement element = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.id("Passwd")));
gmail.findElement(By.id("Passwd")).sendKeys("xyz");

解释:Selenium无法找到该元素的原因是密码输入框的ID最初为“ Passwd-hidden”。在单击“下一步”按钮后,Google首先验证输入的电子邮件地址,然后显示密码输入框(通过将ID从“Passwd-hidden”更改为“Passwd”)。因此,当密码字段仍然隐藏时(即Google仍在验证电子邮件ID时),您的Web驱动程序开始搜索仍处于隐藏状态的ID为Passwd的密码输入框。因此,会抛出异常。


6

你也可以尝试使用完整XPath。我曾遇到过类似的问题,需要点击一个具有JavaScript onclick功能属性的元素。使用完整XPath方法可以解决问题,并且不会抛出交互异常。


我也有过同样的经历。虽然了解原因会很好,但现在还不清楚为什么。 - Seba92

5
请尝试按照以下方式选择密码字段。
    WebDriverWait wait = new WebDriverWait(driver, 10);
    WebElement passwordElement = wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#Passwd")));
    passwordElement.click();
  passwordElement.clear();
     passwordElement.sendKeys("123");

3
在我的情况下,生成异常的元素是一个属于表单的按钮。我进行了替换。
WebElement btnLogin = driver.findElement(By.cssSelector("button"));
btnLogin.click();

使用

btnLogin.submit();

我的环境是在Windows 10下使用的Chromedriver。


1

在我的情况下,我使用的是Python-Selenium。

我有两个指令。第二个指令无法执行。

我在两个指令之间加入了time.sleep(1),问题就解决了。

如果需要的话,您可以根据自己的需要更改睡眠时间。


1
在我的情况下,查询不够具体。页面上有多个具有相同属性的元素,所以找到的第一个元素并不是我需要的那个。结果导致了“元素不可交互”的错误,因为我试图点击错误的元素。最终,我找到了所有“相同”元素的ID,并选择第N个元素而不是第一个元素。这就解释了为什么有些人说使用XPath对他们有效。
注意:我正在使用Clojure和Etaoin库,它是Selenium的封装,因此术语可能不匹配。
以下是引发“元素不可交互”错误的有问题的代码示例:
(let [submit-button-query {:tag :button :fn/has-class "submit-yes"}
      submit-button-element (query driver submit-button-query)] 
       (click-el driver submit-button-element))  

工作代码:

(let [submit-button-query {:tag :button :fn/has-class "submit-yes"}   ;; query that I assumed was unique and matched the button I was interested in but, in fact, there were multiple elements with that class. I didnt realize it because I was using query fn that only returns the first match. Below Im using query-all fn to find all matches first
      all-submit-button-elements (query-all driver submit-button-query)
      pop-up-submit-button-element (last all-submit-button-elements)] ;; my case was simple and I could safely assume that the button I need is the last one from the list of matches 
   (click-el driver pop-up-submit-button-element))                    ;; successful click 

请添加一个代码示例。 - sanitizedUser
@用户已经更新了我的回答 - sitanosik

0

我曾经遇到过同样的问题,后来找到了原因。我试图在一个 span 标签中输入内容,而不是 input 标签。我的 XPath 是用 span 标签编写的,这是错误的做法。我查看了元素的 Html,并找到了问题所在。然后我只需要找到作为子元素的 input 标签即可。只有在使用 input 标签名称创建 XPath 时,才能在输入字段中输入内容。


0

我之所以出现这个错误,是因为我在使用 Selenium WebDriver Node.js 函数 By.css() 时选择器选择错误了。

你可以通过在网页浏览器的 Web 控制台(Ctrl+Shift+K 快捷键)中使用 JavaScript 函数 document.querySelectorAll() 来检查你的选择器是否正确。


0

我必须先悬停在元素上,子元素才会出现。一开始我没有考虑到这一点。

    WebElement boardMenu = this.driver.findElement(By.linkText(boardTitle));
    Actions action = new Actions(this.driver);

    action.moveToElement(boardMenu).perform();

另一个提示是检查您是否拥有该DOM的一个元素。在检查网页时尝试使用Ctrl+F并检查您的xpath;如果您使用findElement方法,则应返回一个元素。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接