Python Selenium Find Element by X Path Only under that Class Name - python

I am trying to apply find_element_by_xpath only on specific classnames
textboxes = driver.find_elements_by_class_name("freebirdFormviewerViewNumberedItemContainer")
for element in textboxes:
a = element.find_element_by_xpath("//*[contains(#id, 'i')]")
I want to find the element by x path that contains the first item that has "id" in it, as there could be multiples in that node e.g "id1", "id2"
The problem is that it keeps returning the same id i.e "id1" despite me using the for loop.
Does it not loop through different element in the textboxes list? I want to apply the find_element_by_xpath only under that child node.

You are close to the right solution but missing a small point . :)
So inside the for loop you should use a = element.find_element_by_xpath(".//*[contains(#id, 'i')]")
I mean the . before the // at the beginning of the xpath expression.
Also possibly there is a problem with i inside the contains(#id, 'i') - I don't see where you are updating it's value.
To find the input element you can simply use the following css selector .freebirdFormviewerViewNumberedItemContainer input or if you prefer xpath you can use //div[#class='freebirdFormviewerViewNumberedItemContainer']//input

You are not augmenting i inside your loop, so it just stays the same for every iteration.

Related

Is there a way to get the index of an element and store it to update an XPATH in Python?

I have a list that looks like this in my UI:
UI image
The XPATH for the first row's "..." button is //tbody/tr[1]/td[2]/a[1]/i[1], and each subsequent row's XPATH has the tr[] portion updated depending on the index of the row.
Is it possible to store the xpath of the button as:
button = //tbody/tr[i]/td[2]/a[1]/i[1] ?
And if so, if I create a new rule, is there a way I can update tr[i] to reflect the index of the newly added rule so I can call button.click()?
looks like, you wanna make indexing bit dynamic :
so, for this xpath :-
//tbody/tr[1]/td[2]/a[1]/i[1]
you can do following:
i = 1
button = f"//tbody/tr[{i}]/td[2]/a[1]/i[1]"
and can use it in Selenium.
you can use it for loop as well with the indices.

Selenium find second element by Xpath

I want to find_element_by_xpath("//button[#class='sqdOP']") in python selenium , But i have 2 Button with that's class and i need the second one, so it takes me only the first one.
i've tried the code below
find_element_by_xpath("//button[#class='sqdOP'][2]")
find_element_by_xpath("//[button[#class='sqdOP']][2]")
find_element_by_xpath("//button[2][#class='sqdOP']")
find_element_by_xpath("//button[#class='sqdOP'[2]]")
None of above worked.
You're probably looking for this XPath expression :
find_element_by_xpath("(//button[#class='sqdOP'])[2]"
Just add () to get the second button element on the page which fulfill a specific attribute condition (#class='sqdOP').
Side note : your second try (//[button...) is not a valid XPath expression. You can't start an expression with a predicate. You need an element name or a wildcard (*).
Use find_elements_by_xpath instead of find_element_by_xpath to get a list of elements. Access a specific index in this list to get the required element.
You can try with JavaScript executor
WebElement buttton = driver.find_element_by_class_name("sqdOP")
driver.execute_script("arguments[1].click();",buttton)
arguments[1] means click on second element.

Click (), send Keys () functions are not available for find element by x path option

I am using Python version 3.8.2 with selenium 3.14.1.
I am new to both Python and Selenium. I am using Pycharm to write my automation scripts.
When i try to use driver.find_elements_by_xpath().click() command, The click() option is not displayed in the drop down.
The same click() option is available if i use driver.find_element_by_name or driver.find_element_by_id commands.
Find elements by Name
Find elements by id
How can we resolve this issue?
To quote the Selenium documentation:
To find multiple elements (these methods will return a list):
find_elements_by_name
find_elements_by_xpath
...
You can't call .click on driver.find_elements_by_xpath() because driver.find_elements_by_xpath() returns a list of elements, rather than a single element.
Suppose driver.find_elements_by_xpath() returns 10 elements. What do you want to do with these 10 elements? Click on the first one? Click on the last one? Click on all of them?
If you only want to find a single element using XPath, use driver.find_element_by_xpath() (note, no s after element) instead.
The documentation page I linked to above lists 8 methods for finding a single element on the page. All of these methods apart from find_element_by_id have a corresponding method for returning multiple elements, whose name differs only by replacing element with elements. (There is no find_elements_by_id method because ids are supposed to be unique: there should never be more than one element with the same id.)
Adding for above answer.
You can use a List to store webelements and loop through them while doing actions. Something in java.
List<WebElement> elements = driver.findElements(By.id("001"));
for(WebElement ele:elements) {
ele.click();
}

Finding an element via xpath by index number of an element in a table

I am trying to find an element via index number in Python Selenium. The element has the following xpath;
/html/body/div[4]/div[1]/div[3]/div/div[2]/div/div/div/div/div/div/div[1]/div[2]/div/div/div/div[2]/div/div/div/div[2]/div/div[3]/div[1]/div/div/div[9]
I have also included the below image of the element I want.
Element I want:
I am able to find the element via normal xpath, but I want to do this in a loop 10,000 times.
I was wondering if there is a way to find the element using its index number. Here is the code I have for it, for just index value 5, but it is not working.
Fund_click.append (driver.find_element_by_xpath("//div[#id='app']/div[1]/div[3]/div/div[2]/div/div/div/div/div/div/div[1]/div[2]/div/div/div/div[2]/div/div/div/div[2]/div/div[3]/div[1]/div/div/[div/#index='5']"))
Based on your snapshot you can try this way to see if you get any difference.I have consider to attribute claas & Index.
for i in range(1,10000):
print(driver.find_element_by_xpath("//div[#class='tg-row tg-level-0 tg-even tg-focused']" and "//div[#index='" + str(i) + "']"))
If you want use index number then just try below code.But i am not sure you are able to identify elements only using index so better to try 1st option above.
for i in range(1,10000):
print(driver.find_element_by_xpath("//div[#index='" + str(i) + "']"))
Try the below xpath to confirm, you can able to locate all the elements or not? If the page is loaded fully then you should see all the matches (Inspect manually).
//div[#id='app']//div[contains(#class, 'tg-row')]
You can fetch and store all the elements by using driver.find_elements_by_xpath() method with the help of above xpath locator so that you can avoid iterating through element index each time. Try the below code :
# Fetching and storing all the matches
elements = driver.find_elements_by_xpath("//div[#id='app']//div[contains(#class, 'tg-row')]");
for element in elements:
# printing the index numbers to confirm it has fetched or not?
print(element.get_attribute('index'))
Try to give some delay before fetching if the element is present and if you get NoSuchElementException or check for frame/iframe.
If all the elements are not visible, you many need to perform some scroll operations.
If the above mentioned method doesn't work then you can try the below xpaths to identify that element based on index/matching index numbers and you can proceed with your approach.
(//div[#id='app']//div[contains(#class, 'tg-row')])[matching index]
or
//div[#id='app']//div[contains(#class, 'tg-row') and #index='provide
index number here']
or
//div[contains(#class, 'tg-row') and #index='provide index number
here']
or
//div[#index='provide index number here']
or
(//div[contains(#class, 'tg-row')])[provide matching index number
here]
I hope it helps...

Scan through row elements whose classname is identical

I have a number of links in rows, in a web page, whose class-names are the same. Like this:
I am able to click the first link occurrence using XPATH,
"(//span[#class='odds black'])"
However, I want to scan through the particular row and click on each odds (if it is present).
Any help on how to achieve this ?
Note: I cannot find the element using other attributes, as it will change dynamically as per the data.
Image of reference source code:
Instead of using the XPATH in this format:
"(//span[#class='odds black'])"
could you use it in this format shown just above your red box:
/html/body/div[2]/div[3]/div[1]/div[1]/div[2]table/tbody[31]/tr[1]/td[5]/a/span[2]/span/span
(you can get this format easily by selecting an element in firebug, right clicking it's code and selecting copy XPATH).
I have found in many instances I can add a counter for a tr[1] or some other path attribute in order to move down rows quite accurately. I can't really see your site to compare the xpath below but I imagine it would be something like:
/html/body/div[2]/div[3]/div[1]/div[1]/div[2]table/tbody[31]/tr[1]/td[5]/a/span[2]/span/span
/html/body/div[2]/div[3]/div[1]/div[1]/div[2]table/tbody[31]/tr[2]/td[5]/a/span[2]/span/span
/html/body/div[2]/div[3]/div[1]/div[1]/div[2]table/tbody[31]/tr[3]/td[5]/a/span[2]/span/span
then you can add a counter like "i"
so you would iterate the counter in the loop and set it to something along the lines of:
"/html/body/div[2]/div[3]/div[1]/div[1]/div[2]table/tbody[31]/tr["+str(i)+"]/td[5]/a/span[2]/span/span"
Assuming that class name will be always 'odds some color' you can use xpath's contains() function. Xpath like this:
"//span[contains(#class,'odds')]"
will return all spans that contain string 'odds' in classname.
CSS selectors are class aware so it would make more sense to me to use;
span.odds
Xpath treats class as a simple string so forces you to use "contains" where as CSS allows you to treat classes separately

Categories