是的,这实际上很容易做到。
一个 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 服务 - 只是不要忘记偶尔从您忘记的孤立硒驱动程序中清理操作系统 :)