首先,我正在使用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。
答案 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进程。为此,您可以保存进程pid
或name
并用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))分开,使控制仅运行一个实例以及执行更多操作变得更加容易。
使用这些选项,您是在告诉外部经理启动/停止服务,而不是尝试通过您的应用程序对其进行控制。
在分布式环境中,您可能需要确保仅在特定节点上启动chromedriver-即,仅让celery worker在其上侦听带有chromedriver启动任务的代理队列,或者连接到目标节点上的docker引擎,或者在其中使用node_id / tag一群/ k8s ...