WebDriver打开新标签页

27

我已经在网络和WebDriver API中搜索过了。我没有看到使用WebDriver/Selenium2.0打开新标签页的方法。

能有人确认一下我的想法吗?

谢谢, Chris。 附言:我目前看到的替代方法是要么在同一窗口加载不同的URL,要么打开新窗口。


我已经为你的具体问题添加了正确的答案,但考虑到你提到了“替代方案”,我猜想你的问题可能还有更多。如果你能提供更多背景信息,那么就可以给出更完整的答案。 - JimEvans
17个回答

35

完全有一种跨浏览器的方法可以使用webdriver来实现这一点,那些说你不能的人只是太懒惰了。首先,你需要使用WebDriver将锚标签注入到打开所需选项卡的页面中。以下是我的做法(注意:driver是一个WebDriver实例):

/**
 * Executes a script on an element
 * @note Really should only be used when the web driver is sucking at exposing
 * functionality natively
 * @param script The script to execute
 * @param element The target of the script, referenced as arguments[0]
 */
public void trigger(String script, WebElement element) {
    ((JavascriptExecutor)driver).executeScript(script, element);
}

/** Executes a script
 * @note Really should only be used when the web driver is sucking at exposing
 * functionality natively
 * @param script The script to execute
 */
public Object trigger(String script) {
    return ((JavascriptExecutor)driver).executeScript(script);
}

/**
 * Opens a new tab for the given URL
 * @param url The URL to 
 * @throws JavaScriptException If unable to open tab
 */
public void openTab(String url) {
    String script = "var d=document,a=d.createElement('a');a.target='_blank';a.href='%s';a.innerHTML='.';d.body.appendChild(a);return a";
    Object element = trigger(String.format(script, url));
    if (element instanceof WebElement) {
        WebElement anchor = (WebElement) element; anchor.click();
        trigger("var a=arguments[0];a.parentNode.removeChild(a);", anchor);
    } else {
        throw new JavaScriptException(element, "Unable to open tab", 1);
    }       
}

接下来,您需要告诉webdriver将当前窗口句柄切换到新标签页。以下是我的做法:

/**
 * Switches to the non-current window
 */
public void switchWindow() throws NoSuchWindowException, NoSuchWindowException {
    Set<String> handles = driver.getWindowHandles();
    String current = driver.getWindowHandle();
    handles.remove(current);
    String newTab = handles.iterator().next();
    locator.window(newTab);
}

完成之后,您可以使用相同的WebDriver实例与新页面上下文中的元素进行交互。完成该选项卡后,您始终可以使用类似于上面的switchWindow功能的机制返回默认的窗口上下文。我将把它作为一个让您自己去解决的练习。


2
switchWindow()函数中最后一行的locator是什么? - jamesfzhang
2
在常规的非远程版本的Webdriver中,我相信定位器只需要使用driver.switchTo(),对吗? - djangofan
6
我同意这里提供的代码能够通过WebDriver在任何给定的浏览器窗口中打开一个新标签页。然而,并不能保证某个特定的驱动程序能够控制生成的新标签页。 - JimEvans
5
@Jonathan Azoff 你如何控制打开的选项卡呢?打开一个选项卡是可行的,但如果驱动程序无法处理选项卡,这将给你带来无尽的痛苦。 - AutomatedTester
这篇 Stack Overflow 的帖子对 C# 的答案有所帮助:https://dev59.com/dW025IYBdhLWcg3wFxqa。要获取 JavaScriptExecutor,可以创建一个方法,如下所示:public static IJavaScriptExecutor Scripts(this IWebDriver driver) { return (IJavaScriptExecutor)driver; } - JabberwockyDecompiler
显示剩余2条评论

30

目前,Selenium WebDriver API 不支持在浏览器内管理选项卡。


19
给负评者:这就是项目本身给出的答案。仅仅因为它不是你喜欢的答案,不意味着它是错误的或质量差。 - JimEvans
@JimEvans,这个答案质量很差,因为它没有回答问题。下面提供的解决方法更有用。一个说“这是一个笨拙的方法”的答案总是比一个说“你不能这样做”的答案更有用。 - Ryan Lundy
1
@Kyralessa 尊敬的,我不同意。有时候合理的答案就是“你不能这样做”。在这种情况下,这是正确的。API不支持,也不会支持它。其他答案中所谓的解决方法可能会打开一个新标签页,但无法保证WebDriver能够打开新标签页。实际上,我相当确定至少有一个浏览器无法打开。与其给出任何解决方案都可以跨浏览器工作(WebDriver的主要承诺之一),还不如明确说明限制,避免误导。 - JimEvans
1
@Kyralessa 你能够在Chrome中使其工作。很好。告诉我,它也能在IE或Safari中工作吗?哦,还记得,仅因为它今天在Chrome中能够工作,由于API明确不支持,绝对没有保证它将在未来版本中继续工作。虽然很高兴你能够在某些情况下使其工作。 - JimEvans
1
没有必要重申你已经说过的话。我完全理解。我只是不同意你的观点。既然你似乎决心试图说服人们,一个由项目本身提供的答案比项目作者不能保证有效的答案更加错误或无用,并且还决心在这个问题上占据最后一言,那么我将让这成为我对此事的最后评论。 - JimEvans
显示剩余3条评论

