class current_frame(): filename_screenshot = "" filename_htmldump = "" def main(self, LOGDIR): # # The first variable is the log directory. # ucount = 0 self.marionette = Marionette(host='localhost', port=2828) self.marionette.start_session() self.marionette.set_search_timeout(1000) # # Now loop through all the iframes, gathering details about each one. # print "" print "Iframe for 'top level' () ..." self.filename_screenshot = LOGDIR + "top_level" + ".png" self.filename_htmldump = LOGDIR + "top_level" + ".html" self.marionette.switch_to_frame() self.record_frame() frames = self.marionette.find_elements("tag name", "iframe") for fnum in range(len(frames)): # # App name is usually in the "src" attribute, so it's worth a shot.. # frame_src = frames[fnum].get_attribute("src") if frame_src != "": startpos = frame_src.index('/') + 2 stoppos = frame_src.index('.') appname = frame_src[startpos:stoppos] filename = appname else: ucount = ucount + 1 appname = "(unknown)" filename = "unknown_" + str(ucount) # # Because we call this script sometimes when we hit a Marionette issue, # these filenames may already exist (and we'd overwrite them!), so # add 'DEBUG_' to the start of the filename. # filename = "DEBUG_" + filename filename_details = LOGDIR + filename + "_iframe_details.txt" self.filename_screenshot = LOGDIR + filename + ".png" self.filename_htmldump = LOGDIR + filename + ".html" # # This iframe gives me problems sometimes, so I'm ignoring it for now. # if appname == "costcontrol": continue print "" print "Iframe for app \"" + appname + "\" ..." # # Record the iframe details (pretty verbose, but 'execute_script' # wasn't letting me use 'for' loops in js for some reason). # print " |_ iframe details saved to : " + filename_details f = open(filename_details, 'w') f.write("Attributes for this iframe ...\n") num_attribs = self.marionette.execute_script("return document.getElementsByTagName('iframe')[" + str(fnum) + "].attributes.length;") for i in range(num_attribs): attrib_name = self.marionette.execute_script("return document.getElementsByTagName('iframe')[" + str(fnum) + "].attributes[" + str(i) + "].nodeName;") attrib_value = self.marionette.execute_script("return document.getElementsByTagName('iframe')[" + str(fnum) + "].attributes[" + str(i) + "].nodeValue;") f.write(" |_ " + attrib_name.ljust(20) + ": \"" + attrib_value + "\"\n") f.close() # # Switch to this frame. # self.marionette.switch_to_frame(fnum) if appname == "keyboard": # # Take the html dump and save it to the file. # print " |_ html dump saved to : " + self.filename_htmldump f = open(self.filename_htmldump, 'w') f.write(self.marionette.page_source.encode('utf8', 'ignore')) f.close() else: self.record_frame() self.marionette.switch_to_frame() def record_frame(self): # # Take the screenshot and save it to the file. # print " |_ screenshot saved to : " + self.filename_screenshot screenshot = self.marionette.screenshot() with open(self.filename_screenshot, 'w') as f: f.write(base64.decodestring(screenshot)) f.close() # # Take the html dump and save it to the file. # print " |_ html dump saved to : " + self.filename_htmldump f = open(self.filename_htmldump, 'w') f.write(self.marionette.page_source.encode('utf8', 'ignore')) f.close()
class Puppet: MIME_TYPES = [ "application/epub+zip", "application/gzip", "application/java-archive", "application/json", "application/ld+json", "application/msword", "application/octet-stream", "application/ogg", "application/pdf", "application/rtf", "application/vnd.amazon.ebook", "application/vnd.apple.installer+xml", "application/vnd.mozilla.xul+xml", "application/vnd.ms-excel", "application/vnd.ms-fontobject", "application/vnd.ms-powerpoint", "application/vnd.oasis.opendocument.presentation", "application/vnd.oasis.opendocument.spreadsheet", "application/vnd.oasis.opendocument.text", "application/vnd.openxmlformats-officedocument.presentationml.presentation", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/vnd.visio", "application/x-7z-compressed", "application/x-abiword", "application/x-bzip", "application/x-bzip2", "application/x-csh", "application/x-freearc", "application/xhtml+xml", "application/xml", "application/x-rar-compressed", "application/x-sh", "application/x-shockwave-flash", "application/x-tar", "application/zip", "appliction/php", "audio/aac", "audio/midi audio/x-midi", "audio/mpeg", "audio/ogg", "audio/wav", "audio/webm", "font/otf", "font/ttf", "font/woff", "font/woff2", "image/bmp", "image/gif", "image/jpeg", "image/png", "image/svg+xml", "image/tiff", "image/vnd.microsoft.icon", "image/webp", "text/calendar", "text/css", "text/csv", "text/html", "text/javascript", "text/javascript", "text/plain", "text/xml", "video/3gpp", "video/3gpp2", "video/mp2t", "video/mpeg", "video/ogg", "video/webm", "video/x-msvideo" ] METHOD_CSS_SELECTOR = "css selector" NO_LOG = "-" DELETE_TARGET_FILES = ["mimeTypes.rdf", "handlers.json"] USER_DEFINED = 2 GECKO_LOG = Path(__file__).parent.resolve() def __init__(self, binary: str, profile: str): self.__has_session = False self.__auto_download = False self.__download_dir = "" if not Path(binary).is_file(): print(f"Binary {binary} Not Found") return if not Path(profile).is_dir(): print(f"Profile {profile} Not Found") return # geckodriver の log ファイル出力を抑止する self.marionette = Marionette( bin=binary, gecko_log=self.NO_LOG, profile=profile) # start_session 前にファイルを消しておかないと # 後で自動ダウンロードできない self.__delete_download_profile() # start_session しないと quit もできない self.marionette.start_session() self.__has_session = True def __enter__(self): return self def __exit__(self, ex_type, ex_value, trace): if self.has_session: self.quit() @property def has_session(self): return self.__has_session @property def auto_download(self): return self.__auto_download def __delete_download_profile(self): # mimeTypes.rdf と handlers.json に # ファイル読み込み時の動作設定が保存されている(text/plain はファイルを保存、など) # 自動ダウンロードするため既存の設定は削除する for name in self.DELETE_TARGET_FILES: p = Path(self.marionette.profile_path).joinpath(name) if p.is_file(): p.unlink() def __activate_auto_download(self): # 一度有効にすると同セッション内では無効にできない self.marionette.set_pref("browser.download.useDownloadDir", True) self.marionette.set_pref("browser.helperApps.neverAsk.saveToDisk", ",".join(self.MIME_TYPES)) self.marionette.set_pref( "browser.download.folderList", self.USER_DEFINED) self.marionette.set_pref("browser.download.lastDir", None) self.__auto_download = True @property def download_dir(self): if self.__auto_download == False: raise Exception("auto download not activated") return self.__download_dir @download_dir.setter def download_dir(self, dir: str): p = Path(dir) if not p.is_dir(): print(f"Download Dir {dir} Not Found") return full_path = str(p.resolve()) if self.__auto_download == False: self.__activate_auto_download() # self.__auto_download = True self.marionette.set_pref("browser.download.dir", full_path) self.marionette.set_pref("browser.download.downloadDir", full_path) self.__download_dir = full_path def set_download(self, dir: str): self.download_dir = dir def query_selector(self, selectors: str) -> HTMLElement: return self.marionette.find_element(self.METHOD_CSS_SELECTOR, selectors) def query_selectors(self, selectors: str) -> List[HTMLElement]: return self.marionette.find_elements(self.METHOD_CSS_SELECTOR, selectors) def wait(self, seconds: int): actions = Actions(self.marionette) actions.wait(seconds).perform() def quit(self): profile = Path(self.marionette.profile_path) self.marionette.quit(clean=True) # self.__forced_rmdir(profile) # Path(self.GECKO_LOG).unlink() self.__has_session = False def exec(self, script: str) -> Optional[str]: # script 内での記述簡略化のため mrnt = self.marionette set_download = self.set_download wait = self.wait quit = self.quit query_selector = self.query_selector query_selectors = self.query_selectors try: exec(script) return None except Exception as err: return str(err.args[0]) @classmethod def __forced_rmdir(self, p: Path): if p.is_dir(): for f in p.iterdir(): if f.is_file(): f.unlink() elif f.is_dir(): self.__forced_rmdir(f) p.rmdir()
class MarionetteHelper: """ Helper for starting firefox and for remote browsing """ def __init__(self, firefox_path, logger=None): self.logger = logger # type: logging.Logger self.client = None # type: Marionette self.ffpopen = None # type: subprocess.Popen self.ffpath = firefox_path # type: str if logger is None: self.logger = logging.getLogger("MarionetteHelper") self.logger.debug("Marionette helper init done") def _open_session(self, host='localhost', port=2828): """ Opens the session for marionette""" caps = {u'acceptInsecureCerts': True, } self.client = Marionette(host, port=port) self.client.start_session(capabilities=caps) def run_firefox(self): """ Start the firefox process""" self.logger.debug("Starting firefox process") self.ffpopen = subprocess.Popen([self.ffpath, "-marionette"]) self.logger.debug("Opening marionette session") self._open_session() def quit_firefox(self): """ Close the firefox process and close marionette session""" #self.logger.debug("Closing firefox") #self.client._send_message("Marionette:Quit") self.client._request_in_app_shutdown("eForceQuit") self.client.delete_session(False) self.client.cleanup() self.client = None # reset client state #try: # self.client.close() # try to close the window anyway #except InvalidSessionIdException: # pass #except socket.error: # pass #finally: # try: # self.logger.debug("Closing marionette session") # self.client.delete_session(False) # close client session # except InvalidSessionIdException: # pass # except socket.error: # pass # self.client = None # reset client state #self.logger.debug("Waiting for firefox to close") #for _ in range(3): # give the process 3 seconds to terminate # time.sleep(1) # self.ffpopen.poll() # if self.ffpopen.returncode is not None: # break #self.ffpopen.poll() #if self.ffpopen.returncode is None: # self.logger.warning("Firefox not closed in time, killing it!") # self.ffpopen.kill() # process was not quit in time, kill it #self.ffpopen = None # reset popen state #self.logger.debug("Firefox is closed") def ___get_client(self): """ Returns the internal marionette client object""" return self.client def navigate_to_url(self, url): """ Open an url in format of http[s]://example.com""" try: if "http" not in url: url = "http://" + url self.client.navigate(url) except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def back(self): """ Go a page backward""" try: self.client.go_back() except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def forward(self): """ Go a page forward""" try: self.client.go_forward() except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def follow_link(self, index=0): """ Click on a link""" try: links = self.client.find_elements(By.TAG_NAME, "a") links[index].click() except ElementNotVisibleException: self.logger.warning("Error: Element not visible") return False except ElementNotSelectableException: self.logger.warning("Error: Element not selectable") return False except ElementNotAccessibleException: self.logger.warning("Error: Element not accessible") return False except ElementNotInteractableException: self.logger.warning("Error: Element not interactable") return False except NoSuchElementException: self.logger.warning("Error: Element does not exist") return False except TimeoutException: self.logger.warning("Error: Timeout") return False except IndexError: self.logger.warning("Error: Out of bound") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def click_element_by_class_name(self, html_class_name): """ Click on first element via class name""" try: e = self.client.find_element(By.CLASS_NAME, html_class_name) e.click() except ElementNotVisibleException: self.logger.warning("Error: Element not visible") return False except ElementNotSelectableException: self.logger.warning("Error: Element not selectable") return False except ElementNotAccessibleException: self.logger.warning("Error: Element not accessible") return False except ElementNotInteractableException: self.logger.warning("Error: Element not interactable") return False except NoSuchElementException: self.logger.warning("Error: Element does not exist") return False except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def click_element_by_css_selector(self, css_selector): """ Click on first element via css selector""" try: e = self.client.find_element(By.CSS_SELECTOR, css_selector) e.click() except ElementNotVisibleException: self.logger.warning("Error: Element not visible") return False except ElementNotSelectableException: self.logger.warning("Error: Element not selectable") return False except ElementNotAccessibleException: self.logger.warning("Error: Element not accessible") return False except ElementNotInteractableException: self.logger.warning("Error: Element not interactable") return False except NoSuchElementException: self.logger.warning("Error: Element does not exist") return False except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def click_element_by_id(self, html_id): """ Click on first element via element id""" try: e = self.client.find_element(By.ID, html_id) e.click() except ElementNotVisibleException: self.logger.warning("Error: Element not visible") return False except ElementNotSelectableException: self.logger.warning("Error: Element not selectable") return False except ElementNotAccessibleException: self.logger.warning("Error: Element not accessible") return False except ElementNotInteractableException: self.logger.warning("Error: Element not interactable") return False except NoSuchElementException: self.logger.warning("Error: Element does not exist") return False except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def click_element_by_name(self, html_name): """ Click on first element via element name""" try: e = self.client.find_element(By.NAME, html_name) e.click() except ElementNotVisibleException: self.logger.warning("Error: Element not visible") return False except ElementNotSelectableException: self.logger.warning("Error: Element not selectable") return False except ElementNotAccessibleException: self.logger.warning("Error: Element not accessible") return False except ElementNotInteractableException: self.logger.warning("Error: Element not interactable") return False except NoSuchElementException: self.logger.warning("Error: Element does not exist") return False except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def click_element_by_tag_name(self, html_tag_name): """ Click on first element via tag name""" try: e = self.client.find_element(By.TAG_NAME, html_tag_name) e.click() except ElementNotVisibleException: self.logger.warning("Error: Element not visible") return False except ElementNotSelectableException: self.logger.warning("Error: Element not selectable") return False except ElementNotAccessibleException: self.logger.warning("Error: Element not accessible") return False except ElementNotInteractableException: self.logger.warning("Error: Element not interactable") return False except NoSuchElementException: self.logger.warning("Error: Element does not exist") return False except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def click_element_by_xpath(self, xpath): """ Click on first element via xpath""" try: e = self.client.find_element(By.XPATH, xpath) e.click() except ElementNotVisibleException: self.logger.warning("Error: Element not visible") return False except ElementNotSelectableException: self.logger.warning("Error: Element not selectable") return False except ElementNotAccessibleException: self.logger.warning("Error: Element not accessible") return False except ElementNotInteractableException: self.logger.warning("Error: Element not interactable") return False except NoSuchElementException: self.logger.warning("Error: Element does not exist") return False except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def click_element_by_link_text(self, html_link_text): """ Click on first element via link text""" try: e = self.client.find_element(By.LINK_TEXT, html_link_text) e.click() except ElementNotVisibleException: self.logger.warning("Error: Element not visible") return False except ElementNotSelectableException: self.logger.warning("Error: Element not selectable") return False except ElementNotAccessibleException: self.logger.warning("Error: Element not accessible") return False except ElementNotInteractableException: self.logger.warning("Error: Element not interactable") return False except NoSuchElementException: self.logger.warning("Error: Element does not exist") return False except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def send_keys_to_element_by_name(self, name, text): """ Sends text to an element via name""" try: e = self.client.find_element(By.NAME, name) e.send_keys(text) except ElementNotVisibleException: self.logger.warning("Error: Element not visible") return False except ElementNotSelectableException: self.logger.warning("Error: Element not selectable") return False except ElementNotAccessibleException: self.logger.warning("Error: Element not accessible") return False except ElementNotInteractableException: self.logger.warning("Error: Element not interactable") return False except NoSuchElementException: self.logger.warning("Error: Element does not exist") return False except TimeoutException: self.logger.warning("Error: Timeout") return False return True def select_window(self, index): """ Switch window via index""" try: self.client.switch_to_window(self.client.window_handles[index]) except NoSuchWindowException: self.logger.warning("Error: Window does not exist") return False return True def close_window(self): """ Close the current window""" self.client.close() # this won't close the last window, call quit_firefox instead def get_current_window_index(self): """ Get current windows index""" return self.client.window_handles.index(self.client.current_window_handle) def new_tab(self): """ Open a new empty tab""" with self.client.using_context("chrome"): self.client.find_element(By.ID, "menu_newNavigatorTab").click() def new_window(self): """ Open a new empty window""" with self.client.using_context("chrome"): self.client.execute_script("window.open();") def close_tab(self): """ Close the current tab""" self.close_window() # basically the same as close windows
class Puppet: def __init__(self, binary: str, profile: str): self.__has_marionette = False self.__auto_download = False self.__download_dir = "" if not Path(binary).is_file(): return if not Path(profile).is_dir(): return # geckodriver の log ファイル出力を抑止する NO_LOG = "-" self.marionette = Marionette(bin=binary, gecko_log=NO_LOG, profile=profile) # start_session しないと quit もできない self.marionette.start_session() self.__has_marionette = True @property def has_marionette(self): return self.__has_marionette @property def auto_download(self): return self.__auto_download def __activate_auto_download(self): # 一度有効にすると同セッション内では無効にできない # firefox52 では MIME_TYPES.rdf, firefox60 では handlers.json に # ファイルダウンロード時の動作設定が記述されている(text/plain はプログラムで開く、など) # 自動ダウンロードするため既存の設定は削除する MIME_TYPES_HANDLERS = ["MIME_TYPES.rdf", "handlers.json"] for name in MIME_TYPES_HANDLERS: p = Path(self.marionette.profile_path).joinpath(name) if p.is_file(): p.unlink() self.marionette.set_pref("browser.download.useDownloadDir", True) self.marionette.set_pref("browser.helperApps.neverAsk.saveToDisk", ",".join(MIME_TYPES)) USER_DEFINED = 2 self.marionette.set_pref("browser.download.folderList", USER_DEFINED) @property def download_dir(self): if self.__auto_download == False: raise Exception("auto download has not been activated") return self.__download_dir @download_dir.setter def download_dir(self, dir: str): p = Path(dir) if not p.is_dir(): return full_path = str(p.resolve()) if self.__auto_download == False: self.__activate_auto_download() self.__auto_download = True self.marionette.set_pref("browser.download.dir", full_path) self.__download_dir = full_path def set_download(self, dir: str): self.download_dir = dir def query_selector(self, selectors: str) -> HTMLElement: METHOD_CSS_SELECTOR = "css selector" return self.marionette.find_element(METHOD_CSS_SELECTOR, selectors) def query_selectors(self, selectors: str) -> List[HTMLElement]: METHOD_CSS_SELECTOR = "css selector" return self.marionette.find_elements(METHOD_CSS_SELECTOR, selectors) def wait(self, seconds: int): actions = Actions(self.marionette) actions.wait(seconds).perform() def quit(self): self.marionette.quit() def exec(self, script: str): # script 内での記述簡略化のため mrnt = self.marionette set_download = self.set_download wait = self.wait quit = self.quit query_selector = self.query_selector query_selectors = self.query_selectors exec(script)
except: print "Already logged" # Move to the term term = args.search # encode the term and change the space ('%20') in a '+' term = urllib.quote_plus(term, safe='') client.navigate("https://translate.wordpress.org/consistency?search=" + term + "&set=" + args.lang + "%2Fdefault") # Remove the strings different from our removeOtherStrings = "var right = document.querySelectorAll('table td:nth-child(2) .string');for (var i=0; i<right.length; i++){if(right[i].innerHTML!=='" + cgi.escape(args.remove.replace("'","\\'")) + "') {td = right[i].parentNode;tr = td.parentNode;tr.outerHTML=''}}" result = client.execute_script(removeOtherStrings) # Force to open the link in another tab with a little hack in js addTarget = "var anchors = document.querySelectorAll('table td:nth-child(2) .meta a');for (var i=0; i<anchors.length; i++){anchors[i].setAttribute('target', '_blank');}" result = client.execute_script(addTarget) # Open all the links openPages = client.find_elements(By.CSS_SELECTOR, 'table td:nth-child(2) .meta a') print('Find ' + str(len(openPages)) + ' wrong strings for ' + args.search + ' with -> ' + args.remove) i = 0 j = 0 for openPage in openPages: original_window = client.current_window_handle openPage.click() # Wait page load, glotpress is very slow time.sleep(1.5) all_tab = client.window_handles if all_tab[-1] != original_window: # Switch to the tab opened client.switch_to_window(all_tab[-1]) Wait(client).until(logged_in) i += 1 print(str(i) + ' - Switch to ' + client.find_element(By.CSS_SELECTOR, '.breadcrumb li:nth-child(3)').text)
except: print "Already logged" # Move to the term term = args.search # encode the term and change the space ('%20') in a '+' term = urllib.quote_plus(term, safe='') client.navigate("https://translate.wordpress.org/consistency?search=" + term + "&set=" + args.lang + "%2Fdefault") # Remove the strings different from our removeOtherStrings = "var right = document.querySelectorAll('table td:nth-child(2) .string');for (var i=0; i<right.length; i++){if(right[i].innerHTML!=='" + cgi.escape(args.remove.replace("'","\\'")) + "') {td = right[i].parentNode;tr = td.parentNode;tr.outerHTML=''}}" result = client.execute_script(removeOtherStrings) # Force to open the link in another tab with a little hack in js addTarget = "var anchors = document.querySelectorAll('table td:nth-child(2) .meta a');for (var i=0; i<anchors.length; i++){anchors[i].setAttribute('target', '_blank');}" result = client.execute_script(addTarget) # Open all the links openPages = client.find_elements(By.CSS_SELECTOR, 'table td:nth-child(2) .meta a') print('Find ' + str(len(openPages)) + ' wrong strings for ' + args.search + ' with -> ' + args.remove) i = 0 j = 0 for openPage in openPages: original_window = client.current_window_handle openPage.click() # Wait page load, glotpress is very slow time.sleep(1.5) all_tab = client.window_handles if all_tab[-1] != original_window: # Switch to the tab opened client.switch_to_window(all_tab[-1]) Wait(client).until(logged_in) i += 1 print(str(i) + ' - Switch to ' + client.find_element(By.CSS_SELECTOR, '.breadcrumb li:nth-child(3)').text)