我有一个 Selenium 测试套件,它运行许多测试,并且在每个新测试中,它都会在我打开的任何其他窗口之上打开一个浏览器窗口。在本地环境中工作时非常不和谐。有没有办法告诉 Selenium 或操作系统(Mac)在后台打开窗口?
18 回答
如果您在 Python 中使用 Selenium Web 驱动程序,则可以使用 PyVirtualDisplay,它是 Xvfb 和 Xephyr 的 Python 包装器。
PyVirtualDisplay 需要 Xvfb 作为依赖项。在Ubuntu上,首先安装 Xvfb:
sudo apt-get install xvfb
然后从PyPI安装 PyVirtualDisplay :
pip install pyvirtualdisplay
使用 PyVirtualDisplay 以无头模式在 Python 中使用 Selenium 脚本示例:
#!/usr/bin/env python
from pyvirtualdisplay import Display
from selenium import webdriver
display = Display(visible=0, size=(800, 600))
display.start()
# Now Firefox will run in a virtual display.
# You will not see the browser.
browser = webdriver.Firefox()
browser.get('http://www.google.com')
print browser.title
browser.quit()
display.stop()
编辑
最初的答案是在 2014 年发布的,现在我们正处于 2018 年的风口浪尖。和其他一切一样,浏览器也在进步。Chrome 现在有一个完全无头的版本,无需使用任何第三方库来隐藏 UI 窗口。示例代码如下:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
CHROME_PATH = '/usr/bin/google-chrome'
CHROMEDRIVER_PATH = '/usr/bin/chromedriver'
WINDOW_SIZE = "1920,1080"
chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--window-size=%s" % WINDOW_SIZE)
chrome_options.binary_location = CHROME_PATH
driver = webdriver.Chrome(executable_path=CHROMEDRIVER_PATH,
chrome_options=chrome_options
)
driver.get("https://www.google.com")
driver.get_screenshot_as_file("capture.png")
driver.close()
有几种方法,但它不是简单的“设置配置值”。除非你投资一个不适合每个人要求的无头浏览器,否则它有点像 hack:
如何隐藏 Firefox 窗口(Selenium WebDriver)?
和
您可以“据说”将一些参数传递给 Chrome,具体来说:--no-startup-window
请注意,对于某些浏览器,尤其是 Internet Explorer,如果不让它在焦点上运行会损害您的测试。
你也可以用AutoIt破解一下,一旦它打开就隐藏窗口。
Chrome 57 可以选择传递 --headless 标志,这会使窗口不可见。
此标志与 --no-startup-window 不同,因为最后一个不启动窗口。如本页所述,它用于托管后台应用程序。
将标志传递给 Selenium webdriver (ChromeDriver) 的 Java 代码:
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless");
ChromeDriver chromeDriver = new ChromeDriver(options);
要在没有任何浏览器的情况下运行,您可以在无头模式下运行它。
我向你展示了一个现在对我有用的 Python 示例
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("headless")
self.driver = webdriver.Chrome(executable_path='/Users/${userName}/Drivers/chromedriver', chrome_options=options)
我还在 Google 官方网站https://developers.google.com/web/updates/2017/04/headless-chrome中添加了更多关于此的信息
我在 Windows 中为 Firefox 使用了这段代码并得到了答案(参考这里):
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
Options = Options()
Options.headless = True
Driver = webdriver.Firefox(options=Options, executable_path='geckodriver.exe')
Driver.get(...)
...
但我没有为其他浏览器测试它。
Since Chrome 57 you have the headless argument:
var options = new ChromeOptions();
options.AddArguments("headless");
using (IWebDriver driver = new ChromeDriver(options))
{
// The rest of your tests
}
The headless mode of Chrome performs 30.97% better than the UI version. The other headless driver PhantomJS delivers 34.92% better than the Chrome's headless mode.
PhantomJSDriver
using (IWebDriver driver = new PhantomJSDriver())
{
// The rest of your test
}
The headless mode of Mozilla Firefox performs 3.68% better than the UI version. This is a disappointment since the Chrome's headless mode achieves > 30% better time than the UI one. The other headless driver PhantomJS delivers 34.92% better than the Chrome's headless mode. Surprisingly for me, the Edge browser beats all of them.
var options = new FirefoxOptions();
options.AddArguments("--headless");
{
// The rest of your test
}
This is available from Firefox 57+
The headless mode of Mozilla Firefox performs 3.68% better than the UI version. This is a disappointment since the Chrome's headless mode achieves > 30% better time than the UI one. The other headless driver PhantomJS delivers 34.92% better than the Chrome's headless mode. Surprisingly for me, the Edge browser beats all of them.
Note: PhantomJS is not maintained any more!
在 Windows 上,您可以使用 win32gui:
import win32gui
import win32con
import subprocess
class HideFox:
def __init__(self, exe='firefox.exe'):
self.exe = exe
self.get_hwnd()
def get_hwnd(self):
win_name = get_win_name(self.exe)
self.hwnd = win32gui.FindWindow(0,win_name)
def hide(self):
win32gui.ShowWindow(self.hwnd, win32con.SW_MINIMIZE)
win32gui.ShowWindow(self.hwnd, win32con.SW_HIDE)
def show(self):
win32gui.ShowWindow(self.hwnd, win32con.SW_SHOW)
win32gui.ShowWindow(self.hwnd, win32con.SW_MAXIMIZE)
def get_win_name(exe):
''' Simple function that gets the window name of the process with the given name'''
info = subprocess.STARTUPINFO()
info.dwFlags |= subprocess.STARTF_USESHOWWINDOW
raw = subprocess.check_output('tasklist /v /fo csv', startupinfo=info).split('\n')[1:-1]
for proc in raw:
try:
proc = eval('[' + proc + ']')
if proc[0] == exe:
return proc[8]
except:
pass
raise ValueError('Could not find a process with name ' + exe)
例子:
hider = HideFox('firefox.exe') # Can be anything, e.q., phantomjs.exe, notepad.exe, etc.
# To hide the window
hider.hide()
# To show again
hider.show()
但是,此解决方案存在一个问题 - 使用 send_keys 方法会显示窗口。您可以使用不显示窗口的 JavaScript 来处理它:
def send_keys_without_opening_window(id_of_the_element, keys)
YourWebdriver.execute_script("document.getElementById('" + id_of_the_element + "').value = '" + keys + "';")
我建议使用PhantomJS。欲了解更多信息,您可以访问幻影官方网站。
据我所知,PhantomJS 仅适用于 Firefox ......
下载 PhantomJs.exe 后,您需要将其导入您的项目,如下图 PhantomJS 所示。
我把我的放在里面: common → Library → phantomjs.exe
现在,您在 Selenium 代码中要做的就是更改行
browser = webdriver.Firefox()
像这样的东西
import os
path2phantom = os.getcwd() + "\common\Library\phantomjs.exe"
browser = webdriver.PhantomJS(path2phantom)
PhantomJS 的路径可能会有所不同......随心所欲地改变:)
这个技巧对我有用,我很确定它也对你有用;)
It may be in options. Here is the identical Java code.
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setHeadless(true);
WebDriver driver = new ChromeDriver(chromeOptions);
如果您使用的是 Google Chrome 驱动程序,则可以使用这个非常简单的代码(它对我有用):
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_argument("--headless")
driver = webdriver.Chrome('chromedriver2_win32/chromedriver.exe', options=chrome_options)
driver.get('https://www.anywebsite.com')
这是一个简单的Node.js解决方案,适用于 Selenium 的新版本 4.x(也可能是 3.x)。
铬合金
const { Builder } = require('selenium-webdriver')
const chrome = require('selenium-webdriver/chrome');
let driver = await new Builder().forBrowser('chrome').setChromeOptions(new chrome.Options().headless()).build()
await driver.get('https://example.com')
火狐
const { Builder } = require('selenium-webdriver')
const firefox = require('selenium-webdriver/firefox');
let driver = await new Builder().forBrowser('firefox').setFirefoxOptions(new firefox.Options().headless()).build()
await driver.get('https://example.com')
整个事情只是在后台运行。这正是我们想要的。
在 *nix 上,您还可以运行 Xvfb 之类的无头 X Window 服务器并将DISPLAY环境变量指向它:
实现此目的的一种方法是在无头模式下运行浏览器。这样做的另一个优点是测试执行得更快。
请在下面找到代码以在 Chrome 浏览器中设置无头模式。
package chrome;
public class HeadlessTesting {
public static void main(String[] args) throws IOException {
System.setProperty("webdriver.chrome.driver",
"ChromeDriverPath");
ChromeOptions options = new ChromeOptions();
options.addArguments("headless");
options.addArguments("window-size=1200x600");
WebDriver driver = new ChromeDriver(options);
driver.get("https://contentstack.built.io");
driver.get("https://www.google.co.in/");
System.out.println("title is: " + driver.getTitle());
File scrFile = ((TakesScreenshot) driver)
.getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("pathTOSaveFile"));
driver.quit();
}
}
如果您使用的是 Ubuntu (Gnome),一种简单的解决方法是安装 Gnome 扩展自动移动窗口:https ://extensions.gnome.org/extension/16/auto-move-windows/
然后将浏览器(例如 Chrome)设置为另一个工作区(例如 Workspace 2)。浏览器将在其他工作区静默运行,不再打扰您。您仍然可以在工作区中使用 Chrome,而不会受到任何干扰。
我的 chromedriver 使用 Python 时遇到了同样的问题,options.add_argument("headless")对我不起作用,但后来我意识到如何修复它,所以我将它引入下面的代码:
opt = webdriver.ChromeOptions()
opt.arguments.append("headless")
这是一个对我有用的 .NET 解决方案:
在http://phantomjs.org/download.html下载 PhantomJS 。
从下载文件夹中的 bin 文件夹中复制 .exe 文件,并将其粘贴到 Visual Studio 项目的 bin 调试/发布文件夹中。
添加这个使用
using OpenQA.Selenium.PhantomJS;
在您的代码中,像这样打开驱动程序:
PhantomJSDriver driver = new PhantomJSDriver();
using (driver)
{
driver.Navigate().GoToUrl("http://testing-ground.scraping.pro/login");
// Your code here
}
只需添加一个简单的“无头”选项参数。
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("--headless")
driver = webdriver.Chrome("PATH_TO_DRIVER", options=options)
用它 ...
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.headless = True
driver = webdriver.Chrome(CHROMEDRIVER_PATH, chrome_options=options)