Python Selenium sending keys to a textfield - python

Im writing a google forms submitter and I'm having problems with the textfield-type questions.
Basically I am using:
textfield = question.find_element_by_class_name("quantumWizTextinputPaperinputInput")
to find the textfield and then the problems start coming in. The type of "textfield" is:<selenium.webdriver.firefox.webelement.FirefoxWebElement (session="1b49148e-2a24-4efb-b3a5-e84be92223ae", element="3b437c8b-8d05-4410-8047-bcac9ea81f0f")>
and when I want to call .send_keys(string) on it it says that Exception has occurred: AttributeError 'list' object has no attribute 'send_keys'
So basically it says that the element returned is a list (noenetheless that type() returns a firefoxwebdriver element type).
So if I try to go with textfield[0] or textfield[1] etc... it of course throws an error that a FirefoxWebDriver is not subscribable.
What the frick?
Here's the block of code:
buttons = question.find_elements_by_class_name("appsMaterialWizToggleRadiogroupRadioButtonContainer")
buttons2 = question.find_elements_by_class_name("quantumWizTogglePapercheckboxInnerBox")
try:
textfield = question.find_element_by_class_name("quantumWizTextinputPaperinputInput")
except:
print("not found")
textfield = []
pass
And then below to send keys into it:
if len(buttons) == 0 and len(buttons2) == 0:
print(textfield)
textfield.send_keys("lol spam")

try:
textfield = question.find_element_by_class_name("quantumWizTextinputPaperinputInput")
except:
print("not found")
textfield = []
pass
The problem lies within this snippet. If textfield, or to be more specific the class_name quantumWizTextinputPaperinputInput can't be found, Python continues to evaluate the except block. Within there you stated textfield = [] - that's the reason for your problems:
Exception has occurred: AttributeError 'list' object has no attribute
'send_keys' So basically it says that the element returned is a list
(noenetheless that type() returns a firefoxwebdriver element type). So
if I try to go with textfield[0] or textfield[1] etc... it of course
throws an error that a FirefoxWebDriver is not subscribable.
You can't send send_keys to a list.
List is empty, hence a textfield[0] should throw IndexError.
A solution to this problem is to find the proper class_name. Without a HTML code we can't help you to do that.

Related

How do I return a Null value when an element is missing from Selenium with Python

I have a script where I get some data from a web page in Selenium using Python. However for some of the pages I'm scraping through, some of the elements are not present and this throws a NoSuchElementException error.
How do I return a null value for when the element is not present. I reied using or None but it still throws the error. Also, the elements following this one also depend on the presence of the first one as shown below:
metadata = driver.find_element(By.PARTIAL_LINK_TEXT, 'Complete metadata on ') or None
metadata_url = metadata.get_attribute('href') or None
dataset_id = metadata_url.split('metadata/')[1] or None
output_dict['datasets'].append({'title': dataset_title, 'url': dataset_link, 'metadata_url': metadata_url})
The element that is missing from some pages is the metadata.
I'm looking to populate the metadata_url field as null.
Please assist with this.
This code:
var = function_call(param) or None
runs the function, gets the output, transforms this output into a boolean (see truthyness in python), and if that output is False, then it sets that variable to None instead.
However, the function (find_element, here) doesn't return a Falsy value, but raises a NoSuchElementException exception if it doesn't find anything.
That means you need to use a try except block in your code instead of the or None
try:
metadata = driver.find_element(By.PARTIAL_LINK_TEXT, 'Complete metadata on ')
# If we are at this line, then find_element found something, and we
# can set values for our url and dataset id
metadata_url = metadata.get_attribute('href') # this will be None if there's no href attribute
dataset_id = metadata_url.split('metadata/')[1]
except selenium.common.exceptions.NoSuchElementException:
metadata_url = None
dataset_id = None
In the case when metadata_url is None, you will need to handle that case, because metadata_url.split will not work, it will raise a AttributeError: 'NoneType' object has no attribute 'split'.
I guess you're trying to use JS syntax in Python. You'll have to instead check if the element exists first.
if not metadata_url:
return None

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 ''

