I know I am doing something wrong. I need to create software to test a website. send_keys is working just fine for the rest of my code but I am not sure what I am doing wrong in this section. I have tried everything I can think of. I am very new to python and selenium so it's probably something silly.
Things I have tried:
1.
elem = lambda: driver.find_element_by_xpath('//textarea[#aria-label="Comment"]').click()
elem().click()
elem.send_keys("this is a comment")
elem.send_keys(Keys.RETURN)
2.
elem = lambda: driver.find_element_by_xpath('//span[#aria-label="Comment"]').click()
elem().click()
elem.send_keys("this is a comment")
elem.send_keys(Keys.RETURN)
3.
com_elem = driver.find_element_by_xpath('//textarea[#aria-label="Add a comment…"]')
com_elem.clear()
com_elem.send_keys("comment")
I have tried every combination I can think of and I know it needs to match the HTML but I have still tried it with lambda and without, with span and textarea (since it has a button you press that places your cursor in the text box)
I do not know what else to try.
All it needs to do is click the text box, add words and hit enter.
this is HTML for the text box it needs to go inside of:
<form class="X7cDz" method="POST">
<textarea aria-label="Add a comment…" placeholder="Add a comment…" class="Ypffh" autocomplete="off" autocorrect="off" style="height: 18px;"></textarea>
<button class="sqdOP yWX7d y3zKF " type="submit">
Post
</button>
</form>
This is HTML for the button that it can click and the cursor will go in the box:
<span class="_15y0l">
<button class="dCJp8 afkep">
<span aria-label="Comment" class="glyphsSpriteComment__outline__24__grey_9 u-__7">
</span>
</button>
</span>
This part of the website works perfectly. I know because I have tested it by hand.
The desired element is a JavaScript enabled element so to invoke send_keys() on the element you have to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
elem = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "textarea[aria-label^='Add a comment'][placeholder^='Add a comment']")))
elem.send_keys("Daniela Ciro")
elem.send_keys(Keys.RETURN)
Using XPATH:
elem = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//textarea[starts-with(#aria-label, 'Add a comment') and starts-with(#placeholder, 'Add a comment')]")))
elem.send_keys("Daniela Ciro")
elem.send_keys(Keys.RETURN)
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
I don't think you need to use lambda to complete this task. You're on the right track, you need to first identify the path of the textbox and set it to a variable so your send_keys() will know where to input the text. You then need to find the enter button's path and click it. Something along the lines of this should help:
elem = driver.find_element_by_xpath('textbox xpath here')
elem.send_keys('what you want to put into textbox')
driver.find_element_by_xpath('your enter button xpath here').click()
If you could provide the website or an example, it would be possible for me to give more specific code.
Related
I try to log in to this web page with my credentials.
https://www.oddsportal.com/login
I am able to get the "username" and "password" input boxes but I am not able to send the data.
Selenium locates the elements (via "id" or otherwise), but gives problems when trying to send values or pressing enter:
"AttributeError: 'NoneType' object has no attribute 'click'"
"AttributeError: 'NoneType' object has no attribute 'send_keys'"
I've tried find, xpath, actionchain and execute_script, too.
Any clue how to click and send keys?
TVM.
I add some code tried:
us = driver.find_element_by_xpath('//input[#type="hidden"]')
print(us)
output:
<selenium.webdriver.remote.webelement.WebElement (session="84a2b7c7a5e9eda5e562d7a8f17ab749", element="1201c113-012c-4918-84cf-8011b696a5ff")>
I tried too:
us = driver.find_element(By.ID, "login-username-sign")
print(us)
output:
<selenium.webdriver.remote.webelement.WebElement (session="b8e6d51511c6cad8d24cf7946c46865f", element="004a920b-752d-4280-8dd1-5c8f330efa74")>
I tried:
us = driver.find_element(By.ID, "login-username-sign")
us.send_keys("1234")
output:
ElementNotInteractableException: Message: element not interactable
(Session info: chrome=109.0.5414.74)
Etc.
"Info about human login": To log in manually you have to put the cursor over the text box, click and then type.
This actions fail (click and type) under Selenium (I dont get it clicks but I think Selinium does get the object).
HTML:
<form action="https://www.oddsportal.com/userLogin" method="post" class="flex flex-col flex-1 mt-[10px]">
<input type="hidden" name="_token" value="PhbLpoaq9vnNILGD4H6YYO7kFAoq2CUnT606hOHO">
<input type="hidden" name="referer">
<div class="item">
<div class="title">
<label for="login-username-sign" class="mb-2 text-xs text-black-main">Username</label>
<span class="required" title="required item">*</span>
</div>
<div>
<input class="int-text w-[300px] min-sm:w-[340px] pl-4 h-10 mb-[14px] border border-solid border-box border-black-main border-opacity-20 hover:input-hover" type="text" id="login-username-sign" name="login-username" size="25" required="">
</div>
</div>
<div class="item">
<div class="title">
<label for="login-password-sign" class="mb-2 text-xs text-black-main">Password</label>
<span class="required" title="required item">*</span>
</div>
<div class="flex h-10 bg-white-main">
<input class="int-text w-[300px] min-sm:w-[340px] pl-4 h-10 mb-[14px] border-solid border border-black-main border-opacity-20 hover:input-hover" type="password" id="login-password-sign" name="login-password" autocomplete="on" size="25" required="">
<div class="grid absolute left-[90%] items-center justify-center h-10 w-8"><div onclick="switchVisibility(this, 'login-password-sign')" class="w-6 h-5 bg-center bg-no-repeat bg-cover cursor-pointer passlog bg-eye_icon !bg-off_eye_icon">
</div>
</div>
</div>
You were close enough. However the locator strategy you were trying to use, i.e.
us = driver.find_element(By.ID, "login-username-sign")
identifies two (2) elements within the HTML DOM. Among them first one is hidden where as the second matching element is your desired element.
Solution
To cut sort the task of identifying the Username & Password field you can click on the LOGIN element in the top right corner of the page which opens the Username & Password fields within a Modal Dialog Box and you can identify the desired elements using the following locator strategies:
Code Block:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
driver.get('https://www.oddsportal.com/login')
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button#onetrust-accept-btn-handler"))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[#class='flex gap-3']//div[contains(#class, 'loginModalBtn') and starts-with(., 'Login')]"))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div#loginDiv form[action='https://www.oddsportal.com/userLogin'] input#login-username-sign"))).send_keys("daniel2014")
driver.find_element(By.CSS_SELECTOR, "div#loginDiv form[action='https://www.oddsportal.com/userLogin'] input#login-password-sign-m").send_keys("daniel2014")
Browser Snapshot:
I can't open that link due to security policy of my working computer, but I can be quite sure that your problem is caused by bad locators.
"AttributeError: 'NoneType' object has no attribute 'click'"
and
"AttributeError: 'NoneType' object has no attribute 'send_keys'"
Means you did not actually get the web element you trying to click / send keys to.
Also sending keys (text) with Selenium to element with 'input type="hidden" ' is also not possible. Selenium imitates human user GUI actions. As a human user you can not insert text to hidden element.
First of all, you have to register the website creating an account
manually by filling blank form using Username, password, email and
country name from the following url
Then go with your desired login url
and run the selenium code and see the real scenerio from the selenium
automated browser. Now you willnotice that the login url will ask to
fillthe form with the username and password only and you have to use
your registered username and password and click on login button. That
okey! Nope. At first, accept cookies, then fill up the login form.
You have to apply JavaScript execution in order to click on Login
button, Otherwise, it will throw ClickIntercept Exception. Because
Login button interacts with other dynamic element.
Script:
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from webdriver_manager.chrome import ChromeDriverManager
import time
options = webdriver.ChromeOptions()
options.add_argument("start-maximized")
options.add_experimental_option("detach", True)
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()),options=options)
URL ='https://www.oddsportal.com/login'
driver.get(URL)
time.sleep(5)
cookie_btn = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, '(//*[#id="onetrust-button-group"]/button)[1]'))).click()
UserName = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, '(//*[#id="login-username-sign"])[2]'))).send_keys('Akij')#Your registered account's username
PassWord = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#login-password-sign'))).send_keys('789456rtU') #Your registered account's password
LogIn = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, '(//*[#name="login-submit"])[2]')))
#You have to apply JavaSript execution in order to click on Login button, Otherwise it will throw ClickIntercept Exception
#Because Login button interacts with other dynamic element.
LogIn_click = driver.execute_script("arguments[0].click();", LogIn)
time.sleep(1)
See the below output:
Output-01
Output-02
There are 2 login forms on that page. Your Selenium code is failing because it locates the first one, which is hidden unless you press login in top right corner of the page:
If you press F12 in chrome devtools and try to search for element like this:
document.querySelectorAll("div.pt-5 form #login-username-sign") it will find both login fields. This is a 'css' selector which you can use in your python code.
Since it looks 'top to bottom' the easiest would be to do:
document.querySelectorAll("div.pt-5 form #login-username-sign")[1]
Here is a test of how it works, inside devtools:
To sum things up - you should be able to locate it with:
find_elements(By.CSS_SELECTOR, "div.pt-5 form #login-username-sign")[1]
find_elements returns a list of all elements matching that selector (we will get 2). Our login is the second one in DOM, so we pick [1] from the list.
I'm using python and Selenium to scrape some search results in LinkedIn but I'm having trouble finding the people button on the top left in order to filter my results to have only people. I noticed that the ID of the button is dynamic so I tried different ways to find the buttons, all of which have failed. Here is the HTML code of the button:
<div class="peek-carousel js-slideshow">
<ul class="peek-carousel__slides js-list">
<li class="mr2">
<button aria-checked="false" role="radio" aria-label="People" id="ember69" class="artdeco-pill artdeco-pill--slate artdeco-pill--2 artdeco-pill--choice ember-view search-reusables__filter-pill-button" type="button"> People </button>
and here are my three attempts (python code):
1) people_button = driver.find_element_by_css_selector("#people + button")
2) people_button = driver.find_element_by_xpath("//button[#aria-label='People']")
3) people_button = driver.find_element_by_xpath("//button[#aria-label='People'][#type='button']")
I'm having also the same problem for the next button on the bottom right to go to the next page here is the HTML code of the button:
<span class="artdeco-button__text">
Next
</span>
The first locator doesn't work because there is no element with an ID "people" on the page. The second and third work fine for me. I've tested them in the dev tools in Chrome using $$() for CSS selector and $x() for XPath. In this case, $x("//button[#aria-label='People']") returns a single element. My guess is that you need to add a wait.
I would use a CSS selector in this case because they are faster and better supported, e.g. "button[aria-label='People']". But, since you used XPath this should work
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
new WebDriverWait(driver, 10).until(EC.element_to_be_clickable(By.XPath("//button[#aria-label='People']"))).click()
<input class="jss1805" name="confirmWeight" tabindex="0" type="checkbox" data-indeterminate="false" value="">
The code^ is from a html website and its a checkbox which I want to click. Except it's an input rather than a button or td. Am I able to click this as when I run selenium it seems to not find it.
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "/html/body/div[1]/div[2]/main/form/div/div[2]/div[4]/div[2]/div/div/div[2]/div/div[1]/div/div/label/span[1]/span/input"))).click()
This finds the element but doesn't click it.
Try the following:
from selenium.webdriver.support.wait import WebDriverWait
wait = WebDriverWait(driver, 20)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[name=confirmWeight]")))
element = driver.find_element_by_css_selector("input[name=confirmWeight]")
element.click()
Explanation:
First you need to wait till your element is clickable. For this you have to define the locator which is unique.
Find the element and click it
If you want to make an input use:
element.send_keys("`your input")
If you want to click on svg, that is a child use: input[name=confirmWeight]>svg
I don't see it in your html. It looks like the info you provided is not enough.
I am starting with Python - Selenium and I cannot target the element in login website. I tried many options of targeting this button but no options works (class name, css selector, id, name..). When I skip this step and get on the next page manually by exact url the finding, focusing, sending keys to element and clicking on the "Next" button is no problem but this "welcome" login button cannot target totally.
Using function "driver.find_element_by_XXX".
For example:
"driver.find_element_by_class_name("login-box-actions").click()"
Please, where I am making a mistake?
Many thanks,
regards David
<div class="login-box-actions">
<a style="cursor: pointer" ng-click="confirmLogin()" class="btn btn-primary btn-block btn-flat ng-binding">Login</a>
</div>
It may fail because the element could not found.
For that, you have to wait for the element to be load and clickable.
Refer to the following example, wait for the element to be clickable.
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
WebDriverWait(driver, 20).until(EC.element_to_be_clickable(
(By.CSS_SELECTOR, "btn btn-primary btn-block btn-flat ng-binding"))).click()
You can try finding the element by using different identifiers. Selenium supports:
find_element_by_id
find_element_by_name
find_element_by_xpath
find_element_by_link_text
find_element_by_partial_link_text
find_element_by_tag_name
find_element_by_class_name
find_element_by_css_selector
You need to click into the <a> element instead of the div:
login_button = driver.find_element_by_xpath("//a[text()='Login']")
login_button.click()
I have a button, i can successfully find it and capture it's text. However click is not working. Can someone help.
<button class="yellow labeled icon button no-margin" type="button">
<div class="icon my_class"></div>
<span class="ttt">Add new student</span>
</button>
This works:
return driver.find_element(By.XPATH, 'xpath').text
But this does not work and "no exception". Code pass but click not done.
driver.find_element(By.XPATH, 'xpath').click()
You can try clicking it with javascript :
element = driver.find_element(By.XPATH, 'xpath')
driver.execute_script("arguments[0].click();", element)
Of-coarse invoking .text and click() relates to two different states of a WebElement.
Your code block return driver.find_element(By.XPATH, 'xpath').text succeeds as the text Add new student gets rendered within the HTML DOM when you lookout for it. This doesn't guarantees that the WebElement is also interactable by that time. There is a possibility of a JavaScript/Ajax at work rendering the button at that point of time.
It is worth to mention that rendering of the text Add new student resembles to the expected_conditions clause of text_to_be_present_in_element where as interactability (i.e. clickability) resembles to the expected_conditions clause of element_to_be_clickable
Solution
As you mentioned it's an AngularJS based site/element and the click is not getting executed you have to induce WebDriverWait in-conjunction with expected_conditions clause set as element_to_be_clickable as follows :
WebDriverWait(self.driver, 30).until(EC.element_to_be_clickable((By.XPATH, "xpath"))).click()