如何检查元素是否存在
本文关键字:元素 是否 存在 检查 何检查 | 更新日期: 2023-09-27 18:34:34
在我的使用Firefox Selenium WebDriver的C# Windows Forms应用程序中,我需要检查一个元素是否存在,如果不存在,请单击另一个元素。如果有视频,观看后会变成W_VIEWED
:
driver.FindElement(By.XPath("//div[@class='video']/a")).Click();
else
{
driver.FindElement(By.XPath("//div[@class='W_VIEWED']/a")).Click();
}
错误 3 只有赋值、调用、递增、递减、等待和新对象表达式可以用作语句 242
以下命令检查元素是否退出
bool isElementDisplayed = driver.findElement(By.xpath("element")).isDisplayed()
请记住,如果findElement
找不到元素,则会引发异常,因此您需要正确处理它。
在我的一个应用程序中,我通过检查单独函数中的元素来处理异常:
private bool IsElementPresent(By by)
{
try
{
driver.FindElement(by);
return true;
}
catch (NoSuchElementException)
{
return false;
}
}
调用功能:
if (IsElementPresent(By.Id("element name")))
{
// Do if exists
}
else
{
// Do if does not exists
}
您可以使用带有"s"的 FindElements 来确定它是否存在,因为 FindElement 会导致异常。 如果 FindElements 不返回元素,则返回一个空列表。
List<IWebElement> elementList = new List<IWebElement>();
elementList.AddRange(driver.FindElements(By.XPath("//input[@att='something']")));
if(elementList.Count > 0)
{
//If the count is greater than 0 your element exists.
elementList[0].Click();
}
所以我最近想出了另一种方法,它要快得多。如果您的元素具有唯一 ID 或页面上其他任何地方都不存在的某些属性,则可以检查页面源代码。
driver.PageSource.Contains("UniqueID");
它会检查页面以查看 ID 或其他唯一文本是否存在。 这几乎是瞬间发生的,而不是使用 Try/Catch 语句,这需要 ~20 秒。 FindElements也需要很长时间才能运行。
我使用接受答案的解决方案有一段时间了,但我需要一种更快的方法来检查,而不是每次检查失败时都等待超时期限。因此,我制作了一些适用于 IWebElement 和 IWebDriver 的扩展函数,用于检查标记或类是否存在。
public static class ExtensionMethods {
public static bool ContainsTag(this IWebElement element, string tagName)
{
string elementText = element.GetAttribute("innerHTML");
return CheckStringForTag(elementText, tagName);
}
public static bool ContainsClass(this IWebElement element, string className)
{
string elementText = element.GetAttribute("innerHTML");
return CheckStringForClass(elementText, className);
}
public static bool ContainsTag(this IWebDriver driver, string tagName)
{
return CheckStringForTag(driver.PageSource, tagName);
}
public static bool ContainsClass(this IWebDriver driver, string className)
{
return CheckStringForClass(driver.PageSource, className);
}
private static bool CheckStringForTag(string text, string tagName)
{
if (!string.IsNullOrWhiteSpace(text))
{
return text.Contains("<" + tagName + ">") || text.Contains("</" + tagName + ">") || text.Contains("<" + tagName + " ");
}
return false;
}
private static bool CheckStringForClass(string text, string className)
{
if (!string.IsNullOrWhiteSpace(text))
{
string pattern = string.Format(".*class[''s]?=[''s]?.*[''s''"]{0}[''s''"].*.*", className);
Match m = Regex.Match(text, className, RegexOptions.IgnoreCase);
return m.Success;
}
return false;
}
public static string InnerHTML(this IWebElement element)
{
return element.GetAttribute("innerHTML");
}
}
注意:这与Dominic Giallombardo的答案类似,但扩展了。
此方法将允许您等待元素存在。这在有条件地创建元素的前端 SPA 框架中尤其重要,例如 Vue.js。您可以根据应用程序的性能调整重试计数。无论如何,它将等待您的ELEMENT_FIND_WAIT_TIME * ELEMENT_FIND_WAIT_RETRY_COUNT
毫秒,然后完全失败。这解决了我们遇到的问题。
protected Func<IWebElement> GetLazyElement(By by, int retryCount=0)
{
if (retryCount >= ELEMENT_FIND_WAIT_RETRY_COUNT)
{
throw new Exception("Wait timeout for element to show up" + by.ToString());
}
return new Func<IWebElement>(() => {
try
{
Debug.WriteLine("Finding element " + by.ToString());
var element = _webDriver.FindElement(by);
return element;
}
catch (Exception)
{
Debug.WriteLine($"Failed to find element: {by} (Waiting {ELEMENT_FIND_WAIT_TIME}ms)");
Thread.Sleep(ELEMENT_FIND_WAIT_TIME);
var lazyFunc = GetLazyElement(by, retryCount++);
return lazyFunc();
}
});
}
Dominic Giallombardo的回答对我有用。在后台加载的基于 Ajax 的信息上,需要等待元素出现。
因此,如果您想等待并在元素出现时执行操作,可以使用标签和转到标签 + else 条件。以下是修改后的代码,它将等待元素通过循环出现:
ChecksomeElement:
List<IWebElement> elementList = new List<IWebElement>();
elementList.AddRange(driver.FindElements(By.XPath("//div[@class='video']/a")));
if (elementList.Count > 0)
{
elementList[0].Click();
}
else
{
System.Threading.Thread.Sleep(2000);
goto checksomeelement;
}
使用的。"verify"方法将根据元素是否存在返回 true 或 false。名为"testfunc"的方法是您输入元素名称的位置。在此示例中,我正在寻找页面上是否显示"英语"。
此外,我在之前帖子的评论中注意到,人们说他们必须等待 10 秒或更长时间才能捕获才能工作。尝试删除代码中的显式等待,以便 catch 立即工作。
static public bool verify(string elementName)
{
try
{
bool isElementDisplayed = driver.FindElement(By.XPath(elementName)).Displayed;
return true;
}
catch
{
return false;
}
return false;
}
static void testfunc()
{
bool test = verify("//option[contains(.,'English')]");
Console.WriteLine(test);
}
如果您正在使用ImplicitWait
并且想要通过使用FindElement
来查看元素是否存在而无需等待,请尝试以下代码:
ElementExists(By.Id(id));
static public bool ElementExists(By method)
{
var oldTime = _driver.Manage().Timeouts().ImplicitWait;
_driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromMilliseconds(1);
try
{
bool isElementDisplayed = _driver.FindElement(method).Displayed;
_driver.Manage().Timeouts().ImplicitWait = oldTime;
return true;
}
catch
{
_driver.Manage().Timeouts().ImplicitWait = oldTime;
return false;
}
}