如何自动更新硒中的chromeDriver和geckDriver

时间:2019-03-26 20:04:16

标签: selenium selenium-chromedriver selenium-grid geckodriver

我在多个节点计算机上设置了硒网格,其中我在所有硒节点计算机上手动下载了chromeDriver和geckoDriver并将它们分别用于chrome和firefox浏览器。

现在,由于此 我的节点计算机上的浏览器不断更新,并且由于各个驱动程序更新是手动过程,因此它迫使我登录到每个硒节点计算机并手动更新它们。

此过程可以自动化吗?

PS:我知道可以使用dockered硒化网格来获取/拉取最新的浏览器图像及其驱动程序,但是从传统的selenium网格切换到dockerized硒化网格是另一回事,并且将需要一些时间来实现。

7 个答案:

答案 0 :(得分:2)

我认为您当前的方法不可行。新版本的浏览器发布时,对Selenium(或任何其他驱动程序)的考虑为零。一旦发布了新的浏览器更新,就有相当高的可能性将不再有适用于该版本的现有驱动程序。 Selenium团队通常需要几天的时间来发布更新的驱动程序,以匹配最新版本的浏览器。

并且由于您正在自动更新浏览器,因此您可能会自动中断Selenium测试,直到发布新的驱动程序版本或降级浏览器为止。

现在,您可能会满意,并且可以禁用浏览器的测试,直到最新的Selenium驱动程序与最新的浏览器版本一起使用为止。如果是这样,那么这里有一些解决方案:

1)(如果使用的是C#),请将驱动程序作为Nuget软件包或依赖项文件夹存储在测试解决方案中。然后,无论驱动程序在何处运行,都应自动引用该驱动程序。当您需要更新驱动程序时,您只需要将其更新到一个位置,然后检查更改。所有客户端计算机都将通过您的CI流程,提取最新的代码,其中包括该新驱动程序。

2)如果由于某种原因,您不希望驱动程序作为Nuget程序包或手动保存的依赖项存在于项目中,请让CI处理更新过程。将自动化代码指向当前正在其上运行的任何客户端计算机上某个公共目录中的驱动程序->在下载依赖关系后计算机将依赖关系存储在何处。例如;通过Windows机器上的控制台下载硒文件,会将其放在%APPDATA%“ C:\ Users \ xxxxxx \ AppData \ Roaming \ npm \ node_modules”中的某个位置。那就是您的测试解决方案应该看的地方。

然后,在您的CI脚本中,运行任何测试之前,下载最新的驱动程序。 Windows和Linux / Unix Kernels之间的语法几乎相同,甚至不一致。假设您已经安装了npm。

npm install -g selenium

如果您已经有最新版本,则什么也不会发生。如果不这样做,则在运行测试之前,CI脚本将下载最新的驱动程序。然后,您的测试解决方案将指向驱动程序在客户端上的存储位置,并将自动使用最新的驱动程序。

答案 1 :(得分:0)

现在,该问题已通过here<body> <c:forEach items="${jsonData1}" var="list"> ${list.name} ${list.rating} </c:forEach> <c:forEach items="${jsonData2}" var="list"> ${list.reviews} </c:forEach> </body> 模块解决了

说明:

  

Python模块,方便下载和部署WebDriver二进制文件。该模块中的类可用于自动搜索和下载WebDriver二进制文件的最新版本(或特定版本),然后通过将其复制或符号链接到Selenium或其他工具应具有的位置来提取它并将其放置。找到它。

希望有帮助!

答案 2 :(得分:0)

我知道这是一个古老的问题,但是我认为这对人们也有帮助:https://github.com/rosolko/WebDriverManager.Net。它的Nuget程序包(https://www.nuget.org/packages/WebDriverManager/)似乎可以使用.NET解决问题。

答案 3 :(得分:0)

First @Asyranok is right,即使已实施的自动更新代码在100%的时间内都无法使用。但是,对于我们许多人来说,偶尔的停机时间是“确定的”,只要只有几天。

我发现每隔几个月手动更新X个服务器会令人非常恼火,而硒网站上有well written instructions关于如何“自动更新”驱动程序,我还没有看到一个公开可用的驱动程序本指南的非图书馆实施。

