Skip to content

QUESTION: Using without a context manager #3482

@PFython

Description

@PFython

Hi Michael and team - first of all thanks so much for an amazing package... I have so many good things to say about it (and your examples... and your videos...) but will save that for another place/time!

I just wanted to check if I'm missing something important with regards to context managers and most/all of the examples in your documentation starting with with SB(uc=True, test=True, locale_code="en") as sb: etc?

For debugging and REPL work, and generally doing more with the sb object without one massive with block, I prefer to manually create and close the object, which means the browser stays open for as long as I need to tinker. Indeed many original selenium scripts include a final driver.close(). Here's the wrapper I've come up with but since I don't know what I don't know, I just wanted to ask if there are any problems you can see with this approach please? And if not, maybe include something like this as an optional approach in the docs or the package itself?

Also, very trivial points but could the arguments of SB.__exit__ be made optional so that SB.__exit__() works without specifying None three times? Also SB.activate_cdp_mode() defaulting to None? And pls=None instead of pls="none"?

Many thanks in advance for your time considering this!

import atexit
import platform

import httpx
import requests
from seleniumbase import SB

sb_defaults = {
    'uc': True,
    'headless': False,
    'test': False,
    'locale_code': "en",
    'cdp': False,
    'pls': "none",
    'ad_block': True,
    'xvfb': platform.platform().startswith("Linux")
}

def get_sb(**kwargs):
    """
    Return a SeleniumBase object with Undetected Chromedriver (UC) and/or Chrome Devtools Protocol
    (CDP) enabled, and helper methods added.

    >>> sb = get_sb()
    >>> sb.get("https://www.rightmove.co.uk/properties/157644773")
    >>> sb.click('#onetrust-accept-btn-handler')
    >>> sb.fetch()
    >>> sb.highlight('h1')
    >>> sb.post_message("SeleniumBase wasn't detected", duration=4)
    >>> sb.close()
    """
    kwargs = sb_defaults | kwargs
    cdp = kwargs.pop('cdp')
    sb_base = SB(**kwargs)
    sb = sb_base.__enter__()
    if cdp:
        sb.activate_cdp_mode(None)
    def _close():
        sb_base.__exit__(None, None, None)
    def _fetch(url=None):
        """Fetch html page source and save as .html attribute"""
        if url:
            sb.get(url)
        sb.html = sb.get_page_source()
    def _get_response(url=None, use_httpx=False):
        """
        Generate requests.Response or httpx.Response object eg for further use by parsel/lxml etc
        """
        sb.fetch(url)  # copy page source to .html
        status_code = sb.get_link_status_code(sb.get_current_url())
        if use_httpx:
            response = httpx.Response(status_code)
        else:
            response = requests.Response()
            response.status_code = status_code
            response._content_consumed = True
        response.url = sb.get_current_url()
        if isinstance(sb.html, bytes):
            response._content = base64.b64decode(sb.html)
        if isinstance(sb.html, str):
            response._content = sb.html.encode("utf-8")
        return response
    for method in [_close, _fetch,  _get_response]:
        setattr(sb, method.__name__.removeprefix("_"), method)
    # Add aliases:
    sb.first = sb.find_element
    sb.all = sb.find_elements
    sb.quit = sb.close
    atexit.register(sb.quit)
    return sb

Metadata

Metadata

Assignees

No one assigned

    Labels

    UC Mode / CDP ModeUndetected Chromedriver Mode / CDP ModequestionSomeone is looking for answers

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions