I'm practicing with selenium right now but I can't seem to get it to print the correct URL.
import time
from selenium import webdriver
driver = webdriver.Firefox()
home_page = ''
driver.get(home_page)
time.sleep(15)
for i in range(1,9):
listing_page = driver.find_element_by_xpath('//*[#id="m_property_lst_cnt_realtor_more_'+str(i)+'"]').click()
realtor_url = driver.find_element_by_xpath('//*[#id="lblMediaLinks"]/a').click()
print(driver.current_url)
driver.get(home_page)
time.sleep(5)
I need the URL of the webpage that opens up when selenium clicks on the element in realtor_url. It instead prints the URL of the first click from listing_page.
(Note: webpage that is opened from realtor_url is a completely different website, if that helps)
You need to switch to the newly opened window before printing the URL, then close the newly opened window and switch back to the original window.
// do the click that opens another window
WebDriverWait(driver, 10).until(lambda d: len(d.window_handles) == 2)
driver.switch_to_window(driver.window_handles[1])
print(driver.current_url)
driver.close()
driver.switch_to_window(driver.window_handles[0])
A couple other things...
.click() returns void, i.e. nothing, so there's nothing ever stored in listing_page or realtor_url variables.
sleep() is a bad practice. Don't use it. Google it to find out the details why. Replace sleep() with a relevant WebDriverWait.
I believe you need to change the "focus"of the window in order to print the correct url. The current window handler may be pointing to the previous click and not changed focus to the new window.
Try and get to change the "window handler". Every new window opened has a handler.
I hope this helps. window_handles Or this Handle multiple window in Python
EDIT:
The below should bring you to the latest open window.
driver.switch_to_window(driver.window_handles[-1])
Related
I am trying to automate a task which can save me thousands of clicks.
I searched a bit for available modules in Python and I have selected to work with Selenium.
I installed Firefox drivers and did some progress but I am stuck for a long time. I finally gave up, opened a Stack Overflow account and wanted to bring this problem into this helpful medium.
My code can successfully do some clicks, but I could not make the code click a button like element. I have to click such items so that page opens some new elements. (Hopefully I am going to click on these new elements to save some excels files automatically).
Here is the part which works as expected:
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time
browser = webdriver.Firefox()
url = "https://www.tbb.org.tr/tr/bankacilik/banka-ve-sektor-bilgileri/istatistiki-raporlar/59"
browser.get(url)
time.sleep(2)
bank_reports_element_xpath = "//*[#title= 'Tüm Raporlar']"
bank_reports_element = browser.find_element_by_xpath(bank_reports_element_xpath)
bank_reports_element.click()
time.sleep(2)
second_item = "//div[#data-catid = '52']"
finance_tables_element = browser.find_element_by_xpath(second_item)
finance_tables_element.click()
years_item = "//div[#class = 'years']"
years_element = finance_tables_element.find_element_by_xpath(years_item)
year_elements = years_element.find_elements_by_xpath("a")
There I would like to click on the years.
a screenshot of the years that I can't click using Selenium
As an example, I get the element related to year 2004.
year2004 = year_elements[2]
Issuing a year2004.click() command gives an ElementNotInteractableException exception.
year2004.click() # ElementNotInteractableException: Element could not be scrolled into view
Based on searching similar posts, I tried the following (executing the click via javascript). I got no error but it does not do anything. When I click the year2004 button with mouse, a list pops-up in the page. But when I run the below code, no list pops up in the page.
browser.implicitly_wait(4)
browser.execute_script("arguments[0].scrollIntoView();", year2004)
browser.execute_script("arguments[0].click()", year2004)
I tried also the following code. I get "TypeError: rect is undefined"
browser.implicitly_wait(4)
action = ActionChains(browser)
action.move_to_element(year2004) # gives: TypeError: rect is undefined
action.click(on_element = year2004) # gives: TypeError: rect is undefined
action.perform()
I tried using Chrome Driver and got similar results. The errors definitions were not exactly the same. Instead of the above "rect is undefined" error, Chrome error is like: "Javascript error: Failed to execute 'elementsFromPoints' on 'Document': Provided double value is non-finite"
I don't know if it is relevant but year2004.location dictionary has a 0 value for "x".
I would appreciate any answer,
Keep safe
Use this xpath will give you all the elements of year in 52 category
//div[#data-catid='52']/descendant-or-self::*/div[#class='years']/child::a
for scrolling try
browser.send_keys(Keys.PAGE_DOWN)
I checked manually and page down button is working for me press it twice for desire element
I want to use Selenium to click an element in a menu drop down list. Unfortunately the element I want to click is all the way at the bottom of the list. My Selenium Python Chrome code runs perfectly in foreground mode, but when I run it in background / headless mode I get a timeout, or not clickable error (see notes below). Here is the code, using the actual public url, so you can test it out if you want:
# define chrome options
options = webdriver.ChromeOptions()
# make sure browser is maximized so all elements are visible
options.add_argument('--start-maximized')
# define driver
driver = webdriver.Chrome(chrome_options=options)
# define function used to get button
def getbutton(driver, xpath, waittime=10):
return WebDriverWait(driver, waittime).until(EC.element_to_be_clickable((By.XPATH, xpath)))
# navigate to url
driver.get('http://oasis.caiso.com/mrioasis/logon.do')
# another two different ways to make sure browser window is maximized
# I'm going through this trouble just in case selenium needs the window
# maximized to see the element
driver.fullscreen_window()
driver.maximize_window()
# choose dropdown menu
button1 = getbutton(driver, "//span[contains(#id, 'LBL_')][text()='ATLAS REFERENCE']", waittime=120)
hover = ActionChains(driver).move_to_element(button1)
hover.perform()
time.sleep(5)
# see about navigating to the second to last button in the drop down
# menu list - not what I want, but a test
testing = True
if testing:
# move to second to last button - interestingly this works in foregraound AND background / headless modes
button1a = getbutton(driver, "//span[contains(#id, 'LBL_')][text()='Intertie Scheduling Limit and Tie Mapping']")
hover = ActionChains(driver).move_to_element(button1a)
# THIS WORKS in foreground AND backgroubd modes
hover.perform()
time.sleep(10)
# Now try and click the button I really want - the LAST button in the drop down menu list
button2 = getbutton(driver, "//span[contains(#id, 'LBL_')][text()='Master Control Area Generating Capability List']", waittime=120)
button2.click()
button2 = getbutton fails with the following error message:
selenium.common.exceptions.TimeoutException
Interestingly, if I turn testing to False, I get the following error message:
selenium.common.exceptions.WebDriverException: Message: unknown error:
Element <span ...></table>">Master Control Area Generating Capability List</span>
is not clickable at point (128, 599). Other element would receive the click
It seems like selenium is unable to see the element in background / headless mode, even though neither of these exceptions occur when running in foreground mode.
I'm running Python in Windows Server 2012 R2 for what it's worth.
Thanks for any help!
I've changed a few things in your code and I no longer get the errors. I'm not sure if it's loading the correct webpage though since it's headless and everything seems to be dynamically loaded.
# another two different ways to make sure browser window is maximized
# I'm going through this trouble just in case selenium needs the window
# maximized to see the element
#driver.fullscreen_window()
#driver.maximize_window()
# choose dropdown menu
button1 = driver.find_element_by_xpath("//span[contains(#id, 'LBL_')][text()='ATLAS REFERENCE']")
hover = ActionChains(driver)
hover.move_to_element(button1)
# see about navigating to the second to last button in the drop down
# menu list - not what I want, but a test
testing = True
if testing:
# move to second to last button - interestingly this works in foregraound AND background / headless modes
button1a = driver.find_element_by_xpath("//span[contains(#id, 'LBL_')][text()='Intertie Scheduling Limit and Tie Mapping']")
hover.move_to_element(button1a)
# THIS WORKS in foreground AND backgroubd modes
# Now try and click the button I really want - the LAST button in the drop down menu list
button2 = driver.find_element_by_xpath("//span[contains(#id, 'LBL_')][text()='Master Control Area Generating Capability List']")
hover.click(button2)
hover.perform()
I'm selecting the elements with .find_element_by_xpath() and I'm queuing up all the ActionChains to execute them all at the end with hover.perform().
After further analysis, I'm unable to locate the "masterControlAreaGenCapGrid_GRID_LABEL" element with driver.find_element_by_id("masterControlAreaGenCapGrid_GRID_LABEL").text
It works when the browser isn't headless though...
So I finally figured out what the problem is: Running Windows task scheduler with option 'run whether user is logged on or not' only opens a small browser (1024x768) that CANNOT be resized, even with all the great suggestions being offered here. So I simply cannot see the element I want to click.
See the same issue resolved here: screen resolution in mode "Run whether user is logged on or not", in windows task scheduler
So the less than ideal workaround is to only run when user is logged on.
Thanks for all your help!
The automation task requires moving to an open tab, executing a command ( a button click) and then moving on to the next tab. This process is repeated for the next 4-5 tabs.
I already have a code that automates this process. I have a for loop that goes through each of the window handles for the opened tabs and automates the button click. But the issue is that on each tab, the driver waits for the execution of the button click to process and the new page to load before moving on to the next tab. I ideally want the driver to click the button and move to the next tab instantaneously without waiting for the new page to load.
Is there some method for achieving this? Are there any other options besides using Selenium for this sort of automation.
My current code looks like something like this :
handles = driver.window_handles
for i in range(4):
driver.switch_to_window(handles[i])
driver.find_element_by_id('submit').click()
for i in range(3):
driver.switch_to_window(driver.window_handles[i+1])
chain = ActionChains(driver)
element = driver.find_element_by_name('submit')
chain.move_to_element_with_offset(element, 0, 0)
chain.click(element)
chain.release(element)
chain.perform()
I used the aboce code to use ActionChains to click the button. But im getting a StateElementReferenceException. The rrror is triggered at chain.perform()
StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
Using action chains to perform the click action will allow Selenium to continue without waiting for the result of the click action. Tested on linux, python3.4, chromedriver2.38:
from selenium.webdriver.common.action_chains import ActionChains
from selenium.common.exceptions import *
chain = ActionChains(super().driver)
try:
element = driver.find_element_by_id('submit')
chain.move_to_element_with_offset(element, 0, 0)
chain.click(element)
chain.release(element)
# Perform the chained actions including the left-click.
chain.perform()
except:
print("Failed to click element")
raise
I'm trying to .click() a few elements in a pop up-list on a webpage, but keep getting the StaleElementReferenceException when i try to move_to_elements.
The code is based around a number of clickable elements in a feed. When clicked, these elements result in a pop-up box with more clickable elements that I want to access.
I access the pop up-box with the following code, where popupbox_links are a list with coordinates and links for the pop up boxes:
for coordinate in popupbox_links:
actions = ActionChains(driver)
actions.move_to_element(coordinate["Popupbox location"]).perform()
time.sleep(3)
popupboxpath = coordinate["Popupbox link"]
popupboxpath.click()
time.sleep(3)
This works fine. But when the pop up box is opened, I want to perform the following:
seemore = driver.find_element_by_link_text("See More")
time.sleep(2)
actions.move_to_element(seemore).perform()
time.sleep(2)
seemore.click()
time.sleep(3)
findbuttons = driver.find_elements_by_link_text("Button")
time.sleep(2)
print(findbutton)
for button in findbuttons:
time.sleep(2)
actions.move_to_element(button).perform()
time.sleep(2)
button.click()
time.sleep(randint(1, 5))
The trouble starts at actions.move_to_element on both "See more" and "Button". Even though the print(findbutton) actually returns a list with contents, containing the elements that I want to click, Selenium seems to be unable to move_to_element on these. Instead, it throws StaleElementReferenceException.
To make it more confusing, the script seems to work at times. Although usually it just crashes.
Any clues on how to solve this? Big thanks in advance.
I'm running the latest Selenium on Python 3.6 with the Chrome WebDriver.
StaleElementReferenceException Says that element is stage because something has changed in page after you created the webElement object. In you case that could be happening due to button.click().
The simplest solution is to create new element every time, rather than iterate element from the loop.
following changes might work.
findbuttons = driver.find_elements_by_link_text("Button")
time.sleep(2)
print(findbuttons)
for i in range(len(findbuttons)):
time.sleep(2)
elem = driver.find_elements_by_link_text("Button")[i]
actions.move_to_element(elem).perform()
time.sleep(2)
elem.click()
time.sleep(randint(1, 5))
I am working on a project and in this project there are two webpages I need to examine.I have to open these two webpages at the same time in different windows and examine them at the same time.
There must be two windows and there is a function that checks an element's status.But this function must be checking them at the same time.How can I solve this problem?
Thanks
You can open more than one browser at a time:
from selenium import webdriver
driver1 = webdriver.Firefox()
driver2 = webdriver.Firefox()
driver1.get(...)
driver2.get(...)
If you want two windows into the current driver session you can use a little javascipt to open a second window with a single driver:
driver.execute_script("$(window.open('http://www.example.com'))")
window1 = driver.window_handles[0]
window2 = driver.window_handles[1]
# test the first window
driver.switch_to_window(window1)
...
# test the second window
driver.switch_to_window(window2)
...
I'm not sure about doing at at exactly the same time, but you could open one of the pages in a separate tab, then move between the two do your comparison.
driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL +"t");
ArrayList<String> tabs = new ArrayList<String> (driver.getWindowHandles());
driver.switchTo().window(tabs.get(0));
***get value to compare****
driver.switchTo().window(tabs.get(1));
driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL +"Keys.TAB");
***get second value and compare***
If not, perhaps look into using Selenium Grid to run two tests in parallel.
I only spotted that you're working in Python after writing the answer, but im sure there's an equivalent.