Search code examples
seleniumwebdrivercss-selectorsselenium-webdriver

I need to find an element in Selenium by CSS


I want to find the element of this link "us states" in <h5>. I am trying this on Craigslist. How can I do it?

Here is the URL: http://auburn.craigslist.org/

<html class="">

<head>

<body class="homepage w1024 list">
    <script type="text/javascript">
        <article id="pagecontainer">
            <section class="body">
                <table id="container" cellspacing="0" cellpadding="0"
                <tbody>
                <tr>
                     <td id="leftbar">
                     <td id="center">
                     <td id="rightbar">
                         <ul class="menu collapsible">
                             <li class="expand s">
                             <li class="s">
                             <li class="s">
                                 <h5 class="ban hot">us states</h5>
                                 <ul class="acitem" style="display: none;">
                            </li>
                            <li class="s">
                            <li class="s">

Solution

  • Only using class names is not sufficient in your case.

    • By.cssSelector(".ban") has 15 matching nodes
    • By.cssSelector(".hot") has 11 matching nodes
    • By.cssSelector(".ban.hot") has 5 matching nodes

    Therefore you need more restrictions to narrow it down. Option 1 and 2 below are available for CSS selector, 1 might be the one that suits your needs best.

    Option 1: Using list items' index (CssSelector or XPath)

    Limitations

    • Not stable enough if the site's structure changes

    Example:

    driver.FindElement(By.CssSelector("#rightbar > .menu > li:nth-of-type(3) > h5"));
    driver.FindElement(By.XPath("//*[@id='rightbar']/ul/li[3]/h5"));
    

    Option 2: Using Selenium's FindElements, then index them. (CssSelector or XPath)

    Limitations

    • Not stable enough if a site's structure changes
    • Not the native selector's way

    Example:

    // Note that By.CssSelector(".ban.hot") and //*[contains(@class, 'ban hot')] are different, but doesn't matter in your case
    IList<IWebElement> hotBanners = driver.FindElements(By.CssSelector(".ban.hot"));
    IWebElement banUsStates = hotBanners[3];
    

    Option 3: Using text (XPath only)

    Limitations

    • Not for multilanguage sites
    • Only for XPath, not for Selenium's CssSelector

    Example:

    driver.FindElement(By.XPath("//h5[contains(@class, 'ban hot') and text() = 'us states']"));
    

    Option 4: Index the grouped selector (XPath only)

    Limitations

    • Not stable enough if the site's structure changes
    • Only for XPath, not CssSelector

    Example:

    driver.FindElement(By.XPath("(//h5[contains(@class, 'ban hot')])[3]"));
    

    Option 5: Find the hidden list items link by href, then traverse back to h5 (XPath only)

    Limitations

    • Only for XPath, not CssSelector
    • Low performance
    • Tricky XPath

    Example:

    driver.FindElement(By.XPath(".//li[.//ul/li/a[contains(@href, 'geo.craigslist.org/iso/us/al')]]/h5"));