How to find second element of a WebElement in Selenium - python

i want to get the second child element of content.When i try this code it says the nth-child(2) is not a valid expression. How can i get the child element of content?
content= stream.find_elements_by_class_name("content")
for l in content:
child = l.find_elements_by_xpath("nth-child(2)")
print(child.tag_name)

This solution works for me.
child = l.find_elements_by_xpath("./*[2]").

Related

Why does it print the session id instead of the element path?

Code:
FindComment = browser.find_element_by_xpath("//*[contains(text(), 'commented')]").parent
print(FindComment)
Output:
<selenium.webdriver.firefox.webdriver.WebDriver (session="99sf9sfjSIFSf-f9sf(JSFsfsfs")>
Not sure why it prints this. I want it to print the actual element path
https://www.selenium.dev/selenium/docs/api/py/webdriver_remote/selenium.webdriver.remote.webelement.html
parent
Internal reference to the WebDriver instance this element was
found from.
You cannot find the locator from webelement
The only thing you could do is
element.get_attribute("outerHTML")

Get child element using xpath selenium python

We can get a parent of a selenium element using xpath, by
par_element = element.find_element_by_xpath('..')
In a similar fashion, how can we get the child of the element? I tried the following and did not work
child_element = element.find_element_by_xpath('/')
child_element = element.find_element_by_xpath('//')
To get to the child of the WebElement you need to set the context to the current element using the dot character i.e. .. So effectively your line of code can be either of the following:
child_element = element.find_element_by_xpath('./')
or
child_element = element.find_element_by_xpath('.//')

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.

How to find child element while having found the parent div?

I have a google form that I am webscraping(at least trying to). I want to look through it to find text where it says "Name ", then find the parent div of the whole block that contains that question and look for an input element where I can use send_keys() to fill out my name. I was able to find "Name " and find the parent div.
src = result.content
driver = webdriver.Chrome()
driver.get('https://exampleform.com')
soup = BeautifulSoup(src, 'html.parser')
name = soup.find(string="Name ")
nameBlock = name.find_parents('div', class_="freebirdFormviewerViewNumberedItemContainer", limit = 1)
if soup.find(string="Name "):
print('yes')
#prints yes
if name.find_parents('div', class_="freebirdFormviewerViewNumberedItemContainer", limit = 1):
print('okay')
#prints okay
if nameBlock.find('input'):
print('yup')
#gets error
# Also have tried nameBlock.find(tag = 'input')
# and nameBlock.find_element_by_tag_name('input)
# and name.find_parents('div', class_="freebirdFormviewerViewNumberedItemContainer", limit = 1).find('input)
I have tested out that I have found the parent function by printing out the variable "nameBlock" and was able to get the whole parent div and saw with the input tag there in the console. But then I get this error when I try the use the final "if" statement to see if I was able to locate the input element:
AttributeError: ResultSet object has no attribute 'find_elements_by_tag_name'. You're probably treating a list of elements like a single element. Did you call find_all() when you meant to call find()?
I think it has the parent selected as each child within that parent as well so every child is looking for
nameBlock.find('input')
but I am not really sure how I would go about just selecting the child input element. Any suggestions? Also here is the HTML to better help understand my issue.
AttributeError: ResultSet object has no attribute 'find_elements_by_tag_name'. You're probably treating a list of elements like a single element. Did you call find_all() when you meant to call find()?
The error says that You have used find_elements_by_tag_name() which returns as list not the webelement.
Change this to
find_element_by_tag_name() which will return as webelement and you can now use send_keys() method.

Indexing over the results returned by selenium

I try to index over results returned by an xpath. For example:
xpath = '//a[#id="someID"]'
can return a few results. I want to get a list of them. I thought that doing:
numOfResults = sel.get_xpath_count(xpath)
l = []
for i in range(1,numOfResults+1):
l.append(sel.get_text('(%s)[%d]'%(xpath, i)))
would work because doing something similar with firefox's Xpath checker works:
(//a[#id='someID'])[2]
returns the 2nd result.
Ideas why the behavior would be different and how to do such a thing with selenium
Thanks
Can you try the xpath /html/descendant::a[#id="someID"] You can replace the /html with something else that is an ancestor of your links like id('content'). You should then be able to locate individual links using [1], [2] etc.
From the XPath TR at http://www.w3.org/TR/xpath#path-abbrev:
NOTE: The location path //para[1] does not mean the same as the location path /descendant::para[1]. The latter selects the first descendant para element; the former selects all descendant para elements that are the first para children of their parents.
The answer is that you need to tell selenium that you're using xpath:
numOfResults = sel.get_xpath_count(xpath)
l = []
for i in range(1,numOfResults+1):
l.append(sel.get_text(xpath='(%s)[%d]'%(xpath, i)))
In Selenium you normally do it without the extra brackets so your loop would look like the following
numOfResults = sel.get_xpath_count(xpath)
l = []
for i in range(1,numOfResults+1):
l.append(sel.get_text('%s[%d]'%(xpath, i)))
And that will produce a valid XPath in Selenium like //a[#id='someID'][2]

Categories