cannot locate a web element - python

I just want to write a simple log in script for Apple website:
Sign In
The ID and password form cannot be located properly.
Actually, I tried a lot of thing like:
driver.find_element_by_xpath("//*[#type='email']")
or
driver.find_element_by_xpath("//*[#name='login-appleId']")
and
driver.find_element_by_xpath("//*[#id='login-appleId']")
I did not find any iframe in this page. And I tried same thing for customer checkout button, also same problem happens.
Any suggestions would be appreciate!
Best,
Luke

You can Follow this code .. It works ..!!
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
driver = webdriver.Chrome('E:\chromedriver.exe') #location
driver.get('url') #https://secure2.store.apple.com/shop/sign_in?c=aHR0cDovL3d3dy5hcHBsZS5jb20vc2hvcC9iYWd8MWFvczVjNGU3ZWNjZjgwODVjNWY4NDk0OTA0ODJhMDc2Y2FkNmU3ODJkOTE&o=O01LV0gy&r=SXYD4UDAPXU7P7KXF&s=aHR0cHM6Ly9zZWN1cmUyLnN0b3JlLmFwcGxlLmNvbS9zaG9wL2NoZWNrb3V0L3N0YXJ0P3BsdG49RkNBRjZGQjR8MWFvczAyZmZkZjQwNTgwOGI4ZTNkMDQ5MWRiM2NmZmExYTgxNzRkZTllMjY&t=SXYD4UDAPXU7P7KXF&up=t
def find_by_xpath(locator):
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, locator))
)
return element
class FormPage(object):
def fill_form(self, data):
find_by_xpath('//input[#name = "login-appleId"]').send_keys(data['usr')
find_by_xpath('//input[#name = "login-password"]').send_keys(data['pwd'])
return self
def submit(self):
find_by_xpath('//input[#id = "sign-in"]').click()
data = {
'usr': 'xx#apple.com',
'pwd': 'xxxx'
}
if __name__=="__main__":
FormPage().fill_form(data).submit()
driver.quit() # closes the webbrowser
Hope it is helpful to you
Thanks.!!

I recommend you try the following:
driver.find_element_by_id("login-appleId")
driver.find_element_by_id("login-password")

Sometimes in WebDriver there are scenarios where the WebElement isn't loaded properly on DOM and webdriver tries to find it. So to handle these kind of scenarios there are 2 types of wait provided by WebDriver library.
You just need to implement one of these based on your requirements.
Implicit Waits
Explicit Waits
I suggest you to implement one of these and then try to execute your script.

Related

WebDriverWait().until().send_keys giving TimeoutException

I am trying to scrape a website and I am unable to send keys to the email/password boxes to log in.
from config import root_dir, username_placer, password_placer
import os
import pathlib
os.chdir(root_dir)
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
from selenium.webdriver.support.ui import Select
import time
import math
import datetime as dt
import pandas as pd
from parse_account_name import parse_account_name
class Placer:
def __init__(self, account_name):
# Set webdriver parameters
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--kiosk-printing')
chrome_options.add_argument("window-size=1440,1080")
chromedriver = r'.\_reference\chromedriver.exe'
self.driver = webdriver.Chrome(executable_path=chromedriver, options=chrome_options)
self.driver.get('https://permits.placer.ca.gov/CitizenAccess/Default.aspx')
# Log in
WebDriverWait(self.driver, 30).until(lambda d: d.find_element_by_xpath('//*[#id="ctl00_PlaceHolderMain_LoginBox_txtUserId"]')).send_keys(username_placer)
self.driver.find_element_by_xpath('//*[#id="ctl00_PlaceHolderMain_LoginBox_txtPassword"]').send_keys(password_placer)
self.driver.find_element_by_xpath('//*[#id="ctl00_PlaceHolderMain_LoginBox_btnLogin"]').click()
time.sleep(2)
def search_placer(account_name):
scraper = Placer(account_name)
#
if __name__ == '__main__':
account_name = '''test'''
result = search_placer(account_name)
print(result)
It will just return a TimeoutException. I've tried using EC.element_to_be_clickable, but I get the same error. Without waiting and just trying to skip to sending keys, I (predictably) get NoSuchElementException.
If I print the page source, it returns the collapsed HTML.
It seems like the page and elements load by the time it looks for the login box element, so I'm not sure why it can't find it. What should I try at this point?
The issue you are facing is that the elements you are trying to reach are inside of an IFRAME. Using Selenium, you have to first switch to the IFRAME before interacting with that part of the page. Once you are done with elements inside the IFRAME, make sure you switch back to the default content.
Additional feedback...
If you are going to locate an element using the ID, always use By.ID instead of By.XPATH. It's much simpler syntax and easier to read.
You should always use the EC class methods when possible rather than writing your own custom wait conditions.
Using sleep is a bad practice and should be avoided whenever possible. Instead use WebDriverWait each time you need to wait for an element as you did earlier in your code.
Using these suggestions, the updated code would be something like
self.driver.get('https://permits.placer.ca.gov/CitizenAccess/Default.aspx')
driver.switch_to.frame(driver.find_element(By.ID, "ACAFrame"))
# Log in
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "ctl00_PlaceHolderMain_LoginBox_txtUserId")).send_keys(username_placer)
self.driver.find_element(By.ID, "ctl00_PlaceHolderMain_LoginBox_txtPassword").send_keys(password_placer)
self.driver.find_element(By.ID, "ctl00_PlaceHolderMain_LoginBox_btnLogin").click()
driver.switch_to.default_content()
# don't use sleep... instead use a WebDriverWait

