C# Selenium调用FindElement查找不存在元素时抛异常如何解决
C# Selenium 注册邮箱校验元素存在性判断实现
场景说明
实现网站邮箱注册可用性校验逻辑:输入邮箱后判断页面是否触发注册错误提示,若存在错误提示则代表邮箱已被占用,归入不可用邮箱列表;若不存在错误提示则代表邮箱可用,归入可用邮箱列表。
页面错误提示元素HTML结构如下:
<div class="i24fI"> <span class="coreSpriteInputError gBp1f"></span> </div>
原有问题
原有实现代码如下:
IWebDriver driver = new ChromeDriver(); for (int i = 0; i < Convert.ToInt32((mailCount.Text)); i++) { string email = helper.RastgeleKelime(); driver.Navigate().GoToUrl("https://www.xxxxxxx.com/accounts/emailsignup/"); Thread.Sleep(2000); IWebElement username = driver.FindElement(By.Name("emailOrPhone")); IWebElement Fullname = driver.FindElement(By.Name("fullName")); username.SendKeys("cccc@hotmail.com"); Fullname.SendKeys("ssssss"); Thread.Sleep(2000); IWebElement error = driver.FindElement(By.CssSelector("div.i24fI span.coreSpriteInputError")); if (error != null) { avMailList.Items.Add(email.ToString()); } else { mailList.Items.Add(email.ToString()); } Thread.Sleep(2000); }
核心问题:FindElement方法在匹配不到目标元素时,不会返回null,而是直接抛出NoSuchElementException异常,导致后续if-else判断逻辑完全无法正常执行。
除此之外原有代码还存在三个影响结果正确性的问题:
- 邮箱输入框传入了写死的固定值
cccc@hotmail.com,没有使用循环中生成的随机邮箱变量,校验结果和待检测邮箱完全不对应 - 列表归属逻辑写反:存在错误提示代表邮箱不可用,原代码反而将其加入了可用邮箱列表
- 大量使用固定时长的
Thread.Sleep,既影响执行效率,页面加载慢时还会因为元素没加载出来触发异常
正确实现方案
用FindElements方法替代FindElement做元素存在性判断即可:FindElements在匹配不到元素时会返回元素数量为0的空集合,不会抛出异常,只要判断返回集合的Count是否大于0,就能准确判断元素是否存在。
修正后的完整代码如下:
IWebDriver driver = new ChromeDriver(); // 初始化显式等待,最长等待10秒,替代固定Sleep提升效率 WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10)); for (int i = 0; i < Convert.ToInt32(mailCount.Text); i++) { string email = helper.RastgeleKelime(); driver.Navigate().GoToUrl("https://www.xxxxxxx.com/accounts/emailsignup/"); // 等待邮箱输入框可交互后再执行输入,避免页面未加载完成报错 IWebElement usernameInput = wait.Until(d => d.FindElement(By.Name("emailOrPhone"))); IWebElement fullnameInput = driver.FindElement(By.Name("fullName")); // 传入当前循环生成的待检测邮箱,不要写死固定值 usernameInput.SendKeys(email); fullnameInput.SendKeys("ssssss"); // 等待前端校验逻辑触发,预留短时间等错误提示渲染 Thread.Sleep(500); // 查找错误提示元素集合,无匹配时返回空集合不抛异常 IReadOnlyCollection<IWebElement> errorTips = driver.FindElements(By.CssSelector("div.i24fI span.coreSpriteInputError")); if (errorTips.Count > 0) { // 存在错误提示 = 邮箱已占用,加入不可用列表 mailList.Items.Add(email); } else { // 无错误提示 = 邮箱可用,加入可用列表 avMailList.Items.Add(email); } }
注意事项
- 不推荐用try-catch包裹
FindElement的方式判断元素存在性,异常捕获本身有额外性能开销,稳定性和执行效率都不如FindElements方案 - 尽量减少固定时长的
Thread.Sleep使用,换成Selenium的显式等待,等元素满足可交互、存在等条件后再执行后续操作,代码执行速度和稳定性都会明显提升
内容的提问来源于stack exchange,提问作者Muhammet Sinan Korkut
相关产品推荐
相关产品推荐

