Double condition with Xpath selenium Python - python

I want to access elements of all balises that find like this : <div class='xxxx' the text >
I did as this with Xpath:
textSearch = 'the text'
hometeam = driver.find_elements(By.XPATH,"//div[#class='xxxx'] and //div[contains(text(),'"+ textSearch +"')]")
But this not works and casting this exception : TypeError: Failed to execute 'evaluate' on 'Document': The result is not a node set, and therefore cannot be converted to the desired type.
How do ?

Combine the conditions within the [...]
E.g., //div[#class='xxxx' and contains(text(), 'justin')].
Demo here

Related

SyntaxError: Failed to execute 'evaluate' on 'Document': xpath

Element:
XPATH:
//*[#id="autocomplete_code"]
I am getting syntax error for below statement, what is not correct in this xpath? I tried just with id and both id & class.
account = driver.find_element(By.XPATH,"//*input[#id='autocomplete_code' and #class = 'account_code_ac inputSearch ui-autocomplete-input']")
changing code as below fixed the syntax error, but still not able to select the search result value with arrow down key
account = driver.find_element(By.XPATH,"//*[#id='autocomplete_code']")
account.send_keys("1100-1200-200167-620038")
account.send_keys(Keys.ARROW_DOWN)
account.send_keys(Keys.RETURN)
changing code as below works fine:
account =driver.find_element(By.XPATH,"//*[#aria-label='Search an Account']").click()
account = driver.find_element(By.XPATH,"//*[#id='autocomplete_code']")
account.send_keys("1100-1200-200167-620038")
element = wait.until(EC.visibility_of_element_located((By.XPATH, '//a[contains(#aria-label, "1100-1200-200167-620038")]')))
account.send_keys(Keys.ARROW_DOWN)
account.send_keys(Keys.RETURN)

How to construct a xpath expression with variable for Selenium in python using %s

