I am writing a python script to input text, that then has a dropdown appear to select from a list of items. These items are all hidden values and are not inputted to the webpage until selected by clicking on said item.
Specifically I am attempting to input data on Fitbits website to track food (a thing for work, but it is tedious to input food consumption each day). I would like to automate this :)
My script currently looks like this...
#! python3
# fitbitSubmitFood.py this script submits the food log on fitbit.com
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
browser = webdriver.Chrome()
# open webpage to log food
browser.get('https://www.fitbit.com/foods/log')
# login to the website
# email username input
emailSelect = browser.find_element_by_xpath('//*[#id="loginForm"]/fieldset/dl/dd[1]/input')
emailSelect.send_keys('EMAIL')
# email password input
inputPassword = browser.find_element_by_xpath('//*[#id="loginForm"]/fieldset/dl/dd[2]/input')
inputPassword.send_keys('PASSWORD')
# click log in
clickLogin = browser.find_element_by_xpath('//*[#id="loginForm"]/div[1]/button')
clickLogin.click() # clicky click!
# input What did you eat?
foodSelect = browser.find_element_by_xpath('//*[#id="foodselectinput"]')
foodSelect.send_keys('Pizza, Bread') # select by visible text
# input How Much?
howMuch = browser.find_element_by_xpath('//*[#id="quantityselectinput"]')
howMuch.send_keys('3')
# click Log Food
logfood = browser.find_element_by_xpath('//*[#id="foodAutoCompButton"]')
# logfood.click() # clicky click!
# Close web browser
The current script above throws the following error.
selenium.common.exceptions.InvalidElementStateException: Message: invalid element state
So I have also tried suggestions from this stackoverflow question.
Entering a value into a type="hidden" field using Selenium + Python
WebDriverWait(foodSelect, 10).until(EC.visibility_of_element_located((By.XPATH,'//*[#id="foodId"]'))) # wait for hidden text to populate
This threw the following error...
selenium.common.exceptions.TimeoutException: Message:
Here is a snippet from the website
input type="text" name="foodselectinput" id="foodselectinput" class="text columnFull yui-ac-input" maxlength="80" tabindex="1" autocomplete="off"
I can see the following on the website for the hidden value. This value is not passed to the webpage until after the food is selected from the drop down menu.
input name="foodId" id="foodId" type="hidden" value="13272"
Note: I have already tried using the click method for the Pizza, Bread
clickFood = browser.find_element_by_xpath('//*[#id="foodselectcontainer"]/div/div[2]/ul/li[1]/div/div[1]')
clickFood.click() # click it!
This did not work.
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*[#id="foodselectcontainer"]/div/div[2]/ul/li[1]/div/div[1]"}
The script cannot continue until the food item is selected on the webpage. Hence, the question.
How would one pass the hidden value or select from a dropdown?
From your snippet
input type="text" name="foodselectinput" id="foodselectinput" class="text columnFull yui-ac-input" maxlength="80" tabindex="1" autocomplete="off"
yui-ac-input refers AutoComplete from YUI 2 Library (That's what I thought)
As the site mentioned by you asked credentials. I created a sample code for YUI Example
Sorry I dont know python.Below is a Java code. The syntax looks more or less same. So get the idea from below code and implement it
public void start() {
driver.get("http://yui.github.io/yui2/docs/yui_2.9.0_full/examples/autocomplete/ac_basic_array.html");
yuiAutoSuggestSelect("Cali");
}
public void yuiAutoSuggestSelect(String value) {
WebElement inputElement = driver.findElement(By.className("yui-ac-input"));
inputElement.sendKeys(value);
By autoSuggSel = By.xpath("//div[#class='yui-ac-container']//div[#class='yui-ac-bd']//li");
WebElement autoSuggestEl = driver.findElement(autoSuggSel);
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOf(autoSuggestEl)).click();
}
Related
I am trying to input code on a pin pad form available on a website and get it validated. However, I am getting a validation error. I fear the clicked pin buttons are not being read by the website's script. Can anyone help me with this? I am attaching the code as well as the page source code.
The UI of website looks like this
The div class on website which contains the keypad is as follows:-
<div class="pin_pad">
<span id='keypad1' onmouseout="this.className=''" onmouseover="this.className='pin_hover'">1</span>
<span id='keypad2' onmouseout="this.className=''" onmouseover="this.className='pin_hover'">2</span>
<span id='keypad3' onmouseout="this.className=''" onmouseover="this.className='pin_hover'">3</span>
<span id='keypad4' onmouseout="this.className=''" onmouseover="this.className='pin_hover'">4</span>
<span class="submit_btn" onmouseout="this.className='submit_btn'" onmouseover="this.className='submit_btnpin_hover'" onclick="return validate();">Submit</span>
</div>
My pin is "4444". I am trying to use the .click() method to get "4" clicked. Although I can see that "4" has been clicked 4 times, upon submit, the page shows a validation error. Can anyone help me in solving this problem? Here's my code in python:-
pinpad = driver.find_elements_by_class_name('pin_pad')
element = driver.find_element_by_xpath("//span[text()=4]").click()
for k in range(4):
actionChains = ActionChains(driver)
actionChains.context_click(element).perform()
time.sleep(1)
driver.find_element_by_xpath("//span[text()='Submit']").submit()
Instead of
context_click(element).perform()
do this :
move_to_element(key4).click().perform()
context_click is for right click and move_to_element() is for moving your mouse cursor to the specify element.
Brief explanation :
You can introduce WebDriverWait for more stability, and I don't think you need to do context_click() instead it is move_to_element() plus ActionChains object creation optimization and instead of submit you may wanna use click(). Check out the code below :
pinpad = driver.find_elements_by_class_name('pin_pad')
key4 = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "span#keypad4"))).click()
actionChains = ActionChains(driver)
for k in range(4):
actionChains.move_to_element(key4).click().perform()
sleep(1)
wait.until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Submit']"))).click()
Hi guys I am still learning selenium and basics of coding so sorry for noob question :)
I have a list of links in the CSV
I want to open each link, do some action and go to another link from CSV list, but if the website doesnt have that button I want just to move to another link from the csv
For now when the page has those elements i can loop trough, but sometimes this page doesnt have this elements and wants to redirect me to external site.
I have value like this on the page:
<p class="uk-text-large uk-text-center uk-alert">You are leaving this site</p>
'
<input type="submit" name="submit" onclick="ga('send', 'event', 'external', 'click',
'logedin');" id="submit" value="redirect" class="uk-button uk-button-primary uk-button-large">
I would like if selenium finds on the page text "You are leaving this site" or value "redirect" on the page just to move to another link from the list.
This is the first part that works when all pages have button and dont want to redirect me to the external site
One extra moment as well would be if i could add a note was the link skipped or not the CSV as new column
'
from selenium import webdriver
import time
import pandas as pd
import config
from webdriver_manager.chrome import ChromeDriverManager
df = pd.read_csv("listofurls.csv")
df = pd.read_csv('listofurls.csv')
urls = df['link']
for url in urls:
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get('https://www.website.com/login?redirect=%2F')
driver.maximize_window()
usernamebox = driver.find_element_by_id("Email_login")
usernamebox.send_keys(config.email)
passbox = driver.find_element_by_id("Password_login")
passbox.send_keys(config.password)
loginbutton = driver.find_element_by_xpath('//*[#id="Password_login"]')
loginbutton.submit()
time.sleep(3)
#data = {}
driver.get(url)
cookies = driver.find_element_by_xpath('//*[#id="__allow_ct_container"]/div/div/a')
cookies.click()
cv = driver.find_element_by_css_selector("input[type='radio'][value='293608']")
cv.click()
submit = driver.find_element_by_xpath('//*[#id="__submit"]')
submit.click()
#driver.close()
print('done')
An element having id __submit and containing foo text can be found using the following XPATH:
driver.find_element_by_xpath("//*[#id='__submit' and contains(text(), 'foo')]")
Have a look at this XPATH cheatsheet.
I am trying to collect email addresses from a form on a website that has readonly inside of it.
<input name="email" id="email" type="text" class="form-control" value="example#gmail.com" readonly="">
I want to be able to get the email address (example#gmail.com) but everything I try returns "unable to locate element".
Everything is configured properly as the rest of the script is working fine, which I have left out.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup
import re
import pandas as pd
import os
x = 0
all_volunteers = driver.find_elements_by_xpath('//*[#title="View volunteer record"]')
for volunteer in all_volunteers:
volunteer.click()
driver.implicitly_wait(3)
# email_add = driver.find_element_by_id('emaillabel')
#email_add = driver.switch_to_frame(driver.find_element_by_name('email'))
#print(email_add.get_attribute('email'))
#email_add = driver.find_element_by_css_selector('input id')
#email_add = driver.find_element_by_xpath('//input [#name="email"]')
#email_add = driver.find_element_by_tag_name('Email Address')
email_add = driver.find_element_by_xpath('//*[#id="email"]')
print(email_add.get_attribute('value'))
# back button
driver.execute_script("window.history.go(-1)")
#increase counter by 1
x += 1
Everything commented out (followed by #) is what I have tried.
Is any one able to tell me what I am doing wrong or missing?
I have a debugging solution to locate the element.
In the browser, open the web page containing the email input
Open developer tools (F12)
Open console tab in the developer tools
Type $x('//input[#id="email"]') and see if the element is located. This is the native xpath locator
You can also try document.getElementById('email') in the console
If the element is not found still, try the iFrame selector marked in the screenshot to identify iframes and switch to it.
If more than one element is returned, it means that you might have to modify the selector to find unique element.
I'm trying to figure out a way to automatically log in / enter text into a given text field on a particular web page. I've already don't this before, but this particular page isn't responding to anything I've thrown at it yet.
The default page load already has the auto-focus on the necessary text box. I'm currently using Python to write the Selenium code. My current script includes prior processes that lead to the page in question, where my current problem lies. Additionally, I've been running this code in a Google-Chrome browser, but with the user-agent selected to Edge - Mobile (but that probably won't matter here).
The website in question is the Microsoft login at this link.
The CSS/HTML of the text box in question:
<input type="email" name="loginfmt" id="i0116" maxlength="113" lang="en" class="form-control ltr_override" aria-describedby="usernameError loginHeader loginDescription" aria-required="true" data-bind="textInput: usernameTextbox.value,
hasFocusEx: usernameTextbox.focused,
placeholder: $placeholderText,
ariaLabel: tenantBranding.UserIdLabel || str['CT_PWD_STR_Username_AriaLabel'],
css: { 'has-error': usernameTextbox.error },
attr: inputAttributes" placeholder="Email, phone, or Skype" aria-label="Enter your email, phone, or Skype.">
The code I'm currently testing (which is basically three varied iterations of the same idea), after the given page loads:
element = driver.find_element_by_id("i0116")
element.click()
element.clear()
element.send_keys("wbhyatt3#gmail.com")
element.send_keys(Keys.RETURN)
time.sleep(1)
element = driver.find_element_by_name("loginfmt")
element.click()
element.clear()
element.send_keys("wbhyatt3#gmail.com")
element.send_keys(Keys.RETURN)
time.sleep(1)
element = driver.find_element_by_css_selector("input.email")
element.click()
element.clear()
element.send_keys("wbhyatt3#gmail.com")
element.send_keys(Keys.RETURN)
Unfortunately, trying to select the textbox via the input id, class, or name don't seem to be working. It should be worth noting that the page CSS I'm referencing for the text box includes an element "input" prior - I'm not sure if this will affect my current code. I'm fairly certain that either the send_keys aren't working, or perhaps the selection of the element, itself.
What makes the situation even more frustrating is that the page's default focus is on the textbox - so I don't even truly need to select the element, I just need to be able to enter text and submit/enter.
I've also tried targeting it as an iframe, but that hasn't seemed to help either.
Any ideas? Any and all help would be deeply appreciated. I am simply trying to find a way to enter text into the login box.
To enter an EmailID into the field with placeholder text as Email, phone, or Skype you can use the following code block :
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("start-maximized")
options.add_argument("disable-infobars")
options.add_argument("--disable-extensions")
driver = webdriver.Chrome(chrome_options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
driver.get('https://login.live.com/login.srf')
print("Page Title is : %s" %driver.title)
element = driver.find_element_by_xpath("//input[#class='form-control ltr_override' and #name='loginfmt']")
element.click()
element.clear()
element.send_keys("wbhyatt3#gmail.com")
Console Output :
Page Title is : Sign in to your Microsoft account
Snapshot :
I'm trying to connect to a school url and automate the process with selenium. Originally I tried using splinter, but ran into similar problems. I can't seem to be able to interact with the username and password fields. I realized a little ways in that it is an iframe that I need to interact with. Currently I have:
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox()
driver.get("https://my.oregonstate.edu/webapps/login/")
driver.switch_to.frame('Content') #I tried contentFrame and content as well
loginid = driver.find_elements_by_id('user_id')
loginid.send_keys("***")
passwd = driver.find_elements_by_id('password')
passwd.send_keys("***")
sub = driver.find_elements_by_id('login')
sub.click()
time.sleep(5)
driver.close()
Here is the HTML that I am trying to interact with:
The Website: https://my.oregonstate.edu/webapps/portal/frameset.jsp
The iframe:
<iframe id="contentFrame" style="height: 593px;" name="content" title="Content" src="/webapps/portal/execute/tabs/tabAction?tab_tab_group_id=_1_1" frameborder="0"></iframe>
The forms:
Username:
<input name="user_id" id="user_id" size="25" maxlength="50" type="text">
Password:
<input size="25" name="password" id="password" autocomplete="off" type="password">
It seems that selenium can locate the elements just find, but I am unable to input any information into these fields, I got the error 'List object has no attribute'. When I realized it was the iframe I tried to navigate into that but it says 'Unable to locate frame: Content'. Is there another iframe that I am missing? Or something obvious? This is my first time here so sorry if I messed something up with the code linking.
Thanks for the help.
driver.switch_to.frame() takes frame's id or name, where your frame have id = contentFrame and name = content. (The reason they didn't work is probably because of a different issue, read through please)
First, please try use either one of them, not Content (which has upper case C).
Once you have fixed the issue above, there will be another error in your code.
loginid = driver.find_elements_by_id('user_id')
loginid.send_keys("***")
driver.find_elements_by_id finds all matching elements, which is a list. So you can't use send_keys. Please use driver.find_element_by_id('user_id').
Here is the code I tested working.
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("https://my.oregonstate.edu/webapps/login/")
driver.switch_to.frame('content') # all lower case to match your actual frame name
loginid = driver.find_element_by_id('user_id')
loginid.send_keys("***")
passwd = driver.find_element_by_id('password')
passwd.send_keys("***")
Regarding issue in your following comments
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("https://my.oregonstate.edu/webapps/login/?action=relogin")
loginid = driver.find_element_by_id('user_id')
loginid.send_keys("***")
passwd = driver.find_element_by_id('password')
passwd.send_keys("***")
driver.find_element_by_css_selector('.submit.button-1').click()