I see a few things that might be causing the issues you are seeing and a few other things that will cause issues later. I'll list them here and then below I've made some suggestions for improving the script. Finally, I've updated the script with the suggested improvements. I've tested the code and it's working correctly.
- The fact that you don't wait for the element to be visible may be part of the problems you are seeing.
- Your script doesn't actually check for the "In stock." text.
- There's really no such thing as a null element result of a
.FindElement()
call. The find either works and returns the element or it doesn't work and it throws an exception. That's why your code never gets to the while
loop when the element isn't found. My recommendation here would be to either find an element that you know will always be present or use .FindElements()
(plural) and then check to see if there's an element in the returned collection (meaning the element exists). This will avoid unnecessary exceptions being thrown and will still accomplish the task.
Thread.Sleep()
takes milliseconds as the parameter so 2500 is 2.5s. I'm assuming you intended to wait for more than 2.5s? I prefer to use TimeSpan.FromSeconds(30)
to make it clearer how many seconds I'm waiting. NOTE: There are also many other From*
options you may be interested in using also, e.g. TimeSpan.FromMinutes(2)
.
- You never increment
counter
... meaning your script will be stuck in an infinite loop.
- Your XPath is an absolute XPath which means that it starts at the
/html
tag. This is considered a bad practice because you end up with a very strict (and typically long) XPath which if any element along the specified chain is added/deleted/changed, your XPath will break. If you have to use XPath, instead create a relative XPath with the minimal information needed to uniquely locate the element. Best practice would be to use an ID or CSS selector instead and only use an XPath for locating an element by contained text or for more complex scenarios.
I would suggest a few changes...
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.
Add a wait to make sure the element is visible.
Find an element that is always there and check the contained text for the desired string.
Increment counter
.
Here's what the final code looks like. I ran this code and it successfully wrote "HEYYYY" to the console.
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();
}
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…