Python intermittently throws "AttributeError: 'NoneType' object has no attribute 'get'" on the same dictionary

I have a nested dictionary like so:
mail = {
'data': { 'from': {'text': '123#example.com'}}
# some other entries...
}
I'm trying to copy from value using following code:
data = mail.get('data')
new_dict['parse']['from'] = data.get('from').get('text')
The second line throws the exception:
AttributeError: 'NoneType' object has no attribute 'get'
The strange thing is, this only happens sometimes. If I add a print statement just before the second line like:
data = mail.get('data')
print(type(data.get('from')))
new_dict['parse']['from'] = data.get('from').get('text')
The error disappears and I get <class 'dict'> as expected. If I remove the print statement, it works sometimes and other times it throws the error. Nothing else changes in the code or data. The reason I'm using get() is to retrieve value safely in case the key is missing.
In the call data.get('from').get('text'), if data does not contain the key 'from', it will return None. None.get('text') raises then the exception you see, because a None object has no get method (of course).
The way around this is to pass in a better default-object than None (the default default-object), which has the get method. That would be an empty dictionary, {}:
data = mail.get('data')
new_dict['parse']['from'] = data.get('from', {}).get('text')

AttributeError: "str' object has no attribute 'text

I make script for shopify cart since it is impossible to purchase manually, when I ran the script to my command prompt,
it says ,
line 109, in AttributeError: "str' object has no attribute
'text
Scrape Product Info based on selected colors
if blue and cinder:
productInfo(urlBlueResponse.text)
productInfo(urlCinderResponse.text)
elif blue:
productInfo(urlBlueResponse.text)
elif cinder:
productInfo(urlCinderResponse.text)
else:
print(Fore.RED + timestamp
I was told it was from a capitalization mismatch, can somebody please explain this to me. I am new to coding and I want to learn all I can.
Based on the error message, either urlBlueResponse or urlCinderResponse (or both) are a string datatype. The way you are using them, it appears you expect these to be objects which have a text attribute. The error message is telling you that they're str objects and don't have text attributes.
This error happened when you tried to access an attribute on a string object -- .text -- that does not exist as an element on that object.
It looks like your code is working with HTTP request and response objects of some kind: urlBlueResponse
It is plausible that you got an error or some other unexpected behavior in the request/response cycle that resulted in one of the response objects returning a str (string) type instead of a response object with a text attribute. I suggest you handle the exception with a try/except block:
try:
if blue and cinder:
productInfo(urlBlueResponse.text)
productInfo(urlCinderResponse.text)
elif blue:
productInfo(urlBlueResponse.text)
elif cinder:
productInfo(urlCinderResponse.text)
else:
print(Fore.RED + timestamp)
except AttributeError as e:
#exception handler logic goes here
print("got exception: ")
print(e)
#if error indicates your request is recoverable then do so:
if recoverable(e):
do_request(again)
#if error is unrecoverable, decorate it and reraise it
#(See *Link)
# or just reraise it:
raise(e)
*Link: (Re-raise exception with a different type and message, preserving existing information)
urlBlueResponse = eval(urlBlueResponse)

Python if no AttributeError

I have a small script that returns the title of a webpage
title = BeautifulSoup(urllib2.urlopen(URL)).title.string
But not all websites specify a <title> tag, in which case my script returns
AttributeError: 'NoneType' object has no attribute 'string'
Is there a way to have the title variable equal to the title if there is a title on the webpage?
I am tried
if BeautifulSoup(urllib2.urlopen(url)).title.string.strip():
print BeautifulSoup(urllib2.urlopen(url)).title.string.strip()
else:
print url
But it still raises the AttributeError error
try:
title = BeautifulSoup(urllib2.urlopen(URL)).title.string
except AttributeError:
title = url
You can use inbuilt function getattr to check whether the attribute exists and if not set a default value to it.
In your case it will be like
title = getattr(BeautifulSoup(urllib2.urlopen(URL)).title, 'string', 'default title')
Check documentation for getattr function - https://docs.python.org/2/library/functions.html#getattr

Categories

Resources