Повторное использование существующего сеанса браузера в Selenium

Сравнение Selenium и UFT

Для тех, кто имеет опыт работы с QTP / UFT, возможность протестировать один и тот же браузер после разрыва соединения обычно несложно.

1. systemutil.run "iexplore.exe"
2. x = 2/0
3. Browser("index:=0").navigate ("http://www.google.com")

Если мы запустим приведенный выше код в QTP / UFT, он выдаст ошибку в строке № 2, и мы сможем повторно запустить код из строки № 3, и он будет работать и перемещаться внутри браузера, который мы открыли ранее.

UFT также работает, когда браузер запускается вручную, а не через скрипт. Однако в Selenium это невозможно из-за архитектурных различий.

Поскольку разработчики Selenium не видят в этом особого смысла, они категорически против добавления этого в код Selenium.

В этой статье мы увидим более чистый и эффективный способ добиться повторного использования браузера.

Запуск браузера в Selenium

Чтобы запустить браузер в Selenium с использованием Python, мы просто импортируем веб-драйвер и запускаем браузер.

from selenium import webdriver

driver = webdriver.Chrome()

Если мы запустим приведенный выше код, он запустит браузер и выйдет. Поскольку созданный нами объект браузера был уничтожен, мы больше не можем управлять этим браузером с помощью скрипта. Это зомби-браузер с точки зрения Selenium.

Теперь, когда мы создаем объект WebDriver (Firefox, сhromer или любой другой браузер) в Selenium, происходит несколько вещей:

  1. Запускается предполагаемый агент браузера (chromedriver для chrome, geckodriver для Firefox и т. Д.)
  2. Создается исполнитель команд. Этот объект отвечает за отправку команд агенту.
  3. Устанавливается новый сеанс с агентом, который, в свою очередь, связывается с браузером. session_id создается для идентификации сеанса.

Информация из шагов №2 и №3 важна для нас, чтобы мы могли воссоздать объект драйвера. Итак, давайте обновим наш скрипт, чтобы вывести эту информацию.

from selenium import webdriver
driver = webdriver.Chrome()

executor_url = driver.command_executor._url
session_id = driver.session_id

print session_id
print executor_url

driver.get("http://tarunlalwani.com")

Пример вывода приведенного выше кода приведен ниже:

7397a385-7661-0449-9e0a-902355617485
http://127.0.0.1:51259

Создание драйвера с использованием идентификатора сеанса и Command Executor

Итак, теперь у нас есть session_id и executor_url. Попробуем воссоздать сеанс.

Моей первой попыткой было создать драйвер с помощью RemoteWebDriver или WebDriver

from selenium import webdriver

driver = webdriver.Chrome()
executor_url = driver.command_executor._url
session_id = driver.session_id
driver.get("http://tarunlalwani.com")

print session_id
print executor_url


driver2 = webdriver.Remote(command_executor=executor_url, desired_capabilities={})
driver2.session_id = session_id
print driver2.current_url

Когда мы запускаем приведенный выше код, он печатает URL-адрес в конце. Это означает, что мы смогли воссоздать объект драйвера для браузера Chrome.http://tarunlalwani.com

Тестирование в браузере Firefox

Мы протестировали наш предыдущий подход в браузере Chrome. Давайте также протестируем наше решение в Firefox:

from selenium import webdriver

driver = webdriver.Firefox()
executor_url = driver.command_executor._url
session_id = driver.session_id
driver.get("http://tarunlalwani.com")

print session_id
print executor_url


driver2 = webdriver.Remote(command_executor=executor_url, desired_capabilities={})
driver2.session_id = session_id
print driver2.current_url

Ошибка  в нашем скрипте в следующем:

driver2 = webdriver.Remote(command_executor=executor_url, desired_capabilities={})

Traceback (most recent call last):
  File "/Users/tarun.lalwani/Desktop/tarunlalwani.com/tarunlalwani/content/code/selenium_enumerator.py", line 101, in <module>
    driver2 = webdriver.Remote(command_executor=executor_url, desired_capabilities={})
  File "/usr/local/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 98, in __init__
    self.start_session(desired_capabilities, browser_profile)
  File "/usr/local/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 188, in start_session
    response = self.execute(Command.NEW_SESSION, parameters)
  File "/usr/local/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 252, in execute
    self.error_handler.check_response(response)
  File "/usr/local/lib/python2.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 194, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException: Message: Session is already started

Ошибка возникает в response = self.execute(Command.NEW_SESSION, parameters). Проблема в том, что снова geckodriver не поддерживает newSession. Следовательно, нужен способ переопределить функцию выполнения при создании драйвера.

Мы создаем новую функцию, которая возвращает фиктивный ответ на newSession с нашим sessionId. Обновленный код приведен ниже:

from selenium import webdriver

driver = webdriver.Firefox()
executor_url = driver.command_executor._url
session_id = driver.session_id
driver.get("http://tarunlalwani.com")

print session_id
print executor_url

def create_driver_session(session_id, executor_url):
    from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver

    # Save the original function, so we can revert our patch
    org_command_execute = RemoteWebDriver.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 org_command_execute(self, command, params)

    # Patch the function before creating the driver object
    RemoteWebDriver.execute = new_command_execute

    new_driver = webdriver.Remote(command_executor=executor_url, desired_capabilities={})
    new_driver.session_id = session_id

    # Replace the patched function with original function
    RemoteWebDriver.execute = org_command_execute

    return new_driver

driver2 = create_driver_session(session_id, executor_url)
print driver2.current_url

Этот код отлично работает. Единственное предостережение в том, что мы теряем фактические возможности, которые браузер возвращал при запуске. В большинстве случаев это не должно иметь большого значения.

Браузер в режиме ожидания

В одном из наших проектов парсинга мы хотим завершить наш скрипт и оставить браузер в режиме ожидания. При повторном запуске скрипта он повторно использует последний браузер и продолжает работу. Это может стать важным фактором при очистке сайтов с более высокой степенью защиты.

Функциональность фреймворка

Одна из наших платформ автоматизации, позволяющая пользователям выполнять коды автоматизации из любой точки. Для реализации такой функции было важно иметь возможность воссоздать последний драйвер сеанса.

Ответить