如何使用 Selenium for C# 通过 XPath 查找文本?

4
我试图通过XPath查询检查文本"In stock.",但是我的XPath变量elementInStock返回的是一个ID,并且看起来它没有找到URL https://www.amazon.co.uk/dp/B08H96W864/ref=twister_B08J4RCVXW?_encoding=UTF8&th=1中的文本"In stock."。希望能帮助我找到文本"In stock."并执行Console.WriteLine("HEYYYY"); 如果找不到文本"In stock.",则按照我的代码逻辑继续执行while循环,如果XPath为null,则不执行while循环。请给出建议。
class Program
    {
        static void Main(string[] args)
        {

            IWebDriver driver = new ChromeDriver();

            //Navigate to
            driver.Navigate().GoToUrl("https://www.amazon.co.uk/dp/B08H96W864/ref=twister_B08J4RCVXW?_encoding=UTF8&th=1");

            driver.Manage().Window.Maximize();


            IWebElement elementInStock = driver.FindElement(By.XPath("/html/body/div[2]/div[2]/div[5]/div[4]/div[4]/div[18]"));

            

            if (elementInStock != null)
            {
                Console.WriteLine("HEYYYY");
            }

            else if (elementInStock == null)
                {
                    int counter = 0;

                    while (counter < 10)
                    {

                        Thread.Sleep(2500);

                        driver.Navigate().Refresh();

                    }
                }


            }
        }
    }
1个回答

2
我看到了一些可能导致你遇到问题的原因,还有一些会在以后引起问题的东西。我将在此列出它们,然后下面我会提出一些改进脚本的建议。最后,我已经使用建议的改进更新了脚本。我已经测试了代码,它可以正常工作。
  1. 你没有等待元素可见可能是你遇到问题的一部分。
  2. 你的脚本实际上没有检查“有现货”文本。
  3. 不存在一个 .FindElement() 调用的 null 元素结果。查找要么有效并返回元素,要么无效并抛出异常。这就是为什么当元素未被找到时,你的代码永远不会进入 while 循环的原因。我的建议是查找一个你知道总是存在的元素或使用 .FindElements()(复数形式),然后检查返回的集合中是否有元素(表示该元素存在)。这将避免抛出不必要的异常,但仍能完成任务。
  4. Thread.Sleep() 的参数是毫秒,所以 2500 是 2.5 秒。我假设你打算等待超过 2.5 秒?我更喜欢使用 TimeSpan.FromSeconds(30) 来清楚地表明我要等待多少秒。注意:还有许多其他的 From* 选项,你可能也会感兴趣使用,例如 TimeSpan.FromMinutes(2)
  5. 你从未增加过 counter……这意味着你的脚本将陷入无限循环。
  6. 你的 XPath 是绝对 XPath,这意味着它从 /html 标签开始。这被认为是一种不好的实践,因为你最终会得到一个非常严格(通常很长)的 XPath,如果沿指定的链添加/删除/更改任何元素,你的 XPath 将会失效。如果必须使用 XPath,则应创建具有唯一定位元素所需最小信息的相对 XPath。最好的做法是使用 ID 或 CSS 选择器,仅在包含文本或用于更复杂的情况下使用 XPath 来定位元素。
我建议进行一些更改...
  1. In this case, we can use an ID, availability, on the parent element instead of using XPath.

     <div id="availability" class="a-section a-spacing-none">
         <span class="a-size-medium a-color-success">In stock.</span>
     </div>
    

    NOTE: I've cleaned up a LOT of extra whitespace from the HTML above to save space. It won't matter in this case given that I'm planning to use the ID to locate the element but I am going to add .Trim() to the text returned to remove all that extra whitespace.

  2. Add a wait to make sure the element is visible.

  3. Find an element that is always there and check the contained text for the desired string.

  4. Increment counter.

以下是最终代码的样子。我运行了这段代码,并成功地将“HEYYYY”写入控制台。

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using System;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        IWebDriver driver = new ChromeDriver();
        driver.Manage().Window.Maximize();
        driver.Url = "https://www.amazon.co.uk/dp/B08H96W864/ref=twister_B08J4RCVXW?_encoding=UTF8&th=1";

        int counter = 0;
        while (counter < 10)
        {
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(15));
            IWebElement availability = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("availability")));
            if (availability.Text.Trim() == "In stock.")
            {
                Console.WriteLine("HEYYYY");
                break;
            }

            counter++;
            Thread.Sleep(TimeSpan.FromSeconds(30));
            driver.Navigate().Refresh();
        }
    }
}

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