不知什么原因,我的浏览器打开远程服务器的测试页面非常慢。所以我在想,如果我在退出脚本后能重新连接到浏览器,但不执行
webdriver.quit()
,这将使浏览器保持开放。这可能是一种HOOK或webdriver的处理方式。
我查阅了Selenium的API文档,但没有找到任何功能。
我使用的是Chrome 62, x64, windows 7, selenium 3.8.0。
我将非常感谢你的问题是否能得到解决。
如何用selenium重新连接到webdriver打开的浏览器?
No
,你不能重新连接到以前的
Web Browsing Session
在你退出脚本之后。即使你能够从以前的
Session ID
、
Cookies
和其他会话属性中提取出
Browsing Context
你仍然无法将这些属性作为一个
HOOK
to the
WebDriver
.
一个更简洁的方法是,调用
webdriver.quit()
,然后跨过一个新的
Browsing Context
.
Deep Dive
为了重新建立联系,各地已经进行了很多讨论和尝试。 WebDriver 到一个现有的运行中的 Browsing Context . In the discussion 允许webdriver附加到一个正在运行的浏览器上 西蒙-斯图尔特 [Creator WebDriver]明确提到。
Yes , that's actually quite easy to do.
A selenium <-> webdriver session is represented by a connection url and session_id, you just reconnect to an existing one.
免责声明 - 该方法是使用硒的内部属性("私有",在某种程度上),在新版本中可能会改变;你最好不要把它用于生产代码;最好不要对远程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
--这样它就会连接到正在运行的selenium进程。
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库会自动为它启动一个新的会话--现在你有一个webdriver进程,有两个会话(浏览器实例)。
如果你导航到一个网址,你会看到它是在那个新的浏览器实例上执行的,而不是在之前启动时留下的那个实例上--这不是我们想要的行为。
在这一点上,需要做两件事--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/')
就这样--你现在连接到以前/已经存在的会话,以及它的所有属性(cookies、LocalStorage等)。
顺便说一下,在启动新的远程驱动程序时,你不必提供desired_capabilities
--这些代码被储存起来,并从你接管的现有会话中继承。
注意事项- 运行SE进程会导致系统中的一些资源消耗。
每当有一个进程启动后没有关闭--就像第一段代码中的那样--它就会停留在那里,直到你手动杀死它。我的意思是,例如在Windows中,你会看到一个 "chromedriver.exe "进程,一旦你用完它,你必须手动终止它。它不能被连接到它的驱动程序关闭,因为它是一个远程的selenium进程。
原因是--每当你启动一个本地浏览器实例,然后调用它的quit()
方法时,它有2个部分--第一个部分是从Selenium实例中删除会话(上面第二段代码中所做的),另一个部分是停止本地服务(chrome/geckodriver)--这通常是可行的。
问题是,对于远程会话来说,缺少第二部分--你的本地机器不能控制一个远程进程,那是远程枢纽的工作。因此,第二部分实际上是一个pass
的python语句--一个无用的东西。
如果你在远程集线器上启动了太多的selenium服务,而又无法控制它--这将导致该服务器的资源耗尽。像BrowserStack这样的云计算供应商对此采取了措施--他们会关闭过去60年没有活动的服务,等等--这是你不想做的。
至于本地的SE服务--只要别忘了偶尔清理一下操作系统中被你遗忘的无主的Selenium驱动程序就可以了 :)
亲爱的@TodorMinakov 这段代码没有满足我的期望。我希望每当我运行python程序时,选择唯一打开的窗口并在该窗口上使用Selenium。我将感谢你的帮助。
为此,你需要知道(储存)连接的URL--host:port,以及会话ID;就像上面的解释一样。如果你有了它们,你就可以通过上述步骤重新连接。
嘿,因为我已经按照你的指示,
command_executor= 'http://127.0.0.1:*****'
被正确填写了,
sessionNumber = XXXXXXXXXXXXXXXXX
也是如此。但实际上发生的情况是,两个新的窗口[2,3]被打开了,但都没有共享之前打开的窗口[1]的相同数据。所以现在有三个打开的窗口【1,2,3】。
dmohr
:
Todor,你的方法对我来说很有效,谢谢你的分享。
Eugene S
发布于
2017-12-18
0
人赞同
不谈为什么你认为留下一个打开的浏览器窗口就能解决速度慢的问题,你其实不需要一个句柄来做到这一点。只要在不关闭会话的情况下继续运行测试,或者换句话说,不调用
driver.quit()
,正如你自己提到的那样。这里的问题是,框架是否有自己的运行器?像Cucumber?
在任何情况下,你必须有一些 "设置 "和 "清理 "代码。因此,你需要做的是,在 "清理 "阶段,确保浏览器回到初始状态。这意味着