如何停止由硒远程驱动程序启动的Chrome?

时间:2019-12-29 12:31:19

标签: python django selenium google-chrome celery

首先,我正在使用Django,并且正在构建一个API。例如,我的路线像api/get-some-element

browser_url = cache.get('user_%d.browser_url' % user_id)
is_browser_queued = cache.get('user_%d.browser_queued' % user_id)

if browser_url:
    capabilities = DesiredCapabilities.CHROME.copy()
    return webdriver.Remote(
        command_executor=browser_url,
        desired_capabilities=capabilities,
        options=options,
    )

if not is_browser_queued:
    run_browser.delay(user_id) # launch main chrome
    cache.set('user_%d.browser_queued' % user_id, True, None)

在首次访问该路线时,它将向Celery发送任务以启动Selenium Headless Chrome(主镀铬)。为什么我使用芹菜?因为我需要使Chrome始终运行。 (Idk更好的方法,这就是我所知道的。)

然后,对于该路由上的下一次访问,它将以Waiting chrome to launched.响应,直到执行Celery任务(chrome已正确启动)。

启动主chrome后,它将立即启动Selenium Headless Remote Driver(无Celery),此远程驱动程序的目的是访问主chrome。然后,它只是从网站中获取一些元素。

但是,完成后,远程驱动程序仍在运行。如何停止呢?

我知道诸如driver.quit()driver.close()之类的命令。但是,据我所知,它会将命令发送到主chrome,而不是发送给远程驱动程序启动的chrome。那不是我想要的。我不想退出主Chrome,只需退出由远程驱动程序启动的Chrome。

4 个答案:

答案 0 :(得分:0)

driver.close(),driver.quit(),driver.close关闭当前窗口,driver.quit关闭所有窗口,我也强烈建议您不要使用硒,因为它很慢而且是同一件事可以通过请求实现

答案 1 :(得分:0)

问题仅在于Chrome的driver.quit()方法。退出的驱动程序无法正常工作,没有杀死所有铬进程(包括子进程)。您可以做的是更改Selenium jar代码来解决此问题。

或者您可以使用finally块。

System.setProperty("webdriver.chrome.driver","/<path to chrome driver>/chromedriver");
    ChromeOptions options = new ChromeOptions();
    options.setBinary(new File("/<path to chrome >/google-chrome"));
    driver = new ChromeDriver(options);
    try
    {
        //automated steps
    }
    finally
    {
        driver.quit();
    }

答案 2 :(得分:0)

您是否正在使用多个Chrome窗口?

driver.close 应该可以工作,因为它只关闭聚焦窗口。 也许您应该尝试:

driver.switch_to.window(driver.window_handles[1])
driver.close()

在这种情况下,您应该找到要切换的特定窗口。 请让我知道是否可行

答案 3 :(得分:0)

您正在启动外部进程,并希望从另一个(不是启动它的进程)停止 python进程。为此,您可以保存进程pidname并用os.kill(pid, signal.SIGKILL)similar alternatives杀死它。


您也可以start chromedriver as a service

service = Service('/path/to/chromedriver')
service.start()
...
service.stop()

,其背面使用subprocess.Popen。正如您可能是从一个python进程/ celery worker开始,后来又从另一个python-celery worker停止一样-将service.pid保存在缓存/数据库/队列/ etc中,然后直接发送信号来处理pid,而不是执行service.stop()。 / p>

直接终止进程的一个可能的缺点-它可能无法正确执行所有清理任务(即关闭打开的套接字),可能会挂起,您可能需要更多逻辑来控制其状态等。


控制其他过程的替代方法-依靠外部服务管理器,例如 systemd docker 。这将所有流程控制逻辑(它们的配置(服务文件或Dockerfile))分开,使控制仅运行一个实例以及执行更多操作变得更加容易。

  • 使用systemd作为服务启动chromedriver作为系统服务。您可以使用pystemd
  • 从python控制
  • 或者如果您正在使用docker,请使用docker-python
  • 将chromedriver作为docker容器启动

使用这些选项,您是在告诉外部经理启动/停止服务,而不是尝试通过您的应用程序对其进行控制。

在分布式环境中,您可能需要确保仅在特定节点上启动chromedriver-即,仅让celery worker在其上侦听带有chromedriver启动任务的代理队列,或者连接到目标节点上的docker引擎,或者在其中使用node_id / tag一群/ k8s ...