We developed a Chrome extension, and I want to test our extension with Selenium. I created a test, but the problem is that our extension opens a new tab when it's installed, and I think I get an exception from the other tab. Is it possible to switch to the active tab I'm testing? Or another option is to start with the extension disabled, then login to our website and only then enable the extension. Is it possible? Here is my code:
def login_to_webapp(self):
self.driver.get(url='http://example.com/logout')
self.driver.maximize_window()
self.assertEqual(first="Web Editor", second=self.driver.title)
action = webdriver.ActionChains(driver=self.driver)
action.move_to_element(to_element=self.driver.find_element_by_xpath(xpath="//div[#id='header_floater']/div[#class='header_menu']/button[#class='btn_header signature_menu'][text()='My signature']"))
action.perform()
self.driver.find_element_by_xpath(xpath="//ul[#id='signature_menu_downlist'][#class='menu_downlist']/li[text()='Log In']").click()
self.driver.find_element_by_xpath(xpath="//form[#id='atho-form']/div[#class='input']/input[#name='useremail']").send_keys("[email]")
self.driver.find_element_by_xpath(xpath="//form[#id='atho-form']/div[#class='input']/input[#name='password']").send_keys("[password]")
self.driver.find_element_by_xpath(xpath="//form[#id='atho-form']/button[#type='submit'][#class='atho-button signin_button'][text()='Sign in']").click()
The test fails with ElementNotVisibleException: Message: element not visible, because in the new tab (opened by the extension) "Log In" is not visible (I think the new tab is opened only after the command self.driver.get(url='http://example.com/logout')).
Update: I found out that the exception is not related to the extra tab, it's from our website. But I closed the extra tab with this code, according to #aberna's answer:
def close_last_tab(self):
if (len(self.driver.window_handles) == 2):
self.driver.switch_to.window(window_name=self.driver.window_handles[-1])
self.driver.close()
self.driver.switch_to.window(window_name=self.driver.window_handles[0])
After closing the extra tab, I can see my tab in the video.
This actually worked for me in 3.x:
driver.switch_to.window(driver.window_handles[1])
window handles are appended, so this selects the second tab in the list
to continue with first tab:
driver.switch_to.window(driver.window_handles[0])
Some possible approaches:
1 - Switch between the tabs using the send_keys (CONTROL + TAB)
self.driver.find_element_by_tag_name('body').send_keys(Keys.CONTROL + Keys.TAB)
2 - Switch between the tabs using the using ActionsChains (CONTROL+TAB)
actions = ActionChains(self.driver)
actions.key_down(Keys.CONTROL).key_down(Keys.TAB).key_up(Keys.TAB).key_up(Keys.CONTROL).perform()
3 - Another approach could make usage of the Selenium methods to check current window and move to another one:
You can use
driver.window_handles
to find a list of window handles and after try to switch using the following methods.
- driver.switch_to.active_element
- driver.switch_to.default_content
- driver.switch_to.window
For example, to switch to the last opened tab, you can do:
driver.switch_to.window(driver.window_handles[-1])
The accepted answer didn't work for me.
To open a new tab and have selenium switch to it, I used:
driver.execute_script('''window.open("https://some.site/", "_blank");''')
sleep(1) # you can also try without it, just playing safe
driver.switch_to.window(driver.window_handles[-1]) # last opened tab handle
# driver.switch_to_window(driver.window_handles[-1]) # for older versions
if you need to switch back to the main tab, use:
driver.switch_to.window(driver.window_handles[0])
Summary:
The window_handles contains a list of the handles of opened tabs, use it as argument in switch_to.window() to switch between tabs.
Pressing ctrl+t or choosing window_handles[0] assumes that you only have one tab open when you start.
If you have multiple tabs open then it could become unreliable.
This is what I do:
old_tabs=self.driver.window_handles
#Perform action that opens new window here
new_tabs=self.driver.window_handles
for tab in new_tabs:
if tab in old tabs:
pass
else:
new_tab=tab
driver.switch_to.window(new_tab)
This is something that would positively identify the new tab before switching to it and sets the active window to the desired new tab.
Just telling the browser to send ctrl+tab does not work because it doesn't tell the webdriver to actually switch to the new tab.
if you want to close only active tab and need to keep the browser window open, you can make use of switch_to.window method which has the input parameter as window handle-id. Following example shows how to achieve this automation:
from selenium import webdriver
import time
driver = webdriver.Firefox()
driver.get('https://www.google.com')
driver.execute_script("window.open('');")
time.sleep(5)
driver.switch_to.window(driver.window_handles[1])
driver.get("https://facebook.com")
time.sleep(5)
driver.close()
time.sleep(5)
driver.switch_to.window(driver.window_handles[0])
driver.get("https://www.yahoo.com")
time.sleep(5)
#driver.close()
The tip from the user "aberna" worked for me the following way:
First I got a list of the tabs:
tab_list = driver.window_handles
Then I selectet the tab:
driver.switch_to.window(test[1])
Going back to previous tab:
driver.switch_to.window(test[0])
TLDR: there is a workaround solution, with some limitations.
I am working with the already opened browser, as shown here. The problem is that every time I launch the script, selenium internally selects a random tab. The official documentation says:
Clicking a link which opens in a new window will focus the new window
or tab on screen, but WebDriver will not know which window the
Operating System considers active.
It sounds very strange to me. Because is not that the first task of selenium to handle and automate browser interaction? More of that, switching to any tab with driver.switch_to.window(...) actually will switch the active tab in gui. Seems that it is a bug. At the moment of writing the python-selenium version is 4.1.0.
Let's look which approaches could we use.
Using selenium window_handles[0] approach
The approach from the answer above is not reliable. It does not always work. For example when you switch between different tabs, chromium/vivaldi may start returning not a current tab.
print("Current driver tab:", driver.title) # <- the random tab title
driver.switch_to.window(chromium_driver.window_handles[0])
print("Current driver tab:", driver.title) # <-- the currently opened tab title. But not always reliable.
So skip this method.
Using remote debugging approach
Provides nothing additional to what is in selenium driver from previous approach.
Getting the list of tabs via the remote debugging protocol like
r = requests.get("http://127.0.0.1:9222/json")
j = r.json()
found_tab = False
for el in j:
if el["type"] == "page": # Do this check, because if that is background-page, it represents one of installed extensions
found_tab = el
break
if not found_tab:
print("Could not find tab", file=sys.stderr)
real_opened_tab_handle = "CDwindow-" + found_tab["id"]
driver.switch_to(real_opened_tab_handle)
actually returns the same as what is in driver.window_handles. So also skip this method.
Workaround solution for X11
from wmctrl import Window
all_x11_windows = Window.list()
chromium_windows = [ el for el in all_x11_windows if el.wm_class == 'chromium.Chromium' ]
if len(chromium_windows) != 1:
print("unexpected numbner of chromium windows")
exit(1)
real_active_tab_name = chromium_windows[0].wm_name.rstrip(" – Chromium")
chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
# https://stackoverflow.com/a/70088095/7869636 - Selenium connect to existing browser.
# Need to start chromium as: chromium --remote-debugging-port=9222
driver = webdriver.Chrome(service=Service(ChromeDriverManager(chrome_type=ChromeType.CHROMIUM).install()), options=chrome_options)
tabs = driver.window_handles
found_active_tab = False
for tab in tabs:
driver.switch_to.window(tab)
if driver.title != real_active_tab_name:
continue
else:
found_active_tab = True
break
if not found_active_tab:
print("Cannot switch to needed tab, something went wrong")
exit(1)
else:
print("Successfully switched to opened tab")
print("Working with tab called:", driver.title)
The idea is to get the window title from wmctrl, which will let you know the active tab name.
Workaround solution for Wayland
Previous solution has a limitation, wmctrl only works with x11 windows.
I currently found out how to get the title of a window at which you click.
print("Please click on the browser window")
opened_tab = subprocess.run("qdbus org.kde.KWin /KWin queryWindowInfo | grep caption", shell=True, capture_output=True).stdout.decode("utf-8")
opened_tab_title = opened_tab.rstrip(" - Vivaldi\n").lstrip("caption: ")
Then the script from the previous solution could be used.
The solution could be improved using kwin window list query on wayland. I would be glad if somebody helps to improve this. Unfortunately, I do not know currently how to get list of wayland windows.
Here is the full script.
Note: Remove the spaces in the two lines for tiny URL below. Stack Overflow does not allow the tiny link in here.
import ahk
import win32clipboard
import traceback
import appJar
import requests
import sys
import urllib
import selenium
import getpass
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import socket
import time
import urllib.request
from ahk import AHK, Hotkey, ActionChain # You want to play with AHK.
from appJar import gui
try:
ahk = AHK(executable_path="C:\\Program Files\\AutoHotkey\\AutoHotkeyU64.exe")
except:
ahk = AHK(executable_path="C:\\Program Files\\AutoHotkey\\AutoHotkeyU32.exe")
finally:
pass
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--start-maximized')
chrome_options.add_experimental_option("excludeSwitches", ['enable-automation']);
chromeDriver = webdriver.Chrome('C:\\new_software\\chromedriver.exe', chrome_options = chrome_options)
def ahk_disabledevmodescript():
try:
ahk = AHK(executable_path="C:\\Program Files\\AutoHotkey\\AutoHotkeyU64.exe")
except:
ahk = AHK(executable_path="C:\\Program Files\\AutoHotkey\\AutoHotkeyU32.exe")
finally:
pass
ahk_disabledevmodescriptt= [
str('WinActivate,ahk_exe chrome.exe'),
str('Send {esc}'),
]
#Run-Script
for snipet in ahk_disabledevmodescriptt:
ahk.run_script(snipet, blocking=True )
return
def launchtabsagain():
chromeDriver.execute_script("window.open('https://developers.google.com/edu/python/introduction', 'tab2');")
chromeDriver.execute_script("window.open('https://www.facebook.com/', 'tab3');")
chromeDriver.execute_script("window.open('https://developer.mozilla.org/en-US/docs/Web/API/Window/open', 'tab4');")
chromeDriver.execute_script("window.open('https://www.easyespanol.org/', 'tab5');")
chromeDriver.execute_script("window.open('https://www.google.com/search?source=hp&ei=EPO2Xf3EMLPc9AO07b2gAw&q=programming+is+not+difficult&oq=programming+is+not+difficult&gs_l=psy-ab.3..0i22i30.3497.22282..22555...9.0..0.219.3981.21j16j1......0....1..gws-wiz.....6..0i362i308i154i357j0j0i131j0i10j33i22i29i30..10001%3A0%2C154.h1w5MmbFx7c&ved=0ahUKEwj9jIyzjb_lAhUzLn0KHbR2DzQQ4dUDCAg&uact=5', 'tab6');")
chromeDriver.execute_script("window.open('https://www.google.com/search?source=hp&ei=NvO2XdCrIMHg9APduYzQDA&q=dinner+recipes&oq=&gs_l=psy-ab.1.0.0i362i308i154i357l6.0.0..3736...0.0..0.179.179.0j1......0......gws-wiz.....6....10001%3A0%2C154.gsoCDxw8cyU', 'tab7');")
return
chromeDriver.get('https://ebc.cybersource.com/ebc2/')
compoanionWindow = ahk.active_window
launchtabs = launchtabsagain()
disabledevexetmessage = ahk_disabledevmodescript()
def copyUrl():
try:
ahk = AHK(executable_path="C:\\Program Files\\AutoHotkey\\AutoHotkeyU64.exe")
except:
ahk = AHK(executable_path="C:\\Program Files\\AutoHotkey\\AutoHotkeyU32.exe")
finally:
pass
snipet = str('WinActivate,ahk_exe chrome.exe')
ahk.run_script(snipet, blocking=True )
compoanionWindow.activate()
ahk_TinyChromeCopyURLScript=[
str('WinActivate,ahk_exe chrome.exe'),
str('send ^l'),
str('sleep 10'),
str('send ^c'),
str('BlockInput, MouseMoveoff'),
str('clipwait'),
]
#Run-AHK Script
if ahk:
for snipet in ahk_TinyChromeCopyURLScript:
ahk.run_script(snipet, blocking=True )
win32clipboard.OpenClipboard()
urlToShorten = win32clipboard.GetClipboardData()
win32clipboard.CloseClipboard()
return(urlToShorten)
def tiny_url(url):
try:
apiurl = "https: // tinyurl. com / api - create. php? url= " #remove spaces here
tinyp = requests.Session()
tinyp.proxies = {"https" : "https://USER:PASSWORD." + "#userproxy.visa.com:443", "http" : "http://USER:PASSWORD." + "#userproxy.visa.com:8080"}
tinyUrl = tinyp.get(apiurl+url).text
returnedresponse = tinyp.get(apiurl+url)
if returnedresponse.status_code == 200:
print('Success! response code =' + str(returnedresponse))
else:
print('Code returned = ' + str(returnedresponse))
print('From IP Address =' +IPadd)
except:
apiurl = "https: // tinyurl. com / api - create. php? url= " #remove spaces here
tinyp = requests.Session()
tinyUrl = tinyp.get(apiurl+url).text
returnedresponse = tinyp.get(apiurl+url)
if returnedresponse.status_code == 200:
print('Success! response code =' + str(returnedresponse))
print('From IP Address =' +IPadd)
else:
print('Code returned = ' + str(returnedresponse))
return tinyUrl
def tinyUrlButton():
longUrl = copyUrl()
try:
ahk = AHK(executable_path="C:\\Program Files\\AutoHotkey\\AutoHotkeyU64.exe")
except:
ahk = AHK(executable_path="C:\\Program Files\\AutoHotkey\\AutoHotkeyU32.exe")
finally:
pass
try:
shortUrl = tiny_url(longUrl)
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardText(shortUrl)
win32clipboard.CloseClipboard()
if ahk:
try:
if str(shortUrl) == 'Error':
ahk.run_script("Msgbox,262144 ,Done.,"+ shortUrl + "`rPlease make sure there is a link to copy and that the page is fully loaded., 5.5" )
else:
ahk.run_script("Msgbox,262144 ,Done.,"+ shortUrl + " is in your clipboard., 1.5" )
# ahk.run_script("WinActivate, tinyUrl" )
except:
traceback.print_exc()
print('error during ahk script')
pass
except:
print('Error getting tinyURl')
traceback.print_exc()
def closeChromeTabs():
try:
try:
ahk = AHK(executable_path="C:\\Program Files\\AutoHotkey\\AutoHotkeyU64.exe")
except:
ahk = AHK(executable_path="C:\\Program Files\\AutoHotkey\\AutoHotkeyU32.exe")
finally:
pass
compoanionWindow.activate()
ahk_CloseChromeOtherTabsScript = [
str('WinActivate,ahk_exe chrome.exe'),
str('Mouseclick, Right, 30, 25,,1'),
str('Send {UP 3} {enter}'),
str('BlockInput, MouseMoveOff'),
]
#Run-Script
if ahk:
for snipet in ahk_CloseChromeOtherTabsScript:
ahk.run_script(snipet, blocking=True )
return(True)
except:
traceback.print_exc()
print("Failed to run closeTabs function.")
ahk.run_script('Msgbox,262144,,Failed to run closeTabs function.,2')
return(False)
# create a GUI and testing this library.
window = gui("tinyUrl and close Tabs test ", "200x160")
window.setFont(9)
window.setBg("blue")
window.removeToolbar(hide=True)
window.addLabel("description", "Testing AHK Library.")
window.addLabel("title", "tinyURL")
window.setLabelBg("title", "blue")
window.setLabelFg("title", "white")
window.addButtons(["T"], tinyUrlButton)
window.addLabel("title1", "Close tabs")
window.setLabelBg("title1", "blue")
window.setLabelFg("title1", "white")
window.addButtons(["C"], closeChromeTabs)
window.addLabel("title2", "Launch tabs")
window.setLabelBg("title2", "blue")
window.setLabelFg("title2", "white")
window.addButtons(["L"], launchtabsagain)
window.go()
if window.exitFullscreen():
chromeDriver.quit()
def closeTabs():
try:
try:
ahk = AHK(executable_path="C:\\Program Files\\AutoHotkey\\AutoHotkeyU64.exe")
except:
ahk = AHK(executable_path="C:\\Program Files\\AutoHotkey\\AutoHotkeyU32.exe")
finally:
pass
compoanionWindow.activate()
ahk_CloseChromeOtherTabsScript = [
str('WinActivate,ahk_exe chrome.exe'),
str('Mouseclick, Right, 30, 25,,1'),
str('Send {UP 3} {enter}'),
str('BlockInput, MouseMoveOff'),
]
#Run-Script
if ahk:
for snipet in ahk_CloseChromeOtherTabsScript:
ahk.run_script(snipet, blocking=True )
return(True)
except:
traceback.print_exc()
print("Failed to run closeTabs function.")
ahk.run_script('Msgbox,262144,Failed,Failed to run closeTabs function.,2')
return(False)
Found a way using ahk library. Very easy for us non-programmers that need to solve this problem. used Python 3.7.3
Install ahk with. pip install ahk
import ahk
from ahk import AHK
import selenium
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = webdriver.ChromeOptions()
options.add_experimental_option("excludeSwitches", ['enable-automation']); #to disable infobar about chrome controlled by automation.
chrome_options.add_argument('--start-maximized')
chromeDriver = webdriver.Chrome('C:\\new_software\\chromedriver.exe', chrome_options = options) #specify your chromedriver location
chromeDriver.get('https://www.autohotkey.com/')#launch a tab
#launch some other random tabs for testing.
chromeDriver.execute_script("window.open('https://developers.google.com/edu/python/introduction', 'tab2');")
chromeDriver.execute_script("window.open('https://www.facebook.com/', 'tab3');")
chromeDriver.execute_script("window.open('https://developer.mozilla.org/en-US/docs/Web/API/Window/open', 'tab4');"`)
seleniumwindow = ahk.active_window #as soon as you open you Selenium session, get a handle of the window frame with AHK.
seleniumwindow.activate() #will activate whatever tab you have active in the Selenium browser as AHK is activating the window frame
#To activate specific tabs I would use chromeDriver.switchTo()
#chromeDriver.switch_to_window(chromeDriver.window_handles[-1]) This takes you to the last opened tab in Selenium and chromeDriver.switch_to_window(chromeDriver.window_handles[1])to the second tab, etc..
Related
Recently I have started working with multiple tabs in Selenium and I have encountered a strange problem. When I'm executing this code:
WebDriverWait(driver, 10).until(EC.number_of_windows_to_be(2))
driver.switch_to.window(driver.window_handles[-1])
time.sleep(1)
url_in_page_source= eu.look_for_url_in_page_source(
page_html=driver.page_source,
left_delimiter='placeholder',
right_delimiter='placeholder'
)
driver.close()
driver.switch_to.window(driver.window_handles[0])
# time.sleep(10) # <--- this is fixing the error
return url_in_page_source
and immediately after the return statement when I'm trying to visit extracted url by driver.get() I'm getting this error:
Message: no such window: target window already closed
from unknown error: web view not found
However I have found out that adding a simple time.sleep(10) just before return statement is fixing the issue, but what is more strange to me - when I have tried to lower the wait time just below 10 secs the error is still existing. I have no idea why it is happening. Maybe I'm doing something wrong. I will be very grateful for any help and explanations.
Edit:
Here's source code of the eu.look_for_url_in_page_source() as per #JeffC request
def look_for_url_in_page_source(page_html, left_url_delimiter, right_url_delimiter):
print('Processing URL with f:look_for_url_in_page_source()')
# extracts multiple URLs from page_source
extracted_urls = []
while True:
# check if delimiters are present in page_html
find_left_url_delimiter = page_html.find(left_url_delimiter)
find_right_url_delimiter = page_html.find(right_url_delimiter)
if find_left_url_delimiter == -1 or find_right_url_delimiter == -1:
if len(extracted_urls) > 0:
return extracted_urls
print('f:look_for_url_in_page_source() was not able to get any text.')
return False
left_url_delimiter_pos = find_left_url_delimiter + len(left_url_delimiter)
right_url_delimiter_pos = page_html[left_url_delimiter_pos:].find(right_url_delimiter) + left_url_delimiter_pos
extracted_url = page_html[left_url_delimiter_pos:right_url_delimiter_pos].strip()
extracted_urls.append(extracted_url)
page_html = page_html[right_url_delimiter_pos:]
There are a lot many process involved in the process of closing a tab and switching to the parent Browsing Context which is beyond the scope of our naked eyes. Having said that, neither
driver.switch_to.window(driver.window_handles[-1])
is an ideal way to switch to the new tab, nor
driver.switch_to.window(driver.window_handles[0])
is an ideal way to switch to the parent tab.
You can find a detailed discussion on tab switching in Open web in new tab Selenium + Python
References
A few relevant discussions:
"NoSuchWindowException: no such window: window was already closed" while switching tabs using Selenium and WebDriver through Python3
I will describe you a problem of interaction EXCEL VBA Script calling a python webscraper script, to collect an visualize financial data from the n-tv website.
It is an exercise and only private interest for me , to understand, where my mistake is. I am a beginner in programming and not a professional, so please do not be irritated by my probably very poor program style. I am just learning and this is an exercise.
First I show you my python web scraper Script based on selenium:
Screenshot
[enter image description here][1]
+
Text of code:
"""
Spyder Editor
This is a temporary script file.
"""
import time
print("ich bin überfordert")
time.sleep(3)
print("import ausgeführt")
time.sleep(3)
from selenium import webdriver
driver = webdriver.Chrome(executable_path = 'C:\Program Files\Google\chromedriver.exe')
driver.get('http:\\www.n-tv.de')
time.sleep(5)
iframe = driver.find_element_by_xpath('//*[#id="sp_message_iframe_532515"]')
driver.switch_to.frame(iframe)
button = driver.find_element_by_xpath('//*[#id="notice"]/div[3]/div[2]/button')
button.click()
time.sleep(5)
driver.refresh()
driver.implicitly_wait(15)
link = driver.find_elements_by_class_name('stock__currency')
link[0].click()
time.sleep(3)
tab2 = driver.find_elements_by_class_name("tableholder")
rows = tab2[3].find_elements_by_class_name('linked')
datei = open('textdatei.txt','a')
for row in rows:
cols = row.find_elements_by_tag_name('td')
zeichen = ""
for col in cols:
print(col.text)
zeichen = zeichen + col.text + "\t"
print(zeichen)
datei.write(zeichen + "\n")
datei.close()
driver.close()
It is based on selenium, clicks away a cookie button in an iframe, links to the target finanzdata DAX an reads out those data in a file.txt.
Then the text of the calling EXCEL VBA Script:
Sub Textdatei_Einlesen()
Dim objShell As Object
Dim PythonExe, PythonScript As String
Set objShell = VBA.CreateObject("Wscript.Shell")
Dim TextAusDatei As String
Dim Zähler As Long
Dim Tabelle As Worksheet
PythonExe = """C:\Python39\python.exe"""
PythonScript = "C:\Users\annet\ScrapeTest.py"
'PythonScript = "D:\PYTHON-Test\shell_excel.py"
Set objShell = VBA.CreateObject("Wscript.Shell")
objShell.Run PythonExe & PythonScript, 1, True
End Sub
The VBA Script is working in the kind, that a simple test python program “shell_excel.py” is called by excel, runs without problem an so far it seemed all ok.
Above As you can see, the small “shell_excel.py” counter test script is executed correctly.
Following the source code of shell_excel.py:
# -*- coding: utf-8 -*-
"""
Spyder Editor
This is a temporary script file.
"""
import time
print("ich bin überfordert")
for i in range(0,10):
print(str(i))
time.sleep(i)
print("sek: " + str(i))
print("import ausgeführt")
But the Problems arises, if the Excel VBA calls the python scraper script:
As you can see, the web scraper is called and started like the first print commad of python script.
But the rest of the lines of the python source code is not executed. After a ca half a second the prompt shell is closed without any calling of the webdriver or something else as an effect, even without any error message.
As you can see by screenshot, the scraper script is running until the first print command, but at the first imports it is finished without any result and effect.
I think there must be problems by importing selenium etc.
And that I do not understand, because if i call and run my scrape script alone under xSpider, it works fine.
I know, there would be other ways to get the data into excel sheet, but I want in ideal case only open excel, press vba run button, the scraping an other processes are starting and automaticalliy excel takes the scraped data from txt file to make graphics.
Has anyone an idea, where the problem in my python environment coud be ?
Remark again, the scraper alone works, the excel vba script alone works, the small python script to test is called correctly by excel vba, but if i switch to the selenium based script it is not executed at the import parts.
Has anyone an idea ?
I am very sorry, the screenshot as jpg files are here not imported, i don not why, it seems i have not the rights.
The python script worked sometimes but not always so I added some WebDriverWait blocks and that seems to have fixed it. The VBA is much the same except I used Exec instead of Run to capture the output.
Option Explicit
Sub Textdatei_Einlesen()
Const PyExe = "C:\Python39\python.exe"
Const PyScript = "C:\Users\annet\ScrapeTest.py"
Dim objShell As Object, objScript As Object
Set objShell = VBA.CreateObject("Wscript.Shell")
Set objScript = objShell.Exec("""" & PyExe & """ " & PyScript)
MsgBox objScript.StdOut.ReadAll(), vbInformation
End Sub
python
import time
import sys
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
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.common.exceptions import TimeoutException
URL = 'https://www.n-tv.de'
DRIVERPATH = r'C:\Program Files\Google\chromedriver.exe'
def logit(s):
log.write(time.strftime("%H:%M:%S ") + s + "\n")
# create logfile
logfile = sys.path[0] + '\\' + time.strftime('%Y-%m-%d_%H%M%S') + ".log"
log = open(logfile,'a')
# webdriver
s = Service(DRIVERPATH)
op = webdriver.ChromeOptions()
op.add_argument('--ignore-certificate-errors-spki-list')
driver = webdriver.Chrome(service=s,options=op)
print("Getting " + URL)
driver.get(URL)
try:
iframe = WebDriverWait(driver, 3).until \
(EC.presence_of_element_located((By.XPATH,'//*[#id="sp_message_iframe_532515"]')))
logit("IFrame is ready!")
except TimeoutException:
logit("Loading IFrame took too much time!")
quit()
driver.switch_to.frame(iframe)
driver.implicitly_wait(3)
button = driver.find_element(By.XPATH,'//*[#id="notice"]/div[3]/div[2]/button')
button.click()
time.sleep(2)
driver.refresh()
try:
WebDriverWait(driver, 5).until \
(EC.presence_of_all_elements_located((By.CLASS_NAME,'stock__currency')))
logit("Page is ready!")
except TimeoutException:
logit("Loading Page took too much time!")
driver.quit()
quit()
link = driver.find_elements(By.CLASS_NAME,'stock__currency')
link[0].click()
try:
WebDriverWait(driver, 5).until \
(EC.presence_of_all_elements_located((By.CLASS_NAME,'tableholder')))
logit("Table is ready!")
except TimeoutException:
logit("Loading Table took too much time!")
driver.quit()
quit()
# find table
tab2 = driver.find_elements(By.CLASS_NAME,"tableholder")
rows = tab2[3].find_elements(By.CLASS_NAME,'linked')
# create text file
datei = open('textdatei.txt','a')
# write to text file
for row in rows:
logit(row.get_attribute('innerHTML'))
cols = row.find_elements(By.TAG_NAME,'td')
zeichen = ""
for col in cols:
zeichen = zeichen + col.text + "\t"
datei.write(zeichen + "\n")
# exit
datei.close()
log.close()
driver.quit()
print("Ended see logfile " + logfile)
quit()
def get_status(driver):
try:
driver.execute(Command.STATUS)
return "Alive"
except (socket.error, httplib.CannotSendRequest):
return "Dead"
if get_status(driver) == 'Alive':
#using this opens a whole new window but i want to go to another website in same tab.
driver.get('https://www.amazon.in')
else :
driver.get('https://www.google.in')
so basically i want to open a new url in the active tab of chrome/firefox browser. but i failed to find any workaround. i hope you can answer this question.
all tutorials on this redirect me to java function
driver.navigate.to()
which is not working in python.
This code did open a new URL within the same tab.
from selenium import webdriver
from selenium.webdriver.remote.command import Command
import http.client as httplib
import socket
def get_status(driver):
try:
driver.execute(Command.STATUS)
return "Alive"
except (socket.error, httplib.CannotSendRequest):
return "Dead"
driver = webdriver.Chrome(executable_path="path to chromedriver.exe")
driver.maximize_window()
driver.implicitly_wait(20)
driver.get("https://www.youtube.com/")
if get_status(driver) == 'Alive':
# using this opens a whole new window but i want to go to another website in same tab.
driver.get('https://www.amazon.in')
else:
driver.get('https://www.google.in')
driver.quit()
I wrote a script to find the download link through a series of click, first on the settings gear icon then on the "Export data" tab and finally on the click here to download data link.
However when i click on the final link it does not download the data to my specified default directory.
**ideally i would like to download the data directly to a variable but i couldn't even figure out the why the general download wasn't working.
I have tried getting the href from the download link and opening a new tab using that url but it still gives me nothing
URL = 'https://edap.epa.gov/public/single/?appid=73b2b6a5-70c6-4820-b3fa-186ac094f10d&sheet=1e76b65b-dd6c-41fd-9143-ba44874e1f9d'
DELAY = 10
def init_driver(url):
options = webdriver.chrome.options.Options()
path = '/Users/X/Applications/chromedriver'
options.add_argument("--headless")
options.add_argument("download.default_directory=Users/X/Python/data_scraper/epa_data")
driver = webdriver.Chrome(chrome_options= options, executable_path=path)
driver.implicitly_wait(20)
driver.get(url)
return driver
def find_settings(web_driver):
#find the settings gear
#time.sleep(10)
try:
driver_wait = WebDriverWait(web_driver,10)
ng_scope = driver_wait.until(EC.visibility_of_element_located((By.CLASS_NAME,"ng-scope")))
settings = web_driver.find_element_by_css_selector("span.cl-icon.cl-icon--cogwheel.cl-icon-right-align")
print(settings)
settings.click()
#export_data = web_driver.find_elements_by_css_selector("span.lui-list__text.ng-binding")
#print(web_driver.page_source)
except Exception as e:
print(e)
print(web_driver.page_source)
def get_settings_list(web_driver):
#find the export button and download data
menu_item_list = {}
find_settings(web_driver)
#print(web_driver.page_source)
try:
time.sleep(8)
print("got menu_items")
menu_items = web_driver.find_elements_by_css_selector("span.lui-list__text.ng-binding")
for i in menu_items:
print(i.text)
menu_item_list[i.text] = i
except Exception as e:
print(e)
return menu_item_list
def get_export_data(web_driver):
menu_items = get_settings_list(web_driver)
print(menu_items)
export_data = menu_items['Export data']
export_data.click()
web_driver.execute_script("window.open();")
print(driver.window_handles)
main_window = driver.window_handles[0]
temp_window = driver.window_handles[1]
driver.switch_to_window(main_window)
time.sleep(8)
download_data = driver.find_element_by_xpath("//a[contains(text(), 'Click here to download your data file.')]")
download_href = download_data.get_attribute('href')
print(download_href)
download_data.click()
driver.switch_to_window(temp_window)
driver.get("https://edap.epa.gov"+download_href)
print(driver.page_source)
driver = init_driver(URL)
#get_settings_list(driver)
get_export_data(driver)
I would like to have this code emulate the manual action of clicking the settings gear icon, then export data then download data which downloads data in a csv (ideally i want to skip the file and put in a pandas dataframe, but that an issue for another time)
For security reasons, Chrome will not allow downloads while running headless. Here's a link to some more information and a possible workaround.
Unless you need to use Chrome, Firefox will allow downloads while headless - albeit with some tweaking.
There is a link on my tested page which is opened in new TAB by default. I need to open the link and verify some values on the newly opened page.
As I found selenium does not support working with tabs, so I am trying to open the link in new window, but it still does not work..
I implemented python function to hold SHIFT key (I have done this before for CTRL and it works) and then I called "click" function, but the link is still being opened in new tab
from robot.libraries.BuiltIn import BuiltIn
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
class CustomSeleniumLibrary(object):
def __init__(self):
self.driver = None
self.library = None
self.ac = None
def get_library_instance(self):
if self.library is None:
self.library = BuiltIn().get_library_instance('ExtendedSelenium2Library')
return self.library
def get_action_chain(self):
if self.ac is None:
self.ac = ActionChains(self.get_library_instance()._current_browser())
return self.ac
def hold_shift(self):
actionChain = self.get_action_chain()
actionChain.key_down(Keys.SHIFT)
actionChain.perform()
The robot keyword is
Open project detail
wait until element is visible ${LINK_TO_PROJECT}
${project}= get text ${LINK_TO_PROJECT}
hold shift
click element ${LINK_TO_PROJECT}
#sleep 2s
#release shift
element should contain //h3 Project Details: ${project}
I tried many variants with sleeps, releasing the key etc. but it never really opens the link in new window. I also tried to verify the data in newly opened tab (without trying to open in new window), but it is always redirected into original tab very quickly so the DOM on new tab is not loaded yet.. Thanks for any suggestion!
You can use below code to handle page opened in new tab:
current = driver.current_window_handle
driver.find_element_by_css_selector('a').click() # use own selector
new_tab = [tab for tab in driver.window_handles if tab != current][0]
driver.switch_to.window(new_tab)
# do some actions
driver.close()
driver.switch_to.window(current)
Also you can make little hack (not recommended, but...) to avoid handling new tabs and force link to open in the current tab:
link = driver.find_element_by_css_selector('a')
driver.execute_script('arguments[0].target="_self";', link)