Selenium + Python - entering text in form with no label/id? - python

I"m trying to enter some text in the box as shown below. I've narrowed the element down to SMDMainText. I've tried numerous ways of finding the element, however when I try to send_keys(), the result is that I get the error "element not interactable". The issue that I'm facing is that I'm trying to find an element called <input automplete="on"> and don't quite understand how to send text to it.
element = browser.find_element_by_class_name("styledModalDialogueDIV")
element = browser.find_element_by_css_selector("form")
element = browser.find_element_by_id("SMDMain")
element = browser.find_element_by_id("SMDMainText")
element = browser.find_element_by_css_selector("input")
# comment all but 1 line above, and try below:
element.send_keys("Hello World") # same error is produced for each try

You need to target the input tag.
element = browser.find_element_by_css_selector("#SMDMainText>div>input")

Related

Get text from span (Whatsapp Web)

I am learning Python with Selenium and I would like to capture the username from the last message in a whatsapp group conversation. I tried it in several ways but I couldn't.
Ex:
I would like to get the text "Nay"from this part and store it in a variable.
<span dir="auto" class="FMlAw FdF4z _3Whw5">Nay</span>
Print Screen
I tried:
texto1 = post[ultimo].find_element_by_xpath("//span[#class_name = 'FMlAw FdF4z _3Whw5']").text
But i get an error AttributeError: 'NoneType' object has no attribute 'text'
I achieved relative success with the code below but in addition to copying the user's name, this also copied the messages
texto1 = post[ultimo].find_element_by_class_name("_3Whw5").text
Sorry, I'm using Google Translate.
Thanks.
#get all messsages as a list
messages = driver.find_elements_by_xpath("//div[contains(#class,'message-in focusable-list-item')]/following::span[contains(#class,'selectable-text')]/span")
#reverse the list so you can get easier the last element
messages.reverse()
#last element becomes the first - now you can use it, I printed for the purpose of testing
print(messages[0].text)

How to change a value in an input element using Selenium in Python?

I got a input element that I need to clear the actual value and input another one.
The HTML has the following structure:
<input class="input-mini" type="text" name="daterangepicker_start" value="">
I used the following code to find this element:
test = browser.find_elements_by_css_selector("input[type='text'][name='daterangepicker_start']")
Then I got a list of 7 elements and I guess the first one is the one. So a tried to clear the field and after send the new value as following:
test[0].clear()
test[0].send_keys('02/07/2019')
However, for both codes I got the same error:
ElementNotInteractableException: element not interactable
(Session info: chrome=76.0.3809.87)
Sometimes, the element can be under a <div that is considered hidden, I have experienced this before, sometimes you can try .click() to make the element Interactable, like this:
test[0].click()
test[0].clear()
test[0].send_keys('02/07/2019')
In case the above does not allow the element to change to an interactable state, try changing the value with javascript:
browser.execute_script("arguments[0].value = arguments[1]", test[0], "02/07/2019")
I would also recommend to look through the element list and figure out which one within the list is actually the element you're trying to interact with, in case it's not truly test[0].
Use WebDriverWait
test = WebDriverWait(driver, 5).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR , "input[type='text'][name='daterangepicker_start']")))
test[0].clear()
test[0].send_keys('02/07/2019')

Getting unexpected TypeErrorwhen trying to find element on page by text

I am using a wait function to make Selenium search for the presence of an element on the page by its text before it continues to take actions. I am trying to pass the text that I am searching for into my function, however, I keep getting "TypeError: 'str' object is not callable", which is odd because I am looking for a string! I've tried everything I can think of, even escape sequences, but nothing seems to make it work. Please find my code below:
self.webdriver_wait(action = 'find_text', keys_to_pass = 'Financial Documents')
def webdriver_wait(self, selector = '#body', action='', keys_to_pass=''):
try:
WebDriverWait(self.browser, 240).until(EC.presence_of_element_located((By.XPATH("//*[contains(text(), \' + str(keys_to_pass) + \'')]"))))
By.XPATH is not a method, but a simple string (By.XPATH == 'xpath'), you need to use it as below:
WebDriverWait(self.browser, 240).until(EC.presence_of_element_located((By.XPATH, "//*[contains(text(), '%s')]" % keys_to_pass)))