我的回答特定于C#,对于该语言,通常建议的解决方案是use NuGet自动拉最新的驱动程序,这有两个问题:

  1. 您需要以chrome更新的频率进行部署(大多数公司都还没有,我们也没有),否则您的应用在chrome更新和您的“新”版本之间的时间将被“破坏”。应用程序部署,并且只有在按计划发布时,临时发布时,才需要经历一系列手动步骤来更新,构建,发布等,才能使应用程序再次运行。 / p>

  2. 您需要(通常为without a work around)从NuGet中手动拉出最新的chromedrive,这也是手动操作。

最好使用python和@leminhnguyenHUST suggests使用的库,该库将在运行时自动提取最新的chromedriver。我环顾四周,还没有找到任何可用于C#的东西,因此我决定自己动手并将其构建到我的应用程序中:

public void DownloadLatestVersionOfChromeDriver()
{
    string path = DownloadLatestVersionOfChromeDriverGetVersionPath();
    var version = DownloadLatestVersionOfChromeDriverGetChromeVersion(path);
    var urlToDownload = DownloadLatestVersionOfChromeDriverGetURLToDownload(version);
    DownloadLatestVersionOfChromeDriverKillAllChromeDriverProcesses();
    DownloadLatestVersionOfChromeDriverDownloadNewVersionOfChrome(urlToDownload);
}

public string DownloadLatestVersionOfChromeDriverGetVersionPath()
{
    //Path originates from here: https://chromedriver.chromium.org/downloads/version-selection            
    using (RegistryKey key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe"))
    {
        if (key != null)
        {
            Object o = key.GetValue("");
            if (!String.IsNullOrEmpty(o.ToString()))
            {
                return o.ToString();
            }
            else
            {
                throw new ArgumentException("Unable to get version because chrome registry value was null");
            }
        }
        else
        {
            throw new ArgumentException("Unable to get version because chrome registry path was null");
        }
    }
}

public string DownloadLatestVersionOfChromeDriverGetChromeVersion(string productVersionPath)
{
    if (String.IsNullOrEmpty(productVersionPath))
    {
        throw new ArgumentException("Unable to get version because path is empty");
    }

    if (!File.Exists(productVersionPath))
    {
        throw new FileNotFoundException("Unable to get version because path specifies a file that does not exists");
    }

    var versionInfo = FileVersionInfo.GetVersionInfo(productVersionPath);
    if (versionInfo != null && !String.IsNullOrEmpty(versionInfo.FileVersion))
    {
        return versionInfo.FileVersion;
    }
    else
    {
        throw new ArgumentException("Unable to get version from path because the version is either null or empty: " + productVersionPath);
    }
}

public string DownloadLatestVersionOfChromeDriverGetURLToDownload(string version)
{
    if (String.IsNullOrEmpty(version))
    {
        throw new ArgumentException("Unable to get url because version is empty");
    }

    //URL's originates from here: https://chromedriver.chromium.org/downloads/version-selection
    string html = string.Empty;
    string urlToPathLocation = @"https://chromedriver.storage.googleapis.com/LATEST_RELEASE_" + String.Join(".", version.Split('.').Take(3));

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlToPathLocation);
    request.AutomaticDecompression = DecompressionMethods.GZip;

    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    using (Stream stream = response.GetResponseStream())
    using (StreamReader reader = new StreamReader(stream))
    {
        html = reader.ReadToEnd();
    }

    if (String.IsNullOrEmpty(html))
    {
        throw new WebException("Unable to get version path from website");
    }

    return "https://chromedriver.storage.googleapis.com/" + html + "/chromedriver_win32.zip";
}

public void DownloadLatestVersionOfChromeDriverKillAllChromeDriverProcesses()
{
    //It's important to kill all processes before attempting to replace the chrome driver, because if you do not you may still have file locks left over
    var processes = Process.GetProcessesByName("chromedriver");
    foreach (var process in processes)
    {
        try
        {
            process.Kill();
        }
        catch
        {
            //We do our best here but if another user account is running the chrome driver we may not be able to kill it unless we run from a elevated user account + various other reasons we don't care about
        }
    }
}

