Locating divs with changing class names (selenium) - python

I am taking a selenium course online and we are automating log ins. The lecture is outdated and the website we are using is updated (Quora).
The problem is, the input fields have randomly generated class names which makes the "find_element_by_id method useless.
I can not figure out how to log in for different sessions. How would I select these fields during different sessions ( that have different class names ). This is what my code looks like. Thank you in advance. I tried asking the course instructor but he hasnt responded all week.
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome(executable_path = r'/Users/mpbro17/Desktop/chromedriver')
driver.get('https://www.quora.com')
driver.find_element_by_id("__w2_fy0VXDC_email").clear()
driver.find_element_by_id("__w2_fy0VXDC_email").send_keys("programmingdude183#gmail.com")
driver.find_element_by_id("__w2_fy0VXDC_password").clear()
driver.find_element_by_id("__w2_fy0VXDC_password").send_keys("testpassword1")
driver.find_element_by_id("__w2_fy0VXDC_submit_button").click()
ERROR
Traceback (most recent call last):
File "/Users/mbpro/Desktop/projects/scraping_course/test_quora_login.py", line 13, in <module>
driver.find_element_by_name("email").clear()
File "/usr/local/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py", line 92, in clear
self._execute(Command.CLEAR_ELEMENT)
File "/usr/local/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py", line 494, in _execute
return self._parent.execute(command, params)
File "/usr/local/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 236, in execute
self.error_handler.check_response(response)
File "/usr/local/lib/python2.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 192, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.InvalidElementStateException: Message: invalid element state: Element is not currently interactable and may not be manipulated
(Session info: chrome=53.0.2785.143)
(Driver info: chromedriver=2.24.417412 (ac882d3ce7c0d99292439bf3405780058fcca0a6),platform=Mac OS X 10.11.5 x86_64)

Try css selectors instead:
driver.find_element_by_css_selector('[id$="email"]')
driver.find_element_by_css_selector('[id$="password"]')
driver.find_element_by_css_selector('[id$="submit_button"]')

You could have used find_element_by_name method to find your elements (email and password) and cssSelector for Login button. I think, this won't make you disheartened.
driver.find_element_by_name("email").clear()
driver.find_element_by_name("email").send_keys("programmingdude183#gmail.com")
driver.find_element_by_name("password").clear()
driver.find_element_by_name("password").send_keys("testpassword1")
driver.find_element_by_css_selector("input[value='Login']").click()

You have to go with name as it standard.However there are two elements present if you go by name property.
So go by the below xpath
//div[#class='regular_login']//input[#name='email']
//div[#class='regular_login']//input[#name='password']
//div[#class='regular_login']//input[contains(#class,'submit')]

Related

Python WebDriver send_keys not working on element and returns ElementNotInteractableException