Python Selenium impossible, tried id, class can't find XPath

I am trying to enter a field with text (email), in the username box. However, it is not interacting with it. I have it in a try & except statement but it only spits out excepts.
Website is account.protonmail.com/signup
I have tried everything: xpath, class, id, but nothing works. I am losing my mind!
Password works fine:
Does not work:
driver.find_element_by_xpath('//*[#id="username"]').send_keys(password)
Does work:
driver.find_element_by_xpath('//*[#id="repeat-password"]').send_keys(password)
And yes, I do wait until JavaScript finishes running.
it is in iframe, and needs explicit waits :-
driver = webdriver.Chrome(driver_path)
driver.maximize_window()
driver.get("https://account.protonmail.com/signup")
wait = WebDriverWait(driver, 20)
wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "iframe[sandbox^='allow-scripts']")))
ele = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#username"))).send_keys('someemail#gmail.com')
Imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Element you are trying to access is inside an iframe. First you need to switch to the frame like this
driver.switch_to.frame(driver.find_element_by_xpath("//iframe[contains(#src,'account-api.protonmail.com')]"))
It's very difficult for you to write everything, make it easier
click = driver.find_element_by_xpath('//*[#id="username"]').click()
click.send_keys('')
click.send_keys(password)

Can't login to Target.com with Selenium

I'm working on a online purchase bot for target.com and I've run into a blocker. Upon providing correct username and password combination on the login page and clicking "login", I get the following error message on the target login page: "Sorry, something went wrong. Please try again.". This only occurs when running through browser automation. Just wondering if there's a workaround for this issue. Here is my code thus far:
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
PATH="C:\Program Files (x86)\chromedriver.exe"
driver = webdriver.Chrome(PATH)
btn_sign_in_nav = "//span[text()='Sign in']"
btn_sign_in_drop_down = "//div[#id='accountMenu']//div[text()='Sign in']"
input_username_login = "//input[#id='username']"
input_password_login = "//input[#id='password']"
btn_submit_login = "//button[#id='login']"
def xpath_explicit_wait(xpath_val, time_sec):
if type(time_sec) != int or type(xpath_val) != str:
print("NUMERICAL VALUES ONLY!")
driver.quit()
try:
element = WebDriverWait(driver, time_sec).until(
EC.presence_of_element_located((By.XPATH, xpath_val))
)
except NoSuchElementException:
driver.quit()
def login_user(url, username, password):
driver.get(url)
driver.implicitly_wait(3)
driver.find_element_by_xpath(btn_sign_in_nav).click()
xpath_explicit_wait(btn_sign_in_drop_down, 5)
driver.find_element_by_xpath(btn_sign_in_drop_down).click()
driver.implicitly_wait(3)
driver.find_element_by_xpath(input_username_login).send_keys(username)
driver.find_element_by_xpath(input_password_login).send_keys(password)
xpath_explicit_wait(btn_submit_login, 5)
driver.find_element_by_xpath(btn_submit_login).click()
There are detection mechanisms on sites like target that detect when you're using selenium and prevent the site from working.
More details can be found in the answer here: Can a website detect when you are using Selenium with chromedriver?
PhoenixBot implements a mechanism that changes the contents of the driver so that it's undetectable. Use this same mechanism and your problems will vanish, as mine did! :-D
https://github.com/Strip3s/PhoenixBot/blob/554441b3b6888a9be46b8aed6d364dc33da92e87/utils/selenium_utils.py#L150-L173
There is a bot Phoenixbot, I can't speak for the functionality 100% but the auto login portion definitely works and is python. https://github.com/Strip3s/PhoenixBot/blob/master/sites/target.py
I've been attempting to figure out how exactly it's accomplishing that but no success replicating successfully in my own code. Maybe take a look.... If you figure it out I'd love to know.
IF you have the ability to use Safari webdriver, then see the below code.
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
driver = webdriver.Safari(executable_path='/usr/bin/safaridriver')
driver.get('https://www.target.com/')
action = ActionChains(driver)
driver.find_element(By.XPATH, '//*[#id="account"]').click()
WebDriverWait(driver, 30).until(ec.presence_of_element_located((By.XPATH, '//*[#id="accountNav-signIn"]')))
action.send_keys(Keys.ENTER)
action.perform()
WebDriverWait(driver, 10).until(ec.presence_of_element_located((By.XPATH, '//h2[#class="sc-hMqMXs sc-esjQYD eXTUDl"]')))
driver.find_element(By.ID, 'username').click()
driver.find_element(By.ID, 'username').send_keys('foo')
time.sleep(5)
driver.find_element(By.ID, 'password').click()
driver.find_element(By.ID, 'password').send_keys('bar')
time.sleep(5)
driver.find_element(By.XPATH, "//button[#id=\'login\']").send_keys(Keys.ENTER)
time.sleep(10)
driver.quit()
As #Decian Shanaghy mentioned, Target seems to be bot protected, but Safari webdriver still works.
The time.waits are not needed, you can remove them if you would like.
For anyone still seeking a solution to this, see this answer at Can a website detect when you are using Selenium with chromedriver?. I did a search through the chromedriver binary executable (MacOS in my case) and changed instances of $cdc_ to $abc_.
I originally suspected Target employs a JavaScript solution to hunting selenium users. I confirmed this suspicion by using selenium to open a browser at https://www.target.com without any automation. I attempted to manually login and obtained a 401 response with the well known "Sorry, something went wrong. Please try again." That didn't rule out a UI-based bot hunting solution but it pointed to a JavaScript hunter.

