Clicking a button by class name using selenium with python - python

Probably a silly question, but I have spent a ridiculous amount of time trying to figure this out. I am building a scrapper bot using selenium in python, and I am just trying to click a button on a web page. The web page opens and resizes...
def initalize_browser():
driver.get("**website name**")
driver.maximize_window()
but I cannot get it to click a specific button. This is the buttons HTML code:
<button class="mx-auto green-btn btnHref" onclick="window.location ='/medical'" onkeypress="window.location='/medical'">
Medical and Hospital Costs
</button>
And this is my code:
click_button=driver.find_element(by=By.CLASS_NAME, value="mx-auto green-btn btnHref")
click_button.click()
This is the error I get for this code:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":".mx-auto green-btn btnHref"}
I have tried out so many variations of this, including:
driver.find_element_by_xpath('//button[#class="mx-auto green-btn btnHref"]').click()
Where I get this error:
AttributeError: 'WebDriver' object has no attribute 'find_element_by_xpath'
I have also checked to see if there are perhaps any other attributes with the same class name, but there is not. Any help would be super appreciated, thank you!

The method find_element_by_xpath is deprecated now. Use this line:
driver.find_element(By.XPATH, '//button[#class="mx-auto green-btn btnHref"]').click()
instead of:
driver.find_element_by_xpath('//button[#class="mx-auto green-btn btnHref"]').click()
And be sure you have this in imports:
from selenium.webdriver.common.by import By
The locator click_button=driver.find_element(by=By.CLASS_NAME, value="mx-auto green-btn btnHref") doesn't work because By.CLASS_NAME needs only one class name to find an element, but you gave it 3 class names. The html attribute class consists of a list of elements divided by space. So, in this html code
<button class="mx-auto green-btn btnHref" onclick="window.location ='/medical'" onkeypress="window.location='/medical'">
Medical and Hospital Costs
</button>
the attribute class has 3 class names mx-auto, green-btn and btnHref
You can't use all the 3 classes with By.CLASS_NAME but you can use all of them using the By.XPATH

Related

Selenium: element not interactable

I have developed an application using Angular, Node.js/Express.js and MySQL. The application has a login page that is displayed when any user visits the link. After logging in, the user is taken to the home page with a lot of other pages that are displayed in the navbar. I am trying to perform an automation test on the application and I am getting this error when I try to make my automated test click on one of the links in the navbar.
TypeError: 'WebElement' object is not subscriptable
After trying different things the error still does not get resolved. I ended up getting an error of Message: element not interactable
I have found the element using the console in Chrome and it is also clickable when I perform the click action in the console $x("//a")[1].click() or $$("[class = 'navbar-nav ml-auto'] li a")[1].click() but when I run the script in selenium then it throws the error. Can anybody tell me how can I make the navbar item clickable in selenium?
Here's my code:
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('http://name-of-the-local-server:3000')
browser.implicitly_wait(3);
email_element = browser.find_element_by_css_selector("input[name = 'usermail']")
password_element = browser.find_element_by_css_selector("input[name = 'passcode']")
submit_btn_element = browser.find_element_by_css_selector("button[name = 'loginButton']")
email_element.send_keys("someone#example.com")
password_element.send_keys("pass123")
submit_btn_element.click()
#executes perfectly until here
navbar_element = browser.find_elements_by_css_selector("[class = 'navbar-nav ml-auto'] li a")
navbar_element[1].click()
EDIT: I have added a bit of HTML that I want to click as by default it loads the home page
<a _ngcontent-imt-c24="" routerlinkactive="active" routerlink="/admin"
class="nav-link" href="/admin"><i _ngcontent-imt-c24="" class="bi bi-people"
style="font-size: 1.3rem;"></i> Admin</a>
<i _ngcontent-sun-c24="" class="bi bi-people" style="font-size: 1.3rem;"></i>
Any help would be appreciated. Thanks!
Instead of this :
navbar_element = browser.find_element_by_xpath("//a")
use this
navbar_element = browser.find_elements_by_xpath("//a")
find_element will return a single web element where as find_elements will return list of web elements
You are using navbar_element[0].click() if stored in list, it will click on first web element.
or iterate over a list like this :
for link in navbar_element:
ActionChains(driver).move_to_element(link).click().perform()

