在我使用 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 只有赋值、调用、递增、递减、await 和 new 对象表达式可以用作语句 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
}
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 或页面其他位置不存在的某些属性,您可以检查 PageSource。
driver.PageSource.Contains("UniqueID");
它检查页面以查看 ID 或其他唯一文本是否存在。 这几乎是瞬间发生的,而不是使用 Try/Catch 语句,后者大约需要 20 秒。 FindElements 也需要很长时间才能运行。
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();
}
});
}
多米尼克·吉隆巴尔多的回答对我有用。对于在后台加载的基于Ajax的信息,等待元素出现是必需的循环。
因此,如果您想在元素出现时等待并执行操作,可以使用标签和go to label + else 条件。这是修改后的代码,它将通过循环等待元素出现:
检查某些元素:
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;
}
此外,我注意到在之前的帖子的评论中,人们说他们必须等待 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;
}
}
FindElements().Count
函数(注意元素的“s”)。 如果元素不存在,则计数为
0
,否则元素存在
if(driver.FindElements(By.XPath("//div[@class='video']/a")).Count > 0) {...}
FindElement().Displayed
bool 的问题是,如果元素不存在,它会抛出异常。 如果您希望有类似的 bool 元素,您可以使用三元运算符来处理两种存在情况:
bool Displayed = driver.FindElements(By.XPath("//div[@class='video']/a")).Count > 0 ? true : false;