webdriver.quit() ,那么浏览器将保持打开状态。这可能是一种HOOK或webdriver句柄。我查看了selenium API文档,但没有找到任何函数。我使用Chrome 62,x64,Windows 7,selenium 3.8.0。无论问题是否能够解决,我都将非常感激。
webdriver.quit() ,那么浏览器将保持打开状态。这可能是一种HOOK或webdriver句柄。我查看了selenium API文档,但没有找到任何函数。我使用Chrome 62,x64,Windows 7,selenium 3.8.0。无论问题是否能够解决,我都将非常感激。
不行,在退出脚本后你无法重新连接到之前的Web浏览会话。即使你能够从以前的浏览上下文中提取会话ID
、Cookies
和其他会话属性,你也无法将这些属性作为HOOK传递给WebDriver。
更干净的方法是调用webdriver.quit()
然后开启一个新的浏览上下文。
关于重新连接WebDriver到已经运行的浏览上下文,曾有过很多讨论和尝试。在讨论中允许WebDriver附加到运行的浏览器中,Simon Stewart [创建WebDriver] 明确指出:
- 重新连接到现有的浏览上下文是一种特定于浏览器的功能,因此无法以通用方式实现。
- 使用Internet Explorer,可以在操作系统中遍历打开的窗口并找到正确的IE进程进行附加。
- Firefox和Google Chrome需要以特定的方式和配置启动,这意味着仅附加到运行中的实例在技术上不可能。
selenium <-> webdriver会话由连接URL和session_id表示,您只需重新连接到现有会话即可。
免责声明 - 该方法使用selenium内部属性(在某种程度上为“私有”),这些属性可能会在新版本中更改;最好不要将其用于生产代码;最好不要针对远程SE(您的hub或像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库会自动为其启动一个新会话 - 现在你有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”进程,您必须在完成后手动终止它。它不能被连接到它的驱动程序关闭为远程Selenium过程。
原因 - 每当您启动本地浏览器实例,然后调用其quit()方法时,它有两个部分 - 第一个部分是从Selenium实例中删除会话(在上面的第二个代码片段中完成的内容),而另一个部分则是停止本地服务(chrome/geckodriver) - 这通常可以正常工作。
事情是,对于远程会话,第二部分缺失 - 您的本地机器无法控制远程过程,这是该远程中心的工作。因此,该第二部分实际上是一个pass
python语句 - 无操作。
如果您在远程中心上启动了太多的Selenium服务,并且无法对其进行控制 - 那将导致来自该服务器的资源耗尽。像BrowserStack这样的云提供商采取措施防止这种情况发生 - 它们关闭最近60秒内没有活动的服务等等,但 - 这是您不想做的事情。
至于本地SE服务 - 只需偶尔清理一下您忘记的孤立的Selenium驱动程序即可 :)
command_executor='http://127.0.0.1:*****'
和sessionNumber=XXXXXXXXXXXXXXXXX
。但实际上发生的是打开了两个新窗口[2,3],但没有一个窗口与先前打开的窗口[1]共享相同的数据。因此现在有三个打开的窗口[1,2,3]。 - JoeChromiumOptions.DebuggerAddress = "127.0.0.1:" & remotePort
没有设置任何其他选项,开始执行
driver As IWebDriver = New EdgeDriver(driverService, ChromiumOptions, CommandTimeout)
混合了此处分享的各种解决方案并进行了调整后,我现在已经将其工作正常如下。脚本将使用先前打开的Chrome窗口(如果存在) - 远程连接可以完全杀死浏览器(如果需要),代码功能也很好。
我希望有一种自动获取会话ID和上一个活动会话的URL的方法,而不必在上一个会话期间将它们写入文件以供使用...
这是我在这里的第一篇文章,如有违反规定之处,请多多包涵。
#Set manually - read/write from a file for automation
session_id = "e0137cd71ab49b111f0151c756625d31"
executor_url = "http://localhost:50491"
def attach_to_session(executor_url, session_id):
original_execute = WebDriver.execute
def new_command_execute(self, command, params=None):
if command == "newSession":
# Mock the response
return {'success': 0, 'value': None, 'sessionId': session_id}
else:
return original_execute(self, command, params)
# Patch the function before creating the driver object
WebDriver.execute = new_command_execute
driver = webdriver.Remote(command_executor=executor_url, desired_capabilities={})
driver.session_id = session_id
# Replace the patched function with original function
WebDriver.execute = original_execute
return driver
remote_session = 0
#Try to connect to the last opened session - if failing open new window
try:
driver = attach_to_session(executor_url,session_id)
driver.current_url
print(" Driver has an active window we have connected to it and running here now : ")
print(" Chrome session ID ",session_id)
print(" executor_url",executor_url)
except:
print("No Driver window open - make a new one")
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()),options=myoptions)
session_id = driver.session_id
executor_url = driver.command_executor._url
这是我在2023年使用的一些有效代码。Python 代码:
from selenium import webdrive
# driver = webdriver.Firefox()
# executor_url = driver.command_executor._url
# session_id = driver.session_id
# print(executor_url)
# print(session_id)
class SessionRemote(webdriver.Remote):
def start_session(self, desired_capabilities, browser_profile=None):
# Skip the NEW_SESSION command issued by the original driver
# and set only some required attributes
self.w3c = True
driver = SessionRemote(command_executor='your.executor.url', desired_capabilities=None)
driver.session_id = 'your-session-id'
我在this的重复线程上找到了部分答案,以及另一个我现在无法找到的stackoverflow线程上的类定义。取消注释前5行并注释最后2行。然后相反地添加您的URL和sessionID。
编辑:仅当您在单独的终端中运行第一部分时才起作用。您可以在另一个终端中运行第二部分,并将其重复使用多次。
do shell script "open -a /Applications/Microsoft\\ Edge.app --args --remote-debugging-port=9222 --user-data-dir='~/seEdge'"
# Python code to attach to a specific browser session
from selenium import webdriver
import time # used to add delay in the automation script
# set option to make execution of automation scripts
edge_options = webdriver.EdgeOptions()
edge_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
driver = webdriver.Edge(options=edge_options)
不谈为什么你认为保持一个开放的浏览器窗口会解决缓慢的问题,你实际上不需要一个句柄来做到这一点。只需在不关闭会话或换言之,不调用driver.quit()
的情况下继续运行测试,就可以了。不过问题是:有没有自带其自己运行器的框架?像Cucumber一样?
无论如何,你必须有一些“设置”和“清除”代码。所以你需要在“清理”阶段确保浏览器回到它的初始状态。那意味着: