0

I am automating a website, and it has multiple searchboxes with the same title, class, etc. It usually occurs 2 or 3 times on every page. Is there a way in which I can tell Selenium to only use the 2nd or 3rd occurrence?

I currently have this:

driver.find_element(By.XPATH, './/*[@title = "Searchbox"]').click()

And

driver.find_element(By.XPATH, './/*[@title = "Searchbox"]').send_keys(i)

It currently clicks the first searchbox and types number i, but I want Selenium to do this for any other searchbox with the same html.

Thanks!

  • So there will always be something uniques about each searchbox, maybe 'label-hint', or 'text' etc. Once you find that out you will have to write custom XPaths to access them and perform the required actions. – PSR Jan 23 '22 at 11:54
  • Refer this to find out how to write custom Xpaths => https://stackoverflow.com/questions/70776928/how-to-write-xpath-of-a-nested-element – PSR Jan 23 '22 at 11:55

3 Answers3

1

Ideally your locator strategy should identify each and every WebElement uniquely within the DOM Tree.

As your Locator Strategy identifies 2 or 3 elements on every page, you need to construct a more canonical locator. However the following line of code:

driver.find_element(By.XPATH, './/*[@title = "Searchbox"]')

will always select the first matching element.


To click on the second and third matching element, you can use the following locator strategies:

  • To click on second match:

    driver.find_element(By.XPATH, "(.//*[@title = "Searchbox"])[1]").click()
    
  • To click on third:

    driver.find_element(By.XPATH, "(.//*[@title = "Searchbox"])[2]").click()
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • Thanks! I understand your logic, but you removed both of the ‘ at the beginning and and, and replace them by brackets. If I do this, I get the SyntaxError, and if I use them combined I get InvalidSelectorException. Do you know what I am doing wrong? – Not_a_Robot Jan 23 '22 at 14:20
  • @Not_a_Robot Missed the double quotes, added now. Let me know the status. – undetected Selenium Jan 23 '22 at 19:05
0

As a last resort you can use xpath indexing:

if this .//*[@title = "Searchbox"] represent 1/3 nodes or 1/2 nodes

you can simply change it to

(.//*[@title = "Searchbox"])[2] 

and use it like this:

driver.find_element(By.XPATH, "(.//*[@title = 'Searchbox'])[2]").send_keys(i)

to represent 2nd node

or [3] to represent 3rd node.

(.//*[@title = "Searchbox"])[3]

and so on....

This is not recommended but can be used as a last resort.

cruisepandey
  • 28,520
  • 6
  • 20
  • 38
0

To get some element by it's occurrence using xpath just wrap the xpath in (<your xpath>)[number] where number is the element occurrence number.

For click the second one:

driver.find_element(By.XPATH, '(.//*[@title = "Searchbox"])[2]').click()
Max Daroshchanka
  • 2,698
  • 2
  • 10
  • 14
  • after 5 hours you have given the same answer which is already answered by 2 answerers. What addition does it add to the community? – cruisepandey Jan 23 '22 at 17:04
  • @cruisepandey If still no any answer is accepted, they might be unclear to the person who asked. I've rephrased the answer in the way, how I think it's more clear. Is such behavior is a bad practice? No issue, I'll able to delete this answer. – Max Daroshchanka Jan 23 '22 at 17:09
  • No, that should not be required. I just wanted to know the thought process behind it. Cheers ! – cruisepandey Jan 23 '22 at 17:10
  • 1
    @cruisepandey I agree, your answer is good, so I'll try to be more careful in future, sorry. – Max Daroshchanka Jan 23 '22 at 17:46