9
        var windowHandles = webDriver.WindowHandles;
        var script = string.Format("window.open('{0}', '_blank');", url);
        scriptExecutor.ExecuteScript(script);
        var newWindowHandles = webDriver.WindowHandles;
        var openedWindowHandle = newWindowHandles.Except(windowHandles).Single();
        webDriver.SwitchTo().Window(openedWindowHandle);

这解决了我的问题,在chromedriver上打开标签页。 - janderson

4

我曾经遇到了同样的问题,并找到了答案。可以试一下。

Robot r = new Robot(); 
r.keyPress(KeyEvent.VK_CONTROL); 
r.keyPress(KeyEvent.VK_T); 
r.keyRelease(KeyEvent.VK_CONTROL); 
r.keyRelease(KeyEvent.VK_T);

它将会打开一个新的标签页,您可以在新标签页中执行您的操作。

有趣的想法。通过Selenium Grid管道能行吗? - djangofan

1

嘿@Paul和所有在Python中打开第二个标签页遇到问题的人。这是解决方案。

我不确定这是否是webdriver中的错误,还是因为它尚未与mutlitab兼容,但它肯定在使用mutlitab时表现不正常,我将展示如何修复它。

问题: 我看到不止一个问题。

第一个问题与当您打开第二个标签页时,您只能看到一个句柄而不是两个有关。

第二个问题,这就是我的解决方案所在的地方。似乎虽然句柄值仍存储在驱动程序中,但窗口由于某种原因已经失去了与其同步。

以下是通过解决第二个问题来解决问题的方法:

elem = browser.find_element_by_xpath("/html/body/div[2]/div[4]/div/a") #href link
time.sleep(2) 
elem.send_keys(Keys.CONTROL + Keys.RETURN + "2") #Will open a second tab

#solution for the 2nd issue is here    
for handle in browser.window_handles:
        print "Handle is:" + str(handle) #only one handle number
        browser.switch_to_window(handle)

time.sleep(3)

#Switch the frame over. Even if you have switched it before you need to do it again
browser.switch_to_frame("Frame") 


"""now this is how you handle closing the tab and working again with the original tab"""

#again switch window over
elem.send_keys(Keys.CONTROL + "w")
for handle in browser.window_handles:
    print "HandleAgain is:" + str(handle) #same handle number as before
    browser.switch_to_window(handle)

#again switch frame over if you are working with one
browser.switch_to_frame("Frame") 

time.sleep(3)
#doing a second round/tab
elem = browser.find_element_by_xpath("/html/body/div[2]/div[4]/div/a") #href link
time.sleep(2) 
elem.send_keys(Keys.CONTROL + Keys.RETURN + "2") #open a 2nd tab again

"""Got it? find the handle, switch over the window then switch the frame"""

对我来说它完美地工作。我可以回答问题...


1
做这个。
_webDriver.SwitchTo().Window(_webDriver.WindowHandles.Where(x => x != _webDriver.CurrentWindowHandle).First());

或者使用Last()等。

注意,窗口句柄的顺序可能与浏览器中显示的顺序不同,因此建议在执行导致新标签页打开的命令之前保留当前窗口的历史记录。然后,您可以将存储的窗口句柄与当前集合进行比较,并在列表中切换到新的窗口句柄,其中只应存在一个。


1

我们无法使用Web Driver / Selenium 2.0创建新的选项卡或处理选项卡。

您可以打开一个新窗口代替。


1

虽然没有打开新选项卡的API,但你可以创建一个稍微不同名称的WebDriver实例并传递你想要在新选项卡中打开的URL来实现。完成所需的所有操作后,关闭该选项卡并将新的driver设置为NULL,以使其不干扰Webdriver的原始实例。如果需要同时打开两个选项卡,请确保引用适当的WebDriver实例。我曾将它用于Sitecore CMS自动化,并且效果很好。


1

感谢@Jonathan Azoff提出的好主意!

以下是我在Ruby中的实现:

def open_new_window(url)
  a = @driver.execute_script("var d=document,a=d.createElement('a');a.target='_blank';a.href=arguments[0];a.innerHTML='.';d.body.appendChild(a);return a", url)
  a.click
  @driver.switch_to.window(@driver.window_handles.last)
end

1
@Test
 public void openTab() {
  //Open tab 2 using CTRL + t keys.
  driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL +"t");


 //Open URL In 2nd tab.
  driver.get("http://www.qaautomated.com/p/contact.html");

  //Call switchToTab() method to switch to 1st tab
  switchToTab(); 
}

public void switchToTab() {
  //Switching between tabs using CTRL + tab keys.
  driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL +"\t");
  //Switch to current selected tab's content.
  driver.switchTo().defaultContent();  
 } 

我们可以很容易地使用键盘事件来自动打开和切换多个标签页。这个例子是从这里引用的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接