7

I am currently working with Selenium and have now reached the interesting, yet incredibly difficult, world of CSS selectors.

I'm currently looking at selecting the different options of the Google tool bar. E.g when you search for something, on the results page you get options to search for the same term but under images, news, videos etc

I'm particularly interested in selecting the "Images" link.

I've been working on it for quite a while and the closest i have got is the below selector:

div a.q.qs[href]

This drills down into the right sub classes but there are 16 of them. Despite hours of aimless searching, i'm unable to complete the query with a contains method around the anchor text, which is unique in the targeted sub classes.

I'm aware there is a By LinkText option in Selenium, but i'm not sure if the anchor text is unique across the entire page. Also, i really want to understand CSS selectors in general so even if it was, i want to resolve this particular issue so i can apply it to future problems.

I'm looking for something like the below pseudo CSS selector:

div a.q.qs[href].Anchorcontains("Images")

Can anyone help?

frianH
  • 7,295
  • 6
  • 20
  • 45
Rusty Shackleford
  • 337
  • 1
  • 6
  • 18
  • This is an interesting question. I would suggest you to add some code blocks to make it more readable (the CSS selectors) and to remove the selenium and java tags, because even if it is a java&selenium problem for you, the question itself focusses only on css selectors. – Clijsters Aug 27 '18 at 13:22
  • 1
    All links have a unique parameter called `tbm`: its value is `isch` for images, so I'd go with `a[href*="isch"]`. Works on browser, not sure about selenium though. – BackSlash Aug 27 '18 at 13:24
  • This is a great idea. Alternatively you could assume that the "Images" item is always the second in the list. And if you are sure, that at the time you want to select images, "All" is selected, it is the first item containing a link. – Clijsters Aug 27 '18 at 13:26
  • If you're looking to select by actual text content of an anchor, you can not do that: https://stackoverflow.com/questions/1520429/is-there-a-css-selector-for-elements-containing-certain-text – Serg Chernata Aug 27 '18 at 13:31
  • 1
    Here are some links to CSS references that will help you get started: [W3C reference](https://www.w3.org/TR/selectors/#overview), [SauceLabs CSS Selectors tips](https://saucelabs.com/resources/articles/selenium-tips-css-selectors), and [Taming Advanced CSS Selectors](https://www.smashingmagazine.com/2009/08/taming-advanced-css-selectors/). – JeffC Aug 27 '18 at 13:52
  • @RustyShackleford Nice to see you got a solution to your question but I am sure you still don't know what `isch` exactly is and don't be surprised tomorrow to see `isch` completely unavailable within the _href_ attribute. – undetected Selenium Aug 27 '18 at 16:56

2 Answers2

23

All links have a unique parameter called tbm: its value is isch for images, so I'd go with

a[href*="tbm=isch"]
BackSlash
  • 21,927
  • 22
  • 96
  • 136
  • I like your idea, it just has one small drawback: If the search text is e.g. "Witzisch", it would match any search link. Shouldn't it be `"tbm=isch"`? – Clijsters Aug 27 '18 at 13:28
  • 2
    Thanks, this is what i am looking for. It's also made it clear to me that i should investigate hrefs in future for unique sub strings – Rusty Shackleford Aug 27 '18 at 14:58
3

There are sometimes ways to get what you want with CSS selectors but if you want to find an element by contained text, you will have to use either link text/partial link text if it's a link or XPath for everything else.

The XPath for what you want is

//div[@id='hdtb-msb-vis']//a[.='Images']

You could use //a[.='Images'] but that returns two elements, one of which is not visible.

To break this down

// at any level
div find a DIV
[@id='hdtb-msb-vis'] that contains an ID of 'hdtb-msb-vis'
//a that has a child A at any level
[.='Images'] that contains text (.) equal to 'Images'

If you want to explore by link text, you can write something like

int count = driver.findElements(By.linkText("Images")).size();

and print count. My guess is that it will be 2, one of which is not visible. You can use Selenium to further filter this down to only the visible link, if you wanted.

You are going to have the same issue with BackSlash's CSS selector answer. You can tweak it slightly and solve this problem with the CSS selector locator

#hdtb-msb-vis a[href*='tbm=isch']

Here are some links to CSS references that will help you get started: W3C reference, SauceLabs CSS Selectors tips, and Taming Advanced CSS Selectors.

JeffC
  • 22,180
  • 5
  • 32
  • 55
  • Thanks for this @JeffC - I've accepted BackSlashes answer as the CSS is more readable. However, i actually think your answer provides a more targeted way of doing things. I'm conflicted! I wish i could make two accepted answers – Rusty Shackleford Aug 27 '18 at 15:00
  • That's fine. Readable is in the eye of the reader. Once you get more familiar with them, they will be easier to read. Without the more specific locator, you will need to write more Java/Selenium code to handle the invisible element to avoid issues. – JeffC Aug 27 '18 at 15:12