I am trying to use selenium to locate and select a certain element based on a variable passed into the function when it is called. I thought this would be simple enough with a good ol:
show = browser.find_element_by_xpath("//*[contains(text(), '%s')]" % eventName)
However, I receive error:
selenium.common.exceptions.InvalidSelectorException: Message: invalid selector: Unable to locate an element with the xpath expression //*[contains(text(), 'VARIABLE_TEXT')] because of the following error:
SyntaxError: Failed to execute 'evaluate' on 'Document': The string '//*[contains(text(), 'VARIABLE_TEXT')]' is not a valid XPath expression.
Here is--distilled and simplified--the part of the HTML I am attempting to select:
<ul>
<li class="seriesElement">
<input id="productionId_0" name="productionIds" type="checkbox" value="VALUE"><input type="hidden" name="_productionIds" value="on"><label for="productionId_0" class="prodColor0">TEXT</label>
</li>
<li class="seriesElement">
<input id="productionId_1" name="productionIds" type="checkbox" value="VALUE"><input type="hidden" name="_productionIds" value="on"><label for="productionId_1" class="prodColor1">TEXT</label>
</li>
</ul>
There are many of these list elements, and I want to select one by the text. Have I just used the wrong syntax for my xpath expression, or is this a different beast entirely?
You can try this way.See if this helps.
VAR_TEXT="TEXT"
print(driver.find_element_by_xpath("//label[contains(text() ,'" + VAR_TEXT + "')]").text)
OR
VAR_TEXT="TEXT"
print(driver.find_element_by_xpath("//*[contains(text() ,'" + VAR_TEXT + "')]").text)
OR
VAR_TEXT="TEXT"
print(driver.find_element_by_xpath("//label[text()[contains(.,'" + VAR_TEXT + "')]]").text)
OR
VAR_TEXT="TEXT"
print(driver.find_element_by_xpath("//*[text()[contains(.,'" + VAR_TEXT + "')]]").text)
To locate a certain element based on it's variable text you can write a method as follows:
Using .:
def find_myelement_with_text(myString):
show = browser.find_element_by_xpath("//label[.='" + myString + "']")
Using %s:
def find_myelement_with_text(myString):
show = browser.find_element_by_xpath("//label[contains(text(), '%s')]" % (myString))
Using format():
def find_myelement_with_text(myString):
show = browser.find_element_by_xpath('//label[contains(text(), "{}")]'.format(myString))
Now you can call this method from anywhere within your program as follows:
find_myelement_with_text("TEXT")
The good ol' 😀 %s worked as expected - you can see the substitution in the error message, the problem is with the xpath itself.
If you run it through a standalone parser (not the browser's one), you'll see the culprit for the error:
Unable to perform XPath operation. A sequence of more than one item is not allowed as the first argument of contains() ("", "", ...)
(that's a Java one, the text will be similar for other ones)
Long story short it's the output of text() that bothers it - it's a nodeset; if you change that function to a ., it should work:
show = browser.find_element_by_xpath("//*[contains(., '%s')]" % eventName)

How to extract text from element where the parent element is having attribute style="display:none" using Selenium

I want to extract Phone number from this div. This div has style="display:none"
So I can not access the children of this div. Please help me out in getting the phone number from the div.
I guess We need to change that display:none; to visibility:visible. How can I do this in Python Selenuim
Edit
I have tried the code below, as suggested in the first answer but it throws the following error:
email_div = browser.find_element_by_class_name("returnemail")
email_div_contents = browser.execute_script('return arguments[0].innerHTML', email_div)
telephone = email_div_contents.find_element_by_class_name('reply-tel-number').get_attribute('textContent')
AttributeError: 'str' object has no attribute
'find_element_by_class_name
'
As per the documentation execute_script() returns:
The command's JSON response loaded into a dictionary object.
Hence, moving forward when you attempted to invoke find_element_by_class_name() method on the dictionary object as follows:
email_div_contents.find_element_by_class_name('reply-tel-number').get_attribute('textContent')
The following error is raised:
AttributeError: 'str' object has no attribute 'find_element_by_class_name'
To remove the attribute style="display:none" from the desired element and extract the phone number you can use the following solution:
element = driver.find_element_by_xpath("//div[#class='returnemail js-only']")
driver.execute_script("arguments[0].removeAttribute('style')", element)
tel_number = element.find_element_by_xpath("./aside/ul//li//p[#class='reply-tel-number']").get_attribute("innerHTML")
Your code has incorrect place:
email_div = browser.find_element_by_class_name("returnemail")
email_div_contents = browser.execute_script('return arguments[0].innerHTML', email_div)
email_div_contents.find_element_by_class_name()
email_div_contents is a string represents the HTML code of the email_div, not a web element,
You can't call find_element_by_class_name() on a string.
That's why you got error:
'str' object has no attribute 'find_element_by_class_name'
You can always call get_attribute() to fetch attribute value on visible and invisible element.
To get the text content of invisible element you can use get_attribute('innerText').
phone_number = driver.find_element_by_css_selector("div.returnemail .reply-tel-number")
.get_attribute('innerText')
Actually, element.text call element.get_attribute('innerText') inside, but element.text will respect user experience: If user can't see the element from page, element.text will return empty string as user see. (Even element.get_attribute('innerText') return non-empty string)
#property
text:
if ( element is visible ):
return element.get_attribute('innerText')
else:
return ''

How can I click in link but without "a href" [Selenium + Python]

I don't know how can I click on "Utwórz konto" on https://www.morele.net/login.
I tried:
link_registration = driver.find_element_by_class_name("//li[#class = 'el-login-nav register']")
link_registration.click()
but I get error:
selenium.common.exceptions.InvalidSelectorException: Message: Given
css selector expression ".//li[#class = 'el-login-nav register']" is
invalid: InvalidSelectorError: './/li[#class = 'el-login-nav
register']' is not a valid selector: ".//li[#class = 'el-login-nav
register']"
You are trying to pass an XPath expression to the "by class name" locator - no wonder it fails.
I would use a CSS selector instead:
register = driver.find_element_by_css_selector(".autorization-form .register")
register.click()
.autorization-form .register would match an element having a register class somewhere (at any depth level) inside an element having an autorization-form class. Space here means parent-child relationship - but the child can be at any level inside the parent.
You are getting that error because you used the find_element_by_class_name() command but passed in an xpath. You need to either use find_elements_by_xpath() or a different locator function. Either of these should work:
driver.find_element_by_xpath("//li[#class = 'el-login-nav register']");
driver.find_element_by_css_selector("li.register")

How to get rid of Cannot focus element exception

I faced with following issue with chromedriver: I have a text input field and a texarea. I can successfully send text to both elements with follow code
input = driver.find_element_by_xpath('//input[#type="text"]')
input.send_keys('test')
textarea = driver.find_element_by_xpath('//textarea[not(#readonly)]')
textarea.send_keys('test')
But if to try this code
text_fields = driver.find_elements_by_xpath('//*[input[#type="text"] or textarea[not(#readonly)]]')
for field in text_fields:
field.send_keys('test')
I get selenium.common.exceptions.WebDriverException: Message: unknown error: cannot focus element
P.S. Adding field.click() before sending text or using ActionChains failed to solve issue. Also len(text_fields) return 2, so both elements correctly matched with XPath
The second expression will return the parent element of the input or textarea. If you wish to get both in a single XPath then:
text_fields = driver.find_elements_by_xpath("//input[#type='text'] | //textarea[not(#readonly)]")
for field in text_fields:
field.send_keys('test')
Or with a CSS selector :
text_fields = driver.find_elements_by_css_selector("input[type='text'] , textarea:not([readonly])")
for field in text_fields:
field.send_keys('test')

Categories

Resources