NoSuchElementException when using Selenium Python [duplicate]

This question already has an answer here:
Selenium "selenium.common.exceptions.NoSuchElementException" when using Chrome
(1 answer)
Closed 2 years ago.
I'm trying to scrape the promotion information of each product from a website by clicking on the product and go to its detailed page. When the spider clicks on the product, the web will ask it to log in, and I tried the following code:
def __init__(self):
self.driver = webdriver.Chrome(executable_path = '/usr/bin/chromedriver')
...
def start_scraping(self, response):
self.driver.get(response.url)
self.driver.find_element_by_id('fm-login-id').send_keys('iamgooglepenn')
self.driver.find_element_by_id('fm-login-password').send_keys('HelloWorld1_')
self.driver.find_element_by_class_name('fm-button fm-submit password-login').click()
...
However, there is NoSuchElementException when I run it.
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="fm-login-id"]"}
'spider_exceptions/NoSuchElementException': 14,
The HTML of the login page is as follows:
<div class='input-plain-wrap input-wrap-loginid'>
<input id='fm-login-id' class='fm-text' name='fm-login-id'...>
event
</div>
So, I'm pretty sure the id should be 'fm-login-id'. The reason I could think of that might cause this issue is that this login page is a popup.
Basically, it pops up in the middle of the main page. Looking at the HTML of the site, I can see that the login type seems to be a new HTML window
<!DOCTYPE html>
<html>event
....
<\html>
I'm not sure if this is the issue, and if so, how to fix it? Also, is there other reasons that might've caused the issue?
The popup will have an ID. You might have to add f'#{popup_id}' to the end of response.url. Like this URL: https://stackoverflow.com/questions/62906380/nosuchelementexception-when-using-selenium-python/62906409#62906409. It contains #62906409 because 62906409 is the ID of an element in the page.
The login page inside a frame, you need switch it first:
#switch it first
self.driver.switch_to.frame(driver.find_element_by_id('J_loginIframe'))
self.driver.find_element_by_id('fm-login-id').send_keys('iamgooglepenn')
self.driver.find_element_by_id('fm-login-password').send_keys('HelloWorld1_')
And for login button you can't use .find_element_by_class_name, this method just for single class name. This element having multiple class name, so use .find_element_by_css_selector like bellow:
#submit button
self.driver.find_element_by_css_selector('.fm-button.fm-submit.password-login').click()
The login content seems to be nested in an iFrame element (if you trace it all the way to the top, you should find an iFrame with id="sufei-dialog-content"), which means you need to switch to that iFrame for that nested html before selecting your desired element, otherwise it will not work.
First you will need to use driver.switch_to.frame("sufei-dialog-content"), and then select your element with driver.find_element_by_name() or whatever you had.
A similar issue can be found here: Selenium and iframe in html
Just a simple mistake:
<div class='input-plain-wrap input-wrap-loginid'>
<input id='fm-login-id class='fm-text' name='fm-login-id'...>
event
</div>
is actually supposed to be:
<div class='input-plain-wrap input-wrap-loginid'>
<input id='fm-login-id' class='fm-text' name='fm-login-id'...>
event
</div>
You forgot a single-quote.
Have you tried driver.find_element_by_name('fm-login-id')?
You should try finding the elements by their XPaths. You just have to inspect the element, right-click on it and copy its XPath. The XPath of the first <input ... is //*[#id="fm-login-id"].

WebDriver switchTo().alert() function fails

Have this line in my html:
<a class="btn" onclick="return confirm('Are you sure you want to delete this post?')" href="#">
Try to switch to the pop-up window and click OK by using
driver.switchTo().alert().accept()
but it keeps giving me AttributeError: 'WebDriver' object has no attribute 'switchTo'. I also try to locate the element ID of the buttons of the pop-up window but I could not make it work. Any suggestions will be appreciated.
In Python you should use
driver.switch_to.alert.accept()
as switchTo() is Java method
I am little late to answer, It is java syntax dear and you use python,
use this code:
alert = driver.switch_to.alert()
alert.accept()

