Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reuse a selenium browser session

I'm trying to access an existing selenium browser session from a separate python process. I'm able to get this working within the same python script, but when I break the reuse logic out to a separate script, it fails with the error message:

Traceback (most recent call last):
  File "/usr/local/Cellar/python3/3.6.2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/request.py", line 1318, in do_open
    encode_chunked=req.has_header('Transfer-encoding'))
  File "/usr/local/Cellar/python3/3.6.2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1239, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/local/Cellar/python3/3.6.2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1285, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/local/Cellar/python3/3.6.2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1234, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/local/Cellar/python3/3.6.2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1026, in _send_output
    self.send(msg)
  File "/usr/local/Cellar/python3/3.6.2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 964, in send
    self.connect()
  File "/usr/local/Cellar/python3/3.6.2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 936, in connect
    (self.host,self.port), self.timeout, self.source_address)
  File "/usr/local/Cellar/python3/3.6.2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/socket.py", line 722, in create_connection
    raise err
  File "/usr/local/Cellar/python3/3.6.2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/socket.py", line 713, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [Errno 61] Connection refused

Here's the code that attempts to access the existing session from a separate script (this is the code that generates the error). Right now I'm updating the session_id and executor values each time manually:

""" module docstring """
import time
from selenium import webdriver

def main():
  """ reuse window in different scripts """
  # driver = webdriver.Chrome()
  session_id = '7b10acc2c99d90a68fecb71e5e481c0f'
  # executor_url = 'http://127.0.0.1:9515'
  executor_url = 'http://127.0.0.1:54467'

  print(session_id)
  print(executor_url)

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

  print('driver instance created')
  driver2.session_id = session_id
  print(driver2.current_url)
  driver2.get('http://www.yahoo.com')

  time.sleep(10)

if __name__ == '__main__':
  main()

This is the code that sets up the initial browser session:

""" module docstring """
import time
from selenium import webdriver

def main():
  """ reuse window in different scripts """
  driver = webdriver.Chrome()
  executor_url = driver.command_executor._url # pylint: disable=W0212
  session_id = driver.session_id
  driver.get("http://tarunlalwani.com")

  print(session_id)
  print(executor_url)

  time.sleep(300)

if __name__ == '__main__':
  main()

Here's the script that successfully alters the existing browser window, however this is from within the same python script:

""" module docstring """
import time
from selenium import webdriver

def main():
  """ reuse window in same script """
  driver = webdriver.Chrome()
  executor_url = driver.command_executor._url # pylint: disable=W0212
  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.get('http://www.yahoo.com')

  time.sleep(300)

if __name__ == '__main__':
  main()
like image 665
opike Avatar asked Apr 11 '18 01:04

opike


People also ask

Can selenium interact with an existing browser session?

Can Selenium interact with an existing browser session? We can interact with an existing browser session. This is performed by using the Capabilities and ChromeOptions classes. The Capabilities class obtains the browser capabilities with the help of the getCapabilities method.

Is it possible to close a browser in selenium?

This is possible with Selenium 2 and WebDriver. I'm not sure if it is with different versions. In Selenium 2 with WebDriver you can call webDriver = new FirefoxDriver () which spawns a browser, and that browser will stay open for the duration of your testing, or you can choose to close it with webDriver.Quit ().

How do I keep a session alive for long selenium scripts?

How do I keep a session alive for long Selenium scripts in automation? How do I keep a session alive for long Selenium scripts in automation? We can keep a session alive for long Selenium scripts in automation. In Chrome browser, this can be achieved with the help of the ChromeOptions and Capabilities classes.

How to get session ID and_URL in selenium?

We are taking advantage of the fact that Selenium lets you attach a driver to a session id and an URL. You can extract your session id and _url from the driver object as mentioned below In case you are using a framework, you can print out the session id and url in the method where you try to get the element.


2 Answers

If you want the ultimate performance, you can make Selenium as an HTTP server to receive commands. Example:

# Created by [email protected] at 2022/1/29 11:58

import threading

import flask
import requests
import selenium.webdriver

app = flask.Flask(__name__)


@app.post("/")
def home():
    return str(driver.execute_script(flask.request.data.decode()))


threading.Thread(target=lambda: app.run(host="127.0.0.1", port=5000)).start()
driver = selenium.webdriver.Chrome()

print("1+1=", requests.post("http://localhost:5000", "return 1+1").text)
print("userAgent=", requests.post("http://localhost:5000", "return navigator.userAgent").text)
like image 155
BaiJiFeiLong Avatar answered Oct 04 '22 13:10

BaiJiFeiLong


Here is an example using a one file solution, though it would work in a two file solution as well.

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from multiprocessing import Process
import time

# The main process calls this function to create the driver instance.
def createDriverInstance():
    options = Options()
    options.add_argument('--disable-infobars')
    driver = webdriver.Chrome(chrome_options=options, port=9515)
    return driver

# Called by the second process only.
def secondProcess(executor_url, session_id):
    options = Options()
    options.add_argument("--disable-infobars")
    options.add_argument("--enable-file-cookies")
    capabilities = options.to_capabilities()
    same_driver = webdriver.Remote(command_executor=executor_url, desired_capabilities=capabilities)
    same_driver.close()
    same_driver.session_id = session_id
    same_driver.get("https://www.wikipedia.org")
    time.sleep(4)
    same_driver.quit()

if __name__ == '__main__':
    driver = createDriverInstance()
    driver.get("https://google.com")
    time.sleep(2)

    # Pass the driver session and command_executor to the second process.
    p = Process(target=secondProcess, args=(driver.command_executor._url,driver.session_id))
    p.start()
like image 25
Ron Norris Avatar answered Oct 04 '22 14:10

Ron Norris