I am trying to send some keystrokes using python webdriver to a p element that is attached to a js event listener. When i type the keys in manually, it works. However when I use driver.send_keys(), it returns an ElementNotInteractableException. The element is as follows:
<p data-v-6779462c="" id="textBox" class="input"></p>
My code to locate and send the keystrokes to the element is as follows:
input_area = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, '//p[#id="textBox"]')))
input_area.click()
input_area.send_keys(keys)
input_area.send_keys(Keys.ENTER)
The full stacktrace is as follows:
Traceback (most recent call last):
File "automation.py", line 32, in <module>
input_area.send_keys(word)
File "/home/server/.local/lib/python3.8/site-packages/selenium/webdriver/remote/webelement.py", line 477, in send_keys
self._execute(Command.SEND_KEYS_TO_ELEMENT,
File "/home/server/.local/lib/python3.8/site-packages/selenium/webdriver/remote/webelement.py", line 633, in _execute
return self._parent.execute(command, params)
File "/home/server/.local/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
self.error_handler.check_response(response)
File "/home/server/.local/lib/python3.8/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable
(Session info: chrome=87.0.4280.66)
I am using Chrome on Ubuntu Linux.
I need the way to solve this and why it is happening.
Thanks in advance!
P tag is a paragraph tag , you cannot Interact with it .
You should be sending keys to input tag
Try below code
input_area.click()
elemInput = driver.switch_to.active_element
elemInput.send_keys(Keys.ENTER)

How to cancel a download at chrome://downloads with Selenium in Python 3

This question is very similar to Selenium webdriver can't find elements at chrome://downloads
I'm trying to use Selenium with Python (3) to get at the cancel button on the chrome://downloads page. My use case is that I have an obfuscated link for which a random token is generated every time a user clicks on it. If you don't click on it, you can't start the download (it seems to fire a piece of js that generates the token, but I haven't been successful in digging through the code to figure out how that happens).
For my test to pass, all I need is to verify that:
The download starts (and doesn't give a 404), and
The file it's trying to download is the right size.
The way that I'm trying to accomplish this is by triggering the download by clicking on the button element, then having Selenium open chrome://downloads, cancel the download, and capture the file size of the file that it attempted to download.
In theory this seems like it should work, the stumbling block is trying to access any elements in the #shadow-root tags on the chrome://downloads page. The solution to the other question which I linked above unfortunately no longer works:
driver = webdriver.Chrome("chromedriver.exe")
driver.get("chrome://downloads/")
manager = driver.find_element_by_css_selector('body/deep/downloads-manager')
item = manager.find_element_by_css_selector('body/deep/downloads-item')
shadow = driver.execute_script('return arguments[0].shadowRoot;', item)
link = shadow.find_element_by_css_selector('div#title-area>a')
file_url = link.get_attribute("href")
... as it fails on the item declaration line:
>>> item = manager.find_element_by_css_selector('body/deep/downloads-item')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.7/site-packages/selenium/webdriver/remote/webelement.py", line 430, in find_element_by_css_selector
return self.find_element(by=By.CSS_SELECTOR, value=css_selector)
File "/usr/local/lib/python3.7/site-packages/selenium/webdriver/remote/webelement.py", line 659, in find_element
{"using": by, "value": value})['value']
File "/usr/local/lib/python3.7/site-packages/selenium/webdriver/remote/webelement.py", line 633, in _execute
return self._parent.execute(command, params)
File "/usr/local/lib/python3.7/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
self.error_handler.check_response(response)
File "/usr/local/lib/python3.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"body/deep/downloads-item"}
(Session info: chrome=80.0.3987.149)
This is out of my area of expertise, and any help in figuring out how to get at the cancel button would be greatly appreciated.
Please try the below.
driver.execute_script("document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector("cr-button[focus-type='cancel']").click()")
If you need more information how to work on the shadow-root elements, please refer here. And if you want to work on the downloads then you can refer to this and update the js as per your requirement.

Selenium-python2.7: click on a modal table checkbox (following Selenium IDE)

I think my question is somehow related to this post
Selenium - cannot click on an element inside a modal
I click on a an element and it opens a modal table. Then, I would like to select a particular checknox in a long list but Selenium gives me back an error.
That's what I did:
I tested first with Selenium IDE: first I recorded the operations but when I try to replay them in the log I get this:
Running 'Step2_sele'
1.open on /reserve-space/... OK
2.click on css=a[title="Locations"] > span... OK
3.click on linkText=Add/Remove Locations... OK
4.Trying to find xpath=//input[#value='2427']... Failed:
Element is not currently visible and may not be manipulated
I thought I should have given more time to the element to show up and I wrote this with Python
browser = webdriver.Chrome()
browser.get(url_res)
time.sleep(10)
browser.find_element_by_css_selector('a[title="Locations"]>span').click()
time.sleep(10)
browser.find_element_by_css_selector('a.dynamic-filter-item-add.summary').click()
time.sleep(10)
browser.find_element_by_xpath("xpath=//input[#value='2427']").click()
But I get this other error
Traceback (most recent call last):
File "bot.py", line 69, in <module>
browser.find_element_by_xpath("xpath=//input[#value='2427']").click()
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 393, in find_element_by_xpath
return self.find_element(by=By.XPATH, value=xpath)
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 966, in find_element
'value': value})['value']
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 320, in execute
self.error_handler.check_response(response)
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.InvalidSelectorException: Message: invalid selector: Unable to locate an element with the xpath expression xpath=//input[#value='2427'] because of the following error:
TypeError: Failed to execute 'evaluate' on 'Document': The result is not a node set, and therefore cannot be converted to the desired type.
(Session info: chrome=69.0.3497.100)
(Driver info: chromedriver=2.41.578737 (49da6702b16031c40d63e5618de03a32ff6c197e),platform=Windows NT 10.0.16299 x86_64)
This is a screenshot of how the html code look like because I cannot post the real url
I assume the xpath string causes the problem. If my assumption is correction, the following should work:
browser.find_element_by_xpath("//input[#value='2427']").click()

Trouble finding element

