如何阻止硒远程驱动程序启动的铬?



首先,我正在使用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)
browser_session_id = cache.get('user_%d.browser_session_id' % user_id) # session id of the main chrome
if browser_url:
capabilities = DesiredCapabilities.CHROME.copy()
driver = webdriver.Remote(
command_executor=browser_url,
desired_capabilities=capabilities,
options=options,
)
driver.session_id = browser_session_id
return driver
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无头远程驱动程序(没有Celery(,这个远程驱动程序的目的是访问主chrome。然后,它只是从网站上抓取一些元素。

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

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

driver.close((, driver.quit(( , driver.close 关闭当前窗口,driver.quit 关闭所有窗口 ,我也强烈建议你不要使用硒,它非常慢,同样的事情可以通过请求来实现

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

或者你可以利用最终阻止。

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();
}

您是否使用多个 Chrome 窗口?

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

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

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

您正在启动一个外部进程,并希望另一个(不是启动它的那个(python进程停止它。为此,您可以保存进程pidname,并使用os.kill(pid, signal.SIGKILL)或类似的替代方案杀死它。


您还可以将 chromedriver 作为服务启动:

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

在后面使用subprocess.Popen。因为您可能从一个 python 进程/芹菜工作线程开始,然后从另一个进程停止 - 将service.pid保存在缓存/数据库/队列/等中,并直接发送信号来处理 pid,而不是执行service.stop()

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


控制另一个进程的替代方案 -是依靠外部服务管理器,如systemddocker。这将所有进程控制逻辑在其配置(服务文件或 Dockerfile(中分离出来,从而更容易控制仅运行一个实例等等。

  • 使用 Systemd 即服务启动 Chrome 驱动程序即系统服务。你可以从python控制,即pystemd
  • 或者,如果您正在使用Docker-Python将ChromeDriver作为Docker容器启动

使用这些选项,您可以告诉外部管理员启动/停止服务,而不是尝试从您的应用程序控制它。

在分布式环境中,您可能希望确保 chromedriver 仅在特定节点上启动 - 即只让芹菜工人在其上侦听带有 chromedriver 启动任务的代理队列或连接到目标节点上的 docker 引擎或在 swarm/k8s 中使用 node_id/tag ...

最新更新