如何使用Selenium WebDriver for Python在浏览器中打开一个新窗口?

21
我尝试使用Python的Selenium在浏览器中打开一个新标签页或新窗口。无论是打开新标签页还是新窗口,都不重要,只要打开浏览器的第二个实例即可。
我已经尝试了几种不同的方法,但都没有成功。
  1. Switching to a window that does not exist with hopes that it would then open a new window upon failure to locate said window:

    driver.switch_to_window(None)

  2. Iterating through open windows (although there is currently only one)

    for handle in driver.window_handles:
        driver.switch_to_window(handle)
    
  3. Attempting to simulate a keyboard key press

    from selenium.webdriver.common.keys import Keys
    driver.send_keys(Keys.CONTROL + 'T')
    
这个特定问题的困难在于似乎无法直接将按键发送到浏览器,只能发送到类似这样的特定元素:
driver.find_element_by_id('elementID').send_keys(Keys.CONTROL + 'T')

然而,当像这样的命令被发送到一个元素时,它似乎什么都没有发生。我试图找到页面上最顶层的HTML元素并将键盘输入发送到那里,但又遭遇了失败:

driver.find_element_by_id('wrapper').send_keys(Keys.CONTROL + 'T')

我在网上找到了另一个版本,但由于不确定需要导入哪个类/模块,无法验证其有效性或无效性。

act = ActionChains(driver)
act.key_down(browserKeys.CONTROL)
act.click("").perform()
act.key_up(browserKeys.CONTROL)

这两种语法非常相似(我不确定哪一种或两种都是正确的语法)

actions.key_down(Keys.CONTROL)
element.send_keys('t')
actions.key_up(Keys.CONTROL)

仅适用于主流浏览器,比如Firefox、Chrome等。例如,PhantomJS没有键绑定,您需要使用适当的JavaScript代码调用execute_script()。如果您需要传递项目/cookie,请创建一个target=_blank链接,然后单击它即可。 - m3nda
几乎是 Open web in new tab Selenium + Python - Stack Overflow 的副本,只不过它在新标签页中打开;然而,大多数情况下,Selenium 处理标签页/窗口的方式是相同的。 - user202729
6个回答

28

你可以像这样做

driver = webdriver.Firefox() #First FF window
second_driver = webdriver.Firefox() #The new window you wanted to open

根据您希望与哪个窗口进行交互,您需要相应地发送命令

print driver.title #to interact with the first driver
print second_driver.title #to interact with the second driver

针对所有的反对者:


原帖要求"只需要打开浏览器的第二个实例即可",这个回答并不包含每个人使用情况所需的全部可能性。 下面的其他答案可能更适合您的特定需求。


1
太完美了!如此简单,却正好实现了我想要的,谢谢。不过,有没有一种方法可以将该命令概括,使其无论使用哪个浏览器都能工作?也许有一种方法可以在第一个驱动程序中推导出正在使用的浏览器,以便打开第二个驱动程序? - Zach Olivare
也许有一种方法可以在第一个驱动程序中推导出正在使用的浏览器,以打开第二个驱动程序?但我不确定这样做会增加什么价值。即使有用,我也不知道如何实现。无论如何,如果您发现此答案有帮助,请将其标记为答案,方法如下 - http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work/5235#5235 - Amey
10
这实际上会打开第二个 Firefox 窗口。对于某些测试用例来说,“在现有浏览器中打开新窗口”和“完全新的浏览器应用程序”之间的区别可能很重要。 - ManicDee
当您打开多个浏览器实例时,可能会使用大量内存。每个实例将占用超过100 MB的空间。我建议不要这样做。 - fx-kirin
2
如果您需要在共享会话等情况下打开一个新窗口怎么办?如果您只需要2个窗口并且完全不关心用户如何与浏览器交互,那么这个答案是可行的。我要给它点踩,因为“如何使用Python的Selenium WebDriver在浏览器上打开一个新窗口?”表明他们想要从现有的浏览器或驱动程序中打开一个新窗口。这就是我在谷歌上寻找的内容,而您的答案根本没有做到这一点。也许您应该包括其他方法来完成这个任务? - RattleyCooper

18

您可以使用execute_script打开新窗口。

driver = webdriver.Firefox()
driver.get("https://linkedin.com")
# open new tab
driver.execute_script("window.open('https://twitter.com')")
print driver.current_window_handle

# Switch to new window
driver.switch_to.window(driver.window_handles[-1])
print " Twitter window should go to facebook "
print "New window ", driver.title
driver.get("http://facebook.com")
print "New window ", driver.title

# Switch to old window
driver.switch_to.window(driver.window_handles[0])
print " Linkedin should go to gmail "
print "Old window ", driver.title
driver.get("http://gmail.com")
print "Old window ", driver.title

# Again new window
driver.switch_to.window(driver.window_handles[1])
print " Facebook window should go to Google "
print "New window ", driver.title
driver.get("http://google.com")
print "New window ", driver.title

4
这段话中没有提及Jquery的加载,并且你假设它是由PhantomJS加载的先前URL所载入。此外,JavaScript代码是相同的,因此只需使用 driver.execute_script("window.open('https://twitter.com')") 即可。 - m3nda
注意:这可能会在新标签页或新窗口中打开,这取决于Firefox设置。有关更多详细信息,请参阅我的答案 - user202729