I am very new to coding and I am trying to make a form filler on Nike.com using the Selenium Chrome webdriver. However, a pop-up comes up about cookied and I am finding it hard to remove it so I can fill out the form.
This is what it looks like
and my code looks like this:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
#Initialise a chrome browser and return it
def initialisebrowser():
browser=webdriver.Chrome(r'''C:\Users\ben_s\Downloads\chromedriver''')
return browser
#Pass in the browser and url, and go to the url with the browser
def geturl(browser, url):
browser.get(url)
#Initialise the browser (and store the returned browser)
browser = initialisebrowser()
#Go to a url(nike.com) with the browser
geturl(browser,"https://www.nike.com/gb/en_gb/s/register")
button = browser.find_element_by_class_name("nsg-button.nsg-grad--nike-orange.yes-button.cookie-settings-button.js-yes-button")
button.click()
When I run this code, I get this error:
Traceback (most recent call last):
File "C:\Users\ben_s\Desktop\Nike Account Generator.py", line 19, in <module>
button = browser.find_element_by_class_name("nsg-button.nsg-grad--nike-orange.yes-button.cookie-settings-button.js-yes-button")
File "C:\Python\Python36\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 557, in find_element_by_class_name
return self.find_element(by=By.CLASS_NAME, value=name)
File "C:\Python\Python36\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 957, in find_element
'value': value})['value']
File "C:\Python\Python36\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 314, in execute
self.error_handler.check_response(response)
File "C:\Python\Python36\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"class name","selector":"nsg-button.nsg-grad--nike-orange.yes-button.cookie-settings-button.js-yes-button"}
(Session info: chrome=67.0.3396.87)
(Driver info: chromedriver=2.38.552522 (437e6fbedfa8762dec75e2c5b3ddb86763dc9dcb),platform=Windows NT 10.0.17134 x86_64)
Any ideas, pointers or solutions to the problem are much apprieciated
find_element_by_class_name recives one class as parameter
browser.find_element_by_class_name('yes-button')
The parameter you provided is combination of all the webelement classes, and is used by css_selector
browser.find_element_by_css_selector('.nsg-button.nsg-grad--nike-orange.yes-button.cookie-settings-button.js-yes-button')
Note that you need to add . before the first class as well, otherwise it is treated as tag name. For example in this case
browser.find_element_by_css_selector('button.nsg-button.nsg-grad--nike-orange.yes-button.cookie-settings-button.js-yes-button')
To make sure the button exists before clicking on it you can use explicit wait
button = WebDriverWait(driver, 10).until(expected_conditions.element_to_be_clickable((By.CLASS_NAME, 'yes-button')))
button.click()
use time.sleep to wait until the popup will load, and after that you can use cookie-settings-button-container class that is parrent of the btn this will work.
time.sleep(1)
button = browser.find_element_by_class_name("cookie-settings-button-container")
button.click()

How are we going to hit next url using python and selenium IDE

I am trying to hit next url using python and selenium IDE.
It is showing only first link then error for next URL.I do not know what I am missing here. Can anyone help me out?
Here is my code
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
#base Url
baseurl="http://www.happytrips.com/"
driver = webdriver.Firefox()
driver.get(baseurl)
driver.implicitly_wait(2)
link_name=driver.find_elements_by_xpath(".//*[#id='container']/div[3]/div/nav/div/ul/li/a")
for tab1 in link_name:
driver.implicitly_wait(3)
tab1_destination=tab1.get_attribute('href')
print tab1_destination
driver.get(tab1_destination)
Output
http://timesofindia.indiatimes.com/
Traceback (most recent call last):
File "happytest1.py", line 13, in <module>
tab1_destination=tab1.get_attribute('href')
File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webelement.py", line 97, in get_attribute
resp = self._execute(Command.GET_ELEMENT_ATTRIBUTE, {'name': name})
File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webelement.py", line 402, in _execute
return self._parent.execute(command, params)
File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py", line 175, in execute
self.error_handler.check_response(response)
File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/errorhandler.py", line 166, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.StaleElementReferenceException: Message: Element not found in the cache - perhaps the page has changed since it was looked up
Stacktrace:
at fxdriver.cache.getElementAt (resource://fxdriver/modules/web-element-cache.js:8953)
at Utils.getElementAt (file:///tmp/tmpH_Pmgs/extensions/fxdriver#googlecode.com/components/command-processor.js:8546)
at WebElement.getElementAttribute (file:///tmp/tmpH_Pmgs/extensions/fxdriver#googlecode.com/components/command-processor.js:11746)
at DelayedCommand.prototype.executeInternal_/h (file:///tmp/tmpH_Pmgs/extensions/fxdriver#googlecode.com/components/command-processor.js:12274)
at fxdriver.Timer.prototype.setTimeout/<.notify (file:///tmp/tmpH_Pmgs/extensions/fxdriver#googlecode.com/components/command-processor.js:603)
When you do a get of another page, all existing elements become invalid. You need to get all of the URLs before switching to a new page.
So, add another loop. The first loop iterates over the elements to save each URL, and the second loop iterates over the list of URLs rather than over the list of elements.

Categories