How to automate opening of new tabs on Google Chrome? Selenium Python - python

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

Related

How to type text in input element in Selenium without finding the input element?

I have a python script that uses Selenium and, in the script, a Google Login (OAuth) button is clicked and a new window is displayed as shown below:
In the new window, thanks to the superb UX :P, the input element for the email field is already selected. Since the field is already selected, can I use Selenium to just start typing without finding the input element and using send_key?
Just switch to active element .switch_to.active_element :
element = driver.switch_to.active_element
element.send_keys('value')
from selenium.webdriver.common.action_chains import ActionChains
actions = ActionChains(driver)
actions.send_keys('hotmail.com')
actions.perform()
Try using action chains to send the keys over.

Why a click function of a web page element doesn't work (using Selenium module of Python)?

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

Selenium Python Chrome: Last element in drop down list is not visible in Headless mode

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!

Selenium not printing out the right URL

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])

Selenium - Click at certain position

Using the Python version of Selenium, is it possible to click some element in the DOM and to specify the coordinates where you want to click it?
The Java version has the method clickAt, which actually does exactly what I am looking for, but can't find the equivalent in Python.
This should do it! Namely you need to use action chains from webdriver. Once you have an instance of that, you simply register a bunch of actions and then call perform() to perform them.
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.google.com")
el=driver.find_elements_by_xpath("//button[contains(string(), 'Lucky')]")[0]
action = webdriver.common.action_chains.ActionChains(driver)
action.move_to_element_with_offset(el, 5, 5)
action.click()
action.perform()
This will move the mouse 5 pixels down and 5 pixels right from the upper-left corner of the button I feel lucky. Then it will click().
Notice that you must use perform(). Else nothing will happen.
The reason you are getting confused is clickAt is an old v1 (Selenium RC) method.
WebDriver has a slightly different concept, of 'Actions'.
Specifically, the 'Actions' builder for the Python bindings live here.
The idea of the clickAt command is to click at a certain position relative to a particular element.
The same is achievable within the WebDriver, using the 'Actions' builder.
Hopefully this updated documentation can help.
You can perform the task with the Action chains in the python specially with Edge browser:
from selenium.webdriver import ActionChains
actionChains = ActionChains(driver)
button_xpath = '//xapth...'
button = driver.find_element_by_xpath(button_xpath)
actionChains.move_to_element(button).click().perform()
But sometimes Action chain does not finds the DOM element. Hence better option to use execute scipt in following way:
button_xpath = '//xapth...'
button = driver.find_element_by_xpath(button_xpath)
driver.execute_script("arguments[0].click();", button)
I've not personally used this method, but looking through the source code of selenium.py I've found the following methods that look like they'd do what you want - They look to wrap clickAt:
def click_at(self,locator,coordString):
"""
Clicks on a link, button, checkbox or radio button. If the click action
causes a new page to load (like a link usually does), call
waitForPageToLoad.
'locator' is an element locator
'coordString' is specifies the x,y position (i.e. - 10,20) of the mouse event relative to the element returned by the locator.
"""
self.do_command("clickAt", [locator,coordString,])
def double_click_at(self,locator,coordString):
"""
Doubleclicks on a link, button, checkbox or radio button. If the action
causes a new page to load (like a link usually does), call
waitForPageToLoad.
'locator' is an element locator
'coordString' is specifies the x,y position (i.e. - 10,20) of the mouse event relative to the element returned by the locator.
"""
self.do_command("doubleClickAt", [locator,coordString,])
They appear in the selenium object and here is their online API documentation.

Categories

Resources