Python selenium unable to find element neither by class name nor xpath

I'm newbie in Selenium. I start to learn Selenium via book. And I struggle with unclear behavior of Selenium. For educational purposes I use this site:
http://magento-demo.lexiconn.com/ - I'm trying to find search button by its class name, (which is: class='button search button') or by it xpath
search_button = self.driver.find_element_by_xpath('/html/body/div/div[2]/header/div/div[4]/form/div[1]/button')
or
search_button = self.driver.find_element_by_class_name('button')
but each time selenium unable to find it. Please help me to understand reason of such behavior. Thank you
I used Selenium IDE and it shows me XPATH: //button[#type='submit']
when I tried to find element by xpath,I have got the same error and it is strange. Please advise.
My code is:
import unittest
from selenium import webdriver
class HomePageTest(unittest.TestCase):
#classmethod
def setUpClass(cls):
#create new Firefox session
cls.driver = webdriver.Firefox()
cls.driver.implicitly_wait(30)
cls.driver.maximize_window()
#navvigate to application home page
cls.driver.get('http://magento-demo.lexiconn.com/')
def test_search__text_field_max_length(self):
#get the search text box
search_field=self.driver.find_element_by_id("search")
#check maxlenght attribute st to 128
self.assertEqual("128",search_field.get_attribute("maxlength"))
def test_search_button_enabled(self):
# get Search button
search_button = self.driver.find_element_by_class_name('button')
# check Search button is enabled
self.assertTrue(search_button.is_enabled())
#classmethod
def tearDown(self):
#close the browser window
self.driver.quit()
if __name__=='__main__':
unittest.main(verbosity=2)
Try this :
search_button = self.driver.find_element_by_xpath('//button[#class="button search-button"]')
Try downloading the selenium IDE plugin, install and start recording. Click on the button you want and view how its target is recorded in the IDE. Programmatically, selenium will accept the same xpaths and other selectors as the IDE. After it's been recorded in the IDE, there is a pull down on the target field that lets you see all the different ways you can select that element, ie xpath vs. by class etc.
http://www.seleniumhq.org/projects/ide/
you might try:
css=button.button.search-button
//button[#type='submit']
//form[#id='search_mini_form']/div/button
I think the issue is that your locator isn't specific enough. There is more than one button on the page and more than one element with class=button on the page. This CSS selector is working for me.
self.driver.find_element_by_css_selector("button[title='Search']")
Try this way using xpath locator
Explanation: Use title attribute of <button> tag.
self.driver.find_element_by_xpath("//button[#title='Search']")
OR
Explanation: Use title and type attribute of <button> tag.
self.driver.find_element_by_xpath("//button[#title='Search'][#type='submit']")

accessing form tag with selenium web driver

I am trying to locate a tag on a page, but so far finding it by name/id/xpath have not worked. This is what I've tried to locate it by xpath:
db = driver.find_element_by_xpath("/html/body/form")
and also
driver.find_element_by_xpath("//form[#id='formControl']")
Both of these return the error:
selenium.common.exceptions.NoSuchElementException: Message: u'Unable to locate element:
It's as if it can not find the form on the page. Any ideas of how to fix?
Here's the beginning of the html on the page:
<html>
<body id="bodyControl" class="PersonalizationPage ContentPage Layout_PageUsesRegions" onunload="closeTimeoutWarningPopupWindow();return true;" onload="return __MasterOnLoad();" onresize="return __MasterOnResize();">
<form name="formControl" method="post" action="default.wl?appflag=65.14&bhcp=1&MT=208&rs=LAWS2.0&strRecreate=no&sv=Split&transfertoken=10281204301250d0dbca913e4aa6887c7d425f4ede9c&vr=2.0" id="formControl" target="_top">
Try this.
driver.find_element_by_id("formControl")
And two things:
Make sure that the form isn't inside of a frame on the page. If it is, you will have to switch to the frame (it is functionally a different webpage displayed in a box.)
Make sure that you've got the right browser window selected, if you're manipulating multiple windows, you're going to have to switch to the one you want to search through.

Categories