public void DownloadLatestVersionOfChromeDriverDownloadNewVersionOfChrome(string urlToDownload)
{
    if (String.IsNullOrEmpty(urlToDownload))
    {
        throw new ArgumentException("Unable to get url because urlToDownload is empty");
    }

    //Downloaded files always come as a zip, we need to do a bit of switching around to get everything in the right place
    using (var client = new WebClient())
    {
        if (File.Exists(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\chromedriver.zip"))
        {
            File.Delete(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\chromedriver.zip");
        }

        client.DownloadFile(urlToDownload, "chromedriver.zip");

        if (File.Exists(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\chromedriver.zip") && File.Exists(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\chromedriver.exe"))
        {
            File.Delete(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\chromedriver.exe");
        }

        if (File.Exists(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\chromedriver.zip"))
        {
            System.IO.Compression.ZipFile.ExtractToDirectory(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\chromedriver.zip", System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location));
        }
    }
}

然后通常我会在应用程序开始时使用这种非常骇人的调用来调用此功能,并确保最新的chromedriver可用于我的应用程序:

//This is a very poor way of determining if I "need" to update the chromedriver,     
//however I've yet to figure out a better way of doing this...
try
{
    using (var chromeDriver = SetupChromeDriver())
    {
        chromeDriver.Navigate().GoToUrl("www.google.com");
        chromeDriver.Quit();
    }
}
catch
{
    DownloadLatestVersionOfChromeDriver();
}

我相信这可以得到很大的改善,但是到目前为止,它对我来说是可行的。

注意:十字张贴Here

答案 4 :(得分:0)

基于Java的解决方案的一个选项是Bonigarcia Webdrivermanager。似乎它已内置了对远程Web驱动程序的支持,使用该drivermanager能够在selenium网格的Hub上下载最新的浏览器。检查this帖子。

答案 5 :(得分:0)

我遇到了同样的情况。我想出了以下解决方案,通过检查 Chrome 兼容性来自动更新驱动程序,

update_chromedriver.py

import zipfile

from bs4 import BeautifulSoup
import requests
import re
from selenium import webdriver
from selenium.common.exceptions import SessionNotCreatedException
from selenium.webdriver.chrome.options import Options

downloads_url = "https://chromedriver.chromium.org/downloads"
basic_downloads_path = 'https://chromedriver.storage.googleapis.com/{0}chromedriver_{1}.zip'
options = Options()
options.add_argument('--headless')
options.add_argument('--disable-gpu')

# os='win32'
os = 'linux64'
driver_executable = './driver/chromedriver'


def check_browser():
    driver = None
    try:
        driver = webdriver.Chrome(executable_path=driver_executable, options=options)
        driver.get('https://www.google.com/')
        return True
    except SessionNotCreatedException:
        return False
    finally:
        if driver is not None:
            driver.close()


def download_zip(_url):
    r = requests.get(_url, allow_redirects=True)
    open('./driver/chrome.zip', 'wb').write(r.content)
    with zipfile.ZipFile('./driver/chrome.zip') as z:
        z.extractall('./driver/')


def get_versions():
    html = requests.get(downloads_url).text
    soup = BeautifulSoup(html, "html.parser")
    versions_a = soup.find_all('a', href=re.compile('https://chromedriver.storage.googleapis.com/index.html\\?path='))
    versions = []
    for a in versions_a:
        version = a['href'].split('=', 1)[1]
        versions.append(version)
    return versions


def auto_update_driver():
    print('====> Checking current Chrome compatibility.')
    compatible = check_browser()
    print('====> It is ' + ('Compatible.' if compatible else 'Not Compatible.'))
    if not compatible:
        print('====> Trying to find alternate versions.')
        versions = get_versions()
        print(f'==> ({len(versions)}) found.')
        for version in versions:
            url = basic_downloads_path.format(version, os)
            download_zip(url)
            compatible = check_browser()
            print(f'==> Trying version {version} - {"Compatible" if compatible else "Not Compatible"}')
            if compatible:
                break
        if not compatible:
            raise Exception('Unable to upgrade chrome version. Probably you are using very old chrome version.'
                            'Please update chrome and try again!!')
<块引用>

请注意:

  1. 我的 chrome 驱动程序位于当前路径 ./driver/
  2. 这在我的 ubuntu 机器上运行。请根据您的要求进行相应更改

上述python脚本的使用

from update_chromedriver import auto_update_driver

auto_update_driver()

答案 6 :(得分:-1)

您可以使用ansible或puppet在所有节点上获取更新包