This has been bugging me for a long time, if anyone can help me spot the mistake in my program, it will be appreciated.
Thanks.
class amz_bot():
def __init__(self):
self.driver = webdriver.Firefox()
def login(self):
self.driver.get("http://www.amazon.com/")
time.sleep(5)
while True:
ActionChains(self.driver).send_keys(Keys.F5).perform()
time.sleep(5)
bot = amz_bot()
bot.login()
It looks like the F5 isn't going anywhere.
Selenium spins up a browser but the ActionChain object is a low level key press. Even though it's created with the driver object, it doesn't have the context of the window.
If you were to send any other (normal) keys - where are they sent?
One solution is to use send_keys_to_element instead just blind send_keys.
This will put the focus in the window then send f5.
In my solution here, i'm assuming it only has one html tag... It's a fair assumption, but, my first attempt used body and then it turned out there were 3 pf those.
So... Try this:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from time import sleep
import time
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
class amz_bot():
def __init__(self):
self.driver = webdriver.Chrome()
def login(self):
self.driver.get("http://www.amazon.com/")
time.sleep(5)
while True:
e = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, 'html')))
ActionChains(self.driver).send_keys_to_element(e, Keys.F5).perform()
time.sleep(10)
bot = amz_bot()
bot.login()
This kind of worked for me - but it's weird. When selenium presses F5 (so it's doing the key press!) the page isn't refreshing, it's going into a search result.
I'm going to have another look in a moment (and i'll update the answer) but this is a step in the right direction. At least something is happening with the key press.
Update - Another option is to use javascript. Instead of F5, this refreshes the page:
self.driver.execute_script("location.reload()")
It's worth a try for it's simplicity but it might be similar to the standard browser.refresh()
Another update:
Another approach is to navigate the browser to the current url - doing the same job as the refresh
self.driver.get(self.driver.current_url)
Related
I am creating a bot that checks to see if the Catus Trails 270 have been released and then buys them for me. I don't know how to check and see if the button is there or not. I am going to look for the button and then if it doesn't see it, it refreshes the page and looks again. I am using the other air maxes as an example for what the page will look like when it drops. Here is a code sample: Thank you!
from selenium import webdriver
from time import sleep
from selenium.webdriver.common.keys import Keys
class catusBot:
def __init__(self, name):
self.driver = webdriver.Chrome()
self.driver.get("https://www.nike.com/launch/t/air-max-2090-pure-platinum-amd?cp=usns_aff_nike_")
if self.driver.find_element_by_xpath("/html/body/div[2]/div/div/div[1]/div/div[3]/div[2]/div/section[1]/div[2]/aside/div/div[2]/div/div[2]/ul/li[11]/button") == True:
self.driver.find_element_by_xpath("/html/body/div[2]/div/div/div[1]/div/div[3]/div[2]/div/section[1]/div[2]/aside/div/div[2]/div/div[2]/ul/li[11]/button").click()
self.driver.find_element_by_xpath("/html/body/div[2]/div/div/div[1]/div/div[3]/div[2]/div/section[1]/div[2]/aside/div/div[2]/div/div[2]/div/button").click()
else:
self.driver.refresh()
my_bot = catusBot("Ethan Houseworth")
find_element_by_* methods will raise a NoSuchElementException if the element can not be found. You will want to handle that.
I'm trying to write a Python script with Selenium to autocomplete a form.
There are several fields with auto-complete. I can fill these out and select as follows:
field1 = driver.find_element_by_id("field-1")
field1.send_keys("input")
driver.find_element_by_xpath("//ul[1]/li[1]") #this clicks on the first autocomplete option
This works fine.
However, in order to proceed to the next form, I have to first simulate a click away, and usually delay by 5-8 seconds:
driver.find_element_by_xpath("//body").click()
time.sleep(delay)
Delay is usually set at 8 seconds - any less and it seems to not work from time to time.
Is there a more efficient way to do this that avoids using a timed delay?
I thought that possibly I need to exit the form / let Selenium confirm that the autocomplete has been selected.
You can use WebDriverWait to wait for an element to be located in the new form. This way you wouldn't have to explicitly declare a delay functionality and the code will resume execution once the new form becomes present.
Sample code
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
browser = webdriver.Firefox()
browser.get("url")
delay = 3 # seconds
driver.find_element_by_xpath("//body").click()
try:
myElem = WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.ID, 'IdOfMyElement')))
print "new form is ready!"
# add your code here
except TimeoutException:
print "Loading took too much time!"
You can also use any other type of method to find the locator.
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.
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.
I have these includes:
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.keys import Keys
Browser set up via
browser = webdriver.Firefox()
browser.get(loginURL)
However sometimes I do
browser.switch_to_frame("nameofframe")
And it won't work (sometimes it does, sometimes it doesn't).
I am not sure if this is because Selenium isn't actually waiting for pages to load before it executes the rest of the code or what. Is there a way to force a webpage load?
Because sometimes I'll do something like
browser.find_element_by_name("txtPassword").send_keys(password + Keys.RETURN)
#sends login information, goes to next page and clicks on Relevant Link Text
browser.find_element_by_partial_link_text("Relevant Link Text").click()
And it'll work great most of the time, but sometimes I'll get an error where it can't find "Relevant Link Text" because it can't "see" it or some other such thing.
Also, is there a better way to check if an element exists or not? That is, what is the best way to handle:
browser.find_element_by_id("something")
When that element may or may not exist?
You could use WebDriverWait:
from contextlib import closing
from selenium.webdriver import Chrome as Browser
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import NoSuchFrameException
def frame_available_cb(frame_reference):
"""Return a callback that checks whether the frame is available."""
def callback(browser):
try:
browser.switch_to_frame(frame_reference)
except NoSuchFrameException:
return False
else:
return True
return callback
with closing(Browser()) as browser:
browser.get(url)
# wait for frame
WebDriverWait(browser, timeout=10).until(frame_available_cb("frame name"))