Why I can't send_keys to Twitch search bar in Python with Selenium?

I was trying to write a Selenium bot to search in twitch.
I can click the search bar but I can't send any value to the search bar.
what is the issue? I worked for hours but can't fix my problem.
This is my code:
from selenium import webdriver
#https://selenium-python.readthedocs.io/
from selenium.webdriver.common.keys import Keys
#from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class Twitch:
def __init__(self):
self.browser = webdriver.Chrome()
def openTwitch(self):
self.browser.get("https://www.twitch.tv/")
self.browser.maximize_window()
try:
barClick = WebDriverWait(self.browser,10).until(EC.element_to_be_clickable((By.XPATH, '//*[#id="root"]/div/div[2]/nav/div/div[2]/div/div')))
barClick.click()
except:
print("Element not clickable")
try:
searchBar = WebDriverWait(self.browser,10).until(EC.visibility_of_element_located((By.XPATH,'//*[#id="tw-2a283106145a4249e75c7a6787c01324"]')))
searchBar.send_keys("Xantares") #this area is not working..
searchBar.send_keys(Keys.ENTER)
except:
print("Element not writable")
twtch = Twitch()
twtch.openTwitch()
Try not take random generated ids, they are volatile so in the next run you will not reach the element.
For example you could take a reference from input tag like:
searchBar = WebDriverWait(self.browser, 10).until(EC.visibility_of_element_located((By.XPATH,'(//input[#type="search"])[1]')))
There is a powerfool tool in the browser that can help you to find the right selector:
You should press F12, then in the Elements tab, press CTRL + F, it allows you to test the XPATH expressions there.
Regards.
Try insert the text inside input tag.
Something is wrong with your locator,
change with:
searchBar = WebDriverWait(self.browser,10).until(EC.visibility_of_element_located((By.XPATH,'//div[#class="tw-relative"]//input[not(contains(#id, "hidden"))]')))
Are you sure this ID(tw-2a283106145a4249e75c7a6787c01324) is valid? It looks like it's some randomly generated id.
If you would like to do it hardway, set focus to it, and use Actions to send keys.

Selecting nested iframes with Selenium in Python

I'm trying to automate the filling out of an Easily Apply job application on Indeed. Here is an example of a job application on Indeed that uses the Easily Apply approach. I've tried every which way to navigate the nested iframes; however, I cannot find an approach that works. I even found that this question has been asked before, unfortunately, the solution given to the question does not work for me. Below is my code as it stands now:
from selenium import webdriver
driver = webdriver.Firefox()
driver.get('indeed_url_goes_here')
driver.find_element_by_class_name('indeed-apply-button').click()
driver.switch_to_frame(driver.find_element_by_xpath('/html/body/iframe'))
driver.switch_to_frame(driver.find_element_by_xpath('//*[#id="indeedapply-modal-preload-iframe"]'))
driver.find_element_by_class_name('applicant.name')
Find the first parent iframe and switch to it and then to the nested frame by index.
Complete working code:
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
driver = webdriver.Firefox()
driver.get("http://www.indeed.com/viewjob?jk=2e3d019aa34a2801&q=bartender&tk=1a9g51n08a3iof6h&from=web&advn=5333586156877432&sjdu=UvkB_mgi5f7NyMagFcTHP0E6zA3mclLGHWb8Kte-0FV3cY2ZuZvj3LUvh8wnnxrqeYWG3HpvTXBK3G4htWfwgfQeMa0N1Tds6VxYb4V3Vlg&pub=4a1b367933fd867b19b072952f68dceb")
driver.find_element_by_class_name('indeed-apply-button').click()
wait = WebDriverWait(driver, 10)
frame = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "iframe[name$=modal-iframe]")))
driver.switch_to.frame(frame)
driver.switch_to.frame(0)
print(driver.find_element_by_css_selector("h1.jobtitle").text)
Prints the job title from the popup: Bartender/Mixologist.
Well first off, the element doesn't have a class name - it has a regular name and an ID, so use either driver.find_element_by_nameor driver.find_element_by_id.

Categories

Resources