32

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">
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ktmrocks
  • 361
  • 1
  • 5
  • 18

3 Answers3

79

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"));
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Yi Zeng
  • 32,020
  • 13
  • 97
  • 125
  • 1
    By.cssSelector(".ban.hot:nth-of-type(3)") –  May 18 '15 at 12:02
  • This is an addition to Yi Zengs answer. For some reason he didn't mention that you can use nth-of-type with a class name in cssSelector. You don't have to go through a list of elements to get the Nth element containing the class name –  May 21 '15 at 13:36
  • @Vlad: Thanks for pointing out. `nth-of-type` is CSS3, which wasn't fully supported by Selenium under the hood for all browsers at the time. It might be supported now, but I haven't got a chance to verify. Have you tested it with the latest Selenium? – Yi Zeng May 22 '15 at 01:39
  • Tested nth-of-type on Firefox driver in Selnium 2.48 -> works perfectly. – Elmue Dec 29 '15 at 01:17
0

By.cssSelector(".ban") or By.cssSelector(".hot") or By.cssSelector(".ban.hot") should all select it unless there is another element that has those classes.

In CSS, .name means find an element that has a class with name. .foo.bar.baz means to find an element that has all of those classes (in the same element).

However, each of those selectors will select only the first element that matches it on the page. If you need something more specific, please post the HTML of the other elements that have those classes.

Nathan Merrill
  • 7,648
  • 5
  • 37
  • 56
0

You can describe your CSS selection like cascading style sheet rows:

protected override void When()
{
    SUT.Browser.FindElements(By.CssSelector("#carousel > a.tiny.button"))
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
danvitoriano
  • 1,181
  • 10
  • 12