9
我建议在Firefox浏览器中使用CTRL + N命令,而不是创建新的浏览器实例,这样可以减少内存的使用。
import selenium.webdriver as webdriver
from selenium.webdriver.common.keys import Keys

browser = webdriver.Firefox()
body = browser.find_element_by_tag_name('body')
body.send_keys(Keys.CONTROL + 'n')

如何切换和控制窗口已经被 Dhiraj 提到过。


1
这是最好的解决方案,因为窗口在同一驱动程序中打开。但对于XML页面,这种方法不起作用。 - Andrew_STOP_RU_WAR_IN_UA
1
@fx-kirin 在火狐浏览器中不起作用? - Maninder Singh
是的,它停止工作了。请参见https://dev59.com/lV4c5IYBdhLWcg3wAWJE#ArajEYcBWogLw_1bEwPS - user202729

1
driver = webdriver.Chrome()
driver.execute_script("window.open('');")
driver.get('first url')

driver.switch_to.window(driver.window_handles[1])
driver.get('second url')

0
driver.switch_to.new_window()

将会打开一个新窗口。

然后您可以搜索网络。

driver.get("https://google.com")

0
在JavaScript中,窗口和标签之间没有区别。 driver.window_handles 将两者都考虑在内。
然而,如果需要打开一个新窗口,有几种方法:(请参见[3]所需的导入)
  1. 模拟按下ctrl+N键。在新版本中无法使用。请参见this comment

    (
            ActionChains(driver)
            .key_down(Keys.CONTROL)
            .send_keys('n')
            .key_up(Keys.CONTROL)
            .perform()
            )
    

    或者

    body = driver.find_element_by_tag_name('body')
    body.send_keys(Keys.CONTROL + 'n')
    
  2. 按住Shift键,然后单击页面上的链接——仅当页面上有任何链接时才有效。

    (
            ActionChains(driver)
            .key_down(Keys.SHIFT)
            .click(driver.find_element_by_tag_name("a"))
            .key_up(Keys.SHIFT)
            .perform()
            )
    

    如果没有任何链接,则可以创建一个...(修改当前页面!)

    driver.execute_script('''{
        let element=document.createElement("a");
        element.href="about:home";
        element.id="abc"
        element.text="1";
        document.body.appendChild(element);
        element.scrollIntoView();
        }''')
    
    (
            ActionChains(driver)
            .key_down(Keys.SHIFT)
            .click(driver.find_element_by_id("abc"))
            .key_up(Keys.SHIFT)
            .perform()
            )
    

    ... 或导航到具有链接的页面。(如果您在会话开始时执行此操作, 或打开一个新标签页来执行此操作并稍后关闭它,则不会有问题)

    driver.get("data:text/html,<a href=about:blank>1</a>")
    (
            ActionChains(driver)
            .key_down(Keys.SHIFT)
            .click(driver.find_element_by_tag_name("a"))
            .key_up(Keys.SHIFT)
            .perform()
            )
    

    看起来像是一个hack。

  3. (对于Firefox)关闭“在新窗口中而不是新标签页中打开链接”选项, 然后执行window.open()

    来自Settings to open browser links in new tab, and external links in new window | Firefox Support Forum | Mozilla SupportBrowser.link.open_newwindow - MozillaZine Knowledge Base

    browser.link.open_newwindow - 用于Firefox选项卡中的链接

    3 = 将新窗口转到新标签页(默认)
    2 = 允许链接打开新窗口
    1 = 强制新窗口进入同一标签页

    此选项应设置为2。[2]

    请注意,根据https://github.com/SeleniumHQ/selenium/issues/2106#issuecomment-320238039-permalink 无法使用FirefoxProfile设置选项[1]。

    options=webdriver.FirefoxOptions()
    options.set_preference("browser.link.open_newwindow", 2)
    driver=Firefox(firefox_options=options)
    
    driver.execute_script("window.open()")
    
  4. 对于Selenium 4.0.0(预发布版。目前可以使用例如pip install selenium==4.0.0b4进行安装),可以执行以下操作:

    driver.execute(
        selenium.webdriver.remote.command.Command.NEW_WINDOW,
        {"type": "window"}
    )
    

    技术来自this answer


[1]:在当前版本中,由于某些原因,这个方法是可行的,并将browser.link.open_newwindow设置为2。
fp = webdriver.FirefoxProfile()
fp.set_preference("browser.link.open_newwindow", 3)
fp.default_preferences["browser.link.open_newwindow"]=3
fp.DEFAULT_PREFERENCES["browser.link.open_newwindow"]=3
driver=Firefox(firefox_profile=fp)

当这个选项值保持在3时

driver=Firefox()

[2]:如果将值设置为3window.open()将在新标签页中打开而不是新窗口。

[3]:所有必需的导入:

from selenium import webdriver
from selenium.webdriver import Firefox, FirefoxProfile
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains

[4]: 这个答案仅涵盖如何打开一个新窗口。要切换到该新窗口并返回原窗口,请使用WebDriverWaitdriver.switch_to.window(driver.window_handles[i])。有关更多详细信息,请参见https://dev59.com/lV4c5IYBdhLWcg3wAWJE#51893230


就我所记,这个解决方案在我这里是可行且正确的(除了第一个解决方案,其中指出它在新版本中不起作用)。也许有人能够解释一下出了什么问题? - user202729

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