提问人:Thomas_Lcp 提问时间:11/11/2023 最后编辑:Thomas_Lcp 更新时间:11/12/2023 访问量:72
使用 WebDriver.FindElement() 的 .NET。单击 SelectElement 选项后的文本不会更新“数据”
.NET using WebDriver.FindElement().Text after SelectElement option click doesn't update "data"
问:
在我的网页上,我有一个选择元素,可以在单击后更新页面内容。
我写了一段代码,允许我导航 select 元素的不同选项。 这部分代码运行良好,但是,在这些行之后,当我尝试使用
WebDriver.FindElement().Text
(当然使用适当的 XPath)
在允许我导航抛出选项的循环中,数据似乎没有在页面上正确更新。
这是我写的片段:
foreach(IWebElement option in optionList)
{
option.Click();
var productName = driver.FindElement(By.XPath("/html/body/main/section/div[2]/div/section/div[2]/div[1]/div[2]/div[1]/h1/span"));
var productPrice = driver.FindElement(By.XPath("/html/body/main/section/div[2]/div/section/div[2]/div[1]/div[3]/div/div/div[1]/div/span[1]/meta"));
var productDescription = driver.FindElement(By.XPath("/html/body/main/section/div[2]/div/section/div[2]/div[2]/div/div[1]/div/div/p[5]"));
var productReference = driver.FindElement(By.XPath("/html/body/main/section/div[2]/div/section/div[2]/div[1]/div[2]/div[1]/div/span"));
var productReferer = driver.FindElement(By.XPath("/html/body/main/section/div[2]/div/section/div[2]/div[1]/div[2]/div[1]/span/a"));
ProductReference pr = new()
{
DisplayName = productName.Text,
Price = productPrice.Text,
Description = productDescription.Text,
Referer = productReferer.Text,
Reference = productReference.Text,
AttributName = "Couleurs",
AttributValue = option.Text,
};
products.Add(pr);
Console.WriteLine(pr);
}
如果有办法“刷新”浏览器或其他任何东西,我都不知道。
pr AttributValue 始终是正确的,但例如,引用已经相同,而它应该不同。
感谢您的帮助!
更多信息 :
这是循环之前的代码:
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.AddArguments("--headless=new");
chromeOptions.AddExcludedArgument("disable-popup-blocking");
ChromeDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl(url);
IWebElement colorChoiceElmt = driver.FindElement(By.Id("group_4"));
SelectElement select = new SelectElement(colorChoiceElmt);
IList<IWebElement> optionList = select.Options;
已经测试过的代码:
-- 拉蒙建议 --
在拉蒙的建议下,我尝试了这个。问题是,在 Selenium 文档上,他们要求我们不要使用 ExpectedConditions(并且使用它会产生错误),所以我遵循了他们的建议并使用 Explicit 等待,如下所示:
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(2));
wait.Until(d => colorChoiceElmt.Displayed);
colorChoiceElmt.SendKeys("Displayed");
-- 雅罗斯拉夫建议 --
由于 Selenium 在最新版本中尚不支持 ExpectedConditions,因此我安装了“SeleniumExtras.WaitHelpers”块包到以下代码中才能工作。剧透,结果是一样的。
static void ProcessUrl(string url)
{
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.AddArguments("--headless=new");
chromeOptions.AddExcludedArgument("disable-popup-blocking");
ChromeDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl(url);
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement colorChoiceElmt = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("group_4")));
SelectElement select = new SelectElement(colorChoiceElmt);
IList<IWebElement> optionList = select.Options;
string currentProductReference = null;
for (int index = 0; index < optionList.Count; index++)
{
if (index > 1)
{
wait.Until(ExpectedConditions.StalenessOf(colorChoiceElmt));
}
colorChoiceElmt = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("group_4")));
select = new SelectElement(colorChoiceElmt);
optionList = select.Options;
select.SelectByIndex(index);
IWebElement product = driver.FindElement(By.CssSelector(".product-info-row"));
IWebElement productName = product.FindElement(By.CssSelector("[itemprop=name]"));
IWebElement productPrice = product.FindElement(By.CssSelector(".product-price"));
IWebElement productDescription = driver.FindElements(By.CssSelector(".product-description p"))[4];
IWebElement productReference = product.FindElement(By.CssSelector("[itemprop=sku]"));
currentProductReference = productReference.Text;
IWebElement productReferer = product.FindElement(By.CssSelector(".product_header_container a"));
ProductReference pr = new()
{
DisplayName = productName.Text,
Price = productPrice.Text,
Description = productDescription.Text,
Referer = productReferer.Text,
Reference = productReference.Text,
AttributName = "Couleurs",
AttributValue = optionList[index].Text,
};
products.Add(pr);
Console.WriteLine(pr);
}
driver.Quit();
}
答:
您面临的问题似乎与单击选择元素中的选项后检索元素的时间有关。WebDriver 可能正在尝试在页面完全更新之前获取元素。
为了解决这个问题,您可以引入一种等待机制,以确保 WebDriver 在尝试检索其值之前等待元素存在且可见。下面是一个使用以下示例:WebDriverWait
foreach (IWebElement option in optionList)
{
option.Click();
// Introduce WebDriverWait to wait for the elements to be present
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
var productName = wait.Until(ExpectedConditions.ElementIsVisible(By.XPath("/html/body/main/section/div[2]/div/section/div[2]/div[1]/div[2]/div[1]/h1/span")));
var productPrice = wait.Until(ExpectedConditions.ElementIsVisible(By.XPath("/html/body/main/section/div[2]/div/section/div[2]/div[1]/div[3]/div/div/div[1]/div/span[1]/meta")));
var productDescription = wait.Until(ExpectedConditions.ElementIsVisible(By.XPath("/html/body/main/section/div[2]/div/section/div[2]/div[2]/div/div[1]/div/div/p[5]")));
var productReference = wait.Until(ExpectedConditions.ElementIsVisible(By.XPath("/html/body/main/section/div[2]/div/section/div[2]/div[1]/div[2]/div[1]/div/span")));
var productReferer = wait.Until(ExpectedConditions.ElementIsVisible(By.XPath("/html/body/main/section/div[2]/div/section/div[2]/div[1]/div[2]/div[1]/span/a")));
// Rest of your code
}
这样,WebDriver 将等待最多 10 秒(您可以根据需要调整超时)以使元素可见,然后再尝试检索其值。
此外,您可能需要考虑使用更简洁的 XPath 表达式或其他定位器策略来使代码更易于维护。
评论
首先 - 不要使用绝对选择器。 尝试使用指向所需元素的唯一且简短的选择器。
然后 - 在 2+ 尝试上选择下拉选项后,您应该等待上一个下拉元素重新呈现(它发生在您的情况下),因此当它发生时 - 显示新的产品卡信息。 然后,您只需重新初始化下拉元素并从下一个循环中获取数据。
我添加了具有描述逻辑的通用代码,您可以对其进行调整并采用您的脚本结构。
等待元素可见度,使用会像这样4.0+
WebDriverWait
IWebElement colorChoiceElmt = wait.Until(webDriver =>
{
IWebElement target = driver.FindElement(By.Id("group_4"));
return target.Displayed ? target : null;
});
等待元素过时,类似于
wait.Until(webDriver =>
{
try
{
IWebElement target = driver.FindElement(By.CssSelector("[itemprop=image]"));
return !target.Displayed
}
catch (Exception)
{
return true;
}
});
因此,工作示例是:
using System;
using System.Collections.Generic;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
namespace TestProject1
{
[TestFixture]
public class Tests
{
[Test]
public void Test1()
{
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.AddExcludedArgument("disable-popup-blocking");
chromeOptions.AddArgument("--headless=new");
IWebDriver driver = new ChromeDriver(chromeOptions);
string url = "https://www.wrs.it/fr/bouchon-de-huile-moteur/200579-too02-bouchon-de-remplissage-d-huile-ducabike-ducati-diavel-2011.html";
driver.Navigate().GoToUrl(url);
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement colorChoiceElmt = wait.Until(webDriver =>
{
IWebElement target = driver.FindElement(By.Id("group_4"));
return target.Displayed ? target : null;
});
SelectElement select = new SelectElement(colorChoiceElmt);
IList<IWebElement> optionList = select.Options;
List<Dictionary<string, string>> products = new List<Dictionary<string, string>>();
IWebElement product = driver.FindElement(By.CssSelector(".product-info-row"));
string imageHref = product.FindElement(By.CssSelector("[itemprop=image]")).GetDomProperty("href");
string referenceText = product.FindElement(By.CssSelector("[itemprop=sku]")).Text;
for (int index = 0; index < optionList.Count; index++)
{
select.SelectByIndex(index);
wait.Until(webDriver =>
{
try
{
IWebElement target = product.FindElement(By.CssSelector("[itemprop=image]"));
return !target.GetDomProperty("href").Equals(imageHref);
}
catch (Exception)
{
return true;
}
});
wait.Until(webDriver =>
{
try
{
IWebElement target = product.FindElement(By.CssSelector("[itemprop=sku]"));
return !target.Text.Equals(referenceText);
}
catch (Exception)
{
return true;
}
});
imageHref = product.FindElement(By.CssSelector("[itemprop=image]")).GetDomProperty("href");
product = driver.FindElement(By.CssSelector(".product-info-row"));
colorChoiceElmt = wait.Until(webDriver =>
{
IWebElement target = driver.FindElement(By.Id("group_4"));
return target.Displayed ? target : null;
});
select = new SelectElement(colorChoiceElmt);
optionList = select.Options;
string productName = product.FindElement(By.CssSelector("[itemprop=name]")).Text;
string productPrice = product.FindElement(By.CssSelector(".product-price")).Text;
string productDescription = driver.FindElements(By.CssSelector(".product-description p"))[4].Text;
referenceText = product.FindElement(By.CssSelector("[itemprop=sku]")).Text;
string productReferer = product.FindElement(By.CssSelector(".product_header_container a")).Text;
Dictionary<string, string> pr = new Dictionary<string, string>
{
{ "DisplayName", productName },
{ "Price", productPrice },
{ "Description", productDescription },
{ "Referer", productReferer },
{ "Reference", referenceText },
{ "AttributName", "Couleurs" },
{ "AttributValue", optionList[index].Text },
};
products.Add(pr);
}
driver.Quit();
}
}
}
评论
url