Selenium get textarea error

I'm trying to scrap in a website using Selenium and Python, I got stucked in a field called 'textarea' by the website. This is how the website HTML calls the area where I'm trying to extract text:
<textarea class="script" onclick="this.focus();this.select()" readonly="readonly" id="script">
After this code comes the text that I want to get. Here is the code that I'm using:
getCode = driver.find_elements_by_tag_name('textarea')
My problem is that It does not recognize the text by the following codes:
getCode.submit()
getCode.click()
getCode.text()
This is the code error that I always get:
Traceback (most recent call last):
File "ScprL.py", line 55, in module
print (repr(getCode.text))
AttributeError: 'list' object has no attribute 'text'
I would apreciate your help!
You should use driver.find_element_by_tag_name instead
When you use driver.find_elements you get a list of webElements. You should extract the element from the list
elem = driver.find_elements_by_tag_name('textarea')[0]
print element.text
If you have multiple textareas on the page, then you should try to finding the one you need like below
textareas = driver.find_elements_by_tag_name('textarea')
for i, textarea in enumerate(textareas):
print '{} is at index {}'.format(textarea.text, i)
And then use the appropriate i value to get textareas[i]
As you are using driver.find_elements_by_tag_name('textarea') it will retrieve list of web elements. Need to collect these web elements then iterate one by one then get text of each of web element. below is the example in java,
List<WebElement> ButtonNamelist = driver.findElements(By.cssSelector(".locatorHere"));
System.out.println(ButtonNamelist.size());
for(int i=0;i<ButtonNamelist.size();i++){
System.out.println(ButtonNamelist.get(i).getText());
}
Thank You,
Murali
There are two functions for each locator in selenium: "find_elements" and "find_element". The difference is pretty simple: the first one return a list of elements that satisfy selector and the second one returns first found element. You can read more about locating elements here.
So you either need to change your function to find_element_by_tag_name or to retrieve first element from list: find_element_by_tag_name()[0].

XPath: Assessing an Error in this Line of Code?

I recently began learning XPath for a Python project, but I can't seem to get the following line selecting the correct piece of data.
//table[#id="yfncsumtab"]//tr/td/a[#rel="first"]
Said data is found on this page:http://finance.yahoo.com/q/hp?s=QQQX+Historical+Prices
(Inspect Element the "Next" link to get to the code I'm attempting to create an XPath to. In other words, Command/Control F on that page, and Inspect Element the first result)
I've tried many variations of that code, but none seem to select the proper text. I appreciate any and all help - thanks in advance!
'//a[text()="Next"]'
or:
'//table[#id = "yfncsumtab"]//a[text()="Next"]'
or, to get just the first one:
'//table[#id = "yfncsumtab"]//table[1]/tr/td/a[text()="Next"]'
or:
'//table[#id="yfncsumtab"]/tr[2]/td[1]/table[1]/tr/td/a[1]'
The more specific you are, the faster it is to find the element. However, the more specific you are, the more brittle the xpath is: if the developers make a small change in the html structure surrounding the target element, your code won't work.
from lxml import html
doc = html.parse("http://finance.yahoo.com/q/hp?s=QQQX+Historical+Prices")
my_xpath = '//a[text()="Next"]'
for element in doc.xpath(my_xpath):
print("<{}>".format(element.tag))
print(" text = {}".format(element.text))
for attr, val in element.items():
print(" {} = {}".format(attr, val))
--output:--
<a>
text = Next
rel = next
href = /q/hp?s=QQQX&d=11&e=28&f=2014&g=d&a=1&b=1&c=2007&z=66&y=66
<a>
text = Next
rel = next
href = /q/hp?s=QQQX&d=11&e=28&f=2014&g=d&a=1&b=1&c=2007&z=66&y=66
Try this one:
//*[(#id = "yfncsumtab")]//a[(((count(preceding-sibling::*) + 1) = 3) and parent::*)]
With this Xpath I get both the top and the bottom 'Next' link.

Categories