Как я могу подключиться к браузеру, открытому веб-драйвером с селеном?
По некоторым неизвестным причинам мой браузер очень медленно открывает тестовые страницы моего удаленного сервера. Поэтому я думаю, смогу ли я снова подключиться к браузеру после выхода из скрипта, но не выполню webdriver.quit()
это оставит браузер открытым. Это, вероятно, вид крючка или ручки веб-драйвера. Я просмотрел документацию по selenium API, но не нашел никакой функции. Я использую Chrome 62,x64, Windows 7, Селен 3.8.0. Я буду очень признателен за решение вопроса.
7 ответов
Нет, вы не можете подключиться к предыдущему Web Browser
сессия после выхода из сценария. Даже если вы можете извлечь Session ID
, Cookies
и другие атрибуты сеанса из предыдущего Browsing Session
тем не менее вы не сможете передать эти атрибуты как КРЮК на WebDriver
,
Более чистым способом было бы позвонить webdriver.quit()
а затем охватить новый Browsing Session
,
История:
Ранее были некоторые обсуждения и попытки восстановить WebDriver
в существующий текущий сеанс просмотра. Вы можете найти обсуждения в этих QA:
Allow webdriver to attach to a running browser
[docs] webdriver.firefox.useExisting not implemented
Это на самом деле легко сделать - сеанс SE представлен URL-адресом соединения и session_id.
Отказ от ответственности - в этом подходе используются внутренние свойства селена (в некотором роде "частные"), которые могут изменяться в новых выпусках; вам лучше не использовать его для производственного кода; Лучше не использовать его против удаленного SE (вашего хаба или провайдера, такого как BrowserStack/Sauce Labs), потому что в конце объясняется утечка предостережений / ресурсов.
Например, не используйте его в вашем конкретном случае, если вы не уверены, что он вам нужен:)
Когда запускается экземпляр веб-драйвера, вам необходимо получить вышеупомянутые свойства; образец:
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 автоматически запускает для него новый сеанс (который начался где-то около Selenium3, хотя я не уверен в точном времени) - и теперь у вас есть 1 процесс с двумя сеансами.
Если вы перейдете к URL-адресу, вы увидите, что он выполняется на том новом экземпляре браузера, а не на том, который остался от предыдущего запуска, что не является желаемым поведением. На этом этапе необходимо сделать две вещи: а) закрыть текущий сеанс SE и б) переключить этот экземпляр на предыдущий сеанс:
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/')
И это все - теперь вы подключены к предыдущему / уже существующему сеансу со всеми его свойствами (куки, LocalStorage и т. Д.). Вы не должны предоставлять desired_capabilities
при запуске нового удаленного драйвера - они сохраняются и наследуются от существующего сеанса, который вы установили.
Предостережение - запуск процесса SE может привести к некоторому истощению ресурсов в системе.
Всякий раз, когда один запускается, а затем не закрывается - как в первом фрагменте кода - он будет оставаться там до тех пор, пока вы не убьете его вручную. Под этим я подразумеваю - например, в Windows - вы увидите процесс "chromedriver.exe", который необходимо завершить вручную, как только закончите с ним. Он не может быть закрыт драйвером, который подключился к нему, как к процессу удаленного селена.
Причина - всякий раз, когда вы запускаете локальный экземпляр браузера, а затем вызываете его quit()
метод, он состоит из 2 частей - первая состоит в том, чтобы удалить сеанс из экземпляра Selenium (что было сделано во второй части кода там), а другая - остановить локальную службу (chrome/geckodriver) - что в целом работает нормально.
Дело в том, что для удаленных сеансов отсутствует вторая часть - ваш локальный компьютер не может управлять удаленным процессом, это работа центра удаленного управления. Так что вторая часть буквально pass
Заявление Python - нет оп.
Если вы запустите слишком много служб Selen на удаленном концентраторе и не будете управлять им - это приведет к истощению ресурсов с этого сервера. Облачные провайдеры, такие как BrowserStack, принимают меры против этого - они закрывают сервисы без активности в течение последних 60-х и т. Д., И все же - это то, что вы не хотите делать.
А что касается локальных сервисов SE - просто не забывайте время от времени очищать ОС от потерянных драйверов селена, о которых вы забыли:)
для Chromium вы можете получить список запущенных процессов браузера, проверить командную строку этого процесса и выполнить поиск «--remote-debugging-port=", извлечь этот номер порта и использовать его при инициализации веб-драйвера.
установите DriverOptions на
ChromiumOptions.DebuggerAddress = "127.0.0.1:" & remotePort
без каких-либо других опций установите инициировать
driver As IWebDriver = New EdgeDriver(driverService, ChromiumOptions, CommandTimeout)
та часть VB.net, которая мне подходит, но я думаю, что ее можно перевести и использовать и на других языках.
и используйте драйвер как обычно. вы можете продолжить с того места, где страница осталась открытой, или создать известное окно и закрыть старое, если вам нравится своего рода новый старт, но с предыдущими файлами cookie и кешем.
возможно, вы захотите завершить старые процессы «webdriver.exe», потому что при каждом повторном подключении он будет порождать известный.
таким образом вы имитируете поведение реального пользователя, поскольку обычные пользователи не всегда просматривают сайты конфиденциально. они вернулись на ваш сайт со старыми файлами cookie и данными в кеше. поэтому вы можете оптимизировать свой сайт для правильной работы со старыми кэшированными ресурсами и найти способы, при которых пользователю не нужно принудительно перезагружать сайт или очищать кеш каждый раз, когда сайт получает обновление.
ОК, после смешивания различных решений, представленных здесь, и настройки, теперь это работает, как показано ниже. Сценарий будет использовать ранее оставленное открытое окно Chrome, если оно присутствует — удаленное соединение вполне может убить браузер, если это необходимо, и код работает нормально.
Мне бы хотелось, чтобы можно было автоматизировать получение идентификатора session_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'
Я нашел частичный ответ в этом дублирующемся потоке и определение класса в другом потоке stackoverflow, который сейчас не могу найти. Раскомментируйте первые 5 строк и закомментируйте последние 2. Затем сделайте обратное и добавьте свой URL и sessionID .
РЕДАКТИРОВАТЬ: это работает, только если вы запустите первую часть в отдельном терминале. Вы можете запустить вторую часть в другом терминале и использовать ее столько раз, сколько захотите.
Спасибо оригинальному автору, который положил начало этой теме, и это обсуждение оказалось для меня очень полезным, поскольку я смог применить свои навыки Python для конкретного случая использования.
Я попробовал метод Тодора, опубликованный выше, но безуспешно со следующей установкой OS = Mac OS Ventura; Питон = 3.10.4; ЮВ = 4.12.0
Однако я нашел этот метод Шабада , который оказался полезным.
Вот мой код для вышеуказанных настроек, который работал более элегантно
Apple Script для запуска нового сеанса с определенным профилем
do shell script "open -a /Applications/Microsoft\\ Edge.app --args --remote-debugging-port=9222 --user-data-dir='~/seEdge'"
Код Python для прикрепления к этому сеансу
# 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()
как вы упомянули сами. Вопрос здесь, хотя рамки, которые идут со своим собственным бегуном? Как огурец?
В любом случае у вас должен быть какой-то код "настройки" и "очистки". Поэтому вам нужно убедиться, что на этапе "очистки" браузер вернулся в исходное состояние. Это означает:
- Пустая страница отображается
- Куки стираются за сеанс