如何重新连接到 webdriver 使用 selenium 打开的浏览器?

Posted

技术标签:

【中文标题】如何重新连接到 webdriver 使用 selenium 打开的浏览器?【英文标题】:How can I reconnect to the browser opened by webdriver with selenium? 【发布时间】:2018-05-31 09:40:54 【问题描述】:

由于某些未知原因,我的浏览器打开远程服务器的测试页面非常缓慢。所以我在想我是否可以在退出脚本后重新连接到浏览器但不执行webdriver.quit() 这将使浏览器保持打开状态。它可能是一种 HOOK 或 webdriver 句柄。 我查找了 selenium API 文档,但没有找到任何功能。 我正在使用 Chrome 62、x64、windows 7、selenium 3.8.0。 问题能否解决,我将不胜感激。

【问题讨论】:

你的代码在哪里? 您是否尝试过通过使用选项“user-data-dir”而不是 webdriver 每次都创建一个新的来重用 chrome 现有的用户目录。而不是下载 chrome 将使用缓存中的内容。 @Grasshopper 这是什么黑魔法?我使用了这个 Chromeoption。它减少了大量的加载时间。我会查找这个。非常感谢。 缓存帮助页面加载如此之快 Can Selenium interact with an existing browser session?的可能重复 【参考方案1】:

,退出脚本后,您无法重新连接到之前的Web 浏览会话。即使您能够从之前的浏览上下文中提取Session IDCookies和其他会话属性,您仍然无法将这些属性作为HOOK传递em> 到WebDriver。

更简洁的方法是调用webdriver.quit(),然后跨越一个新的浏览上下文


深入研究

围绕将WebDriver 重新连接到现有的正在运行的浏览上下文 进行了大量讨论和尝试。在讨论Allow webdriver to attach to a running browserSimon Stewart [Creator WebDriver] 明确提到:

重新连接到现有的浏览上下文是浏览器特有的功能,因此不能以通用方式实现。 使用internet-explorer,可以遍历操作系统中打开的窗口并找到要附加到的正确 IE 进程。 firefox 和 google-chrome 需要在特定的模式和配置下启动,这实际上意味着只需 附加到正在运行的实例在技术上是不可能的。

tl;博士

webdriver.firefox.useExisting not implemented

【讨论】:

您完全理解并解决了我的困惑。我会做清理工作。非常感谢。【参考方案2】:

是的,这实际上很容易做到。

一个 selenium webdriver session 由一个连接 url 和 session_id 表示,你只需重新连接到一个现有的。

免责声明 - 该方法使用 selenium 内部属性(在某种程度上,“私有”),可能会在新版本中发生变化;您最好不要将其用于生产代码;最好不要用于远程 SE(您的集线器,或像 BrowserStack/Sauce Labs 这样的提供商),因为最后解释了警告/资源消耗。

webdriver实例启动时,需要获取前面提到的属性;示例:

from selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://www.google.com/')

# now Google is opened, the browser is fully functional; print the two properties
# command_executor._url (it's "private", not for a direct usage), and session_id

print(f'driver.command_executor._url: driver.command_executor._url')
print(f'driver.session_id: driver.session_id')

现在知道了这两个属性,另一个实例可以连接; “诀窍”是启动Remote 驱动程序,并提供上面的_url - 因此它将连接到正在运行的硒进程:

driver2 = webdriver.Remote(command_executor=the_known_url)  
# when the started selenium is a local one, the url is in the form 'http://127.0.0.1:62526'

运行时,您会看到一个新的浏览器窗口正在打开。 这是因为在启动驱动程序时,selenium 库会自动为其启动一个新会话 - 现在您有 1 个 webdriver 进程和 2 个会话(浏览器实例)。

如果您导航到一个 url,您会看到它是在该新浏览器实例上执行的,而不是从上一次开始时留下的那个 - 这不是所需的行为。 此时,需要做两件事 - a) 关闭当前 SE 会话(“新的”),b) 将此实例切换到上一个会话:

if driver2.session_id != the_known_session_id:   # this is pretty much guaranteed to be the case
    driver2.close()   # this closes the session's window - it is currently the only one, thus the session itself will be auto-killed, yet:
    driver2.quit()    # for remote connections (like ours), this deletes the session, but does not stop the SE server

# take the session that's already running
driver2.session_id = the_known_session_id

# do something with the now hijacked session:
driver.get('https://www.bing.com/')

而且,就是这样 - 您现在已连接到先前/已经存在的会话,以及它的所有属性(cookie、LocalStorage 等)。

顺便说一句,在启动新的远程驱动程序时,您不必提供 desired_capabilities - 它们会从您接管的现有会话中存储和继承。


警告 - 运行 SE 进程可能会导致系统中的一些资源消耗。

无论何时启动然后没有关闭 - 就像在第一段代码中一样 - 它会一直留在那里,直到你手动杀死它。我的意思是——例如在 Windows 中——你会看到一个“chromedriver.exe”进程,一旦你完成它,你必须手动终止它。它不能被连接到它的驱动程序关闭,就像远程硒进程一样。 原因 - 每当你启动一个本地浏览器实例,然后调用它的 quit() 方法时,它有两个部分 - 第一个是从 Selenium 实例中删除会话(在那里的第二个代码片段中做了什么) ,另一个是停止本地服务(chrome/geckodriver)——这通常可以正常工作。

问题是,对于远程会话,缺少第二部分 - 您的本地计算机无法控制远程进程,这是远程集线器的工作。所以第二部分实际上是一个pass python 语句 - 一个无操作。

如果您在远程集线器上启动了太多 selenium 服务,并且无法控制它 - 这将导致该服务器的资源流失。像 BrowserStack 这样的云提供商对此采取了措施——他们正在关闭过去 60 年代没有任何活动的服务,等等——这是你不想做的事情。

至于本地 SE 服务 - 只是不要忘记偶尔从您忘记的孤立硒驱动程序中清理操作系统 :)

【讨论】:

亲爱的@TodorMinakov,这里的代码没有达到我的期望。每当我运行 python 程序来选择唯一打开的窗口并在该窗口上使用 selenium 时,我都想这样做。感谢您的帮助。 为此,您需要知道(已存储)要连接的 URL - 主机:端口和会话 ID;就像上面的解释一样。如果您拥有它们,您将按照上述步骤重新连接。 嘿,因为我已经按照你的指示填写了command_executor= 'http://127.0.0.1:*****',所以sessionNumber = XXXXXXXXXXXXXXXXX也填写正确。但实际上发生的是打开了两个新窗口 [2,3] 但没有一个共享先前打开的窗口 [1] 的相同数据。所以现在打开了三个窗口 [1,2,3]。【参考方案3】:

如果您不了解为什么您认为保留打开的浏览器窗口会解决速度慢的问题,您实际上并不需要句柄来做到这一点。只需在不关闭会话的情况下继续运行测试,或者换句话说,不要像您自己提到的那样调用driver.quit()。这里的问题是自带运行器的框架吗?喜欢黄瓜吗?

无论如何,您必须有一些“设置”和“清理”代码。因此,您需要做的是确保在“清理”阶段,浏览器恢复到初始状态。这意味着:

显示空白页 会话中的 Cookie 被删除

【讨论】:

所以在这种情况下,设置代码会为您打开浏览器并导航到此页面,然后您运行所有测试,清理部分将关闭窗口和浏览器。这看起来不是一个好的做法,因为您每次都没有干净的会话添加可能的问题,但可以作为一种解决方法。如果您在教学测试后清除 cookie,也不确定页面的行为。 函数webdriver.Chrome.get(url)会等到页面完全加载完毕。这会花费很多时间来加载远程页面。所以我想打开并加载一次页面。我认为退出脚本后 webdriver 仍在后台运行。所以我想找到webdriver的句柄并重新连接到webdriver以重用打开的页面 您在我发布回复后编辑了您的评论,但看看它是否有帮助。 对此我很抱歉。*** 设置了 5 分钟的编辑时间。几乎每次我都会超时。 我的英语很差。这是我的错。

以上是关于如何重新连接到 webdriver 使用 selenium 打开的浏览器?的主要内容,如果未能解决你的问题,请参考以下文章

Selenium WebDriver 连接到 Kameleo 浏览器

如何防止流星重新连接到服务器

查找连接到所有给定标签的电影

重新连接到服务器时如何强制 Atmosphere.js 使用首选传输?

Webdriver 在 45000 毫秒后无法连接到端口 7055 上的主机 127.0.0.1

如何将查询参数添加到 BigQuery 并将其连接到 Data Studio?